fa4f5cff8776b59fb94d5edcd8a557a56311d58b
[platform/upstream/gst-plugins-good.git] / gst / isomp4 / qtdemux.c
1 /* GStreamer
2  * Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu>
3  * Copyright (C) <2003> David A. Schleef <ds@schleef.org>
4  * Copyright (C) <2006> Wim Taymans <wim@fluendo.com>
5  * Copyright (C) <2007> Julien Moutte <julien@fluendo.com>
6  * Copyright (C) <2009> Tim-Philipp Müller <tim centricular net>
7  * Copyright (C) <2009> STEricsson <benjamin.gaignard@stericsson.com>
8  * Copyright (C) <2013> Sreerenj Balachandran <sreerenj.balachandran@intel.com>
9  * Copyright (C) <2013> Intel Corporation
10  * Copyright (C) <2014> Centricular Ltd
11  * Copyright (C) <2015> YouView TV Ltd.
12  * Copyright (C) <2016> British Broadcasting Corporation
13  *
14  * This library is free software; you can redistribute it and/or
15  * modify it under the terms of the GNU Library General Public
16  * License as published by the Free Software Foundation; either
17  * version 2 of the License, or (at your option) any later version.
18  *
19  * This library is distributed in the hope that it will be useful,
20  * but WITHOUT ANY WARRANTY; without even the implied warranty of
21  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
22  * Library General Public License for more details.
23  *
24  * You should have received a copy of the GNU Library General Public
25  * License along with this library; if not, write to the
26  * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
27  * Boston, MA 02110-1301, USA.
28  */
29
30 /**
31  * SECTION:element-qtdemux
32  *
33  * Demuxes a .mov file into raw or compressed audio and/or video streams.
34  *
35  * This element supports both push and pull-based scheduling, depending on the
36  * capabilities of the upstream elements.
37  *
38  * <refsect2>
39  * <title>Example launch line</title>
40  * |[
41  * gst-launch-1.0 filesrc location=test.mov ! qtdemux name=demux  demux.audio_0 ! queue ! decodebin ! audioconvert ! audioresample ! autoaudiosink   demux.video_0 ! queue ! decodebin ! videoconvert ! videoscale ! autovideosink
42  * ]| Play (parse and decode) a .mov file and try to output it to
43  * an automatically detected soundcard and videosink. If the MOV file contains
44  * compressed audio or video data, this will only work if you have the
45  * right decoder elements/plugins installed.
46  * </refsect2>
47  */
48
49 #ifdef HAVE_CONFIG_H
50 #include "config.h"
51 #endif
52
53 #include "gst/gst-i18n-plugin.h"
54
55 #include <glib/gprintf.h>
56 #include <gst/tag/tag.h>
57 #include <gst/audio/audio.h>
58 #include <gst/video/video.h>
59
60 #include "qtatomparser.h"
61 #include "qtdemux_types.h"
62 #include "qtdemux_dump.h"
63 #include "fourcc.h"
64 #include "descriptors.h"
65 #include "qtdemux_lang.h"
66 #include "qtdemux.h"
67 #include "qtpalette.h"
68
69 #include "gst/riff/riff-media.h"
70 #include "gst/riff/riff-read.h"
71
72 #include <gst/pbutils/pbutils.h>
73
74 #include <stdio.h>
75 #include <stdlib.h>
76 #include <string.h>
77
78 #include <math.h>
79 #include <gst/math-compat.h>
80
81 #ifdef HAVE_ZLIB
82 # include <zlib.h>
83 #endif
84
85 /* max. size considered 'sane' for non-mdat atoms */
86 #define QTDEMUX_MAX_ATOM_SIZE (25*1024*1024)
87
88 /* if the sample index is larger than this, something is likely wrong */
89 #define QTDEMUX_MAX_SAMPLE_INDEX_SIZE (200*1024*1024)
90
91 /* For converting qt creation times to unix epoch times */
92 #define QTDEMUX_SECONDS_PER_DAY (60 * 60 * 24)
93 #define QTDEMUX_LEAP_YEARS_FROM_1904_TO_1970 17
94 #define QTDEMUX_SECONDS_FROM_1904_TO_1970 (((1970 - 1904) * (guint64) 365 + \
95     QTDEMUX_LEAP_YEARS_FROM_1904_TO_1970) * QTDEMUX_SECONDS_PER_DAY)
96
97 #define QTDEMUX_TREE_NODE_FOURCC(n) (QT_FOURCC(((guint8 *) (n)->data) + 4))
98
99 #define STREAM_IS_EOS(s) ((s)->time_position == GST_CLOCK_TIME_NONE)
100
101 #define ABSDIFF(x, y) ( (x) > (y) ? ((x) - (y)) : ((y) - (x)) )
102
103 #define QTDEMUX_FIRST_STREAM(demux) ((QtDemuxStream *)(demux)->active_streams \
104   ? (QtDemuxStream *)(demux)->active_streams->data : NULL)
105 #define QTDEMUX_STREAM(s) ((QtDemuxStream *)(s))
106
107 GST_DEBUG_CATEGORY (qtdemux_debug);
108 #define GST_CAT_DEFAULT qtdemux_debug
109
110 typedef struct _QtDemuxSegment QtDemuxSegment;
111 typedef struct _QtDemuxSample QtDemuxSample;
112
113 typedef struct _QtDemuxCencSampleSetInfo QtDemuxCencSampleSetInfo;
114
115 struct _QtDemuxSample
116 {
117   guint32 size;
118   gint32 pts_offset;            /* Add this value to timestamp to get the pts */
119   guint64 offset;
120   guint64 timestamp;            /* DTS In mov time */
121   guint32 duration;             /* In mov time */
122   gboolean keyframe;            /* TRUE when this packet is a keyframe */
123 };
124
125 /* Macros for converting to/from timescale */
126 #define QTSTREAMTIME_TO_GSTTIME(stream, value) (gst_util_uint64_scale((value), GST_SECOND, (stream)->timescale))
127 #define GSTTIME_TO_QTSTREAMTIME(stream, value) (gst_util_uint64_scale((value), (stream)->timescale, GST_SECOND))
128
129 #define QTTIME_TO_GSTTIME(qtdemux, value) (gst_util_uint64_scale((value), GST_SECOND, (qtdemux)->timescale))
130 #define GSTTIME_TO_QTTIME(qtdemux, value) (gst_util_uint64_scale((value), (qtdemux)->timescale, GST_SECOND))
131
132 /* timestamp is the DTS */
133 #define QTSAMPLE_DTS(stream,sample) (QTSTREAMTIME_TO_GSTTIME((stream), (sample)->timestamp))
134 /* timestamp + offset + cslg_shift is the outgoing PTS */
135 #define QTSAMPLE_PTS(stream,sample) (QTSTREAMTIME_TO_GSTTIME((stream), (sample)->timestamp + (stream)->cslg_shift + (sample)->pts_offset))
136 /* timestamp + offset is the PTS used for internal seek calcuations */
137 #define QTSAMPLE_PTS_NO_CSLG(stream,sample) (QTSTREAMTIME_TO_GSTTIME((stream), (sample)->timestamp + (sample)->pts_offset))
138 /* timestamp + duration - dts is the duration */
139 #define QTSAMPLE_DUR_DTS(stream, sample, dts) (QTSTREAMTIME_TO_GSTTIME ((stream), (sample)->timestamp + (sample)->duration) - (dts))
140
141 #define QTSAMPLE_KEYFRAME(stream,sample) ((stream)->all_keyframe || (sample)->keyframe)
142
143 /*
144  * Quicktime has tracks and segments. A track is a continuous piece of
145  * multimedia content. The track is not always played from start to finish but
146  * instead, pieces of the track are 'cut out' and played in sequence. This is
147  * what the segments do.
148  *
149  * Inside the track we have keyframes (K) and delta frames. The track has its
150  * own timing, which starts from 0 and extends to end. The position in the track
151  * is called the media_time.
152  *
153  * The segments now describe the pieces that should be played from this track
154  * and are basically tuples of media_time/duration/rate entries. We can have
155  * multiple segments and they are all played after one another. An example:
156  *
157  * segment 1: media_time: 1 second, duration: 1 second, rate 1
158  * segment 2: media_time: 3 second, duration: 2 second, rate 2
159  *
160  * To correctly play back this track, one must play: 1 second of media starting
161  * from media_time 1 followed by 2 seconds of media starting from media_time 3
162  * at a rate of 2.
163  *
164  * Each of the segments will be played at a specific time, the first segment at
165  * time 0, the second one after the duration of the first one, etc.. Note that
166  * the time in resulting playback is not identical to the media_time of the
167  * track anymore.
168  *
169  * Visually, assuming the track has 4 second of media_time:
170  *
171  *                (a)                   (b)          (c)              (d)
172  *         .-----------------------------------------------------------.
173  * track:  | K.....K.........K........K.......K.......K...........K... |
174  *         '-----------------------------------------------------------'
175  *         0              1              2              3              4
176  *           .------------^              ^   .----------^              ^
177  *          /              .-------------'  /       .------------------'
178  *         /              /          .-----'       /
179  *         .--------------.         .--------------.
180  *         | segment 1    |         | segment 2    |
181  *         '--------------'         '--------------'
182  *
183  * The challenge here is to cut out the right pieces of the track for each of
184  * the playback segments. This fortunately can easily be done with the SEGMENT
185  * events of GStreamer.
186  *
187  * For playback of segment 1, we need to provide the decoder with the keyframe
188  * (a), in the above figure, but we must instruct it only to output the decoded
189  * data between second 1 and 2. We do this with a SEGMENT event for 1 to 2, time
190  * position set to the time of the segment: 0.
191  *
192  * We then proceed to push data from keyframe (a) to frame (b). The decoder
193  * decodes but clips all before media_time 1.
194  *
195  * After finishing a segment, we push out a new SEGMENT event with the clipping
196  * boundaries of the new data.
197  *
198  * This is a good usecase for the GStreamer accumulated SEGMENT events.
199  */
200
201 struct _QtDemuxSegment
202 {
203   /* global time and duration, all gst time */
204   GstClockTime time;
205   GstClockTime stop_time;
206   GstClockTime duration;
207   /* media time of trak, all gst time */
208   GstClockTime media_start;
209   GstClockTime media_stop;
210   gdouble rate;
211   /* Media start time in trak timescale units */
212   guint32 trak_media_start;
213 };
214
215 #define QTSEGMENT_IS_EMPTY(s) ((s)->media_start == GST_CLOCK_TIME_NONE)
216
217 /* Used with fragmented MP4 files (mfra atom) */
218 typedef struct
219 {
220   GstClockTime ts;
221   guint64 moof_offset;
222 } QtDemuxRandomAccessEntry;
223
224 typedef struct _QtDemuxStreamStsdEntry
225 {
226   GstCaps *caps;
227   guint32 fourcc;
228   gboolean sparse;
229
230   /* video info */
231   gint width;
232   gint height;
233   gint par_w;
234   gint par_h;
235   /* Numerator/denominator framerate */
236   gint fps_n;
237   gint fps_d;
238   GstVideoColorimetry colorimetry;
239   guint16 bits_per_sample;
240   guint16 color_table_id;
241   GstMemory *rgb8_palette;
242   guint interlace_mode;
243   guint field_order;
244
245   /* audio info */
246   gdouble rate;
247   gint n_channels;
248   guint samples_per_packet;
249   guint samples_per_frame;
250   guint bytes_per_packet;
251   guint bytes_per_sample;
252   guint bytes_per_frame;
253   guint compression;
254
255   /* if we use chunks or samples */
256   gboolean sampled;
257   guint padding;
258
259 } QtDemuxStreamStsdEntry;
260
261 #define CUR_STREAM(s) (&((s)->stsd_entries[(s)->cur_stsd_entry_index]))
262
263 struct _QtDemuxStream
264 {
265   GstPad *pad;
266
267   GstQTDemux *demux;
268   gchar *stream_id;
269
270   QtDemuxStreamStsdEntry *stsd_entries;
271   guint stsd_entries_length;
272   guint cur_stsd_entry_index;
273
274   /* stream type */
275   guint32 subtype;
276
277   gboolean new_caps;            /* If TRUE, caps need to be generated (by
278                                  * calling _configure_stream()) This happens
279                                  * for MSS and fragmented streams */
280
281   gboolean new_stream;          /* signals that a stream_start is required */
282   gboolean on_keyframe;         /* if this stream last pushed buffer was a
283                                  * keyframe. This is important to identify
284                                  * where to stop pushing buffers after a
285                                  * segment stop time */
286
287   /* if the stream has a redirect URI in its headers, we store it here */
288   gchar *redirect_uri;
289
290   /* track id */
291   guint track_id;
292
293   /* duration/scale */
294   guint64 duration;             /* in timescale units */
295   guint32 timescale;
296
297   /* language */
298   gchar lang_id[4];             /* ISO 639-2T language code */
299
300   /* our samples */
301   guint32 n_samples;
302   QtDemuxSample *samples;
303   gboolean all_keyframe;        /* TRUE when all samples are keyframes (no stss) */
304   guint32 first_duration;       /* duration in timescale of first sample, used for figuring out
305                                    the framerate */
306   guint32 n_samples_moof;       /* sample count in a moof */
307   guint64 duration_moof;        /* duration in timescale of a moof, used for figure out
308                                  * the framerate of fragmented format stream */
309   guint64 duration_last_moof;
310
311   guint32 offset_in_sample;     /* Offset in the current sample, used for
312                                  * streams which have got exceedingly big
313                                  * sample size (such as 24s of raw audio).
314                                  * Only used when max_buffer_size is non-NULL */
315   guint32 max_buffer_size;      /* Maximum allowed size for output buffers.
316                                  * Currently only set for raw audio streams*/
317
318   /* video info */
319   /* aspect ratio */
320   gint display_width;
321   gint display_height;
322
323   /* allocation */
324   gboolean use_allocator;
325   GstAllocator *allocator;
326   GstAllocationParams params;
327
328   gsize alignment;
329
330   /* when a discontinuity is pending */
331   gboolean discont;
332
333   /* list of buffers to push first */
334   GSList *buffers;
335
336   /* if we need to clip this buffer. This is only needed for uncompressed
337    * data */
338   gboolean need_clip;
339
340   /* buffer needs some custom processing, e.g. subtitles */
341   gboolean need_process;
342
343   /* current position */
344   guint32 segment_index;
345   guint32 sample_index;
346   GstClockTime time_position;   /* in gst time */
347   guint64 accumulated_base;
348
349   /* the Gst segment we are processing out, used for clipping */
350   GstSegment segment;
351
352   /* quicktime segments */
353   guint32 n_segments;
354   QtDemuxSegment *segments;
355   gboolean dummy_segment;
356   guint32 from_sample;
357   guint32 to_sample;
358
359   gboolean sent_eos;
360   GstTagList *stream_tags;
361   gboolean send_global_tags;
362
363   GstEvent *pending_event;
364
365   GstByteReader stco;
366   GstByteReader stsz;
367   GstByteReader stsc;
368   GstByteReader stts;
369   GstByteReader stss;
370   GstByteReader stps;
371   GstByteReader ctts;
372
373   gboolean chunks_are_samples;  /* TRUE means treat chunks as samples */
374   gint64 stbl_index;
375   /* stco */
376   guint co_size;
377   GstByteReader co_chunk;
378   guint32 first_chunk;
379   guint32 current_chunk;
380   guint32 last_chunk;
381   guint32 samples_per_chunk;
382   guint32 stsd_sample_description_id;
383   guint32 stco_sample_index;
384   /* stsz */
385   guint32 sample_size;          /* 0 means variable sizes are stored in stsz */
386   /* stsc */
387   guint32 stsc_index;
388   guint32 n_samples_per_chunk;
389   guint32 stsc_chunk_index;
390   guint32 stsc_sample_index;
391   guint64 chunk_offset;
392   /* stts */
393   guint32 stts_index;
394   guint32 stts_samples;
395   guint32 n_sample_times;
396   guint32 stts_sample_index;
397   guint64 stts_time;
398   guint32 stts_duration;
399   /* stss */
400   gboolean stss_present;
401   guint32 n_sample_syncs;
402   guint32 stss_index;
403   /* stps */
404   gboolean stps_present;
405   guint32 n_sample_partial_syncs;
406   guint32 stps_index;
407   QtDemuxRandomAccessEntry *ra_entries;
408   guint n_ra_entries;
409
410   const QtDemuxRandomAccessEntry *pending_seek;
411
412   /* ctts */
413   gboolean ctts_present;
414   guint32 n_composition_times;
415   guint32 ctts_index;
416   guint32 ctts_sample_index;
417   guint32 ctts_count;
418   gint32 ctts_soffset;
419
420   /* cslg */
421   guint32 cslg_shift;
422
423   /* fragmented */
424   gboolean parsed_trex;
425   guint32 def_sample_description_index; /* index is 1-based */
426   guint32 def_sample_duration;
427   guint32 def_sample_size;
428   guint32 def_sample_flags;
429
430   gboolean disabled;
431
432   /* stereoscopic video streams */
433   GstVideoMultiviewMode multiview_mode;
434   GstVideoMultiviewFlags multiview_flags;
435
436   /* protected streams */
437   gboolean protected;
438   guint32 protection_scheme_type;
439   guint32 protection_scheme_version;
440   gpointer protection_scheme_info;      /* specific to the protection scheme */
441   GQueue protection_scheme_event_queue;
442 };
443
444 /* Contains properties and cryptographic info for a set of samples from a
445  * track protected using Common Encryption (cenc) */
446 struct _QtDemuxCencSampleSetInfo
447 {
448   GstStructure *default_properties;
449
450   /* @crypto_info holds one GstStructure per sample */
451   GPtrArray *crypto_info;
452 };
453
454 static const gchar *
455 qt_demux_state_string (enum QtDemuxState state)
456 {
457   switch (state) {
458     case QTDEMUX_STATE_INITIAL:
459       return "<INITIAL>";
460     case QTDEMUX_STATE_HEADER:
461       return "<HEADER>";
462     case QTDEMUX_STATE_MOVIE:
463       return "<MOVIE>";
464     case QTDEMUX_STATE_BUFFER_MDAT:
465       return "<BUFFER_MDAT>";
466     default:
467       return "<UNKNOWN>";
468   }
469 }
470
471 static GNode *qtdemux_tree_get_child_by_type (GNode * node, guint32 fourcc);
472 static GNode *qtdemux_tree_get_child_by_type_full (GNode * node,
473     guint32 fourcc, GstByteReader * parser);
474 static GNode *qtdemux_tree_get_sibling_by_type (GNode * node, guint32 fourcc);
475 static GNode *qtdemux_tree_get_sibling_by_type_full (GNode * node,
476     guint32 fourcc, GstByteReader * parser);
477
478 static GstFlowReturn qtdemux_add_fragmented_samples (GstQTDemux * qtdemux);
479
480 static GstStaticPadTemplate gst_qtdemux_sink_template =
481     GST_STATIC_PAD_TEMPLATE ("sink",
482     GST_PAD_SINK,
483     GST_PAD_ALWAYS,
484     GST_STATIC_CAPS ("video/quicktime; video/mj2; audio/x-m4a; "
485         "application/x-3gp")
486     );
487
488 static GstStaticPadTemplate gst_qtdemux_videosrc_template =
489 GST_STATIC_PAD_TEMPLATE ("video_%u",
490     GST_PAD_SRC,
491     GST_PAD_SOMETIMES,
492     GST_STATIC_CAPS_ANY);
493
494 static GstStaticPadTemplate gst_qtdemux_audiosrc_template =
495 GST_STATIC_PAD_TEMPLATE ("audio_%u",
496     GST_PAD_SRC,
497     GST_PAD_SOMETIMES,
498     GST_STATIC_CAPS_ANY);
499
500 static GstStaticPadTemplate gst_qtdemux_subsrc_template =
501 GST_STATIC_PAD_TEMPLATE ("subtitle_%u",
502     GST_PAD_SRC,
503     GST_PAD_SOMETIMES,
504     GST_STATIC_CAPS_ANY);
505
506 #define gst_qtdemux_parent_class parent_class
507 G_DEFINE_TYPE (GstQTDemux, gst_qtdemux, GST_TYPE_ELEMENT);
508
509 static void gst_qtdemux_dispose (GObject * object);
510
511 static guint32
512 gst_qtdemux_find_index_linear (GstQTDemux * qtdemux, QtDemuxStream * str,
513     GstClockTime media_time);
514 static guint32
515 gst_qtdemux_find_index_for_given_media_offset_linear (GstQTDemux * qtdemux,
516     QtDemuxStream * str, gint64 media_offset);
517
518 #if 0
519 static void gst_qtdemux_set_index (GstElement * element, GstIndex * index);
520 static GstIndex *gst_qtdemux_get_index (GstElement * element);
521 #endif
522 static GstStateChangeReturn gst_qtdemux_change_state (GstElement * element,
523     GstStateChange transition);
524 static gboolean qtdemux_sink_activate (GstPad * sinkpad, GstObject * parent);
525 static gboolean qtdemux_sink_activate_mode (GstPad * sinkpad,
526     GstObject * parent, GstPadMode mode, gboolean active);
527
528 static void gst_qtdemux_loop (GstPad * pad);
529 static GstFlowReturn gst_qtdemux_chain (GstPad * sinkpad, GstObject * parent,
530     GstBuffer * inbuf);
531 static gboolean gst_qtdemux_handle_sink_event (GstPad * pad, GstObject * parent,
532     GstEvent * event);
533 static gboolean gst_qtdemux_setcaps (GstQTDemux * qtdemux, GstCaps * caps);
534 static gboolean gst_qtdemux_configure_stream (GstQTDemux * qtdemux,
535     QtDemuxStream * stream);
536 static void gst_qtdemux_stream_check_and_change_stsd_index (GstQTDemux * demux,
537     QtDemuxStream * stream);
538 static GstFlowReturn gst_qtdemux_process_adapter (GstQTDemux * demux,
539     gboolean force);
540
541 static gboolean qtdemux_parse_moov (GstQTDemux * qtdemux,
542     const guint8 * buffer, guint length);
543 static gboolean qtdemux_parse_node (GstQTDemux * qtdemux, GNode * node,
544     const guint8 * buffer, guint length);
545 static gboolean qtdemux_parse_tree (GstQTDemux * qtdemux);
546 static void qtdemux_parse_udta (GstQTDemux * qtdemux, GstTagList * taglist,
547     GNode * udta);
548
549 static void gst_qtdemux_handle_esds (GstQTDemux * qtdemux,
550     QtDemuxStream * stream, QtDemuxStreamStsdEntry * entry, GNode * esds,
551     GstTagList * list);
552 static GstCaps *qtdemux_video_caps (GstQTDemux * qtdemux,
553     QtDemuxStream * stream, QtDemuxStreamStsdEntry * entry, guint32 fourcc,
554     const guint8 * stsd_entry_data, gchar ** codec_name);
555 static GstCaps *qtdemux_audio_caps (GstQTDemux * qtdemux,
556     QtDemuxStream * stream, QtDemuxStreamStsdEntry * entry, guint32 fourcc,
557     const guint8 * data, int len, gchar ** codec_name);
558 static GstCaps *qtdemux_sub_caps (GstQTDemux * qtdemux, QtDemuxStream * stream,
559     QtDemuxStreamStsdEntry * entry, guint32 fourcc, const guint8 * data,
560     gchar ** codec_name);
561 static GstCaps *qtdemux_generic_caps (GstQTDemux * qtdemux,
562     QtDemuxStream * stream, QtDemuxStreamStsdEntry * entry, guint32 fourcc,
563     const guint8 * stsd_entry_data, gchar ** codec_name);
564
565 static gboolean qtdemux_parse_samples (GstQTDemux * qtdemux,
566     QtDemuxStream * stream, guint32 n);
567 static GstFlowReturn qtdemux_expose_streams (GstQTDemux * qtdemux);
568 static void gst_qtdemux_stream_free (QtDemuxStream * stream);
569 static void gst_qtdemux_stream_clear (QtDemuxStream * stream);
570 static void gst_qtdemux_remove_stream (GstQTDemux * qtdemux,
571     QtDemuxStream * stream);
572 static GstFlowReturn qtdemux_prepare_streams (GstQTDemux * qtdemux);
573 static void qtdemux_do_allocation (GstQTDemux * qtdemux,
574     QtDemuxStream * stream);
575 static gboolean gst_qtdemux_activate_segment (GstQTDemux * qtdemux,
576     QtDemuxStream * stream, guint32 seg_idx, GstClockTime offset);
577 static gboolean gst_qtdemux_stream_update_segment (GstQTDemux * qtdemux,
578     QtDemuxStream * stream, gint seg_idx, GstClockTime offset,
579     GstClockTime * _start, GstClockTime * _stop);
580 static void gst_qtdemux_send_gap_for_segment (GstQTDemux * demux,
581     QtDemuxStream * stream, gint segment_index, GstClockTime pos);
582
583 static gboolean qtdemux_pull_mfro_mfra (GstQTDemux * qtdemux);
584 static void check_update_duration (GstQTDemux * qtdemux, GstClockTime duration);
585
586 static gchar *qtdemux_uuid_bytes_to_string (gconstpointer uuid_bytes);
587
588 static GstStructure *qtdemux_get_cenc_sample_properties (GstQTDemux * qtdemux,
589     QtDemuxStream * stream, guint sample_index);
590 static void gst_qtdemux_append_protection_system_id (GstQTDemux * qtdemux,
591     const gchar * id);
592 static void qtdemux_gst_structure_free (GstStructure * gststructure);
593
594 static void
595 gst_qtdemux_class_init (GstQTDemuxClass * klass)
596 {
597   GObjectClass *gobject_class;
598   GstElementClass *gstelement_class;
599
600   gobject_class = (GObjectClass *) klass;
601   gstelement_class = (GstElementClass *) klass;
602
603   parent_class = g_type_class_peek_parent (klass);
604
605   gobject_class->dispose = gst_qtdemux_dispose;
606
607   gstelement_class->change_state = GST_DEBUG_FUNCPTR (gst_qtdemux_change_state);
608 #if 0
609   gstelement_class->set_index = GST_DEBUG_FUNCPTR (gst_qtdemux_set_index);
610   gstelement_class->get_index = GST_DEBUG_FUNCPTR (gst_qtdemux_get_index);
611 #endif
612
613   gst_tag_register_musicbrainz_tags ();
614
615   gst_element_class_add_static_pad_template (gstelement_class,
616       &gst_qtdemux_sink_template);
617   gst_element_class_add_static_pad_template (gstelement_class,
618       &gst_qtdemux_videosrc_template);
619   gst_element_class_add_static_pad_template (gstelement_class,
620       &gst_qtdemux_audiosrc_template);
621   gst_element_class_add_static_pad_template (gstelement_class,
622       &gst_qtdemux_subsrc_template);
623   gst_element_class_set_static_metadata (gstelement_class, "QuickTime demuxer",
624       "Codec/Demuxer",
625       "Demultiplex a QuickTime file into audio and video streams",
626       "David Schleef <ds@schleef.org>, Wim Taymans <wim@fluendo.com>");
627
628   GST_DEBUG_CATEGORY_INIT (qtdemux_debug, "qtdemux", 0, "qtdemux plugin");
629
630 }
631
632 static void
633 gst_qtdemux_init (GstQTDemux * qtdemux)
634 {
635   qtdemux->sinkpad =
636       gst_pad_new_from_static_template (&gst_qtdemux_sink_template, "sink");
637   gst_pad_set_activate_function (qtdemux->sinkpad, qtdemux_sink_activate);
638   gst_pad_set_activatemode_function (qtdemux->sinkpad,
639       qtdemux_sink_activate_mode);
640   gst_pad_set_chain_function (qtdemux->sinkpad, gst_qtdemux_chain);
641   gst_pad_set_event_function (qtdemux->sinkpad, gst_qtdemux_handle_sink_event);
642   gst_element_add_pad (GST_ELEMENT_CAST (qtdemux), qtdemux->sinkpad);
643
644   qtdemux->state = QTDEMUX_STATE_INITIAL;
645   qtdemux->pullbased = FALSE;
646   qtdemux->posted_redirect = FALSE;
647   qtdemux->neededbytes = 16;
648   qtdemux->todrop = 0;
649   qtdemux->adapter = gst_adapter_new ();
650   qtdemux->offset = 0;
651   qtdemux->first_mdat = -1;
652   qtdemux->got_moov = FALSE;
653   qtdemux->mdatoffset = -1;
654   qtdemux->mdatbuffer = NULL;
655   qtdemux->restoredata_buffer = NULL;
656   qtdemux->restoredata_offset = -1;
657   qtdemux->fragment_start = -1;
658   qtdemux->fragment_start_offset = -1;
659   qtdemux->media_caps = NULL;
660   qtdemux->exposed = FALSE;
661   qtdemux->mss_mode = FALSE;
662   qtdemux->pending_newsegment = NULL;
663   qtdemux->upstream_format_is_time = FALSE;
664   qtdemux->have_group_id = FALSE;
665   qtdemux->group_id = G_MAXUINT;
666   qtdemux->cenc_aux_info_offset = 0;
667   qtdemux->cenc_aux_info_sizes = NULL;
668   qtdemux->cenc_aux_sample_count = 0;
669   qtdemux->protection_system_ids = NULL;
670   g_queue_init (&qtdemux->protection_event_queue);
671   gst_segment_init (&qtdemux->segment, GST_FORMAT_TIME);
672   qtdemux->tag_list = gst_tag_list_new_empty ();
673   gst_tag_list_set_scope (qtdemux->tag_list, GST_TAG_SCOPE_GLOBAL);
674   qtdemux->flowcombiner = gst_flow_combiner_new ();
675
676   GST_OBJECT_FLAG_SET (qtdemux, GST_ELEMENT_FLAG_INDEXABLE);
677 }
678
679 static void
680 gst_qtdemux_dispose (GObject * object)
681 {
682   GstQTDemux *qtdemux = GST_QTDEMUX (object);
683
684   if (qtdemux->adapter) {
685     g_object_unref (G_OBJECT (qtdemux->adapter));
686     qtdemux->adapter = NULL;
687   }
688   gst_tag_list_unref (qtdemux->tag_list);
689   gst_flow_combiner_free (qtdemux->flowcombiner);
690   g_queue_foreach (&qtdemux->protection_event_queue, (GFunc) gst_event_unref,
691       NULL);
692   g_queue_clear (&qtdemux->protection_event_queue);
693
694   g_free (qtdemux->cenc_aux_info_sizes);
695   qtdemux->cenc_aux_info_sizes = NULL;
696
697   G_OBJECT_CLASS (parent_class)->dispose (object);
698 }
699
700 static void
701 gst_qtdemux_post_no_playable_stream_error (GstQTDemux * qtdemux)
702 {
703   if (qtdemux->posted_redirect) {
704     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
705         (_("This file contains no playable streams.")),
706         ("no known streams found, a redirect message has been posted"));
707   } else {
708     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
709         (_("This file contains no playable streams.")),
710         ("no known streams found"));
711   }
712 }
713
714 static GstBuffer *
715 _gst_buffer_new_wrapped (gpointer mem, gsize size, GFreeFunc free_func)
716 {
717   return gst_buffer_new_wrapped_full (free_func ? 0 : GST_MEMORY_FLAG_READONLY,
718       mem, size, 0, size, mem, free_func);
719 }
720
721 static GstFlowReturn
722 gst_qtdemux_pull_atom (GstQTDemux * qtdemux, guint64 offset, guint64 size,
723     GstBuffer ** buf)
724 {
725   GstFlowReturn flow;
726   GstMapInfo map;
727   gsize bsize;
728
729   if (G_UNLIKELY (size == 0)) {
730     GstFlowReturn ret;
731     GstBuffer *tmp = NULL;
732
733     ret = gst_qtdemux_pull_atom (qtdemux, offset, sizeof (guint32), &tmp);
734     if (ret != GST_FLOW_OK)
735       return ret;
736
737     gst_buffer_map (tmp, &map, GST_MAP_READ);
738     size = QT_UINT32 (map.data);
739     GST_DEBUG_OBJECT (qtdemux, "size 0x%08" G_GINT64_MODIFIER "x", size);
740
741     gst_buffer_unmap (tmp, &map);
742     gst_buffer_unref (tmp);
743   }
744
745   /* Sanity check: catch bogus sizes (fuzzed/broken files) */
746   if (G_UNLIKELY (size > QTDEMUX_MAX_ATOM_SIZE)) {
747     if (qtdemux->state != QTDEMUX_STATE_MOVIE && qtdemux->got_moov) {
748       /* we're pulling header but already got most interesting bits,
749        * so never mind the rest (e.g. tags) (that much) */
750       GST_WARNING_OBJECT (qtdemux, "atom has bogus size %" G_GUINT64_FORMAT,
751           size);
752       return GST_FLOW_EOS;
753     } else {
754       GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
755           (_("This file is invalid and cannot be played.")),
756           ("atom has bogus size %" G_GUINT64_FORMAT, size));
757       return GST_FLOW_ERROR;
758     }
759   }
760
761   flow = gst_pad_pull_range (qtdemux->sinkpad, offset, size, buf);
762
763   if (G_UNLIKELY (flow != GST_FLOW_OK))
764     return flow;
765
766   bsize = gst_buffer_get_size (*buf);
767   /* Catch short reads - we don't want any partial atoms */
768   if (G_UNLIKELY (bsize < size)) {
769     GST_WARNING_OBJECT (qtdemux,
770         "short read: %" G_GSIZE_FORMAT " < %" G_GUINT64_FORMAT, bsize, size);
771     gst_buffer_unref (*buf);
772     *buf = NULL;
773     return GST_FLOW_EOS;
774   }
775
776   return flow;
777 }
778
779 #if 1
780 static gboolean
781 gst_qtdemux_src_convert (GstQTDemux * qtdemux, GstPad * pad,
782     GstFormat src_format, gint64 src_value, GstFormat dest_format,
783     gint64 * dest_value)
784 {
785   gboolean res = TRUE;
786   QtDemuxStream *stream = gst_pad_get_element_private (pad);
787   gint32 index;
788
789   if (stream->subtype != FOURCC_vide) {
790     res = FALSE;
791     goto done;
792   }
793
794   switch (src_format) {
795     case GST_FORMAT_TIME:
796       switch (dest_format) {
797         case GST_FORMAT_BYTES:{
798           index = gst_qtdemux_find_index_linear (qtdemux, stream, src_value);
799           if (-1 == index) {
800             res = FALSE;
801             goto done;
802           }
803
804           *dest_value = stream->samples[index].offset;
805
806           GST_DEBUG_OBJECT (qtdemux, "Format Conversion Time->Offset :%"
807               GST_TIME_FORMAT "->%" G_GUINT64_FORMAT,
808               GST_TIME_ARGS (src_value), *dest_value);
809           break;
810         }
811         default:
812           res = FALSE;
813           break;
814       }
815       break;
816     case GST_FORMAT_BYTES:
817       switch (dest_format) {
818         case GST_FORMAT_TIME:{
819           index =
820               gst_qtdemux_find_index_for_given_media_offset_linear (qtdemux,
821               stream, src_value);
822
823           if (-1 == index) {
824             res = FALSE;
825             goto done;
826           }
827
828           *dest_value =
829               QTSTREAMTIME_TO_GSTTIME (stream,
830               stream->samples[index].timestamp);
831           GST_DEBUG_OBJECT (qtdemux,
832               "Format Conversion Offset->Time :%" G_GUINT64_FORMAT "->%"
833               GST_TIME_FORMAT, src_value, GST_TIME_ARGS (*dest_value));
834           break;
835         }
836         default:
837           res = FALSE;
838           break;
839       }
840       break;
841     default:
842       res = FALSE;
843       break;
844   }
845
846 done:
847   return res;
848 }
849 #endif
850
851 static gboolean
852 gst_qtdemux_get_duration (GstQTDemux * qtdemux, GstClockTime * duration)
853 {
854   gboolean res = FALSE;
855
856   *duration = GST_CLOCK_TIME_NONE;
857
858   if (qtdemux->duration != 0 &&
859       qtdemux->duration != G_MAXINT64 && qtdemux->timescale != 0) {
860     *duration = QTTIME_TO_GSTTIME (qtdemux, qtdemux->duration);
861     res = TRUE;
862   } else {
863     *duration = GST_CLOCK_TIME_NONE;
864   }
865
866   return res;
867 }
868
869 static gboolean
870 gst_qtdemux_handle_src_query (GstPad * pad, GstObject * parent,
871     GstQuery * query)
872 {
873   gboolean res = FALSE;
874   GstQTDemux *qtdemux = GST_QTDEMUX (parent);
875
876   GST_LOG_OBJECT (pad, "%s query", GST_QUERY_TYPE_NAME (query));
877
878   switch (GST_QUERY_TYPE (query)) {
879     case GST_QUERY_POSITION:{
880       GstFormat fmt;
881
882       gst_query_parse_position (query, &fmt, NULL);
883       if (fmt == GST_FORMAT_TIME
884           && GST_CLOCK_TIME_IS_VALID (qtdemux->segment.position)) {
885         gst_query_set_position (query, GST_FORMAT_TIME,
886             qtdemux->segment.position);
887         res = TRUE;
888       }
889     }
890       break;
891     case GST_QUERY_DURATION:{
892       GstFormat fmt;
893
894       gst_query_parse_duration (query, &fmt, NULL);
895       if (fmt == GST_FORMAT_TIME) {
896         /* First try to query upstream */
897         res = gst_pad_query_default (pad, parent, query);
898         if (!res) {
899           GstClockTime duration;
900           if (gst_qtdemux_get_duration (qtdemux, &duration) && duration > 0) {
901             gst_query_set_duration (query, GST_FORMAT_TIME, duration);
902             res = TRUE;
903           }
904         }
905       }
906       break;
907     }
908     case GST_QUERY_CONVERT:{
909       GstFormat src_fmt, dest_fmt;
910       gint64 src_value, dest_value = 0;
911
912       gst_query_parse_convert (query, &src_fmt, &src_value, &dest_fmt, NULL);
913
914       res = gst_qtdemux_src_convert (qtdemux, pad,
915           src_fmt, src_value, dest_fmt, &dest_value);
916       if (res)
917         gst_query_set_convert (query, src_fmt, src_value, dest_fmt, dest_value);
918
919       break;
920     }
921     case GST_QUERY_FORMATS:
922       gst_query_set_formats (query, 2, GST_FORMAT_TIME, GST_FORMAT_BYTES);
923       res = TRUE;
924       break;
925     case GST_QUERY_SEEKING:{
926       GstFormat fmt;
927       gboolean seekable;
928
929       /* try upstream first */
930       res = gst_pad_query_default (pad, parent, query);
931
932       if (!res) {
933         gst_query_parse_seeking (query, &fmt, NULL, NULL, NULL);
934         if (fmt == GST_FORMAT_TIME) {
935           GstClockTime duration;
936
937           gst_qtdemux_get_duration (qtdemux, &duration);
938           seekable = TRUE;
939           if (!qtdemux->pullbased) {
940             GstQuery *q;
941
942             /* we might be able with help from upstream */
943             seekable = FALSE;
944             q = gst_query_new_seeking (GST_FORMAT_BYTES);
945             if (gst_pad_peer_query (qtdemux->sinkpad, q)) {
946               gst_query_parse_seeking (q, &fmt, &seekable, NULL, NULL);
947               GST_LOG_OBJECT (qtdemux, "upstream BYTE seekable %d", seekable);
948             }
949             gst_query_unref (q);
950           }
951           gst_query_set_seeking (query, GST_FORMAT_TIME, seekable, 0, duration);
952           res = TRUE;
953         }
954       }
955       break;
956     }
957     case GST_QUERY_SEGMENT:
958     {
959       GstFormat format;
960       gint64 start, stop;
961
962       format = qtdemux->segment.format;
963
964       start =
965           gst_segment_to_stream_time (&qtdemux->segment, format,
966           qtdemux->segment.start);
967       if ((stop = qtdemux->segment.stop) == -1)
968         stop = qtdemux->segment.duration;
969       else
970         stop = gst_segment_to_stream_time (&qtdemux->segment, format, stop);
971
972       gst_query_set_segment (query, qtdemux->segment.rate, format, start, stop);
973       res = TRUE;
974       break;
975     }
976     default:
977       res = gst_pad_query_default (pad, parent, query);
978       break;
979   }
980
981   return res;
982 }
983
984 static void
985 gst_qtdemux_push_tags (GstQTDemux * qtdemux, QtDemuxStream * stream)
986 {
987   if (G_LIKELY (stream->pad)) {
988     GST_DEBUG_OBJECT (qtdemux, "Checking pad %s:%s for tags",
989         GST_DEBUG_PAD_NAME (stream->pad));
990
991     if (!gst_tag_list_is_empty (stream->stream_tags)) {
992       GST_DEBUG_OBJECT (qtdemux, "Sending tags %" GST_PTR_FORMAT,
993           stream->stream_tags);
994       gst_pad_push_event (stream->pad,
995           gst_event_new_tag (gst_tag_list_ref (stream->stream_tags)));
996     }
997
998     if (G_UNLIKELY (stream->send_global_tags)) {
999       GST_DEBUG_OBJECT (qtdemux, "Sending global tags %" GST_PTR_FORMAT,
1000           qtdemux->tag_list);
1001       gst_pad_push_event (stream->pad,
1002           gst_event_new_tag (gst_tag_list_ref (qtdemux->tag_list)));
1003       stream->send_global_tags = FALSE;
1004     }
1005   }
1006 }
1007
1008 /* push event on all source pads; takes ownership of the event */
1009 static void
1010 gst_qtdemux_push_event (GstQTDemux * qtdemux, GstEvent * event)
1011 {
1012   gboolean has_valid_stream = FALSE;
1013   GstEventType etype = GST_EVENT_TYPE (event);
1014   GList *iter;
1015
1016   GST_DEBUG_OBJECT (qtdemux, "pushing %s event on all source pads",
1017       GST_EVENT_TYPE_NAME (event));
1018
1019   for (iter = qtdemux->active_streams; iter; iter = g_list_next (iter)) {
1020     GstPad *pad;
1021     QtDemuxStream *stream = QTDEMUX_STREAM (iter->data);
1022     GST_DEBUG_OBJECT (qtdemux, "pushing on track-id %u", stream->track_id);
1023
1024     if ((pad = stream->pad)) {
1025       has_valid_stream = TRUE;
1026
1027       if (etype == GST_EVENT_EOS) {
1028         /* let's not send twice */
1029         if (stream->sent_eos)
1030           continue;
1031         stream->sent_eos = TRUE;
1032       }
1033
1034       gst_pad_push_event (pad, gst_event_ref (event));
1035     }
1036   }
1037
1038   gst_event_unref (event);
1039
1040   /* if it is EOS and there are no pads, post an error */
1041   if (!has_valid_stream && etype == GST_EVENT_EOS) {
1042     gst_qtdemux_post_no_playable_stream_error (qtdemux);
1043   }
1044 }
1045
1046 /* push a pending newsegment event, if any from the streaming thread */
1047 static void
1048 gst_qtdemux_push_pending_newsegment (GstQTDemux * qtdemux)
1049 {
1050   if (qtdemux->pending_newsegment) {
1051     gst_qtdemux_push_event (qtdemux, qtdemux->pending_newsegment);
1052     qtdemux->pending_newsegment = NULL;
1053   }
1054 }
1055
1056 typedef struct
1057 {
1058   guint64 media_time;
1059 } FindData;
1060
1061 static gint
1062 find_func (QtDemuxSample * s1, gint64 * media_time, gpointer user_data)
1063 {
1064   if ((gint64) s1->timestamp > *media_time)
1065     return 1;
1066   if ((gint64) s1->timestamp == *media_time)
1067     return 0;
1068
1069   return -1;
1070 }
1071
1072 /* find the index of the sample that includes the data for @media_time using a
1073  * binary search.  Only to be called in optimized cases of linear search below.
1074  *
1075  * Returns the index of the sample with the corresponding *DTS*.
1076  */
1077 static guint32
1078 gst_qtdemux_find_index (GstQTDemux * qtdemux, QtDemuxStream * str,
1079     guint64 media_time)
1080 {
1081   QtDemuxSample *result;
1082   guint32 index;
1083
1084   /* convert media_time to mov format */
1085   media_time =
1086       gst_util_uint64_scale_ceil (media_time, str->timescale, GST_SECOND);
1087
1088   result = gst_util_array_binary_search (str->samples, str->stbl_index + 1,
1089       sizeof (QtDemuxSample), (GCompareDataFunc) find_func,
1090       GST_SEARCH_MODE_BEFORE, &media_time, NULL);
1091
1092   if (G_LIKELY (result))
1093     index = result - str->samples;
1094   else
1095     index = 0;
1096
1097   return index;
1098 }
1099
1100
1101
1102 /* find the index of the sample that includes the data for @media_offset using a
1103  * linear search
1104  *
1105  * Returns the index of the sample.
1106  */
1107 static guint32
1108 gst_qtdemux_find_index_for_given_media_offset_linear (GstQTDemux * qtdemux,
1109     QtDemuxStream * str, gint64 media_offset)
1110 {
1111   QtDemuxSample *result = str->samples;
1112   guint32 index = 0;
1113
1114   if (result == NULL || str->n_samples == 0)
1115     return -1;
1116
1117   if (media_offset == result->offset)
1118     return index;
1119
1120   result++;
1121   while (index < str->n_samples - 1) {
1122     if (!qtdemux_parse_samples (qtdemux, str, index + 1))
1123       goto parse_failed;
1124
1125     if (media_offset < result->offset)
1126       break;
1127
1128     index++;
1129     result++;
1130   }
1131   return index;
1132
1133   /* ERRORS */
1134 parse_failed:
1135   {
1136     GST_LOG_OBJECT (qtdemux, "Parsing of index %u failed!", index + 1);
1137     return -1;
1138   }
1139 }
1140
1141 /* find the index of the sample that includes the data for @media_time using a
1142  * linear search, and keeping in mind that not all samples may have been parsed
1143  * yet.  If possible, it will delegate to binary search.
1144  *
1145  * Returns the index of the sample.
1146  */
1147 static guint32
1148 gst_qtdemux_find_index_linear (GstQTDemux * qtdemux, QtDemuxStream * str,
1149     GstClockTime media_time)
1150 {
1151   guint32 index = 0;
1152   guint64 mov_time;
1153   QtDemuxSample *sample;
1154
1155   /* convert media_time to mov format */
1156   mov_time =
1157       gst_util_uint64_scale_ceil (media_time, str->timescale, GST_SECOND);
1158
1159   sample = str->samples;
1160   if (mov_time == sample->timestamp + sample->pts_offset)
1161     return index;
1162
1163   /* use faster search if requested time in already parsed range */
1164   sample = str->samples + str->stbl_index;
1165   if (str->stbl_index >= 0 && mov_time <= sample->timestamp) {
1166     index = gst_qtdemux_find_index (qtdemux, str, media_time);
1167     sample = str->samples + index;
1168   } else {
1169     while (index < str->n_samples - 1) {
1170       if (!qtdemux_parse_samples (qtdemux, str, index + 1))
1171         goto parse_failed;
1172
1173       sample = str->samples + index + 1;
1174       if (mov_time < sample->timestamp) {
1175         sample = str->samples + index;
1176         break;
1177       }
1178
1179       index++;
1180     }
1181   }
1182
1183   /* sample->timestamp is now <= media_time, need to find the corresponding
1184    * PTS now by looking backwards */
1185   while (index > 0 && sample->timestamp + sample->pts_offset > mov_time) {
1186     index--;
1187     sample = str->samples + index;
1188   }
1189
1190   return index;
1191
1192   /* ERRORS */
1193 parse_failed:
1194   {
1195     GST_LOG_OBJECT (qtdemux, "Parsing of index %u failed!", index + 1);
1196     return -1;
1197   }
1198 }
1199
1200 /* find the index of the keyframe needed to decode the sample at @index
1201  * of stream @str, or of a subsequent keyframe (depending on @next)
1202  *
1203  * Returns the index of the keyframe.
1204  */
1205 static guint32
1206 gst_qtdemux_find_keyframe (GstQTDemux * qtdemux, QtDemuxStream * str,
1207     guint32 index, gboolean next)
1208 {
1209   guint32 new_index = index;
1210
1211   if (index >= str->n_samples) {
1212     new_index = str->n_samples;
1213     goto beach;
1214   }
1215
1216   /* all keyframes, return index */
1217   if (str->all_keyframe) {
1218     new_index = index;
1219     goto beach;
1220   }
1221
1222   /* else search until we have a keyframe */
1223   while (new_index < str->n_samples) {
1224     if (next && !qtdemux_parse_samples (qtdemux, str, new_index))
1225       goto parse_failed;
1226
1227     if (str->samples[new_index].keyframe)
1228       break;
1229
1230     if (new_index == 0)
1231       break;
1232
1233     if (next)
1234       new_index++;
1235     else
1236       new_index--;
1237   }
1238
1239   if (new_index == str->n_samples) {
1240     GST_DEBUG_OBJECT (qtdemux, "no next keyframe");
1241     new_index = -1;
1242   }
1243
1244 beach:
1245   GST_DEBUG_OBJECT (qtdemux, "searching for keyframe index %s index %u "
1246       "gave %u", next ? "after" : "before", index, new_index);
1247
1248   return new_index;
1249
1250   /* ERRORS */
1251 parse_failed:
1252   {
1253     GST_LOG_OBJECT (qtdemux, "Parsing of index %u failed!", new_index);
1254     return -1;
1255   }
1256 }
1257
1258 /* find the segment for @time_position for @stream
1259  *
1260  * Returns the index of the segment containing @time_position.
1261  * Returns the last segment and sets the @eos variable to TRUE
1262  * if the time is beyond the end. @eos may be NULL
1263  */
1264 static guint32
1265 gst_qtdemux_find_segment (GstQTDemux * qtdemux, QtDemuxStream * stream,
1266     GstClockTime time_position)
1267 {
1268   gint i;
1269   guint32 seg_idx;
1270
1271   GST_LOG_OBJECT (stream->pad, "finding segment for %" GST_TIME_FORMAT,
1272       GST_TIME_ARGS (time_position));
1273
1274   seg_idx = -1;
1275   for (i = 0; i < stream->n_segments; i++) {
1276     QtDemuxSegment *segment = &stream->segments[i];
1277
1278     GST_LOG_OBJECT (stream->pad,
1279         "looking at segment %" GST_TIME_FORMAT "-%" GST_TIME_FORMAT,
1280         GST_TIME_ARGS (segment->time), GST_TIME_ARGS (segment->stop_time));
1281
1282     /* For the last segment we include stop_time in the last segment */
1283     if (i < stream->n_segments - 1) {
1284       if (segment->time <= time_position && time_position < segment->stop_time) {
1285         GST_LOG_OBJECT (stream->pad, "segment %d matches", i);
1286         seg_idx = i;
1287         break;
1288       }
1289     } else {
1290       /* Last segment always matches */
1291       seg_idx = i;
1292       break;
1293     }
1294   }
1295   return seg_idx;
1296 }
1297
1298 /* move the stream @str to the sample position @index.
1299  *
1300  * Updates @str->sample_index and marks discontinuity if needed.
1301  */
1302 static void
1303 gst_qtdemux_move_stream (GstQTDemux * qtdemux, QtDemuxStream * str,
1304     guint32 index)
1305 {
1306   /* no change needed */
1307   if (index == str->sample_index)
1308     return;
1309
1310   GST_DEBUG_OBJECT (qtdemux, "moving to sample %u of %u", index,
1311       str->n_samples);
1312
1313   /* position changed, we have a discont */
1314   str->sample_index = index;
1315   str->offset_in_sample = 0;
1316   /* Each time we move in the stream we store the position where we are
1317    * starting from */
1318   str->from_sample = index;
1319   str->discont = TRUE;
1320 }
1321
1322 static void
1323 gst_qtdemux_adjust_seek (GstQTDemux * qtdemux, gint64 desired_time,
1324     gboolean use_sparse, gboolean next, gint64 * key_time, gint64 * key_offset)
1325 {
1326   guint64 min_offset;
1327   gint64 min_byte_offset = -1;
1328   GList *iter;
1329
1330   min_offset = desired_time;
1331
1332   /* for each stream, find the index of the sample in the segment
1333    * and move back to the previous keyframe. */
1334   for (iter = qtdemux->active_streams; iter; iter = g_list_next (iter)) {
1335     QtDemuxStream *str;
1336     guint32 index, kindex;
1337     guint32 seg_idx;
1338     GstClockTime media_start;
1339     GstClockTime media_time;
1340     GstClockTime seg_time;
1341     QtDemuxSegment *seg;
1342     gboolean empty_segment = FALSE;
1343
1344     str = QTDEMUX_STREAM (iter->data);
1345
1346     if (CUR_STREAM (str)->sparse && !use_sparse)
1347       continue;
1348
1349     seg_idx = gst_qtdemux_find_segment (qtdemux, str, desired_time);
1350     GST_DEBUG_OBJECT (qtdemux, "align segment %d", seg_idx);
1351
1352     /* get segment and time in the segment */
1353     seg = &str->segments[seg_idx];
1354     seg_time = (desired_time - seg->time) * seg->rate;
1355
1356     while (QTSEGMENT_IS_EMPTY (seg)) {
1357       seg_time = 0;
1358       empty_segment = TRUE;
1359       GST_DEBUG_OBJECT (str->pad, "Segment %d is empty, moving to next one",
1360           seg_idx);
1361       seg_idx++;
1362       if (seg_idx == str->n_segments)
1363         break;
1364       seg = &str->segments[seg_idx];
1365     }
1366
1367     if (seg_idx == str->n_segments) {
1368       /* FIXME track shouldn't have the last segment as empty, but if it
1369        * happens we better handle it */
1370       continue;
1371     }
1372
1373     /* get the media time in the segment */
1374     media_start = seg->media_start + seg_time;
1375
1376     /* get the index of the sample with media time */
1377     index = gst_qtdemux_find_index_linear (qtdemux, str, media_start);
1378     GST_DEBUG_OBJECT (qtdemux, "sample for %" GST_TIME_FORMAT " at %u"
1379         " at offset %" G_GUINT64_FORMAT " (empty segment: %d)",
1380         GST_TIME_ARGS (media_start), index, str->samples[index].offset,
1381         empty_segment);
1382
1383     /* shift to next frame if we are looking for next keyframe */
1384     if (next && QTSAMPLE_PTS_NO_CSLG (str, &str->samples[index]) < media_start
1385         && index < str->stbl_index)
1386       index++;
1387
1388     if (!empty_segment) {
1389       /* find previous keyframe */
1390       kindex = gst_qtdemux_find_keyframe (qtdemux, str, index, next);
1391
1392       /* we will settle for one before if none found after */
1393       if (next && kindex == -1)
1394         kindex = gst_qtdemux_find_keyframe (qtdemux, str, index, FALSE);
1395
1396       /* if the keyframe is at a different position, we need to update the
1397        * requested seek time */
1398       if (index != kindex) {
1399         index = kindex;
1400
1401         /* get timestamp of keyframe */
1402         media_time = QTSAMPLE_PTS_NO_CSLG (str, &str->samples[kindex]);
1403         GST_DEBUG_OBJECT (qtdemux,
1404             "keyframe at %u with time %" GST_TIME_FORMAT " at offset %"
1405             G_GUINT64_FORMAT, kindex, GST_TIME_ARGS (media_time),
1406             str->samples[kindex].offset);
1407
1408         /* keyframes in the segment get a chance to change the
1409          * desired_offset. keyframes out of the segment are
1410          * ignored. */
1411         if (media_time >= seg->media_start) {
1412           GstClockTime seg_time;
1413
1414           /* this keyframe is inside the segment, convert back to
1415            * segment time */
1416           seg_time = (media_time - seg->media_start) + seg->time;
1417           if ((!next && (seg_time < min_offset)) ||
1418               (next && (seg_time > min_offset)))
1419             min_offset = seg_time;
1420         }
1421       }
1422     }
1423
1424     if (min_byte_offset < 0 || str->samples[index].offset < min_byte_offset)
1425       min_byte_offset = str->samples[index].offset;
1426   }
1427
1428   if (key_time)
1429     *key_time = min_offset;
1430   if (key_offset)
1431     *key_offset = min_byte_offset;
1432 }
1433
1434 static gboolean
1435 gst_qtdemux_convert_seek (GstPad * pad, GstFormat * format,
1436     GstSeekType cur_type, gint64 * cur, GstSeekType stop_type, gint64 * stop)
1437 {
1438   gboolean res;
1439
1440   g_return_val_if_fail (format != NULL, FALSE);
1441   g_return_val_if_fail (cur != NULL, FALSE);
1442   g_return_val_if_fail (stop != NULL, FALSE);
1443
1444   if (*format == GST_FORMAT_TIME)
1445     return TRUE;
1446
1447   res = TRUE;
1448   if (cur_type != GST_SEEK_TYPE_NONE)
1449     res = gst_pad_query_convert (pad, *format, *cur, GST_FORMAT_TIME, cur);
1450   if (res && stop_type != GST_SEEK_TYPE_NONE)
1451     res = gst_pad_query_convert (pad, *format, *stop, GST_FORMAT_TIME, stop);
1452
1453   if (res)
1454     *format = GST_FORMAT_TIME;
1455
1456   return res;
1457 }
1458
1459 /* perform seek in push based mode:
1460    find BYTE position to move to based on time and delegate to upstream
1461 */
1462 static gboolean
1463 gst_qtdemux_do_push_seek (GstQTDemux * qtdemux, GstPad * pad, GstEvent * event)
1464 {
1465   gdouble rate;
1466   GstFormat format;
1467   GstSeekFlags flags;
1468   GstSeekType cur_type, stop_type;
1469   gint64 cur, stop, key_cur;
1470   gboolean res;
1471   gint64 byte_cur;
1472   gint64 original_stop;
1473   guint32 seqnum;
1474
1475   GST_DEBUG_OBJECT (qtdemux, "doing push-based seek");
1476
1477   gst_event_parse_seek (event, &rate, &format, &flags,
1478       &cur_type, &cur, &stop_type, &stop);
1479   seqnum = gst_event_get_seqnum (event);
1480
1481   /* only forward streaming and seeking is possible */
1482   if (rate <= 0)
1483     goto unsupported_seek;
1484
1485   /* convert to TIME if needed and possible */
1486   if (!gst_qtdemux_convert_seek (pad, &format, cur_type, &cur,
1487           stop_type, &stop))
1488     goto no_format;
1489
1490   /* Upstream seek in bytes will have undefined stop, but qtdemux stores
1491    * the original stop position to use when upstream pushes the new segment
1492    * for this seek */
1493   original_stop = stop;
1494   stop = -1;
1495
1496   /* find reasonable corresponding BYTE position,
1497    * also try to mind about keyframes, since we can not go back a bit for them
1498    * later on */
1499   /* determining @next here based on SNAP_BEFORE/SNAP_AFTER should
1500    * mostly just work, but let's not yet boldly go there  ... */
1501   gst_qtdemux_adjust_seek (qtdemux, cur, FALSE, FALSE, &key_cur, &byte_cur);
1502
1503   if (byte_cur == -1)
1504     goto abort_seek;
1505
1506   GST_DEBUG_OBJECT (qtdemux, "Pushing BYTE seek rate %g, "
1507       "start %" G_GINT64_FORMAT ", stop %" G_GINT64_FORMAT, rate, byte_cur,
1508       stop);
1509
1510   GST_OBJECT_LOCK (qtdemux);
1511   qtdemux->seek_offset = byte_cur;
1512   if (!(flags & GST_SEEK_FLAG_KEY_UNIT)) {
1513     qtdemux->push_seek_start = cur;
1514   } else {
1515     qtdemux->push_seek_start = key_cur;
1516   }
1517
1518   if (stop_type == GST_SEEK_TYPE_NONE) {
1519     qtdemux->push_seek_stop = qtdemux->segment.stop;
1520   } else {
1521     qtdemux->push_seek_stop = original_stop;
1522   }
1523   GST_OBJECT_UNLOCK (qtdemux);
1524
1525   /* BYTE seek event */
1526   event = gst_event_new_seek (rate, GST_FORMAT_BYTES, flags, cur_type, byte_cur,
1527       stop_type, stop);
1528   gst_event_set_seqnum (event, seqnum);
1529   res = gst_pad_push_event (qtdemux->sinkpad, event);
1530
1531   return res;
1532
1533   /* ERRORS */
1534 abort_seek:
1535   {
1536     GST_DEBUG_OBJECT (qtdemux, "could not determine byte position to seek to, "
1537         "seek aborted.");
1538     return FALSE;
1539   }
1540 unsupported_seek:
1541   {
1542     GST_DEBUG_OBJECT (qtdemux, "unsupported seek, seek aborted.");
1543     return FALSE;
1544   }
1545 no_format:
1546   {
1547     GST_DEBUG_OBJECT (qtdemux, "unsupported format given, seek aborted.");
1548     return FALSE;
1549   }
1550 }
1551
1552 /* perform the seek.
1553  *
1554  * We set all segment_indexes in the streams to unknown and
1555  * adjust the time_position to the desired position. this is enough
1556  * to trigger a segment switch in the streaming thread to start
1557  * streaming from the desired position.
1558  *
1559  * Keyframe seeking is a little more complicated when dealing with
1560  * segments. Ideally we want to move to the previous keyframe in
1561  * the segment but there might not be a keyframe in the segment. In
1562  * fact, none of the segments could contain a keyframe. We take a
1563  * practical approach: seek to the previous keyframe in the segment,
1564  * if there is none, seek to the beginning of the segment.
1565  *
1566  * Called with STREAM_LOCK
1567  */
1568 static gboolean
1569 gst_qtdemux_perform_seek (GstQTDemux * qtdemux, GstSegment * segment,
1570     guint32 seqnum, GstSeekFlags flags)
1571 {
1572   gint64 desired_offset;
1573   GList *iter;
1574
1575   desired_offset = segment->position;
1576
1577   GST_DEBUG_OBJECT (qtdemux, "seeking to %" GST_TIME_FORMAT,
1578       GST_TIME_ARGS (desired_offset));
1579
1580   /* may not have enough fragmented info to do this adjustment,
1581    * and we can't scan (and probably should not) at this time with
1582    * possibly flushing upstream */
1583   if ((flags & GST_SEEK_FLAG_KEY_UNIT) && !qtdemux->fragmented) {
1584     gint64 min_offset;
1585     gboolean next, before, after;
1586
1587     before = ! !(flags & GST_SEEK_FLAG_SNAP_BEFORE);
1588     after = ! !(flags & GST_SEEK_FLAG_SNAP_AFTER);
1589     next = after && !before;
1590     if (segment->rate < 0)
1591       next = !next;
1592
1593     gst_qtdemux_adjust_seek (qtdemux, desired_offset, TRUE, next, &min_offset,
1594         NULL);
1595     GST_DEBUG_OBJECT (qtdemux, "keyframe seek, align to %"
1596         GST_TIME_FORMAT, GST_TIME_ARGS (min_offset));
1597     desired_offset = min_offset;
1598   }
1599
1600   /* and set all streams to the final position */
1601   gst_flow_combiner_reset (qtdemux->flowcombiner);
1602   qtdemux->segment_seqnum = seqnum;
1603   for (iter = qtdemux->active_streams; iter; iter = g_list_next (iter)) {
1604     QtDemuxStream *stream = QTDEMUX_STREAM (iter->data);
1605
1606     stream->time_position = desired_offset;
1607     stream->accumulated_base = 0;
1608     stream->sample_index = -1;
1609     stream->offset_in_sample = 0;
1610     stream->segment_index = -1;
1611     stream->sent_eos = FALSE;
1612
1613     if (segment->flags & GST_SEEK_FLAG_FLUSH)
1614       gst_segment_init (&stream->segment, GST_FORMAT_TIME);
1615   }
1616   segment->position = desired_offset;
1617   segment->time = desired_offset;
1618   if (segment->rate >= 0) {
1619     segment->start = desired_offset;
1620
1621     /* we stop at the end */
1622     if (segment->stop == -1)
1623       segment->stop = segment->duration;
1624   } else {
1625     segment->stop = desired_offset;
1626   }
1627
1628   if (qtdemux->fragmented)
1629     qtdemux->fragmented_seek_pending = TRUE;
1630
1631   return TRUE;
1632 }
1633
1634 /* do a seek in pull based mode */
1635 static gboolean
1636 gst_qtdemux_do_seek (GstQTDemux * qtdemux, GstPad * pad, GstEvent * event)
1637 {
1638   gdouble rate;
1639   GstFormat format;
1640   GstSeekFlags flags;
1641   GstSeekType cur_type, stop_type;
1642   gint64 cur, stop;
1643   gboolean flush;
1644   gboolean update;
1645   GstSegment seeksegment;
1646   guint32 seqnum = GST_SEQNUM_INVALID;
1647   GstEvent *flush_event;
1648   gboolean ret;
1649
1650   if (event) {
1651     GST_DEBUG_OBJECT (qtdemux, "doing seek with event");
1652
1653     gst_event_parse_seek (event, &rate, &format, &flags,
1654         &cur_type, &cur, &stop_type, &stop);
1655     seqnum = gst_event_get_seqnum (event);
1656
1657     /* we have to have a format as the segment format. Try to convert
1658      * if not. */
1659     if (!gst_qtdemux_convert_seek (pad, &format, cur_type, &cur,
1660             stop_type, &stop))
1661       goto no_format;
1662
1663     GST_DEBUG_OBJECT (qtdemux, "seek format %s", gst_format_get_name (format));
1664   } else {
1665     GST_DEBUG_OBJECT (qtdemux, "doing seek without event");
1666     flags = 0;
1667   }
1668
1669   flush = flags & GST_SEEK_FLAG_FLUSH;
1670
1671   /* stop streaming, either by flushing or by pausing the task */
1672   if (flush) {
1673     flush_event = gst_event_new_flush_start ();
1674     if (seqnum != GST_SEQNUM_INVALID)
1675       gst_event_set_seqnum (flush_event, seqnum);
1676     /* unlock upstream pull_range */
1677     gst_pad_push_event (qtdemux->sinkpad, gst_event_ref (flush_event));
1678     /* make sure out loop function exits */
1679     gst_qtdemux_push_event (qtdemux, flush_event);
1680   } else {
1681     /* non flushing seek, pause the task */
1682     gst_pad_pause_task (qtdemux->sinkpad);
1683   }
1684
1685   /* wait for streaming to finish */
1686   GST_PAD_STREAM_LOCK (qtdemux->sinkpad);
1687
1688   /* copy segment, we need this because we still need the old
1689    * segment when we close the current segment. */
1690   memcpy (&seeksegment, &qtdemux->segment, sizeof (GstSegment));
1691
1692   if (event) {
1693     /* configure the segment with the seek variables */
1694     GST_DEBUG_OBJECT (qtdemux, "configuring seek");
1695     if (!gst_segment_do_seek (&seeksegment, rate, format, flags,
1696             cur_type, cur, stop_type, stop, &update)) {
1697       ret = FALSE;
1698       GST_ERROR_OBJECT (qtdemux, "inconsistent seek values, doing nothing");
1699     } else {
1700       /* now do the seek */
1701       ret = gst_qtdemux_perform_seek (qtdemux, &seeksegment, seqnum, flags);
1702     }
1703   } else {
1704     /* now do the seek */
1705     ret = gst_qtdemux_perform_seek (qtdemux, &seeksegment, seqnum, flags);
1706   }
1707
1708   /* prepare for streaming again */
1709   if (flush) {
1710     flush_event = gst_event_new_flush_stop (TRUE);
1711     if (seqnum != GST_SEQNUM_INVALID)
1712       gst_event_set_seqnum (flush_event, seqnum);
1713
1714     gst_pad_push_event (qtdemux->sinkpad, gst_event_ref (flush_event));
1715     gst_qtdemux_push_event (qtdemux, flush_event);
1716   }
1717
1718   /* commit the new segment */
1719   memcpy (&qtdemux->segment, &seeksegment, sizeof (GstSegment));
1720
1721   if (qtdemux->segment.flags & GST_SEEK_FLAG_SEGMENT) {
1722     GstMessage *msg = gst_message_new_segment_start (GST_OBJECT_CAST (qtdemux),
1723         qtdemux->segment.format, qtdemux->segment.position);
1724     if (seqnum != GST_SEQNUM_INVALID)
1725       gst_message_set_seqnum (msg, seqnum);
1726     gst_element_post_message (GST_ELEMENT_CAST (qtdemux), msg);
1727   }
1728
1729   /* restart streaming, NEWSEGMENT will be sent from the streaming thread. */
1730   gst_pad_start_task (qtdemux->sinkpad, (GstTaskFunction) gst_qtdemux_loop,
1731       qtdemux->sinkpad, NULL);
1732
1733   GST_PAD_STREAM_UNLOCK (qtdemux->sinkpad);
1734
1735   return ret;
1736
1737   /* ERRORS */
1738 no_format:
1739   {
1740     GST_DEBUG_OBJECT (qtdemux, "unsupported format given, seek aborted.");
1741     return FALSE;
1742   }
1743 }
1744
1745 static gboolean
1746 qtdemux_ensure_index (GstQTDemux * qtdemux)
1747 {
1748   GList *iter;
1749
1750   GST_DEBUG_OBJECT (qtdemux, "collecting all metadata for all streams");
1751
1752   /* Build complete index */
1753   for (iter = qtdemux->active_streams; iter; iter = g_list_next (iter)) {
1754     QtDemuxStream *stream = QTDEMUX_STREAM (iter->data);
1755
1756     if (!qtdemux_parse_samples (qtdemux, stream, stream->n_samples - 1)) {
1757       GST_LOG_OBJECT (qtdemux,
1758           "Building complete index of track-id %u for seeking failed!",
1759           stream->track_id);
1760       return FALSE;
1761     }
1762   }
1763
1764   return TRUE;
1765 }
1766
1767 static gboolean
1768 gst_qtdemux_handle_src_event (GstPad * pad, GstObject * parent,
1769     GstEvent * event)
1770 {
1771   gboolean res = TRUE;
1772   GstQTDemux *qtdemux = GST_QTDEMUX (parent);
1773
1774   switch (GST_EVENT_TYPE (event)) {
1775     case GST_EVENT_SEEK:
1776     {
1777 #ifndef GST_DISABLE_GST_DEBUG
1778       GstClockTime ts = gst_util_get_timestamp ();
1779 #endif
1780       guint32 seqnum = gst_event_get_seqnum (event);
1781
1782       if (seqnum == qtdemux->segment_seqnum) {
1783         GST_LOG_OBJECT (pad,
1784             "Drop duplicated SEEK event seqnum %" G_GUINT32_FORMAT, seqnum);
1785         gst_event_unref (event);
1786         return TRUE;
1787       }
1788
1789       if (qtdemux->upstream_format_is_time && qtdemux->fragmented) {
1790         /* seek should be handled by upstream, we might need to re-download fragments */
1791         GST_DEBUG_OBJECT (qtdemux,
1792             "let upstream handle seek for fragmented playback");
1793         goto upstream;
1794       }
1795
1796       /* Build complete index for seeking;
1797        * if not a fragmented file at least */
1798       if (!qtdemux->fragmented)
1799         if (!qtdemux_ensure_index (qtdemux))
1800           goto index_failed;
1801 #ifndef GST_DISABLE_GST_DEBUG
1802       ts = gst_util_get_timestamp () - ts;
1803       GST_INFO_OBJECT (qtdemux,
1804           "Time taken to parse index %" GST_TIME_FORMAT, GST_TIME_ARGS (ts));
1805 #endif
1806     }
1807       if (qtdemux->pullbased) {
1808         res = gst_qtdemux_do_seek (qtdemux, pad, event);
1809       } else if (gst_pad_push_event (qtdemux->sinkpad, gst_event_ref (event))) {
1810         GST_DEBUG_OBJECT (qtdemux, "Upstream successfully seeked");
1811         res = TRUE;
1812       } else if (qtdemux->state == QTDEMUX_STATE_MOVIE && qtdemux->n_streams
1813           && !qtdemux->fragmented) {
1814         res = gst_qtdemux_do_push_seek (qtdemux, pad, event);
1815       } else {
1816         GST_DEBUG_OBJECT (qtdemux,
1817             "ignoring seek in push mode in current state");
1818         res = FALSE;
1819       }
1820       gst_event_unref (event);
1821       break;
1822     default:
1823     upstream:
1824       res = gst_pad_event_default (pad, parent, event);
1825       break;
1826   }
1827
1828 done:
1829   return res;
1830
1831   /* ERRORS */
1832 index_failed:
1833   {
1834     GST_ERROR_OBJECT (qtdemux, "Index failed");
1835     gst_event_unref (event);
1836     res = FALSE;
1837     goto done;
1838   }
1839 }
1840
1841 /* Find, for each track, the first sample in coding order that has a file offset >= @byte_pos.
1842  *
1843  * If @fw is false, the coding order is explored backwards.
1844  *
1845  * If @set is true, each stream will be moved to its matched sample, or EOS if no matching
1846  * sample is found for that track.
1847  *
1848  * The stream and sample index of the sample with the minimum offset in the direction explored
1849  * (see @fw) is returned in the output parameters @_stream and @_index respectively.
1850  *
1851  * @_time is set to the QTSAMPLE_PTS of the matched sample with the minimum QTSAMPLE_PTS in the
1852  * direction explored, which may not always match the QTSAMPLE_PTS of the sample returned in
1853  * @_stream and @_index. */
1854 static void
1855 gst_qtdemux_find_sample (GstQTDemux * qtdemux, gint64 byte_pos, gboolean fw,
1856     gboolean set, QtDemuxStream ** _stream, gint * _index, gint64 * _time)
1857 {
1858   gint i, index;
1859   gint64 time, min_time;
1860   QtDemuxStream *stream;
1861   GList *iter;
1862
1863   min_time = -1;
1864   stream = NULL;
1865   index = -1;
1866
1867   for (iter = qtdemux->active_streams; iter; iter = g_list_next (iter)) {
1868     QtDemuxStream *str;
1869     gint inc;
1870     gboolean set_sample;
1871
1872     str = QTDEMUX_STREAM (iter->data);
1873     set_sample = !set;
1874
1875     if (fw) {
1876       i = 0;
1877       inc = 1;
1878     } else {
1879       i = str->n_samples - 1;
1880       inc = -1;
1881     }
1882
1883     for (; (i >= 0) && (i < str->n_samples); i += inc) {
1884       if (str->samples[i].size == 0)
1885         continue;
1886
1887       if (fw && (str->samples[i].offset < byte_pos))
1888         continue;
1889
1890       if (!fw && (str->samples[i].offset + str->samples[i].size > byte_pos))
1891         continue;
1892
1893       /* move stream to first available sample */
1894       if (set) {
1895         gst_qtdemux_move_stream (qtdemux, str, i);
1896         set_sample = TRUE;
1897       }
1898
1899       /* avoid index from sparse streams since they might be far away */
1900       if (!CUR_STREAM (str)->sparse) {
1901         /* determine min/max time */
1902         time = QTSAMPLE_PTS (str, &str->samples[i]);
1903         if (min_time == -1 || (!fw && time > min_time) ||
1904             (fw && time < min_time)) {
1905           min_time = time;
1906         }
1907
1908         /* determine stream with leading sample, to get its position */
1909         if (!stream ||
1910             (fw && (str->samples[i].offset < stream->samples[index].offset)) ||
1911             (!fw && (str->samples[i].offset > stream->samples[index].offset))) {
1912           stream = str;
1913           index = i;
1914         }
1915       }
1916       break;
1917     }
1918
1919     /* no sample for this stream, mark eos */
1920     if (!set_sample)
1921       gst_qtdemux_move_stream (qtdemux, str, str->n_samples);
1922   }
1923
1924   if (_time)
1925     *_time = min_time;
1926   if (_stream)
1927     *_stream = stream;
1928   if (_index)
1929     *_index = index;
1930 }
1931
1932 /* Copied from mpegtsbase code */
1933 /* FIXME: replace this function when we add new util function for stream-id creation */
1934 static gchar *
1935 _get_upstream_id (GstQTDemux * demux)
1936 {
1937   gchar *upstream_id = gst_pad_get_stream_id (demux->sinkpad);
1938
1939   if (!upstream_id) {
1940     /* Try to create one from the upstream URI, else use a randome number */
1941     GstQuery *query;
1942     gchar *uri = NULL;
1943
1944     /* Try to generate one from the URI query and
1945      * if it fails take a random number instead */
1946     query = gst_query_new_uri ();
1947     if (gst_element_query (GST_ELEMENT_CAST (demux), query)) {
1948       gst_query_parse_uri (query, &uri);
1949     }
1950
1951     if (uri) {
1952       GChecksum *cs;
1953
1954       /* And then generate an SHA256 sum of the URI */
1955       cs = g_checksum_new (G_CHECKSUM_SHA256);
1956       g_checksum_update (cs, (const guchar *) uri, strlen (uri));
1957       g_free (uri);
1958       upstream_id = g_strdup (g_checksum_get_string (cs));
1959       g_checksum_free (cs);
1960     } else {
1961       /* Just get some random number if the URI query fails */
1962       GST_FIXME_OBJECT (demux, "Creating random stream-id, consider "
1963           "implementing a deterministic way of creating a stream-id");
1964       upstream_id =
1965           g_strdup_printf ("%08x%08x%08x%08x", g_random_int (), g_random_int (),
1966           g_random_int (), g_random_int ());
1967     }
1968
1969     gst_query_unref (query);
1970   }
1971   return upstream_id;
1972 }
1973
1974 static QtDemuxStream *
1975 _create_stream (GstQTDemux * demux, guint32 track_id)
1976 {
1977   QtDemuxStream *stream;
1978   gchar *upstream_id;
1979
1980   stream = g_new0 (QtDemuxStream, 1);
1981   stream->demux = demux;
1982   stream->track_id = track_id;
1983   upstream_id = _get_upstream_id (demux);
1984   stream->stream_id = g_strdup_printf ("%s/%03u", upstream_id, track_id);
1985   g_free (upstream_id);
1986   /* new streams always need a discont */
1987   stream->discont = TRUE;
1988   /* we enable clipping for raw audio/video streams */
1989   stream->need_clip = FALSE;
1990   stream->need_process = FALSE;
1991   stream->segment_index = -1;
1992   stream->time_position = 0;
1993   stream->sample_index = -1;
1994   stream->offset_in_sample = 0;
1995   stream->new_stream = TRUE;
1996   stream->multiview_mode = GST_VIDEO_MULTIVIEW_MODE_NONE;
1997   stream->multiview_flags = GST_VIDEO_MULTIVIEW_FLAGS_NONE;
1998   stream->protected = FALSE;
1999   stream->protection_scheme_type = 0;
2000   stream->protection_scheme_version = 0;
2001   stream->protection_scheme_info = NULL;
2002   stream->n_samples_moof = 0;
2003   stream->duration_moof = 0;
2004   stream->duration_last_moof = 0;
2005   stream->alignment = 1;
2006   stream->stream_tags = gst_tag_list_new_empty ();
2007   gst_tag_list_set_scope (stream->stream_tags, GST_TAG_SCOPE_STREAM);
2008   g_queue_init (&stream->protection_scheme_event_queue);
2009   return stream;
2010 }
2011
2012 static gboolean
2013 gst_qtdemux_setcaps (GstQTDemux * demux, GstCaps * caps)
2014 {
2015   GstStructure *structure;
2016   const gchar *variant;
2017   const GstCaps *mediacaps = NULL;
2018
2019   GST_DEBUG_OBJECT (demux, "Sink set caps: %" GST_PTR_FORMAT, caps);
2020
2021   structure = gst_caps_get_structure (caps, 0);
2022   variant = gst_structure_get_string (structure, "variant");
2023
2024   if (variant && strcmp (variant, "mss-fragmented") == 0) {
2025     QtDemuxStream *stream;
2026     const GValue *value;
2027
2028     demux->fragmented = TRUE;
2029     demux->mss_mode = TRUE;
2030
2031     if (demux->n_streams > 1) {
2032       /* can't do this, we can only renegotiate for another mss format */
2033       return FALSE;
2034     }
2035
2036     value = gst_structure_get_value (structure, "media-caps");
2037     /* create stream */
2038     if (value) {
2039       const GValue *timescale_v;
2040
2041       /* TODO update when stream changes during playback */
2042
2043       if (demux->n_streams == 0) {
2044         stream = _create_stream (demux, 1);
2045         demux->active_streams = g_list_append (demux->active_streams, stream);
2046         demux->n_streams = 1;
2047         /* mss has no stsd/stsd entry, use id 0 as default */
2048         stream->stsd_entries_length = 1;
2049         stream->stsd_sample_description_id = stream->cur_stsd_entry_index = 0;
2050         stream->stsd_entries = g_new0 (QtDemuxStreamStsdEntry, 1);
2051       } else {
2052         stream = QTDEMUX_FIRST_STREAM (demux);
2053       }
2054
2055       timescale_v = gst_structure_get_value (structure, "timescale");
2056       if (timescale_v) {
2057         stream->timescale = g_value_get_uint64 (timescale_v);
2058       } else {
2059         /* default mss timescale */
2060         stream->timescale = 10000000;
2061       }
2062       demux->timescale = stream->timescale;
2063
2064       mediacaps = gst_value_get_caps (value);
2065       if (!CUR_STREAM (stream)->caps
2066           || !gst_caps_is_equal_fixed (mediacaps, CUR_STREAM (stream)->caps)) {
2067         GST_DEBUG_OBJECT (demux, "We have a new caps %" GST_PTR_FORMAT,
2068             mediacaps);
2069         stream->new_caps = TRUE;
2070       }
2071       gst_caps_replace (&CUR_STREAM (stream)->caps, (GstCaps *) mediacaps);
2072       structure = gst_caps_get_structure (mediacaps, 0);
2073       if (g_str_has_prefix (gst_structure_get_name (structure), "video")) {
2074         stream->subtype = FOURCC_vide;
2075
2076         gst_structure_get_int (structure, "width", &CUR_STREAM (stream)->width);
2077         gst_structure_get_int (structure, "height",
2078             &CUR_STREAM (stream)->height);
2079         gst_structure_get_fraction (structure, "framerate",
2080             &CUR_STREAM (stream)->fps_n, &CUR_STREAM (stream)->fps_d);
2081       } else if (g_str_has_prefix (gst_structure_get_name (structure), "audio")) {
2082         gint rate = 0;
2083         stream->subtype = FOURCC_soun;
2084         gst_structure_get_int (structure, "channels",
2085             &CUR_STREAM (stream)->n_channels);
2086         gst_structure_get_int (structure, "rate", &rate);
2087         CUR_STREAM (stream)->rate = rate;
2088       }
2089     }
2090     gst_caps_replace (&demux->media_caps, (GstCaps *) mediacaps);
2091   } else {
2092     demux->mss_mode = FALSE;
2093   }
2094
2095   return TRUE;
2096 }
2097
2098 static void
2099 gst_qtdemux_reset (GstQTDemux * qtdemux, gboolean hard)
2100 {
2101   GList *iter;
2102
2103   GST_DEBUG_OBJECT (qtdemux, "Resetting demux");
2104   gst_pad_stop_task (qtdemux->sinkpad);
2105
2106   if (hard || qtdemux->upstream_format_is_time) {
2107     qtdemux->state = QTDEMUX_STATE_INITIAL;
2108     qtdemux->neededbytes = 16;
2109     qtdemux->todrop = 0;
2110     qtdemux->pullbased = FALSE;
2111     qtdemux->posted_redirect = FALSE;
2112     qtdemux->first_mdat = -1;
2113     qtdemux->header_size = 0;
2114     qtdemux->mdatoffset = -1;
2115     qtdemux->restoredata_offset = -1;
2116     if (qtdemux->mdatbuffer)
2117       gst_buffer_unref (qtdemux->mdatbuffer);
2118     if (qtdemux->restoredata_buffer)
2119       gst_buffer_unref (qtdemux->restoredata_buffer);
2120     qtdemux->mdatbuffer = NULL;
2121     qtdemux->restoredata_buffer = NULL;
2122     qtdemux->mdatleft = 0;
2123     qtdemux->mdatsize = 0;
2124     if (qtdemux->comp_brands)
2125       gst_buffer_unref (qtdemux->comp_brands);
2126     qtdemux->comp_brands = NULL;
2127     qtdemux->last_moov_offset = -1;
2128     if (qtdemux->moov_node_compressed) {
2129       g_node_destroy (qtdemux->moov_node_compressed);
2130       if (qtdemux->moov_node)
2131         g_free (qtdemux->moov_node->data);
2132     }
2133     qtdemux->moov_node_compressed = NULL;
2134     if (qtdemux->moov_node)
2135       g_node_destroy (qtdemux->moov_node);
2136     qtdemux->moov_node = NULL;
2137     if (qtdemux->tag_list)
2138       gst_mini_object_unref (GST_MINI_OBJECT_CAST (qtdemux->tag_list));
2139     qtdemux->tag_list = gst_tag_list_new_empty ();
2140     gst_tag_list_set_scope (qtdemux->tag_list, GST_TAG_SCOPE_GLOBAL);
2141 #if 0
2142     if (qtdemux->element_index)
2143       gst_object_unref (qtdemux->element_index);
2144     qtdemux->element_index = NULL;
2145 #endif
2146     qtdemux->major_brand = 0;
2147     if (qtdemux->pending_newsegment)
2148       gst_event_unref (qtdemux->pending_newsegment);
2149     qtdemux->pending_newsegment = NULL;
2150     qtdemux->upstream_format_is_time = FALSE;
2151     qtdemux->upstream_seekable = FALSE;
2152     qtdemux->upstream_size = 0;
2153
2154     qtdemux->fragment_start = -1;
2155     qtdemux->fragment_start_offset = -1;
2156     qtdemux->duration = 0;
2157     qtdemux->moof_offset = 0;
2158     qtdemux->chapters_track_id = 0;
2159     qtdemux->have_group_id = FALSE;
2160     qtdemux->group_id = G_MAXUINT;
2161
2162     g_queue_foreach (&qtdemux->protection_event_queue, (GFunc) gst_event_unref,
2163         NULL);
2164     g_queue_clear (&qtdemux->protection_event_queue);
2165   }
2166   qtdemux->offset = 0;
2167   gst_adapter_clear (qtdemux->adapter);
2168   gst_segment_init (&qtdemux->segment, GST_FORMAT_TIME);
2169   qtdemux->segment_seqnum = GST_SEQNUM_INVALID;
2170
2171   if (hard) {
2172     g_list_free_full (qtdemux->active_streams,
2173         (GDestroyNotify) gst_qtdemux_stream_free);
2174     qtdemux->active_streams = NULL;
2175     qtdemux->n_streams = 0;
2176     qtdemux->n_video_streams = 0;
2177     qtdemux->n_audio_streams = 0;
2178     qtdemux->n_sub_streams = 0;
2179     qtdemux->exposed = FALSE;
2180     qtdemux->fragmented = FALSE;
2181     qtdemux->mss_mode = FALSE;
2182     gst_caps_replace (&qtdemux->media_caps, NULL);
2183     qtdemux->timescale = 0;
2184     qtdemux->got_moov = FALSE;
2185     if (qtdemux->protection_system_ids) {
2186       g_ptr_array_free (qtdemux->protection_system_ids, TRUE);
2187       qtdemux->protection_system_ids = NULL;
2188     }
2189   } else if (qtdemux->mss_mode) {
2190     gst_flow_combiner_reset (qtdemux->flowcombiner);
2191     g_list_foreach (qtdemux->active_streams,
2192         (GFunc) gst_qtdemux_stream_clear, NULL);
2193   } else {
2194     gst_flow_combiner_reset (qtdemux->flowcombiner);
2195     for (iter = qtdemux->active_streams; iter; iter = g_list_next (iter)) {
2196       QtDemuxStream *stream = QTDEMUX_STREAM (iter->data);
2197       stream->sent_eos = FALSE;
2198       stream->time_position = 0;
2199       stream->accumulated_base = 0;
2200     }
2201     if (!qtdemux->pending_newsegment) {
2202       qtdemux->pending_newsegment = gst_event_new_segment (&qtdemux->segment);
2203       if (qtdemux->segment_seqnum != GST_SEQNUM_INVALID)
2204         gst_event_set_seqnum (qtdemux->pending_newsegment,
2205             qtdemux->segment_seqnum);
2206     }
2207   }
2208 }
2209
2210
2211 /* Maps the @segment to the qt edts internal segments and pushes
2212  * the correspnding segment event.
2213  *
2214  * If it ends up being at a empty segment, a gap will be pushed and the next
2215  * edts segment will be activated in sequence.
2216  *
2217  * To be used in push-mode only */
2218 static void
2219 gst_qtdemux_map_and_push_segments (GstQTDemux * qtdemux, GstSegment * segment)
2220 {
2221   gint i;
2222   GList *iter;
2223
2224   for (iter = qtdemux->active_streams; iter; iter = g_list_next (iter)) {
2225     QtDemuxStream *stream = QTDEMUX_STREAM (iter->data);
2226
2227     stream->time_position = segment->start;
2228
2229     /* in push mode we should be guaranteed that we will have empty segments
2230      * at the beginning and then one segment after, other scenarios are not
2231      * supported and are discarded when parsing the edts */
2232     for (i = 0; i < stream->n_segments; i++) {
2233       if (stream->segments[i].stop_time > segment->start) {
2234         gst_qtdemux_activate_segment (qtdemux, stream, i,
2235             stream->time_position);
2236         if (QTSEGMENT_IS_EMPTY (&stream->segments[i])) {
2237           /* push the empty segment and move to the next one */
2238           gst_qtdemux_send_gap_for_segment (qtdemux, stream, i,
2239               stream->time_position);
2240           continue;
2241         }
2242
2243         g_assert (i == stream->n_segments - 1);
2244       }
2245     }
2246   }
2247 }
2248
2249 static gboolean
2250 gst_qtdemux_handle_sink_event (GstPad * sinkpad, GstObject * parent,
2251     GstEvent * event)
2252 {
2253   GstQTDemux *demux = GST_QTDEMUX (parent);
2254   gboolean res = TRUE;
2255
2256   GST_LOG_OBJECT (demux, "handling %s event", GST_EVENT_TYPE_NAME (event));
2257
2258   switch (GST_EVENT_TYPE (event)) {
2259     case GST_EVENT_SEGMENT:
2260     {
2261       gint64 offset = 0;
2262       QtDemuxStream *stream;
2263       gint idx;
2264       GstSegment segment;
2265
2266       /* some debug output */
2267       gst_event_copy_segment (event, &segment);
2268       GST_DEBUG_OBJECT (demux, "received newsegment %" GST_SEGMENT_FORMAT,
2269           &segment);
2270
2271       /* erase any previously set segment */
2272       gst_event_replace (&demux->pending_newsegment, NULL);
2273
2274       if (segment.format == GST_FORMAT_TIME) {
2275         GST_DEBUG_OBJECT (demux, "new pending_newsegment");
2276         gst_event_replace (&demux->pending_newsegment, event);
2277         demux->upstream_format_is_time = TRUE;
2278       } else {
2279         GST_DEBUG_OBJECT (demux, "Not storing upstream newsegment, "
2280             "not in time format");
2281
2282         /* chain will send initial newsegment after pads have been added */
2283         if (demux->state != QTDEMUX_STATE_MOVIE || !demux->n_streams) {
2284           GST_DEBUG_OBJECT (demux, "still starting, eating event");
2285           goto exit;
2286         }
2287       }
2288
2289       /* check if this matches a time seek we received previously
2290        * FIXME for backwards compatibility reasons we use the
2291        * seek_offset here to compare. In the future we might want to
2292        * change this to use the seqnum as it uniquely should identify
2293        * the segment that corresponds to the seek. */
2294       GST_DEBUG_OBJECT (demux, "Stored seek offset: %" G_GINT64_FORMAT
2295           ", received segment offset %" G_GINT64_FORMAT,
2296           demux->seek_offset, segment.start);
2297       if (segment.format == GST_FORMAT_BYTES
2298           && demux->seek_offset == segment.start) {
2299         GST_OBJECT_LOCK (demux);
2300         offset = segment.start;
2301
2302         segment.format = GST_FORMAT_TIME;
2303         segment.start = demux->push_seek_start;
2304         segment.stop = demux->push_seek_stop;
2305         GST_DEBUG_OBJECT (demux, "Replaced segment with stored seek "
2306             "segment %" GST_TIME_FORMAT " - %" GST_TIME_FORMAT,
2307             GST_TIME_ARGS (segment.start), GST_TIME_ARGS (segment.stop));
2308         GST_OBJECT_UNLOCK (demux);
2309       }
2310
2311       /* we only expect a BYTE segment, e.g. following a seek */
2312       if (segment.format == GST_FORMAT_BYTES) {
2313         if (GST_CLOCK_TIME_IS_VALID (segment.start)) {
2314           offset = segment.start;
2315
2316           gst_qtdemux_find_sample (demux, segment.start, TRUE, FALSE, NULL,
2317               NULL, (gint64 *) & segment.start);
2318           if ((gint64) segment.start < 0)
2319             segment.start = 0;
2320         }
2321         if (GST_CLOCK_TIME_IS_VALID (segment.stop)) {
2322           gst_qtdemux_find_sample (demux, segment.stop, FALSE, FALSE, NULL,
2323               NULL, (gint64 *) & segment.stop);
2324           /* keyframe seeking should already arrange for start >= stop,
2325            * but make sure in other rare cases */
2326           segment.stop = MAX (segment.stop, segment.start);
2327         }
2328       } else if (segment.format == GST_FORMAT_TIME) {
2329         /* push all data on the adapter before starting this
2330          * new segment */
2331         gst_qtdemux_process_adapter (demux, TRUE);
2332       } else {
2333         GST_DEBUG_OBJECT (demux, "unsupported segment format, ignoring");
2334         goto exit;
2335       }
2336
2337       /* We shouldn't modify upstream driven TIME FORMAT segment */
2338       if (!demux->upstream_format_is_time) {
2339         /* accept upstream's notion of segment and distribute along */
2340         segment.format = GST_FORMAT_TIME;
2341         segment.position = segment.time = segment.start;
2342         segment.duration = demux->segment.duration;
2343         segment.base = gst_segment_to_running_time (&demux->segment,
2344             GST_FORMAT_TIME, demux->segment.position);
2345       }
2346
2347       gst_segment_copy_into (&segment, &demux->segment);
2348       GST_DEBUG_OBJECT (demux, "Pushing newseg %" GST_SEGMENT_FORMAT, &segment);
2349
2350       /* map segment to internal qt segments and push on each stream */
2351       if (demux->n_streams) {
2352         if (demux->fragmented) {
2353           GstEvent *segment_event = gst_event_new_segment (&segment);
2354
2355           gst_event_replace (&demux->pending_newsegment, NULL);
2356           gst_event_set_seqnum (segment_event, demux->segment_seqnum);
2357           gst_qtdemux_push_event (demux, segment_event);
2358         } else {
2359           gst_event_replace (&demux->pending_newsegment, NULL);
2360           gst_qtdemux_map_and_push_segments (demux, &segment);
2361         }
2362       }
2363
2364       /* clear leftover in current segment, if any */
2365       gst_adapter_clear (demux->adapter);
2366
2367       /* set up streaming thread */
2368       demux->offset = offset;
2369       if (demux->upstream_format_is_time) {
2370         GST_DEBUG_OBJECT (demux, "Upstream is driving in time format, "
2371             "set values to restart reading from a new atom");
2372         demux->neededbytes = 16;
2373         demux->todrop = 0;
2374       } else {
2375         gst_qtdemux_find_sample (demux, offset, TRUE, TRUE, &stream, &idx,
2376             NULL);
2377         if (stream) {
2378           demux->todrop = stream->samples[idx].offset - offset;
2379           demux->neededbytes = demux->todrop + stream->samples[idx].size;
2380         } else {
2381           /* set up for EOS */
2382           demux->neededbytes = -1;
2383           demux->todrop = 0;
2384         }
2385       }
2386     exit:
2387       gst_event_unref (event);
2388       res = TRUE;
2389       goto drop;
2390     }
2391     case GST_EVENT_FLUSH_START:
2392     {
2393       if (gst_event_get_seqnum (event) == demux->offset_seek_seqnum) {
2394         gst_event_unref (event);
2395         goto drop;
2396       }
2397       break;
2398     }
2399     case GST_EVENT_FLUSH_STOP:
2400     {
2401       guint64 dur;
2402
2403       dur = demux->segment.duration;
2404       gst_qtdemux_reset (demux, FALSE);
2405       demux->segment.duration = dur;
2406
2407       if (gst_event_get_seqnum (event) == demux->offset_seek_seqnum) {
2408         gst_event_unref (event);
2409         goto drop;
2410       }
2411       break;
2412     }
2413     case GST_EVENT_EOS:
2414       /* If we are in push mode, and get an EOS before we've seen any streams,
2415        * then error out - we have nowhere to send the EOS */
2416       if (!demux->pullbased) {
2417         GList *iter;
2418         gboolean has_valid_stream = FALSE;
2419         for (iter = demux->active_streams; iter; iter = g_list_next (iter)) {
2420           if (QTDEMUX_STREAM (iter->data)->pad != NULL) {
2421             has_valid_stream = TRUE;
2422             break;
2423           }
2424         }
2425         if (!has_valid_stream)
2426           gst_qtdemux_post_no_playable_stream_error (demux);
2427         else {
2428           GST_DEBUG_OBJECT (demux, "Data still available after EOS: %u",
2429               (guint) gst_adapter_available (demux->adapter));
2430           if (gst_qtdemux_process_adapter (demux, TRUE) != GST_FLOW_OK) {
2431             res = FALSE;
2432           }
2433         }
2434       }
2435       break;
2436     case GST_EVENT_CAPS:{
2437       GstCaps *caps = NULL;
2438
2439       gst_event_parse_caps (event, &caps);
2440       gst_qtdemux_setcaps (demux, caps);
2441       res = TRUE;
2442       gst_event_unref (event);
2443       goto drop;
2444     }
2445     case GST_EVENT_PROTECTION:
2446     {
2447       const gchar *system_id = NULL;
2448
2449       gst_event_parse_protection (event, &system_id, NULL, NULL);
2450       GST_DEBUG_OBJECT (demux, "Received protection event for system ID %s",
2451           system_id);
2452       gst_qtdemux_append_protection_system_id (demux, system_id);
2453       /* save the event for later, for source pads that have not been created */
2454       g_queue_push_tail (&demux->protection_event_queue, gst_event_ref (event));
2455       /* send it to all pads that already exist */
2456       gst_qtdemux_push_event (demux, event);
2457       res = TRUE;
2458       goto drop;
2459     }
2460     case GST_EVENT_STREAM_START:
2461     {
2462       res = TRUE;
2463       gst_event_unref (event);
2464       goto drop;
2465     }
2466     default:
2467       break;
2468   }
2469
2470   res = gst_pad_event_default (demux->sinkpad, parent, event) & res;
2471
2472 drop:
2473   return res;
2474 }
2475
2476 #if 0
2477 static void
2478 gst_qtdemux_set_index (GstElement * element, GstIndex * index)
2479 {
2480   GstQTDemux *demux = GST_QTDEMUX (element);
2481
2482   GST_OBJECT_LOCK (demux);
2483   if (demux->element_index)
2484     gst_object_unref (demux->element_index);
2485   if (index) {
2486     demux->element_index = gst_object_ref (index);
2487   } else {
2488     demux->element_index = NULL;
2489   }
2490   GST_OBJECT_UNLOCK (demux);
2491   /* object lock might be taken again */
2492   if (index)
2493     gst_index_get_writer_id (index, GST_OBJECT (element), &demux->index_id);
2494   GST_DEBUG_OBJECT (demux, "Set index %" GST_PTR_FORMAT "for writer id %d",
2495       demux->element_index, demux->index_id);
2496 }
2497
2498 static GstIndex *
2499 gst_qtdemux_get_index (GstElement * element)
2500 {
2501   GstIndex *result = NULL;
2502   GstQTDemux *demux = GST_QTDEMUX (element);
2503
2504   GST_OBJECT_LOCK (demux);
2505   if (demux->element_index)
2506     result = gst_object_ref (demux->element_index);
2507   GST_OBJECT_UNLOCK (demux);
2508
2509   GST_DEBUG_OBJECT (demux, "Returning index %" GST_PTR_FORMAT, result);
2510
2511   return result;
2512 }
2513 #endif
2514
2515 static void
2516 gst_qtdemux_stbl_free (QtDemuxStream * stream)
2517 {
2518   g_free ((gpointer) stream->stco.data);
2519   stream->stco.data = NULL;
2520   g_free ((gpointer) stream->stsz.data);
2521   stream->stsz.data = NULL;
2522   g_free ((gpointer) stream->stsc.data);
2523   stream->stsc.data = NULL;
2524   g_free ((gpointer) stream->stts.data);
2525   stream->stts.data = NULL;
2526   g_free ((gpointer) stream->stss.data);
2527   stream->stss.data = NULL;
2528   g_free ((gpointer) stream->stps.data);
2529   stream->stps.data = NULL;
2530   g_free ((gpointer) stream->ctts.data);
2531   stream->ctts.data = NULL;
2532 }
2533
2534 static void
2535 gst_qtdemux_stream_flush_segments_data (QtDemuxStream * stream)
2536 {
2537   g_free (stream->segments);
2538   stream->segments = NULL;
2539   stream->segment_index = -1;
2540   stream->accumulated_base = 0;
2541 }
2542
2543 static void
2544 gst_qtdemux_stream_flush_samples_data (QtDemuxStream * stream)
2545 {
2546   g_free (stream->samples);
2547   stream->samples = NULL;
2548   gst_qtdemux_stbl_free (stream);
2549
2550   /* fragments */
2551   g_free (stream->ra_entries);
2552   stream->ra_entries = NULL;
2553   stream->n_ra_entries = 0;
2554
2555   stream->sample_index = -1;
2556   stream->stbl_index = -1;
2557   stream->n_samples = 0;
2558   stream->time_position = 0;
2559
2560   stream->n_samples_moof = 0;
2561   stream->duration_moof = 0;
2562   stream->duration_last_moof = 0;
2563 }
2564
2565 static void
2566 gst_qtdemux_stream_clear (QtDemuxStream * stream)
2567 {
2568   gint i;
2569   if (stream->allocator)
2570     gst_object_unref (stream->allocator);
2571   while (stream->buffers) {
2572     gst_buffer_unref (GST_BUFFER_CAST (stream->buffers->data));
2573     stream->buffers = g_slist_delete_link (stream->buffers, stream->buffers);
2574   }
2575   for (i = 0; i < stream->stsd_entries_length; i++) {
2576     QtDemuxStreamStsdEntry *entry = &stream->stsd_entries[i];
2577     if (entry->rgb8_palette) {
2578       gst_memory_unref (entry->rgb8_palette);
2579       entry->rgb8_palette = NULL;
2580     }
2581     entry->sparse = FALSE;
2582   }
2583
2584   gst_tag_list_unref (stream->stream_tags);
2585   stream->stream_tags = gst_tag_list_new_empty ();
2586   gst_tag_list_set_scope (stream->stream_tags, GST_TAG_SCOPE_STREAM);
2587   g_free (stream->redirect_uri);
2588   stream->redirect_uri = NULL;
2589   stream->sent_eos = FALSE;
2590   stream->protected = FALSE;
2591   if (stream->protection_scheme_info) {
2592     if (stream->protection_scheme_type == FOURCC_cenc) {
2593       QtDemuxCencSampleSetInfo *info =
2594           (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
2595       if (info->default_properties)
2596         gst_structure_free (info->default_properties);
2597       if (info->crypto_info)
2598         g_ptr_array_free (info->crypto_info, TRUE);
2599     }
2600     g_free (stream->protection_scheme_info);
2601     stream->protection_scheme_info = NULL;
2602   }
2603   stream->protection_scheme_type = 0;
2604   stream->protection_scheme_version = 0;
2605   g_queue_foreach (&stream->protection_scheme_event_queue,
2606       (GFunc) gst_event_unref, NULL);
2607   g_queue_clear (&stream->protection_scheme_event_queue);
2608   gst_qtdemux_stream_flush_segments_data (stream);
2609   gst_qtdemux_stream_flush_samples_data (stream);
2610 }
2611
2612 static void
2613 gst_qtdemux_stream_reset (QtDemuxStream * stream)
2614 {
2615   gint i;
2616   gst_qtdemux_stream_clear (stream);
2617   for (i = 0; i < stream->stsd_entries_length; i++) {
2618     QtDemuxStreamStsdEntry *entry = &stream->stsd_entries[i];
2619     if (entry->caps) {
2620       gst_caps_unref (entry->caps);
2621       entry->caps = NULL;
2622     }
2623   }
2624   g_free (stream->stsd_entries);
2625   stream->stsd_entries = NULL;
2626   stream->stsd_entries_length = 0;
2627 }
2628
2629
2630 static void
2631 gst_qtdemux_stream_free (QtDemuxStream * stream)
2632 {
2633   gst_qtdemux_stream_reset (stream);
2634   gst_tag_list_unref (stream->stream_tags);
2635   if (stream->pad) {
2636     GstQTDemux *demux = stream->demux;
2637     gst_element_remove_pad (GST_ELEMENT_CAST (demux), stream->pad);
2638     gst_flow_combiner_remove_pad (demux->flowcombiner, stream->pad);
2639   }
2640   g_free (stream->stream_id);
2641   g_free (stream);
2642 }
2643
2644 static void
2645 gst_qtdemux_remove_stream (GstQTDemux * qtdemux, QtDemuxStream * stream)
2646 {
2647   qtdemux->active_streams = g_list_remove (qtdemux->active_streams, stream);
2648   gst_qtdemux_stream_free (stream);
2649   qtdemux->n_streams--;
2650 }
2651
2652 static GstStateChangeReturn
2653 gst_qtdemux_change_state (GstElement * element, GstStateChange transition)
2654 {
2655   GstQTDemux *qtdemux = GST_QTDEMUX (element);
2656   GstStateChangeReturn result = GST_STATE_CHANGE_FAILURE;
2657
2658   switch (transition) {
2659     case GST_STATE_CHANGE_PAUSED_TO_READY:
2660       break;
2661     default:
2662       break;
2663   }
2664
2665   result = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
2666
2667   switch (transition) {
2668     case GST_STATE_CHANGE_PAUSED_TO_READY:{
2669       gst_qtdemux_reset (qtdemux, TRUE);
2670       break;
2671     }
2672     default:
2673       break;
2674   }
2675
2676   return result;
2677 }
2678
2679 static void
2680 qtdemux_parse_ftyp (GstQTDemux * qtdemux, const guint8 * buffer, gint length)
2681 {
2682   /* counts as header data */
2683   qtdemux->header_size += length;
2684
2685   /* only consider at least a sufficiently complete ftyp atom */
2686   if (length >= 20) {
2687     GstBuffer *buf;
2688
2689     qtdemux->major_brand = QT_FOURCC (buffer + 8);
2690     GST_DEBUG_OBJECT (qtdemux, "major brand: %" GST_FOURCC_FORMAT,
2691         GST_FOURCC_ARGS (qtdemux->major_brand));
2692     if (qtdemux->comp_brands)
2693       gst_buffer_unref (qtdemux->comp_brands);
2694     buf = qtdemux->comp_brands = gst_buffer_new_and_alloc (length - 16);
2695     gst_buffer_fill (buf, 0, buffer + 16, length - 16);
2696   }
2697 }
2698
2699 static void
2700 qtdemux_handle_xmp_taglist (GstQTDemux * qtdemux, GstTagList * taglist,
2701     GstTagList * xmptaglist)
2702 {
2703   /* Strip out bogus fields */
2704   if (xmptaglist) {
2705     if (gst_tag_list_get_scope (taglist) == GST_TAG_SCOPE_GLOBAL) {
2706       gst_tag_list_remove_tag (xmptaglist, GST_TAG_VIDEO_CODEC);
2707       gst_tag_list_remove_tag (xmptaglist, GST_TAG_AUDIO_CODEC);
2708     } else {
2709       gst_tag_list_remove_tag (xmptaglist, GST_TAG_CONTAINER_FORMAT);
2710     }
2711
2712     GST_DEBUG_OBJECT (qtdemux, "Found XMP tags %" GST_PTR_FORMAT, xmptaglist);
2713
2714     /* prioritize native tags using _KEEP mode */
2715     gst_tag_list_insert (taglist, xmptaglist, GST_TAG_MERGE_KEEP);
2716     gst_tag_list_unref (xmptaglist);
2717   }
2718 }
2719
2720 static void
2721 qtdemux_parse_piff (GstQTDemux * qtdemux, const guint8 * buffer, gint length,
2722     guint offset)
2723 {
2724   GstByteReader br;
2725   guint8 version;
2726   guint32 flags = 0;
2727   guint i;
2728   guint8 iv_size = 8;
2729   QtDemuxStream *stream;
2730   GstStructure *structure;
2731   QtDemuxCencSampleSetInfo *ss_info = NULL;
2732   const gchar *system_id;
2733   gboolean uses_sub_sample_encryption = FALSE;
2734   guint32 sample_count;
2735
2736   stream = QTDEMUX_FIRST_STREAM (qtdemux);
2737   if (!stream)
2738     return;
2739
2740   structure = gst_caps_get_structure (CUR_STREAM (stream)->caps, 0);
2741   if (!gst_structure_has_name (structure, "application/x-cenc")) {
2742     GST_WARNING_OBJECT (qtdemux,
2743         "Attempting PIFF box parsing on an unencrypted stream.");
2744     return;
2745   }
2746
2747   gst_structure_get (structure, GST_PROTECTION_SYSTEM_ID_CAPS_FIELD,
2748       G_TYPE_STRING, &system_id, NULL);
2749   gst_qtdemux_append_protection_system_id (qtdemux, system_id);
2750
2751   stream->protected = TRUE;
2752   stream->protection_scheme_type = FOURCC_cenc;
2753
2754   if (!stream->protection_scheme_info)
2755     stream->protection_scheme_info = g_new0 (QtDemuxCencSampleSetInfo, 1);
2756
2757   ss_info = (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
2758
2759   if (ss_info->default_properties)
2760     gst_structure_free (ss_info->default_properties);
2761
2762   ss_info->default_properties =
2763       gst_structure_new ("application/x-cenc",
2764       "iv_size", G_TYPE_UINT, iv_size, "encrypted", G_TYPE_BOOLEAN, TRUE, NULL);
2765
2766   if (ss_info->crypto_info) {
2767     GST_LOG_OBJECT (qtdemux, "unreffing existing crypto_info");
2768     g_ptr_array_free (ss_info->crypto_info, TRUE);
2769     ss_info->crypto_info = NULL;
2770   }
2771
2772   /* skip UUID */
2773   gst_byte_reader_init (&br, buffer + offset + 16, length - offset - 16);
2774
2775   if (!gst_byte_reader_get_uint8 (&br, &version)) {
2776     GST_ERROR_OBJECT (qtdemux, "Error getting box's version field");
2777     return;
2778   }
2779
2780   if (!gst_byte_reader_get_uint24_be (&br, &flags)) {
2781     GST_ERROR_OBJECT (qtdemux, "Error getting box's flags field");
2782     return;
2783   }
2784
2785   if ((flags & 0x000001)) {
2786     guint32 algorithm_id = 0;
2787     const guint8 *kid;
2788     GstBuffer *kid_buf;
2789     gboolean is_encrypted = TRUE;
2790
2791     if (!gst_byte_reader_get_uint24_le (&br, &algorithm_id)) {
2792       GST_ERROR_OBJECT (qtdemux, "Error getting box's algorithm ID field");
2793       return;
2794     }
2795
2796     algorithm_id >>= 8;
2797     if (algorithm_id == 0) {
2798       is_encrypted = FALSE;
2799     } else if (algorithm_id == 1) {
2800       /* FIXME: maybe store this in properties? */
2801       GST_DEBUG_OBJECT (qtdemux, "AES 128-bits CTR encrypted stream");
2802     } else if (algorithm_id == 2) {
2803       /* FIXME: maybe store this in properties? */
2804       GST_DEBUG_OBJECT (qtdemux, "AES 128-bits CBC encrypted stream");
2805     }
2806
2807     if (!gst_byte_reader_get_uint8 (&br, &iv_size))
2808       return;
2809
2810     if (!gst_byte_reader_get_data (&br, 16, &kid))
2811       return;
2812
2813     kid_buf = gst_buffer_new_allocate (NULL, 16, NULL);
2814     gst_buffer_fill (kid_buf, 0, kid, 16);
2815     if (ss_info->default_properties)
2816       gst_structure_free (ss_info->default_properties);
2817     ss_info->default_properties =
2818         gst_structure_new ("application/x-cenc",
2819         "iv_size", G_TYPE_UINT, iv_size,
2820         "encrypted", G_TYPE_BOOLEAN, is_encrypted,
2821         "kid", GST_TYPE_BUFFER, kid_buf, NULL);
2822     GST_DEBUG_OBJECT (qtdemux, "default sample properties: "
2823         "is_encrypted=%u, iv_size=%u", is_encrypted, iv_size);
2824     gst_buffer_unref (kid_buf);
2825   } else if ((flags & 0x000002)) {
2826     uses_sub_sample_encryption = TRUE;
2827   }
2828
2829   if (!gst_byte_reader_get_uint32_be (&br, &sample_count)) {
2830     GST_ERROR_OBJECT (qtdemux, "Error getting box's sample count field");
2831     return;
2832   }
2833
2834   ss_info->crypto_info =
2835       g_ptr_array_new_full (sample_count,
2836       (GDestroyNotify) qtdemux_gst_structure_free);
2837
2838   for (i = 0; i < sample_count; ++i) {
2839     GstStructure *properties;
2840     guint8 *data;
2841     GstBuffer *buf;
2842
2843     properties = qtdemux_get_cenc_sample_properties (qtdemux, stream, i);
2844     if (properties == NULL) {
2845       GST_ERROR_OBJECT (qtdemux, "failed to get properties for sample %u", i);
2846       qtdemux->cenc_aux_sample_count = i;
2847       return;
2848     }
2849
2850     if (!gst_byte_reader_dup_data (&br, iv_size, &data)) {
2851       GST_ERROR_OBJECT (qtdemux, "IV data not present for sample %u", i);
2852       gst_structure_free (properties);
2853       qtdemux->cenc_aux_sample_count = i;
2854       return;
2855     }
2856     buf = gst_buffer_new_wrapped (data, iv_size);
2857     gst_structure_set (properties, "iv", GST_TYPE_BUFFER, buf, NULL);
2858     gst_buffer_unref (buf);
2859
2860     if (uses_sub_sample_encryption) {
2861       guint16 n_subsamples;
2862
2863       if (!gst_byte_reader_get_uint16_be (&br, &n_subsamples)
2864           || n_subsamples == 0) {
2865         GST_ERROR_OBJECT (qtdemux,
2866             "failed to get subsample count for sample %u", i);
2867         gst_structure_free (properties);
2868         qtdemux->cenc_aux_sample_count = i;
2869         return;
2870       }
2871       GST_LOG_OBJECT (qtdemux, "subsample count: %u", n_subsamples);
2872       if (!gst_byte_reader_dup_data (&br, n_subsamples * 6, &data)) {
2873         GST_ERROR_OBJECT (qtdemux, "failed to get subsample data for sample %u",
2874             i);
2875         gst_structure_free (properties);
2876         qtdemux->cenc_aux_sample_count = i;
2877         return;
2878       }
2879       buf = gst_buffer_new_wrapped (data, n_subsamples * 6);
2880       gst_structure_set (properties,
2881           "subsample_count", G_TYPE_UINT, n_subsamples,
2882           "subsamples", GST_TYPE_BUFFER, buf, NULL);
2883       gst_buffer_unref (buf);
2884     } else {
2885       gst_structure_set (properties, "subsample_count", G_TYPE_UINT, 0, NULL);
2886     }
2887
2888     g_ptr_array_add (ss_info->crypto_info, properties);
2889   }
2890
2891   qtdemux->cenc_aux_sample_count = sample_count;
2892 }
2893
2894 static void
2895 qtdemux_parse_uuid (GstQTDemux * qtdemux, const guint8 * buffer, gint length)
2896 {
2897   static const guint8 xmp_uuid[] = { 0xBE, 0x7A, 0xCF, 0xCB,
2898     0x97, 0xA9, 0x42, 0xE8,
2899     0x9C, 0x71, 0x99, 0x94,
2900     0x91, 0xE3, 0xAF, 0xAC
2901   };
2902   static const guint8 playready_uuid[] = {
2903     0xd0, 0x8a, 0x4f, 0x18, 0x10, 0xf3, 0x4a, 0x82,
2904     0xb6, 0xc8, 0x32, 0xd8, 0xab, 0xa1, 0x83, 0xd3
2905   };
2906
2907   static const guint8 piff_sample_encryption_uuid[] = {
2908     0xa2, 0x39, 0x4f, 0x52, 0x5a, 0x9b, 0x4f, 0x14,
2909     0xa2, 0x44, 0x6c, 0x42, 0x7c, 0x64, 0x8d, 0xf4
2910   };
2911
2912   guint offset;
2913
2914   /* counts as header data */
2915   qtdemux->header_size += length;
2916
2917   offset = (QT_UINT32 (buffer) == 0) ? 16 : 8;
2918
2919   if (length <= offset + 16) {
2920     GST_DEBUG_OBJECT (qtdemux, "uuid atom is too short, skipping");
2921     return;
2922   }
2923
2924   if (memcmp (buffer + offset, xmp_uuid, 16) == 0) {
2925     GstBuffer *buf;
2926     GstTagList *taglist;
2927
2928     buf = _gst_buffer_new_wrapped ((guint8 *) buffer + offset + 16,
2929         length - offset - 16, NULL);
2930     taglist = gst_tag_list_from_xmp_buffer (buf);
2931     gst_buffer_unref (buf);
2932
2933     /* make sure we have a usable taglist */
2934     qtdemux->tag_list = gst_tag_list_make_writable (qtdemux->tag_list);
2935
2936     qtdemux_handle_xmp_taglist (qtdemux, qtdemux->tag_list, taglist);
2937
2938   } else if (memcmp (buffer + offset, playready_uuid, 16) == 0) {
2939     int len;
2940     const gunichar2 *s_utf16;
2941     char *contents;
2942
2943     len = GST_READ_UINT16_LE (buffer + offset + 0x30);
2944     s_utf16 = (const gunichar2 *) (buffer + offset + 0x32);
2945     contents = g_utf16_to_utf8 (s_utf16, len / 2, NULL, NULL, NULL);
2946     GST_ERROR_OBJECT (qtdemux, "contents: %s", contents);
2947
2948     g_free (contents);
2949
2950     GST_ELEMENT_ERROR (qtdemux, STREAM, DECRYPT,
2951         (_("Cannot play stream because it is encrypted with PlayReady DRM.")),
2952         (NULL));
2953   } else if (memcmp (buffer + offset, piff_sample_encryption_uuid, 16) == 0) {
2954     qtdemux_parse_piff (qtdemux, buffer, length, offset);
2955   } else {
2956     GST_DEBUG_OBJECT (qtdemux, "Ignoring unknown uuid: %08x-%08x-%08x-%08x",
2957         GST_READ_UINT32_LE (buffer + offset),
2958         GST_READ_UINT32_LE (buffer + offset + 4),
2959         GST_READ_UINT32_LE (buffer + offset + 8),
2960         GST_READ_UINT32_LE (buffer + offset + 12));
2961   }
2962 }
2963
2964 static void
2965 qtdemux_parse_sidx (GstQTDemux * qtdemux, const guint8 * buffer, gint length)
2966 {
2967   GstSidxParser sidx_parser;
2968   GstIsoffParserResult res;
2969   guint consumed;
2970
2971   gst_isoff_qt_sidx_parser_init (&sidx_parser);
2972
2973   res =
2974       gst_isoff_qt_sidx_parser_add_data (&sidx_parser, buffer, length,
2975       &consumed);
2976   GST_DEBUG_OBJECT (qtdemux, "sidx parse result: %d", res);
2977   if (res == GST_ISOFF_QT_PARSER_DONE) {
2978     check_update_duration (qtdemux, sidx_parser.cumulative_pts);
2979   }
2980   gst_isoff_qt_sidx_parser_clear (&sidx_parser);
2981 }
2982
2983 /* caller verifies at least 8 bytes in buf */
2984 static void
2985 extract_initial_length_and_fourcc (const guint8 * data, guint size,
2986     guint64 * plength, guint32 * pfourcc)
2987 {
2988   guint64 length;
2989   guint32 fourcc;
2990
2991   length = QT_UINT32 (data);
2992   GST_DEBUG ("length 0x%08" G_GINT64_MODIFIER "x", length);
2993   fourcc = QT_FOURCC (data + 4);
2994   GST_DEBUG ("atom type %" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (fourcc));
2995
2996   if (length == 0) {
2997     length = G_MAXUINT64;
2998   } else if (length == 1 && size >= 16) {
2999     /* this means we have an extended size, which is the 64 bit value of
3000      * the next 8 bytes */
3001     length = QT_UINT64 (data + 8);
3002     GST_DEBUG ("length 0x%08" G_GINT64_MODIFIER "x", length);
3003   }
3004
3005   if (plength)
3006     *plength = length;
3007   if (pfourcc)
3008     *pfourcc = fourcc;
3009 }
3010
3011 static gboolean
3012 qtdemux_parse_mehd (GstQTDemux * qtdemux, GstByteReader * br)
3013 {
3014   guint32 version = 0;
3015   GstClockTime duration = 0;
3016
3017   if (!gst_byte_reader_get_uint32_be (br, &version))
3018     goto failed;
3019
3020   version >>= 24;
3021   if (version == 1) {
3022     if (!gst_byte_reader_get_uint64_be (br, &duration))
3023       goto failed;
3024   } else {
3025     guint32 dur = 0;
3026
3027     if (!gst_byte_reader_get_uint32_be (br, &dur))
3028       goto failed;
3029     duration = dur;
3030   }
3031
3032   GST_INFO_OBJECT (qtdemux, "mehd duration: %" G_GUINT64_FORMAT, duration);
3033   qtdemux->duration = duration;
3034
3035   return TRUE;
3036
3037 failed:
3038   {
3039     GST_DEBUG_OBJECT (qtdemux, "parsing mehd failed");
3040     return FALSE;
3041   }
3042 }
3043
3044 static gboolean
3045 qtdemux_parse_trex (GstQTDemux * qtdemux, QtDemuxStream * stream,
3046     guint32 * ds_duration, guint32 * ds_size, guint32 * ds_flags)
3047 {
3048   if (!stream->parsed_trex && qtdemux->moov_node) {
3049     GNode *mvex, *trex;
3050     GstByteReader trex_data;
3051
3052     mvex = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_mvex);
3053     if (mvex) {
3054       trex = qtdemux_tree_get_child_by_type_full (mvex, FOURCC_trex,
3055           &trex_data);
3056       while (trex) {
3057         guint32 id = 0, sdi = 0, dur = 0, size = 0, flags = 0;
3058
3059         /* skip version/flags */
3060         if (!gst_byte_reader_skip (&trex_data, 4))
3061           goto next;
3062         if (!gst_byte_reader_get_uint32_be (&trex_data, &id))
3063           goto next;
3064         if (id != stream->track_id)
3065           goto next;
3066         if (!gst_byte_reader_get_uint32_be (&trex_data, &sdi))
3067           goto next;
3068         if (!gst_byte_reader_get_uint32_be (&trex_data, &dur))
3069           goto next;
3070         if (!gst_byte_reader_get_uint32_be (&trex_data, &size))
3071           goto next;
3072         if (!gst_byte_reader_get_uint32_be (&trex_data, &flags))
3073           goto next;
3074
3075         GST_DEBUG_OBJECT (qtdemux, "fragment defaults for stream %d; "
3076             "duration %d,  size %d, flags 0x%x", stream->track_id,
3077             dur, size, flags);
3078
3079         stream->parsed_trex = TRUE;
3080         stream->def_sample_description_index = sdi;
3081         stream->def_sample_duration = dur;
3082         stream->def_sample_size = size;
3083         stream->def_sample_flags = flags;
3084
3085       next:
3086         /* iterate all siblings */
3087         trex = qtdemux_tree_get_sibling_by_type_full (trex, FOURCC_trex,
3088             &trex_data);
3089       }
3090     }
3091   }
3092
3093   *ds_duration = stream->def_sample_duration;
3094   *ds_size = stream->def_sample_size;
3095   *ds_flags = stream->def_sample_flags;
3096
3097   /* even then, above values are better than random ... */
3098   if (G_UNLIKELY (!stream->parsed_trex)) {
3099     GST_WARNING_OBJECT (qtdemux,
3100         "failed to find fragment defaults for stream %d", stream->track_id);
3101     return FALSE;
3102   }
3103
3104   return TRUE;
3105 }
3106
3107 /* This method should be called whenever a more accurate duration might
3108  * have been found. It will update all relevant variables if/where needed
3109  */
3110 static void
3111 check_update_duration (GstQTDemux * qtdemux, GstClockTime duration)
3112 {
3113   guint i;
3114   guint64 movdur;
3115   GstClockTime prevdur;
3116   GList *iter;
3117
3118   movdur = GSTTIME_TO_QTTIME (qtdemux, duration);
3119
3120   if (movdur > qtdemux->duration) {
3121     prevdur = QTTIME_TO_GSTTIME (qtdemux, qtdemux->duration);
3122     GST_DEBUG_OBJECT (qtdemux,
3123         "Updating total duration to %" GST_TIME_FORMAT " was %" GST_TIME_FORMAT,
3124         GST_TIME_ARGS (duration), GST_TIME_ARGS (prevdur));
3125     qtdemux->duration = movdur;
3126     GST_DEBUG_OBJECT (qtdemux,
3127         "qtdemux->segment.duration: %" GST_TIME_FORMAT " .stop: %"
3128         GST_TIME_FORMAT, GST_TIME_ARGS (qtdemux->segment.duration),
3129         GST_TIME_ARGS (qtdemux->segment.stop));
3130     if (qtdemux->segment.duration == prevdur) {
3131       /* If the current segment has duration/stop identical to previous duration
3132        * update them also (because they were set at that point in time with
3133        * the wrong duration */
3134       /* We convert the value *from* the timescale version to avoid rounding errors */
3135       GstClockTime fixeddur = QTTIME_TO_GSTTIME (qtdemux, movdur);
3136       GST_DEBUG_OBJECT (qtdemux, "Updated segment.duration and segment.stop");
3137       qtdemux->segment.duration = fixeddur;
3138       qtdemux->segment.stop = fixeddur;
3139     }
3140   }
3141   for (iter = qtdemux->active_streams, i = 0; iter;
3142       iter = g_list_next (iter), i++) {
3143     QtDemuxStream *stream = QTDEMUX_STREAM (iter->data);
3144
3145     movdur = GSTTIME_TO_QTSTREAMTIME (stream, duration);
3146     if (movdur > stream->duration) {
3147       GST_DEBUG_OBJECT (qtdemux,
3148           "Updating stream #%d duration to %" GST_TIME_FORMAT, i,
3149           GST_TIME_ARGS (duration));
3150       stream->duration = movdur;
3151       /* internal duration tracking state has been updated above, so */
3152       /* preserve an open-ended dummy segment rather than repeatedly updating
3153        * it and spamming downstream accordingly with segment events */
3154       if (stream->dummy_segment &&
3155           GST_CLOCK_TIME_IS_VALID (stream->segments[0].duration)) {
3156         /* Update all dummy values to new duration */
3157         stream->segments[0].stop_time = duration;
3158         stream->segments[0].duration = duration;
3159         stream->segments[0].media_stop = duration;
3160
3161         /* let downstream know we possibly have a new stop time */
3162         if (stream->segment_index != -1) {
3163           GstClockTime pos;
3164
3165           if (qtdemux->segment.rate >= 0) {
3166             pos = stream->segment.start;
3167           } else {
3168             pos = stream->segment.stop;
3169           }
3170
3171           gst_qtdemux_stream_update_segment (qtdemux, stream,
3172               stream->segment_index, pos, NULL, NULL);
3173         }
3174       }
3175     }
3176   }
3177 }
3178
3179 static gboolean
3180 qtdemux_parse_trun (GstQTDemux * qtdemux, GstByteReader * trun,
3181     QtDemuxStream * stream, guint32 d_sample_duration, guint32 d_sample_size,
3182     guint32 d_sample_flags, gint64 moof_offset, gint64 moof_length,
3183     gint64 * base_offset, gint64 * running_offset, gint64 decode_ts,
3184     gboolean has_tfdt)
3185 {
3186   GstClockTime gst_ts = GST_CLOCK_TIME_NONE;
3187   guint64 timestamp;
3188   gint32 data_offset = 0;
3189   guint32 flags = 0, first_flags = 0, samples_count = 0;
3190   gint i;
3191   guint8 *data;
3192   guint entry_size, dur_offset, size_offset, flags_offset = 0, ct_offset = 0;
3193   QtDemuxSample *sample;
3194   gboolean ismv = FALSE;
3195   gint64 initial_offset;
3196
3197   GST_LOG_OBJECT (qtdemux, "parsing trun track-id %d; "
3198       "default dur %d, size %d, flags 0x%x, base offset %" G_GINT64_FORMAT ", "
3199       "decode ts %" G_GINT64_FORMAT, stream->track_id, d_sample_duration,
3200       d_sample_size, d_sample_flags, *base_offset, decode_ts);
3201
3202   if (stream->pending_seek && moof_offset < stream->pending_seek->moof_offset) {
3203     GST_INFO_OBJECT (stream->pad, "skipping trun before seek target fragment");
3204     return TRUE;
3205   }
3206
3207   /* presence of stss or not can't really tell us much,
3208    * and flags and so on tend to be marginally reliable in these files */
3209   if (stream->subtype == FOURCC_soun) {
3210     GST_DEBUG_OBJECT (qtdemux,
3211         "sound track in fragmented file; marking all keyframes");
3212     stream->all_keyframe = TRUE;
3213   }
3214
3215   if (!gst_byte_reader_skip (trun, 1) ||
3216       !gst_byte_reader_get_uint24_be (trun, &flags))
3217     goto fail;
3218
3219   if (!gst_byte_reader_get_uint32_be (trun, &samples_count))
3220     goto fail;
3221
3222   if (flags & TR_DATA_OFFSET) {
3223     /* note this is really signed */
3224     if (!gst_byte_reader_get_int32_be (trun, &data_offset))
3225       goto fail;
3226     GST_LOG_OBJECT (qtdemux, "trun data offset %d", data_offset);
3227     /* default base offset = first byte of moof */
3228     if (*base_offset == -1) {
3229       GST_LOG_OBJECT (qtdemux, "base_offset at moof");
3230       *base_offset = moof_offset;
3231     }
3232     *running_offset = *base_offset + data_offset;
3233   } else {
3234     /* if no offset at all, that would mean data starts at moof start,
3235      * which is a bit wrong and is ismv crappy way, so compensate
3236      * assuming data is in mdat following moof */
3237     if (*base_offset == -1) {
3238       *base_offset = moof_offset + moof_length + 8;
3239       GST_LOG_OBJECT (qtdemux, "base_offset assumed in mdat after moof");
3240       ismv = TRUE;
3241     }
3242     if (*running_offset == -1)
3243       *running_offset = *base_offset;
3244   }
3245
3246   GST_LOG_OBJECT (qtdemux, "running offset now %" G_GINT64_FORMAT,
3247       *running_offset);
3248   GST_LOG_OBJECT (qtdemux, "trun offset %d, flags 0x%x, entries %d",
3249       data_offset, flags, samples_count);
3250
3251   if (flags & TR_FIRST_SAMPLE_FLAGS) {
3252     if (G_UNLIKELY (flags & TR_SAMPLE_FLAGS)) {
3253       GST_DEBUG_OBJECT (qtdemux,
3254           "invalid flags; SAMPLE and FIRST_SAMPLE present, discarding latter");
3255       flags ^= TR_FIRST_SAMPLE_FLAGS;
3256     } else {
3257       if (!gst_byte_reader_get_uint32_be (trun, &first_flags))
3258         goto fail;
3259       GST_LOG_OBJECT (qtdemux, "first flags: 0x%x", first_flags);
3260     }
3261   }
3262
3263   /* FIXME ? spec says other bits should also be checked to determine
3264    * entry size (and prefix size for that matter) */
3265   entry_size = 0;
3266   dur_offset = size_offset = 0;
3267   if (flags & TR_SAMPLE_DURATION) {
3268     GST_LOG_OBJECT (qtdemux, "entry duration present");
3269     dur_offset = entry_size;
3270     entry_size += 4;
3271   }
3272   if (flags & TR_SAMPLE_SIZE) {
3273     GST_LOG_OBJECT (qtdemux, "entry size present");
3274     size_offset = entry_size;
3275     entry_size += 4;
3276   }
3277   if (flags & TR_SAMPLE_FLAGS) {
3278     GST_LOG_OBJECT (qtdemux, "entry flags present");
3279     flags_offset = entry_size;
3280     entry_size += 4;
3281   }
3282   if (flags & TR_COMPOSITION_TIME_OFFSETS) {
3283     GST_LOG_OBJECT (qtdemux, "entry ct offset present");
3284     ct_offset = entry_size;
3285     entry_size += 4;
3286   }
3287
3288   if (!qt_atom_parser_has_chunks (trun, samples_count, entry_size))
3289     goto fail;
3290   data = (guint8 *) gst_byte_reader_peek_data_unchecked (trun);
3291
3292   if (stream->n_samples + samples_count >=
3293       QTDEMUX_MAX_SAMPLE_INDEX_SIZE / sizeof (QtDemuxSample))
3294     goto index_too_big;
3295
3296   GST_DEBUG_OBJECT (qtdemux, "allocating n_samples %u * %u (%.2f MB)",
3297       stream->n_samples + samples_count, (guint) sizeof (QtDemuxSample),
3298       (stream->n_samples + samples_count) *
3299       sizeof (QtDemuxSample) / (1024.0 * 1024.0));
3300
3301   /* create a new array of samples if it's the first sample parsed */
3302   if (stream->n_samples == 0) {
3303     g_assert (stream->samples == NULL);
3304     stream->samples = g_try_new0 (QtDemuxSample, samples_count);
3305     /* or try to reallocate it with space enough to insert the new samples */
3306   } else
3307     stream->samples = g_try_renew (QtDemuxSample, stream->samples,
3308         stream->n_samples + samples_count);
3309   if (stream->samples == NULL)
3310     goto out_of_memory;
3311
3312   if (qtdemux->fragment_start != -1) {
3313     timestamp = GSTTIME_TO_QTSTREAMTIME (stream, qtdemux->fragment_start);
3314     qtdemux->fragment_start = -1;
3315   } else {
3316     if (stream->n_samples == 0) {
3317       if (decode_ts > 0) {
3318         timestamp = decode_ts;
3319       } else if (stream->pending_seek != NULL) {
3320         /* if we don't have a timestamp from a tfdt box, we'll use the one
3321          * from the mfra seek table */
3322         GST_INFO_OBJECT (stream->pad, "pending seek ts = %" GST_TIME_FORMAT,
3323             GST_TIME_ARGS (stream->pending_seek->ts));
3324
3325         /* FIXME: this is not fully correct, the timestamp refers to the random
3326          * access sample refered to in the tfra entry, which may not necessarily
3327          * be the first sample in the tfrag/trun (but hopefully/usually is) */
3328         timestamp = GSTTIME_TO_QTSTREAMTIME (stream, stream->pending_seek->ts);
3329       } else {
3330         timestamp = 0;
3331       }
3332
3333       gst_ts = QTSTREAMTIME_TO_GSTTIME (stream, timestamp);
3334       GST_INFO_OBJECT (stream->pad, "first sample ts %" GST_TIME_FORMAT,
3335           GST_TIME_ARGS (gst_ts));
3336     } else {
3337       /* subsequent fragments extend stream */
3338       timestamp =
3339           stream->samples[stream->n_samples - 1].timestamp +
3340           stream->samples[stream->n_samples - 1].duration;
3341
3342       /* If this is a GST_FORMAT_BYTES stream and there's a significant
3343        * difference (1 sec.) between decode_ts and timestamp, prefer the
3344        * former */
3345       if (has_tfdt && !qtdemux->upstream_format_is_time
3346           && ABSDIFF (decode_ts, timestamp) >
3347           MAX (stream->duration_last_moof / 2,
3348               GSTTIME_TO_QTSTREAMTIME (stream, GST_SECOND))) {
3349         GST_INFO_OBJECT (qtdemux,
3350             "decode_ts (%" GST_TIME_FORMAT ") and timestamp (%" GST_TIME_FORMAT
3351             ") are significantly different (more than %" GST_TIME_FORMAT
3352             "), using decode_ts",
3353             GST_TIME_ARGS (QTSTREAMTIME_TO_GSTTIME (stream, decode_ts)),
3354             GST_TIME_ARGS (QTSTREAMTIME_TO_GSTTIME (stream, timestamp)),
3355             GST_TIME_ARGS (QTSTREAMTIME_TO_GSTTIME (stream,
3356                     MAX (stream->duration_last_moof / 2,
3357                         GSTTIME_TO_QTSTREAMTIME (stream, GST_SECOND)))));
3358         timestamp = decode_ts;
3359       }
3360
3361       gst_ts = QTSTREAMTIME_TO_GSTTIME (stream, timestamp);
3362       GST_INFO_OBJECT (qtdemux, "first sample ts %" GST_TIME_FORMAT
3363           " (extends previous samples)", GST_TIME_ARGS (gst_ts));
3364     }
3365   }
3366
3367   initial_offset = *running_offset;
3368
3369   sample = stream->samples + stream->n_samples;
3370   for (i = 0; i < samples_count; i++) {
3371     guint32 dur, size, sflags, ct;
3372
3373     /* first read sample data */
3374     if (flags & TR_SAMPLE_DURATION) {
3375       dur = QT_UINT32 (data + dur_offset);
3376     } else {
3377       dur = d_sample_duration;
3378     }
3379     if (flags & TR_SAMPLE_SIZE) {
3380       size = QT_UINT32 (data + size_offset);
3381     } else {
3382       size = d_sample_size;
3383     }
3384     if (flags & TR_FIRST_SAMPLE_FLAGS) {
3385       if (i == 0) {
3386         sflags = first_flags;
3387       } else {
3388         sflags = d_sample_flags;
3389       }
3390     } else if (flags & TR_SAMPLE_FLAGS) {
3391       sflags = QT_UINT32 (data + flags_offset);
3392     } else {
3393       sflags = d_sample_flags;
3394     }
3395     if (flags & TR_COMPOSITION_TIME_OFFSETS) {
3396       ct = QT_UINT32 (data + ct_offset);
3397     } else {
3398       ct = 0;
3399     }
3400     data += entry_size;
3401
3402     /* fill the sample information */
3403     sample->offset = *running_offset;
3404     sample->pts_offset = ct;
3405     sample->size = size;
3406     sample->timestamp = timestamp;
3407     sample->duration = dur;
3408     /* sample-is-difference-sample */
3409     /* ismv seems to use 0x40 for keyframe, 0xc0 for non-keyframe,
3410      * now idea how it relates to bitfield other than massive LE/BE confusion */
3411     sample->keyframe = ismv ? ((sflags & 0xff) == 0x40) : !(sflags & 0x10000);
3412     *running_offset += size;
3413     timestamp += dur;
3414     stream->duration_moof += dur;
3415     sample++;
3416   }
3417
3418   /* Update total duration if needed */
3419   check_update_duration (qtdemux, QTSTREAMTIME_TO_GSTTIME (stream, timestamp));
3420
3421   /* Pre-emptively figure out size of mdat based on trun information.
3422    * If the [mdat] atom is effectivelly read, it will be replaced by the actual
3423    * size, else we will still be able to use this when dealing with gap'ed
3424    * input */
3425   qtdemux->mdatleft = *running_offset - initial_offset;
3426   qtdemux->mdatoffset = initial_offset;
3427   qtdemux->mdatsize = qtdemux->mdatleft;
3428
3429   stream->n_samples += samples_count;
3430   stream->n_samples_moof += samples_count;
3431
3432   if (stream->pending_seek != NULL)
3433     stream->pending_seek = NULL;
3434
3435   return TRUE;
3436
3437 fail:
3438   {
3439     GST_WARNING_OBJECT (qtdemux, "failed to parse trun");
3440     return FALSE;
3441   }
3442 out_of_memory:
3443   {
3444     GST_WARNING_OBJECT (qtdemux, "failed to allocate %d samples",
3445         stream->n_samples);
3446     return FALSE;
3447   }
3448 index_too_big:
3449   {
3450     GST_WARNING_OBJECT (qtdemux, "not allocating index of %d samples, would "
3451         "be larger than %uMB (broken file?)", stream->n_samples,
3452         QTDEMUX_MAX_SAMPLE_INDEX_SIZE >> 20);
3453     return FALSE;
3454   }
3455 }
3456
3457 /* find stream with @id */
3458 static inline QtDemuxStream *
3459 qtdemux_find_stream (GstQTDemux * qtdemux, guint32 id)
3460 {
3461   QtDemuxStream *stream;
3462   GList *iter;
3463
3464   /* check */
3465   if (G_UNLIKELY (!id)) {
3466     GST_DEBUG_OBJECT (qtdemux, "invalid track id 0");
3467     return NULL;
3468   }
3469
3470   for (iter = qtdemux->active_streams; iter; iter = g_list_next (iter)) {
3471     stream = QTDEMUX_STREAM (iter->data);
3472     if (stream->track_id == id)
3473       return stream;
3474   }
3475   if (qtdemux->mss_mode) {
3476     /* mss should have only 1 stream anyway */
3477     return QTDEMUX_FIRST_STREAM (qtdemux);
3478   }
3479
3480   return NULL;
3481 }
3482
3483 static gboolean
3484 qtdemux_parse_mfhd (GstQTDemux * qtdemux, GstByteReader * mfhd,
3485     guint32 * fragment_number)
3486 {
3487   if (!gst_byte_reader_skip (mfhd, 4))
3488     goto fail;
3489   if (!gst_byte_reader_get_uint32_be (mfhd, fragment_number))
3490     goto fail;
3491   return TRUE;
3492 fail:
3493   {
3494     GST_WARNING_OBJECT (qtdemux, "Failed to parse mfhd atom");
3495     return FALSE;
3496   }
3497 }
3498
3499 static gboolean
3500 qtdemux_parse_tfhd (GstQTDemux * qtdemux, GstByteReader * tfhd,
3501     QtDemuxStream ** stream, guint32 * default_sample_duration,
3502     guint32 * default_sample_size, guint32 * default_sample_flags,
3503     gint64 * base_offset)
3504 {
3505   guint32 flags = 0;
3506   guint32 track_id = 0;
3507
3508   if (!gst_byte_reader_skip (tfhd, 1) ||
3509       !gst_byte_reader_get_uint24_be (tfhd, &flags))
3510     goto invalid_track;
3511
3512   if (!gst_byte_reader_get_uint32_be (tfhd, &track_id))
3513     goto invalid_track;
3514
3515   *stream = qtdemux_find_stream (qtdemux, track_id);
3516   if (G_UNLIKELY (!*stream))
3517     goto unknown_stream;
3518
3519   if (flags & TF_DEFAULT_BASE_IS_MOOF)
3520     *base_offset = qtdemux->moof_offset;
3521
3522   if (flags & TF_BASE_DATA_OFFSET)
3523     if (!gst_byte_reader_get_uint64_be (tfhd, (guint64 *) base_offset))
3524       goto invalid_track;
3525
3526   /* obtain stream defaults */
3527   qtdemux_parse_trex (qtdemux, *stream,
3528       default_sample_duration, default_sample_size, default_sample_flags);
3529
3530   (*stream)->stsd_sample_description_id =
3531       (*stream)->def_sample_description_index - 1;
3532
3533   if (flags & TF_SAMPLE_DESCRIPTION_INDEX) {
3534     guint32 sample_description_index;
3535     if (!gst_byte_reader_get_uint32_be (tfhd, &sample_description_index))
3536       goto invalid_track;
3537     (*stream)->stsd_sample_description_id = sample_description_index - 1;
3538   }
3539
3540   if (qtdemux->mss_mode) {
3541     /* mss has no stsd entry */
3542     (*stream)->stsd_sample_description_id = 0;
3543   }
3544
3545   if (flags & TF_DEFAULT_SAMPLE_DURATION)
3546     if (!gst_byte_reader_get_uint32_be (tfhd, default_sample_duration))
3547       goto invalid_track;
3548
3549   if (flags & TF_DEFAULT_SAMPLE_SIZE)
3550     if (!gst_byte_reader_get_uint32_be (tfhd, default_sample_size))
3551       goto invalid_track;
3552
3553   if (flags & TF_DEFAULT_SAMPLE_FLAGS)
3554     if (!gst_byte_reader_get_uint32_be (tfhd, default_sample_flags))
3555       goto invalid_track;
3556
3557   return TRUE;
3558
3559 invalid_track:
3560   {
3561     GST_WARNING_OBJECT (qtdemux, "invalid track fragment header");
3562     return FALSE;
3563   }
3564 unknown_stream:
3565   {
3566     GST_DEBUG_OBJECT (qtdemux, "unknown stream in tfhd");
3567     return TRUE;
3568   }
3569 }
3570
3571 static gboolean
3572 qtdemux_parse_tfdt (GstQTDemux * qtdemux, GstByteReader * br,
3573     guint64 * decode_time)
3574 {
3575   guint32 version = 0;
3576
3577   if (!gst_byte_reader_get_uint32_be (br, &version))
3578     return FALSE;
3579
3580   version >>= 24;
3581   if (version == 1) {
3582     if (!gst_byte_reader_get_uint64_be (br, decode_time))
3583       goto failed;
3584   } else {
3585     guint32 dec_time = 0;
3586     if (!gst_byte_reader_get_uint32_be (br, &dec_time))
3587       goto failed;
3588     *decode_time = dec_time;
3589   }
3590
3591   GST_INFO_OBJECT (qtdemux, "Track fragment decode time: %" G_GUINT64_FORMAT,
3592       *decode_time);
3593
3594   return TRUE;
3595
3596 failed:
3597   {
3598     GST_DEBUG_OBJECT (qtdemux, "parsing tfdt failed");
3599     return FALSE;
3600   }
3601 }
3602
3603 /* Returns a pointer to a GstStructure containing the properties of
3604  * the stream sample identified by @sample_index. The caller must unref
3605  * the returned object after use. Returns NULL if unsuccessful. */
3606 static GstStructure *
3607 qtdemux_get_cenc_sample_properties (GstQTDemux * qtdemux,
3608     QtDemuxStream * stream, guint sample_index)
3609 {
3610   QtDemuxCencSampleSetInfo *info = NULL;
3611
3612   g_return_val_if_fail (stream != NULL, NULL);
3613   g_return_val_if_fail (stream->protected, NULL);
3614   g_return_val_if_fail (stream->protection_scheme_info != NULL, NULL);
3615
3616   info = (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
3617
3618   /* Currently, cenc properties for groups of samples are not supported, so
3619    * simply return a copy of the default sample properties */
3620   return gst_structure_copy (info->default_properties);
3621 }
3622
3623 /* Parses the sizes of sample auxiliary information contained within a stream,
3624  * as given in a saiz box. Returns array of sample_count guint8 size values,
3625  * or NULL on failure */
3626 static guint8 *
3627 qtdemux_parse_saiz (GstQTDemux * qtdemux, QtDemuxStream * stream,
3628     GstByteReader * br, guint32 * sample_count)
3629 {
3630   guint32 flags = 0;
3631   guint8 *info_sizes;
3632   guint8 default_info_size;
3633
3634   g_return_val_if_fail (qtdemux != NULL, NULL);
3635   g_return_val_if_fail (stream != NULL, NULL);
3636   g_return_val_if_fail (br != NULL, NULL);
3637   g_return_val_if_fail (sample_count != NULL, NULL);
3638
3639   if (!gst_byte_reader_get_uint32_be (br, &flags))
3640     return NULL;
3641
3642   if (flags & 0x1) {
3643     /* aux_info_type and aux_info_type_parameter are ignored */
3644     if (!gst_byte_reader_skip (br, 8))
3645       return NULL;
3646   }
3647
3648   if (!gst_byte_reader_get_uint8 (br, &default_info_size))
3649     return NULL;
3650   GST_DEBUG_OBJECT (qtdemux, "default_info_size: %u", default_info_size);
3651
3652   if (!gst_byte_reader_get_uint32_be (br, sample_count))
3653     return NULL;
3654   GST_DEBUG_OBJECT (qtdemux, "sample_count: %u", *sample_count);
3655
3656
3657   if (default_info_size == 0) {
3658     if (!gst_byte_reader_dup_data (br, *sample_count, &info_sizes)) {
3659       return NULL;
3660     }
3661   } else {
3662     info_sizes = g_new (guint8, *sample_count);
3663     memset (info_sizes, default_info_size, *sample_count);
3664   }
3665
3666   return info_sizes;
3667 }
3668
3669 /* Parses the offset of sample auxiliary information contained within a stream,
3670  * as given in a saio box. Returns TRUE if successful; FALSE otherwise. */
3671 static gboolean
3672 qtdemux_parse_saio (GstQTDemux * qtdemux, QtDemuxStream * stream,
3673     GstByteReader * br, guint32 * info_type, guint32 * info_type_parameter,
3674     guint64 * offset)
3675 {
3676   guint8 version = 0;
3677   guint32 flags = 0;
3678   guint32 aux_info_type = 0;
3679   guint32 aux_info_type_parameter = 0;
3680   guint32 entry_count;
3681   guint32 off_32;
3682   guint64 off_64;
3683   const guint8 *aux_info_type_data = NULL;
3684
3685   g_return_val_if_fail (qtdemux != NULL, FALSE);
3686   g_return_val_if_fail (stream != NULL, FALSE);
3687   g_return_val_if_fail (br != NULL, FALSE);
3688   g_return_val_if_fail (offset != NULL, FALSE);
3689
3690   if (!gst_byte_reader_get_uint8 (br, &version))
3691     return FALSE;
3692
3693   if (!gst_byte_reader_get_uint24_be (br, &flags))
3694     return FALSE;
3695
3696   if (flags & 0x1) {
3697
3698     if (!gst_byte_reader_get_data (br, 4, &aux_info_type_data))
3699       return FALSE;
3700     aux_info_type = QT_FOURCC (aux_info_type_data);
3701
3702     if (!gst_byte_reader_get_uint32_be (br, &aux_info_type_parameter))
3703       return FALSE;
3704   } else if (stream->protected) {
3705     aux_info_type = stream->protection_scheme_type;
3706   } else {
3707     aux_info_type = CUR_STREAM (stream)->fourcc;
3708   }
3709
3710   if (info_type)
3711     *info_type = aux_info_type;
3712   if (info_type_parameter)
3713     *info_type_parameter = aux_info_type_parameter;
3714
3715   GST_DEBUG_OBJECT (qtdemux, "aux_info_type: '%" GST_FOURCC_FORMAT "', "
3716       "aux_info_type_parameter:  %#06x",
3717       GST_FOURCC_ARGS (aux_info_type), aux_info_type_parameter);
3718
3719   if (!gst_byte_reader_get_uint32_be (br, &entry_count))
3720     return FALSE;
3721
3722   if (entry_count != 1) {
3723     GST_ERROR_OBJECT (qtdemux, "multiple offsets are not supported");
3724     return FALSE;
3725   }
3726
3727   if (version == 0) {
3728     if (!gst_byte_reader_get_uint32_be (br, &off_32))
3729       return FALSE;
3730     *offset = (guint64) off_32;
3731   } else {
3732     if (!gst_byte_reader_get_uint64_be (br, &off_64))
3733       return FALSE;
3734     *offset = off_64;
3735   }
3736
3737   GST_DEBUG_OBJECT (qtdemux, "offset: %" G_GUINT64_FORMAT, *offset);
3738   return TRUE;
3739 }
3740
3741 static void
3742 qtdemux_gst_structure_free (GstStructure * gststructure)
3743 {
3744   if (gststructure) {
3745     gst_structure_free (gststructure);
3746   }
3747 }
3748
3749 /* Parses auxiliary information relating to samples protected using Common
3750  * Encryption (cenc); the format of this information is defined in
3751  * ISO/IEC 23001-7. Returns TRUE if successful; FALSE otherwise. */
3752 static gboolean
3753 qtdemux_parse_cenc_aux_info (GstQTDemux * qtdemux, QtDemuxStream * stream,
3754     GstByteReader * br, guint8 * info_sizes, guint32 sample_count)
3755 {
3756   QtDemuxCencSampleSetInfo *ss_info = NULL;
3757   guint8 size;
3758   gint i;
3759   GPtrArray *old_crypto_info = NULL;
3760   guint old_entries = 0;
3761
3762   g_return_val_if_fail (qtdemux != NULL, FALSE);
3763   g_return_val_if_fail (stream != NULL, FALSE);
3764   g_return_val_if_fail (br != NULL, FALSE);
3765   g_return_val_if_fail (stream->protected, FALSE);
3766   g_return_val_if_fail (stream->protection_scheme_info != NULL, FALSE);
3767
3768   ss_info = (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
3769
3770   if (ss_info->crypto_info) {
3771     old_crypto_info = ss_info->crypto_info;
3772     /* Count number of non-null entries remaining at the tail end */
3773     for (i = old_crypto_info->len - 1; i >= 0; i--) {
3774       if (g_ptr_array_index (old_crypto_info, i) == NULL)
3775         break;
3776       old_entries++;
3777     }
3778   }
3779
3780   ss_info->crypto_info =
3781       g_ptr_array_new_full (sample_count + old_entries,
3782       (GDestroyNotify) qtdemux_gst_structure_free);
3783
3784   /* We preserve old entries because we parse the next moof in advance
3785    * of consuming all samples from the previous moof, and otherwise
3786    * we'd discard the corresponding crypto info for the samples
3787    * from the previous fragment. */
3788   if (old_entries) {
3789     GST_DEBUG_OBJECT (qtdemux, "Preserving %d old crypto info entries",
3790         old_entries);
3791     for (i = old_crypto_info->len - old_entries; i < old_crypto_info->len; i++) {
3792       g_ptr_array_add (ss_info->crypto_info, g_ptr_array_index (old_crypto_info,
3793               i));
3794       g_ptr_array_index (old_crypto_info, i) = NULL;
3795     }
3796   }
3797
3798   if (old_crypto_info) {
3799     /* Everything now belongs to the new array */
3800     g_ptr_array_free (old_crypto_info, TRUE);
3801   }
3802
3803   for (i = 0; i < sample_count; ++i) {
3804     GstStructure *properties;
3805     guint16 n_subsamples = 0;
3806     guint8 *data;
3807     guint iv_size;
3808     GstBuffer *buf;
3809
3810     properties = qtdemux_get_cenc_sample_properties (qtdemux, stream, i);
3811     if (properties == NULL) {
3812       GST_ERROR_OBJECT (qtdemux, "failed to get properties for sample %u", i);
3813       return FALSE;
3814     }
3815     if (!gst_structure_get_uint (properties, "iv_size", &iv_size)) {
3816       GST_ERROR_OBJECT (qtdemux, "failed to get iv_size for sample %u", i);
3817       gst_structure_free (properties);
3818       return FALSE;
3819     }
3820     if (!gst_byte_reader_dup_data (br, iv_size, &data)) {
3821       GST_ERROR_OBJECT (qtdemux, "failed to get IV for sample %u", i);
3822       gst_structure_free (properties);
3823       return FALSE;
3824     }
3825     buf = gst_buffer_new_wrapped (data, iv_size);
3826     gst_structure_set (properties, "iv", GST_TYPE_BUFFER, buf, NULL);
3827     gst_buffer_unref (buf);
3828     size = info_sizes[i];
3829     if (size > iv_size) {
3830       if (!gst_byte_reader_get_uint16_be (br, &n_subsamples)
3831           || !(n_subsamples > 0)) {
3832         gst_structure_free (properties);
3833         GST_ERROR_OBJECT (qtdemux,
3834             "failed to get subsample count for sample %u", i);
3835         return FALSE;
3836       }
3837       GST_LOG_OBJECT (qtdemux, "subsample count: %u", n_subsamples);
3838       if (!gst_byte_reader_dup_data (br, n_subsamples * 6, &data)) {
3839         GST_ERROR_OBJECT (qtdemux, "failed to get subsample data for sample %u",
3840             i);
3841         gst_structure_free (properties);
3842         return FALSE;
3843       }
3844       buf = gst_buffer_new_wrapped (data, n_subsamples * 6);
3845       if (!buf) {
3846         gst_structure_free (properties);
3847         return FALSE;
3848       }
3849       gst_structure_set (properties,
3850           "subsample_count", G_TYPE_UINT, n_subsamples,
3851           "subsamples", GST_TYPE_BUFFER, buf, NULL);
3852       gst_buffer_unref (buf);
3853     } else {
3854       gst_structure_set (properties, "subsample_count", G_TYPE_UINT, 0, NULL);
3855     }
3856     g_ptr_array_add (ss_info->crypto_info, properties);
3857   }
3858   return TRUE;
3859 }
3860
3861 /* Converts a UUID in raw byte form to a string representation, as defined in
3862  * RFC 4122. The caller takes ownership of the returned string and is
3863  * responsible for freeing it after use. */
3864 static gchar *
3865 qtdemux_uuid_bytes_to_string (gconstpointer uuid_bytes)
3866 {
3867   const guint8 *uuid = (const guint8 *) uuid_bytes;
3868
3869   return g_strdup_printf ("%02x%02x%02x%02x-%02x%02x-%02x%02x-"
3870       "%02x%02x-%02x%02x%02x%02x%02x%02x",
3871       uuid[0], uuid[1], uuid[2], uuid[3],
3872       uuid[4], uuid[5], uuid[6], uuid[7],
3873       uuid[8], uuid[9], uuid[10], uuid[11],
3874       uuid[12], uuid[13], uuid[14], uuid[15]);
3875 }
3876
3877 /* Parses a Protection System Specific Header box (pssh), as defined in the
3878  * Common Encryption (cenc) standard (ISO/IEC 23001-7), which contains
3879  * information needed by a specific content protection system in order to
3880  * decrypt cenc-protected tracks. Returns TRUE if successful; FALSE
3881  * otherwise. */
3882 static gboolean
3883 qtdemux_parse_pssh (GstQTDemux * qtdemux, GNode * node)
3884 {
3885   gchar *sysid_string;
3886   guint32 pssh_size = QT_UINT32 (node->data);
3887   GstBuffer *pssh = NULL;
3888   GstEvent *event = NULL;
3889   guint32 parent_box_type;
3890   GList *iter;
3891
3892   if (G_UNLIKELY (pssh_size < 32U)) {
3893     GST_ERROR_OBJECT (qtdemux, "invalid box size");
3894     return FALSE;
3895   }
3896
3897   sysid_string =
3898       qtdemux_uuid_bytes_to_string ((const guint8 *) node->data + 12);
3899
3900   gst_qtdemux_append_protection_system_id (qtdemux, sysid_string);
3901
3902   pssh = gst_buffer_new_wrapped (g_memdup (node->data, pssh_size), pssh_size);
3903   GST_LOG_OBJECT (qtdemux, "cenc pssh size: %" G_GSIZE_FORMAT,
3904       gst_buffer_get_size (pssh));
3905
3906   parent_box_type = QT_FOURCC ((const guint8 *) node->parent->data + 4);
3907
3908   /* Push an event containing the pssh box onto the queues of all streams. */
3909   event = gst_event_new_protection (sysid_string, pssh,
3910       (parent_box_type == FOURCC_moov) ? "isobmff/moov" : "isobmff/moof");
3911   for (iter = qtdemux->active_streams; iter; iter = g_list_next (iter)) {
3912     QtDemuxStream *stream = QTDEMUX_STREAM (iter->data);
3913     g_queue_push_tail (&stream->protection_scheme_event_queue,
3914         gst_event_ref (event));
3915   }
3916   g_free (sysid_string);
3917   gst_event_unref (event);
3918   gst_buffer_unref (pssh);
3919   return TRUE;
3920 }
3921
3922 static gboolean
3923 qtdemux_parse_moof (GstQTDemux * qtdemux, const guint8 * buffer, guint length,
3924     guint64 moof_offset, QtDemuxStream * stream)
3925 {
3926   GNode *moof_node, *traf_node, *tfhd_node, *trun_node, *tfdt_node, *mfhd_node;
3927   GNode *uuid_node;
3928   GstByteReader mfhd_data, trun_data, tfhd_data, tfdt_data;
3929   GNode *saiz_node, *saio_node, *pssh_node;
3930   GstByteReader saiz_data, saio_data;
3931   guint32 ds_size = 0, ds_duration = 0, ds_flags = 0;
3932   gint64 base_offset, running_offset;
3933   guint32 frag_num;
3934
3935   /* NOTE @stream ignored */
3936
3937   moof_node = g_node_new ((guint8 *) buffer);
3938   qtdemux_parse_node (qtdemux, moof_node, buffer, length);
3939   qtdemux_node_dump (qtdemux, moof_node);
3940
3941   /* Get fragment number from mfhd and check it's valid */
3942   mfhd_node =
3943       qtdemux_tree_get_child_by_type_full (moof_node, FOURCC_mfhd, &mfhd_data);
3944   if (mfhd_node == NULL)
3945     goto missing_mfhd;
3946   if (!qtdemux_parse_mfhd (qtdemux, &mfhd_data, &frag_num))
3947     goto fail;
3948   GST_DEBUG_OBJECT (qtdemux, "Fragment #%d", frag_num);
3949
3950   /* unknown base_offset to start with */
3951   base_offset = running_offset = -1;
3952   traf_node = qtdemux_tree_get_child_by_type (moof_node, FOURCC_traf);
3953   while (traf_node) {
3954     guint64 decode_time = 0;
3955
3956     /* Fragment Header node */
3957     tfhd_node =
3958         qtdemux_tree_get_child_by_type_full (traf_node, FOURCC_tfhd,
3959         &tfhd_data);
3960     if (!tfhd_node)
3961       goto missing_tfhd;
3962     if (!qtdemux_parse_tfhd (qtdemux, &tfhd_data, &stream, &ds_duration,
3963             &ds_size, &ds_flags, &base_offset))
3964       goto missing_tfhd;
3965
3966     /* The following code assumes at most a single set of sample auxiliary
3967      * data in the fragment (consisting of a saiz box and a corresponding saio
3968      * box); in theory, however, there could be multiple sets of sample
3969      * auxiliary data in a fragment. */
3970     saiz_node =
3971         qtdemux_tree_get_child_by_type_full (traf_node, FOURCC_saiz,
3972         &saiz_data);
3973     if (saiz_node) {
3974       guint32 info_type = 0;
3975       guint64 offset = 0;
3976       guint32 info_type_parameter = 0;
3977
3978       g_free (qtdemux->cenc_aux_info_sizes);
3979
3980       qtdemux->cenc_aux_info_sizes =
3981           qtdemux_parse_saiz (qtdemux, stream, &saiz_data,
3982           &qtdemux->cenc_aux_sample_count);
3983       if (qtdemux->cenc_aux_info_sizes == NULL) {
3984         GST_ERROR_OBJECT (qtdemux, "failed to parse saiz box");
3985         goto fail;
3986       }
3987       saio_node =
3988           qtdemux_tree_get_child_by_type_full (traf_node, FOURCC_saio,
3989           &saio_data);
3990       if (!saio_node) {
3991         GST_ERROR_OBJECT (qtdemux, "saiz box without a corresponding saio box");
3992         g_free (qtdemux->cenc_aux_info_sizes);
3993         qtdemux->cenc_aux_info_sizes = NULL;
3994         goto fail;
3995       }
3996
3997       if (G_UNLIKELY (!qtdemux_parse_saio (qtdemux, stream, &saio_data,
3998                   &info_type, &info_type_parameter, &offset))) {
3999         GST_ERROR_OBJECT (qtdemux, "failed to parse saio box");
4000         g_free (qtdemux->cenc_aux_info_sizes);
4001         qtdemux->cenc_aux_info_sizes = NULL;
4002         goto fail;
4003       }
4004       if (base_offset > -1 && base_offset > qtdemux->moof_offset)
4005         offset += (guint64) (base_offset - qtdemux->moof_offset);
4006       if (info_type == FOURCC_cenc && info_type_parameter == 0U) {
4007         GstByteReader br;
4008         if (offset > length) {
4009           GST_DEBUG_OBJECT (qtdemux, "cenc auxiliary info stored out of moof");
4010           qtdemux->cenc_aux_info_offset = offset;
4011         } else {
4012           gst_byte_reader_init (&br, buffer + offset, length - offset);
4013           if (!qtdemux_parse_cenc_aux_info (qtdemux, stream, &br,
4014                   qtdemux->cenc_aux_info_sizes,
4015                   qtdemux->cenc_aux_sample_count)) {
4016             GST_ERROR_OBJECT (qtdemux, "failed to parse cenc auxiliary info");
4017             g_free (qtdemux->cenc_aux_info_sizes);
4018             qtdemux->cenc_aux_info_sizes = NULL;
4019             goto fail;
4020           }
4021         }
4022       }
4023     }
4024
4025     tfdt_node =
4026         qtdemux_tree_get_child_by_type_full (traf_node, FOURCC_tfdt,
4027         &tfdt_data);
4028     if (tfdt_node) {
4029       /* We'll use decode_time to interpolate timestamps
4030        * in case the input timestamps are missing */
4031       qtdemux_parse_tfdt (qtdemux, &tfdt_data, &decode_time);
4032
4033       GST_DEBUG_OBJECT (qtdemux, "decode time %" G_GINT64_FORMAT
4034           " (%" GST_TIME_FORMAT ")", decode_time,
4035           GST_TIME_ARGS (stream ? QTSTREAMTIME_TO_GSTTIME (stream,
4036                   decode_time) : GST_CLOCK_TIME_NONE));
4037
4038       /* Discard the fragment buffer timestamp info to avoid using it.
4039        * Rely on tfdt instead as it is more accurate than the timestamp
4040        * that is fetched from a manifest/playlist and is usually
4041        * less accurate. */
4042       qtdemux->fragment_start = -1;
4043     }
4044
4045     if (G_UNLIKELY (!stream)) {
4046       /* we lost track of offset, we'll need to regain it,
4047        * but can delay complaining until later or avoid doing so altogether */
4048       base_offset = -2;
4049       goto next;
4050     }
4051     if (G_UNLIKELY (base_offset < -1))
4052       goto lost_offset;
4053
4054     if (qtdemux->upstream_format_is_time)
4055       gst_qtdemux_stream_flush_samples_data (stream);
4056
4057     /* initialise moof sample data */
4058     stream->n_samples_moof = 0;
4059     stream->duration_last_moof = stream->duration_moof;
4060     stream->duration_moof = 0;
4061
4062     /* Track Run node */
4063     trun_node =
4064         qtdemux_tree_get_child_by_type_full (traf_node, FOURCC_trun,
4065         &trun_data);
4066     while (trun_node) {
4067       qtdemux_parse_trun (qtdemux, &trun_data, stream,
4068           ds_duration, ds_size, ds_flags, moof_offset, length, &base_offset,
4069           &running_offset, decode_time, (tfdt_node != NULL));
4070       /* iterate all siblings */
4071       trun_node = qtdemux_tree_get_sibling_by_type_full (trun_node, FOURCC_trun,
4072           &trun_data);
4073     }
4074
4075     uuid_node = qtdemux_tree_get_child_by_type (traf_node, FOURCC_uuid);
4076     if (uuid_node) {
4077       guint8 *uuid_buffer = (guint8 *) uuid_node->data;
4078       guint32 box_length = QT_UINT32 (uuid_buffer);
4079
4080       qtdemux_parse_uuid (qtdemux, uuid_buffer, box_length);
4081     }
4082
4083     /* if no new base_offset provided for next traf,
4084      * base is end of current traf */
4085     base_offset = running_offset;
4086     running_offset = -1;
4087
4088     if (stream->n_samples_moof && stream->duration_moof)
4089       stream->new_caps = TRUE;
4090
4091   next:
4092     /* iterate all siblings */
4093     traf_node = qtdemux_tree_get_sibling_by_type (traf_node, FOURCC_traf);
4094   }
4095
4096   /* parse any protection system info */
4097   pssh_node = qtdemux_tree_get_child_by_type (moof_node, FOURCC_pssh);
4098   while (pssh_node) {
4099     GST_LOG_OBJECT (qtdemux, "Parsing pssh box.");
4100     qtdemux_parse_pssh (qtdemux, pssh_node);
4101     pssh_node = qtdemux_tree_get_sibling_by_type (pssh_node, FOURCC_pssh);
4102   }
4103
4104   g_node_destroy (moof_node);
4105   return TRUE;
4106
4107 missing_tfhd:
4108   {
4109     GST_DEBUG_OBJECT (qtdemux, "missing tfhd box");
4110     goto fail;
4111   }
4112 missing_mfhd:
4113   {
4114     GST_DEBUG_OBJECT (qtdemux, "Missing mfhd box");
4115     goto fail;
4116   }
4117 lost_offset:
4118   {
4119     GST_DEBUG_OBJECT (qtdemux, "lost offset");
4120     goto fail;
4121   }
4122 fail:
4123   {
4124     g_node_destroy (moof_node);
4125     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
4126         (_("This file is corrupt and cannot be played.")), (NULL));
4127     return FALSE;
4128   }
4129 }
4130
4131 #if 0
4132 /* might be used if some day we actually use mfra & co
4133  * for random access to fragments,
4134  * but that will require quite some modifications and much less relying
4135  * on a sample array */
4136 #endif
4137
4138 static gboolean
4139 qtdemux_parse_tfra (GstQTDemux * qtdemux, GNode * tfra_node)
4140 {
4141   QtDemuxStream *stream;
4142   guint32 ver_flags, track_id, len, num_entries, i;
4143   guint value_size, traf_size, trun_size, sample_size;
4144   guint64 time = 0, moof_offset = 0;
4145 #if 0
4146   GstBuffer *buf = NULL;
4147   GstFlowReturn ret;
4148 #endif
4149   GstByteReader tfra;
4150
4151   gst_byte_reader_init (&tfra, tfra_node->data, QT_UINT32 (tfra_node->data));
4152
4153   if (!gst_byte_reader_skip (&tfra, 8))
4154     return FALSE;
4155
4156   if (!gst_byte_reader_get_uint32_be (&tfra, &ver_flags))
4157     return FALSE;
4158
4159   if (!gst_byte_reader_get_uint32_be (&tfra, &track_id)
4160       || !gst_byte_reader_get_uint32_be (&tfra, &len)
4161       || !gst_byte_reader_get_uint32_be (&tfra, &num_entries))
4162     return FALSE;
4163
4164   GST_DEBUG_OBJECT (qtdemux, "parsing tfra box for track id %u", track_id);
4165
4166   stream = qtdemux_find_stream (qtdemux, track_id);
4167   if (stream == NULL)
4168     goto unknown_trackid;
4169
4170   value_size = ((ver_flags >> 24) == 1) ? sizeof (guint64) : sizeof (guint32);
4171   sample_size = (len & 3) + 1;
4172   trun_size = ((len & 12) >> 2) + 1;
4173   traf_size = ((len & 48) >> 4) + 1;
4174
4175   GST_DEBUG_OBJECT (qtdemux, "%u entries, sizes: value %u, traf %u, trun %u, "
4176       "sample %u", num_entries, value_size, traf_size, trun_size, sample_size);
4177
4178   if (num_entries == 0)
4179     goto no_samples;
4180
4181   if (!qt_atom_parser_has_chunks (&tfra, num_entries,
4182           value_size + value_size + traf_size + trun_size + sample_size))
4183     goto corrupt_file;
4184
4185   g_free (stream->ra_entries);
4186   stream->ra_entries = g_new (QtDemuxRandomAccessEntry, num_entries);
4187   stream->n_ra_entries = num_entries;
4188
4189   for (i = 0; i < num_entries; i++) {
4190     qt_atom_parser_get_offset (&tfra, value_size, &time);
4191     qt_atom_parser_get_offset (&tfra, value_size, &moof_offset);
4192     qt_atom_parser_get_uint_with_size_unchecked (&tfra, traf_size);
4193     qt_atom_parser_get_uint_with_size_unchecked (&tfra, trun_size);
4194     qt_atom_parser_get_uint_with_size_unchecked (&tfra, sample_size);
4195
4196     time = QTSTREAMTIME_TO_GSTTIME (stream, time);
4197
4198     GST_LOG_OBJECT (qtdemux, "fragment time: %" GST_TIME_FORMAT ", "
4199         " moof_offset: %" G_GUINT64_FORMAT, GST_TIME_ARGS (time), moof_offset);
4200
4201     stream->ra_entries[i].ts = time;
4202     stream->ra_entries[i].moof_offset = moof_offset;
4203
4204     /* don't want to go through the entire file and read all moofs at startup */
4205 #if 0
4206     ret = gst_qtdemux_pull_atom (qtdemux, moof_offset, 0, &buf);
4207     if (ret != GST_FLOW_OK)
4208       goto corrupt_file;
4209     qtdemux_parse_moof (qtdemux, GST_BUFFER_DATA (buf), GST_BUFFER_SIZE (buf),
4210         moof_offset, stream);
4211     gst_buffer_unref (buf);
4212 #endif
4213   }
4214
4215   check_update_duration (qtdemux, time);
4216
4217   return TRUE;
4218
4219 /* ERRORS */
4220 unknown_trackid:
4221   {
4222     GST_WARNING_OBJECT (qtdemux, "Couldn't find stream for track %u", track_id);
4223     return FALSE;
4224   }
4225 corrupt_file:
4226   {
4227     GST_WARNING_OBJECT (qtdemux, "broken traf box, ignoring");
4228     return FALSE;
4229   }
4230 no_samples:
4231   {
4232     GST_WARNING_OBJECT (qtdemux, "stream has no samples");
4233     return FALSE;
4234   }
4235 }
4236
4237 static gboolean
4238 qtdemux_pull_mfro_mfra (GstQTDemux * qtdemux)
4239 {
4240   GstMapInfo mfro_map = GST_MAP_INFO_INIT;
4241   GstMapInfo mfra_map = GST_MAP_INFO_INIT;
4242   GstBuffer *mfro = NULL, *mfra = NULL;
4243   GstFlowReturn flow;
4244   gboolean ret = FALSE;
4245   GNode *mfra_node, *tfra_node;
4246   guint64 mfra_offset = 0;
4247   guint32 fourcc, mfra_size;
4248   gint64 len;
4249
4250   /* query upstream size in bytes */
4251   if (!gst_pad_peer_query_duration (qtdemux->sinkpad, GST_FORMAT_BYTES, &len))
4252     goto size_query_failed;
4253
4254   /* mfro box should be at the very end of the file */
4255   flow = gst_qtdemux_pull_atom (qtdemux, len - 16, 16, &mfro);
4256   if (flow != GST_FLOW_OK)
4257     goto exit;
4258
4259   gst_buffer_map (mfro, &mfro_map, GST_MAP_READ);
4260
4261   fourcc = QT_FOURCC (mfro_map.data + 4);
4262   if (fourcc != FOURCC_mfro)
4263     goto exit;
4264
4265   GST_INFO_OBJECT (qtdemux, "Found mfro box");
4266   if (mfro_map.size < 16)
4267     goto invalid_mfro_size;
4268
4269   mfra_size = QT_UINT32 (mfro_map.data + 12);
4270   if (mfra_size >= len)
4271     goto invalid_mfra_size;
4272
4273   mfra_offset = len - mfra_size;
4274
4275   GST_INFO_OBJECT (qtdemux, "mfra offset: %" G_GUINT64_FORMAT ", size %u",
4276       mfra_offset, mfra_size);
4277
4278   /* now get and parse mfra box */
4279   flow = gst_qtdemux_pull_atom (qtdemux, mfra_offset, mfra_size, &mfra);
4280   if (flow != GST_FLOW_OK)
4281     goto broken_file;
4282
4283   gst_buffer_map (mfra, &mfra_map, GST_MAP_READ);
4284
4285   mfra_node = g_node_new ((guint8 *) mfra_map.data);
4286   qtdemux_parse_node (qtdemux, mfra_node, mfra_map.data, mfra_map.size);
4287
4288   tfra_node = qtdemux_tree_get_child_by_type (mfra_node, FOURCC_tfra);
4289
4290   while (tfra_node) {
4291     qtdemux_parse_tfra (qtdemux, tfra_node);
4292     /* iterate all siblings */
4293     tfra_node = qtdemux_tree_get_sibling_by_type (tfra_node, FOURCC_tfra);
4294   }
4295   g_node_destroy (mfra_node);
4296
4297   GST_INFO_OBJECT (qtdemux, "parsed movie fragment random access box (mfra)");
4298   ret = TRUE;
4299
4300 exit:
4301
4302   if (mfro) {
4303     if (mfro_map.memory != NULL)
4304       gst_buffer_unmap (mfro, &mfro_map);
4305     gst_buffer_unref (mfro);
4306   }
4307   if (mfra) {
4308     if (mfra_map.memory != NULL)
4309       gst_buffer_unmap (mfra, &mfra_map);
4310     gst_buffer_unref (mfra);
4311   }
4312   return ret;
4313
4314 /* ERRORS */
4315 size_query_failed:
4316   {
4317     GST_WARNING_OBJECT (qtdemux, "could not query upstream size");
4318     goto exit;
4319   }
4320 invalid_mfro_size:
4321   {
4322     GST_WARNING_OBJECT (qtdemux, "mfro size is too small");
4323     goto exit;
4324   }
4325 invalid_mfra_size:
4326   {
4327     GST_WARNING_OBJECT (qtdemux, "mfra_size in mfro box is invalid");
4328     goto exit;
4329   }
4330 broken_file:
4331   {
4332     GST_WARNING_OBJECT (qtdemux, "bogus mfra offset or size, broken file");
4333     goto exit;
4334   }
4335 }
4336
4337 static guint64
4338 add_offset (guint64 offset, guint64 advance)
4339 {
4340   /* Avoid 64-bit overflow by clamping */
4341   if (offset > G_MAXUINT64 - advance)
4342     return G_MAXUINT64;
4343   return offset + advance;
4344 }
4345
4346 static GstFlowReturn
4347 gst_qtdemux_loop_state_header (GstQTDemux * qtdemux)
4348 {
4349   guint64 length = 0;
4350   guint32 fourcc = 0;
4351   GstBuffer *buf = NULL;
4352   GstFlowReturn ret = GST_FLOW_OK;
4353   guint64 cur_offset = qtdemux->offset;
4354   GstMapInfo map;
4355
4356   ret = gst_pad_pull_range (qtdemux->sinkpad, cur_offset, 16, &buf);
4357   if (G_UNLIKELY (ret != GST_FLOW_OK))
4358     goto beach;
4359   gst_buffer_map (buf, &map, GST_MAP_READ);
4360   if (G_LIKELY (map.size >= 8))
4361     extract_initial_length_and_fourcc (map.data, map.size, &length, &fourcc);
4362   gst_buffer_unmap (buf, &map);
4363   gst_buffer_unref (buf);
4364
4365   /* maybe we already got most we needed, so only consider this eof */
4366   if (G_UNLIKELY (length == 0)) {
4367     GST_ELEMENT_WARNING (qtdemux, STREAM, DEMUX,
4368         (_("Invalid atom size.")),
4369         ("Header atom '%" GST_FOURCC_FORMAT "' has empty length",
4370             GST_FOURCC_ARGS (fourcc)));
4371     ret = GST_FLOW_EOS;
4372     goto beach;
4373   }
4374
4375   switch (fourcc) {
4376     case FOURCC_moof:
4377       /* record for later parsing when needed */
4378       if (!qtdemux->moof_offset) {
4379         qtdemux->moof_offset = qtdemux->offset;
4380       }
4381       if (qtdemux_pull_mfro_mfra (qtdemux)) {
4382         /* FIXME */
4383       } else {
4384         qtdemux->offset += length;      /* skip moof and keep going */
4385       }
4386       if (qtdemux->got_moov) {
4387         GST_INFO_OBJECT (qtdemux, "moof header, got moov, done with headers");
4388         ret = GST_FLOW_EOS;
4389         goto beach;
4390       }
4391       break;
4392     case FOURCC_mdat:
4393     case FOURCC_free:
4394     case FOURCC_skip:
4395     case FOURCC_wide:
4396     case FOURCC_PICT:
4397     case FOURCC_pnot:
4398     {
4399       GST_LOG_OBJECT (qtdemux,
4400           "skipping atom '%" GST_FOURCC_FORMAT "' at %" G_GUINT64_FORMAT,
4401           GST_FOURCC_ARGS (fourcc), cur_offset);
4402       qtdemux->offset = add_offset (qtdemux->offset, length);
4403       break;
4404     }
4405     case FOURCC_moov:
4406     {
4407       GstBuffer *moov = NULL;
4408
4409       if (qtdemux->got_moov) {
4410         GST_DEBUG_OBJECT (qtdemux, "Skipping moov atom as we have one already");
4411         qtdemux->offset = add_offset (qtdemux->offset, length);
4412         goto beach;
4413       }
4414
4415       ret = gst_pad_pull_range (qtdemux->sinkpad, cur_offset, length, &moov);
4416       if (ret != GST_FLOW_OK)
4417         goto beach;
4418       gst_buffer_map (moov, &map, GST_MAP_READ);
4419
4420       if (length != map.size) {
4421         /* Some files have a 'moov' atom at the end of the file which contains
4422          * a terminal 'free' atom where the body of the atom is missing.
4423          * Check for, and permit, this special case.
4424          */
4425         if (map.size >= 8) {
4426           guint8 *final_data = map.data + (map.size - 8);
4427           guint32 final_length = QT_UINT32 (final_data);
4428           guint32 final_fourcc = QT_FOURCC (final_data + 4);
4429
4430           if (final_fourcc == FOURCC_free
4431               && map.size + final_length - 8 == length) {
4432             /* Ok, we've found that special case. Allocate a new buffer with
4433              * that free atom actually present. */
4434             GstBuffer *newmoov = gst_buffer_new_and_alloc (length);
4435             gst_buffer_fill (newmoov, 0, map.data, map.size);
4436             gst_buffer_memset (newmoov, map.size, 0, final_length - 8);
4437             gst_buffer_unmap (moov, &map);
4438             gst_buffer_unref (moov);
4439             moov = newmoov;
4440             gst_buffer_map (moov, &map, GST_MAP_READ);
4441           }
4442         }
4443       }
4444
4445       if (length != map.size) {
4446         GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
4447             (_("This file is incomplete and cannot be played.")),
4448             ("We got less than expected (received %" G_GSIZE_FORMAT
4449                 ", wanted %u, offset %" G_GUINT64_FORMAT ")", map.size,
4450                 (guint) length, cur_offset));
4451         gst_buffer_unmap (moov, &map);
4452         gst_buffer_unref (moov);
4453         ret = GST_FLOW_ERROR;
4454         goto beach;
4455       }
4456       qtdemux->offset += length;
4457
4458       qtdemux_parse_moov (qtdemux, map.data, length);
4459       qtdemux_node_dump (qtdemux, qtdemux->moov_node);
4460
4461       qtdemux_parse_tree (qtdemux);
4462       if (qtdemux->moov_node_compressed) {
4463         g_node_destroy (qtdemux->moov_node_compressed);
4464         g_free (qtdemux->moov_node->data);
4465       }
4466       qtdemux->moov_node_compressed = NULL;
4467       g_node_destroy (qtdemux->moov_node);
4468       qtdemux->moov_node = NULL;
4469       gst_buffer_unmap (moov, &map);
4470       gst_buffer_unref (moov);
4471       qtdemux->got_moov = TRUE;
4472
4473       break;
4474     }
4475     case FOURCC_ftyp:
4476     {
4477       GstBuffer *ftyp = NULL;
4478
4479       /* extract major brand; might come in handy for ISO vs QT issues */
4480       ret = gst_qtdemux_pull_atom (qtdemux, cur_offset, length, &ftyp);
4481       if (ret != GST_FLOW_OK)
4482         goto beach;
4483       qtdemux->offset += length;
4484       gst_buffer_map (ftyp, &map, GST_MAP_READ);
4485       qtdemux_parse_ftyp (qtdemux, map.data, map.size);
4486       gst_buffer_unmap (ftyp, &map);
4487       gst_buffer_unref (ftyp);
4488       break;
4489     }
4490     case FOURCC_uuid:
4491     {
4492       GstBuffer *uuid = NULL;
4493
4494       /* uuid are extension atoms */
4495       ret = gst_qtdemux_pull_atom (qtdemux, cur_offset, length, &uuid);
4496       if (ret != GST_FLOW_OK)
4497         goto beach;
4498       qtdemux->offset += length;
4499       gst_buffer_map (uuid, &map, GST_MAP_READ);
4500       qtdemux_parse_uuid (qtdemux, map.data, map.size);
4501       gst_buffer_unmap (uuid, &map);
4502       gst_buffer_unref (uuid);
4503       break;
4504     }
4505     case FOURCC_sidx:
4506     {
4507       GstBuffer *sidx = NULL;
4508       ret = gst_qtdemux_pull_atom (qtdemux, cur_offset, length, &sidx);
4509       if (ret != GST_FLOW_OK)
4510         goto beach;
4511       qtdemux->offset += length;
4512       gst_buffer_map (sidx, &map, GST_MAP_READ);
4513       qtdemux_parse_sidx (qtdemux, map.data, map.size);
4514       gst_buffer_unmap (sidx, &map);
4515       gst_buffer_unref (sidx);
4516       break;
4517     }
4518     default:
4519     {
4520       GstBuffer *unknown = NULL;
4521
4522       GST_LOG_OBJECT (qtdemux,
4523           "unknown %08x '%" GST_FOURCC_FORMAT "' of size %" G_GUINT64_FORMAT
4524           " at %" G_GUINT64_FORMAT, fourcc, GST_FOURCC_ARGS (fourcc), length,
4525           cur_offset);
4526       ret = gst_qtdemux_pull_atom (qtdemux, cur_offset, length, &unknown);
4527       if (ret != GST_FLOW_OK)
4528         goto beach;
4529       gst_buffer_map (unknown, &map, GST_MAP_READ);
4530       GST_MEMDUMP ("Unknown tag", map.data, map.size);
4531       gst_buffer_unmap (unknown, &map);
4532       gst_buffer_unref (unknown);
4533       qtdemux->offset += length;
4534       break;
4535     }
4536   }
4537
4538 beach:
4539   if (ret == GST_FLOW_EOS && (qtdemux->got_moov || qtdemux->media_caps)) {
4540     /* digested all data, show what we have */
4541     qtdemux_prepare_streams (qtdemux);
4542     ret = qtdemux_expose_streams (qtdemux);
4543
4544     qtdemux->state = QTDEMUX_STATE_MOVIE;
4545     GST_DEBUG_OBJECT (qtdemux, "switching state to STATE_MOVIE (%d)",
4546         qtdemux->state);
4547     return ret;
4548   }
4549   return ret;
4550 }
4551
4552 /* Seeks to the previous keyframe of the indexed stream and
4553  * aligns other streams with respect to the keyframe timestamp
4554  * of indexed stream. Only called in case of Reverse Playback
4555  */
4556 static GstFlowReturn
4557 gst_qtdemux_seek_to_previous_keyframe (GstQTDemux * qtdemux)
4558 {
4559   guint32 seg_idx = 0, k_index = 0;
4560   guint32 ref_seg_idx, ref_k_index;
4561   GstClockTime k_pos = 0, last_stop = 0;
4562   QtDemuxSegment *seg = NULL;
4563   QtDemuxStream *ref_str = NULL;
4564   guint64 seg_media_start_mov;  /* segment media start time in mov format */
4565   guint64 target_ts;
4566   GList *iter;
4567
4568   /* Now we choose an arbitrary stream, get the previous keyframe timestamp
4569    * and finally align all the other streams on that timestamp with their
4570    * respective keyframes */
4571   for (iter = qtdemux->active_streams; iter; iter = g_list_next (iter)) {
4572     QtDemuxStream *str = QTDEMUX_STREAM (iter->data);
4573
4574     /* No candidate yet, take the first stream */
4575     if (!ref_str) {
4576       ref_str = str;
4577       continue;
4578     }
4579
4580     /* So that stream has a segment, we prefer video streams */
4581     if (str->subtype == FOURCC_vide) {
4582       ref_str = str;
4583       break;
4584     }
4585   }
4586
4587   if (G_UNLIKELY (!ref_str)) {
4588     GST_DEBUG_OBJECT (qtdemux, "couldn't find any stream");
4589     goto eos;
4590   }
4591
4592   if (G_UNLIKELY (!ref_str->from_sample)) {
4593     GST_DEBUG_OBJECT (qtdemux, "reached the beginning of the file");
4594     goto eos;
4595   }
4596
4597   /* So that stream has been playing from from_sample to to_sample. We will
4598    * get the timestamp of the previous sample and search for a keyframe before
4599    * that. For audio streams we do an arbitrary jump in the past (10 samples) */
4600   if (ref_str->subtype == FOURCC_vide) {
4601     k_index = gst_qtdemux_find_keyframe (qtdemux, ref_str,
4602         ref_str->from_sample - 1, FALSE);
4603   } else {
4604     if (ref_str->from_sample >= 10)
4605       k_index = ref_str->from_sample - 10;
4606     else
4607       k_index = 0;
4608   }
4609
4610   target_ts =
4611       ref_str->samples[k_index].timestamp +
4612       ref_str->samples[k_index].pts_offset;
4613
4614   /* get current segment for that stream */
4615   seg = &ref_str->segments[ref_str->segment_index];
4616   /* Use segment start in original timescale for comparisons */
4617   seg_media_start_mov = seg->trak_media_start;
4618
4619   GST_LOG_OBJECT (qtdemux, "keyframe index %u ts %" G_GUINT64_FORMAT
4620       " seg start %" G_GUINT64_FORMAT " %" GST_TIME_FORMAT "\n",
4621       k_index, target_ts, seg_media_start_mov,
4622       GST_TIME_ARGS (seg->media_start));
4623
4624   /* Crawl back through segments to find the one containing this I frame */
4625   while (target_ts < seg_media_start_mov) {
4626     GST_DEBUG_OBJECT (qtdemux,
4627         "keyframe position (sample %u) is out of segment %u " " target %"
4628         G_GUINT64_FORMAT " seg start %" G_GUINT64_FORMAT, k_index,
4629         ref_str->segment_index, target_ts, seg_media_start_mov);
4630
4631     if (G_UNLIKELY (!ref_str->segment_index)) {
4632       /* Reached first segment, let's consider it's EOS */
4633       goto eos;
4634     }
4635     ref_str->segment_index--;
4636     seg = &ref_str->segments[ref_str->segment_index];
4637     /* Use segment start in original timescale for comparisons */
4638     seg_media_start_mov = seg->trak_media_start;
4639   }
4640   /* Calculate time position of the keyframe and where we should stop */
4641   k_pos =
4642       QTSTREAMTIME_TO_GSTTIME (ref_str,
4643       target_ts - seg->trak_media_start) + seg->time;
4644   last_stop =
4645       QTSTREAMTIME_TO_GSTTIME (ref_str,
4646       ref_str->samples[ref_str->from_sample].timestamp -
4647       seg->trak_media_start) + seg->time;
4648
4649   GST_DEBUG_OBJECT (qtdemux, "preferred stream played from sample %u, "
4650       "now going to sample %u (pts %" GST_TIME_FORMAT ")", ref_str->from_sample,
4651       k_index, GST_TIME_ARGS (k_pos));
4652
4653   /* Set last_stop with the keyframe timestamp we pushed of that stream */
4654   qtdemux->segment.position = last_stop;
4655   GST_DEBUG_OBJECT (qtdemux, "last_stop now is %" GST_TIME_FORMAT,
4656       GST_TIME_ARGS (last_stop));
4657
4658   if (G_UNLIKELY (last_stop < qtdemux->segment.start)) {
4659     GST_DEBUG_OBJECT (qtdemux, "reached the beginning of segment");
4660     goto eos;
4661   }
4662
4663   ref_seg_idx = ref_str->segment_index;
4664   ref_k_index = k_index;
4665
4666   /* Align them all on this */
4667   for (iter = qtdemux->active_streams; iter; iter = g_list_next (iter)) {
4668     guint32 index = 0;
4669     GstClockTime seg_time = 0;
4670     QtDemuxStream *str = QTDEMUX_STREAM (iter->data);
4671
4672     /* aligning reference stream again might lead to backing up to yet another
4673      * keyframe (due to timestamp rounding issues),
4674      * potentially putting more load on downstream; so let's try to avoid */
4675     if (str == ref_str) {
4676       seg_idx = ref_seg_idx;
4677       seg = &str->segments[seg_idx];
4678       k_index = ref_k_index;
4679       GST_DEBUG_OBJECT (qtdemux, "reference track-id %u segment %d, "
4680           "sample at index %d", str->track_id, ref_str->segment_index, k_index);
4681     } else {
4682       seg_idx = gst_qtdemux_find_segment (qtdemux, str, k_pos);
4683       GST_DEBUG_OBJECT (qtdemux,
4684           "track-id %u align segment %d for keyframe pos %" GST_TIME_FORMAT,
4685           str->track_id, seg_idx, GST_TIME_ARGS (k_pos));
4686
4687       /* get segment and time in the segment */
4688       seg = &str->segments[seg_idx];
4689       seg_time = k_pos - seg->time;
4690
4691       /* get the media time in the segment.
4692        * No adjustment for empty "filler" segments */
4693       if (seg->media_start != GST_CLOCK_TIME_NONE)
4694         seg_time += seg->media_start;
4695
4696       /* get the index of the sample with media time */
4697       index = gst_qtdemux_find_index_linear (qtdemux, str, seg_time);
4698       GST_DEBUG_OBJECT (qtdemux,
4699           "track-id %u sample for %" GST_TIME_FORMAT " at %u", str->track_id,
4700           GST_TIME_ARGS (seg_time), index);
4701
4702       /* find previous keyframe */
4703       k_index = gst_qtdemux_find_keyframe (qtdemux, str, index, FALSE);
4704     }
4705
4706     /* Remember until where we want to go */
4707     str->to_sample = str->from_sample - 1;
4708     /* Define our time position */
4709     target_ts =
4710         str->samples[k_index].timestamp + str->samples[k_index].pts_offset;
4711     str->time_position = QTSTREAMTIME_TO_GSTTIME (str, target_ts) + seg->time;
4712     if (seg->media_start != GST_CLOCK_TIME_NONE)
4713       str->time_position -= seg->media_start;
4714
4715     /* Now seek back in time */
4716     gst_qtdemux_move_stream (qtdemux, str, k_index);
4717     GST_DEBUG_OBJECT (qtdemux, "track-id %u keyframe at %u, time position %"
4718         GST_TIME_FORMAT " playing from sample %u to %u", str->track_id, k_index,
4719         GST_TIME_ARGS (str->time_position), str->from_sample, str->to_sample);
4720   }
4721
4722   return GST_FLOW_OK;
4723
4724 eos:
4725   return GST_FLOW_EOS;
4726 }
4727
4728 /*
4729  * Gets the current qt segment start, stop and position for the
4730  * given time offset. This is used in update_segment()
4731  */
4732 static void
4733 gst_qtdemux_stream_segment_get_boundaries (GstQTDemux * qtdemux,
4734     QtDemuxStream * stream, GstClockTime offset,
4735     GstClockTime * _start, GstClockTime * _stop, GstClockTime * _time)
4736 {
4737   GstClockTime seg_time;
4738   GstClockTime start, stop, time;
4739   QtDemuxSegment *segment;
4740
4741   segment = &stream->segments[stream->segment_index];
4742
4743   /* get time in this segment */
4744   seg_time = (offset - segment->time) * segment->rate;
4745
4746   GST_LOG_OBJECT (stream->pad, "seg_time %" GST_TIME_FORMAT,
4747       GST_TIME_ARGS (seg_time));
4748
4749   if (G_UNLIKELY (seg_time > segment->duration)) {
4750     GST_LOG_OBJECT (stream->pad,
4751         "seg_time > segment->duration %" GST_TIME_FORMAT,
4752         GST_TIME_ARGS (segment->duration));
4753     seg_time = segment->duration;
4754   }
4755
4756   /* qtdemux->segment.stop is in outside-time-realm, whereas
4757    * segment->media_stop is in track-time-realm.
4758    *
4759    * In order to compare the two, we need to bring segment.stop
4760    * into the track-time-realm
4761    *
4762    * FIXME - does this comment still hold? Don't see any conversion here */
4763
4764   stop = qtdemux->segment.stop;
4765   if (stop == GST_CLOCK_TIME_NONE)
4766     stop = qtdemux->segment.duration;
4767   if (stop == GST_CLOCK_TIME_NONE)
4768     stop = segment->media_stop;
4769   else
4770     stop =
4771         MIN (segment->media_stop, stop - segment->time + segment->media_start);
4772
4773   if (G_UNLIKELY (QTSEGMENT_IS_EMPTY (segment))) {
4774     start = segment->time + seg_time;
4775     time = offset;
4776     stop = start - seg_time + segment->duration;
4777   } else if (qtdemux->segment.rate >= 0) {
4778     start = MIN (segment->media_start + seg_time, stop);
4779     time = offset;
4780   } else {
4781     if (segment->media_start >= qtdemux->segment.start) {
4782       time = segment->time;
4783     } else {
4784       time = segment->time + (qtdemux->segment.start - segment->media_start);
4785     }
4786
4787     start = MAX (segment->media_start, qtdemux->segment.start);
4788     stop = MIN (segment->media_start + seg_time, stop);
4789   }
4790
4791   *_start = start;
4792   *_stop = stop;
4793   *_time = time;
4794 }
4795
4796 /*
4797  * Updates the qt segment used for the stream and pushes a new segment event
4798  * downstream on this stream's pad.
4799  */
4800 static gboolean
4801 gst_qtdemux_stream_update_segment (GstQTDemux * qtdemux, QtDemuxStream * stream,
4802     gint seg_idx, GstClockTime offset, GstClockTime * _start,
4803     GstClockTime * _stop)
4804 {
4805   QtDemuxSegment *segment;
4806   GstClockTime start = 0, stop = GST_CLOCK_TIME_NONE, time = 0;
4807   gdouble rate;
4808   GstEvent *event;
4809
4810   /* update the current segment */
4811   stream->segment_index = seg_idx;
4812
4813   /* get the segment */
4814   segment = &stream->segments[seg_idx];
4815
4816   if (G_UNLIKELY (offset < segment->time)) {
4817     GST_WARNING_OBJECT (stream->pad, "offset < segment->time %" GST_TIME_FORMAT,
4818         GST_TIME_ARGS (segment->time));
4819     return FALSE;
4820   }
4821
4822   /* segment lies beyond total indicated duration */
4823   if (G_UNLIKELY (qtdemux->segment.duration != GST_CLOCK_TIME_NONE &&
4824           segment->time > qtdemux->segment.duration)) {
4825     GST_WARNING_OBJECT (stream->pad, "file duration %" GST_TIME_FORMAT
4826         " < segment->time %" GST_TIME_FORMAT,
4827         GST_TIME_ARGS (qtdemux->segment.duration),
4828         GST_TIME_ARGS (segment->time));
4829     return FALSE;
4830   }
4831
4832   gst_qtdemux_stream_segment_get_boundaries (qtdemux, stream, offset,
4833       &start, &stop, &time);
4834
4835   GST_DEBUG_OBJECT (stream->pad, "new segment %d from %" GST_TIME_FORMAT
4836       " to %" GST_TIME_FORMAT ", time %" GST_TIME_FORMAT, seg_idx,
4837       GST_TIME_ARGS (start), GST_TIME_ARGS (stop), GST_TIME_ARGS (time));
4838
4839   /* combine global rate with that of the segment */
4840   rate = segment->rate * qtdemux->segment.rate;
4841
4842   /* Copy flags from main segment */
4843   stream->segment.flags = qtdemux->segment.flags;
4844
4845   /* update the segment values used for clipping */
4846   stream->segment.offset = qtdemux->segment.offset;
4847   stream->segment.base = qtdemux->segment.base + stream->accumulated_base;
4848   stream->segment.applied_rate = qtdemux->segment.applied_rate;
4849   stream->segment.rate = rate;
4850   stream->segment.start = start + QTSTREAMTIME_TO_GSTTIME (stream,
4851       stream->cslg_shift);
4852   stream->segment.stop = stop + QTSTREAMTIME_TO_GSTTIME (stream,
4853       stream->cslg_shift);
4854   stream->segment.time = time;
4855   stream->segment.position = stream->segment.start;
4856
4857   GST_DEBUG_OBJECT (stream->pad, "New segment: %" GST_SEGMENT_FORMAT,
4858       &stream->segment);
4859
4860   /* now prepare and send the segment */
4861   if (stream->pad) {
4862     event = gst_event_new_segment (&stream->segment);
4863     if (qtdemux->segment_seqnum != GST_SEQNUM_INVALID) {
4864       gst_event_set_seqnum (event, qtdemux->segment_seqnum);
4865     }
4866     gst_pad_push_event (stream->pad, event);
4867     /* assume we can send more data now */
4868     GST_PAD_LAST_FLOW_RETURN (stream->pad) = GST_FLOW_OK;
4869     /* clear to send tags on this pad now */
4870     gst_qtdemux_push_tags (qtdemux, stream);
4871   }
4872
4873   if (_start)
4874     *_start = start;
4875   if (_stop)
4876     *_stop = stop;
4877
4878   return TRUE;
4879 }
4880
4881 /* activate the given segment number @seg_idx of @stream at time @offset.
4882  * @offset is an absolute global position over all the segments.
4883  *
4884  * This will push out a NEWSEGMENT event with the right values and
4885  * position the stream index to the first decodable sample before
4886  * @offset.
4887  */
4888 static gboolean
4889 gst_qtdemux_activate_segment (GstQTDemux * qtdemux, QtDemuxStream * stream,
4890     guint32 seg_idx, GstClockTime offset)
4891 {
4892   QtDemuxSegment *segment;
4893   guint32 index, kf_index;
4894   GstClockTime start = 0, stop = GST_CLOCK_TIME_NONE;
4895
4896   GST_LOG_OBJECT (stream->pad, "activate segment %d, offset %" GST_TIME_FORMAT,
4897       seg_idx, GST_TIME_ARGS (offset));
4898
4899   if (!gst_qtdemux_stream_update_segment (qtdemux, stream, seg_idx, offset,
4900           &start, &stop))
4901     return FALSE;
4902
4903   segment = &stream->segments[stream->segment_index];
4904
4905   /* in the fragmented case, we pick a fragment that starts before our
4906    * desired position and rely on downstream to wait for a keyframe
4907    * (FIXME: doesn't seem to work so well with ismv and wmv, as no parser; the
4908    * tfra entries tells us which trun/sample the key unit is in, but we don't
4909    * make use of this additional information at the moment) */
4910   if (qtdemux->fragmented && !qtdemux->fragmented_seek_pending) {
4911     stream->to_sample = G_MAXUINT32;
4912     return TRUE;
4913   } else {
4914     /* well, it will be taken care of below */
4915     qtdemux->fragmented_seek_pending = FALSE;
4916     /* FIXME ideally the do_fragmented_seek can be done right here,
4917      * rather than at loop level
4918      * (which might even allow handling edit lists in a fragmented file) */
4919   }
4920
4921   /* We don't need to look for a sample in push-based */
4922   if (!qtdemux->pullbased)
4923     return TRUE;
4924
4925   /* and move to the keyframe before the indicated media time of the
4926    * segment */
4927   if (G_LIKELY (!QTSEGMENT_IS_EMPTY (segment))) {
4928     if (qtdemux->segment.rate >= 0) {
4929       index = gst_qtdemux_find_index_linear (qtdemux, stream, start);
4930       stream->to_sample = G_MAXUINT32;
4931       GST_DEBUG_OBJECT (stream->pad,
4932           "moving data pointer to %" GST_TIME_FORMAT ", index: %u, pts %"
4933           GST_TIME_FORMAT, GST_TIME_ARGS (start), index,
4934           GST_TIME_ARGS (QTSAMPLE_PTS (stream, &stream->samples[index])));
4935     } else {
4936       index = gst_qtdemux_find_index_linear (qtdemux, stream, stop);
4937       stream->to_sample = index;
4938       GST_DEBUG_OBJECT (stream->pad,
4939           "moving data pointer to %" GST_TIME_FORMAT ", index: %u, pts %"
4940           GST_TIME_FORMAT, GST_TIME_ARGS (stop), index,
4941           GST_TIME_ARGS (QTSAMPLE_PTS (stream, &stream->samples[index])));
4942     }
4943   } else {
4944     GST_DEBUG_OBJECT (stream->pad, "No need to look for keyframe, "
4945         "this is an empty segment");
4946     return TRUE;
4947   }
4948
4949   /* gst_qtdemux_parse_sample () called from gst_qtdemux_find_index_linear ()
4950    * encountered an error and printed a message so we return appropriately */
4951   if (index == -1)
4952     return FALSE;
4953
4954   /* we're at the right spot */
4955   if (index == stream->sample_index) {
4956     GST_DEBUG_OBJECT (stream->pad, "we are at the right index");
4957     return TRUE;
4958   }
4959
4960   /* find keyframe of the target index */
4961   kf_index = gst_qtdemux_find_keyframe (qtdemux, stream, index, FALSE);
4962
4963 /* *INDENT-OFF* */
4964 /* indent does stupid stuff with stream->samples[].timestamp */
4965
4966   /* if we move forwards, we don't have to go back to the previous
4967    * keyframe since we already sent that. We can also just jump to
4968    * the keyframe right before the target index if there is one. */
4969   if (index > stream->sample_index) {
4970     /* moving forwards check if we move past a keyframe */
4971     if (kf_index > stream->sample_index) {
4972       GST_DEBUG_OBJECT (stream->pad,
4973            "moving forwards to keyframe at %u (pts %" GST_TIME_FORMAT " dts %"GST_TIME_FORMAT" )", kf_index,
4974            GST_TIME_ARGS (QTSAMPLE_PTS(stream, &stream->samples[kf_index])),
4975            GST_TIME_ARGS (QTSAMPLE_DTS(stream, &stream->samples[kf_index])));
4976       gst_qtdemux_move_stream (qtdemux, stream, kf_index);
4977     } else {
4978       GST_DEBUG_OBJECT (stream->pad,
4979           "moving forwards, keyframe at %u (pts %" GST_TIME_FORMAT " dts %"GST_TIME_FORMAT" ) already sent", kf_index,
4980           GST_TIME_ARGS (QTSAMPLE_PTS (stream, &stream->samples[kf_index])),
4981           GST_TIME_ARGS (QTSAMPLE_DTS (stream, &stream->samples[kf_index])));
4982     }
4983   } else {
4984     GST_DEBUG_OBJECT (stream->pad,
4985         "moving backwards to keyframe at %u (pts %" GST_TIME_FORMAT " dts %"GST_TIME_FORMAT" )", kf_index,
4986         GST_TIME_ARGS (QTSAMPLE_PTS(stream, &stream->samples[kf_index])),
4987         GST_TIME_ARGS (QTSAMPLE_DTS(stream, &stream->samples[kf_index])));
4988     gst_qtdemux_move_stream (qtdemux, stream, kf_index);
4989   }
4990
4991 /* *INDENT-ON* */
4992
4993   return TRUE;
4994 }
4995
4996 /* prepare to get the current sample of @stream, getting essential values.
4997  *
4998  * This function will also prepare and send the segment when needed.
4999  *
5000  * Return FALSE if the stream is EOS.
5001  *
5002  * PULL-BASED
5003  */
5004 static gboolean
5005 gst_qtdemux_prepare_current_sample (GstQTDemux * qtdemux,
5006     QtDemuxStream * stream, gboolean * empty, guint64 * offset, guint * size,
5007     GstClockTime * dts, GstClockTime * pts, GstClockTime * duration,
5008     gboolean * keyframe)
5009 {
5010   QtDemuxSample *sample;
5011   GstClockTime time_position;
5012   guint32 seg_idx;
5013
5014   g_return_val_if_fail (stream != NULL, FALSE);
5015
5016   time_position = stream->time_position;
5017   if (G_UNLIKELY (time_position == GST_CLOCK_TIME_NONE))
5018     goto eos;
5019
5020   seg_idx = stream->segment_index;
5021   if (G_UNLIKELY (seg_idx == -1)) {
5022     /* find segment corresponding to time_position if we are looking
5023      * for a segment. */
5024     seg_idx = gst_qtdemux_find_segment (qtdemux, stream, time_position);
5025   }
5026
5027   /* different segment, activate it, sample_index will be set. */
5028   if (G_UNLIKELY (stream->segment_index != seg_idx))
5029     gst_qtdemux_activate_segment (qtdemux, stream, seg_idx, time_position);
5030
5031   if (G_UNLIKELY (QTSEGMENT_IS_EMPTY (&stream->segments[stream->
5032                   segment_index]))) {
5033     QtDemuxSegment *seg = &stream->segments[stream->segment_index];
5034
5035     GST_LOG_OBJECT (qtdemux, "Empty segment activated,"
5036         " prepare empty sample");
5037
5038     *empty = TRUE;
5039     *pts = *dts = time_position;
5040     *duration = seg->duration - (time_position - seg->time);
5041
5042     return TRUE;
5043   }
5044
5045   *empty = FALSE;
5046
5047   if (stream->sample_index == -1)
5048     stream->sample_index = 0;
5049
5050   GST_LOG_OBJECT (qtdemux, "segment active, index = %u of %u",
5051       stream->sample_index, stream->n_samples);
5052
5053   if (G_UNLIKELY (stream->sample_index >= stream->n_samples)) {
5054     if (!qtdemux->fragmented)
5055       goto eos;
5056
5057     GST_INFO_OBJECT (qtdemux, "out of samples, trying to add more");
5058     do {
5059       GstFlowReturn flow;
5060
5061       GST_OBJECT_LOCK (qtdemux);
5062       flow = qtdemux_add_fragmented_samples (qtdemux);
5063       GST_OBJECT_UNLOCK (qtdemux);
5064
5065       if (flow != GST_FLOW_OK)
5066         goto eos;
5067     }
5068     while (stream->sample_index >= stream->n_samples);
5069   }
5070
5071   if (!qtdemux_parse_samples (qtdemux, stream, stream->sample_index)) {
5072     GST_LOG_OBJECT (qtdemux, "Parsing of index %u failed!",
5073         stream->sample_index);
5074     return FALSE;
5075   }
5076
5077   /* now get the info for the sample we're at */
5078   sample = &stream->samples[stream->sample_index];
5079
5080   *dts = QTSAMPLE_DTS (stream, sample);
5081   *pts = QTSAMPLE_PTS (stream, sample);
5082   *offset = sample->offset;
5083   *size = sample->size;
5084   *duration = QTSAMPLE_DUR_DTS (stream, sample, *dts);
5085   *keyframe = QTSAMPLE_KEYFRAME (stream, sample);
5086
5087   return TRUE;
5088
5089   /* special cases */
5090 eos:
5091   {
5092     stream->time_position = GST_CLOCK_TIME_NONE;
5093     return FALSE;
5094   }
5095 }
5096
5097 /* move to the next sample in @stream.
5098  *
5099  * Moves to the next segment when needed.
5100  */
5101 static void
5102 gst_qtdemux_advance_sample (GstQTDemux * qtdemux, QtDemuxStream * stream)
5103 {
5104   QtDemuxSample *sample;
5105   QtDemuxSegment *segment;
5106
5107   /* get current segment */
5108   segment = &stream->segments[stream->segment_index];
5109
5110   if (G_UNLIKELY (QTSEGMENT_IS_EMPTY (segment))) {
5111     GST_DEBUG_OBJECT (qtdemux, "Empty segment, no samples to advance");
5112     goto next_segment;
5113   }
5114
5115   if (G_UNLIKELY (stream->sample_index >= stream->to_sample)) {
5116     /* Mark the stream as EOS */
5117     GST_DEBUG_OBJECT (qtdemux,
5118         "reached max allowed sample %u, mark EOS", stream->to_sample);
5119     stream->time_position = GST_CLOCK_TIME_NONE;
5120     return;
5121   }
5122
5123   /* move to next sample */
5124   stream->sample_index++;
5125   stream->offset_in_sample = 0;
5126
5127   /* reached the last sample, we need the next segment */
5128   if (G_UNLIKELY (stream->sample_index >= stream->n_samples))
5129     goto next_segment;
5130
5131   if (!qtdemux_parse_samples (qtdemux, stream, stream->sample_index)) {
5132     GST_LOG_OBJECT (qtdemux, "Parsing of index %u failed!",
5133         stream->sample_index);
5134     return;
5135   }
5136
5137   /* get next sample */
5138   sample = &stream->samples[stream->sample_index];
5139
5140   /* see if we are past the segment */
5141   if (G_UNLIKELY (QTSAMPLE_DTS (stream, sample) >= segment->media_stop))
5142     goto next_segment;
5143
5144   if (QTSAMPLE_DTS (stream, sample) >= segment->media_start) {
5145     /* inside the segment, update time_position, looks very familiar to
5146      * GStreamer segments, doesn't it? */
5147     stream->time_position =
5148         QTSAMPLE_DTS (stream, sample) - segment->media_start + segment->time;
5149   } else {
5150     /* not yet in segment, time does not yet increment. This means
5151      * that we are still prerolling keyframes to the decoder so it can
5152      * decode the first sample of the segment. */
5153     stream->time_position = segment->time;
5154   }
5155   return;
5156
5157   /* move to the next segment */
5158 next_segment:
5159   {
5160     GST_DEBUG_OBJECT (qtdemux, "segment %d ended ", stream->segment_index);
5161
5162     if (stream->segment_index == stream->n_segments - 1) {
5163       /* are we at the end of the last segment, we're EOS */
5164       stream->time_position = GST_CLOCK_TIME_NONE;
5165     } else {
5166       /* else we're only at the end of the current segment */
5167       stream->time_position = segment->stop_time;
5168     }
5169     /* make sure we select a new segment */
5170
5171     /* accumulate previous segments */
5172     if (GST_CLOCK_TIME_IS_VALID (stream->segment.stop))
5173       stream->accumulated_base +=
5174           (stream->segment.stop -
5175           stream->segment.start) / ABS (stream->segment.rate);
5176
5177     stream->segment_index = -1;
5178   }
5179 }
5180
5181 static void
5182 gst_qtdemux_sync_streams (GstQTDemux * demux)
5183 {
5184   GList *iter;
5185
5186   if (demux->n_streams <= 1)
5187     return;
5188
5189   for (iter = demux->active_streams; iter; iter = g_list_next (iter)) {
5190     QtDemuxStream *stream;
5191     GstClockTime end_time;
5192
5193     stream = QTDEMUX_STREAM (iter->data);
5194
5195     if (!stream->pad)
5196       continue;
5197
5198     /* TODO advance time on subtitle streams here, if any some day */
5199
5200     /* some clips/trailers may have unbalanced streams at the end,
5201      * so send EOS on shorter stream to prevent stalling others */
5202
5203     /* do not mess with EOS if SEGMENT seeking */
5204     if (demux->segment.flags & GST_SEEK_FLAG_SEGMENT)
5205       continue;
5206
5207     if (demux->pullbased) {
5208       /* loop mode is sample time based */
5209       if (!STREAM_IS_EOS (stream))
5210         continue;
5211     } else {
5212       /* push mode is byte position based */
5213       if (stream->n_samples &&
5214           stream->samples[stream->n_samples - 1].offset >= demux->offset)
5215         continue;
5216     }
5217
5218     if (stream->sent_eos)
5219       continue;
5220
5221     /* only act if some gap */
5222     end_time = stream->segments[stream->n_segments - 1].stop_time;
5223     GST_LOG_OBJECT (demux, "current position: %" GST_TIME_FORMAT
5224         ", stream end: %" GST_TIME_FORMAT,
5225         GST_TIME_ARGS (demux->segment.position), GST_TIME_ARGS (end_time));
5226     if (GST_CLOCK_TIME_IS_VALID (end_time)
5227         && (end_time + 2 * GST_SECOND < demux->segment.position)) {
5228       GstEvent *event;
5229
5230       GST_DEBUG_OBJECT (demux, "sending EOS for stream %s",
5231           GST_PAD_NAME (stream->pad));
5232       stream->sent_eos = TRUE;
5233       event = gst_event_new_eos ();
5234       if (demux->segment_seqnum != GST_SEQNUM_INVALID)
5235         gst_event_set_seqnum (event, demux->segment_seqnum);
5236       gst_pad_push_event (stream->pad, event);
5237     }
5238   }
5239 }
5240
5241 /* EOS and NOT_LINKED need to be combined. This means that we return:
5242  *
5243  *  GST_FLOW_NOT_LINKED: when all pads NOT_LINKED.
5244  *  GST_FLOW_EOS: when all pads EOS or NOT_LINKED.
5245  */
5246 static GstFlowReturn
5247 gst_qtdemux_combine_flows (GstQTDemux * demux, QtDemuxStream * stream,
5248     GstFlowReturn ret)
5249 {
5250   GST_LOG_OBJECT (demux, "flow return: %s", gst_flow_get_name (ret));
5251
5252   if (stream->pad)
5253     ret = gst_flow_combiner_update_pad_flow (demux->flowcombiner, stream->pad,
5254         ret);
5255   else
5256     ret = gst_flow_combiner_update_flow (demux->flowcombiner, ret);
5257
5258   GST_LOG_OBJECT (demux, "combined flow return: %s", gst_flow_get_name (ret));
5259   return ret;
5260 }
5261
5262 /* the input buffer metadata must be writable. Returns NULL when the buffer is
5263  * completely clipped
5264  *
5265  * Should be used only with raw buffers */
5266 static GstBuffer *
5267 gst_qtdemux_clip_buffer (GstQTDemux * qtdemux, QtDemuxStream * stream,
5268     GstBuffer * buf)
5269 {
5270   guint64 start, stop, cstart, cstop, diff;
5271   GstClockTime pts, duration;
5272   gsize size, osize;
5273   gint num_rate, denom_rate;
5274   gint frame_size;
5275   gboolean clip_data;
5276   guint offset;
5277
5278   osize = size = gst_buffer_get_size (buf);
5279   offset = 0;
5280
5281   /* depending on the type, setup the clip parameters */
5282   if (stream->subtype == FOURCC_soun) {
5283     frame_size = CUR_STREAM (stream)->bytes_per_frame;
5284     num_rate = GST_SECOND;
5285     denom_rate = (gint) CUR_STREAM (stream)->rate;
5286     clip_data = TRUE;
5287   } else if (stream->subtype == FOURCC_vide) {
5288     frame_size = size;
5289     num_rate = CUR_STREAM (stream)->fps_n;
5290     denom_rate = CUR_STREAM (stream)->fps_d;
5291     clip_data = FALSE;
5292   } else
5293     goto wrong_type;
5294
5295   if (frame_size <= 0)
5296     goto bad_frame_size;
5297
5298   /* we can only clip if we have a valid pts */
5299   pts = GST_BUFFER_PTS (buf);
5300   if (G_UNLIKELY (!GST_CLOCK_TIME_IS_VALID (pts)))
5301     goto no_pts;
5302
5303   duration = GST_BUFFER_DURATION (buf);
5304
5305   if (G_UNLIKELY (!GST_CLOCK_TIME_IS_VALID (duration))) {
5306     duration =
5307         gst_util_uint64_scale_int (size / frame_size, num_rate, denom_rate);
5308   }
5309
5310   start = pts;
5311   stop = start + duration;
5312
5313   if (G_UNLIKELY (!gst_segment_clip (&stream->segment,
5314               GST_FORMAT_TIME, start, stop, &cstart, &cstop)))
5315     goto clipped;
5316
5317   /* see if some clipping happened */
5318   diff = cstart - start;
5319   if (diff > 0) {
5320     pts += diff;
5321     duration -= diff;
5322
5323     if (clip_data) {
5324       /* bring clipped time to samples and to bytes */
5325       diff = gst_util_uint64_scale_int (diff, denom_rate, num_rate);
5326       diff *= frame_size;
5327
5328       GST_DEBUG_OBJECT (qtdemux,
5329           "clipping start to %" GST_TIME_FORMAT " %"
5330           G_GUINT64_FORMAT " bytes", GST_TIME_ARGS (cstart), diff);
5331
5332       offset = diff;
5333       size -= diff;
5334     }
5335   }
5336   diff = stop - cstop;
5337   if (diff > 0) {
5338     duration -= diff;
5339
5340     if (clip_data) {
5341       /* bring clipped time to samples and then to bytes */
5342       diff = gst_util_uint64_scale_int (diff, denom_rate, num_rate);
5343       diff *= frame_size;
5344       GST_DEBUG_OBJECT (qtdemux,
5345           "clipping stop to %" GST_TIME_FORMAT " %" G_GUINT64_FORMAT
5346           " bytes", GST_TIME_ARGS (cstop), diff);
5347       size -= diff;
5348     }
5349   }
5350
5351   if (offset != 0 || size != osize)
5352     gst_buffer_resize (buf, offset, size);
5353
5354   GST_BUFFER_DTS (buf) = GST_CLOCK_TIME_NONE;
5355   GST_BUFFER_PTS (buf) = pts;
5356   GST_BUFFER_DURATION (buf) = duration;
5357
5358   return buf;
5359
5360   /* dropped buffer */
5361 wrong_type:
5362   {
5363     GST_DEBUG_OBJECT (qtdemux, "unknown stream type");
5364     return buf;
5365   }
5366 bad_frame_size:
5367   {
5368     GST_DEBUG_OBJECT (qtdemux, "bad frame size");
5369     return buf;
5370   }
5371 no_pts:
5372   {
5373     GST_DEBUG_OBJECT (qtdemux, "no pts on buffer");
5374     return buf;
5375   }
5376 clipped:
5377   {
5378     GST_DEBUG_OBJECT (qtdemux, "clipped buffer");
5379     gst_buffer_unref (buf);
5380     return NULL;
5381   }
5382 }
5383
5384 static GstBuffer *
5385 gst_qtdemux_align_buffer (GstQTDemux * demux,
5386     GstBuffer * buffer, gsize alignment)
5387 {
5388   GstMapInfo map;
5389
5390   gst_buffer_map (buffer, &map, GST_MAP_READ);
5391
5392   if (map.size < sizeof (guintptr)) {
5393     gst_buffer_unmap (buffer, &map);
5394     return buffer;
5395   }
5396
5397   if (((guintptr) map.data) & (alignment - 1)) {
5398     GstBuffer *new_buffer;
5399     GstAllocationParams params = { 0, alignment - 1, 0, 0, };
5400
5401     new_buffer = gst_buffer_new_allocate (NULL,
5402         gst_buffer_get_size (buffer), &params);
5403
5404     /* Copy data "by hand", so ensure alignment is kept: */
5405     gst_buffer_fill (new_buffer, 0, map.data, map.size);
5406
5407     gst_buffer_copy_into (new_buffer, buffer, GST_BUFFER_COPY_METADATA, 0, -1);
5408     GST_DEBUG_OBJECT (demux,
5409         "We want output aligned on %" G_GSIZE_FORMAT ", reallocated",
5410         alignment);
5411
5412     gst_buffer_unmap (buffer, &map);
5413     gst_buffer_unref (buffer);
5414
5415     return new_buffer;
5416   }
5417
5418   gst_buffer_unmap (buffer, &map);
5419   return buffer;
5420 }
5421
5422 static guint8 *
5423 convert_to_ccdata (const guint8 * ccpair, guint8 ccpair_size, guint field,
5424     gsize * res)
5425 {
5426   guint8 *storage;
5427   gsize i;
5428
5429   /* We are converting from pairs to triplets */
5430   *res = ccpair_size / 2 * 3;
5431   storage = g_malloc (*res);
5432   for (i = 0; i * 2 < ccpair_size; i += 1) {
5433     if (field == 1)
5434       storage[i * 3] = 0xfc;
5435     else
5436       storage[i * 3] = 0xfd;
5437     storage[i * 3 + 1] = ccpair[i * 2];
5438     storage[i * 3 + 2] = ccpair[i * 2 + 1];
5439   }
5440
5441   return storage;
5442 }
5443
5444 static guint8 *
5445 extract_cc_from_data (QtDemuxStream * stream, const guint8 * data, gsize size,
5446     gsize * cclen)
5447 {
5448   guint8 *res = NULL;
5449   guint32 atom_length, fourcc;
5450   QtDemuxStreamStsdEntry *stsd_entry;
5451
5452   GST_MEMDUMP ("caption atom", data, size);
5453
5454   /* There might be multiple atoms */
5455
5456   *cclen = 0;
5457   if (size < 8)
5458     goto invalid_cdat;
5459   atom_length = QT_UINT32 (data);
5460   fourcc = QT_FOURCC (data + 4);
5461   if (G_UNLIKELY (atom_length > size || atom_length == 8))
5462     goto invalid_cdat;
5463
5464   GST_DEBUG_OBJECT (stream->pad, "here");
5465
5466   /* Check if we have somethig compatible */
5467   stsd_entry = CUR_STREAM (stream);
5468   switch (stsd_entry->fourcc) {
5469     case FOURCC_c608:{
5470       guint8 *cdat = NULL, *cdt2 = NULL;
5471       gsize cdat_size = 0, cdt2_size = 0;
5472       /* Should be cdat or cdt2 */
5473       if (fourcc != FOURCC_cdat && fourcc != FOURCC_cdt2) {
5474         GST_WARNING_OBJECT (stream->pad,
5475             "Unknown data atom (%" GST_FOURCC_FORMAT ") for CEA608",
5476             GST_FOURCC_ARGS (fourcc));
5477         goto invalid_cdat;
5478       }
5479
5480       /* Convert to cc_data triplet */
5481       if (fourcc == FOURCC_cdat)
5482         cdat = convert_to_ccdata (data + 8, atom_length - 8, 1, &cdat_size);
5483       else
5484         cdt2 = convert_to_ccdata (data + 8, atom_length - 8, 2, &cdt2_size);
5485       GST_DEBUG_OBJECT (stream->pad, "size:%" G_GSIZE_FORMAT " atom_length:%u",
5486           size, atom_length);
5487
5488       /* Check for another atom ? */
5489       if (size > atom_length + 8) {
5490         guint32 new_atom_length = QT_UINT32 (data + atom_length);
5491         if (size >= atom_length + new_atom_length) {
5492           fourcc = QT_FOURCC (data + atom_length + 4);
5493           if (fourcc == FOURCC_cdat) {
5494             if (cdat == NULL)
5495               cdat =
5496                   convert_to_ccdata (data + atom_length + 8,
5497                   new_atom_length - 8, 1, &cdat_size);
5498             else
5499               GST_WARNING_OBJECT (stream->pad,
5500                   "Got multiple [cdat] atoms in a c608 sample. This is unsupported for now. Please file a bug");
5501           } else {
5502             if (cdt2 == NULL)
5503               cdt2 =
5504                   convert_to_ccdata (data + atom_length + 8,
5505                   new_atom_length - 8, 2, &cdt2_size);
5506             else
5507               GST_WARNING_OBJECT (stream->pad,
5508                   "Got multiple [cdt2] atoms in a c608 sample. This is unsupported for now. Please file a bug");
5509           }
5510         }
5511       }
5512
5513       *cclen = cdat_size + cdt2_size;
5514       res = g_malloc (*cclen);
5515       if (cdat_size)
5516         memcpy (res, cdat, cdat_size);
5517       if (cdt2_size)
5518         memcpy (res + cdat_size, cdt2, cdt2_size);
5519       g_free (cdat);
5520       g_free (cdt2);
5521     }
5522       break;
5523     case FOURCC_c708:
5524       if (fourcc != FOURCC_ccdp) {
5525         GST_WARNING_OBJECT (stream->pad,
5526             "Unknown data atom (%" GST_FOURCC_FORMAT ") for CEA708",
5527             GST_FOURCC_ARGS (fourcc));
5528         goto invalid_cdat;
5529       }
5530       *cclen = atom_length - 8;
5531       res = g_memdup (data + 8, *cclen);
5532       break;
5533     default:
5534       /* Keep this here in case other closed caption formats are added */
5535       g_assert_not_reached ();
5536       break;
5537   }
5538
5539   GST_MEMDUMP ("Output", res, *cclen);
5540   return res;
5541
5542   /* Errors */
5543 invalid_cdat:
5544   GST_WARNING ("[cdat] atom is too small or invalid");
5545   return NULL;
5546 }
5547
5548 /* the input buffer metadata must be writable,
5549  * but time/duration etc not yet set and need not be preserved */
5550 static GstBuffer *
5551 gst_qtdemux_process_buffer (GstQTDemux * qtdemux, QtDemuxStream * stream,
5552     GstBuffer * buf)
5553 {
5554   GstMapInfo map;
5555   guint nsize = 0;
5556   gchar *str;
5557
5558   /* not many cases for now */
5559   if (G_UNLIKELY (CUR_STREAM (stream)->fourcc == FOURCC_mp4s)) {
5560     /* send a one time dvd clut event */
5561     if (stream->pending_event && stream->pad)
5562       gst_pad_push_event (stream->pad, stream->pending_event);
5563     stream->pending_event = NULL;
5564   }
5565
5566   if (G_UNLIKELY (stream->subtype != FOURCC_text
5567           && stream->subtype != FOURCC_sbtl &&
5568           stream->subtype != FOURCC_subp && stream->subtype != FOURCC_clcp)) {
5569     return buf;
5570   }
5571
5572   gst_buffer_map (buf, &map, GST_MAP_READ);
5573
5574   /* empty buffer is sent to terminate previous subtitle */
5575   if (map.size <= 2) {
5576     gst_buffer_unmap (buf, &map);
5577     gst_buffer_unref (buf);
5578     return NULL;
5579   }
5580   if (stream->subtype == FOURCC_subp) {
5581     /* That's all the processing needed for subpictures */
5582     gst_buffer_unmap (buf, &map);
5583     return buf;
5584   }
5585
5586   if (stream->subtype == FOURCC_clcp) {
5587     guint8 *cc;
5588     gsize cclen = 0;
5589     /* For closed caption, we need to extract the information from the
5590      * [cdat],[cdt2] or [ccdp] atom */
5591     cc = extract_cc_from_data (stream, map.data, map.size, &cclen);
5592     gst_buffer_unmap (buf, &map);
5593     gst_buffer_unref (buf);
5594     if (cc) {
5595       buf = _gst_buffer_new_wrapped (cc, cclen, g_free);
5596     } else {
5597       /* Conversion failed or there's nothing */
5598       buf = NULL;
5599     }
5600     return buf;
5601   }
5602
5603   nsize = GST_READ_UINT16_BE (map.data);
5604   nsize = MIN (nsize, map.size - 2);
5605
5606   GST_LOG_OBJECT (qtdemux, "3GPP timed text subtitle: %d/%" G_GSIZE_FORMAT "",
5607       nsize, map.size);
5608
5609   /* takes care of UTF-8 validation or UTF-16 recognition,
5610    * no other encoding expected */
5611   str = gst_tag_freeform_string_to_utf8 ((gchar *) map.data + 2, nsize, NULL);
5612   gst_buffer_unmap (buf, &map);
5613   if (str) {
5614     gst_buffer_unref (buf);
5615     buf = _gst_buffer_new_wrapped (str, strlen (str), g_free);
5616   } else {
5617     /* this should not really happen unless the subtitle is corrupted */
5618     gst_buffer_unref (buf);
5619     buf = NULL;
5620   }
5621
5622   /* FIXME ? convert optional subsequent style info to markup */
5623
5624   return buf;
5625 }
5626
5627 /* Sets a buffer's attributes properly and pushes it downstream.
5628  * Also checks for additional actions and custom processing that may
5629  * need to be done first.
5630  */
5631 static GstFlowReturn
5632 gst_qtdemux_decorate_and_push_buffer (GstQTDemux * qtdemux,
5633     QtDemuxStream * stream, GstBuffer * buf,
5634     GstClockTime dts, GstClockTime pts, GstClockTime duration,
5635     gboolean keyframe, GstClockTime position, guint64 byte_position)
5636 {
5637   GstFlowReturn ret = GST_FLOW_OK;
5638
5639   /* offset the timestamps according to the edit list */
5640
5641   if (G_UNLIKELY (CUR_STREAM (stream)->fourcc == FOURCC_rtsp)) {
5642     gchar *url;
5643     GstMapInfo map;
5644
5645     gst_buffer_map (buf, &map, GST_MAP_READ);
5646     url = g_strndup ((gchar *) map.data, map.size);
5647     gst_buffer_unmap (buf, &map);
5648     if (url != NULL && strlen (url) != 0) {
5649       /* we have RTSP redirect now */
5650       gst_element_post_message (GST_ELEMENT_CAST (qtdemux),
5651           gst_message_new_element (GST_OBJECT_CAST (qtdemux),
5652               gst_structure_new ("redirect",
5653                   "new-location", G_TYPE_STRING, url, NULL)));
5654       qtdemux->posted_redirect = TRUE;
5655     } else {
5656       GST_WARNING_OBJECT (qtdemux, "Redirect URI of stream is empty, not "
5657           "posting");
5658     }
5659     g_free (url);
5660   }
5661
5662   /* position reporting */
5663   if (qtdemux->segment.rate >= 0) {
5664     qtdemux->segment.position = position;
5665     gst_qtdemux_sync_streams (qtdemux);
5666   }
5667
5668   if (G_UNLIKELY (!stream->pad)) {
5669     GST_DEBUG_OBJECT (qtdemux, "No output pad for stream, ignoring");
5670     gst_buffer_unref (buf);
5671     goto exit;
5672   }
5673
5674   /* send out pending buffers */
5675   while (stream->buffers) {
5676     GstBuffer *buffer = (GstBuffer *) stream->buffers->data;
5677
5678     if (G_UNLIKELY (stream->discont)) {
5679       GST_LOG_OBJECT (qtdemux, "marking discont buffer");
5680       GST_BUFFER_FLAG_SET (buffer, GST_BUFFER_FLAG_DISCONT);
5681       stream->discont = FALSE;
5682     } else {
5683       GST_BUFFER_FLAG_UNSET (buf, GST_BUFFER_FLAG_DISCONT);
5684     }
5685
5686     if (stream->alignment > 1)
5687       buffer = gst_qtdemux_align_buffer (qtdemux, buffer, stream->alignment);
5688     gst_pad_push (stream->pad, buffer);
5689
5690     stream->buffers = g_slist_delete_link (stream->buffers, stream->buffers);
5691   }
5692
5693   /* we're going to modify the metadata */
5694   buf = gst_buffer_make_writable (buf);
5695
5696   if (G_UNLIKELY (stream->need_process))
5697     buf = gst_qtdemux_process_buffer (qtdemux, stream, buf);
5698
5699   if (!buf) {
5700     goto exit;
5701   }
5702
5703   GST_BUFFER_DTS (buf) = dts;
5704   GST_BUFFER_PTS (buf) = pts;
5705   GST_BUFFER_DURATION (buf) = duration;
5706   GST_BUFFER_OFFSET (buf) = -1;
5707   GST_BUFFER_OFFSET_END (buf) = -1;
5708
5709   if (G_UNLIKELY (CUR_STREAM (stream)->rgb8_palette))
5710     gst_buffer_append_memory (buf,
5711         gst_memory_ref (CUR_STREAM (stream)->rgb8_palette));
5712
5713   if (G_UNLIKELY (CUR_STREAM (stream)->padding)) {
5714     gst_buffer_resize (buf, CUR_STREAM (stream)->padding, -1);
5715   }
5716 #if 0
5717   if (G_UNLIKELY (qtdemux->element_index)) {
5718     GstClockTime stream_time;
5719
5720     stream_time =
5721         gst_segment_to_stream_time (&stream->segment, GST_FORMAT_TIME,
5722         timestamp);
5723     if (GST_CLOCK_TIME_IS_VALID (stream_time)) {
5724       GST_LOG_OBJECT (qtdemux,
5725           "adding association %" GST_TIME_FORMAT "-> %"
5726           G_GUINT64_FORMAT, GST_TIME_ARGS (stream_time), byte_position);
5727       gst_index_add_association (qtdemux->element_index,
5728           qtdemux->index_id,
5729           keyframe ? GST_ASSOCIATION_FLAG_KEY_UNIT :
5730           GST_ASSOCIATION_FLAG_DELTA_UNIT, GST_FORMAT_TIME, stream_time,
5731           GST_FORMAT_BYTES, byte_position, NULL);
5732     }
5733   }
5734 #endif
5735
5736   if (stream->need_clip)
5737     buf = gst_qtdemux_clip_buffer (qtdemux, stream, buf);
5738
5739   if (G_UNLIKELY (buf == NULL))
5740     goto exit;
5741
5742   if (G_UNLIKELY (stream->discont)) {
5743     GST_LOG_OBJECT (qtdemux, "marking discont buffer");
5744     GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_DISCONT);
5745     stream->discont = FALSE;
5746   } else {
5747     GST_BUFFER_FLAG_UNSET (buf, GST_BUFFER_FLAG_DISCONT);
5748   }
5749
5750   if (!keyframe) {
5751     GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_DELTA_UNIT);
5752     stream->on_keyframe = FALSE;
5753   } else {
5754     stream->on_keyframe = TRUE;
5755   }
5756
5757
5758   GST_LOG_OBJECT (qtdemux,
5759       "Pushing buffer with dts %" GST_TIME_FORMAT ", pts %" GST_TIME_FORMAT
5760       ", duration %" GST_TIME_FORMAT " on pad %s", GST_TIME_ARGS (dts),
5761       GST_TIME_ARGS (pts), GST_TIME_ARGS (duration),
5762       GST_PAD_NAME (stream->pad));
5763
5764   if (stream->protected && stream->protection_scheme_type == FOURCC_cenc) {
5765     GstStructure *crypto_info;
5766     QtDemuxCencSampleSetInfo *info =
5767         (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
5768     gint index;
5769     GstEvent *event;
5770
5771     while ((event = g_queue_pop_head (&stream->protection_scheme_event_queue))) {
5772       gst_pad_push_event (stream->pad, event);
5773     }
5774
5775     if (info->crypto_info == NULL) {
5776       GST_DEBUG_OBJECT (qtdemux, "cenc metadata hasn't been parsed yet");
5777       gst_buffer_unref (buf);
5778       goto exit;
5779     }
5780
5781     /* The end of the crypto_info array matches our n_samples position,
5782      * so count backward from there */
5783     index = stream->sample_index - stream->n_samples + info->crypto_info->len;
5784     if (G_LIKELY (index >= 0 && index < info->crypto_info->len)) {
5785       /* steal structure from array */
5786       crypto_info = g_ptr_array_index (info->crypto_info, index);
5787       g_ptr_array_index (info->crypto_info, index) = NULL;
5788       GST_LOG_OBJECT (qtdemux, "attaching cenc metadata [%u/%u]", index,
5789           info->crypto_info->len);
5790       if (!crypto_info || !gst_buffer_add_protection_meta (buf, crypto_info))
5791         GST_ERROR_OBJECT (qtdemux, "failed to attach cenc metadata to buffer");
5792     } else {
5793       GST_INFO_OBJECT (qtdemux, "No crypto info with index %d and sample %d",
5794           index, stream->sample_index);
5795     }
5796   }
5797
5798   if (stream->alignment > 1)
5799     buf = gst_qtdemux_align_buffer (qtdemux, buf, stream->alignment);
5800
5801   ret = gst_pad_push (stream->pad, buf);
5802
5803   if (GST_CLOCK_TIME_IS_VALID (pts) && GST_CLOCK_TIME_IS_VALID (duration)) {
5804     /* mark position in stream, we'll need this to know when to send GAP event */
5805     stream->segment.position = pts + duration;
5806   }
5807
5808 exit:
5809   return ret;
5810 }
5811
5812 static const QtDemuxRandomAccessEntry *
5813 gst_qtdemux_stream_seek_fragment (GstQTDemux * qtdemux, QtDemuxStream * stream,
5814     GstClockTime pos, gboolean after)
5815 {
5816   QtDemuxRandomAccessEntry *entries = stream->ra_entries;
5817   guint n_entries = stream->n_ra_entries;
5818   guint i;
5819
5820   /* we assume the table is sorted */
5821   for (i = 0; i < n_entries; ++i) {
5822     if (entries[i].ts > pos)
5823       break;
5824   }
5825
5826   /* FIXME: maybe save first moof_offset somewhere instead, but for now it's
5827    * probably okay to assume that the index lists the very first fragment */
5828   if (i == 0)
5829     return &entries[0];
5830
5831   if (after)
5832     return &entries[i];
5833   else
5834     return &entries[i - 1];
5835 }
5836
5837 static gboolean
5838 gst_qtdemux_do_fragmented_seek (GstQTDemux * qtdemux)
5839 {
5840   const QtDemuxRandomAccessEntry *best_entry = NULL;
5841   GList *iter;
5842
5843   GST_OBJECT_LOCK (qtdemux);
5844
5845   g_assert (qtdemux->n_streams > 0);
5846
5847   /* first see if we can determine where to go to using mfra,
5848    * before we start clearing things */
5849   for (iter = qtdemux->active_streams; iter; iter = g_list_next (iter)) {
5850     const QtDemuxRandomAccessEntry *entry;
5851     QtDemuxStream *stream;
5852     gboolean is_audio_or_video;
5853
5854     stream = QTDEMUX_STREAM (iter->data);
5855
5856     if (stream->ra_entries == NULL)
5857       continue;
5858
5859     if (stream->subtype == FOURCC_vide || stream->subtype == FOURCC_soun)
5860       is_audio_or_video = TRUE;
5861     else
5862       is_audio_or_video = FALSE;
5863
5864     entry =
5865         gst_qtdemux_stream_seek_fragment (qtdemux, stream,
5866         stream->time_position, !is_audio_or_video);
5867
5868     GST_INFO_OBJECT (stream->pad, "%" GST_TIME_FORMAT " at offset "
5869         "%" G_GUINT64_FORMAT, GST_TIME_ARGS (entry->ts), entry->moof_offset);
5870
5871     stream->pending_seek = entry;
5872
5873     /* decide position to jump to just based on audio/video tracks, not subs */
5874     if (!is_audio_or_video)
5875       continue;
5876
5877     if (best_entry == NULL || entry->moof_offset < best_entry->moof_offset)
5878       best_entry = entry;
5879   }
5880
5881   /* no luck, will handle seek otherwise */
5882   if (best_entry == NULL) {
5883     GST_OBJECT_UNLOCK (qtdemux);
5884     return FALSE;
5885   }
5886
5887   /* ok, now we can prepare for processing as of located moof */
5888   for (iter = qtdemux->active_streams; iter; iter = g_list_next (iter)) {
5889     QtDemuxStream *stream;
5890
5891     stream = QTDEMUX_STREAM (iter->data);
5892
5893     g_free (stream->samples);
5894     stream->samples = NULL;
5895     stream->n_samples = 0;
5896     stream->stbl_index = -1;    /* no samples have yet been parsed */
5897     stream->sample_index = -1;
5898
5899     if (stream->protection_scheme_info) {
5900       /* Clear out any old cenc crypto info entries as we'll move to a new moof */
5901       if (stream->protection_scheme_type == FOURCC_cenc) {
5902         QtDemuxCencSampleSetInfo *info =
5903             (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
5904         if (info->crypto_info) {
5905           g_ptr_array_free (info->crypto_info, TRUE);
5906           info->crypto_info = NULL;
5907         }
5908       }
5909     }
5910   }
5911
5912   GST_INFO_OBJECT (qtdemux, "seek to %" GST_TIME_FORMAT ", best fragment "
5913       "moof offset: %" G_GUINT64_FORMAT ", ts %" GST_TIME_FORMAT,
5914       GST_TIME_ARGS (QTDEMUX_FIRST_STREAM (qtdemux)->time_position),
5915       best_entry->moof_offset, GST_TIME_ARGS (best_entry->ts));
5916
5917   qtdemux->moof_offset = best_entry->moof_offset;
5918
5919   qtdemux_add_fragmented_samples (qtdemux);
5920
5921   GST_OBJECT_UNLOCK (qtdemux);
5922   return TRUE;
5923 }
5924
5925 static GstFlowReturn
5926 gst_qtdemux_loop_state_movie (GstQTDemux * qtdemux)
5927 {
5928   GstFlowReturn ret = GST_FLOW_OK;
5929   GstBuffer *buf = NULL;
5930   QtDemuxStream *stream, *target_stream = NULL;
5931   GstClockTime min_time;
5932   guint64 offset = 0;
5933   GstClockTime dts = GST_CLOCK_TIME_NONE;
5934   GstClockTime pts = GST_CLOCK_TIME_NONE;
5935   GstClockTime duration = 0;
5936   gboolean keyframe = FALSE;
5937   guint sample_size = 0;
5938   gboolean empty = 0;
5939   guint size;
5940   GList *iter;
5941
5942   gst_qtdemux_push_pending_newsegment (qtdemux);
5943
5944   if (qtdemux->fragmented_seek_pending) {
5945     GST_INFO_OBJECT (qtdemux, "pending fragmented seek");
5946     if (gst_qtdemux_do_fragmented_seek (qtdemux)) {
5947       GST_INFO_OBJECT (qtdemux, "fragmented seek done!");
5948       qtdemux->fragmented_seek_pending = FALSE;
5949     } else {
5950       GST_INFO_OBJECT (qtdemux, "fragmented seek still pending");
5951     }
5952   }
5953
5954   /* Figure out the next stream sample to output, min_time is expressed in
5955    * global time and runs over the edit list segments. */
5956   min_time = G_MAXUINT64;
5957   for (iter = qtdemux->active_streams; iter; iter = g_list_next (iter)) {
5958     GstClockTime position;
5959
5960     stream = QTDEMUX_STREAM (iter->data);
5961     position = stream->time_position;
5962
5963     /* position of -1 is EOS */
5964     if (position != GST_CLOCK_TIME_NONE && position < min_time) {
5965       min_time = position;
5966       target_stream = stream;
5967     }
5968   }
5969   /* all are EOS */
5970   if (G_UNLIKELY (target_stream == NULL)) {
5971     GST_DEBUG_OBJECT (qtdemux, "all streams are EOS");
5972     goto eos;
5973   }
5974
5975   /* check for segment end */
5976   if (G_UNLIKELY (qtdemux->segment.stop != -1
5977           && ((qtdemux->segment.rate >= 0 && qtdemux->segment.stop <= min_time)
5978               || (qtdemux->segment.rate < 0
5979                   && qtdemux->segment.start > min_time))
5980           && target_stream->on_keyframe)) {
5981     GST_DEBUG_OBJECT (qtdemux, "we reached the end of our segment.");
5982     target_stream->time_position = GST_CLOCK_TIME_NONE;
5983     goto eos_stream;
5984   }
5985
5986   /* gap events for subtitle streams */
5987   for (iter = qtdemux->active_streams; iter; iter = g_list_next (iter)) {
5988     stream = QTDEMUX_STREAM (iter->data);
5989     if (stream->pad && (stream->subtype == FOURCC_subp
5990             || stream->subtype == FOURCC_text
5991             || stream->subtype == FOURCC_sbtl)) {
5992       /* send one second gap events until the stream catches up */
5993       /* gaps can only be sent after segment is activated (segment.stop is no longer -1) */
5994       while (GST_CLOCK_TIME_IS_VALID (stream->segment.stop) &&
5995           GST_CLOCK_TIME_IS_VALID (stream->segment.position) &&
5996           stream->segment.position + GST_SECOND < min_time) {
5997         GstEvent *gap =
5998             gst_event_new_gap (stream->segment.position, GST_SECOND);
5999         gst_pad_push_event (stream->pad, gap);
6000         stream->segment.position += GST_SECOND;
6001       }
6002     }
6003   }
6004
6005   stream = target_stream;
6006   /* fetch info for the current sample of this stream */
6007   if (G_UNLIKELY (!gst_qtdemux_prepare_current_sample (qtdemux, stream, &empty,
6008               &offset, &sample_size, &dts, &pts, &duration, &keyframe)))
6009     goto eos_stream;
6010
6011   gst_qtdemux_stream_check_and_change_stsd_index (qtdemux, stream);
6012   if (stream->new_caps) {
6013     gst_qtdemux_configure_stream (qtdemux, stream);
6014     qtdemux_do_allocation (qtdemux, stream);
6015   }
6016
6017   /* If we're doing a keyframe-only trickmode, only push keyframes on video streams */
6018   if (G_UNLIKELY (qtdemux->
6019           segment.flags & GST_SEGMENT_FLAG_TRICKMODE_KEY_UNITS)) {
6020     if (stream->subtype == FOURCC_vide && !keyframe) {
6021       GST_LOG_OBJECT (qtdemux, "Skipping non-keyframe on track-id %u",
6022           stream->track_id);
6023       goto next;
6024     }
6025   }
6026
6027   GST_DEBUG_OBJECT (qtdemux,
6028       "pushing from track-id %u, empty %d offset %" G_GUINT64_FORMAT
6029       ", size %d, dts=%" GST_TIME_FORMAT ", pts=%" GST_TIME_FORMAT
6030       ", duration %" GST_TIME_FORMAT, stream->track_id, empty, offset,
6031       sample_size, GST_TIME_ARGS (dts), GST_TIME_ARGS (pts),
6032       GST_TIME_ARGS (duration));
6033
6034   if (G_UNLIKELY (empty)) {
6035     /* empty segment, push a gap if there's a second or more
6036      * difference and move to the next one */
6037     if ((pts + duration - stream->segment.position) >= GST_SECOND)
6038       gst_pad_push_event (stream->pad, gst_event_new_gap (pts, duration));
6039     stream->segment.position = pts + duration;
6040     goto next;
6041   }
6042
6043   /* hmm, empty sample, skip and move to next sample */
6044   if (G_UNLIKELY (sample_size <= 0))
6045     goto next;
6046
6047   /* last pushed sample was out of boundary, goto next sample */
6048   if (G_UNLIKELY (GST_PAD_LAST_FLOW_RETURN (stream->pad) == GST_FLOW_EOS))
6049     goto next;
6050
6051   if (stream->max_buffer_size == 0 || sample_size <= stream->max_buffer_size) {
6052     size = sample_size;
6053   } else {
6054     GST_DEBUG_OBJECT (qtdemux,
6055         "size %d larger than stream max_buffer_size %d, trimming",
6056         sample_size, stream->max_buffer_size);
6057     size =
6058         MIN (sample_size - stream->offset_in_sample, stream->max_buffer_size);
6059   }
6060
6061   if (qtdemux->cenc_aux_info_offset > 0) {
6062     GstMapInfo map;
6063     GstByteReader br;
6064     GstBuffer *aux_info = NULL;
6065
6066     /* pull the data stored before the sample */
6067     ret =
6068         gst_qtdemux_pull_atom (qtdemux, qtdemux->offset,
6069         offset + stream->offset_in_sample - qtdemux->offset, &aux_info);
6070     if (G_UNLIKELY (ret != GST_FLOW_OK))
6071       goto beach;
6072     gst_buffer_map (aux_info, &map, GST_MAP_READ);
6073     GST_DEBUG_OBJECT (qtdemux, "parsing cenc auxiliary info");
6074     gst_byte_reader_init (&br, map.data + 8, map.size);
6075     if (!qtdemux_parse_cenc_aux_info (qtdemux, stream, &br,
6076             qtdemux->cenc_aux_info_sizes, qtdemux->cenc_aux_sample_count)) {
6077       GST_ERROR_OBJECT (qtdemux, "failed to parse cenc auxiliary info");
6078       gst_buffer_unmap (aux_info, &map);
6079       gst_buffer_unref (aux_info);
6080       ret = GST_FLOW_ERROR;
6081       goto beach;
6082     }
6083     gst_buffer_unmap (aux_info, &map);
6084     gst_buffer_unref (aux_info);
6085   }
6086
6087   GST_LOG_OBJECT (qtdemux, "reading %d bytes @ %" G_GUINT64_FORMAT, size,
6088       offset);
6089
6090   if (stream->use_allocator) {
6091     /* if we have a per-stream allocator, use it */
6092     buf = gst_buffer_new_allocate (stream->allocator, size, &stream->params);
6093   }
6094
6095   ret = gst_qtdemux_pull_atom (qtdemux, offset + stream->offset_in_sample,
6096       size, &buf);
6097   if (G_UNLIKELY (ret != GST_FLOW_OK))
6098     goto beach;
6099
6100   if (size != sample_size) {
6101     pts += gst_util_uint64_scale_int (GST_SECOND,
6102         stream->offset_in_sample / CUR_STREAM (stream)->bytes_per_frame,
6103         stream->timescale);
6104     dts +=
6105         gst_util_uint64_scale_int (GST_SECOND,
6106         stream->offset_in_sample / CUR_STREAM (stream)->bytes_per_frame,
6107         stream->timescale);
6108     duration =
6109         gst_util_uint64_scale_int (GST_SECOND,
6110         size / CUR_STREAM (stream)->bytes_per_frame, stream->timescale);
6111   }
6112
6113   ret = gst_qtdemux_decorate_and_push_buffer (qtdemux, stream, buf,
6114       dts, pts, duration, keyframe, min_time, offset);
6115
6116   if (size != sample_size) {
6117     QtDemuxSample *sample = &stream->samples[stream->sample_index];
6118     QtDemuxSegment *segment = &stream->segments[stream->segment_index];
6119
6120     GstClockTime time_position = QTSTREAMTIME_TO_GSTTIME (stream,
6121         sample->timestamp +
6122         stream->offset_in_sample / CUR_STREAM (stream)->bytes_per_frame);
6123     if (time_position >= segment->media_start) {
6124       /* inside the segment, update time_position, looks very familiar to
6125        * GStreamer segments, doesn't it? */
6126       stream->time_position = (time_position - segment->media_start) +
6127           segment->time;
6128     } else {
6129       /* not yet in segment, time does not yet increment. This means
6130        * that we are still prerolling keyframes to the decoder so it can
6131        * decode the first sample of the segment. */
6132       stream->time_position = segment->time;
6133     }
6134   }
6135
6136   /* combine flows */
6137   ret = gst_qtdemux_combine_flows (qtdemux, stream, ret);
6138   /* ignore unlinked, we will not push on the pad anymore and we will EOS when
6139    * we have no more data for the pad to push */
6140   if (ret == GST_FLOW_EOS)
6141     ret = GST_FLOW_OK;
6142
6143   stream->offset_in_sample += size;
6144   if (stream->offset_in_sample >= sample_size) {
6145     gst_qtdemux_advance_sample (qtdemux, stream);
6146   }
6147   goto beach;
6148
6149 next:
6150   gst_qtdemux_advance_sample (qtdemux, stream);
6151
6152 beach:
6153   return ret;
6154
6155   /* special cases */
6156 eos:
6157   {
6158     GST_DEBUG_OBJECT (qtdemux, "No samples left for any streams - EOS");
6159     ret = GST_FLOW_EOS;
6160     goto beach;
6161   }
6162 eos_stream:
6163   {
6164     GST_DEBUG_OBJECT (qtdemux, "No samples left for stream");
6165     /* EOS will be raised if all are EOS */
6166     ret = GST_FLOW_OK;
6167     goto beach;
6168   }
6169 }
6170
6171 static void
6172 gst_qtdemux_loop (GstPad * pad)
6173 {
6174   GstQTDemux *qtdemux;
6175   guint64 cur_offset;
6176   GstFlowReturn ret;
6177
6178   qtdemux = GST_QTDEMUX (gst_pad_get_parent (pad));
6179
6180   cur_offset = qtdemux->offset;
6181   GST_LOG_OBJECT (qtdemux, "loop at position %" G_GUINT64_FORMAT ", state %s",
6182       cur_offset, qt_demux_state_string (qtdemux->state));
6183
6184   switch (qtdemux->state) {
6185     case QTDEMUX_STATE_INITIAL:
6186     case QTDEMUX_STATE_HEADER:
6187       ret = gst_qtdemux_loop_state_header (qtdemux);
6188       break;
6189     case QTDEMUX_STATE_MOVIE:
6190       ret = gst_qtdemux_loop_state_movie (qtdemux);
6191       if (qtdemux->segment.rate < 0 && ret == GST_FLOW_EOS) {
6192         ret = gst_qtdemux_seek_to_previous_keyframe (qtdemux);
6193       }
6194       break;
6195     default:
6196       /* ouch */
6197       goto invalid_state;
6198   }
6199
6200   /* if something went wrong, pause */
6201   if (ret != GST_FLOW_OK)
6202     goto pause;
6203
6204 done:
6205   gst_object_unref (qtdemux);
6206   return;
6207
6208   /* ERRORS */
6209 invalid_state:
6210   {
6211     GST_ELEMENT_ERROR (qtdemux, STREAM, FAILED,
6212         (NULL), ("streaming stopped, invalid state"));
6213     gst_pad_pause_task (pad);
6214     gst_qtdemux_push_event (qtdemux, gst_event_new_eos ());
6215     goto done;
6216   }
6217 pause:
6218   {
6219     const gchar *reason = gst_flow_get_name (ret);
6220
6221     GST_LOG_OBJECT (qtdemux, "pausing task, reason %s", reason);
6222
6223     gst_pad_pause_task (pad);
6224
6225     /* fatal errors need special actions */
6226     /* check EOS */
6227     if (ret == GST_FLOW_EOS) {
6228       if (qtdemux->n_streams == 0) {
6229         /* we have no streams, post an error */
6230         gst_qtdemux_post_no_playable_stream_error (qtdemux);
6231       }
6232       if (qtdemux->segment.flags & GST_SEEK_FLAG_SEGMENT) {
6233         gint64 stop;
6234
6235         if ((stop = qtdemux->segment.stop) == -1)
6236           stop = qtdemux->segment.duration;
6237
6238         if (qtdemux->segment.rate >= 0) {
6239           GstMessage *message;
6240           GstEvent *event;
6241
6242           GST_LOG_OBJECT (qtdemux, "Sending segment done, at end of segment");
6243           message = gst_message_new_segment_done (GST_OBJECT_CAST (qtdemux),
6244               GST_FORMAT_TIME, stop);
6245           event = gst_event_new_segment_done (GST_FORMAT_TIME, stop);
6246           if (qtdemux->segment_seqnum != GST_SEQNUM_INVALID) {
6247             gst_message_set_seqnum (message, qtdemux->segment_seqnum);
6248             gst_event_set_seqnum (event, qtdemux->segment_seqnum);
6249           }
6250           gst_element_post_message (GST_ELEMENT_CAST (qtdemux), message);
6251           gst_qtdemux_push_event (qtdemux, event);
6252         } else {
6253           GstMessage *message;
6254           GstEvent *event;
6255
6256           /*  For Reverse Playback */
6257           GST_LOG_OBJECT (qtdemux, "Sending segment done, at start of segment");
6258           message = gst_message_new_segment_done (GST_OBJECT_CAST (qtdemux),
6259               GST_FORMAT_TIME, qtdemux->segment.start);
6260           event = gst_event_new_segment_done (GST_FORMAT_TIME,
6261               qtdemux->segment.start);
6262           if (qtdemux->segment_seqnum != GST_SEQNUM_INVALID) {
6263             gst_message_set_seqnum (message, qtdemux->segment_seqnum);
6264             gst_event_set_seqnum (event, qtdemux->segment_seqnum);
6265           }
6266           gst_element_post_message (GST_ELEMENT_CAST (qtdemux), message);
6267           gst_qtdemux_push_event (qtdemux, event);
6268         }
6269       } else {
6270         GstEvent *event;
6271
6272         GST_LOG_OBJECT (qtdemux, "Sending EOS at end of segment");
6273         event = gst_event_new_eos ();
6274         if (qtdemux->segment_seqnum != GST_SEQNUM_INVALID)
6275           gst_event_set_seqnum (event, qtdemux->segment_seqnum);
6276         gst_qtdemux_push_event (qtdemux, event);
6277       }
6278     } else if (ret == GST_FLOW_NOT_LINKED || ret < GST_FLOW_EOS) {
6279       GST_ELEMENT_FLOW_ERROR (qtdemux, ret);
6280       gst_qtdemux_push_event (qtdemux, gst_event_new_eos ());
6281     }
6282     goto done;
6283   }
6284 }
6285
6286 /*
6287  * has_next_entry
6288  *
6289  * Returns if there are samples to be played.
6290  */
6291 static gboolean
6292 has_next_entry (GstQTDemux * demux)
6293 {
6294   QtDemuxStream *stream;
6295   GList *iter;
6296
6297   GST_DEBUG_OBJECT (demux, "Checking if there are samples not played yet");
6298
6299   for (iter = demux->active_streams; iter; iter = g_list_next (iter)) {
6300     stream = QTDEMUX_STREAM (iter->data);
6301
6302     if (stream->sample_index == -1) {
6303       stream->sample_index = 0;
6304       stream->offset_in_sample = 0;
6305     }
6306
6307     if (stream->sample_index >= stream->n_samples) {
6308       GST_LOG_OBJECT (demux, "track-id %u samples exhausted", stream->track_id);
6309       continue;
6310     }
6311     GST_DEBUG_OBJECT (demux, "Found a sample");
6312     return TRUE;
6313   }
6314
6315   GST_DEBUG_OBJECT (demux, "There wasn't any next sample");
6316   return FALSE;
6317 }
6318
6319 /*
6320  * next_entry_size
6321  *
6322  * Returns the size of the first entry at the current offset.
6323  * If -1, there are none (which means EOS or empty file).
6324  */
6325 static guint64
6326 next_entry_size (GstQTDemux * demux)
6327 {
6328   QtDemuxStream *stream, *target_stream = NULL;
6329   guint64 smalloffs = (guint64) - 1;
6330   QtDemuxSample *sample;
6331   GList *iter;
6332
6333   GST_LOG_OBJECT (demux, "Finding entry at offset %" G_GUINT64_FORMAT,
6334       demux->offset);
6335
6336   for (iter = demux->active_streams; iter; iter = g_list_next (iter)) {
6337     stream = QTDEMUX_STREAM (iter->data);
6338
6339     if (stream->sample_index == -1) {
6340       stream->sample_index = 0;
6341       stream->offset_in_sample = 0;
6342     }
6343
6344     if (stream->sample_index >= stream->n_samples) {
6345       GST_LOG_OBJECT (demux, "track-id %u samples exhausted", stream->track_id);
6346       continue;
6347     }
6348
6349     if (!qtdemux_parse_samples (demux, stream, stream->sample_index)) {
6350       GST_LOG_OBJECT (demux, "Parsing of index %u from stbl atom failed!",
6351           stream->sample_index);
6352       return -1;
6353     }
6354
6355     sample = &stream->samples[stream->sample_index];
6356
6357     GST_LOG_OBJECT (demux,
6358         "Checking track-id %u (sample_index:%d / offset:%" G_GUINT64_FORMAT
6359         " / size:%" G_GUINT32_FORMAT ")", stream->track_id,
6360         stream->sample_index, sample->offset, sample->size);
6361
6362     if (((smalloffs == -1)
6363             || (sample->offset < smalloffs)) && (sample->size)) {
6364       smalloffs = sample->offset;
6365       target_stream = stream;
6366     }
6367   }
6368
6369   if (!target_stream)
6370     return -1;
6371
6372   GST_LOG_OBJECT (demux,
6373       "track-id %u offset %" G_GUINT64_FORMAT " demux->offset :%"
6374       G_GUINT64_FORMAT, target_stream->track_id, smalloffs, demux->offset);
6375
6376   stream = target_stream;
6377   sample = &stream->samples[stream->sample_index];
6378
6379   if (sample->offset >= demux->offset) {
6380     demux->todrop = sample->offset - demux->offset;
6381     return sample->size + demux->todrop;
6382   }
6383
6384   GST_DEBUG_OBJECT (demux,
6385       "There wasn't any entry at offset %" G_GUINT64_FORMAT, demux->offset);
6386   return -1;
6387 }
6388
6389 static void
6390 gst_qtdemux_post_progress (GstQTDemux * demux, gint num, gint denom)
6391 {
6392   gint perc = (gint) ((gdouble) num * 100.0 / (gdouble) denom);
6393
6394   gst_element_post_message (GST_ELEMENT_CAST (demux),
6395       gst_message_new_element (GST_OBJECT_CAST (demux),
6396           gst_structure_new ("progress", "percent", G_TYPE_INT, perc, NULL)));
6397 }
6398
6399 static gboolean
6400 qtdemux_seek_offset (GstQTDemux * demux, guint64 offset)
6401 {
6402   GstEvent *event;
6403   gboolean res = 0;
6404
6405   GST_DEBUG_OBJECT (demux, "Seeking to %" G_GUINT64_FORMAT, offset);
6406
6407   event =
6408       gst_event_new_seek (1.0, GST_FORMAT_BYTES,
6409       GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_ACCURATE, GST_SEEK_TYPE_SET, offset,
6410       GST_SEEK_TYPE_NONE, -1);
6411
6412   /* store seqnum to drop flush events, they don't need to reach downstream */
6413   demux->offset_seek_seqnum = gst_event_get_seqnum (event);
6414   res = gst_pad_push_event (demux->sinkpad, event);
6415   demux->offset_seek_seqnum = GST_SEQNUM_INVALID;
6416
6417   return res;
6418 }
6419
6420 /* check for seekable upstream, above and beyond a mere query */
6421 static void
6422 gst_qtdemux_check_seekability (GstQTDemux * demux)
6423 {
6424   GstQuery *query;
6425   gboolean seekable = FALSE;
6426   gint64 start = -1, stop = -1;
6427
6428   if (demux->upstream_size)
6429     return;
6430
6431   if (demux->upstream_format_is_time)
6432     return;
6433
6434   query = gst_query_new_seeking (GST_FORMAT_BYTES);
6435   if (!gst_pad_peer_query (demux->sinkpad, query)) {
6436     GST_DEBUG_OBJECT (demux, "seeking query failed");
6437     goto done;
6438   }
6439
6440   gst_query_parse_seeking (query, NULL, &seekable, &start, &stop);
6441
6442   /* try harder to query upstream size if we didn't get it the first time */
6443   if (seekable && stop == -1) {
6444     GST_DEBUG_OBJECT (demux, "doing duration query to fix up unset stop");
6445     gst_pad_peer_query_duration (demux->sinkpad, GST_FORMAT_BYTES, &stop);
6446   }
6447
6448   /* if upstream doesn't know the size, it's likely that it's not seekable in
6449    * practice even if it technically may be seekable */
6450   if (seekable && (start != 0 || stop <= start)) {
6451     GST_DEBUG_OBJECT (demux, "seekable but unknown start/stop -> disable");
6452     seekable = FALSE;
6453   }
6454
6455 done:
6456   gst_query_unref (query);
6457
6458   GST_DEBUG_OBJECT (demux, "seekable: %d (%" G_GUINT64_FORMAT " - %"
6459       G_GUINT64_FORMAT ")", seekable, start, stop);
6460   demux->upstream_seekable = seekable;
6461   demux->upstream_size = seekable ? stop : -1;
6462 }
6463
6464 static void
6465 gst_qtdemux_drop_data (GstQTDemux * demux, gint bytes)
6466 {
6467   g_return_if_fail (bytes <= demux->todrop);
6468
6469   GST_LOG_OBJECT (demux, "Dropping %d bytes", bytes);
6470   gst_adapter_flush (demux->adapter, bytes);
6471   demux->neededbytes -= bytes;
6472   demux->offset += bytes;
6473   demux->todrop -= bytes;
6474 }
6475
6476 static void
6477 gst_qtdemux_check_send_pending_segment (GstQTDemux * demux)
6478 {
6479   if (G_UNLIKELY (demux->pending_newsegment)) {
6480     gint i;
6481     GList *iter;
6482
6483     gst_qtdemux_push_pending_newsegment (demux);
6484     /* clear to send tags on all streams */
6485     for (iter = demux->active_streams, i = 0; iter;
6486         iter = g_list_next (iter), i++) {
6487       QtDemuxStream *stream = QTDEMUX_STREAM (iter->data);
6488       gst_qtdemux_push_tags (demux, stream);
6489       if (CUR_STREAM (stream)->sparse) {
6490         GST_INFO_OBJECT (demux, "Sending gap event on stream %d", i);
6491         gst_pad_push_event (stream->pad,
6492             gst_event_new_gap (stream->segment.position, GST_CLOCK_TIME_NONE));
6493       }
6494     }
6495   }
6496 }
6497
6498 static void
6499 gst_qtdemux_send_gap_for_segment (GstQTDemux * demux,
6500     QtDemuxStream * stream, gint segment_index, GstClockTime pos)
6501 {
6502   GstClockTime ts, dur;
6503   GstEvent *gap;
6504
6505   ts = pos;
6506   dur =
6507       stream->segments[segment_index].duration - (pos -
6508       stream->segments[segment_index].time);
6509   gap = gst_event_new_gap (ts, dur);
6510   stream->time_position += dur;
6511
6512   GST_DEBUG_OBJECT (stream->pad, "Pushing gap for empty "
6513       "segment: %" GST_PTR_FORMAT, gap);
6514   gst_pad_push_event (stream->pad, gap);
6515 }
6516
6517 static void
6518 gst_qtdemux_stream_send_initial_gap_segments (GstQTDemux * demux,
6519     QtDemuxStream * stream)
6520 {
6521   gint i;
6522
6523   /* Push any initial gap segments before proceeding to the
6524    * 'real' data */
6525   for (i = 0; i < stream->n_segments; i++) {
6526     gst_qtdemux_activate_segment (demux, stream, i, stream->time_position);
6527
6528     if (QTSEGMENT_IS_EMPTY (&stream->segments[i])) {
6529       gst_qtdemux_send_gap_for_segment (demux, stream, i,
6530           stream->time_position);
6531     } else {
6532       /* Only support empty segment at the beginning followed by
6533        * one non-empty segment, this was checked when parsing the
6534        * edts atom, arriving here is unexpected */
6535       g_assert (i + 1 == stream->n_segments);
6536       break;
6537     }
6538   }
6539 }
6540
6541 static GstFlowReturn
6542 gst_qtdemux_chain (GstPad * sinkpad, GstObject * parent, GstBuffer * inbuf)
6543 {
6544   GstQTDemux *demux;
6545
6546   demux = GST_QTDEMUX (parent);
6547
6548   GST_DEBUG_OBJECT (demux,
6549       "Received buffer pts:%" GST_TIME_FORMAT " dts:%" GST_TIME_FORMAT
6550       " offset:%" G_GUINT64_FORMAT " size:%" G_GSIZE_FORMAT " demux offset:%"
6551       G_GUINT64_FORMAT, GST_TIME_ARGS (GST_BUFFER_PTS (inbuf)),
6552       GST_TIME_ARGS (GST_BUFFER_DTS (inbuf)), GST_BUFFER_OFFSET (inbuf),
6553       gst_buffer_get_size (inbuf), demux->offset);
6554
6555   if (GST_BUFFER_FLAG_IS_SET (inbuf, GST_BUFFER_FLAG_DISCONT)) {
6556     gboolean is_gap_input = FALSE;
6557     GList *iter;
6558
6559     GST_DEBUG_OBJECT (demux, "Got DISCONT, marking all streams as DISCONT");
6560
6561     for (iter = demux->active_streams; iter; iter = g_list_next (iter)) {
6562       QTDEMUX_STREAM (iter->data)->discont = TRUE;
6563     }
6564
6565     /* Check if we can land back on our feet in the case where upstream is
6566      * handling the seeking/pushing of samples with gaps in between (like
6567      * in the case of trick-mode DASH for example) */
6568     if (demux->upstream_format_is_time
6569         && GST_BUFFER_OFFSET (inbuf) != GST_BUFFER_OFFSET_NONE) {
6570       for (iter = demux->active_streams; iter; iter = g_list_next (iter)) {
6571         guint32 res;
6572         QtDemuxStream *stream = QTDEMUX_STREAM (iter->data);
6573         GST_LOG_OBJECT (demux,
6574             "track-id #%u , checking if offset %" G_GUINT64_FORMAT
6575             " is a sample start", stream->track_id, GST_BUFFER_OFFSET (inbuf));
6576         res =
6577             gst_qtdemux_find_index_for_given_media_offset_linear (demux,
6578             stream, GST_BUFFER_OFFSET (inbuf));
6579         if (res != -1) {
6580           QtDemuxSample *sample = &stream->samples[res];
6581           GST_LOG_OBJECT (demux,
6582               "Checking if sample %d from track-id %u is valid (offset:%"
6583               G_GUINT64_FORMAT " size:%" G_GUINT32_FORMAT ")", res,
6584               stream->track_id, sample->offset, sample->size);
6585           if (sample->offset == GST_BUFFER_OFFSET (inbuf)) {
6586             GST_LOG_OBJECT (demux,
6587                 "new buffer corresponds to a valid sample : %" G_GUINT32_FORMAT,
6588                 res);
6589             is_gap_input = TRUE;
6590             /* We can go back to standard playback mode */
6591             demux->state = QTDEMUX_STATE_MOVIE;
6592             /* Remember which sample this stream is at */
6593             stream->sample_index = res;
6594             /* Finally update all push-based values to the expected values */
6595             demux->neededbytes = stream->samples[res].size;
6596             demux->offset = GST_BUFFER_OFFSET (inbuf);
6597             demux->mdatleft =
6598                 demux->mdatsize - demux->offset + demux->mdatoffset;
6599             demux->todrop = 0;
6600           }
6601         }
6602       }
6603       if (!is_gap_input) {
6604         GST_DEBUG_OBJECT (demux, "Resetting, actual DISCONT");
6605         /* Reset state if it's a real discont */
6606         demux->neededbytes = 16;
6607         demux->state = QTDEMUX_STATE_INITIAL;
6608         demux->offset = GST_BUFFER_OFFSET (inbuf);
6609         gst_adapter_clear (demux->adapter);
6610       }
6611     }
6612     /* Reverse fragmented playback, need to flush all we have before
6613      * consuming a new fragment.
6614      * The samples array have the timestamps calculated by accumulating the
6615      * durations but this won't work for reverse playback of fragments as
6616      * the timestamps of a subsequent fragment should be smaller than the
6617      * previously received one. */
6618     if (!is_gap_input && demux->fragmented && demux->segment.rate < 0) {
6619       gst_qtdemux_process_adapter (demux, TRUE);
6620       g_list_foreach (demux->active_streams,
6621           (GFunc) gst_qtdemux_stream_flush_samples_data, NULL);
6622     }
6623   }
6624
6625   gst_adapter_push (demux->adapter, inbuf);
6626
6627   GST_DEBUG_OBJECT (demux,
6628       "pushing in inbuf %p, neededbytes:%u, available:%" G_GSIZE_FORMAT, inbuf,
6629       demux->neededbytes, gst_adapter_available (demux->adapter));
6630
6631   return gst_qtdemux_process_adapter (demux, FALSE);
6632 }
6633
6634 static GstFlowReturn
6635 gst_qtdemux_process_adapter (GstQTDemux * demux, gboolean force)
6636 {
6637   GstFlowReturn ret = GST_FLOW_OK;
6638
6639   /* we never really mean to buffer that much */
6640   if (demux->neededbytes == -1) {
6641     goto eos;
6642   }
6643
6644   while (((gst_adapter_available (demux->adapter)) >= demux->neededbytes) &&
6645       (ret == GST_FLOW_OK || (ret == GST_FLOW_NOT_LINKED && force))) {
6646
6647 #ifndef GST_DISABLE_GST_DEBUG
6648     {
6649       guint64 discont_offset, distance_from_discont;
6650
6651       discont_offset = gst_adapter_offset_at_discont (demux->adapter);
6652       distance_from_discont =
6653           gst_adapter_distance_from_discont (demux->adapter);
6654
6655       GST_DEBUG_OBJECT (demux,
6656           "state:%s , demux->neededbytes:%d, demux->offset:%" G_GUINT64_FORMAT
6657           " adapter offset :%" G_GUINT64_FORMAT " (+ %" G_GUINT64_FORMAT
6658           " bytes)", qt_demux_state_string (demux->state), demux->neededbytes,
6659           demux->offset, discont_offset, distance_from_discont);
6660     }
6661 #endif
6662
6663     switch (demux->state) {
6664       case QTDEMUX_STATE_INITIAL:{
6665         const guint8 *data;
6666         guint32 fourcc;
6667         guint64 size;
6668
6669         gst_qtdemux_check_seekability (demux);
6670
6671         data = gst_adapter_map (demux->adapter, demux->neededbytes);
6672
6673         /* get fourcc/length, set neededbytes */
6674         extract_initial_length_and_fourcc ((guint8 *) data, demux->neededbytes,
6675             &size, &fourcc);
6676         gst_adapter_unmap (demux->adapter);
6677         data = NULL;
6678         GST_DEBUG_OBJECT (demux, "Peeking found [%" GST_FOURCC_FORMAT "] "
6679             "size: %" G_GUINT64_FORMAT, GST_FOURCC_ARGS (fourcc), size);
6680         if (size == 0) {
6681           GST_ELEMENT_ERROR (demux, STREAM, DEMUX,
6682               (_("This file is invalid and cannot be played.")),
6683               ("initial atom '%" GST_FOURCC_FORMAT "' has empty length",
6684                   GST_FOURCC_ARGS (fourcc)));
6685           ret = GST_FLOW_ERROR;
6686           break;
6687         }
6688         if (fourcc == FOURCC_mdat) {
6689           gint next_entry = next_entry_size (demux);
6690           if (demux->n_streams > 0 && (next_entry != -1 || !demux->fragmented)) {
6691             /* we have the headers, start playback */
6692             demux->state = QTDEMUX_STATE_MOVIE;
6693             demux->neededbytes = next_entry;
6694             demux->mdatleft = size;
6695             demux->mdatsize = demux->mdatleft;
6696           } else {
6697             /* no headers yet, try to get them */
6698             guint bs;
6699             gboolean res;
6700             guint64 old, target;
6701
6702           buffer_data:
6703             old = demux->offset;
6704             target = old + size;
6705
6706             /* try to jump over the atom with a seek */
6707             /* only bother if it seems worth doing so,
6708              * and avoids possible upstream/server problems */
6709             if (demux->upstream_seekable &&
6710                 demux->upstream_size > 4 * (1 << 20)) {
6711               res = qtdemux_seek_offset (demux, target);
6712             } else {
6713               GST_DEBUG_OBJECT (demux, "skipping seek");
6714               res = FALSE;
6715             }
6716
6717             if (res) {
6718               GST_DEBUG_OBJECT (demux, "seek success");
6719               /* remember the offset fo the first mdat so we can seek back to it
6720                * after we have the headers */
6721               if (fourcc == FOURCC_mdat && demux->first_mdat == -1) {
6722                 demux->first_mdat = old;
6723                 GST_DEBUG_OBJECT (demux, "first mdat at %" G_GUINT64_FORMAT,
6724                     demux->first_mdat);
6725               }
6726               /* seek worked, continue reading */
6727               demux->offset = target;
6728               demux->neededbytes = 16;
6729               demux->state = QTDEMUX_STATE_INITIAL;
6730             } else {
6731               /* seek failed, need to buffer */
6732               demux->offset = old;
6733               GST_DEBUG_OBJECT (demux, "seek failed/skipped");
6734               /* there may be multiple mdat (or alike) buffers */
6735               /* sanity check */
6736               if (demux->mdatbuffer)
6737                 bs = gst_buffer_get_size (demux->mdatbuffer);
6738               else
6739                 bs = 0;
6740               if (size + bs > 10 * (1 << 20))
6741                 goto no_moov;
6742               demux->state = QTDEMUX_STATE_BUFFER_MDAT;
6743               demux->neededbytes = size;
6744               if (!demux->mdatbuffer)
6745                 demux->mdatoffset = demux->offset;
6746             }
6747           }
6748         } else if (G_UNLIKELY (size > QTDEMUX_MAX_ATOM_SIZE)) {
6749           GST_ELEMENT_ERROR (demux, STREAM, DEMUX,
6750               (_("This file is invalid and cannot be played.")),
6751               ("atom %" GST_FOURCC_FORMAT " has bogus size %" G_GUINT64_FORMAT,
6752                   GST_FOURCC_ARGS (fourcc), size));
6753           ret = GST_FLOW_ERROR;
6754           break;
6755         } else {
6756           /* this means we already started buffering and still no moov header,
6757            * let's continue buffering everything till we get moov */
6758           if (demux->mdatbuffer && !(fourcc == FOURCC_moov
6759                   || fourcc == FOURCC_moof))
6760             goto buffer_data;
6761           demux->neededbytes = size;
6762           demux->state = QTDEMUX_STATE_HEADER;
6763         }
6764         break;
6765       }
6766       case QTDEMUX_STATE_HEADER:{
6767         const guint8 *data;
6768         guint32 fourcc;
6769
6770         GST_DEBUG_OBJECT (demux, "In header");
6771
6772         data = gst_adapter_map (demux->adapter, demux->neededbytes);
6773
6774         /* parse the header */
6775         extract_initial_length_and_fourcc (data, demux->neededbytes, NULL,
6776             &fourcc);
6777         if (fourcc == FOURCC_moov) {
6778           GList *iter;
6779
6780           /* in usual fragmented setup we could try to scan for more
6781            * and end up at the the moov (after mdat) again */
6782           if (demux->got_moov && demux->n_streams > 0 &&
6783               (!demux->fragmented
6784                   || demux->last_moov_offset == demux->offset)) {
6785             GST_DEBUG_OBJECT (demux,
6786                 "Skipping moov atom as we have (this) one already");
6787           } else {
6788             GST_DEBUG_OBJECT (demux, "Parsing [moov]");
6789
6790             if (demux->got_moov && demux->fragmented) {
6791               GST_DEBUG_OBJECT (demux,
6792                   "Got a second moov, clean up data from old one");
6793               if (demux->moov_node_compressed) {
6794                 g_node_destroy (demux->moov_node_compressed);
6795                 if (demux->moov_node)
6796                   g_free (demux->moov_node->data);
6797               }
6798               demux->moov_node_compressed = NULL;
6799               if (demux->moov_node)
6800                 g_node_destroy (demux->moov_node);
6801               demux->moov_node = NULL;
6802             } else {
6803               /* prepare newsegment to send when streaming actually starts */
6804               if (!demux->pending_newsegment) {
6805                 demux->pending_newsegment =
6806                     gst_event_new_segment (&demux->segment);
6807                 if (demux->segment_seqnum != GST_SEQNUM_INVALID)
6808                   gst_event_set_seqnum (demux->pending_newsegment,
6809                       demux->segment_seqnum);
6810               }
6811             }
6812
6813             demux->last_moov_offset = demux->offset;
6814
6815             qtdemux_parse_moov (demux, data, demux->neededbytes);
6816             qtdemux_node_dump (demux, demux->moov_node);
6817             qtdemux_parse_tree (demux);
6818             qtdemux_prepare_streams (demux);
6819             if (!demux->got_moov)
6820               qtdemux_expose_streams (demux);
6821             else {
6822
6823               for (iter = demux->active_streams; iter;
6824                   iter = g_list_next (iter)) {
6825                 gst_qtdemux_configure_stream (demux,
6826                     QTDEMUX_STREAM (iter->data));
6827               }
6828             }
6829
6830             demux->got_moov = TRUE;
6831             gst_qtdemux_check_send_pending_segment (demux);
6832
6833             /* fragmented streams headers shouldn't contain edts atoms */
6834             if (!demux->fragmented) {
6835               for (iter = demux->active_streams; iter;
6836                   iter = g_list_next (iter)) {
6837                 gst_qtdemux_stream_send_initial_gap_segments (demux,
6838                     QTDEMUX_STREAM (iter->data));
6839               }
6840             }
6841
6842             if (demux->moov_node_compressed) {
6843               g_node_destroy (demux->moov_node_compressed);
6844               g_free (demux->moov_node->data);
6845             }
6846             demux->moov_node_compressed = NULL;
6847             g_node_destroy (demux->moov_node);
6848             demux->moov_node = NULL;
6849             GST_DEBUG_OBJECT (demux, "Finished parsing the header");
6850           }
6851         } else if (fourcc == FOURCC_moof) {
6852           if ((demux->got_moov || demux->media_caps) && demux->fragmented) {
6853             guint64 dist = 0;
6854             GstClockTime prev_pts;
6855             guint64 prev_offset;
6856             guint64 adapter_discont_offset, adapter_discont_dist;
6857
6858             GST_DEBUG_OBJECT (demux, "Parsing [moof]");
6859
6860             /*
6861              * The timestamp of the moof buffer is relevant as some scenarios
6862              * won't have the initial timestamp in the atoms. Whenever a new
6863              * buffer has started, we get that buffer's PTS and use it as a base
6864              * timestamp for the trun entries.
6865              *
6866              * To keep track of the current buffer timestamp and starting point
6867              * we use gst_adapter_prev_pts that gives us the PTS and the distance
6868              * from the beggining of the buffer, with the distance and demux->offset
6869              * we know if it is still the same buffer or not.
6870              */
6871             prev_pts = gst_adapter_prev_pts (demux->adapter, &dist);
6872             prev_offset = demux->offset - dist;
6873             if (demux->fragment_start_offset == -1
6874                 || prev_offset > demux->fragment_start_offset) {
6875               demux->fragment_start_offset = prev_offset;
6876               demux->fragment_start = prev_pts;
6877               GST_DEBUG_OBJECT (demux,
6878                   "New fragment start found at: %" G_GUINT64_FORMAT " : %"
6879                   GST_TIME_FORMAT, demux->fragment_start_offset,
6880                   GST_TIME_ARGS (demux->fragment_start));
6881             }
6882
6883             /* We can't use prev_offset() here because this would require
6884              * upstream to set consistent and correct offsets on all buffers
6885              * since the discont. Nothing ever did that in the past and we
6886              * would break backwards compatibility here then.
6887              * Instead take the offset we had at the last discont and count
6888              * the bytes from there. This works with old code as there would
6889              * be no discont between moov and moof, and also works with
6890              * adaptivedemux which correctly sets offset and will set the
6891              * DISCONT flag accordingly when needed.
6892              *
6893              * We also only do this for upstream TIME segments as otherwise
6894              * there are potential backwards compatibility problems with
6895              * seeking in PUSH mode and upstream providing inconsistent
6896              * timestamps. */
6897             adapter_discont_offset =
6898                 gst_adapter_offset_at_discont (demux->adapter);
6899             adapter_discont_dist =
6900                 gst_adapter_distance_from_discont (demux->adapter);
6901
6902             GST_DEBUG_OBJECT (demux,
6903                 "demux offset %" G_GUINT64_FORMAT " adapter offset %"
6904                 G_GUINT64_FORMAT " (+ %" G_GUINT64_FORMAT " bytes)",
6905                 demux->offset, adapter_discont_offset, adapter_discont_dist);
6906
6907             if (demux->upstream_format_is_time) {
6908               demux->moof_offset = adapter_discont_offset;
6909               if (demux->moof_offset != GST_BUFFER_OFFSET_NONE)
6910                 demux->moof_offset += adapter_discont_dist;
6911               if (demux->moof_offset == GST_BUFFER_OFFSET_NONE)
6912                 demux->moof_offset = demux->offset;
6913             } else {
6914               demux->moof_offset = demux->offset;
6915             }
6916
6917             if (!qtdemux_parse_moof (demux, data, demux->neededbytes,
6918                     demux->moof_offset, NULL)) {
6919               gst_adapter_unmap (demux->adapter);
6920               ret = GST_FLOW_ERROR;
6921               goto done;
6922             }
6923             /* in MSS we need to expose the pads after the first moof as we won't get a moov */
6924             if (demux->mss_mode && !demux->exposed) {
6925               if (!demux->pending_newsegment) {
6926                 GST_DEBUG_OBJECT (demux, "new pending_newsegment");
6927                 demux->pending_newsegment =
6928                     gst_event_new_segment (&demux->segment);
6929                 if (demux->segment_seqnum != GST_SEQNUM_INVALID)
6930                   gst_event_set_seqnum (demux->pending_newsegment,
6931                       demux->segment_seqnum);
6932               }
6933               qtdemux_expose_streams (demux);
6934             }
6935           } else {
6936             GST_DEBUG_OBJECT (demux, "Discarding [moof]");
6937           }
6938         } else if (fourcc == FOURCC_ftyp) {
6939           GST_DEBUG_OBJECT (demux, "Parsing [ftyp]");
6940           qtdemux_parse_ftyp (demux, data, demux->neededbytes);
6941         } else if (fourcc == FOURCC_uuid) {
6942           GST_DEBUG_OBJECT (demux, "Parsing [uuid]");
6943           qtdemux_parse_uuid (demux, data, demux->neededbytes);
6944         } else if (fourcc == FOURCC_sidx) {
6945           GST_DEBUG_OBJECT (demux, "Parsing [sidx]");
6946           qtdemux_parse_sidx (demux, data, demux->neededbytes);
6947         } else {
6948           switch (fourcc) {
6949             case FOURCC_styp:
6950               /* [styp] is like a [ftyp], but in fragment header. We ignore it for now
6951                * FALLTHROUGH */
6952             case FOURCC_skip:
6953             case FOURCC_free:
6954               /* [free] and [skip] are padding atoms */
6955               GST_DEBUG_OBJECT (demux,
6956                   "Skipping fourcc while parsing header : %" GST_FOURCC_FORMAT,
6957                   GST_FOURCC_ARGS (fourcc));
6958               break;
6959             default:
6960               GST_WARNING_OBJECT (demux,
6961                   "Unknown fourcc while parsing header : %" GST_FOURCC_FORMAT,
6962                   GST_FOURCC_ARGS (fourcc));
6963               /* Let's jump that one and go back to initial state */
6964               break;
6965           }
6966         }
6967         gst_adapter_unmap (demux->adapter);
6968         data = NULL;
6969
6970         if (demux->mdatbuffer && demux->n_streams) {
6971           gsize remaining_data_size = 0;
6972
6973           /* the mdat was before the header */
6974           GST_DEBUG_OBJECT (demux, "We have n_streams:%d and mdatbuffer:%p",
6975               demux->n_streams, demux->mdatbuffer);
6976           /* restore our adapter/offset view of things with upstream;
6977            * put preceding buffered data ahead of current moov data.
6978            * This should also handle evil mdat, moov, mdat cases and alike */
6979           gst_adapter_flush (demux->adapter, demux->neededbytes);
6980
6981           /* Store any remaining data after the mdat for later usage */
6982           remaining_data_size = gst_adapter_available (demux->adapter);
6983           if (remaining_data_size > 0) {
6984             g_assert (demux->restoredata_buffer == NULL);
6985             demux->restoredata_buffer =
6986                 gst_adapter_take_buffer (demux->adapter, remaining_data_size);
6987             demux->restoredata_offset = demux->offset + demux->neededbytes;
6988             GST_DEBUG_OBJECT (demux,
6989                 "Stored %" G_GSIZE_FORMAT " post mdat bytes at offset %"
6990                 G_GUINT64_FORMAT, remaining_data_size,
6991                 demux->restoredata_offset);
6992           }
6993
6994           gst_adapter_push (demux->adapter, demux->mdatbuffer);
6995           demux->mdatbuffer = NULL;
6996           demux->offset = demux->mdatoffset;
6997           demux->neededbytes = next_entry_size (demux);
6998           demux->state = QTDEMUX_STATE_MOVIE;
6999           demux->mdatleft = gst_adapter_available (demux->adapter);
7000           demux->mdatsize = demux->mdatleft;
7001         } else {
7002           GST_DEBUG_OBJECT (demux, "Carrying on normally");
7003           gst_adapter_flush (demux->adapter, demux->neededbytes);
7004
7005           /* only go back to the mdat if there are samples to play */
7006           if (demux->got_moov && demux->first_mdat != -1
7007               && has_next_entry (demux)) {
7008             gboolean res;
7009
7010             /* we need to seek back */
7011             res = qtdemux_seek_offset (demux, demux->first_mdat);
7012             if (res) {
7013               demux->offset = demux->first_mdat;
7014             } else {
7015               GST_DEBUG_OBJECT (demux, "Seek back failed");
7016             }
7017           } else {
7018             demux->offset += demux->neededbytes;
7019           }
7020           demux->neededbytes = 16;
7021           demux->state = QTDEMUX_STATE_INITIAL;
7022         }
7023
7024         break;
7025       }
7026       case QTDEMUX_STATE_BUFFER_MDAT:{
7027         GstBuffer *buf;
7028         guint8 fourcc[4];
7029
7030         GST_DEBUG_OBJECT (demux, "Got our buffer at offset %" G_GUINT64_FORMAT,
7031             demux->offset);
7032         buf = gst_adapter_take_buffer (demux->adapter, demux->neededbytes);
7033         gst_buffer_extract (buf, 0, fourcc, 4);
7034         GST_DEBUG_OBJECT (demux, "mdatbuffer starts with %" GST_FOURCC_FORMAT,
7035             GST_FOURCC_ARGS (QT_FOURCC (fourcc)));
7036         if (demux->mdatbuffer)
7037           demux->mdatbuffer = gst_buffer_append (demux->mdatbuffer, buf);
7038         else
7039           demux->mdatbuffer = buf;
7040         demux->offset += demux->neededbytes;
7041         demux->neededbytes = 16;
7042         demux->state = QTDEMUX_STATE_INITIAL;
7043         gst_qtdemux_post_progress (demux, 1, 1);
7044
7045         break;
7046       }
7047       case QTDEMUX_STATE_MOVIE:{
7048         QtDemuxStream *stream = NULL;
7049         QtDemuxSample *sample;
7050         GstClockTime dts, pts, duration;
7051         gboolean keyframe;
7052         GList *iter;
7053
7054         GST_DEBUG_OBJECT (demux,
7055             "BEGIN // in MOVIE for offset %" G_GUINT64_FORMAT, demux->offset);
7056
7057         if (demux->fragmented) {
7058           GST_DEBUG_OBJECT (demux, "mdat remaining %" G_GUINT64_FORMAT,
7059               demux->mdatleft);
7060           if (G_LIKELY (demux->todrop < demux->mdatleft)) {
7061             /* if needed data starts within this atom,
7062              * then it should not exceed this atom */
7063             if (G_UNLIKELY (demux->neededbytes > demux->mdatleft)) {
7064               GST_ELEMENT_ERROR (demux, STREAM, DEMUX,
7065                   (_("This file is invalid and cannot be played.")),
7066                   ("sample data crosses atom boundary"));
7067               ret = GST_FLOW_ERROR;
7068               break;
7069             }
7070             demux->mdatleft -= demux->neededbytes;
7071           } else {
7072             GST_DEBUG_OBJECT (demux, "data atom emptied; resuming atom scan");
7073             /* so we are dropping more than left in this atom */
7074             gst_qtdemux_drop_data (demux, demux->mdatleft);
7075             demux->mdatleft = 0;
7076
7077             /* need to resume atom parsing so we do not miss any other pieces */
7078             demux->state = QTDEMUX_STATE_INITIAL;
7079             demux->neededbytes = 16;
7080
7081             /* check if there was any stored post mdat data from previous buffers */
7082             if (demux->restoredata_buffer) {
7083               g_assert (gst_adapter_available (demux->adapter) == 0);
7084
7085               gst_adapter_push (demux->adapter, demux->restoredata_buffer);
7086               demux->restoredata_buffer = NULL;
7087               demux->offset = demux->restoredata_offset;
7088             }
7089
7090             break;
7091           }
7092         }
7093
7094         if (demux->todrop) {
7095           if (demux->cenc_aux_info_offset > 0) {
7096             GstByteReader br;
7097             const guint8 *data;
7098
7099             GST_DEBUG_OBJECT (demux, "parsing cenc auxiliary info");
7100             data = gst_adapter_map (demux->adapter, demux->todrop);
7101             gst_byte_reader_init (&br, data + 8, demux->todrop);
7102             if (!qtdemux_parse_cenc_aux_info (demux,
7103                     QTDEMUX_FIRST_STREAM (demux), &br,
7104                     demux->cenc_aux_info_sizes, demux->cenc_aux_sample_count)) {
7105               GST_ERROR_OBJECT (demux, "failed to parse cenc auxiliary info");
7106               ret = GST_FLOW_ERROR;
7107               gst_adapter_unmap (demux->adapter);
7108               g_free (demux->cenc_aux_info_sizes);
7109               demux->cenc_aux_info_sizes = NULL;
7110               goto done;
7111             }
7112             demux->cenc_aux_info_offset = 0;
7113             g_free (demux->cenc_aux_info_sizes);
7114             demux->cenc_aux_info_sizes = NULL;
7115             gst_adapter_unmap (demux->adapter);
7116           }
7117           gst_qtdemux_drop_data (demux, demux->todrop);
7118         }
7119
7120         /* first buffer? */
7121         /* initial newsegment sent here after having added pads,
7122          * possible others in sink_event */
7123         gst_qtdemux_check_send_pending_segment (demux);
7124
7125         /* Figure out which stream this packet belongs to */
7126         for (iter = demux->active_streams; iter; iter = g_list_next (iter)) {
7127           stream = QTDEMUX_STREAM (iter->data);
7128           if (stream->sample_index >= stream->n_samples) {
7129             /* reset to be checked below G_UNLIKELY (stream == NULL) */
7130             stream = NULL;
7131             continue;
7132           }
7133           GST_LOG_OBJECT (demux,
7134               "Checking track-id %u (sample_index:%d / offset:%"
7135               G_GUINT64_FORMAT " / size:%d)", stream->track_id,
7136               stream->sample_index,
7137               stream->samples[stream->sample_index].offset,
7138               stream->samples[stream->sample_index].size);
7139
7140           if (stream->samples[stream->sample_index].offset == demux->offset)
7141             break;
7142         }
7143
7144         if (G_UNLIKELY (stream == NULL))
7145           goto unknown_stream;
7146
7147         gst_qtdemux_stream_check_and_change_stsd_index (demux, stream);
7148
7149         if (stream->new_caps) {
7150           gst_qtdemux_configure_stream (demux, stream);
7151         }
7152
7153         /* Put data in a buffer, set timestamps, caps, ... */
7154         sample = &stream->samples[stream->sample_index];
7155
7156         if (G_LIKELY (!(STREAM_IS_EOS (stream)))) {
7157           GST_DEBUG_OBJECT (demux, "stream : %" GST_FOURCC_FORMAT,
7158               GST_FOURCC_ARGS (CUR_STREAM (stream)->fourcc));
7159
7160           dts = QTSAMPLE_DTS (stream, sample);
7161           pts = QTSAMPLE_PTS (stream, sample);
7162           duration = QTSAMPLE_DUR_DTS (stream, sample, dts);
7163           keyframe = QTSAMPLE_KEYFRAME (stream, sample);
7164
7165           /* check for segment end */
7166           if (G_UNLIKELY (demux->segment.stop != -1
7167                   && demux->segment.stop <= pts && stream->on_keyframe)) {
7168             GST_DEBUG_OBJECT (demux, "we reached the end of our segment.");
7169             stream->time_position = GST_CLOCK_TIME_NONE;        /* this means EOS */
7170
7171             /* skip this data, stream is EOS */
7172             gst_adapter_flush (demux->adapter, demux->neededbytes);
7173             demux->offset += demux->neededbytes;
7174
7175             /* check if all streams are eos */
7176             ret = GST_FLOW_EOS;
7177             for (iter = demux->active_streams; iter; iter = g_list_next (iter)) {
7178               if (!STREAM_IS_EOS (QTDEMUX_STREAM (iter->data))) {
7179                 ret = GST_FLOW_OK;
7180                 break;
7181               }
7182             }
7183           } else {
7184             GstBuffer *outbuf;
7185
7186             outbuf =
7187                 gst_adapter_take_buffer (demux->adapter, demux->neededbytes);
7188
7189             /* FIXME: should either be an assert or a plain check */
7190             g_return_val_if_fail (outbuf != NULL, GST_FLOW_ERROR);
7191
7192             ret = gst_qtdemux_decorate_and_push_buffer (demux, stream, outbuf,
7193                 dts, pts, duration, keyframe, dts, demux->offset);
7194           }
7195
7196           /* combine flows */
7197           ret = gst_qtdemux_combine_flows (demux, stream, ret);
7198         } else {
7199           /* skip this data, stream is EOS */
7200           gst_adapter_flush (demux->adapter, demux->neededbytes);
7201         }
7202
7203         stream->sample_index++;
7204         stream->offset_in_sample = 0;
7205
7206         /* update current offset and figure out size of next buffer */
7207         GST_LOG_OBJECT (demux, "increasing offset %" G_GUINT64_FORMAT " by %u",
7208             demux->offset, demux->neededbytes);
7209         demux->offset += demux->neededbytes;
7210         GST_LOG_OBJECT (demux, "offset is now %" G_GUINT64_FORMAT,
7211             demux->offset);
7212
7213
7214         if (ret == GST_FLOW_EOS) {
7215           GST_DEBUG_OBJECT (demux, "All streams are EOS, signal upstream");
7216           demux->neededbytes = -1;
7217           goto eos;
7218         }
7219
7220         if ((demux->neededbytes = next_entry_size (demux)) == -1) {
7221           if (demux->fragmented) {
7222             GST_DEBUG_OBJECT (demux, "(temporarily) out of fragmented samples");
7223             /* there may be more to follow, only finish this atom */
7224             demux->todrop = demux->mdatleft;
7225             demux->neededbytes = demux->todrop;
7226             break;
7227           }
7228           goto eos;
7229         }
7230         if (ret != GST_FLOW_OK && ret != GST_FLOW_NOT_LINKED) {
7231           goto non_ok_unlinked_flow;
7232         }
7233         break;
7234       }
7235       default:
7236         goto invalid_state;
7237     }
7238   }
7239
7240   /* when buffering movie data, at least show user something is happening */
7241   if (ret == GST_FLOW_OK && demux->state == QTDEMUX_STATE_BUFFER_MDAT &&
7242       gst_adapter_available (demux->adapter) <= demux->neededbytes) {
7243     gst_qtdemux_post_progress (demux, gst_adapter_available (demux->adapter),
7244         demux->neededbytes);
7245   }
7246 done:
7247
7248   return ret;
7249
7250   /* ERRORS */
7251 non_ok_unlinked_flow:
7252   {
7253     GST_DEBUG_OBJECT (demux, "Stopping, combined return flow %s",
7254         gst_flow_get_name (ret));
7255     return ret;
7256   }
7257 unknown_stream:
7258   {
7259     GST_ELEMENT_ERROR (demux, STREAM, FAILED, (NULL), ("unknown stream found"));
7260     ret = GST_FLOW_ERROR;
7261     goto done;
7262   }
7263 eos:
7264   {
7265     GST_DEBUG_OBJECT (demux, "no next entry, EOS");
7266     ret = GST_FLOW_EOS;
7267     goto done;
7268   }
7269 invalid_state:
7270   {
7271     GST_ELEMENT_ERROR (demux, STREAM, FAILED,
7272         (NULL), ("qtdemuxer invalid state %d", demux->state));
7273     ret = GST_FLOW_ERROR;
7274     goto done;
7275   }
7276 no_moov:
7277   {
7278     GST_ELEMENT_ERROR (demux, STREAM, FAILED,
7279         (NULL), ("no 'moov' atom within the first 10 MB"));
7280     ret = GST_FLOW_ERROR;
7281     goto done;
7282   }
7283 }
7284
7285 static gboolean
7286 qtdemux_sink_activate (GstPad * sinkpad, GstObject * parent)
7287 {
7288   GstQuery *query;
7289   gboolean pull_mode;
7290
7291   query = gst_query_new_scheduling ();
7292
7293   if (!gst_pad_peer_query (sinkpad, query)) {
7294     gst_query_unref (query);
7295     goto activate_push;
7296   }
7297
7298   pull_mode = gst_query_has_scheduling_mode_with_flags (query,
7299       GST_PAD_MODE_PULL, GST_SCHEDULING_FLAG_SEEKABLE);
7300   gst_query_unref (query);
7301
7302   if (!pull_mode)
7303     goto activate_push;
7304
7305   GST_DEBUG_OBJECT (sinkpad, "activating pull");
7306   return gst_pad_activate_mode (sinkpad, GST_PAD_MODE_PULL, TRUE);
7307
7308 activate_push:
7309   {
7310     GST_DEBUG_OBJECT (sinkpad, "activating push");
7311     return gst_pad_activate_mode (sinkpad, GST_PAD_MODE_PUSH, TRUE);
7312   }
7313 }
7314
7315 static gboolean
7316 qtdemux_sink_activate_mode (GstPad * sinkpad, GstObject * parent,
7317     GstPadMode mode, gboolean active)
7318 {
7319   gboolean res;
7320   GstQTDemux *demux = GST_QTDEMUX (parent);
7321
7322   switch (mode) {
7323     case GST_PAD_MODE_PUSH:
7324       demux->pullbased = FALSE;
7325       res = TRUE;
7326       break;
7327     case GST_PAD_MODE_PULL:
7328       if (active) {
7329         demux->pullbased = TRUE;
7330         res = gst_pad_start_task (sinkpad, (GstTaskFunction) gst_qtdemux_loop,
7331             sinkpad, NULL);
7332       } else {
7333         res = gst_pad_stop_task (sinkpad);
7334       }
7335       break;
7336     default:
7337       res = FALSE;
7338       break;
7339   }
7340   return res;
7341 }
7342
7343 #ifdef HAVE_ZLIB
7344 static void *
7345 qtdemux_inflate (void *z_buffer, guint z_length, guint * length)
7346 {
7347   guint8 *buffer;
7348   z_stream z;
7349   int ret;
7350
7351   memset (&z, 0, sizeof (z));
7352   z.zalloc = NULL;
7353   z.zfree = NULL;
7354   z.opaque = NULL;
7355
7356   if ((ret = inflateInit (&z)) != Z_OK) {
7357     GST_ERROR ("inflateInit() returned %d", ret);
7358     return NULL;
7359   }
7360
7361   z.next_in = z_buffer;
7362   z.avail_in = z_length;
7363
7364   buffer = (guint8 *) g_malloc (*length);
7365   z.avail_out = *length;
7366   z.next_out = (Bytef *) buffer;
7367   do {
7368     ret = inflate (&z, Z_NO_FLUSH);
7369     if (ret == Z_STREAM_END) {
7370       break;
7371     } else if (ret != Z_OK) {
7372       GST_WARNING ("inflate() returned %d", ret);
7373       break;
7374     }
7375
7376     *length += 4096;
7377     buffer = (guint8 *) g_realloc (buffer, *length);
7378     z.next_out = (Bytef *) (buffer + z.total_out);
7379     z.avail_out += 4096;
7380   } while (z.avail_in > 0);
7381
7382   if (ret != Z_STREAM_END) {
7383     g_free (buffer);
7384     buffer = NULL;
7385     *length = 0;
7386   } else {
7387     *length = z.total_out;
7388   }
7389
7390   inflateEnd (&z);
7391
7392   return buffer;
7393 }
7394 #endif /* HAVE_ZLIB */
7395
7396 static gboolean
7397 qtdemux_parse_moov (GstQTDemux * qtdemux, const guint8 * buffer, guint length)
7398 {
7399   GNode *cmov;
7400
7401   qtdemux->moov_node = g_node_new ((guint8 *) buffer);
7402
7403   /* counts as header data */
7404   qtdemux->header_size += length;
7405
7406   GST_DEBUG_OBJECT (qtdemux, "parsing 'moov' atom");
7407   qtdemux_parse_node (qtdemux, qtdemux->moov_node, buffer, length);
7408
7409   cmov = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_cmov);
7410   if (cmov) {
7411     guint32 method;
7412     GNode *dcom;
7413     GNode *cmvd;
7414     guint32 dcom_len;
7415
7416     dcom = qtdemux_tree_get_child_by_type (cmov, FOURCC_dcom);
7417     cmvd = qtdemux_tree_get_child_by_type (cmov, FOURCC_cmvd);
7418     if (dcom == NULL || cmvd == NULL)
7419       goto invalid_compression;
7420
7421     dcom_len = QT_UINT32 (dcom->data);
7422     if (dcom_len < 12)
7423       goto invalid_compression;
7424
7425     method = QT_FOURCC ((guint8 *) dcom->data + 8);
7426     switch (method) {
7427 #ifdef HAVE_ZLIB
7428       case FOURCC_zlib:{
7429         guint uncompressed_length;
7430         guint compressed_length;
7431         guint8 *buf;
7432         guint32 cmvd_len;
7433
7434         cmvd_len = QT_UINT32 ((guint8 *) cmvd->data);
7435         if (cmvd_len < 12)
7436           goto invalid_compression;
7437
7438         uncompressed_length = QT_UINT32 ((guint8 *) cmvd->data + 8);
7439         compressed_length = cmvd_len - 12;
7440         GST_LOG ("length = %u", uncompressed_length);
7441
7442         buf =
7443             (guint8 *) qtdemux_inflate ((guint8 *) cmvd->data + 12,
7444             compressed_length, &uncompressed_length);
7445
7446         if (buf) {
7447           qtdemux->moov_node_compressed = qtdemux->moov_node;
7448           qtdemux->moov_node = g_node_new (buf);
7449
7450           qtdemux_parse_node (qtdemux, qtdemux->moov_node, buf,
7451               uncompressed_length);
7452         }
7453         break;
7454       }
7455 #endif /* HAVE_ZLIB */
7456       default:
7457         GST_WARNING_OBJECT (qtdemux, "unknown or unhandled header compression "
7458             "type %" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (method));
7459         break;
7460     }
7461   }
7462   return TRUE;
7463
7464   /* ERRORS */
7465 invalid_compression:
7466   {
7467     GST_ERROR_OBJECT (qtdemux, "invalid compressed header");
7468     return FALSE;
7469   }
7470 }
7471
7472 static gboolean
7473 qtdemux_parse_container (GstQTDemux * qtdemux, GNode * node, const guint8 * buf,
7474     const guint8 * end)
7475 {
7476   while (G_UNLIKELY (buf < end)) {
7477     GNode *child;
7478     guint32 len;
7479
7480     if (G_UNLIKELY (buf + 4 > end)) {
7481       GST_LOG_OBJECT (qtdemux, "buffer overrun");
7482       break;
7483     }
7484     len = QT_UINT32 (buf);
7485     if (G_UNLIKELY (len == 0)) {
7486       GST_LOG_OBJECT (qtdemux, "empty container");
7487       break;
7488     }
7489     if (G_UNLIKELY (len < 8)) {
7490       GST_WARNING_OBJECT (qtdemux, "length too short (%d < 8)", len);
7491       break;
7492     }
7493     if (G_UNLIKELY (len > (end - buf))) {
7494       GST_WARNING_OBJECT (qtdemux, "length too long (%d > %d)", len,
7495           (gint) (end - buf));
7496       break;
7497     }
7498
7499     child = g_node_new ((guint8 *) buf);
7500     g_node_append (node, child);
7501     GST_LOG_OBJECT (qtdemux, "adding new node of len %d", len);
7502     qtdemux_parse_node (qtdemux, child, buf, len);
7503
7504     buf += len;
7505   }
7506   return TRUE;
7507 }
7508
7509 static gboolean
7510 qtdemux_parse_theora_extension (GstQTDemux * qtdemux, QtDemuxStream * stream,
7511     GNode * xdxt)
7512 {
7513   int len = QT_UINT32 (xdxt->data);
7514   guint8 *buf = xdxt->data;
7515   guint8 *end = buf + len;
7516   GstBuffer *buffer;
7517
7518   /* skip size and type */
7519   buf += 8;
7520   end -= 8;
7521
7522   while (buf < end) {
7523     gint size;
7524     guint32 type;
7525
7526     size = QT_UINT32 (buf);
7527     type = QT_FOURCC (buf + 4);
7528
7529     GST_LOG_OBJECT (qtdemux, "%p %p", buf, end);
7530
7531     if (buf + size > end || size <= 0)
7532       break;
7533
7534     buf += 8;
7535     size -= 8;
7536
7537     GST_WARNING_OBJECT (qtdemux, "have cookie %" GST_FOURCC_FORMAT,
7538         GST_FOURCC_ARGS (type));
7539
7540     switch (type) {
7541       case FOURCC_tCtH:
7542         buffer = gst_buffer_new_and_alloc (size);
7543         gst_buffer_fill (buffer, 0, buf, size);
7544         stream->buffers = g_slist_append (stream->buffers, buffer);
7545         GST_LOG_OBJECT (qtdemux, "parsing theora header");
7546         break;
7547       case FOURCC_tCt_:
7548         buffer = gst_buffer_new_and_alloc (size);
7549         gst_buffer_fill (buffer, 0, buf, size);
7550         stream->buffers = g_slist_append (stream->buffers, buffer);
7551         GST_LOG_OBJECT (qtdemux, "parsing theora comment");
7552         break;
7553       case FOURCC_tCtC:
7554         buffer = gst_buffer_new_and_alloc (size);
7555         gst_buffer_fill (buffer, 0, buf, size);
7556         stream->buffers = g_slist_append (stream->buffers, buffer);
7557         GST_LOG_OBJECT (qtdemux, "parsing theora codebook");
7558         break;
7559       default:
7560         GST_WARNING_OBJECT (qtdemux,
7561             "unknown theora cookie %" GST_FOURCC_FORMAT,
7562             GST_FOURCC_ARGS (type));
7563         break;
7564     }
7565     buf += size;
7566   }
7567   return TRUE;
7568 }
7569
7570 static gboolean
7571 qtdemux_parse_node (GstQTDemux * qtdemux, GNode * node, const guint8 * buffer,
7572     guint length)
7573 {
7574   guint32 fourcc = 0;
7575   guint32 node_length = 0;
7576   const QtNodeType *type;
7577   const guint8 *end;
7578
7579   GST_LOG_OBJECT (qtdemux, "qtdemux_parse buffer %p length %u", buffer, length);
7580
7581   if (G_UNLIKELY (length < 8))
7582     goto not_enough_data;
7583
7584   node_length = QT_UINT32 (buffer);
7585   fourcc = QT_FOURCC (buffer + 4);
7586
7587   /* ignore empty nodes */
7588   if (G_UNLIKELY (fourcc == 0 || node_length == 8))
7589     return TRUE;
7590
7591   type = qtdemux_type_get (fourcc);
7592
7593   end = buffer + length;
7594
7595   GST_LOG_OBJECT (qtdemux,
7596       "parsing '%" GST_FOURCC_FORMAT "', length=%u, name '%s'",
7597       GST_FOURCC_ARGS (fourcc), node_length, type->name);
7598
7599   if (node_length > length)
7600     goto broken_atom_size;
7601
7602   if (type->flags & QT_FLAG_CONTAINER) {
7603     qtdemux_parse_container (qtdemux, node, buffer + 8, end);
7604   } else {
7605     switch (fourcc) {
7606       case FOURCC_stsd:
7607       {
7608         if (node_length < 20) {
7609           GST_LOG_OBJECT (qtdemux, "skipping small stsd box");
7610           break;
7611         }
7612         GST_DEBUG_OBJECT (qtdemux,
7613             "parsing stsd (sample table, sample description) atom");
7614         /* Skip over 8 byte atom hdr + 1 byte version, 3 bytes flags, 4 byte num_entries */
7615         qtdemux_parse_container (qtdemux, node, buffer + 16, end);
7616         break;
7617       }
7618       case FOURCC_mp4a:
7619       case FOURCC_alac:
7620       case FOURCC_fLaC:
7621       {
7622         guint32 version;
7623         guint32 offset;
7624         guint min_size;
7625
7626         /* also read alac (or whatever) in stead of mp4a in the following,
7627          * since a similar layout is used in other cases as well */
7628         if (fourcc == FOURCC_mp4a)
7629           min_size = 20;
7630         else if (fourcc == FOURCC_fLaC)
7631           min_size = 86;
7632         else
7633           min_size = 40;
7634
7635         /* There are two things we might encounter here: a true mp4a atom, and
7636            an mp4a entry in an stsd atom. The latter is what we're interested
7637            in, and it looks like an atom, but isn't really one. The true mp4a
7638            atom is short, so we detect it based on length here. */
7639         if (length < min_size) {
7640           GST_LOG_OBJECT (qtdemux, "skipping small %" GST_FOURCC_FORMAT " box",
7641               GST_FOURCC_ARGS (fourcc));
7642           break;
7643         }
7644
7645         /* 'version' here is the sound sample description version. Types 0 and
7646            1 are documented in the QTFF reference, but type 2 is not: it's
7647            described in Apple header files instead (struct SoundDescriptionV2
7648            in Movies.h) */
7649         version = QT_UINT16 (buffer + 16);
7650
7651         GST_DEBUG_OBJECT (qtdemux, "%" GST_FOURCC_FORMAT " version 0x%08x",
7652             GST_FOURCC_ARGS (fourcc), version);
7653
7654         /* parse any esds descriptors */
7655         switch (version) {
7656           case 0:
7657             offset = 0x24;
7658             break;
7659           case 1:
7660             offset = 0x34;
7661             break;
7662           case 2:
7663             offset = 0x48;
7664             break;
7665           default:
7666             GST_WARNING_OBJECT (qtdemux,
7667                 "unhandled %" GST_FOURCC_FORMAT " version 0x%08x",
7668                 GST_FOURCC_ARGS (fourcc), version);
7669             offset = 0;
7670             break;
7671         }
7672         if (offset)
7673           qtdemux_parse_container (qtdemux, node, buffer + offset, end);
7674         break;
7675       }
7676       case FOURCC_mp4v:
7677       case FOURCC_MP4V:
7678       case FOURCC_fmp4:
7679       case FOURCC_FMP4:
7680       case FOURCC_apcs:
7681       case FOURCC_apch:
7682       case FOURCC_apcn:
7683       case FOURCC_apco:
7684       case FOURCC_ap4h:
7685       case FOURCC_xvid:
7686       case FOURCC_XVID:
7687       case FOURCC_H264:
7688       case FOURCC_avc1:
7689       case FOURCC_avc3:
7690       case FOURCC_H265:
7691       case FOURCC_hvc1:
7692       case FOURCC_hev1:
7693       case FOURCC_mjp2:
7694       case FOURCC_encv:
7695       {
7696         guint32 version;
7697         guint32 str_len;
7698
7699         /* codec_data is contained inside these atoms, which all have
7700          * the same format. */
7701         /* video sample description size is 86 bytes without extension.
7702          * node_length have to be bigger than 86 bytes because video sample
7703          * description can include extenstions such as esds, fiel, glbl, etc. */
7704         if (node_length < 86) {
7705           GST_WARNING_OBJECT (qtdemux, "%" GST_FOURCC_FORMAT
7706               " sample description length too short (%u < 86)",
7707               GST_FOURCC_ARGS (fourcc), node_length);
7708           break;
7709         }
7710
7711         GST_DEBUG_OBJECT (qtdemux, "parsing in %" GST_FOURCC_FORMAT,
7712             GST_FOURCC_ARGS (fourcc));
7713
7714         /* version (2 bytes) : this is set to 0, unless a compressor has changed
7715          *              its data format.
7716          * revision level (2 bytes) : must be set to 0. */
7717         version = QT_UINT32 (buffer + 16);
7718         GST_DEBUG_OBJECT (qtdemux, "version %08x", version);
7719
7720         /* compressor name : PASCAL string and informative purposes
7721          * first byte : the number of bytes to be displayed.
7722          *              it has to be less than 32 because it is reserved
7723          *              space of 32 bytes total including itself. */
7724         str_len = QT_UINT8 (buffer + 50);
7725         if (str_len < 32)
7726           GST_DEBUG_OBJECT (qtdemux, "compressorname = %.*s", str_len,
7727               (char *) buffer + 51);
7728         else
7729           GST_WARNING_OBJECT (qtdemux,
7730               "compressorname length too big (%u > 31)", str_len);
7731
7732         GST_MEMDUMP_OBJECT (qtdemux, "video sample description", buffer,
7733             end - buffer);
7734         qtdemux_parse_container (qtdemux, node, buffer + 86, end);
7735         break;
7736       }
7737       case FOURCC_meta:
7738       {
7739         GST_DEBUG_OBJECT (qtdemux, "parsing meta atom");
7740
7741         /* You are reading this correctly. QTFF specifies that the
7742          * metadata atom is a short atom, whereas ISO BMFF specifies
7743          * it's a full atom. But since so many people are doing things
7744          * differently, we actually peek into the atom to see which
7745          * variant it is */
7746         if (length < 16) {
7747           GST_LOG_OBJECT (qtdemux, "skipping small %" GST_FOURCC_FORMAT " box",
7748               GST_FOURCC_ARGS (fourcc));
7749           break;
7750         }
7751         if (QT_FOURCC (buffer + 12) == FOURCC_hdlr) {
7752           /* Variant 1: What QTFF specifies. 'meta' is a short header which
7753            * starts with a 'hdlr' atom */
7754           qtdemux_parse_container (qtdemux, node, buffer + 8, end);
7755         } else if (QT_UINT32 (buffer + 8) == 0x00000000) {
7756           /* Variant 2: What ISO BMFF specifies. 'meta' is a _full_ atom
7757            * with version/flags both set to zero */
7758           qtdemux_parse_container (qtdemux, node, buffer + 12, end);
7759         } else
7760           GST_WARNING_OBJECT (qtdemux, "Unknown 'meta' atom format");
7761         break;
7762       }
7763       case FOURCC_mp4s:
7764       {
7765         GST_MEMDUMP_OBJECT (qtdemux, "mp4s", buffer, end - buffer);
7766         /* Skip 8 byte header, plus 8 byte version + flags + entry_count */
7767         qtdemux_parse_container (qtdemux, node, buffer + 16, end);
7768         break;
7769       }
7770       case FOURCC_XiTh:
7771       {
7772         guint32 version;
7773         guint32 offset;
7774
7775         if (length < 16) {
7776           GST_LOG_OBJECT (qtdemux, "skipping small %" GST_FOURCC_FORMAT " box",
7777               GST_FOURCC_ARGS (fourcc));
7778           break;
7779         }
7780
7781         version = QT_UINT32 (buffer + 12);
7782         GST_DEBUG_OBJECT (qtdemux, "parsing XiTh atom version 0x%08x", version);
7783
7784         switch (version) {
7785           case 0x00000001:
7786             offset = 0x62;
7787             break;
7788           default:
7789             GST_DEBUG_OBJECT (qtdemux, "unknown version 0x%08x", version);
7790             offset = 0;
7791             break;
7792         }
7793         if (offset) {
7794           if (length < offset) {
7795             GST_WARNING_OBJECT (qtdemux,
7796                 "skipping too small %" GST_FOURCC_FORMAT " box",
7797                 GST_FOURCC_ARGS (fourcc));
7798             break;
7799           }
7800           qtdemux_parse_container (qtdemux, node, buffer + offset, end);
7801         }
7802         break;
7803       }
7804       case FOURCC_in24:
7805       {
7806         qtdemux_parse_container (qtdemux, node, buffer + 0x34, end);
7807         break;
7808       }
7809       case FOURCC_uuid:
7810       {
7811         qtdemux_parse_uuid (qtdemux, buffer, end - buffer);
7812         break;
7813       }
7814       case FOURCC_enca:
7815       {
7816         qtdemux_parse_container (qtdemux, node, buffer + 36, end);
7817         break;
7818       }
7819       default:
7820         if (!strcmp (type->name, "unknown"))
7821           GST_MEMDUMP ("Unknown tag", buffer + 4, end - buffer - 4);
7822         break;
7823     }
7824   }
7825   GST_LOG_OBJECT (qtdemux, "parsed '%" GST_FOURCC_FORMAT "'",
7826       GST_FOURCC_ARGS (fourcc));
7827   return TRUE;
7828
7829 /* ERRORS */
7830 not_enough_data:
7831   {
7832     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
7833         (_("This file is corrupt and cannot be played.")),
7834         ("Not enough data for an atom header, got only %u bytes", length));
7835     return FALSE;
7836   }
7837 broken_atom_size:
7838   {
7839     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
7840         (_("This file is corrupt and cannot be played.")),
7841         ("Atom '%" GST_FOURCC_FORMAT "' has size of %u bytes, but we have only "
7842             "%u bytes available.", GST_FOURCC_ARGS (fourcc), node_length,
7843             length));
7844     return FALSE;
7845   }
7846 }
7847
7848 static GNode *
7849 qtdemux_tree_get_child_by_type (GNode * node, guint32 fourcc)
7850 {
7851   GNode *child;
7852   guint8 *buffer;
7853   guint32 child_fourcc;
7854
7855   for (child = g_node_first_child (node); child;
7856       child = g_node_next_sibling (child)) {
7857     buffer = (guint8 *) child->data;
7858
7859     child_fourcc = QT_FOURCC (buffer + 4);
7860
7861     if (G_UNLIKELY (child_fourcc == fourcc)) {
7862       return child;
7863     }
7864   }
7865   return NULL;
7866 }
7867
7868 static GNode *
7869 qtdemux_tree_get_child_by_type_full (GNode * node, guint32 fourcc,
7870     GstByteReader * parser)
7871 {
7872   GNode *child;
7873   guint8 *buffer;
7874   guint32 child_fourcc, child_len;
7875
7876   for (child = g_node_first_child (node); child;
7877       child = g_node_next_sibling (child)) {
7878     buffer = (guint8 *) child->data;
7879
7880     child_len = QT_UINT32 (buffer);
7881     child_fourcc = QT_FOURCC (buffer + 4);
7882
7883     if (G_UNLIKELY (child_fourcc == fourcc)) {
7884       if (G_UNLIKELY (child_len < (4 + 4)))
7885         return NULL;
7886       /* FIXME: must verify if atom length < parent atom length */
7887       gst_byte_reader_init (parser, buffer + (4 + 4), child_len - (4 + 4));
7888       return child;
7889     }
7890   }
7891   return NULL;
7892 }
7893
7894 static GNode *
7895 qtdemux_tree_get_child_by_index (GNode * node, guint index)
7896 {
7897   return g_node_nth_child (node, index);
7898 }
7899
7900 static GNode *
7901 qtdemux_tree_get_sibling_by_type_full (GNode * node, guint32 fourcc,
7902     GstByteReader * parser)
7903 {
7904   GNode *child;
7905   guint8 *buffer;
7906   guint32 child_fourcc, child_len;
7907
7908   for (child = g_node_next_sibling (node); child;
7909       child = g_node_next_sibling (child)) {
7910     buffer = (guint8 *) child->data;
7911
7912     child_fourcc = QT_FOURCC (buffer + 4);
7913
7914     if (child_fourcc == fourcc) {
7915       if (parser) {
7916         child_len = QT_UINT32 (buffer);
7917         if (G_UNLIKELY (child_len < (4 + 4)))
7918           return NULL;
7919         /* FIXME: must verify if atom length < parent atom length */
7920         gst_byte_reader_init (parser, buffer + (4 + 4), child_len - (4 + 4));
7921       }
7922       return child;
7923     }
7924   }
7925   return NULL;
7926 }
7927
7928 static GNode *
7929 qtdemux_tree_get_sibling_by_type (GNode * node, guint32 fourcc)
7930 {
7931   return qtdemux_tree_get_sibling_by_type_full (node, fourcc, NULL);
7932 }
7933
7934 static void
7935 qtdemux_do_allocation (GstQTDemux * qtdemux, QtDemuxStream * stream)
7936 {
7937 /* FIXME: This can only reliably work if demuxers have a
7938  * separate streaming thread per srcpad. This should be
7939  * done in a demuxer base class, which integrates parts
7940  * of multiqueue
7941  *
7942  * https://bugzilla.gnome.org/show_bug.cgi?id=701856
7943  */
7944 #if 0
7945   GstQuery *query;
7946
7947   query = gst_query_new_allocation (stream->caps, FALSE);
7948
7949   if (!gst_pad_peer_query (stream->pad, query)) {
7950     /* not a problem, just debug a little */
7951     GST_DEBUG_OBJECT (qtdemux, "peer ALLOCATION query failed");
7952   }
7953
7954   if (stream->allocator)
7955     gst_object_unref (stream->allocator);
7956
7957   if (gst_query_get_n_allocation_params (query) > 0) {
7958     /* try the allocator */
7959     gst_query_parse_nth_allocation_param (query, 0, &stream->allocator,
7960         &stream->params);
7961     stream->use_allocator = TRUE;
7962   } else {
7963     stream->allocator = NULL;
7964     gst_allocation_params_init (&stream->params);
7965     stream->use_allocator = FALSE;
7966   }
7967   gst_query_unref (query);
7968 #endif
7969 }
7970
7971 static gboolean
7972 gst_qtdemux_configure_protected_caps (GstQTDemux * qtdemux,
7973     QtDemuxStream * stream)
7974 {
7975   GstStructure *s;
7976   const gchar *selected_system;
7977
7978   g_return_val_if_fail (qtdemux != NULL, FALSE);
7979   g_return_val_if_fail (stream != NULL, FALSE);
7980   g_return_val_if_fail (gst_caps_get_size (CUR_STREAM (stream)->caps) == 1,
7981       FALSE);
7982
7983   if (stream->protection_scheme_type != FOURCC_cenc) {
7984     GST_ERROR_OBJECT (qtdemux, "unsupported protection scheme");
7985     return FALSE;
7986   }
7987   if (qtdemux->protection_system_ids == NULL) {
7988     GST_ERROR_OBJECT (qtdemux, "stream is protected using cenc, but no "
7989         "cenc protection system information has been found");
7990     return FALSE;
7991   }
7992   g_ptr_array_add (qtdemux->protection_system_ids, NULL);
7993   selected_system = gst_protection_select_system ((const gchar **)
7994       qtdemux->protection_system_ids->pdata);
7995   g_ptr_array_remove_index (qtdemux->protection_system_ids,
7996       qtdemux->protection_system_ids->len - 1);
7997   if (!selected_system) {
7998     GST_ERROR_OBJECT (qtdemux, "stream is protected, but no "
7999         "suitable decryptor element has been found");
8000     return FALSE;
8001   }
8002
8003   s = gst_caps_get_structure (CUR_STREAM (stream)->caps, 0);
8004   if (!gst_structure_has_name (s, "application/x-cenc")) {
8005     gst_structure_set (s,
8006         "original-media-type", G_TYPE_STRING, gst_structure_get_name (s),
8007         GST_PROTECTION_SYSTEM_ID_CAPS_FIELD, G_TYPE_STRING, selected_system,
8008         NULL);
8009     gst_structure_set_name (s, "application/x-cenc");
8010   }
8011   return TRUE;
8012 }
8013
8014 static gboolean
8015 gst_qtdemux_configure_stream (GstQTDemux * qtdemux, QtDemuxStream * stream)
8016 {
8017   if (stream->subtype == FOURCC_vide) {
8018     /* fps is calculated base on the duration of the average framerate since
8019      * qt does not have a fixed framerate. */
8020     gboolean fps_available = TRUE;
8021
8022     if ((stream->n_samples == 1 && stream->first_duration == 0)
8023         || (qtdemux->fragmented && stream->n_samples_moof == 1)) {
8024       /* still frame */
8025       CUR_STREAM (stream)->fps_n = 0;
8026       CUR_STREAM (stream)->fps_d = 1;
8027     } else {
8028       if (stream->duration == 0 || stream->n_samples < 2) {
8029         CUR_STREAM (stream)->fps_n = stream->timescale;
8030         CUR_STREAM (stream)->fps_d = 1;
8031         fps_available = FALSE;
8032       } else {
8033         GstClockTime avg_duration;
8034         guint64 duration;
8035         guint32 n_samples;
8036
8037         /* duration and n_samples can be updated for fragmented format
8038          * so, framerate of fragmented format is calculated using data in a moof */
8039         if (qtdemux->fragmented && stream->n_samples_moof > 0
8040             && stream->duration_moof > 0) {
8041           n_samples = stream->n_samples_moof;
8042           duration = stream->duration_moof;
8043         } else {
8044           n_samples = stream->n_samples;
8045           duration = stream->duration;
8046         }
8047
8048         /* Calculate a framerate, ignoring the first sample which is sometimes truncated */
8049         /* stream->duration is guint64, timescale, n_samples are guint32 */
8050         avg_duration =
8051             gst_util_uint64_scale_round (duration -
8052             stream->first_duration, GST_SECOND,
8053             (guint64) (stream->timescale) * (n_samples - 1));
8054
8055         GST_LOG_OBJECT (qtdemux,
8056             "Calculating avg sample duration based on stream (or moof) duration %"
8057             G_GUINT64_FORMAT
8058             " minus first sample %u, leaving %d samples gives %"
8059             GST_TIME_FORMAT, duration, stream->first_duration,
8060             n_samples - 1, GST_TIME_ARGS (avg_duration));
8061
8062         gst_video_guess_framerate (avg_duration, &CUR_STREAM (stream)->fps_n,
8063             &CUR_STREAM (stream)->fps_d);
8064
8065         GST_DEBUG_OBJECT (qtdemux,
8066             "Calculating framerate, timescale %u gave fps_n %d fps_d %d",
8067             stream->timescale, CUR_STREAM (stream)->fps_n,
8068             CUR_STREAM (stream)->fps_d);
8069       }
8070     }
8071
8072     if (CUR_STREAM (stream)->caps) {
8073       CUR_STREAM (stream)->caps =
8074           gst_caps_make_writable (CUR_STREAM (stream)->caps);
8075
8076       gst_caps_set_simple (CUR_STREAM (stream)->caps,
8077           "width", G_TYPE_INT, CUR_STREAM (stream)->width,
8078           "height", G_TYPE_INT, CUR_STREAM (stream)->height, NULL);
8079
8080       /* set framerate if calculated framerate is reliable */
8081       if (fps_available) {
8082         gst_caps_set_simple (CUR_STREAM (stream)->caps,
8083             "framerate", GST_TYPE_FRACTION, CUR_STREAM (stream)->fps_n,
8084             CUR_STREAM (stream)->fps_d, NULL);
8085       }
8086
8087       /* calculate pixel-aspect-ratio using display width and height */
8088       GST_DEBUG_OBJECT (qtdemux,
8089           "video size %dx%d, target display size %dx%d",
8090           CUR_STREAM (stream)->width, CUR_STREAM (stream)->height,
8091           stream->display_width, stream->display_height);
8092       /* qt file might have pasp atom */
8093       if (CUR_STREAM (stream)->par_w > 0 && CUR_STREAM (stream)->par_h > 0) {
8094         GST_DEBUG_OBJECT (qtdemux, "par %d:%d", CUR_STREAM (stream)->par_w,
8095             CUR_STREAM (stream)->par_h);
8096         gst_caps_set_simple (CUR_STREAM (stream)->caps, "pixel-aspect-ratio",
8097             GST_TYPE_FRACTION, CUR_STREAM (stream)->par_w,
8098             CUR_STREAM (stream)->par_h, NULL);
8099       } else if (stream->display_width > 0 && stream->display_height > 0
8100           && CUR_STREAM (stream)->width > 0
8101           && CUR_STREAM (stream)->height > 0) {
8102         gint n, d;
8103
8104         /* calculate the pixel aspect ratio using the display and pixel w/h */
8105         n = stream->display_width * CUR_STREAM (stream)->height;
8106         d = stream->display_height * CUR_STREAM (stream)->width;
8107         if (n == d)
8108           n = d = 1;
8109         GST_DEBUG_OBJECT (qtdemux, "setting PAR to %d/%d", n, d);
8110         CUR_STREAM (stream)->par_w = n;
8111         CUR_STREAM (stream)->par_h = d;
8112         gst_caps_set_simple (CUR_STREAM (stream)->caps, "pixel-aspect-ratio",
8113             GST_TYPE_FRACTION, CUR_STREAM (stream)->par_w,
8114             CUR_STREAM (stream)->par_h, NULL);
8115       }
8116
8117       if (CUR_STREAM (stream)->interlace_mode > 0) {
8118         if (CUR_STREAM (stream)->interlace_mode == 1) {
8119           gst_caps_set_simple (CUR_STREAM (stream)->caps, "interlace-mode",
8120               G_TYPE_STRING, "progressive", NULL);
8121         } else if (CUR_STREAM (stream)->interlace_mode == 2) {
8122           gst_caps_set_simple (CUR_STREAM (stream)->caps, "interlace-mode",
8123               G_TYPE_STRING, "interleaved", NULL);
8124           if (CUR_STREAM (stream)->field_order == 9) {
8125             gst_caps_set_simple (CUR_STREAM (stream)->caps, "field-order",
8126                 G_TYPE_STRING, "top-field-first", NULL);
8127           } else if (CUR_STREAM (stream)->field_order == 14) {
8128             gst_caps_set_simple (CUR_STREAM (stream)->caps, "field-order",
8129                 G_TYPE_STRING, "bottom-field-first", NULL);
8130           }
8131         }
8132       }
8133
8134       /* Create incomplete colorimetry here if needed */
8135       if (CUR_STREAM (stream)->colorimetry.range ||
8136           CUR_STREAM (stream)->colorimetry.matrix ||
8137           CUR_STREAM (stream)->colorimetry.transfer
8138           || CUR_STREAM (stream)->colorimetry.primaries) {
8139         gchar *colorimetry =
8140             gst_video_colorimetry_to_string (&CUR_STREAM (stream)->colorimetry);
8141         gst_caps_set_simple (CUR_STREAM (stream)->caps, "colorimetry",
8142             G_TYPE_STRING, colorimetry, NULL);
8143         g_free (colorimetry);
8144       }
8145
8146       if (stream->multiview_mode != GST_VIDEO_MULTIVIEW_MODE_NONE) {
8147         guint par_w = 1, par_h = 1;
8148
8149         if (CUR_STREAM (stream)->par_w > 0 && CUR_STREAM (stream)->par_h > 0) {
8150           par_w = CUR_STREAM (stream)->par_w;
8151           par_h = CUR_STREAM (stream)->par_h;
8152         }
8153
8154         if (gst_video_multiview_guess_half_aspect (stream->multiview_mode,
8155                 CUR_STREAM (stream)->width, CUR_STREAM (stream)->height, par_w,
8156                 par_h)) {
8157           stream->multiview_flags |= GST_VIDEO_MULTIVIEW_FLAGS_HALF_ASPECT;
8158         }
8159
8160         gst_caps_set_simple (CUR_STREAM (stream)->caps,
8161             "multiview-mode", G_TYPE_STRING,
8162             gst_video_multiview_mode_to_caps_string (stream->multiview_mode),
8163             "multiview-flags", GST_TYPE_VIDEO_MULTIVIEW_FLAGSET,
8164             stream->multiview_flags, GST_FLAG_SET_MASK_EXACT, NULL);
8165       }
8166     }
8167   }
8168
8169   else if (stream->subtype == FOURCC_soun) {
8170     if (CUR_STREAM (stream)->caps) {
8171       CUR_STREAM (stream)->caps =
8172           gst_caps_make_writable (CUR_STREAM (stream)->caps);
8173       if (CUR_STREAM (stream)->rate > 0)
8174         gst_caps_set_simple (CUR_STREAM (stream)->caps,
8175             "rate", G_TYPE_INT, (int) CUR_STREAM (stream)->rate, NULL);
8176       if (CUR_STREAM (stream)->n_channels > 0)
8177         gst_caps_set_simple (CUR_STREAM (stream)->caps,
8178             "channels", G_TYPE_INT, CUR_STREAM (stream)->n_channels, NULL);
8179       if (CUR_STREAM (stream)->n_channels > 2) {
8180         /* FIXME: Need to parse the 'chan' atom to get channel layouts
8181          * correctly; this is just the minimum we can do - assume
8182          * we don't actually have any channel positions. */
8183         gst_caps_set_simple (CUR_STREAM (stream)->caps,
8184             "channel-mask", GST_TYPE_BITMASK, G_GUINT64_CONSTANT (0), NULL);
8185       }
8186     }
8187   }
8188
8189   if (stream->pad) {
8190     GstCaps *prev_caps = NULL;
8191
8192     GST_PAD_ELEMENT_PRIVATE (stream->pad) = stream;
8193     gst_pad_set_event_function (stream->pad, gst_qtdemux_handle_src_event);
8194     gst_pad_set_query_function (stream->pad, gst_qtdemux_handle_src_query);
8195     gst_pad_set_active (stream->pad, TRUE);
8196
8197     gst_pad_use_fixed_caps (stream->pad);
8198
8199     if (stream->protected) {
8200       if (!gst_qtdemux_configure_protected_caps (qtdemux, stream)) {
8201         GST_ERROR_OBJECT (qtdemux,
8202             "Failed to configure protected stream caps.");
8203         return FALSE;
8204       }
8205     }
8206
8207     GST_DEBUG_OBJECT (qtdemux, "setting caps %" GST_PTR_FORMAT,
8208         CUR_STREAM (stream)->caps);
8209     if (stream->new_stream) {
8210       GstEvent *event;
8211       GstStreamFlags stream_flags = GST_STREAM_FLAG_NONE;
8212
8213       event =
8214           gst_pad_get_sticky_event (qtdemux->sinkpad, GST_EVENT_STREAM_START,
8215           0);
8216       if (event) {
8217         gst_event_parse_stream_flags (event, &stream_flags);
8218         if (gst_event_parse_group_id (event, &qtdemux->group_id))
8219           qtdemux->have_group_id = TRUE;
8220         else
8221           qtdemux->have_group_id = FALSE;
8222         gst_event_unref (event);
8223       } else if (!qtdemux->have_group_id) {
8224         qtdemux->have_group_id = TRUE;
8225         qtdemux->group_id = gst_util_group_id_next ();
8226       }
8227
8228       stream->new_stream = FALSE;
8229       event = gst_event_new_stream_start (stream->stream_id);
8230       if (qtdemux->have_group_id)
8231         gst_event_set_group_id (event, qtdemux->group_id);
8232       if (stream->disabled)
8233         stream_flags |= GST_STREAM_FLAG_UNSELECT;
8234       if (CUR_STREAM (stream)->sparse) {
8235         stream_flags |= GST_STREAM_FLAG_SPARSE;
8236       } else {
8237         stream_flags &= ~GST_STREAM_FLAG_SPARSE;
8238       }
8239       gst_event_set_stream_flags (event, stream_flags);
8240       gst_pad_push_event (stream->pad, event);
8241     }
8242
8243     prev_caps = gst_pad_get_current_caps (stream->pad);
8244
8245     if (CUR_STREAM (stream)->caps) {
8246       if (!prev_caps
8247           || !gst_caps_is_equal_fixed (prev_caps, CUR_STREAM (stream)->caps)) {
8248         GST_DEBUG_OBJECT (qtdemux, "setting caps %" GST_PTR_FORMAT,
8249             CUR_STREAM (stream)->caps);
8250         gst_pad_set_caps (stream->pad, CUR_STREAM (stream)->caps);
8251       } else {
8252         GST_DEBUG_OBJECT (qtdemux, "ignore duplicated caps");
8253       }
8254     } else {
8255       GST_WARNING_OBJECT (qtdemux, "stream without caps");
8256     }
8257
8258     if (prev_caps)
8259       gst_caps_unref (prev_caps);
8260     stream->new_caps = FALSE;
8261   }
8262   return TRUE;
8263 }
8264
8265 static void
8266 gst_qtdemux_stream_check_and_change_stsd_index (GstQTDemux * demux,
8267     QtDemuxStream * stream)
8268 {
8269   if (stream->cur_stsd_entry_index == stream->stsd_sample_description_id)
8270     return;
8271
8272   GST_DEBUG_OBJECT (stream->pad, "Changing stsd index from '%u' to '%u'",
8273       stream->cur_stsd_entry_index, stream->stsd_sample_description_id);
8274   if (G_UNLIKELY (stream->stsd_sample_description_id >=
8275           stream->stsd_entries_length)) {
8276     GST_ELEMENT_ERROR (demux, STREAM, DEMUX,
8277         (_("This file is invalid and cannot be played.")),
8278         ("New sample description id is out of bounds (%d >= %d)",
8279             stream->stsd_sample_description_id, stream->stsd_entries_length));
8280   } else {
8281     stream->cur_stsd_entry_index = stream->stsd_sample_description_id;
8282     stream->new_caps = TRUE;
8283   }
8284 }
8285
8286 static gboolean
8287 gst_qtdemux_add_stream (GstQTDemux * qtdemux,
8288     QtDemuxStream * stream, GstTagList * list)
8289 {
8290   gboolean ret = TRUE;
8291   /* consistent default for push based mode */
8292   gst_segment_init (&stream->segment, GST_FORMAT_TIME);
8293
8294   if (stream->subtype == FOURCC_vide) {
8295     gchar *name = g_strdup_printf ("video_%u", qtdemux->n_video_streams);
8296
8297     stream->pad =
8298         gst_pad_new_from_static_template (&gst_qtdemux_videosrc_template, name);
8299     g_free (name);
8300
8301     if (!gst_qtdemux_configure_stream (qtdemux, stream)) {
8302       gst_object_unref (stream->pad);
8303       stream->pad = NULL;
8304       ret = FALSE;
8305       goto done;
8306     }
8307
8308     qtdemux->n_video_streams++;
8309   } else if (stream->subtype == FOURCC_soun) {
8310     gchar *name = g_strdup_printf ("audio_%u", qtdemux->n_audio_streams);
8311
8312     stream->pad =
8313         gst_pad_new_from_static_template (&gst_qtdemux_audiosrc_template, name);
8314     g_free (name);
8315     if (!gst_qtdemux_configure_stream (qtdemux, stream)) {
8316       gst_object_unref (stream->pad);
8317       stream->pad = NULL;
8318       ret = FALSE;
8319       goto done;
8320     }
8321     qtdemux->n_audio_streams++;
8322   } else if (stream->subtype == FOURCC_strm) {
8323     GST_DEBUG_OBJECT (qtdemux, "stream type, not creating pad");
8324   } else if (stream->subtype == FOURCC_subp || stream->subtype == FOURCC_text
8325       || stream->subtype == FOURCC_sbtl || stream->subtype == FOURCC_subt) {
8326     gchar *name = g_strdup_printf ("subtitle_%u", qtdemux->n_sub_streams);
8327
8328     stream->pad =
8329         gst_pad_new_from_static_template (&gst_qtdemux_subsrc_template, name);
8330     g_free (name);
8331     if (!gst_qtdemux_configure_stream (qtdemux, stream)) {
8332       gst_object_unref (stream->pad);
8333       stream->pad = NULL;
8334       ret = FALSE;
8335       goto done;
8336     }
8337     qtdemux->n_sub_streams++;
8338   } else if (CUR_STREAM (stream)->caps) {
8339     gchar *name = g_strdup_printf ("video_%u", qtdemux->n_video_streams);
8340
8341     stream->pad =
8342         gst_pad_new_from_static_template (&gst_qtdemux_videosrc_template, name);
8343     g_free (name);
8344     if (!gst_qtdemux_configure_stream (qtdemux, stream)) {
8345       gst_object_unref (stream->pad);
8346       stream->pad = NULL;
8347       ret = FALSE;
8348       goto done;
8349     }
8350     qtdemux->n_video_streams++;
8351   } else {
8352     GST_DEBUG_OBJECT (qtdemux, "unknown stream type");
8353     goto done;
8354   }
8355
8356   if (stream->pad) {
8357     GList *l;
8358
8359     GST_DEBUG_OBJECT (qtdemux, "adding pad %s %p to qtdemux %p",
8360         GST_OBJECT_NAME (stream->pad), stream->pad, qtdemux);
8361     gst_element_add_pad (GST_ELEMENT_CAST (qtdemux), stream->pad);
8362     gst_flow_combiner_add_pad (qtdemux->flowcombiner, stream->pad);
8363
8364     if (stream->stream_tags)
8365       gst_tag_list_unref (stream->stream_tags);
8366     stream->stream_tags = list;
8367     list = NULL;
8368     /* global tags go on each pad anyway */
8369     stream->send_global_tags = TRUE;
8370     /* send upstream GST_EVENT_PROTECTION events that were received before
8371        this source pad was created */
8372     for (l = qtdemux->protection_event_queue.head; l != NULL; l = l->next)
8373       gst_pad_push_event (stream->pad, gst_event_ref (l->data));
8374   }
8375 done:
8376   if (list)
8377     gst_tag_list_unref (list);
8378   return ret;
8379 }
8380
8381 /* find next atom with @fourcc starting at @offset */
8382 static GstFlowReturn
8383 qtdemux_find_atom (GstQTDemux * qtdemux, guint64 * offset,
8384     guint64 * length, guint32 fourcc)
8385 {
8386   GstFlowReturn ret;
8387   guint32 lfourcc;
8388   GstBuffer *buf;
8389
8390   GST_LOG_OBJECT (qtdemux, "finding fourcc %" GST_FOURCC_FORMAT " at offset %"
8391       G_GUINT64_FORMAT, GST_FOURCC_ARGS (fourcc), *offset);
8392
8393   while (TRUE) {
8394     GstMapInfo map;
8395
8396     buf = NULL;
8397     ret = gst_pad_pull_range (qtdemux->sinkpad, *offset, 16, &buf);
8398     if (G_UNLIKELY (ret != GST_FLOW_OK))
8399       goto locate_failed;
8400     if (G_UNLIKELY (gst_buffer_get_size (buf) != 16)) {
8401       /* likely EOF */
8402       ret = GST_FLOW_EOS;
8403       gst_buffer_unref (buf);
8404       goto locate_failed;
8405     }
8406     gst_buffer_map (buf, &map, GST_MAP_READ);
8407     extract_initial_length_and_fourcc (map.data, 16, length, &lfourcc);
8408     gst_buffer_unmap (buf, &map);
8409     gst_buffer_unref (buf);
8410
8411     if (G_UNLIKELY (*length == 0)) {
8412       GST_DEBUG_OBJECT (qtdemux, "invalid length 0");
8413       ret = GST_FLOW_ERROR;
8414       goto locate_failed;
8415     }
8416
8417     if (lfourcc == fourcc) {
8418       GST_DEBUG_OBJECT (qtdemux, "found fourcc at offset %" G_GUINT64_FORMAT,
8419           *offset);
8420       break;
8421     } else {
8422       GST_LOG_OBJECT (qtdemux,
8423           "skipping atom '%" GST_FOURCC_FORMAT "' at %" G_GUINT64_FORMAT,
8424           GST_FOURCC_ARGS (fourcc), *offset);
8425       *offset += *length;
8426     }
8427   }
8428
8429   return GST_FLOW_OK;
8430
8431 locate_failed:
8432   {
8433     /* might simply have had last one */
8434     GST_DEBUG_OBJECT (qtdemux, "fourcc not found");
8435     return ret;
8436   }
8437 }
8438
8439 /* should only do something in pull mode */
8440 /* call with OBJECT lock */
8441 static GstFlowReturn
8442 qtdemux_add_fragmented_samples (GstQTDemux * qtdemux)
8443 {
8444   guint64 length, offset;
8445   GstBuffer *buf = NULL;
8446   GstFlowReturn ret = GST_FLOW_OK;
8447   GstFlowReturn res = GST_FLOW_OK;
8448   GstMapInfo map;
8449
8450   offset = qtdemux->moof_offset;
8451   GST_DEBUG_OBJECT (qtdemux, "next moof at offset %" G_GUINT64_FORMAT, offset);
8452
8453   if (!offset) {
8454     GST_DEBUG_OBJECT (qtdemux, "no next moof");
8455     return GST_FLOW_EOS;
8456   }
8457
8458   /* best not do pull etc with lock held */
8459   GST_OBJECT_UNLOCK (qtdemux);
8460
8461   ret = qtdemux_find_atom (qtdemux, &offset, &length, FOURCC_moof);
8462   if (ret != GST_FLOW_OK)
8463     goto flow_failed;
8464
8465   ret = gst_qtdemux_pull_atom (qtdemux, offset, length, &buf);
8466   if (G_UNLIKELY (ret != GST_FLOW_OK))
8467     goto flow_failed;
8468   gst_buffer_map (buf, &map, GST_MAP_READ);
8469   if (!qtdemux_parse_moof (qtdemux, map.data, map.size, offset, NULL)) {
8470     gst_buffer_unmap (buf, &map);
8471     gst_buffer_unref (buf);
8472     buf = NULL;
8473     goto parse_failed;
8474   }
8475
8476   gst_buffer_unmap (buf, &map);
8477   gst_buffer_unref (buf);
8478   buf = NULL;
8479
8480   offset += length;
8481   /* look for next moof */
8482   ret = qtdemux_find_atom (qtdemux, &offset, &length, FOURCC_moof);
8483   if (G_UNLIKELY (ret != GST_FLOW_OK))
8484     goto flow_failed;
8485
8486 exit:
8487   GST_OBJECT_LOCK (qtdemux);
8488
8489   qtdemux->moof_offset = offset;
8490
8491   return res;
8492
8493 parse_failed:
8494   {
8495     GST_DEBUG_OBJECT (qtdemux, "failed to parse moof");
8496     offset = 0;
8497     res = GST_FLOW_ERROR;
8498     goto exit;
8499   }
8500 flow_failed:
8501   {
8502     /* maybe upstream temporarily flushing */
8503     if (ret != GST_FLOW_FLUSHING) {
8504       GST_DEBUG_OBJECT (qtdemux, "no next moof");
8505       offset = 0;
8506     } else {
8507       GST_DEBUG_OBJECT (qtdemux, "upstream WRONG_STATE");
8508       /* resume at current position next time */
8509     }
8510     res = ret;
8511     goto exit;
8512   }
8513 }
8514
8515 /* initialise bytereaders for stbl sub-atoms */
8516 static gboolean
8517 qtdemux_stbl_init (GstQTDemux * qtdemux, QtDemuxStream * stream, GNode * stbl)
8518 {
8519   stream->stbl_index = -1;      /* no samples have yet been parsed */
8520   stream->sample_index = -1;
8521
8522   /* time-to-sample atom */
8523   if (!qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stts, &stream->stts))
8524     goto corrupt_file;
8525
8526   /* copy atom data into a new buffer for later use */
8527   stream->stts.data = g_memdup (stream->stts.data, stream->stts.size);
8528
8529   /* skip version + flags */
8530   if (!gst_byte_reader_skip (&stream->stts, 1 + 3) ||
8531       !gst_byte_reader_get_uint32_be (&stream->stts, &stream->n_sample_times))
8532     goto corrupt_file;
8533   GST_LOG_OBJECT (qtdemux, "%u timestamp blocks", stream->n_sample_times);
8534
8535   /* make sure there's enough data */
8536   if (!qt_atom_parser_has_chunks (&stream->stts, stream->n_sample_times, 8)) {
8537     stream->n_sample_times = gst_byte_reader_get_remaining (&stream->stts) / 8;
8538     GST_LOG_OBJECT (qtdemux, "overriding to %u timestamp blocks",
8539         stream->n_sample_times);
8540     if (!stream->n_sample_times)
8541       goto corrupt_file;
8542   }
8543
8544   /* sync sample atom */
8545   stream->stps_present = FALSE;
8546   if ((stream->stss_present =
8547           ! !qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stss,
8548               &stream->stss) ? TRUE : FALSE) == TRUE) {
8549     /* copy atom data into a new buffer for later use */
8550     stream->stss.data = g_memdup (stream->stss.data, stream->stss.size);
8551
8552     /* skip version + flags */
8553     if (!gst_byte_reader_skip (&stream->stss, 1 + 3) ||
8554         !gst_byte_reader_get_uint32_be (&stream->stss, &stream->n_sample_syncs))
8555       goto corrupt_file;
8556
8557     if (stream->n_sample_syncs) {
8558       /* make sure there's enough data */
8559       if (!qt_atom_parser_has_chunks (&stream->stss, stream->n_sample_syncs, 4))
8560         goto corrupt_file;
8561     }
8562
8563     /* partial sync sample atom */
8564     if ((stream->stps_present =
8565             ! !qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stps,
8566                 &stream->stps) ? TRUE : FALSE) == TRUE) {
8567       /* copy atom data into a new buffer for later use */
8568       stream->stps.data = g_memdup (stream->stps.data, stream->stps.size);
8569
8570       /* skip version + flags */
8571       if (!gst_byte_reader_skip (&stream->stps, 1 + 3) ||
8572           !gst_byte_reader_get_uint32_be (&stream->stps,
8573               &stream->n_sample_partial_syncs))
8574         goto corrupt_file;
8575
8576       /* if there are no entries, the stss table contains the real
8577        * sync samples */
8578       if (stream->n_sample_partial_syncs) {
8579         /* make sure there's enough data */
8580         if (!qt_atom_parser_has_chunks (&stream->stps,
8581                 stream->n_sample_partial_syncs, 4))
8582           goto corrupt_file;
8583       }
8584     }
8585   }
8586
8587   /* sample size */
8588   if (!qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stsz, &stream->stsz))
8589     goto no_samples;
8590
8591   /* copy atom data into a new buffer for later use */
8592   stream->stsz.data = g_memdup (stream->stsz.data, stream->stsz.size);
8593
8594   /* skip version + flags */
8595   if (!gst_byte_reader_skip (&stream->stsz, 1 + 3) ||
8596       !gst_byte_reader_get_uint32_be (&stream->stsz, &stream->sample_size))
8597     goto corrupt_file;
8598
8599   if (!gst_byte_reader_get_uint32_be (&stream->stsz, &stream->n_samples))
8600     goto corrupt_file;
8601
8602   if (!stream->n_samples)
8603     goto no_samples;
8604
8605   /* sample-to-chunk atom */
8606   if (!qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stsc, &stream->stsc))
8607     goto corrupt_file;
8608
8609   /* copy atom data into a new buffer for later use */
8610   stream->stsc.data = g_memdup (stream->stsc.data, stream->stsc.size);
8611
8612   /* skip version + flags */
8613   if (!gst_byte_reader_skip (&stream->stsc, 1 + 3) ||
8614       !gst_byte_reader_get_uint32_be (&stream->stsc,
8615           &stream->n_samples_per_chunk))
8616     goto corrupt_file;
8617
8618   GST_DEBUG_OBJECT (qtdemux, "n_samples_per_chunk %u",
8619       stream->n_samples_per_chunk);
8620
8621   /* make sure there's enough data */
8622   if (!qt_atom_parser_has_chunks (&stream->stsc, stream->n_samples_per_chunk,
8623           12))
8624     goto corrupt_file;
8625
8626
8627   /* chunk offset */
8628   if (qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stco, &stream->stco))
8629     stream->co_size = sizeof (guint32);
8630   else if (qtdemux_tree_get_child_by_type_full (stbl, FOURCC_co64,
8631           &stream->stco))
8632     stream->co_size = sizeof (guint64);
8633   else
8634     goto corrupt_file;
8635
8636   /* copy atom data into a new buffer for later use */
8637   stream->stco.data = g_memdup (stream->stco.data, stream->stco.size);
8638
8639   /* skip version + flags */
8640   if (!gst_byte_reader_skip (&stream->stco, 1 + 3))
8641     goto corrupt_file;
8642
8643   /* chunks_are_samples == TRUE means treat chunks as samples */
8644   stream->chunks_are_samples = stream->sample_size
8645       && !CUR_STREAM (stream)->sampled;
8646   if (stream->chunks_are_samples) {
8647     /* treat chunks as samples */
8648     if (!gst_byte_reader_get_uint32_be (&stream->stco, &stream->n_samples))
8649       goto corrupt_file;
8650   } else {
8651     /* skip number of entries */
8652     if (!gst_byte_reader_skip (&stream->stco, 4))
8653       goto corrupt_file;
8654
8655     /* make sure there are enough data in the stsz atom */
8656     if (!stream->sample_size) {
8657       /* different sizes for each sample */
8658       if (!qt_atom_parser_has_chunks (&stream->stsz, stream->n_samples, 4))
8659         goto corrupt_file;
8660     }
8661   }
8662
8663   GST_DEBUG_OBJECT (qtdemux, "allocating n_samples %u * %u (%.2f MB)",
8664       stream->n_samples, (guint) sizeof (QtDemuxSample),
8665       stream->n_samples * sizeof (QtDemuxSample) / (1024.0 * 1024.0));
8666
8667   if (stream->n_samples >=
8668       QTDEMUX_MAX_SAMPLE_INDEX_SIZE / sizeof (QtDemuxSample)) {
8669     GST_WARNING_OBJECT (qtdemux, "not allocating index of %d samples, would "
8670         "be larger than %uMB (broken file?)", stream->n_samples,
8671         QTDEMUX_MAX_SAMPLE_INDEX_SIZE >> 20);
8672     return FALSE;
8673   }
8674
8675   g_assert (stream->samples == NULL);
8676   stream->samples = g_try_new0 (QtDemuxSample, stream->n_samples);
8677   if (!stream->samples) {
8678     GST_WARNING_OBJECT (qtdemux, "failed to allocate %d samples",
8679         stream->n_samples);
8680     return FALSE;
8681   }
8682
8683   /* composition time-to-sample */
8684   if ((stream->ctts_present =
8685           ! !qtdemux_tree_get_child_by_type_full (stbl, FOURCC_ctts,
8686               &stream->ctts) ? TRUE : FALSE) == TRUE) {
8687     GstByteReader cslg = GST_BYTE_READER_INIT (NULL, 0);
8688
8689     /* copy atom data into a new buffer for later use */
8690     stream->ctts.data = g_memdup (stream->ctts.data, stream->ctts.size);
8691
8692     /* skip version + flags */
8693     if (!gst_byte_reader_skip (&stream->ctts, 1 + 3)
8694         || !gst_byte_reader_get_uint32_be (&stream->ctts,
8695             &stream->n_composition_times))
8696       goto corrupt_file;
8697
8698     /* make sure there's enough data */
8699     if (!qt_atom_parser_has_chunks (&stream->ctts, stream->n_composition_times,
8700             4 + 4))
8701       goto corrupt_file;
8702
8703     /* This is optional, if missing we iterate the ctts */
8704     if (qtdemux_tree_get_child_by_type_full (stbl, FOURCC_cslg, &cslg)) {
8705       if (!gst_byte_reader_skip (&cslg, 1 + 3)
8706           || !gst_byte_reader_get_uint32_be (&cslg, &stream->cslg_shift)) {
8707         g_free ((gpointer) cslg.data);
8708         goto corrupt_file;
8709       }
8710     } else {
8711       gint32 cslg_least = 0;
8712       guint num_entries, pos;
8713       gint i;
8714
8715       pos = gst_byte_reader_get_pos (&stream->ctts);
8716       num_entries = stream->n_composition_times;
8717
8718       stream->cslg_shift = 0;
8719
8720       for (i = 0; i < num_entries; i++) {
8721         gint32 offset;
8722
8723         gst_byte_reader_skip_unchecked (&stream->ctts, 4);
8724         offset = gst_byte_reader_get_int32_be_unchecked (&stream->ctts);
8725
8726         if (offset < cslg_least)
8727           cslg_least = offset;
8728       }
8729
8730       if (cslg_least < 0)
8731         stream->cslg_shift = ABS (cslg_least);
8732       else
8733         stream->cslg_shift = 0;
8734
8735       /* reset the reader so we can generate sample table */
8736       gst_byte_reader_set_pos (&stream->ctts, pos);
8737     }
8738   } else {
8739     /* Ensure the cslg_shift value is consistent so we can use it
8740      * unconditionnally to produce TS and Segment */
8741     stream->cslg_shift = 0;
8742   }
8743
8744   return TRUE;
8745
8746 corrupt_file:
8747   {
8748     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
8749         (_("This file is corrupt and cannot be played.")), (NULL));
8750     return FALSE;
8751   }
8752 no_samples:
8753   {
8754     gst_qtdemux_stbl_free (stream);
8755     if (!qtdemux->fragmented) {
8756       /* not quite good */
8757       GST_WARNING_OBJECT (qtdemux, "stream has no samples");
8758       return FALSE;
8759     } else {
8760       /* may pick up samples elsewhere */
8761       return TRUE;
8762     }
8763   }
8764 }
8765
8766 /* collect samples from the next sample to be parsed up to sample @n for @stream
8767  * by reading the info from @stbl
8768  *
8769  * This code can be executed from both the streaming thread and the seeking
8770  * thread so it takes the object lock to protect itself
8771  */
8772 static gboolean
8773 qtdemux_parse_samples (GstQTDemux * qtdemux, QtDemuxStream * stream, guint32 n)
8774 {
8775   gint i, j, k;
8776   QtDemuxSample *samples, *first, *cur, *last;
8777   guint32 n_samples_per_chunk;
8778   guint32 n_samples;
8779
8780   GST_LOG_OBJECT (qtdemux, "parsing samples for stream fourcc %"
8781       GST_FOURCC_FORMAT ", pad %s",
8782       GST_FOURCC_ARGS (CUR_STREAM (stream)->fourcc),
8783       stream->pad ? GST_PAD_NAME (stream->pad) : "(NULL)");
8784
8785   n_samples = stream->n_samples;
8786
8787   if (n >= n_samples)
8788     goto out_of_samples;
8789
8790   GST_OBJECT_LOCK (qtdemux);
8791   if (n <= stream->stbl_index)
8792     goto already_parsed;
8793
8794   GST_DEBUG_OBJECT (qtdemux, "parsing up to sample %u", n);
8795
8796   if (!stream->stsz.data) {
8797     /* so we already parsed and passed all the moov samples;
8798      * onto fragmented ones */
8799     g_assert (qtdemux->fragmented);
8800     goto done;
8801   }
8802
8803   /* pointer to the sample table */
8804   samples = stream->samples;
8805
8806   /* starts from -1, moves to the next sample index to parse */
8807   stream->stbl_index++;
8808
8809   /* keep track of the first and last sample to fill */
8810   first = &samples[stream->stbl_index];
8811   last = &samples[n];
8812
8813   if (!stream->chunks_are_samples) {
8814     /* set the sample sizes */
8815     if (stream->sample_size == 0) {
8816       /* different sizes for each sample */
8817       for (cur = first; cur <= last; cur++) {
8818         cur->size = gst_byte_reader_get_uint32_be_unchecked (&stream->stsz);
8819         GST_LOG_OBJECT (qtdemux, "sample %d has size %u",
8820             (guint) (cur - samples), cur->size);
8821       }
8822     } else {
8823       /* samples have the same size */
8824       GST_LOG_OBJECT (qtdemux, "all samples have size %u", stream->sample_size);
8825       for (cur = first; cur <= last; cur++)
8826         cur->size = stream->sample_size;
8827     }
8828   }
8829
8830   n_samples_per_chunk = stream->n_samples_per_chunk;
8831   cur = first;
8832
8833   for (i = stream->stsc_index; i < n_samples_per_chunk; i++) {
8834     guint32 last_chunk;
8835
8836     if (stream->stsc_chunk_index >= stream->last_chunk
8837         || stream->stsc_chunk_index < stream->first_chunk) {
8838       stream->first_chunk =
8839           gst_byte_reader_get_uint32_be_unchecked (&stream->stsc);
8840       stream->samples_per_chunk =
8841           gst_byte_reader_get_uint32_be_unchecked (&stream->stsc);
8842       /* starts from 1 */
8843       stream->stsd_sample_description_id =
8844           gst_byte_reader_get_uint32_be_unchecked (&stream->stsc) - 1;
8845
8846       /* chunk numbers are counted from 1 it seems */
8847       if (G_UNLIKELY (stream->first_chunk == 0))
8848         goto corrupt_file;
8849
8850       --stream->first_chunk;
8851
8852       /* the last chunk of each entry is calculated by taking the first chunk
8853        * of the next entry; except if there is no next, where we fake it with
8854        * INT_MAX */
8855       if (G_UNLIKELY (i == (stream->n_samples_per_chunk - 1))) {
8856         stream->last_chunk = G_MAXUINT32;
8857       } else {
8858         stream->last_chunk =
8859             gst_byte_reader_peek_uint32_be_unchecked (&stream->stsc);
8860         if (G_UNLIKELY (stream->last_chunk == 0))
8861           goto corrupt_file;
8862
8863         --stream->last_chunk;
8864       }
8865
8866       GST_LOG_OBJECT (qtdemux,
8867           "entry %d has first_chunk %d, last_chunk %d, samples_per_chunk %d"
8868           "sample desc ID: %d", i, stream->first_chunk, stream->last_chunk,
8869           stream->samples_per_chunk, stream->stsd_sample_description_id);
8870
8871       if (G_UNLIKELY (stream->last_chunk < stream->first_chunk))
8872         goto corrupt_file;
8873
8874       if (stream->last_chunk != G_MAXUINT32) {
8875         if (!qt_atom_parser_peek_sub (&stream->stco,
8876                 stream->first_chunk * stream->co_size,
8877                 (stream->last_chunk - stream->first_chunk) * stream->co_size,
8878                 &stream->co_chunk))
8879           goto corrupt_file;
8880
8881       } else {
8882         stream->co_chunk = stream->stco;
8883         if (!gst_byte_reader_skip (&stream->co_chunk,
8884                 stream->first_chunk * stream->co_size))
8885           goto corrupt_file;
8886       }
8887
8888       stream->stsc_chunk_index = stream->first_chunk;
8889     }
8890
8891     last_chunk = stream->last_chunk;
8892
8893     if (stream->chunks_are_samples) {
8894       cur = &samples[stream->stsc_chunk_index];
8895
8896       for (j = stream->stsc_chunk_index; j < last_chunk; j++) {
8897         if (j > n) {
8898           /* save state */
8899           stream->stsc_chunk_index = j;
8900           goto done;
8901         }
8902
8903         cur->offset =
8904             qt_atom_parser_get_offset_unchecked (&stream->co_chunk,
8905             stream->co_size);
8906
8907         GST_LOG_OBJECT (qtdemux, "Created entry %d with offset "
8908             "%" G_GUINT64_FORMAT, j, cur->offset);
8909
8910         if (CUR_STREAM (stream)->samples_per_frame > 0 &&
8911             CUR_STREAM (stream)->bytes_per_frame > 0) {
8912           cur->size =
8913               (stream->samples_per_chunk * CUR_STREAM (stream)->n_channels) /
8914               CUR_STREAM (stream)->samples_per_frame *
8915               CUR_STREAM (stream)->bytes_per_frame;
8916         } else {
8917           cur->size = stream->samples_per_chunk;
8918         }
8919
8920         GST_DEBUG_OBJECT (qtdemux,
8921             "keyframe sample %d: timestamp %" GST_TIME_FORMAT ", size %u",
8922             j, GST_TIME_ARGS (QTSTREAMTIME_TO_GSTTIME (stream,
8923                     stream->stco_sample_index)), cur->size);
8924
8925         cur->timestamp = stream->stco_sample_index;
8926         cur->duration = stream->samples_per_chunk;
8927         cur->keyframe = TRUE;
8928         cur++;
8929
8930         stream->stco_sample_index += stream->samples_per_chunk;
8931       }
8932       stream->stsc_chunk_index = j;
8933     } else {
8934       for (j = stream->stsc_chunk_index; j < last_chunk; j++) {
8935         guint32 samples_per_chunk;
8936         guint64 chunk_offset;
8937
8938         if (!stream->stsc_sample_index
8939             && !qt_atom_parser_get_offset (&stream->co_chunk, stream->co_size,
8940                 &stream->chunk_offset))
8941           goto corrupt_file;
8942
8943         samples_per_chunk = stream->samples_per_chunk;
8944         chunk_offset = stream->chunk_offset;
8945
8946         for (k = stream->stsc_sample_index; k < samples_per_chunk; k++) {
8947           GST_LOG_OBJECT (qtdemux, "creating entry %d with offset %"
8948               G_GUINT64_FORMAT " and size %d",
8949               (guint) (cur - samples), chunk_offset, cur->size);
8950
8951           cur->offset = chunk_offset;
8952           chunk_offset += cur->size;
8953           cur++;
8954
8955           if (G_UNLIKELY (cur > last)) {
8956             /* save state */
8957             stream->stsc_sample_index = k + 1;
8958             stream->chunk_offset = chunk_offset;
8959             stream->stsc_chunk_index = j;
8960             goto done2;
8961           }
8962         }
8963         stream->stsc_sample_index = 0;
8964       }
8965       stream->stsc_chunk_index = j;
8966     }
8967     stream->stsc_index++;
8968   }
8969
8970   if (stream->chunks_are_samples)
8971     goto ctts;
8972 done2:
8973   {
8974     guint32 n_sample_times;
8975
8976     n_sample_times = stream->n_sample_times;
8977     cur = first;
8978
8979     for (i = stream->stts_index; i < n_sample_times; i++) {
8980       guint32 stts_samples;
8981       gint32 stts_duration;
8982       gint64 stts_time;
8983
8984       if (stream->stts_sample_index >= stream->stts_samples
8985           || !stream->stts_sample_index) {
8986
8987         stream->stts_samples =
8988             gst_byte_reader_get_uint32_be_unchecked (&stream->stts);
8989         stream->stts_duration =
8990             gst_byte_reader_get_uint32_be_unchecked (&stream->stts);
8991
8992         GST_LOG_OBJECT (qtdemux, "block %d, %u timestamps, duration %u",
8993             i, stream->stts_samples, stream->stts_duration);
8994
8995         stream->stts_sample_index = 0;
8996       }
8997
8998       stts_samples = stream->stts_samples;
8999       stts_duration = stream->stts_duration;
9000       stts_time = stream->stts_time;
9001
9002       for (j = stream->stts_sample_index; j < stts_samples; j++) {
9003         GST_DEBUG_OBJECT (qtdemux,
9004             "sample %d: index %d, timestamp %" GST_TIME_FORMAT,
9005             (guint) (cur - samples), j,
9006             GST_TIME_ARGS (QTSTREAMTIME_TO_GSTTIME (stream, stts_time)));
9007
9008         cur->timestamp = stts_time;
9009         cur->duration = stts_duration;
9010
9011         /* avoid 32-bit wrap-around,
9012          * but still mind possible 'negative' duration */
9013         stts_time += (gint64) stts_duration;
9014         cur++;
9015
9016         if (G_UNLIKELY (cur > last)) {
9017           /* save values */
9018           stream->stts_time = stts_time;
9019           stream->stts_sample_index = j + 1;
9020           if (stream->stts_sample_index >= stream->stts_samples)
9021             stream->stts_index++;
9022           goto done3;
9023         }
9024       }
9025       stream->stts_sample_index = 0;
9026       stream->stts_time = stts_time;
9027       stream->stts_index++;
9028     }
9029     /* fill up empty timestamps with the last timestamp, this can happen when
9030      * the last samples do not decode and so we don't have timestamps for them.
9031      * We however look at the last timestamp to estimate the track length so we
9032      * need something in here. */
9033     for (; cur < last; cur++) {
9034       GST_DEBUG_OBJECT (qtdemux,
9035           "fill sample %d: timestamp %" GST_TIME_FORMAT,
9036           (guint) (cur - samples),
9037           GST_TIME_ARGS (QTSTREAMTIME_TO_GSTTIME (stream, stream->stts_time)));
9038       cur->timestamp = stream->stts_time;
9039       cur->duration = -1;
9040     }
9041   }
9042 done3:
9043   {
9044     /* sample sync, can be NULL */
9045     if (stream->stss_present == TRUE) {
9046       guint32 n_sample_syncs;
9047
9048       n_sample_syncs = stream->n_sample_syncs;
9049
9050       if (!n_sample_syncs) {
9051         GST_DEBUG_OBJECT (qtdemux, "all samples are keyframes");
9052         stream->all_keyframe = TRUE;
9053       } else {
9054         for (i = stream->stss_index; i < n_sample_syncs; i++) {
9055           /* note that the first sample is index 1, not 0 */
9056           guint32 index;
9057
9058           index = gst_byte_reader_get_uint32_be_unchecked (&stream->stss);
9059
9060           if (G_LIKELY (index > 0 && index <= n_samples)) {
9061             index -= 1;
9062             samples[index].keyframe = TRUE;
9063             GST_DEBUG_OBJECT (qtdemux, "samples at %u is keyframe", index);
9064             /* and exit if we have enough samples */
9065             if (G_UNLIKELY (index >= n)) {
9066               i++;
9067               break;
9068             }
9069           }
9070         }
9071         /* save state */
9072         stream->stss_index = i;
9073       }
9074
9075       /* stps marks partial sync frames like open GOP I-Frames */
9076       if (stream->stps_present == TRUE) {
9077         guint32 n_sample_partial_syncs;
9078
9079         n_sample_partial_syncs = stream->n_sample_partial_syncs;
9080
9081         /* if there are no entries, the stss table contains the real
9082          * sync samples */
9083         if (n_sample_partial_syncs) {
9084           for (i = stream->stps_index; i < n_sample_partial_syncs; i++) {
9085             /* note that the first sample is index 1, not 0 */
9086             guint32 index;
9087
9088             index = gst_byte_reader_get_uint32_be_unchecked (&stream->stps);
9089
9090             if (G_LIKELY (index > 0 && index <= n_samples)) {
9091               index -= 1;
9092               samples[index].keyframe = TRUE;
9093               GST_DEBUG_OBJECT (qtdemux, "samples at %u is keyframe", index);
9094               /* and exit if we have enough samples */
9095               if (G_UNLIKELY (index >= n)) {
9096                 i++;
9097                 break;
9098               }
9099             }
9100           }
9101           /* save state */
9102           stream->stps_index = i;
9103         }
9104       }
9105     } else {
9106       /* no stss, all samples are keyframes */
9107       stream->all_keyframe = TRUE;
9108       GST_DEBUG_OBJECT (qtdemux, "setting all keyframes");
9109     }
9110   }
9111
9112 ctts:
9113   /* composition time to sample */
9114   if (stream->ctts_present == TRUE) {
9115     guint32 n_composition_times;
9116     guint32 ctts_count;
9117     gint32 ctts_soffset;
9118
9119     /* Fill in the pts_offsets */
9120     cur = first;
9121     n_composition_times = stream->n_composition_times;
9122
9123     for (i = stream->ctts_index; i < n_composition_times; i++) {
9124       if (stream->ctts_sample_index >= stream->ctts_count
9125           || !stream->ctts_sample_index) {
9126         stream->ctts_count =
9127             gst_byte_reader_get_uint32_be_unchecked (&stream->ctts);
9128         stream->ctts_soffset =
9129             gst_byte_reader_get_int32_be_unchecked (&stream->ctts);
9130         stream->ctts_sample_index = 0;
9131       }
9132
9133       ctts_count = stream->ctts_count;
9134       ctts_soffset = stream->ctts_soffset;
9135
9136       for (j = stream->ctts_sample_index; j < ctts_count; j++) {
9137         cur->pts_offset = ctts_soffset;
9138         cur++;
9139
9140         if (G_UNLIKELY (cur > last)) {
9141           /* save state */
9142           stream->ctts_sample_index = j + 1;
9143           goto done;
9144         }
9145       }
9146       stream->ctts_sample_index = 0;
9147       stream->ctts_index++;
9148     }
9149   }
9150 done:
9151   stream->stbl_index = n;
9152   /* if index has been completely parsed, free data that is no-longer needed */
9153   if (n + 1 == stream->n_samples) {
9154     gst_qtdemux_stbl_free (stream);
9155     GST_DEBUG_OBJECT (qtdemux, "parsed all available samples;");
9156     if (qtdemux->pullbased) {
9157       GST_DEBUG_OBJECT (qtdemux, "checking for more samples");
9158       while (n + 1 == stream->n_samples)
9159         if (qtdemux_add_fragmented_samples (qtdemux) != GST_FLOW_OK)
9160           break;
9161     }
9162   }
9163   GST_OBJECT_UNLOCK (qtdemux);
9164
9165   return TRUE;
9166
9167   /* SUCCESS */
9168 already_parsed:
9169   {
9170     GST_LOG_OBJECT (qtdemux,
9171         "Tried to parse up to sample %u but this sample has already been parsed",
9172         n);
9173     /* if fragmented, there may be more */
9174     if (qtdemux->fragmented && n == stream->stbl_index)
9175       goto done;
9176     GST_OBJECT_UNLOCK (qtdemux);
9177     return TRUE;
9178   }
9179   /* ERRORS */
9180 out_of_samples:
9181   {
9182     GST_LOG_OBJECT (qtdemux,
9183         "Tried to parse up to sample %u but there are only %u samples", n + 1,
9184         stream->n_samples);
9185     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
9186         (_("This file is corrupt and cannot be played.")), (NULL));
9187     return FALSE;
9188   }
9189 corrupt_file:
9190   {
9191     GST_OBJECT_UNLOCK (qtdemux);
9192     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
9193         (_("This file is corrupt and cannot be played.")), (NULL));
9194     return FALSE;
9195   }
9196 }
9197
9198 /* collect all segment info for @stream.
9199  */
9200 static gboolean
9201 qtdemux_parse_segments (GstQTDemux * qtdemux, QtDemuxStream * stream,
9202     GNode * trak)
9203 {
9204   GNode *edts;
9205   /* accept edts if they contain gaps at start and there is only
9206    * one media segment */
9207   gboolean allow_pushbased_edts = TRUE;
9208   gint media_segments_count = 0;
9209
9210   /* parse and prepare segment info from the edit list */
9211   GST_DEBUG_OBJECT (qtdemux, "looking for edit list container");
9212   stream->n_segments = 0;
9213   stream->segments = NULL;
9214   if ((edts = qtdemux_tree_get_child_by_type (trak, FOURCC_edts))) {
9215     GNode *elst;
9216     gint n_segments;
9217     gint i, count, entry_size;
9218     guint64 time;
9219     GstClockTime stime;
9220     const guint8 *buffer;
9221     guint8 version;
9222     guint32 size;
9223
9224     GST_DEBUG_OBJECT (qtdemux, "looking for edit list");
9225     if (!(elst = qtdemux_tree_get_child_by_type (edts, FOURCC_elst)))
9226       goto done;
9227
9228     buffer = elst->data;
9229
9230     size = QT_UINT32 (buffer);
9231     /* version, flags, n_segments */
9232     if (size < 16) {
9233       GST_WARNING_OBJECT (qtdemux, "Invalid edit list");
9234       goto done;
9235     }
9236     version = QT_UINT8 (buffer + 8);
9237     entry_size = (version == 1) ? 20 : 12;
9238
9239     n_segments = QT_UINT32 (buffer + 12);
9240
9241     if (n_segments > 100000 || size < 16 + n_segments * entry_size) {
9242       GST_WARNING_OBJECT (qtdemux, "Invalid edit list");
9243       goto done;
9244     }
9245
9246     /* we might allocate a bit too much, at least allocate 1 segment */
9247     stream->segments = g_new (QtDemuxSegment, MAX (n_segments, 1));
9248
9249     /* segments always start from 0 */
9250     time = 0;
9251     stime = 0;
9252     count = 0;
9253     buffer += 16;
9254     for (i = 0; i < n_segments; i++) {
9255       guint64 duration;
9256       guint64 media_time;
9257       gboolean time_valid = TRUE;
9258       QtDemuxSegment *segment;
9259       guint32 rate_int;
9260       GstClockTime media_start = GST_CLOCK_TIME_NONE;
9261
9262       if (version == 1) {
9263         media_time = QT_UINT64 (buffer + 8);
9264         duration = QT_UINT64 (buffer);
9265         if (media_time == G_MAXUINT64)
9266           time_valid = FALSE;
9267       } else {
9268         media_time = QT_UINT32 (buffer + 4);
9269         duration = QT_UINT32 (buffer);
9270         if (media_time == G_MAXUINT32)
9271           time_valid = FALSE;
9272       }
9273
9274       if (time_valid)
9275         media_start = QTSTREAMTIME_TO_GSTTIME (stream, media_time);
9276
9277       segment = &stream->segments[count++];
9278
9279       /* time and duration expressed in global timescale */
9280       segment->time = stime;
9281       /* add non scaled values so we don't cause roundoff errors */
9282       if (duration || media_start == GST_CLOCK_TIME_NONE) {
9283         time += duration;
9284         stime = QTTIME_TO_GSTTIME (qtdemux, time);
9285         segment->duration = stime - segment->time;
9286       } else {
9287         /* zero duration does not imply media_start == media_stop
9288          * but, only specify media_start.*/
9289         stime = QTTIME_TO_GSTTIME (qtdemux, qtdemux->duration);
9290         if (GST_CLOCK_TIME_IS_VALID (stime) && time_valid
9291             && stime >= media_start) {
9292           segment->duration = stime - media_start;
9293         } else {
9294           segment->duration = GST_CLOCK_TIME_NONE;
9295         }
9296       }
9297       segment->stop_time = stime;
9298
9299       segment->trak_media_start = media_time;
9300       /* media_time expressed in stream timescale */
9301       if (time_valid) {
9302         segment->media_start = media_start;
9303         segment->media_stop = segment->media_start + segment->duration;
9304         media_segments_count++;
9305       } else {
9306         segment->media_start = GST_CLOCK_TIME_NONE;
9307         segment->media_stop = GST_CLOCK_TIME_NONE;
9308       }
9309       rate_int = QT_UINT32 (buffer + ((version == 1) ? 16 : 8));
9310
9311       if (rate_int <= 1) {
9312         /* 0 is not allowed, some programs write 1 instead of the floating point
9313          * value */
9314         GST_WARNING_OBJECT (qtdemux, "found suspicious rate %" G_GUINT32_FORMAT,
9315             rate_int);
9316         segment->rate = 1;
9317       } else {
9318         segment->rate = rate_int / 65536.0;
9319       }
9320
9321       GST_DEBUG_OBJECT (qtdemux, "created segment %d time %" GST_TIME_FORMAT
9322           ", duration %" GST_TIME_FORMAT ", media_start %" GST_TIME_FORMAT
9323           " (%" G_GUINT64_FORMAT ") , media_stop %" GST_TIME_FORMAT
9324           " stop_time %" GST_TIME_FORMAT " rate %g, (%d) timescale %u",
9325           i, GST_TIME_ARGS (segment->time),
9326           GST_TIME_ARGS (segment->duration),
9327           GST_TIME_ARGS (segment->media_start), media_time,
9328           GST_TIME_ARGS (segment->media_stop),
9329           GST_TIME_ARGS (segment->stop_time), segment->rate, rate_int,
9330           stream->timescale);
9331       if (segment->stop_time > qtdemux->segment.stop) {
9332         GST_WARNING_OBJECT (qtdemux, "Segment %d "
9333             " extends to %" GST_TIME_FORMAT
9334             " past the end of the file duration %" GST_TIME_FORMAT
9335             " it will be truncated", i, GST_TIME_ARGS (segment->stop_time),
9336             GST_TIME_ARGS (qtdemux->segment.stop));
9337         qtdemux->segment.stop = segment->stop_time;
9338       }
9339
9340       buffer += entry_size;
9341     }
9342     GST_DEBUG_OBJECT (qtdemux, "found %d segments", count);
9343     stream->n_segments = count;
9344     if (media_segments_count != 1)
9345       allow_pushbased_edts = FALSE;
9346   }
9347 done:
9348
9349   /* push based does not handle segments, so act accordingly here,
9350    * and warn if applicable */
9351   if (!qtdemux->pullbased && !allow_pushbased_edts) {
9352     GST_WARNING_OBJECT (qtdemux, "streaming; discarding edit list segments");
9353     /* remove and use default one below, we stream like it anyway */
9354     g_free (stream->segments);
9355     stream->segments = NULL;
9356     stream->n_segments = 0;
9357   }
9358
9359   /* no segments, create one to play the complete trak */
9360   if (stream->n_segments == 0) {
9361     GstClockTime stream_duration =
9362         QTSTREAMTIME_TO_GSTTIME (stream, stream->duration);
9363
9364     if (stream->segments == NULL)
9365       stream->segments = g_new (QtDemuxSegment, 1);
9366
9367     /* represent unknown our way */
9368     if (stream_duration == 0)
9369       stream_duration = GST_CLOCK_TIME_NONE;
9370
9371     stream->segments[0].time = 0;
9372     stream->segments[0].stop_time = stream_duration;
9373     stream->segments[0].duration = stream_duration;
9374     stream->segments[0].media_start = 0;
9375     stream->segments[0].media_stop = stream_duration;
9376     stream->segments[0].rate = 1.0;
9377     stream->segments[0].trak_media_start = 0;
9378
9379     GST_DEBUG_OBJECT (qtdemux, "created dummy segment %" GST_TIME_FORMAT,
9380         GST_TIME_ARGS (stream_duration));
9381     stream->n_segments = 1;
9382     stream->dummy_segment = TRUE;
9383   }
9384   GST_DEBUG_OBJECT (qtdemux, "using %d segments", stream->n_segments);
9385
9386   return TRUE;
9387 }
9388
9389 /*
9390  * Parses the stsd atom of a svq3 trak looking for
9391  * the SMI and gama atoms.
9392  */
9393 static void
9394 qtdemux_parse_svq3_stsd_data (GstQTDemux * qtdemux,
9395     const guint8 * stsd_entry_data, const guint8 ** gamma, GstBuffer ** seqh)
9396 {
9397   const guint8 *_gamma = NULL;
9398   GstBuffer *_seqh = NULL;
9399   const guint8 *stsd_data = stsd_entry_data;
9400   guint32 length = QT_UINT32 (stsd_data);
9401   guint16 version;
9402
9403   if (length < 32) {
9404     GST_WARNING_OBJECT (qtdemux, "stsd too short");
9405     goto end;
9406   }
9407
9408   stsd_data += 16;
9409   length -= 16;
9410   version = QT_UINT16 (stsd_data);
9411   if (version == 3) {
9412     if (length >= 70) {
9413       length -= 70;
9414       stsd_data += 70;
9415       while (length > 8) {
9416         guint32 fourcc, size;
9417         const guint8 *data;
9418         size = QT_UINT32 (stsd_data);
9419         fourcc = QT_FOURCC (stsd_data + 4);
9420         data = stsd_data + 8;
9421
9422         if (size == 0) {
9423           GST_WARNING_OBJECT (qtdemux, "Atom of size 0 found, aborting "
9424               "svq3 atom parsing");
9425           goto end;
9426         }
9427
9428         switch (fourcc) {
9429           case FOURCC_gama:{
9430             if (size == 12) {
9431               _gamma = data;
9432             } else {
9433               GST_WARNING_OBJECT (qtdemux, "Unexpected size %" G_GUINT32_FORMAT
9434                   " for gama atom, expected 12", size);
9435             }
9436             break;
9437           }
9438           case FOURCC_SMI_:{
9439             if (size > 16 && QT_FOURCC (data) == FOURCC_SEQH) {
9440               guint32 seqh_size;
9441               if (_seqh != NULL) {
9442                 GST_WARNING_OBJECT (qtdemux, "Unexpected second SEQH SMI atom "
9443                     " found, ignoring");
9444               } else {
9445                 seqh_size = QT_UINT32 (data + 4);
9446                 if (seqh_size > 0) {
9447                   _seqh = gst_buffer_new_and_alloc (seqh_size);
9448                   gst_buffer_fill (_seqh, 0, data + 8, seqh_size);
9449                 }
9450               }
9451             }
9452             break;
9453           }
9454           default:{
9455             GST_WARNING_OBJECT (qtdemux, "Unhandled atom %" GST_FOURCC_FORMAT
9456                 " in SVQ3 entry in stsd atom", GST_FOURCC_ARGS (fourcc));
9457           }
9458         }
9459
9460         if (size <= length) {
9461           length -= size;
9462           stsd_data += size;
9463         }
9464       }
9465     } else {
9466       GST_WARNING_OBJECT (qtdemux, "SVQ3 entry too short in stsd atom");
9467     }
9468   } else {
9469     GST_WARNING_OBJECT (qtdemux, "Unexpected version for SVQ3 entry %"
9470         G_GUINT16_FORMAT, version);
9471     goto end;
9472   }
9473
9474 end:
9475   if (gamma) {
9476     *gamma = _gamma;
9477   }
9478   if (seqh) {
9479     *seqh = _seqh;
9480   } else if (_seqh) {
9481     gst_buffer_unref (_seqh);
9482   }
9483 }
9484
9485 static gchar *
9486 qtdemux_get_rtsp_uri_from_hndl (GstQTDemux * qtdemux, GNode * minf)
9487 {
9488   GNode *dinf;
9489   GstByteReader dref;
9490   gchar *uri = NULL;
9491
9492   /*
9493    * Get 'dinf', to get its child 'dref', that might contain a 'hndl'
9494    * atom that might contain a 'data' atom with the rtsp uri.
9495    * This case was reported in bug #597497, some info about
9496    * the hndl atom can be found in TN1195
9497    */
9498   dinf = qtdemux_tree_get_child_by_type (minf, FOURCC_dinf);
9499   GST_DEBUG_OBJECT (qtdemux, "Trying to obtain rtsp URI for stream trak");
9500
9501   if (dinf) {
9502     guint32 dref_num_entries = 0;
9503     if (qtdemux_tree_get_child_by_type_full (dinf, FOURCC_dref, &dref) &&
9504         gst_byte_reader_skip (&dref, 4) &&
9505         gst_byte_reader_get_uint32_be (&dref, &dref_num_entries)) {
9506       gint i;
9507
9508       /* search dref entries for hndl atom */
9509       for (i = 0; i < dref_num_entries; i++) {
9510         guint32 size = 0, type;
9511         guint8 string_len = 0;
9512         if (gst_byte_reader_get_uint32_be (&dref, &size) &&
9513             qt_atom_parser_get_fourcc (&dref, &type)) {
9514           if (type == FOURCC_hndl) {
9515             GST_DEBUG_OBJECT (qtdemux, "Found hndl atom");
9516
9517             /* skip data reference handle bytes and the
9518              * following pascal string and some extra 4
9519              * bytes I have no idea what are */
9520             if (!gst_byte_reader_skip (&dref, 4) ||
9521                 !gst_byte_reader_get_uint8 (&dref, &string_len) ||
9522                 !gst_byte_reader_skip (&dref, string_len + 4)) {
9523               GST_WARNING_OBJECT (qtdemux, "Failed to parse hndl atom");
9524               break;
9525             }
9526
9527             /* iterate over the atoms to find the data atom */
9528             while (gst_byte_reader_get_remaining (&dref) >= 8) {
9529               guint32 atom_size;
9530               guint32 atom_type;
9531
9532               if (gst_byte_reader_get_uint32_be (&dref, &atom_size) &&
9533                   qt_atom_parser_get_fourcc (&dref, &atom_type)) {
9534                 if (atom_type == FOURCC_data) {
9535                   const guint8 *uri_aux = NULL;
9536
9537                   /* found the data atom that might contain the rtsp uri */
9538                   GST_DEBUG_OBJECT (qtdemux, "Found data atom inside "
9539                       "hndl atom, interpreting it as an URI");
9540                   if (gst_byte_reader_peek_data (&dref, atom_size - 8,
9541                           &uri_aux)) {
9542                     if (g_strstr_len ((gchar *) uri_aux, 7, "rtsp://") != NULL)
9543                       uri = g_strndup ((gchar *) uri_aux, atom_size - 8);
9544                     else
9545                       GST_WARNING_OBJECT (qtdemux, "Data atom in hndl atom "
9546                           "didn't contain a rtsp address");
9547                   } else {
9548                     GST_WARNING_OBJECT (qtdemux, "Failed to get the data "
9549                         "atom contents");
9550                   }
9551                   break;
9552                 }
9553                 /* skipping to the next entry */
9554                 if (!gst_byte_reader_skip (&dref, atom_size - 8))
9555                   break;
9556               } else {
9557                 GST_WARNING_OBJECT (qtdemux, "Failed to parse hndl child "
9558                     "atom header");
9559                 break;
9560               }
9561             }
9562             break;
9563           }
9564           /* skip to the next entry */
9565           if (!gst_byte_reader_skip (&dref, size - 8))
9566             break;
9567         } else {
9568           GST_WARNING_OBJECT (qtdemux, "Error parsing dref atom");
9569         }
9570       }
9571       GST_DEBUG_OBJECT (qtdemux, "Finished parsing dref atom");
9572     }
9573   }
9574   return uri;
9575 }
9576
9577 #define AMR_NB_ALL_MODES        0x81ff
9578 #define AMR_WB_ALL_MODES        0x83ff
9579 static guint
9580 qtdemux_parse_amr_bitrate (GstBuffer * buf, gboolean wb)
9581 {
9582   /* The 'damr' atom is of the form:
9583    *
9584    * | vendor | decoder_ver | mode_set | mode_change_period | frames/sample |
9585    *    32 b       8 b          16 b           8 b                 8 b
9586    *
9587    * The highest set bit of the first 7 (AMR-NB) or 8 (AMR-WB) bits of mode_set
9588    * represents the highest mode used in the stream (and thus the maximum
9589    * bitrate), with a couple of special cases as seen below.
9590    */
9591
9592   /* Map of frame type ID -> bitrate */
9593   static const guint nb_bitrates[] = {
9594     4750, 5150, 5900, 6700, 7400, 7950, 10200, 12200
9595   };
9596   static const guint wb_bitrates[] = {
9597     6600, 8850, 12650, 14250, 15850, 18250, 19850, 23050, 23850
9598   };
9599   GstMapInfo map;
9600   gsize max_mode;
9601   guint16 mode_set;
9602
9603   gst_buffer_map (buf, &map, GST_MAP_READ);
9604
9605   if (map.size != 0x11) {
9606     GST_DEBUG ("Atom should have size 0x11, not %" G_GSIZE_FORMAT, map.size);
9607     goto bad_data;
9608   }
9609
9610   if (QT_FOURCC (map.data + 4) != FOURCC_damr) {
9611     GST_DEBUG ("Unknown atom in %" GST_FOURCC_FORMAT,
9612         GST_FOURCC_ARGS (QT_UINT32 (map.data + 4)));
9613     goto bad_data;
9614   }
9615
9616   mode_set = QT_UINT16 (map.data + 13);
9617
9618   if (mode_set == (wb ? AMR_WB_ALL_MODES : AMR_NB_ALL_MODES))
9619     max_mode = 7 + (wb ? 1 : 0);
9620   else
9621     /* AMR-NB modes fo from 0-7, and AMR-WB modes go from 0-8 */
9622     max_mode = g_bit_nth_msf ((gulong) mode_set & (wb ? 0x1ff : 0xff), -1);
9623
9624   if (max_mode == -1) {
9625     GST_DEBUG ("No mode indication was found (mode set) = %x",
9626         (guint) mode_set);
9627     goto bad_data;
9628   }
9629
9630   gst_buffer_unmap (buf, &map);
9631   return wb ? wb_bitrates[max_mode] : nb_bitrates[max_mode];
9632
9633 bad_data:
9634   gst_buffer_unmap (buf, &map);
9635   return 0;
9636 }
9637
9638 static gboolean
9639 qtdemux_parse_transformation_matrix (GstQTDemux * qtdemux,
9640     GstByteReader * reader, guint32 * matrix, const gchar * atom)
9641 {
9642   /*
9643    * 9 values of 32 bits (fixed point 16.16, except 2 5 and 8 that are 2.30)
9644    * [0 1 2]
9645    * [3 4 5]
9646    * [6 7 8]
9647    */
9648
9649   if (gst_byte_reader_get_remaining (reader) < 36)
9650     return FALSE;
9651
9652   matrix[0] = gst_byte_reader_get_uint32_be_unchecked (reader);
9653   matrix[1] = gst_byte_reader_get_uint32_be_unchecked (reader);
9654   matrix[2] = gst_byte_reader_get_uint32_be_unchecked (reader);
9655   matrix[3] = gst_byte_reader_get_uint32_be_unchecked (reader);
9656   matrix[4] = gst_byte_reader_get_uint32_be_unchecked (reader);
9657   matrix[5] = gst_byte_reader_get_uint32_be_unchecked (reader);
9658   matrix[6] = gst_byte_reader_get_uint32_be_unchecked (reader);
9659   matrix[7] = gst_byte_reader_get_uint32_be_unchecked (reader);
9660   matrix[8] = gst_byte_reader_get_uint32_be_unchecked (reader);
9661
9662   GST_DEBUG_OBJECT (qtdemux, "Transformation matrix from atom %s", atom);
9663   GST_DEBUG_OBJECT (qtdemux, "%u.%u %u.%u %u.%u", matrix[0] >> 16,
9664       matrix[0] & 0xFFFF, matrix[1] >> 16, matrix[1] & 0xFF, matrix[2] >> 16,
9665       matrix[2] & 0xFF);
9666   GST_DEBUG_OBJECT (qtdemux, "%u.%u %u.%u %u.%u", matrix[3] >> 16,
9667       matrix[3] & 0xFFFF, matrix[4] >> 16, matrix[4] & 0xFF, matrix[5] >> 16,
9668       matrix[5] & 0xFF);
9669   GST_DEBUG_OBJECT (qtdemux, "%u.%u %u.%u %u.%u", matrix[6] >> 16,
9670       matrix[6] & 0xFFFF, matrix[7] >> 16, matrix[7] & 0xFF, matrix[8] >> 16,
9671       matrix[8] & 0xFF);
9672
9673   return TRUE;
9674 }
9675
9676 static void
9677 qtdemux_inspect_transformation_matrix (GstQTDemux * qtdemux,
9678     QtDemuxStream * stream, guint32 * matrix, GstTagList ** taglist)
9679 {
9680
9681 /* [a b c]
9682  * [d e f]
9683  * [g h i]
9684  *
9685  * This macro will only compare value abdegh, it expects cfi to have already
9686  * been checked
9687  */
9688 #define QTCHECK_MATRIX(m,a,b,d,e) ((m)[0] == (a << 16) && (m)[1] == (b << 16) && \
9689                                    (m)[3] == (d << 16) && (m)[4] == (e << 16))
9690
9691   /* only handle the cases where the last column has standard values */
9692   if (matrix[2] == 0 && matrix[5] == 0 && matrix[8] == 1 << 30) {
9693     const gchar *rotation_tag = NULL;
9694
9695     /* no rotation needed */
9696     if (QTCHECK_MATRIX (matrix, 1, 0, 0, 1)) {
9697       /* NOP */
9698     } else if (QTCHECK_MATRIX (matrix, 0, 1, G_MAXUINT16, 0)) {
9699       rotation_tag = "rotate-90";
9700     } else if (QTCHECK_MATRIX (matrix, G_MAXUINT16, 0, 0, G_MAXUINT16)) {
9701       rotation_tag = "rotate-180";
9702     } else if (QTCHECK_MATRIX (matrix, 0, G_MAXUINT16, 1, 0)) {
9703       rotation_tag = "rotate-270";
9704     } else {
9705       GST_FIXME_OBJECT (qtdemux, "Unhandled transformation matrix values");
9706     }
9707
9708     GST_DEBUG_OBJECT (qtdemux, "Transformation matrix rotation %s",
9709         rotation_tag);
9710     if (rotation_tag != NULL) {
9711       if (*taglist == NULL)
9712         *taglist = gst_tag_list_new_empty ();
9713       gst_tag_list_add (*taglist, GST_TAG_MERGE_REPLACE,
9714           GST_TAG_IMAGE_ORIENTATION, rotation_tag, NULL);
9715     }
9716   } else {
9717     GST_FIXME_OBJECT (qtdemux, "Unhandled transformation matrix values");
9718   }
9719 }
9720
9721 /* Parses the boxes defined in ISO/IEC 14496-12 that enable support for
9722  * protected streams (sinf, frma, schm and schi); if the protection scheme is
9723  * Common Encryption (cenc), the function will also parse the tenc box (defined
9724  * in ISO/IEC 23001-7). @container points to the node that contains these boxes
9725  * (typically an enc[v|a|t|s] sample entry); the function will set
9726  * @original_fmt to the fourcc of the original unencrypted stream format.
9727  * Returns TRUE if successful; FALSE otherwise. */
9728 static gboolean
9729 qtdemux_parse_protection_scheme_info (GstQTDemux * qtdemux,
9730     QtDemuxStream * stream, GNode * container, guint32 * original_fmt)
9731 {
9732   GNode *sinf;
9733   GNode *frma;
9734   GNode *schm;
9735   GNode *schi;
9736
9737   g_return_val_if_fail (qtdemux != NULL, FALSE);
9738   g_return_val_if_fail (stream != NULL, FALSE);
9739   g_return_val_if_fail (container != NULL, FALSE);
9740   g_return_val_if_fail (original_fmt != NULL, FALSE);
9741
9742   sinf = qtdemux_tree_get_child_by_type (container, FOURCC_sinf);
9743   if (G_UNLIKELY (!sinf)) {
9744     if (stream->protection_scheme_type == FOURCC_cenc) {
9745       GST_ERROR_OBJECT (qtdemux, "sinf box does not contain schi box, which is "
9746           "mandatory for Common Encryption");
9747       return FALSE;
9748     }
9749     return TRUE;
9750   }
9751
9752   frma = qtdemux_tree_get_child_by_type (sinf, FOURCC_frma);
9753   if (G_UNLIKELY (!frma)) {
9754     GST_ERROR_OBJECT (qtdemux, "sinf box does not contain mandatory frma box");
9755     return FALSE;
9756   }
9757
9758   *original_fmt = QT_FOURCC ((const guint8 *) frma->data + 8);
9759   GST_DEBUG_OBJECT (qtdemux, "original stream format: '%" GST_FOURCC_FORMAT "'",
9760       GST_FOURCC_ARGS (*original_fmt));
9761
9762   schm = qtdemux_tree_get_child_by_type (sinf, FOURCC_schm);
9763   if (!schm) {
9764     GST_DEBUG_OBJECT (qtdemux, "sinf box does not contain schm box");
9765     return FALSE;
9766   }
9767   stream->protection_scheme_type = QT_FOURCC ((const guint8 *) schm->data + 12);
9768   stream->protection_scheme_version =
9769       QT_UINT32 ((const guint8 *) schm->data + 16);
9770
9771   GST_DEBUG_OBJECT (qtdemux,
9772       "protection_scheme_type: %" GST_FOURCC_FORMAT ", "
9773       "protection_scheme_version: %#010x",
9774       GST_FOURCC_ARGS (stream->protection_scheme_type),
9775       stream->protection_scheme_version);
9776
9777   schi = qtdemux_tree_get_child_by_type (sinf, FOURCC_schi);
9778   if (!schi) {
9779     GST_DEBUG_OBJECT (qtdemux, "sinf box does not contain schi box");
9780     return FALSE;
9781   }
9782   if (stream->protection_scheme_type == FOURCC_cenc) {
9783     QtDemuxCencSampleSetInfo *info;
9784     GNode *tenc;
9785     const guint8 *tenc_data;
9786     guint32 isEncrypted;
9787     guint8 iv_size;
9788     const guint8 *default_kid;
9789     GstBuffer *kid_buf;
9790
9791     if (G_UNLIKELY (!stream->protection_scheme_info))
9792       stream->protection_scheme_info =
9793           g_malloc0 (sizeof (QtDemuxCencSampleSetInfo));
9794
9795     info = (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
9796
9797     tenc = qtdemux_tree_get_child_by_type (schi, FOURCC_tenc);
9798     if (!tenc) {
9799       GST_ERROR_OBJECT (qtdemux, "schi box does not contain tenc box, "
9800           "which is mandatory for Common Encryption");
9801       return FALSE;
9802     }
9803     tenc_data = (const guint8 *) tenc->data + 12;
9804     isEncrypted = QT_UINT24 (tenc_data);
9805     iv_size = QT_UINT8 (tenc_data + 3);
9806     default_kid = (tenc_data + 4);
9807     kid_buf = gst_buffer_new_allocate (NULL, 16, NULL);
9808     gst_buffer_fill (kid_buf, 0, default_kid, 16);
9809     if (info->default_properties)
9810       gst_structure_free (info->default_properties);
9811     info->default_properties =
9812         gst_structure_new ("application/x-cenc",
9813         "iv_size", G_TYPE_UINT, iv_size,
9814         "encrypted", G_TYPE_BOOLEAN, (isEncrypted == 1),
9815         "kid", GST_TYPE_BUFFER, kid_buf, NULL);
9816     GST_DEBUG_OBJECT (qtdemux, "default sample properties: "
9817         "is_encrypted=%u, iv_size=%u", isEncrypted, iv_size);
9818     gst_buffer_unref (kid_buf);
9819   }
9820   return TRUE;
9821 }
9822
9823 /* parse the traks.
9824  * With each track we associate a new QtDemuxStream that contains all the info
9825  * about the trak.
9826  * traks that do not decode to something (like strm traks) will not have a pad.
9827  */
9828 static gboolean
9829 qtdemux_parse_trak (GstQTDemux * qtdemux, GNode * trak)
9830 {
9831   GstByteReader tkhd;
9832   int offset;
9833   GNode *mdia;
9834   GNode *mdhd;
9835   GNode *hdlr;
9836   GNode *minf;
9837   GNode *stbl;
9838   GNode *stsd;
9839   GNode *mp4a;
9840   GNode *mp4v;
9841   GNode *esds;
9842   GNode *tref;
9843   GNode *udta;
9844   GNode *svmi;
9845
9846   QtDemuxStream *stream = NULL;
9847   gboolean new_stream = FALSE;
9848   const guint8 *stsd_data;
9849   const guint8 *stsd_entry_data;
9850   guint remaining_stsd_len;
9851   guint stsd_entry_count;
9852   guint stsd_index;
9853   guint16 lang_code;            /* quicktime lang code or packed iso code */
9854   guint32 version;
9855   guint32 tkhd_flags = 0;
9856   guint8 tkhd_version = 0;
9857   guint32 w = 0, h = 0;
9858   guint value_size, stsd_len, len;
9859   guint32 track_id;
9860   guint32 dummy;
9861
9862   GST_DEBUG_OBJECT (qtdemux, "parse_trak");
9863
9864   if (!qtdemux_tree_get_child_by_type_full (trak, FOURCC_tkhd, &tkhd)
9865       || !gst_byte_reader_get_uint8 (&tkhd, &tkhd_version)
9866       || !gst_byte_reader_get_uint24_be (&tkhd, &tkhd_flags))
9867     goto corrupt_file;
9868
9869   /* pick between 64 or 32 bits */
9870   value_size = tkhd_version == 1 ? 8 : 4;
9871   if (!gst_byte_reader_skip (&tkhd, value_size * 2) ||
9872       !gst_byte_reader_get_uint32_be (&tkhd, &track_id))
9873     goto corrupt_file;
9874
9875   if (!qtdemux->got_moov) {
9876     if (qtdemux_find_stream (qtdemux, track_id))
9877       goto existing_stream;
9878     stream = _create_stream (qtdemux, track_id);
9879     stream->track_id = track_id;
9880     new_stream = TRUE;
9881   } else {
9882     stream = qtdemux_find_stream (qtdemux, track_id);
9883     if (!stream) {
9884       GST_WARNING_OBJECT (qtdemux, "Stream not found, going to ignore it");
9885       goto skip_track;
9886     }
9887
9888     /* reset reused stream */
9889     gst_qtdemux_stream_reset (stream);
9890   }
9891   /* need defaults for fragments */
9892   qtdemux_parse_trex (qtdemux, stream, &dummy, &dummy, &dummy);
9893
9894   if ((tkhd_flags & 1) == 0)
9895     stream->disabled = TRUE;
9896
9897   GST_LOG_OBJECT (qtdemux, "track[tkhd] version/flags/id: 0x%02x/%06x/%u",
9898       tkhd_version, tkhd_flags, stream->track_id);
9899
9900   if (!(mdia = qtdemux_tree_get_child_by_type (trak, FOURCC_mdia)))
9901     goto corrupt_file;
9902
9903   if (!(mdhd = qtdemux_tree_get_child_by_type (mdia, FOURCC_mdhd))) {
9904     /* be nice for some crooked mjp2 files that use mhdr for mdhd */
9905     if (qtdemux->major_brand != FOURCC_mjp2 ||
9906         !(mdhd = qtdemux_tree_get_child_by_type (mdia, FOURCC_mhdr)))
9907       goto corrupt_file;
9908   }
9909
9910   len = QT_UINT32 ((guint8 *) mdhd->data);
9911   version = QT_UINT32 ((guint8 *) mdhd->data + 8);
9912   GST_LOG_OBJECT (qtdemux, "track version/flags: %08x", version);
9913   if (version == 0x01000000) {
9914     if (len < 38)
9915       goto corrupt_file;
9916     stream->timescale = QT_UINT32 ((guint8 *) mdhd->data + 28);
9917     stream->duration = QT_UINT64 ((guint8 *) mdhd->data + 32);
9918     lang_code = QT_UINT16 ((guint8 *) mdhd->data + 36);
9919   } else {
9920     if (len < 30)
9921       goto corrupt_file;
9922     stream->timescale = QT_UINT32 ((guint8 *) mdhd->data + 20);
9923     stream->duration = QT_UINT32 ((guint8 *) mdhd->data + 24);
9924     lang_code = QT_UINT16 ((guint8 *) mdhd->data + 28);
9925   }
9926
9927   if (lang_code < 0x400) {
9928     qtdemux_lang_map_qt_code_to_iso (stream->lang_id, lang_code);
9929   } else if (lang_code == 0x7fff) {
9930     stream->lang_id[0] = 0;     /* unspecified */
9931   } else {
9932     stream->lang_id[0] = 0x60 + ((lang_code >> 10) & 0x1F);
9933     stream->lang_id[1] = 0x60 + ((lang_code >> 5) & 0x1F);
9934     stream->lang_id[2] = 0x60 + (lang_code & 0x1F);
9935     stream->lang_id[3] = 0;
9936   }
9937
9938   GST_LOG_OBJECT (qtdemux, "track timescale: %" G_GUINT32_FORMAT,
9939       stream->timescale);
9940   GST_LOG_OBJECT (qtdemux, "track duration: %" G_GUINT64_FORMAT,
9941       stream->duration);
9942   GST_LOG_OBJECT (qtdemux, "track language code/id: 0x%04x/%s",
9943       lang_code, stream->lang_id);
9944
9945   if (G_UNLIKELY (stream->timescale == 0 || qtdemux->timescale == 0))
9946     goto corrupt_file;
9947
9948   if ((tref = qtdemux_tree_get_child_by_type (trak, FOURCC_tref))) {
9949     /* chapters track reference */
9950     GNode *chap = qtdemux_tree_get_child_by_type (tref, FOURCC_chap);
9951     if (chap) {
9952       gsize length = GST_READ_UINT32_BE (chap->data);
9953       if (qtdemux->chapters_track_id)
9954         GST_FIXME_OBJECT (qtdemux, "Multiple CHAP tracks");
9955
9956       if (length >= 12) {
9957         qtdemux->chapters_track_id =
9958             GST_READ_UINT32_BE ((gint8 *) chap->data + 8);
9959       }
9960     }
9961   }
9962
9963   /* fragmented files may have bogus duration in moov */
9964   if (!qtdemux->fragmented &&
9965       qtdemux->duration != G_MAXINT64 && stream->duration != G_MAXINT32) {
9966     guint64 tdur1, tdur2;
9967
9968     /* don't overflow */
9969     tdur1 = stream->timescale * (guint64) qtdemux->duration;
9970     tdur2 = qtdemux->timescale * (guint64) stream->duration;
9971
9972     /* HACK:
9973      * some of those trailers, nowadays, have prologue images that are
9974      * themselves video tracks as well. I haven't really found a way to
9975      * identify those yet, except for just looking at their duration. */
9976     if (tdur1 != 0 && (tdur2 * 10 / tdur1) < 2) {
9977       GST_WARNING_OBJECT (qtdemux,
9978           "Track shorter than 20%% (%" G_GUINT64_FORMAT "/%" G_GUINT32_FORMAT
9979           " vs. %" G_GUINT64_FORMAT "/%" G_GUINT32_FORMAT ") of the stream "
9980           "found, assuming preview image or something; skipping track",
9981           stream->duration, stream->timescale, qtdemux->duration,
9982           qtdemux->timescale);
9983       if (new_stream)
9984         gst_qtdemux_stream_free (stream);
9985       return TRUE;
9986     }
9987   }
9988
9989   if (!(hdlr = qtdemux_tree_get_child_by_type (mdia, FOURCC_hdlr)))
9990     goto corrupt_file;
9991
9992   GST_LOG_OBJECT (qtdemux, "track type: %" GST_FOURCC_FORMAT,
9993       GST_FOURCC_ARGS (QT_FOURCC ((guint8 *) hdlr->data + 12)));
9994
9995   len = QT_UINT32 ((guint8 *) hdlr->data);
9996   if (len >= 20)
9997     stream->subtype = QT_FOURCC ((guint8 *) hdlr->data + 16);
9998   GST_LOG_OBJECT (qtdemux, "track subtype: %" GST_FOURCC_FORMAT,
9999       GST_FOURCC_ARGS (stream->subtype));
10000
10001   if (!(minf = qtdemux_tree_get_child_by_type (mdia, FOURCC_minf)))
10002     goto corrupt_file;
10003
10004   if (!(stbl = qtdemux_tree_get_child_by_type (minf, FOURCC_stbl)))
10005     goto corrupt_file;
10006
10007   /*parse svmi header if existing */
10008   svmi = qtdemux_tree_get_child_by_type (stbl, FOURCC_svmi);
10009   if (svmi) {
10010     len = QT_UINT32 ((guint8 *) svmi->data);
10011     version = QT_UINT32 ((guint8 *) svmi->data + 8);
10012     if (!version) {
10013       GstVideoMultiviewMode mode = GST_VIDEO_MULTIVIEW_MODE_NONE;
10014       GstVideoMultiviewFlags flags = GST_VIDEO_MULTIVIEW_FLAGS_NONE;
10015       guint8 frame_type, frame_layout;
10016
10017       /* MPEG-A stereo video */
10018       if (qtdemux->major_brand == FOURCC_ss02)
10019         flags |= GST_VIDEO_MULTIVIEW_FLAGS_MIXED_MONO;
10020
10021       frame_type = QT_UINT8 ((guint8 *) svmi->data + 12);
10022       frame_layout = QT_UINT8 ((guint8 *) svmi->data + 13) & 0x01;
10023       switch (frame_type) {
10024         case 0:
10025           mode = GST_VIDEO_MULTIVIEW_MODE_SIDE_BY_SIDE;
10026           break;
10027         case 1:
10028           mode = GST_VIDEO_MULTIVIEW_MODE_ROW_INTERLEAVED;
10029           break;
10030         case 2:
10031           mode = GST_VIDEO_MULTIVIEW_MODE_FRAME_BY_FRAME;
10032           break;
10033         case 3:
10034           /* mode 3 is primary/secondary view sequence, ie
10035            * left/right views in separate tracks. See section 7.2
10036            * of ISO/IEC 23000-11:2009 */
10037           GST_FIXME_OBJECT (qtdemux,
10038               "Implement stereo video in separate streams");
10039       }
10040
10041       if ((frame_layout & 0x1) == 0)
10042         flags |= GST_VIDEO_MULTIVIEW_FLAGS_RIGHT_VIEW_FIRST;
10043
10044       GST_LOG_OBJECT (qtdemux,
10045           "StereoVideo: composition type: %u, is_left_first: %u",
10046           frame_type, frame_layout);
10047       stream->multiview_mode = mode;
10048       stream->multiview_flags = flags;
10049     }
10050   }
10051
10052   /* parse rest of tkhd */
10053   if (stream->subtype == FOURCC_vide) {
10054     guint32 matrix[9];
10055
10056     /* version 1 uses some 64-bit ints */
10057     if (!gst_byte_reader_skip (&tkhd, 20 + value_size))
10058       goto corrupt_file;
10059
10060     if (!qtdemux_parse_transformation_matrix (qtdemux, &tkhd, matrix, "tkhd"))
10061       goto corrupt_file;
10062
10063     if (!gst_byte_reader_get_uint32_be (&tkhd, &w)
10064         || !gst_byte_reader_get_uint32_be (&tkhd, &h))
10065       goto corrupt_file;
10066
10067     qtdemux_inspect_transformation_matrix (qtdemux, stream, matrix,
10068         &stream->stream_tags);
10069   }
10070
10071   /* parse stsd */
10072   if (!(stsd = qtdemux_tree_get_child_by_type (stbl, FOURCC_stsd)))
10073     goto corrupt_file;
10074   stsd_data = (const guint8 *) stsd->data;
10075
10076   /* stsd should at least have one entry */
10077   stsd_len = QT_UINT32 (stsd_data);
10078   if (stsd_len < 24) {
10079     /* .. but skip stream with empty stsd produced by some Vivotek cameras */
10080     if (stream->subtype == FOURCC_vivo) {
10081       if (new_stream)
10082         gst_qtdemux_stream_free (stream);
10083       return TRUE;
10084     } else {
10085       goto corrupt_file;
10086     }
10087   }
10088
10089   stream->stsd_entries_length = stsd_entry_count = QT_UINT32 (stsd_data + 12);
10090   stream->stsd_entries = g_new0 (QtDemuxStreamStsdEntry, stsd_entry_count);
10091   GST_LOG_OBJECT (qtdemux, "stsd len:           %d", stsd_len);
10092   GST_LOG_OBJECT (qtdemux, "stsd entry count:   %u", stsd_entry_count);
10093
10094   stsd_entry_data = stsd_data + 16;
10095   remaining_stsd_len = stsd_len - 16;
10096   for (stsd_index = 0; stsd_index < stsd_entry_count; stsd_index++) {
10097     guint32 fourcc;
10098     gchar *codec = NULL;
10099     QtDemuxStreamStsdEntry *entry = &stream->stsd_entries[stsd_index];
10100
10101     /* and that entry should fit within stsd */
10102     len = QT_UINT32 (stsd_entry_data);
10103     if (len > remaining_stsd_len)
10104       goto corrupt_file;
10105
10106     entry->fourcc = fourcc = QT_FOURCC (stsd_entry_data + 4);
10107     GST_LOG_OBJECT (qtdemux, "stsd type:          %" GST_FOURCC_FORMAT,
10108         GST_FOURCC_ARGS (entry->fourcc));
10109     GST_LOG_OBJECT (qtdemux, "stsd type len:      %d", len);
10110
10111     if ((fourcc == FOURCC_drms) || (fourcc == FOURCC_drmi))
10112       goto error_encrypted;
10113
10114     if (fourcc == FOURCC_encv || fourcc == FOURCC_enca) {
10115       /* FIXME this looks wrong, there might be multiple children
10116        * with the same type */
10117       GNode *enc = qtdemux_tree_get_child_by_type (stsd, fourcc);
10118       stream->protected = TRUE;
10119       if (!qtdemux_parse_protection_scheme_info (qtdemux, stream, enc, &fourcc))
10120         GST_ERROR_OBJECT (qtdemux, "Failed to parse protection scheme info");
10121     }
10122
10123     if (stream->subtype == FOURCC_vide) {
10124       GNode *colr;
10125       GNode *fiel;
10126       GNode *pasp;
10127       gboolean gray;
10128       gint depth, palette_size, palette_count;
10129       guint32 *palette_data = NULL;
10130
10131       entry->sampled = TRUE;
10132
10133       stream->display_width = w >> 16;
10134       stream->display_height = h >> 16;
10135
10136       offset = 16;
10137       if (len < 86)             /* TODO verify */
10138         goto corrupt_file;
10139
10140       entry->width = QT_UINT16 (stsd_entry_data + offset + 16);
10141       entry->height = QT_UINT16 (stsd_entry_data + offset + 18);
10142       entry->fps_n = 0;         /* this is filled in later */
10143       entry->fps_d = 0;         /* this is filled in later */
10144       entry->bits_per_sample = QT_UINT16 (stsd_entry_data + offset + 66);
10145       entry->color_table_id = QT_UINT16 (stsd_entry_data + offset + 68);
10146
10147       /* if color_table_id is 0, ctab atom must follow; however some files
10148        * produced by TMPEGEnc have color_table_id = 0 and no ctab atom, so
10149        * if color table is not present we'll correct the value */
10150       if (entry->color_table_id == 0 &&
10151           (len < 90
10152               || QT_FOURCC (stsd_entry_data + offset + 70) != FOURCC_ctab)) {
10153         entry->color_table_id = -1;
10154       }
10155
10156       GST_LOG_OBJECT (qtdemux, "width %d, height %d, bps %d, color table id %d",
10157           entry->width, entry->height, entry->bits_per_sample,
10158           entry->color_table_id);
10159
10160       depth = entry->bits_per_sample;
10161
10162       /* more than 32 bits means grayscale */
10163       gray = (depth > 32);
10164       /* low 32 bits specify the depth  */
10165       depth &= 0x1F;
10166
10167       /* different number of palette entries is determined by depth. */
10168       palette_count = 0;
10169       if ((depth == 1) || (depth == 2) || (depth == 4) || (depth == 8))
10170         palette_count = (1 << depth);
10171       palette_size = palette_count * 4;
10172
10173       if (entry->color_table_id) {
10174         switch (palette_count) {
10175           case 0:
10176             break;
10177           case 2:
10178             palette_data = g_memdup (ff_qt_default_palette_2, palette_size);
10179             break;
10180           case 4:
10181             palette_data = g_memdup (ff_qt_default_palette_4, palette_size);
10182             break;
10183           case 16:
10184             if (gray)
10185               palette_data =
10186                   g_memdup (ff_qt_grayscale_palette_16, palette_size);
10187             else
10188               palette_data = g_memdup (ff_qt_default_palette_16, palette_size);
10189             break;
10190           case 256:
10191             if (gray)
10192               palette_data =
10193                   g_memdup (ff_qt_grayscale_palette_256, palette_size);
10194             else
10195               palette_data = g_memdup (ff_qt_default_palette_256, palette_size);
10196             break;
10197           default:
10198             GST_ELEMENT_WARNING (qtdemux, STREAM, DEMUX,
10199                 (_("The video in this file might not play correctly.")),
10200                 ("unsupported palette depth %d", depth));
10201             break;
10202         }
10203       } else {
10204         gint i, j, start, end;
10205
10206         if (len < 94)
10207           goto corrupt_file;
10208
10209         /* read table */
10210         start = QT_UINT32 (stsd_entry_data + offset + 70);
10211         palette_count = QT_UINT16 (stsd_entry_data + offset + 74);
10212         end = QT_UINT16 (stsd_entry_data + offset + 76);
10213
10214         GST_LOG_OBJECT (qtdemux, "start %d, end %d, palette_count %d",
10215             start, end, palette_count);
10216
10217         if (end > 255)
10218           end = 255;
10219         if (start > end)
10220           start = end;
10221
10222         if (len < 94 + (end - start) * 8)
10223           goto corrupt_file;
10224
10225         /* palette is always the same size */
10226         palette_data = g_malloc0 (256 * 4);
10227         palette_size = 256 * 4;
10228
10229         for (j = 0, i = start; i <= end; j++, i++) {
10230           guint32 a, r, g, b;
10231
10232           a = QT_UINT16 (stsd_entry_data + offset + 78 + (j * 8));
10233           r = QT_UINT16 (stsd_entry_data + offset + 80 + (j * 8));
10234           g = QT_UINT16 (stsd_entry_data + offset + 82 + (j * 8));
10235           b = QT_UINT16 (stsd_entry_data + offset + 84 + (j * 8));
10236
10237           palette_data[i] = ((a & 0xff00) << 16) | ((r & 0xff00) << 8) |
10238               (g & 0xff00) | (b >> 8);
10239         }
10240       }
10241
10242       if (entry->caps)
10243         gst_caps_unref (entry->caps);
10244
10245       entry->caps =
10246           qtdemux_video_caps (qtdemux, stream, entry, fourcc, stsd_entry_data,
10247           &codec);
10248       if (G_UNLIKELY (!entry->caps)) {
10249         g_free (palette_data);
10250         goto unknown_stream;
10251       }
10252
10253       if (codec) {
10254         gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
10255             GST_TAG_VIDEO_CODEC, codec, NULL);
10256         g_free (codec);
10257         codec = NULL;
10258       }
10259
10260       if (palette_data) {
10261         GstStructure *s;
10262
10263         if (entry->rgb8_palette)
10264           gst_memory_unref (entry->rgb8_palette);
10265         entry->rgb8_palette = gst_memory_new_wrapped (GST_MEMORY_FLAG_READONLY,
10266             palette_data, palette_size, 0, palette_size, palette_data, g_free);
10267
10268         s = gst_caps_get_structure (entry->caps, 0);
10269
10270         /* non-raw video has a palette_data property. raw video has the palette as
10271          * an extra plane that we append to the output buffers before we push
10272          * them*/
10273         if (!gst_structure_has_name (s, "video/x-raw")) {
10274           GstBuffer *palette;
10275
10276           palette = gst_buffer_new ();
10277           gst_buffer_append_memory (palette, entry->rgb8_palette);
10278           entry->rgb8_palette = NULL;
10279
10280           gst_caps_set_simple (entry->caps, "palette_data",
10281               GST_TYPE_BUFFER, palette, NULL);
10282           gst_buffer_unref (palette);
10283         }
10284       } else if (palette_count != 0) {
10285         GST_ELEMENT_WARNING (qtdemux, STREAM, NOT_IMPLEMENTED,
10286             (NULL), ("Unsupported palette depth %d", depth));
10287       }
10288
10289       GST_LOG_OBJECT (qtdemux, "frame count:   %u",
10290           QT_UINT16 (stsd_entry_data + offset + 32));
10291
10292       esds = NULL;
10293       pasp = NULL;
10294       colr = NULL;
10295       fiel = NULL;
10296       /* pick 'the' stsd child */
10297       mp4v = qtdemux_tree_get_child_by_index (stsd, stsd_index);
10298       if (!stream->protected) {
10299         if (QTDEMUX_TREE_NODE_FOURCC (mp4v) != fourcc) {
10300           mp4v = NULL;
10301         }
10302       } else {
10303         if (QTDEMUX_TREE_NODE_FOURCC (mp4v) != FOURCC_encv) {
10304           mp4v = NULL;
10305         }
10306       }
10307
10308       if (mp4v) {
10309         esds = qtdemux_tree_get_child_by_type (mp4v, FOURCC_esds);
10310         pasp = qtdemux_tree_get_child_by_type (mp4v, FOURCC_pasp);
10311         colr = qtdemux_tree_get_child_by_type (mp4v, FOURCC_colr);
10312         fiel = qtdemux_tree_get_child_by_type (mp4v, FOURCC_fiel);
10313       }
10314
10315       if (pasp) {
10316         const guint8 *pasp_data = (const guint8 *) pasp->data;
10317         gint len = QT_UINT32 (pasp_data);
10318
10319         if (len == 16) {
10320           CUR_STREAM (stream)->par_w = QT_UINT32 (pasp_data + 8);
10321           CUR_STREAM (stream)->par_h = QT_UINT32 (pasp_data + 12);
10322         } else {
10323           CUR_STREAM (stream)->par_w = 0;
10324           CUR_STREAM (stream)->par_h = 0;
10325         }
10326       } else {
10327         CUR_STREAM (stream)->par_w = 0;
10328         CUR_STREAM (stream)->par_h = 0;
10329       }
10330
10331       if (fiel) {
10332         const guint8 *fiel_data = (const guint8 *) fiel->data;
10333         gint len = QT_UINT32 (fiel_data);
10334
10335         if (len == 10) {
10336           CUR_STREAM (stream)->interlace_mode = GST_READ_UINT8 (fiel_data + 8);
10337           CUR_STREAM (stream)->field_order = GST_READ_UINT8 (fiel_data + 9);
10338         }
10339       }
10340
10341       if (colr) {
10342         const guint8 *colr_data = (const guint8 *) colr->data;
10343         gint len = QT_UINT32 (colr_data);
10344
10345         if (len == 19 || len == 18) {
10346           guint32 color_type = GST_READ_UINT32_LE (colr_data + 8);
10347
10348           if (color_type == FOURCC_nclx || color_type == FOURCC_nclc) {
10349             guint16 primaries = GST_READ_UINT16_BE (colr_data + 12);
10350             guint16 transfer_function = GST_READ_UINT16_BE (colr_data + 14);
10351             guint16 matrix = GST_READ_UINT16_BE (colr_data + 16);
10352             gboolean full_range = len == 19 ? colr_data[17] >> 7 : FALSE;
10353
10354             switch (primaries) {
10355               case 1:
10356                 CUR_STREAM (stream)->colorimetry.primaries =
10357                     GST_VIDEO_COLOR_PRIMARIES_BT709;
10358                 break;
10359               case 5:
10360                 CUR_STREAM (stream)->colorimetry.primaries =
10361                     GST_VIDEO_COLOR_PRIMARIES_BT470BG;
10362                 break;
10363               case 6:
10364                 CUR_STREAM (stream)->colorimetry.primaries =
10365                     GST_VIDEO_COLOR_PRIMARIES_SMPTE170M;
10366                 break;
10367               case 9:
10368                 CUR_STREAM (stream)->colorimetry.primaries =
10369                     GST_VIDEO_COLOR_PRIMARIES_BT2020;
10370                 break;
10371               default:
10372                 break;
10373             }
10374
10375             switch (transfer_function) {
10376               case 1:
10377                 CUR_STREAM (stream)->colorimetry.transfer =
10378                     GST_VIDEO_TRANSFER_BT709;
10379                 break;
10380               case 7:
10381                 CUR_STREAM (stream)->colorimetry.transfer =
10382                     GST_VIDEO_TRANSFER_SMPTE240M;
10383                 break;
10384               default:
10385                 break;
10386             }
10387
10388             switch (matrix) {
10389               case 1:
10390                 CUR_STREAM (stream)->colorimetry.matrix =
10391                     GST_VIDEO_COLOR_MATRIX_BT709;
10392                 break;
10393               case 6:
10394                 CUR_STREAM (stream)->colorimetry.matrix =
10395                     GST_VIDEO_COLOR_MATRIX_BT601;
10396                 break;
10397               case 7:
10398                 CUR_STREAM (stream)->colorimetry.matrix =
10399                     GST_VIDEO_COLOR_MATRIX_SMPTE240M;
10400                 break;
10401               case 9:
10402                 CUR_STREAM (stream)->colorimetry.matrix =
10403                     GST_VIDEO_COLOR_MATRIX_BT2020;
10404                 break;
10405               default:
10406                 break;
10407             }
10408
10409             CUR_STREAM (stream)->colorimetry.range =
10410                 full_range ? GST_VIDEO_COLOR_RANGE_0_255 :
10411                 GST_VIDEO_COLOR_RANGE_16_235;
10412           } else {
10413             GST_DEBUG_OBJECT (qtdemux, "Unsupported color type");
10414           }
10415         } else {
10416           GST_WARNING_OBJECT (qtdemux, "Invalid colr atom size");
10417         }
10418       }
10419
10420       if (esds) {
10421         gst_qtdemux_handle_esds (qtdemux, stream, entry, esds,
10422             stream->stream_tags);
10423       } else {
10424         switch (fourcc) {
10425           case FOURCC_H264:
10426           case FOURCC_avc1:
10427           case FOURCC_avc3:
10428           {
10429             gint len = QT_UINT32 (stsd_entry_data) - 0x56;
10430             const guint8 *avc_data = stsd_entry_data + 0x56;
10431
10432             /* find avcC */
10433             while (len >= 0x8) {
10434               gint size;
10435
10436               if (QT_UINT32 (avc_data) <= len)
10437                 size = QT_UINT32 (avc_data) - 0x8;
10438               else
10439                 size = len - 0x8;
10440
10441               if (size < 1)
10442                 /* No real data, so break out */
10443                 break;
10444
10445               switch (QT_FOURCC (avc_data + 0x4)) {
10446                 case FOURCC_avcC:
10447                 {
10448                   /* parse, if found */
10449                   GstBuffer *buf;
10450
10451                   GST_DEBUG_OBJECT (qtdemux, "found avcC codec_data in stsd");
10452
10453                   /* First 4 bytes are the length of the atom, the next 4 bytes
10454                    * are the fourcc, the next 1 byte is the version, and the
10455                    * subsequent bytes are profile_tier_level structure like data. */
10456                   gst_codec_utils_h264_caps_set_level_and_profile (entry->caps,
10457                       avc_data + 8 + 1, size - 1);
10458                   buf = gst_buffer_new_and_alloc (size);
10459                   gst_buffer_fill (buf, 0, avc_data + 0x8, size);
10460                   gst_caps_set_simple (entry->caps,
10461                       "codec_data", GST_TYPE_BUFFER, buf, NULL);
10462                   gst_buffer_unref (buf);
10463
10464                   break;
10465                 }
10466                 case FOURCC_strf:
10467                 {
10468                   GstBuffer *buf;
10469
10470                   GST_DEBUG_OBJECT (qtdemux, "found strf codec_data in stsd");
10471
10472                   /* First 4 bytes are the length of the atom, the next 4 bytes
10473                    * are the fourcc, next 40 bytes are BITMAPINFOHEADER,
10474                    * next 1 byte is the version, and the
10475                    * subsequent bytes are sequence parameter set like data. */
10476
10477                   size -= 40;   /* we'll be skipping BITMAPINFOHEADER */
10478                   if (size > 1) {
10479                     gst_codec_utils_h264_caps_set_level_and_profile
10480                         (entry->caps, avc_data + 8 + 40 + 1, size - 1);
10481
10482                     buf = gst_buffer_new_and_alloc (size);
10483                     gst_buffer_fill (buf, 0, avc_data + 8 + 40, size);
10484                     gst_caps_set_simple (entry->caps,
10485                         "codec_data", GST_TYPE_BUFFER, buf, NULL);
10486                     gst_buffer_unref (buf);
10487                   }
10488                   break;
10489                 }
10490                 case FOURCC_btrt:
10491                 {
10492                   guint avg_bitrate, max_bitrate;
10493
10494                   /* bufferSizeDB, maxBitrate and avgBitrate - 4 bytes each */
10495                   if (size < 12)
10496                     break;
10497
10498                   max_bitrate = QT_UINT32 (avc_data + 0xc);
10499                   avg_bitrate = QT_UINT32 (avc_data + 0x10);
10500
10501                   if (!max_bitrate && !avg_bitrate)
10502                     break;
10503
10504                   /* Some muxers seem to swap the average and maximum bitrates
10505                    * (I'm looking at you, YouTube), so we swap for sanity. */
10506                   if (max_bitrate > 0 && max_bitrate < avg_bitrate) {
10507                     guint temp = avg_bitrate;
10508
10509                     avg_bitrate = max_bitrate;
10510                     max_bitrate = temp;
10511                   }
10512
10513                   if (max_bitrate > 0 && max_bitrate < G_MAXUINT32) {
10514                     gst_tag_list_add (stream->stream_tags,
10515                         GST_TAG_MERGE_REPLACE, GST_TAG_MAXIMUM_BITRATE,
10516                         max_bitrate, NULL);
10517                   }
10518                   if (avg_bitrate > 0 && avg_bitrate < G_MAXUINT32) {
10519                     gst_tag_list_add (stream->stream_tags,
10520                         GST_TAG_MERGE_REPLACE, GST_TAG_BITRATE, avg_bitrate,
10521                         NULL);
10522                   }
10523
10524                   break;
10525                 }
10526
10527                 default:
10528                   break;
10529               }
10530
10531               len -= size + 8;
10532               avc_data += size + 8;
10533             }
10534
10535             break;
10536           }
10537           case FOURCC_H265:
10538           case FOURCC_hvc1:
10539           case FOURCC_hev1:
10540           {
10541             gint len = QT_UINT32 (stsd_entry_data) - 0x56;
10542             const guint8 *hevc_data = stsd_entry_data + 0x56;
10543
10544             /* find hevc */
10545             while (len >= 0x8) {
10546               gint size;
10547
10548               if (QT_UINT32 (hevc_data) <= len)
10549                 size = QT_UINT32 (hevc_data) - 0x8;
10550               else
10551                 size = len - 0x8;
10552
10553               if (size < 1)
10554                 /* No real data, so break out */
10555                 break;
10556
10557               switch (QT_FOURCC (hevc_data + 0x4)) {
10558                 case FOURCC_hvcC:
10559                 {
10560                   /* parse, if found */
10561                   GstBuffer *buf;
10562
10563                   GST_DEBUG_OBJECT (qtdemux, "found hvcC codec_data in stsd");
10564
10565                   /* First 4 bytes are the length of the atom, the next 4 bytes
10566                    * are the fourcc, the next 1 byte is the version, and the
10567                    * subsequent bytes are sequence parameter set like data. */
10568                   gst_codec_utils_h265_caps_set_level_tier_and_profile
10569                       (entry->caps, hevc_data + 8 + 1, size - 1);
10570
10571                   buf = gst_buffer_new_and_alloc (size);
10572                   gst_buffer_fill (buf, 0, hevc_data + 0x8, size);
10573                   gst_caps_set_simple (entry->caps,
10574                       "codec_data", GST_TYPE_BUFFER, buf, NULL);
10575                   gst_buffer_unref (buf);
10576                   break;
10577                 }
10578                 default:
10579                   break;
10580               }
10581               len -= size + 8;
10582               hevc_data += size + 8;
10583             }
10584             break;
10585           }
10586           case FOURCC_mp4v:
10587           case FOURCC_MP4V:
10588           case FOURCC_fmp4:
10589           case FOURCC_FMP4:
10590           case FOURCC_xvid:
10591           case FOURCC_XVID:
10592           {
10593             GNode *glbl;
10594
10595             GST_DEBUG_OBJECT (qtdemux, "found %" GST_FOURCC_FORMAT,
10596                 GST_FOURCC_ARGS (fourcc));
10597
10598             /* codec data might be in glbl extension atom */
10599             glbl = mp4v ?
10600                 qtdemux_tree_get_child_by_type (mp4v, FOURCC_glbl) : NULL;
10601             if (glbl) {
10602               guint8 *data;
10603               GstBuffer *buf;
10604               gint len;
10605
10606               GST_DEBUG_OBJECT (qtdemux, "found glbl data in stsd");
10607               data = glbl->data;
10608               len = QT_UINT32 (data);
10609               if (len > 0x8) {
10610                 len -= 0x8;
10611                 buf = gst_buffer_new_and_alloc (len);
10612                 gst_buffer_fill (buf, 0, data + 8, len);
10613                 gst_caps_set_simple (entry->caps,
10614                     "codec_data", GST_TYPE_BUFFER, buf, NULL);
10615                 gst_buffer_unref (buf);
10616               }
10617             }
10618             break;
10619           }
10620           case FOURCC_mjp2:
10621           {
10622             /* see annex I of the jpeg2000 spec */
10623             GNode *jp2h, *ihdr, *colr, *mjp2, *field, *prefix, *cmap, *cdef;
10624             const guint8 *data;
10625             const gchar *colorspace = NULL;
10626             gint ncomp = 0;
10627             guint32 ncomp_map = 0;
10628             gint32 *comp_map = NULL;
10629             guint32 nchan_def = 0;
10630             gint32 *chan_def = NULL;
10631
10632             GST_DEBUG_OBJECT (qtdemux, "found mjp2");
10633             /* some required atoms */
10634             mjp2 = qtdemux_tree_get_child_by_index (stsd, stsd_index);
10635             if (!mjp2)
10636               break;
10637             jp2h = qtdemux_tree_get_child_by_type (mjp2, FOURCC_jp2h);
10638             if (!jp2h)
10639               break;
10640
10641             /* number of components; redundant with info in codestream, but useful
10642                to a muxer */
10643             ihdr = qtdemux_tree_get_child_by_type (jp2h, FOURCC_ihdr);
10644             if (!ihdr || QT_UINT32 (ihdr->data) != 22)
10645               break;
10646             ncomp = QT_UINT16 (((guint8 *) ihdr->data) + 16);
10647
10648             colr = qtdemux_tree_get_child_by_type (jp2h, FOURCC_colr);
10649             if (!colr)
10650               break;
10651             GST_DEBUG_OBJECT (qtdemux, "found colr");
10652             /* extract colour space info */
10653             if (QT_UINT8 ((guint8 *) colr->data + 8) == 1) {
10654               switch (QT_UINT32 ((guint8 *) colr->data + 11)) {
10655                 case 16:
10656                   colorspace = "sRGB";
10657                   break;
10658                 case 17:
10659                   colorspace = "GRAY";
10660                   break;
10661                 case 18:
10662                   colorspace = "sYUV";
10663                   break;
10664                 default:
10665                   colorspace = NULL;
10666                   break;
10667               }
10668             }
10669             if (!colorspace)
10670               /* colr is required, and only values 16, 17, and 18 are specified,
10671                  so error if we have no colorspace */
10672               break;
10673
10674             /* extract component mapping */
10675             cmap = qtdemux_tree_get_child_by_type (jp2h, FOURCC_cmap);
10676             if (cmap) {
10677               guint32 cmap_len = 0;
10678               int i;
10679               cmap_len = QT_UINT32 (cmap->data);
10680               if (cmap_len >= 8) {
10681                 /* normal box, subtract off header */
10682                 cmap_len -= 8;
10683                 /* cmap: { u16 cmp; u8 mtyp; u8 pcol; }* */
10684                 if (cmap_len % 4 == 0) {
10685                   ncomp_map = (cmap_len / 4);
10686                   comp_map = g_new0 (gint32, ncomp_map);
10687                   for (i = 0; i < ncomp_map; i++) {
10688                     guint16 cmp;
10689                     guint8 mtyp, pcol;
10690                     cmp = QT_UINT16 (((guint8 *) cmap->data) + 8 + i * 4);
10691                     mtyp = QT_UINT8 (((guint8 *) cmap->data) + 8 + i * 4 + 2);
10692                     pcol = QT_UINT8 (((guint8 *) cmap->data) + 8 + i * 4 + 3);
10693                     comp_map[i] = (mtyp << 24) | (pcol << 16) | cmp;
10694                   }
10695                 }
10696               }
10697             }
10698             /* extract channel definitions */
10699             cdef = qtdemux_tree_get_child_by_type (jp2h, FOURCC_cdef);
10700             if (cdef) {
10701               guint32 cdef_len = 0;
10702               int i;
10703               cdef_len = QT_UINT32 (cdef->data);
10704               if (cdef_len >= 10) {
10705                 /* normal box, subtract off header and len */
10706                 cdef_len -= 10;
10707                 /* cdef: u16 n; { u16 cn; u16 typ; u16 asoc; }* */
10708                 if (cdef_len % 6 == 0) {
10709                   nchan_def = (cdef_len / 6);
10710                   chan_def = g_new0 (gint32, nchan_def);
10711                   for (i = 0; i < nchan_def; i++)
10712                     chan_def[i] = -1;
10713                   for (i = 0; i < nchan_def; i++) {
10714                     guint16 cn, typ, asoc;
10715                     cn = QT_UINT16 (((guint8 *) cdef->data) + 10 + i * 6);
10716                     typ = QT_UINT16 (((guint8 *) cdef->data) + 10 + i * 6 + 2);
10717                     asoc = QT_UINT16 (((guint8 *) cdef->data) + 10 + i * 6 + 4);
10718                     if (cn < nchan_def) {
10719                       switch (typ) {
10720                         case 0:
10721                           chan_def[cn] = asoc;
10722                           break;
10723                         case 1:
10724                           chan_def[cn] = 0;     /* alpha */
10725                           break;
10726                         default:
10727                           chan_def[cn] = -typ;
10728                       }
10729                     }
10730                   }
10731                 }
10732               }
10733             }
10734
10735             gst_caps_set_simple (entry->caps,
10736                 "num-components", G_TYPE_INT, ncomp, NULL);
10737             gst_caps_set_simple (entry->caps,
10738                 "colorspace", G_TYPE_STRING, colorspace, NULL);
10739
10740             if (comp_map) {
10741               GValue arr = { 0, };
10742               GValue elt = { 0, };
10743               int i;
10744               g_value_init (&arr, GST_TYPE_ARRAY);
10745               g_value_init (&elt, G_TYPE_INT);
10746               for (i = 0; i < ncomp_map; i++) {
10747                 g_value_set_int (&elt, comp_map[i]);
10748                 gst_value_array_append_value (&arr, &elt);
10749               }
10750               gst_structure_set_value (gst_caps_get_structure (entry->caps, 0),
10751                   "component-map", &arr);
10752               g_value_unset (&elt);
10753               g_value_unset (&arr);
10754               g_free (comp_map);
10755             }
10756
10757             if (chan_def) {
10758               GValue arr = { 0, };
10759               GValue elt = { 0, };
10760               int i;
10761               g_value_init (&arr, GST_TYPE_ARRAY);
10762               g_value_init (&elt, G_TYPE_INT);
10763               for (i = 0; i < nchan_def; i++) {
10764                 g_value_set_int (&elt, chan_def[i]);
10765                 gst_value_array_append_value (&arr, &elt);
10766               }
10767               gst_structure_set_value (gst_caps_get_structure (entry->caps, 0),
10768                   "channel-definitions", &arr);
10769               g_value_unset (&elt);
10770               g_value_unset (&arr);
10771               g_free (chan_def);
10772             }
10773
10774             /* some optional atoms */
10775             field = qtdemux_tree_get_child_by_type (mjp2, FOURCC_fiel);
10776             prefix = qtdemux_tree_get_child_by_type (mjp2, FOURCC_jp2x);
10777
10778             /* indicate possible fields in caps */
10779             if (field) {
10780               data = (guint8 *) field->data + 8;
10781               if (*data != 1)
10782                 gst_caps_set_simple (entry->caps, "fields", G_TYPE_INT,
10783                     (gint) * data, NULL);
10784             }
10785             /* add codec_data if provided */
10786             if (prefix) {
10787               GstBuffer *buf;
10788               gint len;
10789
10790               GST_DEBUG_OBJECT (qtdemux, "found prefix data in stsd");
10791               data = prefix->data;
10792               len = QT_UINT32 (data);
10793               if (len > 0x8) {
10794                 len -= 0x8;
10795                 buf = gst_buffer_new_and_alloc (len);
10796                 gst_buffer_fill (buf, 0, data + 8, len);
10797                 gst_caps_set_simple (entry->caps,
10798                     "codec_data", GST_TYPE_BUFFER, buf, NULL);
10799                 gst_buffer_unref (buf);
10800               }
10801             }
10802             break;
10803           }
10804           case FOURCC_SVQ3:
10805           case FOURCC_VP31:
10806           {
10807             GstBuffer *buf;
10808             GstBuffer *seqh = NULL;
10809             const guint8 *gamma_data = NULL;
10810             gint len = QT_UINT32 (stsd_data);   /* FIXME review - why put the whole stsd in codec data? */
10811
10812             qtdemux_parse_svq3_stsd_data (qtdemux, stsd_entry_data, &gamma_data,
10813                 &seqh);
10814             if (gamma_data) {
10815               gst_caps_set_simple (entry->caps, "applied-gamma", G_TYPE_DOUBLE,
10816                   QT_FP32 (gamma_data), NULL);
10817             }
10818             if (seqh) {
10819               /* sorry for the bad name, but we don't know what this is, other
10820                * than its own fourcc */
10821               gst_caps_set_simple (entry->caps, "seqh", GST_TYPE_BUFFER, seqh,
10822                   NULL);
10823               gst_buffer_unref (seqh);
10824             }
10825
10826             GST_DEBUG_OBJECT (qtdemux, "found codec_data in stsd");
10827             buf = gst_buffer_new_and_alloc (len);
10828             gst_buffer_fill (buf, 0, stsd_data, len);
10829             gst_caps_set_simple (entry->caps,
10830                 "codec_data", GST_TYPE_BUFFER, buf, NULL);
10831             gst_buffer_unref (buf);
10832             break;
10833           }
10834           case FOURCC_jpeg:
10835           {
10836             /* https://developer.apple.com/standards/qtff-2001.pdf,
10837              * page 92, "Video Sample Description", under table 3.1 */
10838             GstByteReader br;
10839
10840             const gint compressor_offset =
10841                 16 + 4 + 4 * 3 + 2 * 2 + 2 * 4 + 4 + 2;
10842             const gint min_size = compressor_offset + 32 + 2 + 2;
10843             GNode *jpeg;
10844             guint32 len;
10845             guint16 color_table_id = 0;
10846             gboolean ok;
10847
10848             GST_DEBUG_OBJECT (qtdemux, "found jpeg");
10849
10850             /* recover information on interlaced/progressive */
10851             jpeg = qtdemux_tree_get_child_by_type (stsd, FOURCC_jpeg);
10852             if (!jpeg)
10853               break;
10854
10855             len = QT_UINT32 (jpeg->data);
10856             GST_DEBUG_OBJECT (qtdemux, "Found jpeg: len %u, need %d", len,
10857                 min_size);
10858             if (len >= min_size) {
10859               gst_byte_reader_init (&br, jpeg->data, len);
10860
10861               gst_byte_reader_skip (&br, compressor_offset + 32 + 2);
10862               gst_byte_reader_get_uint16_le (&br, &color_table_id);
10863               if (color_table_id != 0) {
10864                 /* the spec says there can be concatenated chunks in the data, and we want
10865                  * to find one called field. Walk through them. */
10866                 gint offset = min_size;
10867                 while (offset + 8 < len) {
10868                   guint32 size = 0, tag;
10869                   ok = gst_byte_reader_get_uint32_le (&br, &size);
10870                   ok &= gst_byte_reader_get_uint32_le (&br, &tag);
10871                   if (!ok || size < 8) {
10872                     GST_WARNING_OBJECT (qtdemux,
10873                         "Failed to walk optional chunk list");
10874                     break;
10875                   }
10876                   GST_DEBUG_OBJECT (qtdemux,
10877                       "Found optional %4.4s chunk, size %u",
10878                       (const char *) &tag, size);
10879                   if (tag == FOURCC_fiel) {
10880                     guint8 n_fields = 0, ordering = 0;
10881                     gst_byte_reader_get_uint8 (&br, &n_fields);
10882                     gst_byte_reader_get_uint8 (&br, &ordering);
10883                     if (n_fields == 1 || n_fields == 2) {
10884                       GST_DEBUG_OBJECT (qtdemux,
10885                           "Found fiel tag with %u fields, ordering %u",
10886                           n_fields, ordering);
10887                       if (n_fields == 2)
10888                         gst_caps_set_simple (CUR_STREAM (stream)->caps,
10889                             "interlace-mode", G_TYPE_STRING, "interleaved",
10890                             NULL);
10891                     } else {
10892                       GST_WARNING_OBJECT (qtdemux,
10893                           "Found fiel tag with invalid fields (%u)", n_fields);
10894                     }
10895                   }
10896                   offset += size;
10897                 }
10898               } else {
10899                 GST_DEBUG_OBJECT (qtdemux,
10900                     "Color table ID is 0, not trying to get interlacedness");
10901               }
10902             } else {
10903               GST_WARNING_OBJECT (qtdemux,
10904                   "Length of jpeg chunk is too small, not trying to get interlacedness");
10905             }
10906
10907             break;
10908           }
10909           case FOURCC_rle_:
10910           case FOURCC_WRLE:
10911           {
10912             gst_caps_set_simple (entry->caps,
10913                 "depth", G_TYPE_INT, QT_UINT16 (stsd_entry_data + offset + 66),
10914                 NULL);
10915             break;
10916           }
10917           case FOURCC_XiTh:
10918           {
10919             GNode *xith, *xdxt;
10920
10921             GST_DEBUG_OBJECT (qtdemux, "found XiTh");
10922             xith = qtdemux_tree_get_child_by_index (stsd, stsd_index);
10923             if (!xith)
10924               break;
10925
10926             xdxt = qtdemux_tree_get_child_by_type (xith, FOURCC_XdxT);
10927             if (!xdxt)
10928               break;
10929
10930             GST_DEBUG_OBJECT (qtdemux, "found XdxT node");
10931             /* collect the headers and store them in a stream list so that we can
10932              * send them out first */
10933             qtdemux_parse_theora_extension (qtdemux, stream, xdxt);
10934             break;
10935           }
10936           case FOURCC_ovc1:
10937           {
10938             GNode *ovc1;
10939             guint8 *ovc1_data;
10940             guint ovc1_len;
10941             GstBuffer *buf;
10942
10943             GST_DEBUG_OBJECT (qtdemux, "parse ovc1 header");
10944             ovc1 = qtdemux_tree_get_child_by_index (stsd, stsd_index);
10945             if (!ovc1)
10946               break;
10947             ovc1_data = ovc1->data;
10948             ovc1_len = QT_UINT32 (ovc1_data);
10949             if (ovc1_len <= 198) {
10950               GST_WARNING_OBJECT (qtdemux, "Too small ovc1 header, skipping");
10951               break;
10952             }
10953             buf = gst_buffer_new_and_alloc (ovc1_len - 198);
10954             gst_buffer_fill (buf, 0, ovc1_data + 198, ovc1_len - 198);
10955             gst_caps_set_simple (entry->caps,
10956                 "codec_data", GST_TYPE_BUFFER, buf, NULL);
10957             gst_buffer_unref (buf);
10958             break;
10959           }
10960           case FOURCC_vc_1:
10961           {
10962             gint len = QT_UINT32 (stsd_entry_data) - 0x56;
10963             const guint8 *vc1_data = stsd_entry_data + 0x56;
10964
10965             /* find dvc1 */
10966             while (len >= 8) {
10967               gint size;
10968
10969               if (QT_UINT32 (vc1_data) <= len)
10970                 size = QT_UINT32 (vc1_data) - 8;
10971               else
10972                 size = len - 8;
10973
10974               if (size < 1)
10975                 /* No real data, so break out */
10976                 break;
10977
10978               switch (QT_FOURCC (vc1_data + 0x4)) {
10979                 case GST_MAKE_FOURCC ('d', 'v', 'c', '1'):
10980                 {
10981                   GstBuffer *buf;
10982
10983                   GST_DEBUG_OBJECT (qtdemux, "found dvc1 codec_data in stsd");
10984                   buf = gst_buffer_new_and_alloc (size);
10985                   gst_buffer_fill (buf, 0, vc1_data + 8, size);
10986                   gst_caps_set_simple (entry->caps,
10987                       "codec_data", GST_TYPE_BUFFER, buf, NULL);
10988                   gst_buffer_unref (buf);
10989                   break;
10990                 }
10991                 default:
10992                   break;
10993               }
10994               len -= size + 8;
10995               vc1_data += size + 8;
10996             }
10997             break;
10998           }
10999           default:
11000             break;
11001         }
11002       }
11003
11004       GST_INFO_OBJECT (qtdemux,
11005           "type %" GST_FOURCC_FORMAT " caps %" GST_PTR_FORMAT,
11006           GST_FOURCC_ARGS (fourcc), entry->caps);
11007
11008     } else if (stream->subtype == FOURCC_soun) {
11009       GNode *wave;
11010       int version, samplesize;
11011       guint16 compression_id;
11012       gboolean amrwb = FALSE;
11013
11014       offset = 16;
11015       /* sample description entry (16) + sound sample description v0 (20) */
11016       if (len < 36)
11017         goto corrupt_file;
11018
11019       version = QT_UINT32 (stsd_entry_data + offset);
11020       entry->n_channels = QT_UINT16 (stsd_entry_data + offset + 8);
11021       samplesize = QT_UINT16 (stsd_entry_data + offset + 10);
11022       compression_id = QT_UINT16 (stsd_entry_data + offset + 12);
11023       entry->rate = QT_FP32 (stsd_entry_data + offset + 16);
11024
11025       GST_LOG_OBJECT (qtdemux, "version/rev:      %08x", version);
11026       GST_LOG_OBJECT (qtdemux, "vendor:           %08x",
11027           QT_UINT32 (stsd_entry_data + offset + 4));
11028       GST_LOG_OBJECT (qtdemux, "n_channels:       %d", entry->n_channels);
11029       GST_LOG_OBJECT (qtdemux, "sample_size:      %d", samplesize);
11030       GST_LOG_OBJECT (qtdemux, "compression_id:   %d", compression_id);
11031       GST_LOG_OBJECT (qtdemux, "packet size:      %d",
11032           QT_UINT16 (stsd_entry_data + offset + 14));
11033       GST_LOG_OBJECT (qtdemux, "sample rate:      %g", entry->rate);
11034
11035       if (compression_id == 0xfffe)
11036         entry->sampled = TRUE;
11037
11038       /* first assume uncompressed audio */
11039       entry->bytes_per_sample = samplesize / 8;
11040       entry->samples_per_frame = entry->n_channels;
11041       entry->bytes_per_frame = entry->n_channels * entry->bytes_per_sample;
11042       entry->samples_per_packet = entry->samples_per_frame;
11043       entry->bytes_per_packet = entry->bytes_per_sample;
11044
11045       offset = 36;
11046       switch (fourcc) {
11047           /* Yes, these have to be hard-coded */
11048         case FOURCC_MAC6:
11049         {
11050           entry->samples_per_packet = 6;
11051           entry->bytes_per_packet = 1;
11052           entry->bytes_per_frame = 1 * entry->n_channels;
11053           entry->bytes_per_sample = 1;
11054           entry->samples_per_frame = 6 * entry->n_channels;
11055           break;
11056         }
11057         case FOURCC_MAC3:
11058         {
11059           entry->samples_per_packet = 3;
11060           entry->bytes_per_packet = 1;
11061           entry->bytes_per_frame = 1 * entry->n_channels;
11062           entry->bytes_per_sample = 1;
11063           entry->samples_per_frame = 3 * entry->n_channels;
11064           break;
11065         }
11066         case FOURCC_ima4:
11067         {
11068           entry->samples_per_packet = 64;
11069           entry->bytes_per_packet = 34;
11070           entry->bytes_per_frame = 34 * entry->n_channels;
11071           entry->bytes_per_sample = 2;
11072           entry->samples_per_frame = 64 * entry->n_channels;
11073           break;
11074         }
11075         case FOURCC_ulaw:
11076         case FOURCC_alaw:
11077         {
11078           entry->samples_per_packet = 1;
11079           entry->bytes_per_packet = 1;
11080           entry->bytes_per_frame = 1 * entry->n_channels;
11081           entry->bytes_per_sample = 1;
11082           entry->samples_per_frame = 1 * entry->n_channels;
11083           break;
11084         }
11085         case FOURCC_agsm:
11086         {
11087           entry->samples_per_packet = 160;
11088           entry->bytes_per_packet = 33;
11089           entry->bytes_per_frame = 33 * entry->n_channels;
11090           entry->bytes_per_sample = 2;
11091           entry->samples_per_frame = 160 * entry->n_channels;
11092           break;
11093         }
11094         default:
11095           break;
11096       }
11097
11098       if (version == 0x00010000) {
11099         /* sample description entry (16) + sound sample description v1 (20+16) */
11100         if (len < 52)
11101           goto corrupt_file;
11102
11103         switch (fourcc) {
11104           case FOURCC_twos:
11105           case FOURCC_sowt:
11106           case FOURCC_raw_:
11107           case FOURCC_lpcm:
11108             break;
11109           default:
11110           {
11111             /* only parse extra decoding config for non-pcm audio */
11112             entry->samples_per_packet = QT_UINT32 (stsd_entry_data + offset);
11113             entry->bytes_per_packet = QT_UINT32 (stsd_entry_data + offset + 4);
11114             entry->bytes_per_frame = QT_UINT32 (stsd_entry_data + offset + 8);
11115             entry->bytes_per_sample = QT_UINT32 (stsd_entry_data + offset + 12);
11116
11117             GST_LOG_OBJECT (qtdemux, "samples/packet:   %d",
11118                 entry->samples_per_packet);
11119             GST_LOG_OBJECT (qtdemux, "bytes/packet:     %d",
11120                 entry->bytes_per_packet);
11121             GST_LOG_OBJECT (qtdemux, "bytes/frame:      %d",
11122                 entry->bytes_per_frame);
11123             GST_LOG_OBJECT (qtdemux, "bytes/sample:     %d",
11124                 entry->bytes_per_sample);
11125
11126             if (!entry->sampled && entry->bytes_per_packet) {
11127               entry->samples_per_frame = (entry->bytes_per_frame /
11128                   entry->bytes_per_packet) * entry->samples_per_packet;
11129               GST_LOG_OBJECT (qtdemux, "samples/frame:    %d",
11130                   entry->samples_per_frame);
11131             }
11132             break;
11133           }
11134         }
11135       } else if (version == 0x00020000) {
11136         union
11137         {
11138           gdouble fp;
11139           guint64 val;
11140         } qtfp;
11141
11142         /* sample description entry (16) + sound sample description v2 (56) */
11143         if (len < 72)
11144           goto corrupt_file;
11145
11146         qtfp.val = QT_UINT64 (stsd_entry_data + offset + 4);
11147         entry->rate = qtfp.fp;
11148         entry->n_channels = QT_UINT32 (stsd_entry_data + offset + 12);
11149
11150         GST_LOG_OBJECT (qtdemux, "Sound sample description Version 2");
11151         GST_LOG_OBJECT (qtdemux, "sample rate:        %g", entry->rate);
11152         GST_LOG_OBJECT (qtdemux, "n_channels:         %d", entry->n_channels);
11153         GST_LOG_OBJECT (qtdemux, "bits/channel:       %d",
11154             QT_UINT32 (stsd_entry_data + offset + 20));
11155         GST_LOG_OBJECT (qtdemux, "format flags:       %X",
11156             QT_UINT32 (stsd_entry_data + offset + 24));
11157         GST_LOG_OBJECT (qtdemux, "bytes/packet:       %d",
11158             QT_UINT32 (stsd_entry_data + offset + 28));
11159         GST_LOG_OBJECT (qtdemux, "LPCM frames/packet: %d",
11160             QT_UINT32 (stsd_entry_data + offset + 32));
11161       } else if (version != 0x00000) {
11162         GST_WARNING_OBJECT (qtdemux, "unknown audio STSD version %08x",
11163             version);
11164       }
11165
11166       if (entry->caps)
11167         gst_caps_unref (entry->caps);
11168
11169       entry->caps = qtdemux_audio_caps (qtdemux, stream, entry, fourcc,
11170           stsd_entry_data + 32, len - 16, &codec);
11171
11172       switch (fourcc) {
11173         case FOURCC_in24:
11174         {
11175           GNode *enda;
11176           GNode *in24;
11177
11178           in24 = qtdemux_tree_get_child_by_type (stsd, FOURCC_in24);
11179
11180           enda = qtdemux_tree_get_child_by_type (in24, FOURCC_enda);
11181           if (!enda) {
11182             wave = qtdemux_tree_get_child_by_type (in24, FOURCC_wave);
11183             if (wave)
11184               enda = qtdemux_tree_get_child_by_type (wave, FOURCC_enda);
11185           }
11186           if (enda) {
11187             int enda_value = QT_UINT16 ((guint8 *) enda->data + 8);
11188             gst_caps_set_simple (entry->caps,
11189                 "format", G_TYPE_STRING, (enda_value) ? "S24LE" : "S24BE",
11190                 NULL);
11191           }
11192           break;
11193         }
11194         case FOURCC_owma:
11195         {
11196           const guint8 *owma_data;
11197           const gchar *codec_name = NULL;
11198           guint owma_len;
11199           GstBuffer *buf;
11200           gint version = 1;
11201           /* from http://msdn.microsoft.com/en-us/library/dd757720(VS.85).aspx */
11202           /* FIXME this should also be gst_riff_strf_auds,
11203            * but the latter one is actually missing bits-per-sample :( */
11204           typedef struct
11205           {
11206             gint16 wFormatTag;
11207             gint16 nChannels;
11208             gint32 nSamplesPerSec;
11209             gint32 nAvgBytesPerSec;
11210             gint16 nBlockAlign;
11211             gint16 wBitsPerSample;
11212             gint16 cbSize;
11213           } WAVEFORMATEX;
11214           WAVEFORMATEX *wfex;
11215
11216           GST_DEBUG_OBJECT (qtdemux, "parse owma");
11217           owma_data = stsd_entry_data;
11218           owma_len = QT_UINT32 (owma_data);
11219           if (owma_len <= 54) {
11220             GST_WARNING_OBJECT (qtdemux, "Too small owma header, skipping");
11221             break;
11222           }
11223           wfex = (WAVEFORMATEX *) (owma_data + 36);
11224           buf = gst_buffer_new_and_alloc (owma_len - 54);
11225           gst_buffer_fill (buf, 0, owma_data + 54, owma_len - 54);
11226           if (wfex->wFormatTag == 0x0161) {
11227             codec_name = "Windows Media Audio";
11228             version = 2;
11229           } else if (wfex->wFormatTag == 0x0162) {
11230             codec_name = "Windows Media Audio 9 Pro";
11231             version = 3;
11232           } else if (wfex->wFormatTag == 0x0163) {
11233             codec_name = "Windows Media Audio 9 Lossless";
11234             /* is that correct? gstffmpegcodecmap.c is missing it, but
11235              * fluendo codec seems to support it */
11236             version = 4;
11237           }
11238
11239           gst_caps_set_simple (entry->caps,
11240               "codec_data", GST_TYPE_BUFFER, buf,
11241               "wmaversion", G_TYPE_INT, version,
11242               "block_align", G_TYPE_INT,
11243               GST_READ_UINT16_LE (&wfex->nBlockAlign), "bitrate", G_TYPE_INT,
11244               GST_READ_UINT32_LE (&wfex->nAvgBytesPerSec), "width", G_TYPE_INT,
11245               GST_READ_UINT16_LE (&wfex->wBitsPerSample), "depth", G_TYPE_INT,
11246               GST_READ_UINT16_LE (&wfex->wBitsPerSample), NULL);
11247           gst_buffer_unref (buf);
11248
11249           if (codec_name) {
11250             g_free (codec);
11251             codec = g_strdup (codec_name);
11252           }
11253           break;
11254         }
11255         case FOURCC_wma_:
11256         {
11257           gint len = QT_UINT32 (stsd_entry_data) - offset;
11258           const guint8 *wfex_data = stsd_entry_data + offset;
11259           const gchar *codec_name = NULL;
11260           gint version = 1;
11261           /* from http://msdn.microsoft.com/en-us/library/dd757720(VS.85).aspx */
11262           /* FIXME this should also be gst_riff_strf_auds,
11263            * but the latter one is actually missing bits-per-sample :( */
11264           typedef struct
11265           {
11266             gint16 wFormatTag;
11267             gint16 nChannels;
11268             gint32 nSamplesPerSec;
11269             gint32 nAvgBytesPerSec;
11270             gint16 nBlockAlign;
11271             gint16 wBitsPerSample;
11272             gint16 cbSize;
11273           } WAVEFORMATEX;
11274           WAVEFORMATEX wfex;
11275
11276           /* FIXME: unify with similar wavformatex parsing code above */
11277           GST_DEBUG_OBJECT (qtdemux, "parse wma, looking for wfex");
11278
11279           /* find wfex */
11280           while (len >= 8) {
11281             gint size;
11282
11283             if (QT_UINT32 (wfex_data) <= len)
11284               size = QT_UINT32 (wfex_data) - 8;
11285             else
11286               size = len - 8;
11287
11288             if (size < 1)
11289               /* No real data, so break out */
11290               break;
11291
11292             switch (QT_FOURCC (wfex_data + 4)) {
11293               case GST_MAKE_FOURCC ('w', 'f', 'e', 'x'):
11294               {
11295                 GST_DEBUG_OBJECT (qtdemux, "found wfex in stsd");
11296
11297                 if (size < 8 + 18)
11298                   break;
11299
11300                 wfex.wFormatTag = GST_READ_UINT16_LE (wfex_data + 8 + 0);
11301                 wfex.nChannels = GST_READ_UINT16_LE (wfex_data + 8 + 2);
11302                 wfex.nSamplesPerSec = GST_READ_UINT32_LE (wfex_data + 8 + 4);
11303                 wfex.nAvgBytesPerSec = GST_READ_UINT32_LE (wfex_data + 8 + 8);
11304                 wfex.nBlockAlign = GST_READ_UINT16_LE (wfex_data + 8 + 12);
11305                 wfex.wBitsPerSample = GST_READ_UINT16_LE (wfex_data + 8 + 14);
11306                 wfex.cbSize = GST_READ_UINT16_LE (wfex_data + 8 + 16);
11307
11308                 GST_LOG_OBJECT (qtdemux, "Found wfex box in stsd:");
11309                 GST_LOG_OBJECT (qtdemux, "FormatTag = 0x%04x, Channels = %u, "
11310                     "SamplesPerSec = %u, AvgBytesPerSec = %u, BlockAlign = %u, "
11311                     "BitsPerSample = %u, Size = %u", wfex.wFormatTag,
11312                     wfex.nChannels, wfex.nSamplesPerSec, wfex.nAvgBytesPerSec,
11313                     wfex.nBlockAlign, wfex.wBitsPerSample, wfex.cbSize);
11314
11315                 if (wfex.wFormatTag == 0x0161) {
11316                   codec_name = "Windows Media Audio";
11317                   version = 2;
11318                 } else if (wfex.wFormatTag == 0x0162) {
11319                   codec_name = "Windows Media Audio 9 Pro";
11320                   version = 3;
11321                 } else if (wfex.wFormatTag == 0x0163) {
11322                   codec_name = "Windows Media Audio 9 Lossless";
11323                   /* is that correct? gstffmpegcodecmap.c is missing it, but
11324                    * fluendo codec seems to support it */
11325                   version = 4;
11326                 }
11327
11328                 gst_caps_set_simple (entry->caps,
11329                     "wmaversion", G_TYPE_INT, version,
11330                     "block_align", G_TYPE_INT, wfex.nBlockAlign,
11331                     "bitrate", G_TYPE_INT, wfex.nAvgBytesPerSec,
11332                     "width", G_TYPE_INT, wfex.wBitsPerSample,
11333                     "depth", G_TYPE_INT, wfex.wBitsPerSample, NULL);
11334
11335                 if (size > wfex.cbSize) {
11336                   GstBuffer *buf;
11337
11338                   buf = gst_buffer_new_and_alloc (size - wfex.cbSize);
11339                   gst_buffer_fill (buf, 0, wfex_data + 8 + wfex.cbSize,
11340                       size - wfex.cbSize);
11341                   gst_caps_set_simple (entry->caps,
11342                       "codec_data", GST_TYPE_BUFFER, buf, NULL);
11343                   gst_buffer_unref (buf);
11344                 } else {
11345                   GST_WARNING_OBJECT (qtdemux, "no codec data");
11346                 }
11347
11348                 if (codec_name) {
11349                   g_free (codec);
11350                   codec = g_strdup (codec_name);
11351                 }
11352                 break;
11353               }
11354               default:
11355                 break;
11356             }
11357             len -= size + 8;
11358             wfex_data += size + 8;
11359           }
11360           break;
11361         }
11362         case FOURCC_opus:
11363         {
11364           const guint8 *opus_data;
11365           guint8 *channel_mapping = NULL;
11366           guint32 rate;
11367           guint8 channels;
11368           guint8 channel_mapping_family;
11369           guint8 stream_count;
11370           guint8 coupled_count;
11371           guint8 i;
11372
11373           opus_data = stsd_entry_data;
11374
11375           channels = GST_READ_UINT8 (opus_data + 45);
11376           rate = GST_READ_UINT32_LE (opus_data + 48);
11377           channel_mapping_family = GST_READ_UINT8 (opus_data + 54);
11378           stream_count = GST_READ_UINT8 (opus_data + 55);
11379           coupled_count = GST_READ_UINT8 (opus_data + 56);
11380
11381           if (channels > 0) {
11382             channel_mapping = g_malloc (channels * sizeof (guint8));
11383             for (i = 0; i < channels; i++)
11384               channel_mapping[i] = GST_READ_UINT8 (opus_data + i + 57);
11385           }
11386
11387           entry->caps = gst_codec_utils_opus_create_caps (rate, channels,
11388               channel_mapping_family, stream_count, coupled_count,
11389               channel_mapping);
11390           break;
11391         }
11392         default:
11393           break;
11394       }
11395
11396       if (codec) {
11397         GstStructure *s;
11398         gint bitrate = 0;
11399
11400         gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
11401             GST_TAG_AUDIO_CODEC, codec, NULL);
11402         g_free (codec);
11403         codec = NULL;
11404
11405         /* some bitrate info may have ended up in caps */
11406         s = gst_caps_get_structure (entry->caps, 0);
11407         gst_structure_get_int (s, "bitrate", &bitrate);
11408         if (bitrate > 0)
11409           gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
11410               GST_TAG_BITRATE, bitrate, NULL);
11411       }
11412
11413       mp4a = qtdemux_tree_get_child_by_index (stsd, stsd_index);
11414       if (!stream->protected) {
11415       } else {
11416         if (QTDEMUX_TREE_NODE_FOURCC (mp4v) != FOURCC_encv) {
11417           mp4v = NULL;
11418         }
11419       }
11420       if (stream->protected && fourcc == FOURCC_mp4a) {
11421         if (QTDEMUX_TREE_NODE_FOURCC (mp4a) != FOURCC_enca) {
11422           mp4a = NULL;
11423         }
11424       } else {
11425         if (QTDEMUX_TREE_NODE_FOURCC (mp4a) != FOURCC_mp4a) {
11426           mp4a = NULL;
11427         }
11428       }
11429
11430       wave = NULL;
11431       esds = NULL;
11432       if (mp4a) {
11433         wave = qtdemux_tree_get_child_by_type (mp4a, FOURCC_wave);
11434         if (wave)
11435           esds = qtdemux_tree_get_child_by_type (wave, FOURCC_esds);
11436         if (!esds)
11437           esds = qtdemux_tree_get_child_by_type (mp4a, FOURCC_esds);
11438       }
11439
11440
11441       /* If the fourcc's bottom 16 bits gives 'sm', then the top
11442          16 bits is a byte-swapped wave-style codec identifier,
11443          and we can find a WAVE header internally to a 'wave' atom here.
11444          This can more clearly be thought of as 'ms' as the top 16 bits, and a
11445          codec id as the bottom 16 bits - but byte-swapped to store in QT (which
11446          is big-endian).
11447        */
11448       if ((fourcc & 0xffff) == (('s' << 8) | 'm')) {
11449         if (len < offset + 20) {
11450           GST_WARNING_OBJECT (qtdemux, "No wave atom in MS-style audio");
11451         } else {
11452           guint32 datalen = QT_UINT32 (stsd_entry_data + offset + 16);
11453           const guint8 *data = stsd_entry_data + offset + 16;
11454           GNode *wavenode;
11455           GNode *waveheadernode;
11456
11457           wavenode = g_node_new ((guint8 *) data);
11458           if (qtdemux_parse_node (qtdemux, wavenode, data, datalen)) {
11459             const guint8 *waveheader;
11460             guint32 headerlen;
11461
11462             waveheadernode = qtdemux_tree_get_child_by_type (wavenode, fourcc);
11463             if (waveheadernode) {
11464               waveheader = (const guint8 *) waveheadernode->data;
11465               headerlen = QT_UINT32 (waveheader);
11466
11467               if (headerlen > 8) {
11468                 gst_riff_strf_auds *header = NULL;
11469                 GstBuffer *headerbuf;
11470                 GstBuffer *extra;
11471
11472                 waveheader += 8;
11473                 headerlen -= 8;
11474
11475                 headerbuf = gst_buffer_new_and_alloc (headerlen);
11476                 gst_buffer_fill (headerbuf, 0, waveheader, headerlen);
11477
11478                 if (gst_riff_parse_strf_auds (GST_ELEMENT_CAST (qtdemux),
11479                         headerbuf, &header, &extra)) {
11480                   gst_caps_unref (entry->caps);
11481                   /* FIXME: Need to do something with the channel reorder map */
11482                   entry->caps =
11483                       gst_riff_create_audio_caps (header->format, NULL, header,
11484                       extra, NULL, NULL, NULL);
11485
11486                   if (extra)
11487                     gst_buffer_unref (extra);
11488                   g_free (header);
11489                 }
11490               }
11491             } else
11492               GST_DEBUG ("Didn't find waveheadernode for this codec");
11493           }
11494           g_node_destroy (wavenode);
11495         }
11496       } else if (esds) {
11497         gst_qtdemux_handle_esds (qtdemux, stream, entry, esds,
11498             stream->stream_tags);
11499       } else {
11500         switch (fourcc) {
11501 #if 0
11502             /* FIXME: what is in the chunk? */
11503           case FOURCC_QDMC:
11504           {
11505             gint len = QT_UINT32 (stsd_data);
11506
11507             /* seems to be always = 116 = 0x74 */
11508             break;
11509           }
11510 #endif
11511           case FOURCC_QDM2:
11512           {
11513             gint len = QT_UINT32 (stsd_entry_data);
11514
11515             if (len > 0x3C) {
11516               GstBuffer *buf = gst_buffer_new_and_alloc (len - 0x3C);
11517
11518               gst_buffer_fill (buf, 0, stsd_entry_data + 0x3C, len - 0x3C);
11519               gst_caps_set_simple (entry->caps,
11520                   "codec_data", GST_TYPE_BUFFER, buf, NULL);
11521               gst_buffer_unref (buf);
11522             }
11523             gst_caps_set_simple (entry->caps,
11524                 "samplesize", G_TYPE_INT, samplesize, NULL);
11525             break;
11526           }
11527           case FOURCC_alac:
11528           {
11529             GNode *alac, *wave = NULL;
11530
11531             /* apparently, m4a has this atom appended directly in the stsd entry,
11532              * while mov has it in a wave atom */
11533             alac = qtdemux_tree_get_child_by_type (stsd, FOURCC_alac);
11534             if (alac) {
11535               /* alac now refers to stsd entry atom */
11536               wave = qtdemux_tree_get_child_by_type (alac, FOURCC_wave);
11537               if (wave)
11538                 alac = qtdemux_tree_get_child_by_type (wave, FOURCC_alac);
11539               else
11540                 alac = qtdemux_tree_get_child_by_type (alac, FOURCC_alac);
11541             }
11542             if (alac) {
11543               const guint8 *alac_data = alac->data;
11544               gint len = QT_UINT32 (alac->data);
11545               GstBuffer *buf;
11546
11547               if (len < 36) {
11548                 GST_DEBUG_OBJECT (qtdemux,
11549                     "discarding alac atom with unexpected len %d", len);
11550               } else {
11551                 /* codec-data contains alac atom size and prefix,
11552                  * ffmpeg likes it that way, not quite gst-ish though ...*/
11553                 buf = gst_buffer_new_and_alloc (len);
11554                 gst_buffer_fill (buf, 0, alac->data, len);
11555                 gst_caps_set_simple (entry->caps,
11556                     "codec_data", GST_TYPE_BUFFER, buf, NULL);
11557                 gst_buffer_unref (buf);
11558
11559                 entry->bytes_per_frame = QT_UINT32 (alac_data + 12);
11560                 entry->n_channels = QT_UINT8 (alac_data + 21);
11561                 entry->rate = QT_UINT32 (alac_data + 32);
11562               }
11563             }
11564             gst_caps_set_simple (entry->caps,
11565                 "samplesize", G_TYPE_INT, samplesize, NULL);
11566             break;
11567           }
11568           case FOURCC_fLaC:
11569           {
11570             /* The codingname of the sample entry is 'fLaC' */
11571             GNode *flac = qtdemux_tree_get_child_by_type (stsd, FOURCC_fLaC);
11572
11573             if (flac) {
11574               /* The 'dfLa' box is added to the sample entry to convey
11575                  initializing information for the decoder. */
11576               const GNode *dfla =
11577                   qtdemux_tree_get_child_by_type (flac, FOURCC_dfLa);
11578
11579               if (dfla) {
11580                 const guint32 len = QT_UINT32 (dfla->data);
11581
11582                 /* Must contain at least dfLa box header (12),
11583                  * METADATA_BLOCK_HEADER (4), METADATA_BLOCK_STREAMINFO (34) */
11584                 if (len < 50) {
11585                   GST_DEBUG_OBJECT (qtdemux,
11586                       "discarding dfla atom with unexpected len %d", len);
11587                 } else {
11588                   /* skip dfLa header to get the METADATA_BLOCKs */
11589                   const guint8 *metadata_blocks = (guint8 *) dfla->data + 12;
11590                   const guint32 metadata_blocks_len = len - 12;
11591
11592                   gchar *stream_marker = g_strdup ("fLaC");
11593                   GstBuffer *block = gst_buffer_new_wrapped (stream_marker,
11594                       strlen (stream_marker));
11595
11596                   guint32 index = 0;
11597                   guint32 remainder = 0;
11598                   guint32 block_size = 0;
11599                   gboolean is_last = FALSE;
11600
11601                   GValue array = G_VALUE_INIT;
11602                   GValue value = G_VALUE_INIT;
11603
11604                   g_value_init (&array, GST_TYPE_ARRAY);
11605                   g_value_init (&value, GST_TYPE_BUFFER);
11606
11607                   gst_value_set_buffer (&value, block);
11608                   gst_value_array_append_value (&array, &value);
11609                   g_value_reset (&value);
11610
11611                   gst_buffer_unref (block);
11612
11613                   /* check there's at least one METADATA_BLOCK_HEADER's worth
11614                    * of data, and we haven't already finished parsing */
11615                   while (!is_last && ((index + 3) < metadata_blocks_len)) {
11616                     remainder = metadata_blocks_len - index;
11617
11618                     /* add the METADATA_BLOCK_HEADER size to the signalled size */
11619                     block_size = 4 +
11620                         (metadata_blocks[index + 1] << 16) +
11621                         (metadata_blocks[index + 2] << 8) +
11622                         metadata_blocks[index + 3];
11623
11624                     /* be careful not to read off end of box */
11625                     if (block_size > remainder) {
11626                       break;
11627                     }
11628
11629                     is_last = metadata_blocks[index] >> 7;
11630
11631                     block = gst_buffer_new_and_alloc (block_size);
11632
11633                     gst_buffer_fill (block, 0, &metadata_blocks[index],
11634                         block_size);
11635
11636                     gst_value_set_buffer (&value, block);
11637                     gst_value_array_append_value (&array, &value);
11638                     g_value_reset (&value);
11639
11640                     gst_buffer_unref (block);
11641
11642                     index += block_size;
11643                   }
11644
11645                   /* only append the metadata if we successfully read all of it */
11646                   if (is_last) {
11647                     gst_structure_set_value (gst_caps_get_structure (CUR_STREAM
11648                             (stream)->caps, 0), "streamheader", &array);
11649                   } else {
11650                     GST_WARNING_OBJECT (qtdemux,
11651                         "discarding all METADATA_BLOCKs due to invalid "
11652                         "block_size %d at idx %d, rem %d", block_size, index,
11653                         remainder);
11654                   }
11655
11656                   g_value_unset (&value);
11657                   g_value_unset (&array);
11658
11659                   /* The sample rate obtained from the stsd may not be accurate
11660                    * since it cannot represent rates greater than 65535Hz, so
11661                    * override that value with the sample rate from the
11662                    * METADATA_BLOCK_STREAMINFO block */
11663                   CUR_STREAM (stream)->rate =
11664                       (QT_UINT32 (metadata_blocks + 14) >> 12) & 0xFFFFF;
11665                 }
11666               }
11667             }
11668             break;
11669           }
11670           case FOURCC_sawb:
11671             /* Fallthrough! */
11672             amrwb = TRUE;
11673           case FOURCC_samr:
11674           {
11675             gint len = QT_UINT32 (stsd_entry_data);
11676
11677             if (len > 0x24) {
11678               GstBuffer *buf = gst_buffer_new_and_alloc (len - 0x24);
11679               guint bitrate;
11680
11681               gst_buffer_fill (buf, 0, stsd_entry_data + 0x24, len - 0x24);
11682
11683               /* If we have enough data, let's try to get the 'damr' atom. See
11684                * the 3GPP container spec (26.244) for more details. */
11685               if ((len - 0x34) > 8 &&
11686                   (bitrate = qtdemux_parse_amr_bitrate (buf, amrwb))) {
11687                 gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
11688                     GST_TAG_MAXIMUM_BITRATE, bitrate, NULL);
11689               }
11690
11691               gst_caps_set_simple (entry->caps,
11692                   "codec_data", GST_TYPE_BUFFER, buf, NULL);
11693               gst_buffer_unref (buf);
11694             }
11695             break;
11696           }
11697           case FOURCC_mp4a:
11698           {
11699             /* mp4a atom withtout ESDS; Attempt to build codec data from atom */
11700             gint len = QT_UINT32 (stsd_entry_data);
11701
11702             if (len >= 34) {
11703               guint16 sound_version = QT_UINT16 (stsd_entry_data + 16);
11704
11705               if (sound_version == 1) {
11706                 guint16 channels = QT_UINT16 (stsd_entry_data + 24);
11707                 guint32 time_scale = QT_UINT32 (stsd_entry_data + 30);
11708                 guint8 codec_data[2];
11709                 GstBuffer *buf;
11710                 gint profile = 2;       /* FIXME: Can this be determined somehow? There doesn't seem to be anything in mp4a atom that specifis compression */
11711
11712                 gint sample_rate_index =
11713                     gst_codec_utils_aac_get_index_from_sample_rate (time_scale);
11714
11715                 /* build AAC codec data */
11716                 codec_data[0] = profile << 3;
11717                 codec_data[0] |= ((sample_rate_index >> 1) & 0x7);
11718                 codec_data[1] = (sample_rate_index & 0x01) << 7;
11719                 codec_data[1] |= (channels & 0xF) << 3;
11720
11721                 buf = gst_buffer_new_and_alloc (2);
11722                 gst_buffer_fill (buf, 0, codec_data, 2);
11723                 gst_caps_set_simple (entry->caps,
11724                     "codec_data", GST_TYPE_BUFFER, buf, NULL);
11725                 gst_buffer_unref (buf);
11726               }
11727             }
11728             break;
11729           }
11730           case FOURCC_lpcm:
11731             /* Fully handled elsewhere */
11732             break;
11733           default:
11734             GST_INFO_OBJECT (qtdemux,
11735                 "unhandled type %" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (fourcc));
11736             break;
11737         }
11738       }
11739       GST_INFO_OBJECT (qtdemux,
11740           "type %" GST_FOURCC_FORMAT " caps %" GST_PTR_FORMAT,
11741           GST_FOURCC_ARGS (fourcc), entry->caps);
11742
11743     } else if (stream->subtype == FOURCC_strm) {
11744       if (fourcc == FOURCC_rtsp) {
11745         stream->redirect_uri = qtdemux_get_rtsp_uri_from_hndl (qtdemux, minf);
11746       } else {
11747         GST_INFO_OBJECT (qtdemux, "unhandled stream type %" GST_FOURCC_FORMAT,
11748             GST_FOURCC_ARGS (fourcc));
11749         goto unknown_stream;
11750       }
11751       entry->sampled = TRUE;
11752     } else if (stream->subtype == FOURCC_subp || stream->subtype == FOURCC_text
11753         || stream->subtype == FOURCC_sbtl || stream->subtype == FOURCC_subt
11754         || stream->subtype == FOURCC_clcp) {
11755
11756       entry->sampled = TRUE;
11757       entry->sparse = TRUE;
11758
11759       entry->caps =
11760           qtdemux_sub_caps (qtdemux, stream, entry, fourcc, stsd_entry_data,
11761           &codec);
11762       if (codec) {
11763         gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
11764             GST_TAG_SUBTITLE_CODEC, codec, NULL);
11765         g_free (codec);
11766         codec = NULL;
11767       }
11768
11769       /* hunt for sort-of codec data */
11770       switch (fourcc) {
11771         case FOURCC_mp4s:
11772         {
11773           GNode *mp4s = NULL;
11774           GNode *esds = NULL;
11775
11776           /* look for palette in a stsd->mp4s->esds sub-atom */
11777           mp4s = qtdemux_tree_get_child_by_type (stsd, FOURCC_mp4s);
11778           if (mp4s)
11779             esds = qtdemux_tree_get_child_by_type (mp4s, FOURCC_esds);
11780           if (esds == NULL) {
11781             /* Invalid STSD */
11782             GST_LOG_OBJECT (qtdemux, "Skipping invalid stsd: no esds child");
11783             break;
11784           }
11785
11786           gst_qtdemux_handle_esds (qtdemux, stream, entry, esds,
11787               stream->stream_tags);
11788           break;
11789         }
11790         default:
11791           GST_INFO_OBJECT (qtdemux,
11792               "unhandled type %" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (fourcc));
11793           break;
11794       }
11795       GST_INFO_OBJECT (qtdemux,
11796           "type %" GST_FOURCC_FORMAT " caps %" GST_PTR_FORMAT,
11797           GST_FOURCC_ARGS (fourcc), entry->caps);
11798     } else {
11799       /* everything in 1 sample */
11800       entry->sampled = TRUE;
11801
11802       entry->caps =
11803           qtdemux_generic_caps (qtdemux, stream, entry, fourcc, stsd_entry_data,
11804           &codec);
11805
11806       if (entry->caps == NULL)
11807         goto unknown_stream;
11808
11809       if (codec) {
11810         gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
11811             GST_TAG_SUBTITLE_CODEC, codec, NULL);
11812         g_free (codec);
11813         codec = NULL;
11814       }
11815     }
11816
11817     /* promote to sampled format */
11818     if (entry->fourcc == FOURCC_samr) {
11819       /* force mono 8000 Hz for AMR */
11820       entry->sampled = TRUE;
11821       entry->n_channels = 1;
11822       entry->rate = 8000;
11823     } else if (entry->fourcc == FOURCC_sawb) {
11824       /* force mono 16000 Hz for AMR-WB */
11825       entry->sampled = TRUE;
11826       entry->n_channels = 1;
11827       entry->rate = 16000;
11828     } else if (entry->fourcc == FOURCC_mp4a) {
11829       entry->sampled = TRUE;
11830     }
11831
11832
11833     stsd_entry_data += len;
11834     remaining_stsd_len -= len;
11835
11836   }
11837
11838   /* collect sample information */
11839   if (!qtdemux_stbl_init (qtdemux, stream, stbl))
11840     goto samples_failed;
11841
11842   if (qtdemux->fragmented) {
11843     guint64 offset;
11844
11845     /* need all moov samples as basis; probably not many if any at all */
11846     /* prevent moof parsing taking of at this time */
11847     offset = qtdemux->moof_offset;
11848     qtdemux->moof_offset = 0;
11849     if (stream->n_samples &&
11850         !qtdemux_parse_samples (qtdemux, stream, stream->n_samples - 1)) {
11851       qtdemux->moof_offset = offset;
11852       goto samples_failed;
11853     }
11854     qtdemux->moof_offset = 0;
11855     /* movie duration more reliable in this case (e.g. mehd) */
11856     if (qtdemux->segment.duration &&
11857         GST_CLOCK_TIME_IS_VALID (qtdemux->segment.duration))
11858       stream->duration =
11859           GSTTIME_TO_QTSTREAMTIME (stream, qtdemux->segment.duration);
11860   }
11861
11862   /* configure segments */
11863   if (!qtdemux_parse_segments (qtdemux, stream, trak))
11864     goto segments_failed;
11865
11866   /* add some language tag, if useful */
11867   if (stream->lang_id[0] != '\0' && strcmp (stream->lang_id, "unk") &&
11868       strcmp (stream->lang_id, "und")) {
11869     const gchar *lang_code;
11870
11871     /* convert ISO 639-2 code to ISO 639-1 */
11872     lang_code = gst_tag_get_language_code (stream->lang_id);
11873     gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
11874         GST_TAG_LANGUAGE_CODE, (lang_code) ? lang_code : stream->lang_id, NULL);
11875   }
11876
11877   /* Check for UDTA tags */
11878   if ((udta = qtdemux_tree_get_child_by_type (trak, FOURCC_udta))) {
11879     qtdemux_parse_udta (qtdemux, stream->stream_tags, udta);
11880   }
11881
11882   /* now we are ready to add the stream */
11883   if (!qtdemux->got_moov) {
11884     qtdemux->active_streams = g_list_append (qtdemux->active_streams, stream);
11885     qtdemux->n_streams++;
11886     GST_DEBUG_OBJECT (qtdemux, "n_streams is now %d", qtdemux->n_streams);
11887   }
11888
11889   return TRUE;
11890
11891 /* ERRORS */
11892 skip_track:
11893   {
11894     GST_INFO_OBJECT (qtdemux, "skip disabled track");
11895     if (new_stream)
11896       gst_qtdemux_stream_free (stream);
11897     return TRUE;
11898   }
11899 corrupt_file:
11900   {
11901     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
11902         (_("This file is corrupt and cannot be played.")), (NULL));
11903     if (new_stream)
11904       gst_qtdemux_stream_free (stream);
11905     return FALSE;
11906   }
11907 error_encrypted:
11908   {
11909     GST_ELEMENT_ERROR (qtdemux, STREAM, DECRYPT, (NULL), (NULL));
11910     if (new_stream)
11911       gst_qtdemux_stream_free (stream);
11912     return FALSE;
11913   }
11914 samples_failed:
11915 segments_failed:
11916   {
11917     /* we posted an error already */
11918     /* free stbl sub-atoms */
11919     gst_qtdemux_stbl_free (stream);
11920     if (new_stream)
11921       gst_qtdemux_stream_free (stream);
11922     return FALSE;
11923   }
11924 existing_stream:
11925   {
11926     GST_INFO_OBJECT (qtdemux, "stream with track id %i already exists",
11927         track_id);
11928     if (new_stream)
11929       gst_qtdemux_stream_free (stream);
11930     return TRUE;
11931   }
11932 unknown_stream:
11933   {
11934     GST_INFO_OBJECT (qtdemux, "unknown subtype %" GST_FOURCC_FORMAT,
11935         GST_FOURCC_ARGS (stream->subtype));
11936     if (new_stream)
11937       gst_qtdemux_stream_free (stream);
11938     return TRUE;
11939   }
11940 }
11941
11942 /* If we can estimate the overall bitrate, and don't have information about the
11943  * stream bitrate for exactly one stream, this guesses the stream bitrate as
11944  * the overall bitrate minus the sum of the bitrates of all other streams. This
11945  * should be useful for the common case where we have one audio and one video
11946  * stream and can estimate the bitrate of one, but not the other. */
11947 static void
11948 gst_qtdemux_guess_bitrate (GstQTDemux * qtdemux)
11949 {
11950   QtDemuxStream *stream = NULL;
11951   gint64 size, sys_bitrate, sum_bitrate = 0;
11952   GstClockTime duration;
11953   guint bitrate;
11954   GList *iter;
11955
11956   if (qtdemux->fragmented)
11957     return;
11958
11959   GST_DEBUG_OBJECT (qtdemux, "Looking for streams with unknown bitrate");
11960
11961   if (!gst_pad_peer_query_duration (qtdemux->sinkpad, GST_FORMAT_BYTES, &size)
11962       || size <= 0) {
11963     GST_DEBUG_OBJECT (qtdemux,
11964         "Size in bytes of the stream not known - bailing");
11965     return;
11966   }
11967
11968   /* Subtract the header size */
11969   GST_DEBUG_OBJECT (qtdemux, "Total size %" G_GINT64_FORMAT ", header size %u",
11970       size, qtdemux->header_size);
11971
11972   if (size < qtdemux->header_size)
11973     return;
11974
11975   size = size - qtdemux->header_size;
11976
11977   if (!gst_qtdemux_get_duration (qtdemux, &duration)) {
11978     GST_DEBUG_OBJECT (qtdemux, "Stream duration not known - bailing");
11979     return;
11980   }
11981
11982   for (iter = qtdemux->active_streams; iter; iter = g_list_next (iter)) {
11983     QtDemuxStream *str = QTDEMUX_STREAM (iter->data);
11984     switch (str->subtype) {
11985       case FOURCC_soun:
11986       case FOURCC_vide:
11987         GST_DEBUG_OBJECT (qtdemux, "checking bitrate for %" GST_PTR_FORMAT,
11988             CUR_STREAM (str)->caps);
11989         /* retrieve bitrate, prefer avg then max */
11990         bitrate = 0;
11991         if (str->stream_tags) {
11992           if (gst_tag_list_get_uint (str->stream_tags,
11993                   GST_TAG_MAXIMUM_BITRATE, &bitrate))
11994             GST_DEBUG_OBJECT (qtdemux, "max-bitrate: %u", bitrate);
11995           if (gst_tag_list_get_uint (str->stream_tags,
11996                   GST_TAG_NOMINAL_BITRATE, &bitrate))
11997             GST_DEBUG_OBJECT (qtdemux, "nominal-bitrate: %u", bitrate);
11998           if (gst_tag_list_get_uint (str->stream_tags,
11999                   GST_TAG_BITRATE, &bitrate))
12000             GST_DEBUG_OBJECT (qtdemux, "bitrate: %u", bitrate);
12001         }
12002         if (bitrate)
12003           sum_bitrate += bitrate;
12004         else {
12005           if (stream) {
12006             GST_DEBUG_OBJECT (qtdemux,
12007                 ">1 stream with unknown bitrate - bailing");
12008             return;
12009           } else
12010             stream = str;
12011         }
12012
12013       default:
12014         /* For other subtypes, we assume no significant impact on bitrate */
12015         break;
12016     }
12017   }
12018
12019   if (!stream) {
12020     GST_DEBUG_OBJECT (qtdemux, "All stream bitrates are known");
12021     return;
12022   }
12023
12024   sys_bitrate = gst_util_uint64_scale (size, GST_SECOND * 8, duration);
12025
12026   if (sys_bitrate < sum_bitrate) {
12027     /* This can happen, since sum_bitrate might be derived from maximum
12028      * bitrates and not average bitrates */
12029     GST_DEBUG_OBJECT (qtdemux,
12030         "System bitrate less than sum bitrate - bailing");
12031     return;
12032   }
12033
12034   bitrate = sys_bitrate - sum_bitrate;
12035   GST_DEBUG_OBJECT (qtdemux, "System bitrate = %" G_GINT64_FORMAT
12036       ", Stream bitrate = %u", sys_bitrate, bitrate);
12037
12038   if (!stream->stream_tags)
12039     stream->stream_tags = gst_tag_list_new_empty ();
12040   else
12041     stream->stream_tags = gst_tag_list_make_writable (stream->stream_tags);
12042
12043   gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
12044       GST_TAG_BITRATE, bitrate, NULL);
12045 }
12046
12047 static GstFlowReturn
12048 qtdemux_prepare_streams (GstQTDemux * qtdemux)
12049 {
12050   GstFlowReturn ret = GST_FLOW_OK;
12051   GList *iter, *next;
12052
12053   GST_DEBUG_OBJECT (qtdemux, "prepare streams");
12054
12055   for (iter = qtdemux->active_streams; ret == GST_FLOW_OK && iter; iter = next) {
12056     QtDemuxStream *stream = QTDEMUX_STREAM (iter->data);
12057     guint32 sample_num = 0;
12058
12059     next = iter->next;
12060
12061     GST_DEBUG_OBJECT (qtdemux, "track-id %u, fourcc %" GST_FOURCC_FORMAT,
12062         stream->track_id, GST_FOURCC_ARGS (CUR_STREAM (stream)->fourcc));
12063
12064     if (qtdemux->fragmented) {
12065       /* need all moov samples first */
12066       GST_OBJECT_LOCK (qtdemux);
12067       while (stream->n_samples == 0)
12068         if ((ret = qtdemux_add_fragmented_samples (qtdemux)) != GST_FLOW_OK)
12069           break;
12070       GST_OBJECT_UNLOCK (qtdemux);
12071     } else {
12072       /* discard any stray moof */
12073       qtdemux->moof_offset = 0;
12074     }
12075
12076     /* prepare braking */
12077     if (ret != GST_FLOW_ERROR)
12078       ret = GST_FLOW_OK;
12079
12080     /* in pull mode, we should have parsed some sample info by now;
12081      * and quite some code will not handle no samples.
12082      * in push mode, we'll just have to deal with it */
12083     if (G_UNLIKELY (qtdemux->pullbased && !stream->n_samples)) {
12084       GST_DEBUG_OBJECT (qtdemux, "no samples for stream; discarding");
12085       gst_qtdemux_remove_stream (qtdemux, stream);
12086       continue;
12087     }
12088
12089     /* parse the initial sample for use in setting the frame rate cap */
12090     while (sample_num == 0 && sample_num < stream->n_samples) {
12091       if (!qtdemux_parse_samples (qtdemux, stream, sample_num))
12092         break;
12093       ++sample_num;
12094     }
12095     if (stream->n_samples > 0 && stream->stbl_index >= 0) {
12096       stream->first_duration = stream->samples[0].duration;
12097       GST_LOG_OBJECT (qtdemux, "track-id %u first duration %u",
12098           stream->track_id, stream->first_duration);
12099     }
12100   }
12101
12102   return ret;
12103 }
12104
12105 static GstFlowReturn
12106 qtdemux_expose_streams (GstQTDemux * qtdemux)
12107 {
12108   GSList *oldpads = NULL;
12109   GSList *iter;
12110   GList *walk, *next;
12111
12112   GST_DEBUG_OBJECT (qtdemux, "exposing streams");
12113
12114   for (walk = qtdemux->active_streams; walk; walk = next) {
12115     QtDemuxStream *stream = QTDEMUX_STREAM (walk->data);
12116     GstPad *oldpad = stream->pad;
12117     GstTagList *list;
12118
12119     next = walk->next;
12120
12121     GST_DEBUG_OBJECT (qtdemux, "track-id %u, fourcc %" GST_FOURCC_FORMAT,
12122         stream->track_id, GST_FOURCC_ARGS (CUR_STREAM (stream)->fourcc));
12123
12124     if ((stream->subtype == FOURCC_text || stream->subtype == FOURCC_sbtl) &&
12125         stream->track_id == qtdemux->chapters_track_id) {
12126       /* TODO - parse chapters track and expose it as GstToc; For now just ignore it
12127          so that it doesn't look like a subtitle track */
12128       gst_qtdemux_remove_stream (qtdemux, stream);
12129       continue;
12130     }
12131
12132     /* now we have all info and can expose */
12133     list = stream->stream_tags;
12134     stream->stream_tags = NULL;
12135     if (oldpad)
12136       oldpads = g_slist_prepend (oldpads, oldpad);
12137     if (!gst_qtdemux_add_stream (qtdemux, stream, list))
12138       return GST_FLOW_ERROR;
12139   }
12140
12141   gst_qtdemux_guess_bitrate (qtdemux);
12142
12143   gst_element_no_more_pads (GST_ELEMENT_CAST (qtdemux));
12144
12145   for (iter = oldpads; iter; iter = g_slist_next (iter)) {
12146     GstPad *oldpad = iter->data;
12147     GstEvent *event;
12148
12149     event = gst_event_new_eos ();
12150     if (qtdemux->segment_seqnum != GST_SEQNUM_INVALID)
12151       gst_event_set_seqnum (event, qtdemux->segment_seqnum);
12152
12153     gst_pad_push_event (oldpad, event);
12154     gst_pad_set_active (oldpad, FALSE);
12155     gst_element_remove_pad (GST_ELEMENT (qtdemux), oldpad);
12156     gst_flow_combiner_remove_pad (qtdemux->flowcombiner, oldpad);
12157     gst_object_unref (oldpad);
12158   }
12159
12160   /* check if we should post a redirect in case there is a single trak
12161    * and it is a redirecting trak */
12162   if (qtdemux->n_streams == 1 &&
12163       QTDEMUX_FIRST_STREAM (qtdemux)->redirect_uri != NULL) {
12164     GstMessage *m;
12165
12166     GST_INFO_OBJECT (qtdemux, "Issuing a redirect due to a single track with "
12167         "an external content");
12168     m = gst_message_new_element (GST_OBJECT_CAST (qtdemux),
12169         gst_structure_new ("redirect",
12170             "new-location", G_TYPE_STRING,
12171             QTDEMUX_FIRST_STREAM (qtdemux)->redirect_uri, NULL));
12172     gst_element_post_message (GST_ELEMENT_CAST (qtdemux), m);
12173     qtdemux->posted_redirect = TRUE;
12174   }
12175
12176   for (walk = qtdemux->active_streams; walk; walk = g_list_next (walk)) {
12177     qtdemux_do_allocation (qtdemux, QTDEMUX_STREAM (walk->data));
12178   }
12179
12180   qtdemux->exposed = TRUE;
12181   return GST_FLOW_OK;
12182 }
12183
12184 /* check if major or compatible brand is 3GP */
12185 static inline gboolean
12186 qtdemux_is_brand_3gp (GstQTDemux * qtdemux, gboolean major)
12187 {
12188   if (major) {
12189     return ((qtdemux->major_brand & GST_MAKE_FOURCC (255, 255, 0, 0)) ==
12190         FOURCC_3g__);
12191   } else if (qtdemux->comp_brands != NULL) {
12192     GstMapInfo map;
12193     guint8 *data;
12194     gsize size;
12195     gboolean res = FALSE;
12196
12197     gst_buffer_map (qtdemux->comp_brands, &map, GST_MAP_READ);
12198     data = map.data;
12199     size = map.size;
12200     while (size >= 4) {
12201       res = res || ((QT_FOURCC (data) & GST_MAKE_FOURCC (255, 255, 0, 0)) ==
12202           FOURCC_3g__);
12203       data += 4;
12204       size -= 4;
12205     }
12206     gst_buffer_unmap (qtdemux->comp_brands, &map);
12207     return res;
12208   } else {
12209     return FALSE;
12210   }
12211 }
12212
12213 /* check if tag is a spec'ed 3GP tag keyword storing a string */
12214 static inline gboolean
12215 qtdemux_is_string_tag_3gp (GstQTDemux * qtdemux, guint32 fourcc)
12216 {
12217   return fourcc == FOURCC_cprt || fourcc == FOURCC_gnre || fourcc == FOURCC_titl
12218       || fourcc == FOURCC_dscp || fourcc == FOURCC_perf || fourcc == FOURCC_auth
12219       || fourcc == FOURCC_albm;
12220 }
12221
12222 static void
12223 qtdemux_tag_add_location (GstQTDemux * qtdemux, GstTagList * taglist,
12224     const char *tag, const char *dummy, GNode * node)
12225 {
12226   const gchar *env_vars[] = { "GST_QT_TAG_ENCODING", "GST_TAG_ENCODING", NULL };
12227   int offset;
12228   char *name;
12229   gchar *data;
12230   gdouble longitude, latitude, altitude;
12231   gint len;
12232
12233   len = QT_UINT32 (node->data);
12234   if (len <= 14)
12235     goto short_read;
12236
12237   data = node->data;
12238   offset = 14;
12239
12240   /* TODO: language code skipped */
12241
12242   name = gst_tag_freeform_string_to_utf8 (data + offset, -1, env_vars);
12243
12244   if (!name) {
12245     /* do not alarm in trivial case, but bail out otherwise */
12246     if (*(data + offset) != 0) {
12247       GST_DEBUG_OBJECT (qtdemux, "failed to convert %s tag to UTF-8, "
12248           "giving up", tag);
12249     }
12250   } else {
12251     gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE,
12252         GST_TAG_GEO_LOCATION_NAME, name, NULL);
12253     offset += strlen (name);
12254     g_free (name);
12255   }
12256
12257   if (len < offset + 2 + 4 + 4 + 4)
12258     goto short_read;
12259
12260   /* +1 +1 = skip null-terminator and location role byte */
12261   offset += 1 + 1;
12262   /* table in spec says unsigned, semantics say negative has meaning ... */
12263   longitude = QT_SFP32 (data + offset);
12264
12265   offset += 4;
12266   latitude = QT_SFP32 (data + offset);
12267
12268   offset += 4;
12269   altitude = QT_SFP32 (data + offset);
12270
12271   /* one invalid means all are invalid */
12272   if (longitude >= -180.0 && longitude <= 180.0 &&
12273       latitude >= -90.0 && latitude <= 90.0) {
12274     gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE,
12275         GST_TAG_GEO_LOCATION_LATITUDE, latitude,
12276         GST_TAG_GEO_LOCATION_LONGITUDE, longitude,
12277         GST_TAG_GEO_LOCATION_ELEVATION, altitude, NULL);
12278   }
12279
12280   /* TODO: no GST_TAG_, so astronomical body and additional notes skipped */
12281
12282   return;
12283
12284   /* ERRORS */
12285 short_read:
12286   {
12287     GST_DEBUG_OBJECT (qtdemux, "short read parsing 3GP location");
12288     return;
12289   }
12290 }
12291
12292
12293 static void
12294 qtdemux_tag_add_year (GstQTDemux * qtdemux, GstTagList * taglist,
12295     const char *tag, const char *dummy, GNode * node)
12296 {
12297   guint16 y;
12298   GDate *date;
12299   gint len;
12300
12301   len = QT_UINT32 (node->data);
12302   if (len < 14)
12303     return;
12304
12305   y = QT_UINT16 ((guint8 *) node->data + 12);
12306   if (y == 0) {
12307     GST_DEBUG_OBJECT (qtdemux, "year: %u is not a valid year", y);
12308     return;
12309   }
12310   GST_DEBUG_OBJECT (qtdemux, "year: %u", y);
12311
12312   date = g_date_new_dmy (1, 1, y);
12313   gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag, date, NULL);
12314   g_date_free (date);
12315 }
12316
12317 static void
12318 qtdemux_tag_add_classification (GstQTDemux * qtdemux, GstTagList * taglist,
12319     const char *tag, const char *dummy, GNode * node)
12320 {
12321   int offset;
12322   char *tag_str = NULL;
12323   guint8 *entity;
12324   guint16 table;
12325   gint len;
12326
12327   len = QT_UINT32 (node->data);
12328   if (len <= 20)
12329     goto short_read;
12330
12331   offset = 12;
12332   entity = (guint8 *) node->data + offset;
12333   if (entity[0] == 0 || entity[1] == 0 || entity[2] == 0 || entity[3] == 0) {
12334     GST_DEBUG_OBJECT (qtdemux,
12335         "classification info: %c%c%c%c invalid classification entity",
12336         entity[0], entity[1], entity[2], entity[3]);
12337     return;
12338   }
12339
12340   offset += 4;
12341   table = QT_UINT16 ((guint8 *) node->data + offset);
12342
12343   /* Language code skipped */
12344
12345   offset += 4;
12346
12347   /* Tag format: "XXXX://Y[YYYY]/classification info string"
12348    * XXXX: classification entity, fixed length 4 chars.
12349    * Y[YYYY]: classification table, max 5 chars.
12350    */
12351   tag_str = g_strdup_printf ("----://%u/%s",
12352       table, (char *) node->data + offset);
12353
12354   /* memcpy To be sure we're preserving byte order */
12355   memcpy (tag_str, entity, 4);
12356   GST_DEBUG_OBJECT (qtdemux, "classification info: %s", tag_str);
12357
12358   gst_tag_list_add (taglist, GST_TAG_MERGE_APPEND, tag, tag_str, NULL);
12359
12360   g_free (tag_str);
12361
12362   return;
12363
12364   /* ERRORS */
12365 short_read:
12366   {
12367     GST_DEBUG_OBJECT (qtdemux, "short read parsing 3GP classification");
12368     return;
12369   }
12370 }
12371
12372 static gboolean
12373 qtdemux_tag_add_str_full (GstQTDemux * qtdemux, GstTagList * taglist,
12374     const char *tag, const char *dummy, GNode * node)
12375 {
12376   const gchar *env_vars[] = { "GST_QT_TAG_ENCODING", "GST_TAG_ENCODING", NULL };
12377   GNode *data;
12378   char *s;
12379   int len;
12380   guint32 type;
12381   int offset;
12382   gboolean ret = TRUE;
12383   const gchar *charset = NULL;
12384
12385   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
12386   if (data) {
12387     len = QT_UINT32 (data->data);
12388     type = QT_UINT32 ((guint8 *) data->data + 8);
12389     if (type == 0x00000001 && len > 16) {
12390       s = gst_tag_freeform_string_to_utf8 ((char *) data->data + 16, len - 16,
12391           env_vars);
12392       if (s) {
12393         GST_DEBUG_OBJECT (qtdemux, "adding tag %s", GST_STR_NULL (s));
12394         gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag, s, NULL);
12395         g_free (s);
12396       } else {
12397         GST_DEBUG_OBJECT (qtdemux, "failed to convert %s tag to UTF-8", tag);
12398       }
12399     }
12400   } else {
12401     len = QT_UINT32 (node->data);
12402     type = QT_UINT32 ((guint8 *) node->data + 4);
12403     if ((type >> 24) == 0xa9 && len > 8 + 4) {
12404       gint str_len;
12405       gint lang_code;
12406
12407       /* Type starts with the (C) symbol, so the next data is a list
12408        * of (string size(16), language code(16), string) */
12409
12410       str_len = QT_UINT16 ((guint8 *) node->data + 8);
12411       lang_code = QT_UINT16 ((guint8 *) node->data + 10);
12412
12413       /* the string + fourcc + size + 2 16bit fields,
12414        * means that there are more tags in this atom */
12415       if (len > str_len + 8 + 4) {
12416         /* TODO how to represent the same tag in different languages? */
12417         GST_WARNING_OBJECT (qtdemux, "Ignoring metadata entry with multiple "
12418             "text alternatives, reading only first one");
12419       }
12420
12421       offset = 12;
12422       len = MIN (len, str_len + 8 + 4); /* remove trailing strings that we don't use */
12423       GST_DEBUG_OBJECT (qtdemux, "found international text tag");
12424
12425       if (lang_code < 0x800) {  /* MAC encoded string */
12426         charset = "mac";
12427       }
12428     } else if (len > 14 && qtdemux_is_string_tag_3gp (qtdemux,
12429             QT_FOURCC ((guint8 *) node->data + 4))) {
12430       guint32 type = QT_UINT32 ((guint8 *) node->data + 8);
12431
12432       /* we go for 3GP style encoding if major brands claims so,
12433        * or if no hope for data be ok UTF-8, and compatible 3GP brand present */
12434       if (qtdemux_is_brand_3gp (qtdemux, TRUE) ||
12435           (qtdemux_is_brand_3gp (qtdemux, FALSE) &&
12436               ((type & 0x00FFFFFF) == 0x0) && (type >> 24 <= 0xF))) {
12437         offset = 14;
12438         /* 16-bit Language code is ignored here as well */
12439         GST_DEBUG_OBJECT (qtdemux, "found 3gpp text tag");
12440       } else {
12441         goto normal;
12442       }
12443     } else {
12444     normal:
12445       offset = 8;
12446       GST_DEBUG_OBJECT (qtdemux, "found normal text tag");
12447       ret = FALSE;              /* may have to fallback */
12448     }
12449     if (charset) {
12450       GError *err = NULL;
12451
12452       s = g_convert ((gchar *) node->data + offset, len - offset, "utf8",
12453           charset, NULL, NULL, &err);
12454       if (err) {
12455         GST_DEBUG_OBJECT (qtdemux, "Failed to convert string from charset %s:"
12456             " %s(%d): %s", charset, g_quark_to_string (err->domain), err->code,
12457             err->message);
12458         g_error_free (err);
12459       }
12460     } else {
12461       s = gst_tag_freeform_string_to_utf8 ((char *) node->data + offset,
12462           len - offset, env_vars);
12463     }
12464     if (s) {
12465       GST_DEBUG_OBJECT (qtdemux, "adding tag %s", GST_STR_NULL (s));
12466       gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag, s, NULL);
12467       g_free (s);
12468       ret = TRUE;
12469     } else {
12470       GST_DEBUG_OBJECT (qtdemux, "failed to convert %s tag to UTF-8", tag);
12471     }
12472   }
12473   return ret;
12474 }
12475
12476 static void
12477 qtdemux_tag_add_str (GstQTDemux * qtdemux, GstTagList * taglist,
12478     const char *tag, const char *dummy, GNode * node)
12479 {
12480   qtdemux_tag_add_str_full (qtdemux, taglist, tag, dummy, node);
12481 }
12482
12483 static void
12484 qtdemux_tag_add_keywords (GstQTDemux * qtdemux, GstTagList * taglist,
12485     const char *tag, const char *dummy, GNode * node)
12486 {
12487   const gchar *env_vars[] = { "GST_QT_TAG_ENCODING", "GST_TAG_ENCODING", NULL };
12488   guint8 *data;
12489   char *s, *t, *k = NULL;
12490   int len;
12491   int offset;
12492   int count;
12493
12494   /* first try normal string tag if major brand not 3GP */
12495   if (!qtdemux_is_brand_3gp (qtdemux, TRUE)) {
12496     if (!qtdemux_tag_add_str_full (qtdemux, taglist, tag, dummy, node)) {
12497       /* hm, that did not work, maybe 3gpp storage in non-3gpp major brand;
12498        * let's try it 3gpp way after minor safety check */
12499       data = node->data;
12500       if (QT_UINT32 (data) < 15 || !qtdemux_is_brand_3gp (qtdemux, FALSE))
12501         return;
12502     } else
12503       return;
12504   }
12505
12506   GST_DEBUG_OBJECT (qtdemux, "found 3gpp keyword tag");
12507
12508   data = node->data;
12509
12510   len = QT_UINT32 (data);
12511   if (len < 15)
12512     goto short_read;
12513
12514   count = QT_UINT8 (data + 14);
12515   offset = 15;
12516   for (; count; count--) {
12517     gint slen;
12518
12519     if (offset + 1 > len)
12520       goto short_read;
12521     slen = QT_UINT8 (data + offset);
12522     offset += 1;
12523     if (offset + slen > len)
12524       goto short_read;
12525     s = gst_tag_freeform_string_to_utf8 ((char *) node->data + offset,
12526         slen, env_vars);
12527     if (s) {
12528       GST_DEBUG_OBJECT (qtdemux, "adding keyword %s", GST_STR_NULL (s));
12529       if (k) {
12530         t = g_strjoin (",", k, s, NULL);
12531         g_free (s);
12532         g_free (k);
12533         k = t;
12534       } else {
12535         k = s;
12536       }
12537     } else {
12538       GST_DEBUG_OBJECT (qtdemux, "failed to convert keyword to UTF-8");
12539     }
12540     offset += slen;
12541   }
12542
12543 done:
12544   if (k) {
12545     GST_DEBUG_OBJECT (qtdemux, "adding tag %s", GST_STR_NULL (k));
12546     gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag, k, NULL);
12547   }
12548   g_free (k);
12549
12550   return;
12551
12552   /* ERRORS */
12553 short_read:
12554   {
12555     GST_DEBUG_OBJECT (qtdemux, "short read parsing 3GP keywords");
12556     goto done;
12557   }
12558 }
12559
12560 static void
12561 qtdemux_tag_add_num (GstQTDemux * qtdemux, GstTagList * taglist,
12562     const char *tag1, const char *tag2, GNode * node)
12563 {
12564   GNode *data;
12565   int len;
12566   int type;
12567   int n1, n2;
12568
12569   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
12570   if (data) {
12571     len = QT_UINT32 (data->data);
12572     type = QT_UINT32 ((guint8 *) data->data + 8);
12573     if (type == 0x00000000 && len >= 22) {
12574       n1 = QT_UINT16 ((guint8 *) data->data + 18);
12575       n2 = QT_UINT16 ((guint8 *) data->data + 20);
12576       if (n1 > 0) {
12577         GST_DEBUG_OBJECT (qtdemux, "adding tag %s=%d", tag1, n1);
12578         gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag1, n1, NULL);
12579       }
12580       if (n2 > 0) {
12581         GST_DEBUG_OBJECT (qtdemux, "adding tag %s=%d", tag2, n2);
12582         gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag2, n2, NULL);
12583       }
12584     }
12585   }
12586 }
12587
12588 static void
12589 qtdemux_tag_add_tmpo (GstQTDemux * qtdemux, GstTagList * taglist,
12590     const char *tag1, const char *dummy, GNode * node)
12591 {
12592   GNode *data;
12593   int len;
12594   int type;
12595   int n1;
12596
12597   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
12598   if (data) {
12599     len = QT_UINT32 (data->data);
12600     type = QT_UINT32 ((guint8 *) data->data + 8);
12601     GST_DEBUG_OBJECT (qtdemux, "have tempo tag, type=%d,len=%d", type, len);
12602     /* some files wrongly have a type 0x0f=15, but it should be 0x15 */
12603     if ((type == 0x00000015 || type == 0x0000000f) && len >= 18) {
12604       n1 = QT_UINT16 ((guint8 *) data->data + 16);
12605       if (n1) {
12606         /* do not add bpm=0 */
12607         GST_DEBUG_OBJECT (qtdemux, "adding tag %d", n1);
12608         gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag1, (gdouble) n1,
12609             NULL);
12610       }
12611     }
12612   }
12613 }
12614
12615 static void
12616 qtdemux_tag_add_uint32 (GstQTDemux * qtdemux, GstTagList * taglist,
12617     const char *tag1, const char *dummy, GNode * node)
12618 {
12619   GNode *data;
12620   int len;
12621   int type;
12622   guint32 num;
12623
12624   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
12625   if (data) {
12626     len = QT_UINT32 (data->data);
12627     type = QT_UINT32 ((guint8 *) data->data + 8);
12628     GST_DEBUG_OBJECT (qtdemux, "have %s tag, type=%d,len=%d", tag1, type, len);
12629     /* some files wrongly have a type 0x0f=15, but it should be 0x15 */
12630     if ((type == 0x00000015 || type == 0x0000000f) && len >= 20) {
12631       num = QT_UINT32 ((guint8 *) data->data + 16);
12632       if (num) {
12633         /* do not add num=0 */
12634         GST_DEBUG_OBJECT (qtdemux, "adding tag %d", num);
12635         gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag1, num, NULL);
12636       }
12637     }
12638   }
12639 }
12640
12641 static void
12642 qtdemux_tag_add_covr (GstQTDemux * qtdemux, GstTagList * taglist,
12643     const char *tag1, const char *dummy, GNode * node)
12644 {
12645   GNode *data;
12646   int len;
12647   int type;
12648   GstSample *sample;
12649
12650   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
12651   if (data) {
12652     len = QT_UINT32 (data->data);
12653     type = QT_UINT32 ((guint8 *) data->data + 8);
12654     GST_DEBUG_OBJECT (qtdemux, "have covr tag, type=%d,len=%d", type, len);
12655     if ((type == 0x0000000d || type == 0x0000000e) && len > 16) {
12656       GstTagImageType image_type;
12657
12658       if (gst_tag_list_get_tag_size (taglist, GST_TAG_IMAGE) == 0)
12659         image_type = GST_TAG_IMAGE_TYPE_FRONT_COVER;
12660       else
12661         image_type = GST_TAG_IMAGE_TYPE_NONE;
12662
12663       if ((sample =
12664               gst_tag_image_data_to_image_sample ((guint8 *) data->data + 16,
12665                   len - 16, image_type))) {
12666         GST_DEBUG_OBJECT (qtdemux, "adding tag size %d", len - 16);
12667         gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag1, sample, NULL);
12668         gst_sample_unref (sample);
12669       }
12670     }
12671   }
12672 }
12673
12674 static void
12675 qtdemux_tag_add_date (GstQTDemux * qtdemux, GstTagList * taglist,
12676     const char *tag, const char *dummy, GNode * node)
12677 {
12678   GNode *data;
12679   GstDateTime *datetime = NULL;
12680   char *s;
12681   int len;
12682   int type;
12683
12684   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
12685   if (data) {
12686     len = QT_UINT32 (data->data);
12687     type = QT_UINT32 ((guint8 *) data->data + 8);
12688     if (type == 0x00000001 && len > 16) {
12689       guint y, m = 1, d = 1;
12690       gint ret;
12691
12692       s = g_strndup ((char *) data->data + 16, len - 16);
12693       GST_DEBUG_OBJECT (qtdemux, "adding date '%s'", s);
12694       datetime = gst_date_time_new_from_iso8601_string (s);
12695       if (datetime != NULL) {
12696         gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, GST_TAG_DATE_TIME,
12697             datetime, NULL);
12698         gst_date_time_unref (datetime);
12699       }
12700
12701       ret = sscanf (s, "%u-%u-%u", &y, &m, &d);
12702       if (ret >= 1 && y > 1500 && y < 3000) {
12703         GDate *date;
12704
12705         date = g_date_new_dmy (d, m, y);
12706         gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag, date, NULL);
12707         g_date_free (date);
12708       } else {
12709         GST_DEBUG_OBJECT (qtdemux, "could not parse date string '%s'", s);
12710       }
12711       g_free (s);
12712     }
12713   }
12714 }
12715
12716 static void
12717 qtdemux_tag_add_gnre (GstQTDemux * qtdemux, GstTagList * taglist,
12718     const char *tag, const char *dummy, GNode * node)
12719 {
12720   GNode *data;
12721
12722   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
12723
12724   /* re-route to normal string tag if major brand says so
12725    * or no data atom and compatible brand suggests so */
12726   if (qtdemux_is_brand_3gp (qtdemux, TRUE) ||
12727       (qtdemux_is_brand_3gp (qtdemux, FALSE) && !data)) {
12728     qtdemux_tag_add_str (qtdemux, taglist, tag, dummy, node);
12729     return;
12730   }
12731
12732   if (data) {
12733     guint len, type, n;
12734
12735     len = QT_UINT32 (data->data);
12736     type = QT_UINT32 ((guint8 *) data->data + 8);
12737     if (type == 0x00000000 && len >= 18) {
12738       n = QT_UINT16 ((guint8 *) data->data + 16);
12739       if (n > 0) {
12740         const gchar *genre;
12741
12742         genre = gst_tag_id3_genre_get (n - 1);
12743         if (genre != NULL) {
12744           GST_DEBUG_OBJECT (qtdemux, "adding %d [%s]", n, genre);
12745           gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag, genre, NULL);
12746         }
12747       }
12748     }
12749   }
12750 }
12751
12752 static void
12753 qtdemux_add_double_tag_from_str (GstQTDemux * demux, GstTagList * taglist,
12754     const gchar * tag, guint8 * data, guint32 datasize)
12755 {
12756   gdouble value;
12757   gchar *datacopy;
12758
12759   /* make a copy to have \0 at the end */
12760   datacopy = g_strndup ((gchar *) data, datasize);
12761
12762   /* convert the str to double */
12763   if (sscanf (datacopy, "%lf", &value) == 1) {
12764     GST_DEBUG_OBJECT (demux, "adding tag: %s [%s]", tag, datacopy);
12765     gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag, value, NULL);
12766   } else {
12767     GST_WARNING_OBJECT (demux, "Failed to parse double from string: %s",
12768         datacopy);
12769   }
12770   g_free (datacopy);
12771 }
12772
12773
12774 static void
12775 qtdemux_tag_add_revdns (GstQTDemux * demux, GstTagList * taglist,
12776     const char *tag, const char *tag_bis, GNode * node)
12777 {
12778   GNode *mean;
12779   GNode *name;
12780   GNode *data;
12781   guint32 meansize;
12782   guint32 namesize;
12783   guint32 datatype;
12784   guint32 datasize;
12785   const gchar *meanstr;
12786   const gchar *namestr;
12787
12788   /* checking the whole ---- atom size for consistency */
12789   if (QT_UINT32 (node->data) <= 4 + 12 + 12 + 16) {
12790     GST_WARNING_OBJECT (demux, "Tag ---- atom is too small, ignoring");
12791     return;
12792   }
12793
12794   mean = qtdemux_tree_get_child_by_type (node, FOURCC_mean);
12795   if (!mean) {
12796     GST_WARNING_OBJECT (demux, "No 'mean' atom found");
12797     return;
12798   }
12799
12800   meansize = QT_UINT32 (mean->data);
12801   if (meansize <= 12) {
12802     GST_WARNING_OBJECT (demux, "Small mean atom, ignoring the whole tag");
12803     return;
12804   }
12805   meanstr = ((gchar *) mean->data) + 12;
12806   meansize -= 12;
12807
12808   name = qtdemux_tree_get_child_by_type (node, FOURCC_name);
12809   if (!name) {
12810     GST_WARNING_OBJECT (demux, "'name' atom not found, ignoring tag");
12811     return;
12812   }
12813
12814   namesize = QT_UINT32 (name->data);
12815   if (namesize <= 12) {
12816     GST_WARNING_OBJECT (demux, "'name' atom is too small, ignoring tag");
12817     return;
12818   }
12819   namestr = ((gchar *) name->data) + 12;
12820   namesize -= 12;
12821
12822   /*
12823    * Data atom is:
12824    * uint32 - size
12825    * uint32 - name
12826    * uint8  - version
12827    * uint24 - data type
12828    * uint32 - all 0
12829    * rest   - the data
12830    */
12831   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
12832   if (!data) {
12833     GST_WARNING_OBJECT (demux, "No data atom in this tag");
12834     return;
12835   }
12836   datasize = QT_UINT32 (data->data);
12837   if (datasize <= 16) {
12838     GST_WARNING_OBJECT (demux, "Data atom too small");
12839     return;
12840   }
12841   datatype = QT_UINT32 (((gchar *) data->data) + 8) & 0xFFFFFF;
12842
12843   if ((strncmp (meanstr, "com.apple.iTunes", meansize) == 0) ||
12844       (strncmp (meanstr, "org.hydrogenaudio.replaygain", meansize) == 0)) {
12845     static const struct
12846     {
12847       const gchar name[28];
12848       const gchar tag[28];
12849     } tags[] = {
12850       {
12851       "replaygain_track_gain", GST_TAG_TRACK_GAIN}, {
12852       "replaygain_track_peak", GST_TAG_TRACK_PEAK}, {
12853       "replaygain_album_gain", GST_TAG_ALBUM_GAIN}, {
12854       "replaygain_album_peak", GST_TAG_ALBUM_PEAK}, {
12855       "MusicBrainz Track Id", GST_TAG_MUSICBRAINZ_TRACKID}, {
12856       "MusicBrainz Artist Id", GST_TAG_MUSICBRAINZ_ARTISTID}, {
12857       "MusicBrainz Album Id", GST_TAG_MUSICBRAINZ_ALBUMID}, {
12858       "MusicBrainz Album Artist Id", GST_TAG_MUSICBRAINZ_ALBUMARTISTID}
12859     };
12860     int i;
12861
12862     for (i = 0; i < G_N_ELEMENTS (tags); ++i) {
12863       if (!g_ascii_strncasecmp (tags[i].name, namestr, namesize)) {
12864         switch (gst_tag_get_type (tags[i].tag)) {
12865           case G_TYPE_DOUBLE:
12866             qtdemux_add_double_tag_from_str (demux, taglist, tags[i].tag,
12867                 ((guint8 *) data->data) + 16, datasize - 16);
12868             break;
12869           case G_TYPE_STRING:
12870             qtdemux_tag_add_str (demux, taglist, tags[i].tag, NULL, node);
12871             break;
12872           default:
12873             /* not reached */
12874             break;
12875         }
12876         break;
12877       }
12878     }
12879     if (i == G_N_ELEMENTS (tags))
12880       goto unknown_tag;
12881   } else {
12882     goto unknown_tag;
12883   }
12884
12885   return;
12886
12887 /* errors */
12888 unknown_tag:
12889 #ifndef GST_DISABLE_GST_DEBUG
12890   {
12891     gchar *namestr_dbg;
12892     gchar *meanstr_dbg;
12893
12894     meanstr_dbg = g_strndup (meanstr, meansize);
12895     namestr_dbg = g_strndup (namestr, namesize);
12896
12897     GST_WARNING_OBJECT (demux, "This tag %s:%s type:%u is not mapped, "
12898         "file a bug at bugzilla.gnome.org", meanstr_dbg, namestr_dbg, datatype);
12899
12900     g_free (namestr_dbg);
12901     g_free (meanstr_dbg);
12902   }
12903 #endif
12904   return;
12905 }
12906
12907 static void
12908 qtdemux_tag_add_id32 (GstQTDemux * demux, GstTagList * taglist, const char *tag,
12909     const char *tag_bis, GNode * node)
12910 {
12911   guint8 *data;
12912   GstBuffer *buf;
12913   guint len;
12914   GstTagList *id32_taglist = NULL;
12915
12916   GST_LOG_OBJECT (demux, "parsing ID32");
12917
12918   data = node->data;
12919   len = GST_READ_UINT32_BE (data);
12920
12921   /* need at least full box and language tag */
12922   if (len < 12 + 2)
12923     return;
12924
12925   buf = gst_buffer_new_allocate (NULL, len - 14, NULL);
12926   gst_buffer_fill (buf, 0, data + 14, len - 14);
12927
12928   id32_taglist = gst_tag_list_from_id3v2_tag (buf);
12929   if (id32_taglist) {
12930     GST_LOG_OBJECT (demux, "parsing ok");
12931     gst_tag_list_insert (taglist, id32_taglist, GST_TAG_MERGE_KEEP);
12932     gst_tag_list_unref (id32_taglist);
12933   } else {
12934     GST_LOG_OBJECT (demux, "parsing failed");
12935   }
12936
12937   gst_buffer_unref (buf);
12938 }
12939
12940 typedef void (*GstQTDemuxAddTagFunc) (GstQTDemux * demux, GstTagList * taglist,
12941     const char *tag, const char *tag_bis, GNode * node);
12942
12943 /* unmapped tags
12944 FOURCC_pcst -> if media is a podcast -> bool
12945 FOURCC_cpil -> if media is part of a compilation -> bool
12946 FOURCC_pgap -> if media is part of a gapless context -> bool
12947 FOURCC_tven -> the tv episode id e.g. S01E23 -> str
12948 */
12949
12950 static const struct
12951 {
12952   guint32 fourcc;
12953   const gchar *gst_tag;
12954   const gchar *gst_tag_bis;
12955   const GstQTDemuxAddTagFunc func;
12956 } add_funcs[] = {
12957   {
12958   FOURCC__nam, GST_TAG_TITLE, NULL, qtdemux_tag_add_str}, {
12959   FOURCC_titl, GST_TAG_TITLE, NULL, qtdemux_tag_add_str}, {
12960   FOURCC__grp, GST_TAG_GROUPING, NULL, qtdemux_tag_add_str}, {
12961   FOURCC__wrt, GST_TAG_COMPOSER, NULL, qtdemux_tag_add_str}, {
12962   FOURCC__ART, GST_TAG_ARTIST, NULL, qtdemux_tag_add_str}, {
12963   FOURCC_aART, GST_TAG_ALBUM_ARTIST, NULL, qtdemux_tag_add_str}, {
12964   FOURCC_perf, GST_TAG_ARTIST, NULL, qtdemux_tag_add_str}, {
12965   FOURCC_auth, GST_TAG_COMPOSER, NULL, qtdemux_tag_add_str}, {
12966   FOURCC__alb, GST_TAG_ALBUM, NULL, qtdemux_tag_add_str}, {
12967   FOURCC_albm, GST_TAG_ALBUM, NULL, qtdemux_tag_add_str}, {
12968   FOURCC_cprt, GST_TAG_COPYRIGHT, NULL, qtdemux_tag_add_str}, {
12969   FOURCC__cpy, GST_TAG_COPYRIGHT, NULL, qtdemux_tag_add_str}, {
12970   FOURCC__cmt, GST_TAG_COMMENT, NULL, qtdemux_tag_add_str}, {
12971   FOURCC__des, GST_TAG_DESCRIPTION, NULL, qtdemux_tag_add_str}, {
12972   FOURCC_desc, GST_TAG_DESCRIPTION, NULL, qtdemux_tag_add_str}, {
12973   FOURCC_dscp, GST_TAG_DESCRIPTION, NULL, qtdemux_tag_add_str}, {
12974   FOURCC__lyr, GST_TAG_LYRICS, NULL, qtdemux_tag_add_str}, {
12975   FOURCC__day, GST_TAG_DATE, NULL, qtdemux_tag_add_date}, {
12976   FOURCC_yrrc, GST_TAG_DATE, NULL, qtdemux_tag_add_year}, {
12977   FOURCC__too, GST_TAG_ENCODER, NULL, qtdemux_tag_add_str}, {
12978   FOURCC__inf, GST_TAG_COMMENT, NULL, qtdemux_tag_add_str}, {
12979   FOURCC_trkn, GST_TAG_TRACK_NUMBER, GST_TAG_TRACK_COUNT, qtdemux_tag_add_num}, {
12980   FOURCC_disk, GST_TAG_ALBUM_VOLUME_NUMBER, GST_TAG_ALBUM_VOLUME_COUNT,
12981         qtdemux_tag_add_num}, {
12982   FOURCC_disc, GST_TAG_ALBUM_VOLUME_NUMBER, GST_TAG_ALBUM_VOLUME_COUNT,
12983         qtdemux_tag_add_num}, {
12984   FOURCC__gen, GST_TAG_GENRE, NULL, qtdemux_tag_add_str}, {
12985   FOURCC_gnre, GST_TAG_GENRE, NULL, qtdemux_tag_add_gnre}, {
12986   FOURCC_tmpo, GST_TAG_BEATS_PER_MINUTE, NULL, qtdemux_tag_add_tmpo}, {
12987   FOURCC_covr, GST_TAG_IMAGE, NULL, qtdemux_tag_add_covr}, {
12988   FOURCC_sonm, GST_TAG_TITLE_SORTNAME, NULL, qtdemux_tag_add_str}, {
12989   FOURCC_soal, GST_TAG_ALBUM_SORTNAME, NULL, qtdemux_tag_add_str}, {
12990   FOURCC_soar, GST_TAG_ARTIST_SORTNAME, NULL, qtdemux_tag_add_str}, {
12991   FOURCC_soaa, GST_TAG_ALBUM_ARTIST_SORTNAME, NULL, qtdemux_tag_add_str}, {
12992   FOURCC_soco, GST_TAG_COMPOSER_SORTNAME, NULL, qtdemux_tag_add_str}, {
12993   FOURCC_sosn, GST_TAG_SHOW_SORTNAME, NULL, qtdemux_tag_add_str}, {
12994   FOURCC_tvsh, GST_TAG_SHOW_NAME, NULL, qtdemux_tag_add_str}, {
12995   FOURCC_tvsn, GST_TAG_SHOW_SEASON_NUMBER, NULL, qtdemux_tag_add_uint32}, {
12996   FOURCC_tves, GST_TAG_SHOW_EPISODE_NUMBER, NULL, qtdemux_tag_add_uint32}, {
12997   FOURCC_kywd, GST_TAG_KEYWORDS, NULL, qtdemux_tag_add_keywords}, {
12998   FOURCC_keyw, GST_TAG_KEYWORDS, NULL, qtdemux_tag_add_str}, {
12999   FOURCC__enc, GST_TAG_ENCODER, NULL, qtdemux_tag_add_str}, {
13000   FOURCC_loci, GST_TAG_GEO_LOCATION_NAME, NULL, qtdemux_tag_add_location}, {
13001   FOURCC_clsf, GST_QT_DEMUX_CLASSIFICATION_TAG, NULL,
13002         qtdemux_tag_add_classification}, {
13003   FOURCC__mak, GST_TAG_DEVICE_MANUFACTURER, NULL, qtdemux_tag_add_str}, {
13004   FOURCC__mod, GST_TAG_DEVICE_MODEL, NULL, qtdemux_tag_add_str}, {
13005   FOURCC__swr, GST_TAG_APPLICATION_NAME, NULL, qtdemux_tag_add_str}, {
13006
13007     /* This is a special case, some tags are stored in this
13008      * 'reverse dns naming', according to:
13009      * http://atomicparsley.sourceforge.net/mpeg-4files.html and
13010      * bug #614471
13011      */
13012   FOURCC_____, "", NULL, qtdemux_tag_add_revdns}, {
13013     /* see http://www.mp4ra.org/specs.html for ID32 in meta box */
13014   FOURCC_ID32, "", NULL, qtdemux_tag_add_id32}
13015 };
13016
13017 struct _GstQtDemuxTagList
13018 {
13019   GstQTDemux *demux;
13020   GstTagList *taglist;
13021 };
13022 typedef struct _GstQtDemuxTagList GstQtDemuxTagList;
13023
13024 static void
13025 qtdemux_tag_add_blob (GNode * node, GstQtDemuxTagList * qtdemuxtaglist)
13026 {
13027   gint len;
13028   guint8 *data;
13029   GstBuffer *buf;
13030   gchar *media_type;
13031   const gchar *style;
13032   GstSample *sample;
13033   GstStructure *s;
13034   guint i;
13035   guint8 ndata[4];
13036   GstQTDemux *demux = qtdemuxtaglist->demux;
13037   GstTagList *taglist = qtdemuxtaglist->taglist;
13038
13039   data = node->data;
13040   len = QT_UINT32 (data);
13041   buf = gst_buffer_new_and_alloc (len);
13042   gst_buffer_fill (buf, 0, data, len);
13043
13044   /* heuristic to determine style of tag */
13045   if (QT_FOURCC (data + 4) == FOURCC_____ ||
13046       (len > 8 + 12 && QT_FOURCC (data + 12) == FOURCC_data))
13047     style = "itunes";
13048   else if (demux->major_brand == FOURCC_qt__)
13049     style = "quicktime";
13050   /* fall back to assuming iso/3gp tag style */
13051   else
13052     style = "iso";
13053
13054   /* santize the name for the caps. */
13055   for (i = 0; i < 4; i++) {
13056     guint8 d = data[4 + i];
13057     if (g_ascii_isalnum (d))
13058       ndata[i] = g_ascii_tolower (d);
13059     else
13060       ndata[i] = '_';
13061   }
13062
13063   media_type = g_strdup_printf ("application/x-gst-qt-%c%c%c%c-tag",
13064       ndata[0], ndata[1], ndata[2], ndata[3]);
13065   GST_DEBUG_OBJECT (demux, "media type %s", media_type);
13066
13067   s = gst_structure_new (media_type, "style", G_TYPE_STRING, style, NULL);
13068   sample = gst_sample_new (buf, NULL, NULL, s);
13069   gst_buffer_unref (buf);
13070   g_free (media_type);
13071
13072   GST_DEBUG_OBJECT (demux, "adding private tag; size %d, info %" GST_PTR_FORMAT,
13073       len, s);
13074
13075   gst_tag_list_add (taglist, GST_TAG_MERGE_APPEND,
13076       GST_QT_DEMUX_PRIVATE_TAG, sample, NULL);
13077
13078   gst_sample_unref (sample);
13079 }
13080
13081 static void
13082 qtdemux_parse_udta (GstQTDemux * qtdemux, GstTagList * taglist, GNode * udta)
13083 {
13084   GNode *meta;
13085   GNode *ilst;
13086   GNode *xmp_;
13087   GNode *node;
13088   gint i;
13089   GstQtDemuxTagList demuxtaglist;
13090
13091   demuxtaglist.demux = qtdemux;
13092   demuxtaglist.taglist = taglist;
13093
13094   meta = qtdemux_tree_get_child_by_type (udta, FOURCC_meta);
13095   if (meta != NULL) {
13096     ilst = qtdemux_tree_get_child_by_type (meta, FOURCC_ilst);
13097     if (ilst == NULL) {
13098       GST_LOG_OBJECT (qtdemux, "no ilst");
13099       return;
13100     }
13101   } else {
13102     ilst = udta;
13103     GST_LOG_OBJECT (qtdemux, "no meta so using udta itself");
13104   }
13105
13106   i = 0;
13107   while (i < G_N_ELEMENTS (add_funcs)) {
13108     node = qtdemux_tree_get_child_by_type (ilst, add_funcs[i].fourcc);
13109     if (node) {
13110       gint len;
13111
13112       len = QT_UINT32 (node->data);
13113       if (len < 12) {
13114         GST_DEBUG_OBJECT (qtdemux, "too small tag atom %" GST_FOURCC_FORMAT,
13115             GST_FOURCC_ARGS (add_funcs[i].fourcc));
13116       } else {
13117         add_funcs[i].func (qtdemux, taglist, add_funcs[i].gst_tag,
13118             add_funcs[i].gst_tag_bis, node);
13119       }
13120       g_node_destroy (node);
13121     } else {
13122       i++;
13123     }
13124   }
13125
13126   /* parsed nodes have been removed, pass along remainder as blob */
13127   g_node_children_foreach (ilst, G_TRAVERSE_ALL,
13128       (GNodeForeachFunc) qtdemux_tag_add_blob, &demuxtaglist);
13129
13130   /* parse up XMP_ node if existing */
13131   xmp_ = qtdemux_tree_get_child_by_type (udta, FOURCC_XMP_);
13132   if (xmp_ != NULL) {
13133     GstBuffer *buf;
13134     GstTagList *xmptaglist;
13135
13136     buf = _gst_buffer_new_wrapped (((guint8 *) xmp_->data) + 8,
13137         QT_UINT32 ((guint8 *) xmp_->data) - 8, NULL);
13138     xmptaglist = gst_tag_list_from_xmp_buffer (buf);
13139     gst_buffer_unref (buf);
13140
13141     qtdemux_handle_xmp_taglist (qtdemux, taglist, xmptaglist);
13142   } else {
13143     GST_DEBUG_OBJECT (qtdemux, "No XMP_ node found");
13144   }
13145 }
13146
13147 typedef struct
13148 {
13149   GstStructure *structure;      /* helper for sort function */
13150   gchar *location;
13151   guint min_req_bitrate;
13152   guint min_req_qt_version;
13153 } GstQtReference;
13154
13155 static gint
13156 qtdemux_redirects_sort_func (gconstpointer a, gconstpointer b)
13157 {
13158   GstQtReference *ref_a = (GstQtReference *) a;
13159   GstQtReference *ref_b = (GstQtReference *) b;
13160
13161   if (ref_b->min_req_qt_version != ref_a->min_req_qt_version)
13162     return ref_b->min_req_qt_version - ref_a->min_req_qt_version;
13163
13164   /* known bitrates go before unknown; higher bitrates go first */
13165   return ref_b->min_req_bitrate - ref_a->min_req_bitrate;
13166 }
13167
13168 /* sort the redirects and post a message for the application.
13169  */
13170 static void
13171 qtdemux_process_redirects (GstQTDemux * qtdemux, GList * references)
13172 {
13173   GstQtReference *best;
13174   GstStructure *s;
13175   GstMessage *msg;
13176   GValue list_val = { 0, };
13177   GList *l;
13178
13179   g_assert (references != NULL);
13180
13181   references = g_list_sort (references, qtdemux_redirects_sort_func);
13182
13183   best = (GstQtReference *) references->data;
13184
13185   g_value_init (&list_val, GST_TYPE_LIST);
13186
13187   for (l = references; l != NULL; l = l->next) {
13188     GstQtReference *ref = (GstQtReference *) l->data;
13189     GValue struct_val = { 0, };
13190
13191     ref->structure = gst_structure_new ("redirect",
13192         "new-location", G_TYPE_STRING, ref->location, NULL);
13193
13194     if (ref->min_req_bitrate > 0) {
13195       gst_structure_set (ref->structure, "minimum-bitrate", G_TYPE_INT,
13196           ref->min_req_bitrate, NULL);
13197     }
13198
13199     g_value_init (&struct_val, GST_TYPE_STRUCTURE);
13200     g_value_set_boxed (&struct_val, ref->structure);
13201     gst_value_list_append_value (&list_val, &struct_val);
13202     g_value_unset (&struct_val);
13203     /* don't free anything here yet, since we need best->structure below */
13204   }
13205
13206   g_assert (best != NULL);
13207   s = gst_structure_copy (best->structure);
13208
13209   if (g_list_length (references) > 1) {
13210     gst_structure_set_value (s, "locations", &list_val);
13211   }
13212
13213   g_value_unset (&list_val);
13214
13215   for (l = references; l != NULL; l = l->next) {
13216     GstQtReference *ref = (GstQtReference *) l->data;
13217
13218     gst_structure_free (ref->structure);
13219     g_free (ref->location);
13220     g_free (ref);
13221   }
13222   g_list_free (references);
13223
13224   GST_INFO_OBJECT (qtdemux, "posting redirect message: %" GST_PTR_FORMAT, s);
13225   msg = gst_message_new_element (GST_OBJECT_CAST (qtdemux), s);
13226   gst_element_post_message (GST_ELEMENT_CAST (qtdemux), msg);
13227   qtdemux->posted_redirect = TRUE;
13228 }
13229
13230 /* look for redirect nodes, collect all redirect information and
13231  * process it.
13232  */
13233 static gboolean
13234 qtdemux_parse_redirects (GstQTDemux * qtdemux)
13235 {
13236   GNode *rmra, *rmda, *rdrf;
13237
13238   rmra = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_rmra);
13239   if (rmra) {
13240     GList *redirects = NULL;
13241
13242     rmda = qtdemux_tree_get_child_by_type (rmra, FOURCC_rmda);
13243     while (rmda) {
13244       GstQtReference ref = { NULL, NULL, 0, 0 };
13245       GNode *rmdr, *rmvc;
13246
13247       if ((rmdr = qtdemux_tree_get_child_by_type (rmda, FOURCC_rmdr))) {
13248         ref.min_req_bitrate = QT_UINT32 ((guint8 *) rmdr->data + 12);
13249         GST_LOG_OBJECT (qtdemux, "data rate atom, required bitrate = %u",
13250             ref.min_req_bitrate);
13251       }
13252
13253       if ((rmvc = qtdemux_tree_get_child_by_type (rmda, FOURCC_rmvc))) {
13254         guint32 package = QT_FOURCC ((guint8 *) rmvc->data + 12);
13255         guint version = QT_UINT32 ((guint8 *) rmvc->data + 16);
13256
13257 #ifndef GST_DISABLE_GST_DEBUG
13258         guint bitmask = QT_UINT32 ((guint8 *) rmvc->data + 20);
13259 #endif
13260         guint check_type = QT_UINT16 ((guint8 *) rmvc->data + 24);
13261
13262         GST_LOG_OBJECT (qtdemux,
13263             "version check atom [%" GST_FOURCC_FORMAT "], version=0x%08x"
13264             ", mask=%08x, check_type=%u", GST_FOURCC_ARGS (package), version,
13265             bitmask, check_type);
13266         if (package == FOURCC_qtim && check_type == 0) {
13267           ref.min_req_qt_version = version;
13268         }
13269       }
13270
13271       rdrf = qtdemux_tree_get_child_by_type (rmda, FOURCC_rdrf);
13272       if (rdrf) {
13273         guint32 ref_type;
13274         guint8 *ref_data;
13275         guint ref_len;
13276
13277         ref_len = QT_UINT32 ((guint8 *) rdrf->data);
13278         if (ref_len > 20) {
13279           ref_type = QT_FOURCC ((guint8 *) rdrf->data + 12);
13280           ref_data = (guint8 *) rdrf->data + 20;
13281           if (ref_type == FOURCC_alis) {
13282             guint record_len, record_version, fn_len;
13283
13284             if (ref_len > 70) {
13285               /* MacOSX alias record, google for alias-layout.txt */
13286               record_len = QT_UINT16 (ref_data + 4);
13287               record_version = QT_UINT16 (ref_data + 4 + 2);
13288               fn_len = QT_UINT8 (ref_data + 50);
13289               if (record_len > 50 && record_version == 2 && fn_len > 0) {
13290                 ref.location = g_strndup ((gchar *) ref_data + 51, fn_len);
13291               }
13292             } else {
13293               GST_WARNING_OBJECT (qtdemux, "Invalid rdrf/alis size (%u < 70)",
13294                   ref_len);
13295             }
13296           } else if (ref_type == FOURCC_url_) {
13297             ref.location = g_strndup ((gchar *) ref_data, ref_len - 8);
13298           } else {
13299             GST_DEBUG_OBJECT (qtdemux,
13300                 "unknown rdrf reference type %" GST_FOURCC_FORMAT,
13301                 GST_FOURCC_ARGS (ref_type));
13302           }
13303           if (ref.location != NULL) {
13304             GST_INFO_OBJECT (qtdemux, "New location: %s", ref.location);
13305             redirects =
13306                 g_list_prepend (redirects, g_memdup (&ref, sizeof (ref)));
13307           } else {
13308             GST_WARNING_OBJECT (qtdemux,
13309                 "Failed to extract redirect location from rdrf atom");
13310           }
13311         } else {
13312           GST_WARNING_OBJECT (qtdemux, "Invalid rdrf size (%u < 20)", ref_len);
13313         }
13314       }
13315
13316       /* look for others */
13317       rmda = qtdemux_tree_get_sibling_by_type (rmda, FOURCC_rmda);
13318     }
13319
13320     if (redirects != NULL) {
13321       qtdemux_process_redirects (qtdemux, redirects);
13322     }
13323   }
13324   return TRUE;
13325 }
13326
13327 static GstTagList *
13328 qtdemux_add_container_format (GstQTDemux * qtdemux, GstTagList * tags)
13329 {
13330   const gchar *fmt;
13331
13332   if (tags == NULL) {
13333     tags = gst_tag_list_new_empty ();
13334     gst_tag_list_set_scope (tags, GST_TAG_SCOPE_GLOBAL);
13335   }
13336
13337   if (qtdemux->major_brand == FOURCC_mjp2)
13338     fmt = "Motion JPEG 2000";
13339   else if ((qtdemux->major_brand & 0xffff) == FOURCC_3g__)
13340     fmt = "3GP";
13341   else if (qtdemux->major_brand == FOURCC_qt__)
13342     fmt = "Quicktime";
13343   else if (qtdemux->fragmented)
13344     fmt = "ISO fMP4";
13345   else
13346     fmt = "ISO MP4/M4A";
13347
13348   GST_LOG_OBJECT (qtdemux, "mapped %" GST_FOURCC_FORMAT " to '%s'",
13349       GST_FOURCC_ARGS (qtdemux->major_brand), fmt);
13350
13351   gst_tag_list_add (tags, GST_TAG_MERGE_REPLACE, GST_TAG_CONTAINER_FORMAT,
13352       fmt, NULL);
13353
13354   return tags;
13355 }
13356
13357 /* we have read the complete moov node now.
13358  * This function parses all of the relevant info, creates the traks and
13359  * prepares all data structures for playback
13360  */
13361 static gboolean
13362 qtdemux_parse_tree (GstQTDemux * qtdemux)
13363 {
13364   GNode *mvhd;
13365   GNode *trak;
13366   GNode *udta;
13367   GNode *mvex;
13368   GstClockTime duration;
13369   GNode *pssh;
13370   guint64 creation_time;
13371   GstDateTime *datetime = NULL;
13372   gint version;
13373
13374   /* make sure we have a usable taglist */
13375   qtdemux->tag_list = gst_tag_list_make_writable (qtdemux->tag_list);
13376
13377   mvhd = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_mvhd);
13378   if (mvhd == NULL) {
13379     GST_LOG_OBJECT (qtdemux, "No mvhd node found, looking for redirects.");
13380     return qtdemux_parse_redirects (qtdemux);
13381   }
13382
13383   version = QT_UINT8 ((guint8 *) mvhd->data + 8);
13384   if (version == 1) {
13385     creation_time = QT_UINT64 ((guint8 *) mvhd->data + 12);
13386     qtdemux->timescale = QT_UINT32 ((guint8 *) mvhd->data + 28);
13387     qtdemux->duration = QT_UINT64 ((guint8 *) mvhd->data + 32);
13388   } else if (version == 0) {
13389     creation_time = QT_UINT32 ((guint8 *) mvhd->data + 12);
13390     qtdemux->timescale = QT_UINT32 ((guint8 *) mvhd->data + 20);
13391     qtdemux->duration = QT_UINT32 ((guint8 *) mvhd->data + 24);
13392   } else {
13393     GST_WARNING_OBJECT (qtdemux, "Unhandled mvhd version %d", version);
13394     return FALSE;
13395   }
13396
13397   /* Moving qt creation time (secs since 1904) to unix time */
13398   if (creation_time != 0) {
13399     /* Try to use epoch first as it should be faster and more commonly found */
13400     if (creation_time >= QTDEMUX_SECONDS_FROM_1904_TO_1970) {
13401       GTimeVal now;
13402
13403       creation_time -= QTDEMUX_SECONDS_FROM_1904_TO_1970;
13404       /* some data cleansing sanity */
13405       g_get_current_time (&now);
13406       if (now.tv_sec + 24 * 3600 < creation_time) {
13407         GST_DEBUG_OBJECT (qtdemux, "discarding bogus future creation time");
13408       } else {
13409         datetime = gst_date_time_new_from_unix_epoch_utc (creation_time);
13410       }
13411     } else {
13412       GDateTime *base_dt = g_date_time_new_utc (1904, 1, 1, 0, 0, 0);
13413       GDateTime *dt, *dt_local;
13414
13415       dt = g_date_time_add_seconds (base_dt, creation_time);
13416       dt_local = g_date_time_to_local (dt);
13417       datetime = gst_date_time_new_from_g_date_time (dt_local);
13418
13419       g_date_time_unref (base_dt);
13420       g_date_time_unref (dt);
13421     }
13422   }
13423   if (datetime) {
13424     /* Use KEEP as explicit tags should have a higher priority than mvhd tag */
13425     gst_tag_list_add (qtdemux->tag_list, GST_TAG_MERGE_KEEP, GST_TAG_DATE_TIME,
13426         datetime, NULL);
13427     gst_date_time_unref (datetime);
13428   }
13429
13430   GST_INFO_OBJECT (qtdemux, "timescale: %u", qtdemux->timescale);
13431   GST_INFO_OBJECT (qtdemux, "duration: %" G_GUINT64_FORMAT, qtdemux->duration);
13432
13433   /* check for fragmented file and get some (default) data */
13434   mvex = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_mvex);
13435   if (mvex) {
13436     GNode *mehd;
13437     GstByteReader mehd_data;
13438
13439     /* let track parsing or anyone know weird stuff might happen ... */
13440     qtdemux->fragmented = TRUE;
13441
13442     /* compensate for total duration */
13443     mehd = qtdemux_tree_get_child_by_type_full (mvex, FOURCC_mehd, &mehd_data);
13444     if (mehd)
13445       qtdemux_parse_mehd (qtdemux, &mehd_data);
13446   }
13447
13448   /* set duration in the segment info */
13449   gst_qtdemux_get_duration (qtdemux, &duration);
13450   if (duration) {
13451     qtdemux->segment.duration = duration;
13452     /* also do not exceed duration; stop is set that way post seek anyway,
13453      * and segment activation falls back to duration,
13454      * whereas loop only checks stop, so let's align this here as well */
13455     qtdemux->segment.stop = duration;
13456   }
13457
13458   /* parse all traks */
13459   trak = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_trak);
13460   while (trak) {
13461     qtdemux_parse_trak (qtdemux, trak);
13462     /* iterate all siblings */
13463     trak = qtdemux_tree_get_sibling_by_type (trak, FOURCC_trak);
13464   }
13465
13466   qtdemux->tag_list = gst_tag_list_make_writable (qtdemux->tag_list);
13467
13468   /* find tags */
13469   udta = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_udta);
13470   if (udta) {
13471     qtdemux_parse_udta (qtdemux, qtdemux->tag_list, udta);
13472   } else {
13473     GST_LOG_OBJECT (qtdemux, "No udta node found.");
13474   }
13475
13476   /* maybe also some tags in meta box */
13477   udta = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_meta);
13478   if (udta) {
13479     GST_DEBUG_OBJECT (qtdemux, "Parsing meta box for tags.");
13480     qtdemux_parse_udta (qtdemux, qtdemux->tag_list, udta);
13481   } else {
13482     GST_LOG_OBJECT (qtdemux, "No meta node found.");
13483   }
13484
13485   /* parse any protection system info */
13486   pssh = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_pssh);
13487   while (pssh) {
13488     GST_LOG_OBJECT (qtdemux, "Parsing pssh box.");
13489     qtdemux_parse_pssh (qtdemux, pssh);
13490     pssh = qtdemux_tree_get_sibling_by_type (pssh, FOURCC_pssh);
13491   }
13492
13493   qtdemux->tag_list = qtdemux_add_container_format (qtdemux, qtdemux->tag_list);
13494
13495   return TRUE;
13496 }
13497
13498 /* taken from ffmpeg */
13499 static int
13500 read_descr_size (guint8 * ptr, guint8 * end, guint8 ** end_out)
13501 {
13502   int count = 4;
13503   int len = 0;
13504
13505   while (count--) {
13506     int c;
13507
13508     if (ptr >= end)
13509       return -1;
13510
13511     c = *ptr++;
13512     len = (len << 7) | (c & 0x7f);
13513     if (!(c & 0x80))
13514       break;
13515   }
13516   *end_out = ptr;
13517   return len;
13518 }
13519
13520 static GList *
13521 parse_xiph_stream_headers (GstQTDemux * qtdemux, gpointer codec_data,
13522     gsize codec_data_size)
13523 {
13524   GList *list = NULL;
13525   guint8 *p = codec_data;
13526   gint i, offset, num_packets;
13527   guint *length, last;
13528
13529   GST_MEMDUMP_OBJECT (qtdemux, "xiph codec data", codec_data, codec_data_size);
13530
13531   if (codec_data == NULL || codec_data_size == 0)
13532     goto error;
13533
13534   /* start of the stream and vorbis audio or theora video, need to
13535    * send the codec_priv data as first three packets */
13536   num_packets = p[0] + 1;
13537   GST_DEBUG_OBJECT (qtdemux,
13538       "%u stream headers, total length=%" G_GSIZE_FORMAT " bytes",
13539       (guint) num_packets, codec_data_size);
13540
13541   /* Let's put some limits, Don't think there even is a xiph codec
13542    * with more than 3-4 headers */
13543   if (G_UNLIKELY (num_packets > 16)) {
13544     GST_WARNING_OBJECT (qtdemux,
13545         "Unlikely number of xiph headers, most likely not valid");
13546     goto error;
13547   }
13548
13549   length = g_alloca (num_packets * sizeof (guint));
13550   last = 0;
13551   offset = 1;
13552
13553   /* first packets, read length values */
13554   for (i = 0; i < num_packets - 1; i++) {
13555     length[i] = 0;
13556     while (offset < codec_data_size) {
13557       length[i] += p[offset];
13558       if (p[offset++] != 0xff)
13559         break;
13560     }
13561     last += length[i];
13562   }
13563   if (offset + last > codec_data_size)
13564     goto error;
13565
13566   /* last packet is the remaining size */
13567   length[i] = codec_data_size - offset - last;
13568
13569   for (i = 0; i < num_packets; i++) {
13570     GstBuffer *hdr;
13571
13572     GST_DEBUG_OBJECT (qtdemux, "buffer %d: %u bytes", i, (guint) length[i]);
13573
13574     if (offset + length[i] > codec_data_size)
13575       goto error;
13576
13577     hdr = gst_buffer_new_wrapped (g_memdup (p + offset, length[i]), length[i]);
13578     list = g_list_append (list, hdr);
13579
13580     offset += length[i];
13581   }
13582
13583   return list;
13584
13585   /* ERRORS */
13586 error:
13587   {
13588     if (list != NULL)
13589       g_list_free_full (list, (GDestroyNotify) gst_buffer_unref);
13590     return NULL;
13591   }
13592
13593 }
13594
13595 /* this can change the codec originally present in @list */
13596 static void
13597 gst_qtdemux_handle_esds (GstQTDemux * qtdemux, QtDemuxStream * stream,
13598     QtDemuxStreamStsdEntry * entry, GNode * esds, GstTagList * list)
13599 {
13600   int len = QT_UINT32 (esds->data);
13601   guint8 *ptr = esds->data;
13602   guint8 *end = ptr + len;
13603   int tag;
13604   guint8 *data_ptr = NULL;
13605   int data_len = 0;
13606   guint8 object_type_id = 0;
13607   guint8 stream_type = 0;
13608   const char *codec_name = NULL;
13609   GstCaps *caps = NULL;
13610
13611   GST_MEMDUMP_OBJECT (qtdemux, "esds", ptr, len);
13612   ptr += 8;
13613   GST_DEBUG_OBJECT (qtdemux, "version/flags = %08x", QT_UINT32 (ptr));
13614   ptr += 4;
13615   while (ptr + 1 < end) {
13616     tag = QT_UINT8 (ptr);
13617     GST_DEBUG_OBJECT (qtdemux, "tag = %02x", tag);
13618     ptr++;
13619     len = read_descr_size (ptr, end, &ptr);
13620     GST_DEBUG_OBJECT (qtdemux, "len = %d", len);
13621
13622     /* Check the stated amount of data is available for reading */
13623     if (len < 0 || ptr + len > end)
13624       break;
13625
13626     switch (tag) {
13627       case ES_DESCRIPTOR_TAG:
13628         GST_DEBUG_OBJECT (qtdemux, "ID 0x%04x", QT_UINT16 (ptr));
13629         GST_DEBUG_OBJECT (qtdemux, "priority 0x%04x", QT_UINT8 (ptr + 2));
13630         ptr += 3;
13631         break;
13632       case DECODER_CONFIG_DESC_TAG:{
13633         guint max_bitrate, avg_bitrate;
13634
13635         object_type_id = QT_UINT8 (ptr);
13636         stream_type = QT_UINT8 (ptr + 1) >> 2;
13637         max_bitrate = QT_UINT32 (ptr + 5);
13638         avg_bitrate = QT_UINT32 (ptr + 9);
13639         GST_DEBUG_OBJECT (qtdemux, "object_type_id %02x", object_type_id);
13640         GST_DEBUG_OBJECT (qtdemux, "stream_type %02x", stream_type);
13641         GST_DEBUG_OBJECT (qtdemux, "buffer_size_db %02x", QT_UINT24 (ptr + 2));
13642         GST_DEBUG_OBJECT (qtdemux, "max bitrate %u", max_bitrate);
13643         GST_DEBUG_OBJECT (qtdemux, "avg bitrate %u", avg_bitrate);
13644         if (max_bitrate > 0 && max_bitrate < G_MAXUINT32) {
13645           gst_tag_list_add (list, GST_TAG_MERGE_REPLACE,
13646               GST_TAG_MAXIMUM_BITRATE, max_bitrate, NULL);
13647         }
13648         if (avg_bitrate > 0 && avg_bitrate < G_MAXUINT32) {
13649           gst_tag_list_add (list, GST_TAG_MERGE_REPLACE, GST_TAG_BITRATE,
13650               avg_bitrate, NULL);
13651         }
13652         ptr += 13;
13653         break;
13654       }
13655       case DECODER_SPECIFIC_INFO_TAG:
13656         GST_MEMDUMP_OBJECT (qtdemux, "data", ptr, len);
13657         if (object_type_id == 0xe0 && len == 0x40) {
13658           guint8 *data;
13659           GstStructure *s;
13660           guint32 clut[16];
13661           gint i;
13662
13663           GST_DEBUG_OBJECT (qtdemux,
13664               "Have VOBSUB palette. Creating palette event");
13665           /* move to decConfigDescr data and read palette */
13666           data = ptr;
13667           for (i = 0; i < 16; i++) {
13668             clut[i] = QT_UINT32 (data);
13669             data += 4;
13670           }
13671
13672           s = gst_structure_new ("application/x-gst-dvd", "event",
13673               G_TYPE_STRING, "dvd-spu-clut-change",
13674               "clut00", G_TYPE_INT, clut[0], "clut01", G_TYPE_INT, clut[1],
13675               "clut02", G_TYPE_INT, clut[2], "clut03", G_TYPE_INT, clut[3],
13676               "clut04", G_TYPE_INT, clut[4], "clut05", G_TYPE_INT, clut[5],
13677               "clut06", G_TYPE_INT, clut[6], "clut07", G_TYPE_INT, clut[7],
13678               "clut08", G_TYPE_INT, clut[8], "clut09", G_TYPE_INT, clut[9],
13679               "clut10", G_TYPE_INT, clut[10], "clut11", G_TYPE_INT, clut[11],
13680               "clut12", G_TYPE_INT, clut[12], "clut13", G_TYPE_INT, clut[13],
13681               "clut14", G_TYPE_INT, clut[14], "clut15", G_TYPE_INT, clut[15],
13682               NULL);
13683
13684           /* store event and trigger custom processing */
13685           stream->pending_event =
13686               gst_event_new_custom (GST_EVENT_CUSTOM_DOWNSTREAM, s);
13687         } else {
13688           /* Generic codec_data handler puts it on the caps */
13689           data_ptr = ptr;
13690           data_len = len;
13691         }
13692
13693         ptr += len;
13694         break;
13695       case SL_CONFIG_DESC_TAG:
13696         GST_DEBUG_OBJECT (qtdemux, "data %02x", QT_UINT8 (ptr));
13697         ptr += 1;
13698         break;
13699       default:
13700         GST_DEBUG_OBJECT (qtdemux, "Unknown/unhandled descriptor tag %02x",
13701             tag);
13702         GST_MEMDUMP_OBJECT (qtdemux, "descriptor data", ptr, len);
13703         ptr += len;
13704         break;
13705     }
13706   }
13707
13708   /* object_type_id in the esds atom in mp4a and mp4v tells us which codec is
13709    * in use, and should also be used to override some other parameters for some
13710    * codecs. */
13711   switch (object_type_id) {
13712     case 0x20:                 /* MPEG-4 */
13713       /* 4 bytes for the visual_object_sequence_start_code and 1 byte for the
13714        * profile_and_level_indication */
13715       if (data_ptr != NULL && data_len >= 5 &&
13716           GST_READ_UINT32_BE (data_ptr) == 0x000001b0) {
13717         gst_codec_utils_mpeg4video_caps_set_level_and_profile (entry->caps,
13718             data_ptr + 4, data_len - 4);
13719       }
13720       break;                    /* Nothing special needed here */
13721     case 0x21:                 /* H.264 */
13722       codec_name = "H.264 / AVC";
13723       caps = gst_caps_new_simple ("video/x-h264",
13724           "stream-format", G_TYPE_STRING, "avc",
13725           "alignment", G_TYPE_STRING, "au", NULL);
13726       break;
13727     case 0x40:                 /* AAC (any) */
13728     case 0x66:                 /* AAC Main */
13729     case 0x67:                 /* AAC LC */
13730     case 0x68:                 /* AAC SSR */
13731       /* Override channels and rate based on the codec_data, as it's often
13732        * wrong. */
13733       /* Only do so for basic setup without HE-AAC extension */
13734       if (data_ptr && data_len == 2) {
13735         guint channels, rate;
13736
13737         channels = gst_codec_utils_aac_get_channels (data_ptr, data_len);
13738         if (channels > 0)
13739           entry->n_channels = channels;
13740
13741         rate = gst_codec_utils_aac_get_sample_rate (data_ptr, data_len);
13742         if (rate > 0)
13743           entry->rate = rate;
13744       }
13745
13746       /* Set level and profile if possible */
13747       if (data_ptr != NULL && data_len >= 2) {
13748         gst_codec_utils_aac_caps_set_level_and_profile (entry->caps,
13749             data_ptr, data_len);
13750       } else {
13751         const gchar *profile_str = NULL;
13752         GstBuffer *buffer;
13753         GstMapInfo map;
13754         guint8 *codec_data;
13755         gint rate_idx, profile;
13756
13757         /* No codec_data, let's invent something.
13758          * FIXME: This is wrong for SBR! */
13759
13760         GST_WARNING_OBJECT (qtdemux, "No codec_data for AAC available");
13761
13762         buffer = gst_buffer_new_and_alloc (2);
13763         gst_buffer_map (buffer, &map, GST_MAP_WRITE);
13764         codec_data = map.data;
13765
13766         rate_idx =
13767             gst_codec_utils_aac_get_index_from_sample_rate (CUR_STREAM
13768             (stream)->rate);
13769
13770         switch (object_type_id) {
13771           case 0x66:
13772             profile_str = "main";
13773             profile = 0;
13774             break;
13775           case 0x67:
13776             profile_str = "lc";
13777             profile = 1;
13778             break;
13779           case 0x68:
13780             profile_str = "ssr";
13781             profile = 2;
13782             break;
13783           default:
13784             profile = 3;
13785             break;
13786         }
13787
13788         codec_data[0] = ((profile + 1) << 3) | ((rate_idx & 0xE) >> 1);
13789         codec_data[1] =
13790             ((rate_idx & 0x1) << 7) | (CUR_STREAM (stream)->n_channels << 3);
13791
13792         gst_buffer_unmap (buffer, &map);
13793         gst_caps_set_simple (CUR_STREAM (stream)->caps, "codec_data",
13794             GST_TYPE_BUFFER, buffer, NULL);
13795         gst_buffer_unref (buffer);
13796
13797         if (profile_str) {
13798           gst_caps_set_simple (CUR_STREAM (stream)->caps, "profile",
13799               G_TYPE_STRING, profile_str, NULL);
13800         }
13801       }
13802       break;
13803     case 0x60:                 /* MPEG-2, various profiles */
13804     case 0x61:
13805     case 0x62:
13806     case 0x63:
13807     case 0x64:
13808     case 0x65:
13809       codec_name = "MPEG-2 video";
13810       caps = gst_caps_new_simple ("video/mpeg",
13811           "mpegversion", G_TYPE_INT, 2,
13812           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
13813       break;
13814     case 0x69:                 /* MPEG-2 BC audio */
13815     case 0x6B:                 /* MPEG-1 audio */
13816       caps = gst_caps_new_simple ("audio/mpeg",
13817           "mpegversion", G_TYPE_INT, 1, NULL);
13818       codec_name = "MPEG-1 audio";
13819       break;
13820     case 0x6A:                 /* MPEG-1 */
13821       codec_name = "MPEG-1 video";
13822       caps = gst_caps_new_simple ("video/mpeg",
13823           "mpegversion", G_TYPE_INT, 1,
13824           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
13825       break;
13826     case 0x6C:                 /* MJPEG */
13827       caps =
13828           gst_caps_new_simple ("image/jpeg", "parsed", G_TYPE_BOOLEAN, TRUE,
13829           NULL);
13830       codec_name = "Motion-JPEG";
13831       break;
13832     case 0x6D:                 /* PNG */
13833       caps =
13834           gst_caps_new_simple ("image/png", "parsed", G_TYPE_BOOLEAN, TRUE,
13835           NULL);
13836       codec_name = "PNG still images";
13837       break;
13838     case 0x6E:                 /* JPEG2000 */
13839       codec_name = "JPEG-2000";
13840       caps = gst_caps_new_simple ("image/x-j2c", "fields", G_TYPE_INT, 1, NULL);
13841       break;
13842     case 0xA4:                 /* Dirac */
13843       codec_name = "Dirac";
13844       caps = gst_caps_new_empty_simple ("video/x-dirac");
13845       break;
13846     case 0xA5:                 /* AC3 */
13847       codec_name = "AC-3 audio";
13848       caps = gst_caps_new_simple ("audio/x-ac3",
13849           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
13850       break;
13851     case 0xA9:                 /* AC3 */
13852       codec_name = "DTS audio";
13853       caps = gst_caps_new_simple ("audio/x-dts",
13854           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
13855       break;
13856     case 0xDD:
13857       if (stream_type == 0x05 && data_ptr) {
13858         GList *headers =
13859             parse_xiph_stream_headers (qtdemux, data_ptr, data_len);
13860         if (headers) {
13861           GList *tmp;
13862           GValue arr_val = G_VALUE_INIT;
13863           GValue buf_val = G_VALUE_INIT;
13864           GstStructure *s;
13865
13866           /* Let's assume it's vorbis if it's an audio stream of type 0xdd and we have codec data that extracts properly */
13867           codec_name = "Vorbis";
13868           caps = gst_caps_new_empty_simple ("audio/x-vorbis");
13869           g_value_init (&arr_val, GST_TYPE_ARRAY);
13870           g_value_init (&buf_val, GST_TYPE_BUFFER);
13871           for (tmp = headers; tmp; tmp = tmp->next) {
13872             g_value_set_boxed (&buf_val, (GstBuffer *) tmp->data);
13873             gst_value_array_append_value (&arr_val, &buf_val);
13874           }
13875           s = gst_caps_get_structure (caps, 0);
13876           gst_structure_take_value (s, "streamheader", &arr_val);
13877           g_value_unset (&buf_val);
13878           g_list_free (headers);
13879
13880           data_ptr = NULL;
13881           data_len = 0;
13882         }
13883       }
13884       break;
13885     case 0xE1:                 /* QCELP */
13886       /* QCELP, the codec_data is a riff tag (little endian) with
13887        * 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). */
13888       caps = gst_caps_new_empty_simple ("audio/qcelp");
13889       codec_name = "QCELP";
13890       break;
13891     default:
13892       break;
13893   }
13894
13895   /* If we have a replacement caps, then change our caps for this stream */
13896   if (caps) {
13897     gst_caps_unref (entry->caps);
13898     entry->caps = caps;
13899   }
13900
13901   if (codec_name && list)
13902     gst_tag_list_add (list, GST_TAG_MERGE_REPLACE,
13903         GST_TAG_AUDIO_CODEC, codec_name, NULL);
13904
13905   /* Add the codec_data attribute to caps, if we have it */
13906   if (data_ptr) {
13907     GstBuffer *buffer;
13908
13909     buffer = gst_buffer_new_and_alloc (data_len);
13910     gst_buffer_fill (buffer, 0, data_ptr, data_len);
13911
13912     GST_DEBUG_OBJECT (qtdemux, "setting codec_data from esds");
13913     GST_MEMDUMP_OBJECT (qtdemux, "codec_data from esds", data_ptr, data_len);
13914
13915     gst_caps_set_simple (entry->caps, "codec_data", GST_TYPE_BUFFER,
13916         buffer, NULL);
13917     gst_buffer_unref (buffer);
13918   }
13919
13920 }
13921
13922 static inline GstCaps *
13923 _get_unknown_codec_name (const gchar * type, guint32 fourcc)
13924 {
13925   GstCaps *caps;
13926   guint i;
13927   char *s, fourstr[5];
13928
13929   g_snprintf (fourstr, 5, "%" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (fourcc));
13930   for (i = 0; i < 4; i++) {
13931     if (!g_ascii_isalnum (fourstr[i]))
13932       fourstr[i] = '_';
13933   }
13934   s = g_strdup_printf ("%s/x-gst-fourcc-%s", type, g_strstrip (fourstr));
13935   caps = gst_caps_new_empty_simple (s);
13936   g_free (s);
13937   return caps;
13938 }
13939
13940 #define _codec(name) \
13941   do { \
13942     if (codec_name) { \
13943       *codec_name = g_strdup (name); \
13944     } \
13945   } while (0)
13946
13947 static GstCaps *
13948 qtdemux_video_caps (GstQTDemux * qtdemux, QtDemuxStream * stream,
13949     QtDemuxStreamStsdEntry * entry, guint32 fourcc,
13950     const guint8 * stsd_entry_data, gchar ** codec_name)
13951 {
13952   GstCaps *caps = NULL;
13953   GstVideoFormat format = GST_VIDEO_FORMAT_UNKNOWN;
13954
13955   switch (fourcc) {
13956     case FOURCC_png:
13957       _codec ("PNG still images");
13958       caps = gst_caps_new_empty_simple ("image/png");
13959       break;
13960     case FOURCC_jpeg:
13961       _codec ("JPEG still images");
13962       caps =
13963           gst_caps_new_simple ("image/jpeg", "parsed", G_TYPE_BOOLEAN, TRUE,
13964           NULL);
13965       break;
13966     case GST_MAKE_FOURCC ('m', 'j', 'p', 'a'):
13967     case GST_MAKE_FOURCC ('A', 'V', 'D', 'J'):
13968     case GST_MAKE_FOURCC ('M', 'J', 'P', 'G'):
13969     case GST_MAKE_FOURCC ('d', 'm', 'b', '1'):
13970       _codec ("Motion-JPEG");
13971       caps =
13972           gst_caps_new_simple ("image/jpeg", "parsed", G_TYPE_BOOLEAN, TRUE,
13973           NULL);
13974       break;
13975     case GST_MAKE_FOURCC ('m', 'j', 'p', 'b'):
13976       _codec ("Motion-JPEG format B");
13977       caps = gst_caps_new_empty_simple ("video/x-mjpeg-b");
13978       break;
13979     case FOURCC_mjp2:
13980       _codec ("JPEG-2000");
13981       /* override to what it should be according to spec, avoid palette_data */
13982       entry->bits_per_sample = 24;
13983       caps = gst_caps_new_simple ("image/x-j2c", "fields", G_TYPE_INT, 1, NULL);
13984       break;
13985     case FOURCC_SVQ3:
13986       _codec ("Sorensen video v.3");
13987       caps = gst_caps_new_simple ("video/x-svq",
13988           "svqversion", G_TYPE_INT, 3, NULL);
13989       break;
13990     case GST_MAKE_FOURCC ('s', 'v', 'q', 'i'):
13991     case GST_MAKE_FOURCC ('S', 'V', 'Q', '1'):
13992       _codec ("Sorensen video v.1");
13993       caps = gst_caps_new_simple ("video/x-svq",
13994           "svqversion", G_TYPE_INT, 1, NULL);
13995       break;
13996     case GST_MAKE_FOURCC ('W', 'R', 'A', 'W'):
13997       caps = gst_caps_new_empty_simple ("video/x-raw");
13998       gst_caps_set_simple (caps, "format", G_TYPE_STRING, "RGB8P", NULL);
13999       _codec ("Windows Raw RGB");
14000       stream->alignment = 32;
14001       break;
14002     case FOURCC_raw_:
14003     {
14004       guint16 bps;
14005
14006       bps = QT_UINT16 (stsd_entry_data + 82);
14007       switch (bps) {
14008         case 15:
14009           format = GST_VIDEO_FORMAT_RGB15;
14010           break;
14011         case 16:
14012           format = GST_VIDEO_FORMAT_RGB16;
14013           break;
14014         case 24:
14015           format = GST_VIDEO_FORMAT_RGB;
14016           break;
14017         case 32:
14018           format = GST_VIDEO_FORMAT_ARGB;
14019           break;
14020         default:
14021           /* unknown */
14022           break;
14023       }
14024       break;
14025     }
14026     case GST_MAKE_FOURCC ('y', 'v', '1', '2'):
14027       format = GST_VIDEO_FORMAT_I420;
14028       break;
14029     case GST_MAKE_FOURCC ('y', 'u', 'v', '2'):
14030     case GST_MAKE_FOURCC ('Y', 'u', 'v', '2'):
14031       format = GST_VIDEO_FORMAT_I420;
14032       break;
14033     case FOURCC_2vuy:
14034     case GST_MAKE_FOURCC ('2', 'V', 'u', 'y'):
14035       format = GST_VIDEO_FORMAT_UYVY;
14036       break;
14037     case GST_MAKE_FOURCC ('v', '3', '0', '8'):
14038       format = GST_VIDEO_FORMAT_v308;
14039       break;
14040     case GST_MAKE_FOURCC ('v', '2', '1', '6'):
14041       format = GST_VIDEO_FORMAT_v216;
14042       break;
14043     case FOURCC_v210:
14044       format = GST_VIDEO_FORMAT_v210;
14045       break;
14046     case GST_MAKE_FOURCC ('r', '2', '1', '0'):
14047       format = GST_VIDEO_FORMAT_r210;
14048       break;
14049       /* Packed YUV 4:4:4 10 bit in 32 bits, complex
14050          case GST_MAKE_FOURCC ('v', '4', '1', '0'):
14051          format = GST_VIDEO_FORMAT_v410;
14052          break;
14053        */
14054       /* Packed YUV 4:4:4:4 8 bit in 32 bits
14055        * but different order than AYUV
14056        case GST_MAKE_FOURCC ('v', '4', '0', '8'):
14057        format = GST_VIDEO_FORMAT_v408;
14058        break;
14059        */
14060     case GST_MAKE_FOURCC ('m', 'p', 'e', 'g'):
14061     case GST_MAKE_FOURCC ('m', 'p', 'g', '1'):
14062       _codec ("MPEG-1 video");
14063       caps = gst_caps_new_simple ("video/mpeg", "mpegversion", G_TYPE_INT, 1,
14064           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
14065       break;
14066     case GST_MAKE_FOURCC ('h', 'd', 'v', '1'): /* HDV 720p30 */
14067     case GST_MAKE_FOURCC ('h', 'd', 'v', '2'): /* HDV 1080i60 */
14068     case GST_MAKE_FOURCC ('h', 'd', 'v', '3'): /* HDV 1080i50 */
14069     case GST_MAKE_FOURCC ('h', 'd', 'v', '4'): /* HDV 720p24 */
14070     case GST_MAKE_FOURCC ('h', 'd', 'v', '5'): /* HDV 720p25 */
14071     case GST_MAKE_FOURCC ('h', 'd', 'v', '6'): /* HDV 1080p24 */
14072     case GST_MAKE_FOURCC ('h', 'd', 'v', '7'): /* HDV 1080p25 */
14073     case GST_MAKE_FOURCC ('h', 'd', 'v', '8'): /* HDV 1080p30 */
14074     case GST_MAKE_FOURCC ('h', 'd', 'v', '9'): /* HDV 720p60 */
14075     case GST_MAKE_FOURCC ('h', 'd', 'v', 'a'): /* HDV 720p50 */
14076     case GST_MAKE_FOURCC ('m', 'x', '5', 'n'): /* MPEG2 IMX NTSC 525/60 50mb/s produced by FCP */
14077     case GST_MAKE_FOURCC ('m', 'x', '5', 'p'): /* MPEG2 IMX PAL 625/60 50mb/s produced by FCP */
14078     case GST_MAKE_FOURCC ('m', 'x', '4', 'n'): /* MPEG2 IMX NTSC 525/60 40mb/s produced by FCP */
14079     case GST_MAKE_FOURCC ('m', 'x', '4', 'p'): /* MPEG2 IMX PAL 625/60 40mb/s produced by FCP */
14080     case GST_MAKE_FOURCC ('m', 'x', '3', 'n'): /* MPEG2 IMX NTSC 525/60 30mb/s produced by FCP */
14081     case GST_MAKE_FOURCC ('m', 'x', '3', 'p'): /* MPEG2 IMX PAL 625/50 30mb/s produced by FCP */
14082     case GST_MAKE_FOURCC ('x', 'd', 'v', '1'): /* XDCAM HD 720p30 35Mb/s */
14083     case GST_MAKE_FOURCC ('x', 'd', 'v', '2'): /* XDCAM HD 1080i60 35Mb/s */
14084     case GST_MAKE_FOURCC ('x', 'd', 'v', '3'): /* XDCAM HD 1080i50 35Mb/s */
14085     case GST_MAKE_FOURCC ('x', 'd', 'v', '4'): /* XDCAM HD 720p24 35Mb/s */
14086     case GST_MAKE_FOURCC ('x', 'd', 'v', '5'): /* XDCAM HD 720p25 35Mb/s */
14087     case GST_MAKE_FOURCC ('x', 'd', 'v', '6'): /* XDCAM HD 1080p24 35Mb/s */
14088     case GST_MAKE_FOURCC ('x', 'd', 'v', '7'): /* XDCAM HD 1080p25 35Mb/s */
14089     case GST_MAKE_FOURCC ('x', 'd', 'v', '8'): /* XDCAM HD 1080p30 35Mb/s */
14090     case GST_MAKE_FOURCC ('x', 'd', 'v', '9'): /* XDCAM HD 720p60 35Mb/s */
14091     case GST_MAKE_FOURCC ('x', 'd', 'v', 'a'): /* XDCAM HD 720p50 35Mb/s */
14092     case GST_MAKE_FOURCC ('x', 'd', 'v', 'b'): /* XDCAM EX 1080i60 50Mb/s CBR */
14093     case GST_MAKE_FOURCC ('x', 'd', 'v', 'c'): /* XDCAM EX 1080i50 50Mb/s CBR */
14094     case GST_MAKE_FOURCC ('x', 'd', 'v', 'd'): /* XDCAM HD 1080p24 50Mb/s CBR */
14095     case GST_MAKE_FOURCC ('x', 'd', 'v', 'e'): /* XDCAM HD 1080p25 50Mb/s CBR */
14096     case GST_MAKE_FOURCC ('x', 'd', 'v', 'f'): /* XDCAM HD 1080p30 50Mb/s CBR */
14097     case GST_MAKE_FOURCC ('x', 'd', '5', '1'): /* XDCAM HD422 720p30 50Mb/s CBR */
14098     case GST_MAKE_FOURCC ('x', 'd', '5', '4'): /* XDCAM HD422 720p24 50Mb/s CBR */
14099     case GST_MAKE_FOURCC ('x', 'd', '5', '5'): /* XDCAM HD422 720p25 50Mb/s CBR */
14100     case GST_MAKE_FOURCC ('x', 'd', '5', '9'): /* XDCAM HD422 720p60 50Mb/s CBR */
14101     case GST_MAKE_FOURCC ('x', 'd', '5', 'a'): /* XDCAM HD422 720p50 50Mb/s CBR */
14102     case GST_MAKE_FOURCC ('x', 'd', '5', 'b'): /* XDCAM HD422 1080i50 50Mb/s CBR */
14103     case GST_MAKE_FOURCC ('x', 'd', '5', 'c'): /* XDCAM HD422 1080i50 50Mb/s CBR */
14104     case GST_MAKE_FOURCC ('x', 'd', '5', 'd'): /* XDCAM HD422 1080p24 50Mb/s CBR */
14105     case GST_MAKE_FOURCC ('x', 'd', '5', 'e'): /* XDCAM HD422 1080p25 50Mb/s CBR */
14106     case GST_MAKE_FOURCC ('x', 'd', '5', 'f'): /* XDCAM HD422 1080p30 50Mb/s CBR */
14107     case GST_MAKE_FOURCC ('x', 'd', 'h', 'd'): /* XDCAM HD 540p */
14108     case GST_MAKE_FOURCC ('x', 'd', 'h', '2'): /* XDCAM HD422 540p */
14109     case GST_MAKE_FOURCC ('A', 'V', 'm', 'p'): /* AVID IMX PAL */
14110     case GST_MAKE_FOURCC ('m', 'p', 'g', '2'): /* AVID IMX PAL */
14111     case GST_MAKE_FOURCC ('m', 'p', '2', 'v'): /* AVID IMX PAL */
14112     case GST_MAKE_FOURCC ('m', '2', 'v', '1'):
14113       _codec ("MPEG-2 video");
14114       caps = gst_caps_new_simple ("video/mpeg", "mpegversion", G_TYPE_INT, 2,
14115           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
14116       break;
14117     case GST_MAKE_FOURCC ('g', 'i', 'f', ' '):
14118       _codec ("GIF still images");
14119       caps = gst_caps_new_empty_simple ("image/gif");
14120       break;
14121     case FOURCC_h263:
14122     case GST_MAKE_FOURCC ('H', '2', '6', '3'):
14123     case FOURCC_s263:
14124     case GST_MAKE_FOURCC ('U', '2', '6', '3'):
14125       _codec ("H.263");
14126       /* ffmpeg uses the height/width props, don't know why */
14127       caps = gst_caps_new_simple ("video/x-h263",
14128           "variant", G_TYPE_STRING, "itu", NULL);
14129       break;
14130     case FOURCC_mp4v:
14131     case FOURCC_MP4V:
14132       _codec ("MPEG-4 video");
14133       caps = gst_caps_new_simple ("video/mpeg", "mpegversion", G_TYPE_INT, 4,
14134           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
14135       break;
14136     case GST_MAKE_FOURCC ('3', 'i', 'v', 'd'):
14137     case GST_MAKE_FOURCC ('3', 'I', 'V', 'D'):
14138       _codec ("Microsoft MPEG-4 4.3");  /* FIXME? */
14139       caps = gst_caps_new_simple ("video/x-msmpeg",
14140           "msmpegversion", G_TYPE_INT, 43, NULL);
14141       break;
14142     case GST_MAKE_FOURCC ('D', 'I', 'V', '3'):
14143       _codec ("DivX 3");
14144       caps = gst_caps_new_simple ("video/x-divx",
14145           "divxversion", G_TYPE_INT, 3, NULL);
14146       break;
14147     case GST_MAKE_FOURCC ('D', 'I', 'V', 'X'):
14148     case GST_MAKE_FOURCC ('d', 'i', 'v', 'x'):
14149       _codec ("DivX 4");
14150       caps = gst_caps_new_simple ("video/x-divx",
14151           "divxversion", G_TYPE_INT, 4, NULL);
14152       break;
14153     case GST_MAKE_FOURCC ('D', 'X', '5', '0'):
14154       _codec ("DivX 5");
14155       caps = gst_caps_new_simple ("video/x-divx",
14156           "divxversion", G_TYPE_INT, 5, NULL);
14157       break;
14158
14159     case GST_MAKE_FOURCC ('F', 'F', 'V', '1'):
14160       _codec ("FFV1");
14161       caps = gst_caps_new_simple ("video/x-ffv",
14162           "ffvversion", G_TYPE_INT, 1, NULL);
14163       break;
14164
14165     case GST_MAKE_FOURCC ('3', 'I', 'V', '1'):
14166     case GST_MAKE_FOURCC ('3', 'I', 'V', '2'):
14167     case FOURCC_XVID:
14168     case FOURCC_xvid:
14169     case FOURCC_FMP4:
14170     case FOURCC_fmp4:
14171     case GST_MAKE_FOURCC ('U', 'M', 'P', '4'):
14172       caps = gst_caps_new_simple ("video/mpeg", "mpegversion", G_TYPE_INT, 4,
14173           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
14174       _codec ("MPEG-4");
14175       break;
14176
14177     case GST_MAKE_FOURCC ('c', 'v', 'i', 'd'):
14178       _codec ("Cinepak");
14179       caps = gst_caps_new_empty_simple ("video/x-cinepak");
14180       break;
14181     case GST_MAKE_FOURCC ('q', 'd', 'r', 'w'):
14182       _codec ("Apple QuickDraw");
14183       caps = gst_caps_new_empty_simple ("video/x-qdrw");
14184       break;
14185     case GST_MAKE_FOURCC ('r', 'p', 'z', 'a'):
14186       _codec ("Apple video");
14187       caps = gst_caps_new_empty_simple ("video/x-apple-video");
14188       break;
14189     case FOURCC_H264:
14190     case FOURCC_avc1:
14191       _codec ("H.264 / AVC");
14192       caps = gst_caps_new_simple ("video/x-h264",
14193           "stream-format", G_TYPE_STRING, "avc",
14194           "alignment", G_TYPE_STRING, "au", NULL);
14195       break;
14196     case FOURCC_avc3:
14197       _codec ("H.264 / AVC");
14198       caps = gst_caps_new_simple ("video/x-h264",
14199           "stream-format", G_TYPE_STRING, "avc3",
14200           "alignment", G_TYPE_STRING, "au", NULL);
14201       break;
14202     case FOURCC_H265:
14203     case FOURCC_hvc1:
14204       _codec ("H.265 / HEVC");
14205       caps = gst_caps_new_simple ("video/x-h265",
14206           "stream-format", G_TYPE_STRING, "hvc1",
14207           "alignment", G_TYPE_STRING, "au", NULL);
14208       break;
14209     case FOURCC_hev1:
14210       _codec ("H.265 / HEVC");
14211       caps = gst_caps_new_simple ("video/x-h265",
14212           "stream-format", G_TYPE_STRING, "hev1",
14213           "alignment", G_TYPE_STRING, "au", NULL);
14214       break;
14215     case FOURCC_rle_:
14216       _codec ("Run-length encoding");
14217       caps = gst_caps_new_simple ("video/x-rle",
14218           "layout", G_TYPE_STRING, "quicktime", NULL);
14219       break;
14220     case FOURCC_WRLE:
14221       _codec ("Run-length encoding");
14222       caps = gst_caps_new_simple ("video/x-rle",
14223           "layout", G_TYPE_STRING, "microsoft", NULL);
14224       break;
14225     case GST_MAKE_FOURCC ('I', 'V', '3', '2'):
14226     case GST_MAKE_FOURCC ('i', 'v', '3', '2'):
14227       _codec ("Indeo Video 3");
14228       caps = gst_caps_new_simple ("video/x-indeo",
14229           "indeoversion", G_TYPE_INT, 3, NULL);
14230       break;
14231     case GST_MAKE_FOURCC ('I', 'V', '4', '1'):
14232     case GST_MAKE_FOURCC ('i', 'v', '4', '1'):
14233       _codec ("Intel Video 4");
14234       caps = gst_caps_new_simple ("video/x-indeo",
14235           "indeoversion", G_TYPE_INT, 4, NULL);
14236       break;
14237     case FOURCC_dvcp:
14238     case FOURCC_dvc_:
14239     case GST_MAKE_FOURCC ('d', 'v', 's', 'd'):
14240     case GST_MAKE_FOURCC ('D', 'V', 'S', 'D'):
14241     case GST_MAKE_FOURCC ('d', 'v', 'c', 's'):
14242     case GST_MAKE_FOURCC ('D', 'V', 'C', 'S'):
14243     case GST_MAKE_FOURCC ('d', 'v', '2', '5'):
14244     case GST_MAKE_FOURCC ('d', 'v', 'p', 'p'):
14245       _codec ("DV Video");
14246       caps = gst_caps_new_simple ("video/x-dv", "dvversion", G_TYPE_INT, 25,
14247           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
14248       break;
14249     case FOURCC_dv5n:          /* DVCPRO50 NTSC */
14250     case FOURCC_dv5p:          /* DVCPRO50 PAL */
14251       _codec ("DVCPro50 Video");
14252       caps = gst_caps_new_simple ("video/x-dv", "dvversion", G_TYPE_INT, 50,
14253           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
14254       break;
14255     case GST_MAKE_FOURCC ('d', 'v', 'h', '5'): /* DVCPRO HD 50i produced by FCP */
14256     case GST_MAKE_FOURCC ('d', 'v', 'h', '6'): /* DVCPRO HD 60i produced by FCP */
14257       _codec ("DVCProHD Video");
14258       caps = gst_caps_new_simple ("video/x-dv", "dvversion", G_TYPE_INT, 100,
14259           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
14260       break;
14261     case GST_MAKE_FOURCC ('s', 'm', 'c', ' '):
14262       _codec ("Apple Graphics (SMC)");
14263       caps = gst_caps_new_empty_simple ("video/x-smc");
14264       break;
14265     case GST_MAKE_FOURCC ('V', 'P', '3', '1'):
14266       _codec ("VP3");
14267       caps = gst_caps_new_empty_simple ("video/x-vp3");
14268       break;
14269     case GST_MAKE_FOURCC ('V', 'P', '6', 'F'):
14270       _codec ("VP6 Flash");
14271       caps = gst_caps_new_empty_simple ("video/x-vp6-flash");
14272       break;
14273     case FOURCC_XiTh:
14274       _codec ("Theora");
14275       caps = gst_caps_new_empty_simple ("video/x-theora");
14276       /* theora uses one byte of padding in the data stream because it does not
14277        * allow 0 sized packets while theora does */
14278       entry->padding = 1;
14279       break;
14280     case FOURCC_drac:
14281       _codec ("Dirac");
14282       caps = gst_caps_new_empty_simple ("video/x-dirac");
14283       break;
14284     case GST_MAKE_FOURCC ('t', 'i', 'f', 'f'):
14285       _codec ("TIFF still images");
14286       caps = gst_caps_new_empty_simple ("image/tiff");
14287       break;
14288     case GST_MAKE_FOURCC ('i', 'c', 'o', 'd'):
14289       _codec ("Apple Intermediate Codec");
14290       caps = gst_caps_from_string ("video/x-apple-intermediate-codec");
14291       break;
14292     case GST_MAKE_FOURCC ('A', 'V', 'd', 'n'):
14293       _codec ("AVID DNxHD");
14294       caps = gst_caps_from_string ("video/x-dnxhd");
14295       break;
14296     case FOURCC_VP80:
14297     case FOURCC_vp08:
14298       _codec ("On2 VP8");
14299       caps = gst_caps_from_string ("video/x-vp8");
14300       break;
14301     case FOURCC_vp09:
14302       _codec ("Google VP9");
14303       caps = gst_caps_from_string ("video/x-vp9");
14304       break;
14305     case FOURCC_apcs:
14306       _codec ("Apple ProRes LT");
14307       caps =
14308           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING, "lt",
14309           NULL);
14310       break;
14311     case FOURCC_apch:
14312       _codec ("Apple ProRes HQ");
14313       caps =
14314           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING, "hq",
14315           NULL);
14316       break;
14317     case FOURCC_apcn:
14318       _codec ("Apple ProRes");
14319       caps =
14320           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING,
14321           "standard", NULL);
14322       break;
14323     case FOURCC_apco:
14324       _codec ("Apple ProRes Proxy");
14325       caps =
14326           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING,
14327           "proxy", NULL);
14328       break;
14329     case FOURCC_ap4h:
14330       _codec ("Apple ProRes 4444");
14331       caps =
14332           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING,
14333           "4444", NULL);
14334       break;
14335     case FOURCC_ap4x:
14336       _codec ("Apple ProRes 4444 XQ");
14337       caps =
14338           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING,
14339           "4444xq", NULL);
14340       break;
14341     case FOURCC_cfhd:
14342       _codec ("GoPro CineForm");
14343       caps = gst_caps_from_string ("video/x-cineform");
14344       break;
14345     case FOURCC_vc_1:
14346     case FOURCC_ovc1:
14347       _codec ("VC-1");
14348       caps = gst_caps_new_simple ("video/x-wmv",
14349           "wmvversion", G_TYPE_INT, 3, "format", G_TYPE_STRING, "WVC1", NULL);
14350       break;
14351     case GST_MAKE_FOURCC ('k', 'p', 'c', 'd'):
14352     default:
14353     {
14354       caps = _get_unknown_codec_name ("video", fourcc);
14355       break;
14356     }
14357   }
14358
14359   if (format != GST_VIDEO_FORMAT_UNKNOWN) {
14360     GstVideoInfo info;
14361
14362     gst_video_info_init (&info);
14363     gst_video_info_set_format (&info, format, entry->width, entry->height);
14364
14365     caps = gst_video_info_to_caps (&info);
14366     *codec_name = gst_pb_utils_get_codec_description (caps);
14367
14368     /* enable clipping for raw video streams */
14369     stream->need_clip = TRUE;
14370     stream->alignment = 32;
14371   }
14372
14373   return caps;
14374 }
14375
14376 static guint
14377 round_up_pow2 (guint n)
14378 {
14379   n = n - 1;
14380   n = n | (n >> 1);
14381   n = n | (n >> 2);
14382   n = n | (n >> 4);
14383   n = n | (n >> 8);
14384   n = n | (n >> 16);
14385   return n + 1;
14386 }
14387
14388 static GstCaps *
14389 qtdemux_audio_caps (GstQTDemux * qtdemux, QtDemuxStream * stream,
14390     QtDemuxStreamStsdEntry * entry, guint32 fourcc, const guint8 * data,
14391     int len, gchar ** codec_name)
14392 {
14393   GstCaps *caps;
14394   const GstStructure *s;
14395   const gchar *name;
14396   gint endian = 0;
14397   GstAudioFormat format = 0;
14398   gint depth;
14399
14400   GST_DEBUG_OBJECT (qtdemux, "resolve fourcc 0x%08x", GUINT32_TO_BE (fourcc));
14401
14402   depth = entry->bytes_per_packet * 8;
14403
14404   switch (fourcc) {
14405     case GST_MAKE_FOURCC ('N', 'O', 'N', 'E'):
14406     case FOURCC_raw_:
14407       /* 8-bit audio is unsigned */
14408       if (depth == 8)
14409         format = GST_AUDIO_FORMAT_U8;
14410       /* otherwise it's signed and big-endian just like 'twos' */
14411     case FOURCC_twos:
14412       endian = G_BIG_ENDIAN;
14413       /* fall-through */
14414     case FOURCC_sowt:
14415     {
14416       gchar *str;
14417
14418       if (!endian)
14419         endian = G_LITTLE_ENDIAN;
14420
14421       if (!format)
14422         format = gst_audio_format_build_integer (TRUE, endian, depth, depth);
14423
14424       str = g_strdup_printf ("Raw %d-bit PCM audio", depth);
14425       _codec (str);
14426       g_free (str);
14427
14428       caps = gst_caps_new_simple ("audio/x-raw",
14429           "format", G_TYPE_STRING, gst_audio_format_to_string (format),
14430           "layout", G_TYPE_STRING, "interleaved", NULL);
14431       stream->alignment = GST_ROUND_UP_8 (depth);
14432       stream->alignment = round_up_pow2 (stream->alignment);
14433       break;
14434     }
14435     case GST_MAKE_FOURCC ('f', 'l', '6', '4'):
14436       _codec ("Raw 64-bit floating-point audio");
14437       caps = gst_caps_new_simple ("audio/x-raw",
14438           "format", G_TYPE_STRING, "F64BE",
14439           "layout", G_TYPE_STRING, "interleaved", NULL);
14440       stream->alignment = 8;
14441       break;
14442     case GST_MAKE_FOURCC ('f', 'l', '3', '2'):
14443       _codec ("Raw 32-bit floating-point audio");
14444       caps = gst_caps_new_simple ("audio/x-raw",
14445           "format", G_TYPE_STRING, "F32BE",
14446           "layout", G_TYPE_STRING, "interleaved", NULL);
14447       stream->alignment = 4;
14448       break;
14449     case FOURCC_in24:
14450       _codec ("Raw 24-bit PCM audio");
14451       /* we assume BIG ENDIAN, an enda box will tell us to change this to little
14452        * endian later */
14453       caps = gst_caps_new_simple ("audio/x-raw",
14454           "format", G_TYPE_STRING, "S24BE",
14455           "layout", G_TYPE_STRING, "interleaved", NULL);
14456       stream->alignment = 4;
14457       break;
14458     case GST_MAKE_FOURCC ('i', 'n', '3', '2'):
14459       _codec ("Raw 32-bit PCM audio");
14460       caps = gst_caps_new_simple ("audio/x-raw",
14461           "format", G_TYPE_STRING, "S32BE",
14462           "layout", G_TYPE_STRING, "interleaved", NULL);
14463       stream->alignment = 4;
14464       break;
14465     case GST_MAKE_FOURCC ('s', '1', '6', 'l'):
14466       _codec ("Raw 16-bit PCM audio");
14467       caps = gst_caps_new_simple ("audio/x-raw",
14468           "format", G_TYPE_STRING, "S16LE",
14469           "layout", G_TYPE_STRING, "interleaved", NULL);
14470       stream->alignment = 2;
14471       break;
14472     case FOURCC_ulaw:
14473       _codec ("Mu-law audio");
14474       caps = gst_caps_new_empty_simple ("audio/x-mulaw");
14475       break;
14476     case FOURCC_alaw:
14477       _codec ("A-law audio");
14478       caps = gst_caps_new_empty_simple ("audio/x-alaw");
14479       break;
14480     case 0x0200736d:
14481     case 0x6d730002:
14482       _codec ("Microsoft ADPCM");
14483       /* Microsoft ADPCM-ACM code 2 */
14484       caps = gst_caps_new_simple ("audio/x-adpcm",
14485           "layout", G_TYPE_STRING, "microsoft", NULL);
14486       break;
14487     case 0x1100736d:
14488     case 0x6d730011:
14489       _codec ("DVI/IMA ADPCM");
14490       caps = gst_caps_new_simple ("audio/x-adpcm",
14491           "layout", G_TYPE_STRING, "dvi", NULL);
14492       break;
14493     case 0x1700736d:
14494     case 0x6d730017:
14495       _codec ("DVI/Intel IMA ADPCM");
14496       /* FIXME DVI/Intel IMA ADPCM/ACM code 17 */
14497       caps = gst_caps_new_simple ("audio/x-adpcm",
14498           "layout", G_TYPE_STRING, "quicktime", NULL);
14499       break;
14500     case 0x5500736d:
14501     case 0x6d730055:
14502       /* MPEG layer 3, CBR only (pre QT4.1) */
14503     case FOURCC__mp3:
14504       _codec ("MPEG-1 layer 3");
14505       /* MPEG layer 3, CBR & VBR (QT4.1 and later) */
14506       caps = gst_caps_new_simple ("audio/mpeg", "layer", G_TYPE_INT, 3,
14507           "mpegversion", G_TYPE_INT, 1, NULL);
14508       break;
14509     case GST_MAKE_FOURCC ('.', 'm', 'p', '2'):
14510       _codec ("MPEG-1 layer 2");
14511       /* MPEG layer 2 */
14512       caps = gst_caps_new_simple ("audio/mpeg", "layer", G_TYPE_INT, 2,
14513           "mpegversion", G_TYPE_INT, 1, NULL);
14514       break;
14515     case 0x20736d:
14516     case GST_MAKE_FOURCC ('e', 'c', '-', '3'):
14517       _codec ("EAC-3 audio");
14518       caps = gst_caps_new_simple ("audio/x-eac3",
14519           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
14520       entry->sampled = TRUE;
14521       break;
14522     case GST_MAKE_FOURCC ('s', 'a', 'c', '3'): // Nero Recode
14523     case FOURCC_ac_3:
14524       _codec ("AC-3 audio");
14525       caps = gst_caps_new_simple ("audio/x-ac3",
14526           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
14527       entry->sampled = TRUE;
14528       break;
14529     case GST_MAKE_FOURCC ('d', 't', 's', 'c'):
14530     case GST_MAKE_FOURCC ('D', 'T', 'S', ' '):
14531       _codec ("DTS audio");
14532       caps = gst_caps_new_simple ("audio/x-dts",
14533           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
14534       entry->sampled = TRUE;
14535       break;
14536     case GST_MAKE_FOURCC ('d', 't', 's', 'h'): // DTS-HD
14537     case GST_MAKE_FOURCC ('d', 't', 's', 'l'): // DTS-HD Lossless
14538       _codec ("DTS-HD audio");
14539       caps = gst_caps_new_simple ("audio/x-dts",
14540           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
14541       entry->sampled = TRUE;
14542       break;
14543     case FOURCC_MAC3:
14544       _codec ("MACE-3");
14545       caps = gst_caps_new_simple ("audio/x-mace",
14546           "maceversion", G_TYPE_INT, 3, NULL);
14547       break;
14548     case FOURCC_MAC6:
14549       _codec ("MACE-6");
14550       caps = gst_caps_new_simple ("audio/x-mace",
14551           "maceversion", G_TYPE_INT, 6, NULL);
14552       break;
14553     case GST_MAKE_FOURCC ('O', 'g', 'g', 'V'):
14554       /* ogg/vorbis */
14555       caps = gst_caps_new_empty_simple ("application/ogg");
14556       break;
14557     case GST_MAKE_FOURCC ('d', 'v', 'c', 'a'):
14558       _codec ("DV audio");
14559       caps = gst_caps_new_empty_simple ("audio/x-dv");
14560       break;
14561     case FOURCC_mp4a:
14562       _codec ("MPEG-4 AAC audio");
14563       caps = gst_caps_new_simple ("audio/mpeg",
14564           "mpegversion", G_TYPE_INT, 4, "framed", G_TYPE_BOOLEAN, TRUE,
14565           "stream-format", G_TYPE_STRING, "raw", NULL);
14566       break;
14567     case GST_MAKE_FOURCC ('Q', 'D', 'M', 'C'):
14568       _codec ("QDesign Music");
14569       caps = gst_caps_new_empty_simple ("audio/x-qdm");
14570       break;
14571     case FOURCC_QDM2:
14572       _codec ("QDesign Music v.2");
14573       /* FIXME: QDesign music version 2 (no constant) */
14574       if (FALSE && data) {
14575         caps = gst_caps_new_simple ("audio/x-qdm2",
14576             "framesize", G_TYPE_INT, QT_UINT32 (data + 52),
14577             "bitrate", G_TYPE_INT, QT_UINT32 (data + 40),
14578             "blocksize", G_TYPE_INT, QT_UINT32 (data + 44), NULL);
14579       } else {
14580         caps = gst_caps_new_empty_simple ("audio/x-qdm2");
14581       }
14582       break;
14583     case FOURCC_agsm:
14584       _codec ("GSM audio");
14585       caps = gst_caps_new_empty_simple ("audio/x-gsm");
14586       break;
14587     case FOURCC_samr:
14588       _codec ("AMR audio");
14589       caps = gst_caps_new_empty_simple ("audio/AMR");
14590       break;
14591     case FOURCC_sawb:
14592       _codec ("AMR-WB audio");
14593       caps = gst_caps_new_empty_simple ("audio/AMR-WB");
14594       break;
14595     case FOURCC_ima4:
14596       _codec ("Quicktime IMA ADPCM");
14597       caps = gst_caps_new_simple ("audio/x-adpcm",
14598           "layout", G_TYPE_STRING, "quicktime", NULL);
14599       break;
14600     case FOURCC_alac:
14601       _codec ("Apple lossless audio");
14602       caps = gst_caps_new_empty_simple ("audio/x-alac");
14603       break;
14604     case FOURCC_fLaC:
14605       _codec ("Free Lossless Audio Codec");
14606       caps = gst_caps_new_simple ("audio/x-flac",
14607           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
14608       break;
14609     case GST_MAKE_FOURCC ('Q', 'c', 'l', 'p'):
14610       _codec ("QualComm PureVoice");
14611       caps = gst_caps_from_string ("audio/qcelp");
14612       break;
14613     case FOURCC_wma_:
14614     case FOURCC_owma:
14615       _codec ("WMA");
14616       caps = gst_caps_new_empty_simple ("audio/x-wma");
14617       break;
14618     case FOURCC_opus:
14619       _codec ("Opus");
14620       caps = gst_caps_new_empty_simple ("audio/x-opus");
14621       break;
14622     case FOURCC_lpcm:
14623     {
14624       guint32 flags = 0;
14625       guint32 depth = 0;
14626       guint32 width = 0;
14627       GstAudioFormat format;
14628       enum
14629       {
14630         FLAG_IS_FLOAT = 0x1,
14631         FLAG_IS_BIG_ENDIAN = 0x2,
14632         FLAG_IS_SIGNED = 0x4,
14633         FLAG_IS_PACKED = 0x8,
14634         FLAG_IS_ALIGNED_HIGH = 0x10,
14635         FLAG_IS_NON_INTERLEAVED = 0x20
14636       };
14637       _codec ("Raw LPCM audio");
14638
14639       if (data && len >= 36) {
14640         depth = QT_UINT32 (data + 24);
14641         flags = QT_UINT32 (data + 28);
14642         width = QT_UINT32 (data + 32) * 8 / entry->n_channels;
14643       }
14644       if ((flags & FLAG_IS_FLOAT) == 0) {
14645         if (depth == 0)
14646           depth = 16;
14647         if (width == 0)
14648           width = 16;
14649         if ((flags & FLAG_IS_ALIGNED_HIGH))
14650           depth = width;
14651
14652         format = gst_audio_format_build_integer ((flags & FLAG_IS_SIGNED) ?
14653             TRUE : FALSE, (flags & FLAG_IS_BIG_ENDIAN) ?
14654             G_BIG_ENDIAN : G_LITTLE_ENDIAN, width, depth);
14655         caps = gst_caps_new_simple ("audio/x-raw",
14656             "format", G_TYPE_STRING,
14657             format !=
14658             GST_AUDIO_FORMAT_UNKNOWN ? gst_audio_format_to_string (format) :
14659             "UNKNOWN", "layout", G_TYPE_STRING,
14660             (flags & FLAG_IS_NON_INTERLEAVED) ? "non-interleaved" :
14661             "interleaved", NULL);
14662         stream->alignment = GST_ROUND_UP_8 (depth);
14663         stream->alignment = round_up_pow2 (stream->alignment);
14664       } else {
14665         if (width == 0)
14666           width = 32;
14667         if (width == 64) {
14668           if (flags & FLAG_IS_BIG_ENDIAN)
14669             format = GST_AUDIO_FORMAT_F64BE;
14670           else
14671             format = GST_AUDIO_FORMAT_F64LE;
14672         } else {
14673           if (flags & FLAG_IS_BIG_ENDIAN)
14674             format = GST_AUDIO_FORMAT_F32BE;
14675           else
14676             format = GST_AUDIO_FORMAT_F32LE;
14677         }
14678         caps = gst_caps_new_simple ("audio/x-raw",
14679             "format", G_TYPE_STRING, gst_audio_format_to_string (format),
14680             "layout", G_TYPE_STRING, (flags & FLAG_IS_NON_INTERLEAVED) ?
14681             "non-interleaved" : "interleaved", NULL);
14682         stream->alignment = width / 8;
14683       }
14684       break;
14685     }
14686     case GST_MAKE_FOURCC ('q', 't', 'v', 'r'):
14687       /* ? */
14688     default:
14689     {
14690       caps = _get_unknown_codec_name ("audio", fourcc);
14691       break;
14692     }
14693   }
14694
14695   if (caps) {
14696     GstCaps *templ_caps =
14697         gst_static_pad_template_get_caps (&gst_qtdemux_audiosrc_template);
14698     GstCaps *intersection = gst_caps_intersect (caps, templ_caps);
14699     gst_caps_unref (caps);
14700     gst_caps_unref (templ_caps);
14701     caps = intersection;
14702   }
14703
14704   /* enable clipping for raw audio streams */
14705   s = gst_caps_get_structure (caps, 0);
14706   name = gst_structure_get_name (s);
14707   if (g_str_has_prefix (name, "audio/x-raw")) {
14708     stream->need_clip = TRUE;
14709     stream->max_buffer_size = 4096 * entry->bytes_per_frame;
14710     GST_DEBUG ("setting max buffer size to %d", stream->max_buffer_size);
14711   }
14712   return caps;
14713 }
14714
14715 static GstCaps *
14716 qtdemux_sub_caps (GstQTDemux * qtdemux, QtDemuxStream * stream,
14717     QtDemuxStreamStsdEntry * entry, guint32 fourcc,
14718     const guint8 * stsd_entry_data, gchar ** codec_name)
14719 {
14720   GstCaps *caps;
14721
14722   GST_DEBUG_OBJECT (qtdemux, "resolve fourcc 0x%08x", GUINT32_TO_BE (fourcc));
14723
14724   switch (fourcc) {
14725     case FOURCC_mp4s:
14726       _codec ("DVD subtitle");
14727       caps = gst_caps_new_empty_simple ("subpicture/x-dvd");
14728       stream->need_process = TRUE;
14729       break;
14730     case FOURCC_text:
14731       _codec ("Quicktime timed text");
14732       goto text;
14733     case FOURCC_tx3g:
14734       _codec ("3GPP timed text");
14735     text:
14736       caps = gst_caps_new_simple ("text/x-raw", "format", G_TYPE_STRING,
14737           "utf8", NULL);
14738       /* actual text piece needs to be extracted */
14739       stream->need_process = TRUE;
14740       break;
14741     case FOURCC_stpp:
14742       _codec ("XML subtitles");
14743       caps = gst_caps_new_empty_simple ("application/ttml+xml");
14744       break;
14745     case FOURCC_c608:
14746       _codec ("CEA 608 Closed Caption");
14747       caps =
14748           gst_caps_new_simple ("closedcaption/x-cea-608", "format",
14749           G_TYPE_STRING, "cc_data", NULL);
14750       stream->need_process = TRUE;
14751       break;
14752     case FOURCC_c708:
14753       _codec ("CEA 708 Closed Caption");
14754       caps =
14755           gst_caps_new_simple ("closedcaption/x-cea-708", "format",
14756           G_TYPE_STRING, "cdp", NULL);
14757       stream->need_process = TRUE;
14758       break;
14759
14760     default:
14761     {
14762       caps = _get_unknown_codec_name ("text", fourcc);
14763       break;
14764     }
14765   }
14766   return caps;
14767 }
14768
14769 static GstCaps *
14770 qtdemux_generic_caps (GstQTDemux * qtdemux, QtDemuxStream * stream,
14771     QtDemuxStreamStsdEntry * entry, guint32 fourcc,
14772     const guint8 * stsd_entry_data, gchar ** codec_name)
14773 {
14774   GstCaps *caps;
14775
14776   switch (fourcc) {
14777     case FOURCC_m1v:
14778       _codec ("MPEG 1 video");
14779       caps = gst_caps_new_simple ("video/mpeg", "mpegversion", G_TYPE_INT, 1,
14780           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
14781       break;
14782     default:
14783       caps = NULL;
14784       break;
14785   }
14786   return caps;
14787 }
14788
14789 static void
14790 gst_qtdemux_append_protection_system_id (GstQTDemux * qtdemux,
14791     const gchar * system_id)
14792 {
14793   gint i;
14794
14795   if (!qtdemux->protection_system_ids)
14796     qtdemux->protection_system_ids =
14797         g_ptr_array_new_with_free_func ((GDestroyNotify) g_free);
14798   /* Check whether we already have an entry for this system ID. */
14799   for (i = 0; i < qtdemux->protection_system_ids->len; ++i) {
14800     const gchar *id = g_ptr_array_index (qtdemux->protection_system_ids, i);
14801     if (g_ascii_strcasecmp (system_id, id) == 0) {
14802       return;
14803     }
14804   }
14805   GST_DEBUG_OBJECT (qtdemux, "Adding cenc protection system ID %s", system_id);
14806   g_ptr_array_add (qtdemux->protection_system_ids, g_ascii_strdown (system_id,
14807           -1));
14808 }