7d9dc5b6c4965bbca46eb4bbd8a023aa9b2dfd7f
[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 #include <gst/riff/riff.h>
60 #include <gst/pbutils/pbutils.h>
61
62 #include "qtatomparser.h"
63 #include "qtdemux_types.h"
64 #include "qtdemux_dump.h"
65 #include "fourcc.h"
66 #include "descriptors.h"
67 #include "qtdemux_lang.h"
68 #include "qtdemux.h"
69 #include "qtpalette.h"
70
71 #include <stdio.h>
72 #include <stdlib.h>
73 #include <string.h>
74
75 #include <math.h>
76 #include <gst/math-compat.h>
77
78 #ifdef HAVE_ZLIB
79 # include <zlib.h>
80 #endif
81
82 /* max. size considered 'sane' for non-mdat atoms */
83 #define QTDEMUX_MAX_ATOM_SIZE (25*1024*1024)
84
85 /* if the sample index is larger than this, something is likely wrong */
86 #define QTDEMUX_MAX_SAMPLE_INDEX_SIZE (200*1024*1024)
87
88 /* For converting qt creation times to unix epoch times */
89 #define QTDEMUX_SECONDS_PER_DAY (60 * 60 * 24)
90 #define QTDEMUX_LEAP_YEARS_FROM_1904_TO_1970 17
91 #define QTDEMUX_SECONDS_FROM_1904_TO_1970 (((1970 - 1904) * (guint64) 365 + \
92     QTDEMUX_LEAP_YEARS_FROM_1904_TO_1970) * QTDEMUX_SECONDS_PER_DAY)
93
94 #define QTDEMUX_TREE_NODE_FOURCC(n) (QT_FOURCC(((guint8 *) (n)->data) + 4))
95
96 #define STREAM_IS_EOS(s) ((s)->time_position == GST_CLOCK_TIME_NONE)
97
98 #define ABSDIFF(x, y) ( (x) > (y) ? ((x) - (y)) : ((y) - (x)) )
99
100 #define QTDEMUX_FIRST_STREAM(demux) ((QtDemuxStream *)(demux)->active_streams \
101   ? (QtDemuxStream *)(demux)->active_streams->data : NULL)
102 #define QTDEMUX_STREAM(s) ((QtDemuxStream *)(s))
103
104 GST_DEBUG_CATEGORY (qtdemux_debug);
105 #define GST_CAT_DEFAULT qtdemux_debug
106
107 typedef struct _QtDemuxSegment QtDemuxSegment;
108 typedef struct _QtDemuxSample QtDemuxSample;
109
110 typedef struct _QtDemuxCencSampleSetInfo QtDemuxCencSampleSetInfo;
111
112 struct _QtDemuxSample
113 {
114   guint32 size;
115   gint32 pts_offset;            /* Add this value to timestamp to get the pts */
116   guint64 offset;
117   guint64 timestamp;            /* DTS In mov time */
118   guint32 duration;             /* In mov time */
119   gboolean keyframe;            /* TRUE when this packet is a keyframe */
120 };
121
122 /* Macros for converting to/from timescale */
123 #define QTSTREAMTIME_TO_GSTTIME(stream, value) (gst_util_uint64_scale((value), GST_SECOND, (stream)->timescale))
124 #define GSTTIME_TO_QTSTREAMTIME(stream, value) (gst_util_uint64_scale((value), (stream)->timescale, GST_SECOND))
125
126 #define QTTIME_TO_GSTTIME(qtdemux, value) (gst_util_uint64_scale((value), GST_SECOND, (qtdemux)->timescale))
127 #define GSTTIME_TO_QTTIME(qtdemux, value) (gst_util_uint64_scale((value), (qtdemux)->timescale, GST_SECOND))
128
129 /* timestamp is the DTS */
130 #define QTSAMPLE_DTS(stream,sample) (QTSTREAMTIME_TO_GSTTIME((stream), (sample)->timestamp))
131 /* timestamp + offset + cslg_shift is the outgoing PTS */
132 #define QTSAMPLE_PTS(stream,sample) (QTSTREAMTIME_TO_GSTTIME((stream), (sample)->timestamp + (stream)->cslg_shift + (sample)->pts_offset))
133 /* timestamp + offset is the PTS used for internal seek calcuations */
134 #define QTSAMPLE_PTS_NO_CSLG(stream,sample) (QTSTREAMTIME_TO_GSTTIME((stream), (sample)->timestamp + (sample)->pts_offset))
135 /* timestamp + duration - dts is the duration */
136 #define QTSAMPLE_DUR_DTS(stream, sample, dts) (QTSTREAMTIME_TO_GSTTIME ((stream), (sample)->timestamp + (sample)->duration) - (dts))
137
138 #define QTSAMPLE_KEYFRAME(stream,sample) ((stream)->all_keyframe || (sample)->keyframe)
139
140 #define QTDEMUX_EXPOSE_GET_LOCK(demux) (&((demux)->expose_lock))
141 #define QTDEMUX_EXPOSE_LOCK(demux) G_STMT_START { \
142     GST_TRACE("Locking from thread %p", g_thread_self()); \
143     g_mutex_lock (QTDEMUX_EXPOSE_GET_LOCK (demux)); \
144     GST_TRACE("Locked from thread %p", g_thread_self()); \
145  } G_STMT_END
146
147 #define QTDEMUX_EXPOSE_UNLOCK(demux) G_STMT_START { \
148     GST_TRACE("Unlocking from thread %p", g_thread_self()); \
149     g_mutex_unlock (QTDEMUX_EXPOSE_GET_LOCK (demux)); \
150  } G_STMT_END
151
152 /*
153  * Quicktime has tracks and segments. A track is a continuous piece of
154  * multimedia content. The track is not always played from start to finish but
155  * instead, pieces of the track are 'cut out' and played in sequence. This is
156  * what the segments do.
157  *
158  * Inside the track we have keyframes (K) and delta frames. The track has its
159  * own timing, which starts from 0 and extends to end. The position in the track
160  * is called the media_time.
161  *
162  * The segments now describe the pieces that should be played from this track
163  * and are basically tuples of media_time/duration/rate entries. We can have
164  * multiple segments and they are all played after one another. An example:
165  *
166  * segment 1: media_time: 1 second, duration: 1 second, rate 1
167  * segment 2: media_time: 3 second, duration: 2 second, rate 2
168  *
169  * To correctly play back this track, one must play: 1 second of media starting
170  * from media_time 1 followed by 2 seconds of media starting from media_time 3
171  * at a rate of 2.
172  *
173  * Each of the segments will be played at a specific time, the first segment at
174  * time 0, the second one after the duration of the first one, etc.. Note that
175  * the time in resulting playback is not identical to the media_time of the
176  * track anymore.
177  *
178  * Visually, assuming the track has 4 second of media_time:
179  *
180  *                (a)                   (b)          (c)              (d)
181  *         .-----------------------------------------------------------.
182  * track:  | K.....K.........K........K.......K.......K...........K... |
183  *         '-----------------------------------------------------------'
184  *         0              1              2              3              4
185  *           .------------^              ^   .----------^              ^
186  *          /              .-------------'  /       .------------------'
187  *         /              /          .-----'       /
188  *         .--------------.         .--------------.
189  *         | segment 1    |         | segment 2    |
190  *         '--------------'         '--------------'
191  *
192  * The challenge here is to cut out the right pieces of the track for each of
193  * the playback segments. This fortunately can easily be done with the SEGMENT
194  * events of GStreamer.
195  *
196  * For playback of segment 1, we need to provide the decoder with the keyframe
197  * (a), in the above figure, but we must instruct it only to output the decoded
198  * data between second 1 and 2. We do this with a SEGMENT event for 1 to 2, time
199  * position set to the time of the segment: 0.
200  *
201  * We then proceed to push data from keyframe (a) to frame (b). The decoder
202  * decodes but clips all before media_time 1.
203  *
204  * After finishing a segment, we push out a new SEGMENT event with the clipping
205  * boundaries of the new data.
206  *
207  * This is a good usecase for the GStreamer accumulated SEGMENT events.
208  */
209
210 struct _QtDemuxSegment
211 {
212   /* global time and duration, all gst time */
213   GstClockTime time;
214   GstClockTime stop_time;
215   GstClockTime duration;
216   /* media time of trak, all gst time */
217   GstClockTime media_start;
218   GstClockTime media_stop;
219   gdouble rate;
220   /* Media start time in trak timescale units */
221   guint32 trak_media_start;
222 };
223
224 #define QTSEGMENT_IS_EMPTY(s) ((s)->media_start == GST_CLOCK_TIME_NONE)
225
226 /* Used with fragmented MP4 files (mfra atom) */
227 typedef struct
228 {
229   GstClockTime ts;
230   guint64 moof_offset;
231 } QtDemuxRandomAccessEntry;
232
233 typedef struct _QtDemuxStreamStsdEntry
234 {
235   GstCaps *caps;
236   guint32 fourcc;
237   gboolean sparse;
238
239   /* video info */
240   gint width;
241   gint height;
242   gint par_w;
243   gint par_h;
244   /* Numerator/denominator framerate */
245   gint fps_n;
246   gint fps_d;
247   GstVideoColorimetry colorimetry;
248   guint16 bits_per_sample;
249   guint16 color_table_id;
250   GstMemory *rgb8_palette;
251   guint interlace_mode;
252   guint field_order;
253
254   /* audio info */
255   gdouble rate;
256   gint n_channels;
257   guint samples_per_packet;
258   guint samples_per_frame;
259   guint bytes_per_packet;
260   guint bytes_per_sample;
261   guint bytes_per_frame;
262   guint compression;
263
264   /* if we use chunks or samples */
265   gboolean sampled;
266   guint padding;
267
268 } QtDemuxStreamStsdEntry;
269
270 #define CUR_STREAM(s) (&((s)->stsd_entries[(s)->cur_stsd_entry_index]))
271
272 struct _QtDemuxStream
273 {
274   GstPad *pad;
275
276   GstQTDemux *demux;
277   gchar *stream_id;
278
279   QtDemuxStreamStsdEntry *stsd_entries;
280   guint stsd_entries_length;
281   guint cur_stsd_entry_index;
282
283   /* stream type */
284   guint32 subtype;
285
286   gboolean new_caps;            /* If TRUE, caps need to be generated (by
287                                  * calling _configure_stream()) This happens
288                                  * for MSS and fragmented streams */
289
290   gboolean new_stream;          /* signals that a stream_start is required */
291   gboolean on_keyframe;         /* if this stream last pushed buffer was a
292                                  * keyframe. This is important to identify
293                                  * where to stop pushing buffers after a
294                                  * segment stop time */
295
296   /* if the stream has a redirect URI in its headers, we store it here */
297   gchar *redirect_uri;
298
299   /* track id */
300   guint track_id;
301
302   /* duration/scale */
303   guint64 duration;             /* in timescale units */
304   guint32 timescale;
305
306   /* language */
307   gchar lang_id[4];             /* ISO 639-2T language code */
308
309   /* our samples */
310   guint32 n_samples;
311   QtDemuxSample *samples;
312   gboolean all_keyframe;        /* TRUE when all samples are keyframes (no stss) */
313   guint32 n_samples_moof;       /* sample count in a moof */
314   guint64 duration_moof;        /* duration in timescale of a moof, used for figure out
315                                  * the framerate of fragmented format stream */
316   guint64 duration_last_moof;
317
318   guint32 offset_in_sample;     /* Offset in the current sample, used for
319                                  * streams which have got exceedingly big
320                                  * sample size (such as 24s of raw audio).
321                                  * Only used when max_buffer_size is non-NULL */
322   guint32 max_buffer_size;      /* Maximum allowed size for output buffers.
323                                  * Currently only set for raw audio streams*/
324
325   /* video info */
326   /* aspect ratio */
327   gint display_width;
328   gint display_height;
329
330   /* allocation */
331   gboolean use_allocator;
332   GstAllocator *allocator;
333   GstAllocationParams params;
334
335   gsize alignment;
336
337   /* when a discontinuity is pending */
338   gboolean discont;
339
340   /* list of buffers to push first */
341   GSList *buffers;
342
343   /* if we need to clip this buffer. This is only needed for uncompressed
344    * data */
345   gboolean need_clip;
346
347   /* buffer needs some custom processing, e.g. subtitles */
348   gboolean need_process;
349
350   /* current position */
351   guint32 segment_index;
352   guint32 sample_index;
353   GstClockTime time_position;   /* in gst time */
354   guint64 accumulated_base;
355
356   /* the Gst segment we are processing out, used for clipping */
357   GstSegment segment;
358
359   /* quicktime segments */
360   guint32 n_segments;
361   QtDemuxSegment *segments;
362   gboolean dummy_segment;
363   guint32 from_sample;
364   guint32 to_sample;
365
366   gboolean sent_eos;
367   GstTagList *stream_tags;
368   gboolean send_global_tags;
369
370   GstEvent *pending_event;
371
372   GstByteReader stco;
373   GstByteReader stsz;
374   GstByteReader stsc;
375   GstByteReader stts;
376   GstByteReader stss;
377   GstByteReader stps;
378   GstByteReader ctts;
379
380   gboolean chunks_are_samples;  /* TRUE means treat chunks as samples */
381   gint64 stbl_index;
382   /* stco */
383   guint co_size;
384   GstByteReader co_chunk;
385   guint32 first_chunk;
386   guint32 current_chunk;
387   guint32 last_chunk;
388   guint32 samples_per_chunk;
389   guint32 stsd_sample_description_id;
390   guint32 stco_sample_index;
391   /* stsz */
392   guint32 sample_size;          /* 0 means variable sizes are stored in stsz */
393   /* stsc */
394   guint32 stsc_index;
395   guint32 n_samples_per_chunk;
396   guint32 stsc_chunk_index;
397   guint32 stsc_sample_index;
398   guint64 chunk_offset;
399   /* stts */
400   guint32 stts_index;
401   guint32 stts_samples;
402   guint32 n_sample_times;
403   guint32 stts_sample_index;
404   guint64 stts_time;
405   guint32 stts_duration;
406   /* stss */
407   gboolean stss_present;
408   guint32 n_sample_syncs;
409   guint32 stss_index;
410   /* stps */
411   gboolean stps_present;
412   guint32 n_sample_partial_syncs;
413   guint32 stps_index;
414   QtDemuxRandomAccessEntry *ra_entries;
415   guint n_ra_entries;
416
417   const QtDemuxRandomAccessEntry *pending_seek;
418
419   /* ctts */
420   gboolean ctts_present;
421   guint32 n_composition_times;
422   guint32 ctts_index;
423   guint32 ctts_sample_index;
424   guint32 ctts_count;
425   gint32 ctts_soffset;
426
427   /* cslg */
428   guint32 cslg_shift;
429
430   /* fragmented */
431   gboolean parsed_trex;
432   guint32 def_sample_description_index; /* index is 1-based */
433   guint32 def_sample_duration;
434   guint32 def_sample_size;
435   guint32 def_sample_flags;
436
437   gboolean disabled;
438
439   /* stereoscopic video streams */
440   GstVideoMultiviewMode multiview_mode;
441   GstVideoMultiviewFlags multiview_flags;
442
443   /* protected streams */
444   gboolean protected;
445   guint32 protection_scheme_type;
446   guint32 protection_scheme_version;
447   gpointer protection_scheme_info;      /* specific to the protection scheme */
448   GQueue protection_scheme_event_queue;
449 };
450
451 /* Contains properties and cryptographic info for a set of samples from a
452  * track protected using Common Encryption (cenc) */
453 struct _QtDemuxCencSampleSetInfo
454 {
455   GstStructure *default_properties;
456
457   /* @crypto_info holds one GstStructure per sample */
458   GPtrArray *crypto_info;
459 };
460
461 static const gchar *
462 qt_demux_state_string (enum QtDemuxState state)
463 {
464   switch (state) {
465     case QTDEMUX_STATE_INITIAL:
466       return "<INITIAL>";
467     case QTDEMUX_STATE_HEADER:
468       return "<HEADER>";
469     case QTDEMUX_STATE_MOVIE:
470       return "<MOVIE>";
471     case QTDEMUX_STATE_BUFFER_MDAT:
472       return "<BUFFER_MDAT>";
473     default:
474       return "<UNKNOWN>";
475   }
476 }
477
478 static GNode *qtdemux_tree_get_child_by_type (GNode * node, guint32 fourcc);
479 static GNode *qtdemux_tree_get_child_by_type_full (GNode * node,
480     guint32 fourcc, GstByteReader * parser);
481 static GNode *qtdemux_tree_get_sibling_by_type (GNode * node, guint32 fourcc);
482 static GNode *qtdemux_tree_get_sibling_by_type_full (GNode * node,
483     guint32 fourcc, GstByteReader * parser);
484
485 static GstFlowReturn qtdemux_add_fragmented_samples (GstQTDemux * qtdemux);
486
487 static GstStaticPadTemplate gst_qtdemux_sink_template =
488     GST_STATIC_PAD_TEMPLATE ("sink",
489     GST_PAD_SINK,
490     GST_PAD_ALWAYS,
491     GST_STATIC_CAPS ("video/quicktime; video/mj2; audio/x-m4a; "
492         "application/x-3gp")
493     );
494
495 static GstStaticPadTemplate gst_qtdemux_videosrc_template =
496 GST_STATIC_PAD_TEMPLATE ("video_%u",
497     GST_PAD_SRC,
498     GST_PAD_SOMETIMES,
499     GST_STATIC_CAPS_ANY);
500
501 static GstStaticPadTemplate gst_qtdemux_audiosrc_template =
502 GST_STATIC_PAD_TEMPLATE ("audio_%u",
503     GST_PAD_SRC,
504     GST_PAD_SOMETIMES,
505     GST_STATIC_CAPS_ANY);
506
507 static GstStaticPadTemplate gst_qtdemux_subsrc_template =
508 GST_STATIC_PAD_TEMPLATE ("subtitle_%u",
509     GST_PAD_SRC,
510     GST_PAD_SOMETIMES,
511     GST_STATIC_CAPS_ANY);
512
513 #define gst_qtdemux_parent_class parent_class
514 G_DEFINE_TYPE (GstQTDemux, gst_qtdemux, GST_TYPE_ELEMENT);
515
516 static void gst_qtdemux_dispose (GObject * object);
517
518 static guint32
519 gst_qtdemux_find_index_linear (GstQTDemux * qtdemux, QtDemuxStream * str,
520     GstClockTime media_time);
521 static guint32
522 gst_qtdemux_find_index_for_given_media_offset_linear (GstQTDemux * qtdemux,
523     QtDemuxStream * str, gint64 media_offset);
524
525 #if 0
526 static void gst_qtdemux_set_index (GstElement * element, GstIndex * index);
527 static GstIndex *gst_qtdemux_get_index (GstElement * element);
528 #endif
529 static GstStateChangeReturn gst_qtdemux_change_state (GstElement * element,
530     GstStateChange transition);
531 static void gst_qtdemux_set_context (GstElement * element,
532     GstContext * context);
533 static gboolean qtdemux_sink_activate (GstPad * sinkpad, GstObject * parent);
534 static gboolean qtdemux_sink_activate_mode (GstPad * sinkpad,
535     GstObject * parent, GstPadMode mode, gboolean active);
536
537 static void gst_qtdemux_loop (GstPad * pad);
538 static GstFlowReturn gst_qtdemux_chain (GstPad * sinkpad, GstObject * parent,
539     GstBuffer * inbuf);
540 static gboolean gst_qtdemux_handle_sink_event (GstPad * pad, GstObject * parent,
541     GstEvent * event);
542 static gboolean gst_qtdemux_setcaps (GstQTDemux * qtdemux, GstCaps * caps);
543 static gboolean gst_qtdemux_configure_stream (GstQTDemux * qtdemux,
544     QtDemuxStream * stream);
545 static void gst_qtdemux_stream_check_and_change_stsd_index (GstQTDemux * demux,
546     QtDemuxStream * stream);
547 static GstFlowReturn gst_qtdemux_process_adapter (GstQTDemux * demux,
548     gboolean force);
549 static GstClockTime gst_qtdemux_streams_get_first_sample_ts (GstQTDemux *
550     demux);
551 static GstClockTime gst_qtdemux_streams_have_samples (GstQTDemux * demux);
552
553 static gboolean qtdemux_parse_moov (GstQTDemux * qtdemux,
554     const guint8 * buffer, guint length);
555 static gboolean qtdemux_parse_node (GstQTDemux * qtdemux, GNode * node,
556     const guint8 * buffer, guint length);
557 static gboolean qtdemux_parse_tree (GstQTDemux * qtdemux);
558 static void qtdemux_parse_udta (GstQTDemux * qtdemux, GstTagList * taglist,
559     GNode * udta);
560
561 static void gst_qtdemux_handle_esds (GstQTDemux * qtdemux,
562     QtDemuxStream * stream, QtDemuxStreamStsdEntry * entry, GNode * esds,
563     GstTagList * list);
564 static GstCaps *qtdemux_video_caps (GstQTDemux * qtdemux,
565     QtDemuxStream * stream, QtDemuxStreamStsdEntry * entry, guint32 fourcc,
566     const guint8 * stsd_entry_data, gchar ** codec_name);
567 static GstCaps *qtdemux_audio_caps (GstQTDemux * qtdemux,
568     QtDemuxStream * stream, QtDemuxStreamStsdEntry * entry, guint32 fourcc,
569     const guint8 * data, int len, gchar ** codec_name);
570 static GstCaps *qtdemux_sub_caps (GstQTDemux * qtdemux, QtDemuxStream * stream,
571     QtDemuxStreamStsdEntry * entry, guint32 fourcc, const guint8 * data,
572     gchar ** codec_name);
573 static GstCaps *qtdemux_generic_caps (GstQTDemux * qtdemux,
574     QtDemuxStream * stream, QtDemuxStreamStsdEntry * entry, guint32 fourcc,
575     const guint8 * stsd_entry_data, gchar ** codec_name);
576
577 static gboolean qtdemux_parse_samples (GstQTDemux * qtdemux,
578     QtDemuxStream * stream, guint32 n);
579 static GstFlowReturn qtdemux_expose_streams (GstQTDemux * qtdemux);
580 static void gst_qtdemux_stream_free (QtDemuxStream * stream);
581 static void gst_qtdemux_stream_clear (QtDemuxStream * stream);
582 static void gst_qtdemux_remove_stream (GstQTDemux * qtdemux,
583     QtDemuxStream * stream);
584 static GstFlowReturn qtdemux_prepare_streams (GstQTDemux * qtdemux);
585 static void qtdemux_do_allocation (GstQTDemux * qtdemux,
586     QtDemuxStream * stream);
587 static gboolean gst_qtdemux_activate_segment (GstQTDemux * qtdemux,
588     QtDemuxStream * stream, guint32 seg_idx, GstClockTime offset);
589 static gboolean gst_qtdemux_stream_update_segment (GstQTDemux * qtdemux,
590     QtDemuxStream * stream, gint seg_idx, GstClockTime offset,
591     GstClockTime * _start, GstClockTime * _stop);
592 static void gst_qtdemux_send_gap_for_segment (GstQTDemux * demux,
593     QtDemuxStream * stream, gint segment_index, GstClockTime pos);
594
595 static gboolean qtdemux_pull_mfro_mfra (GstQTDemux * qtdemux);
596 static void check_update_duration (GstQTDemux * qtdemux, GstClockTime duration);
597
598 static gchar *qtdemux_uuid_bytes_to_string (gconstpointer uuid_bytes);
599
600 static GstStructure *qtdemux_get_cenc_sample_properties (GstQTDemux * qtdemux,
601     QtDemuxStream * stream, guint sample_index);
602 static void gst_qtdemux_append_protection_system_id (GstQTDemux * qtdemux,
603     const gchar * id);
604 static void qtdemux_gst_structure_free (GstStructure * gststructure);
605 static void gst_qtdemux_reset (GstQTDemux * qtdemux, gboolean hard);
606
607 static void
608 gst_qtdemux_class_init (GstQTDemuxClass * klass)
609 {
610   GObjectClass *gobject_class;
611   GstElementClass *gstelement_class;
612
613   gobject_class = (GObjectClass *) klass;
614   gstelement_class = (GstElementClass *) klass;
615
616   parent_class = g_type_class_peek_parent (klass);
617
618   gobject_class->dispose = gst_qtdemux_dispose;
619
620   gstelement_class->change_state = GST_DEBUG_FUNCPTR (gst_qtdemux_change_state);
621 #if 0
622   gstelement_class->set_index = GST_DEBUG_FUNCPTR (gst_qtdemux_set_index);
623   gstelement_class->get_index = GST_DEBUG_FUNCPTR (gst_qtdemux_get_index);
624 #endif
625   gstelement_class->set_context = GST_DEBUG_FUNCPTR (gst_qtdemux_set_context);
626
627   gst_tag_register_musicbrainz_tags ();
628
629   gst_element_class_add_static_pad_template (gstelement_class,
630       &gst_qtdemux_sink_template);
631   gst_element_class_add_static_pad_template (gstelement_class,
632       &gst_qtdemux_videosrc_template);
633   gst_element_class_add_static_pad_template (gstelement_class,
634       &gst_qtdemux_audiosrc_template);
635   gst_element_class_add_static_pad_template (gstelement_class,
636       &gst_qtdemux_subsrc_template);
637   gst_element_class_set_static_metadata (gstelement_class, "QuickTime demuxer",
638       "Codec/Demuxer",
639       "Demultiplex a QuickTime file into audio and video streams",
640       "David Schleef <ds@schleef.org>, Wim Taymans <wim@fluendo.com>");
641
642   GST_DEBUG_CATEGORY_INIT (qtdemux_debug, "qtdemux", 0, "qtdemux plugin");
643   gst_riff_init ();
644 }
645
646 static void
647 gst_qtdemux_init (GstQTDemux * qtdemux)
648 {
649   qtdemux->sinkpad =
650       gst_pad_new_from_static_template (&gst_qtdemux_sink_template, "sink");
651   gst_pad_set_activate_function (qtdemux->sinkpad, qtdemux_sink_activate);
652   gst_pad_set_activatemode_function (qtdemux->sinkpad,
653       qtdemux_sink_activate_mode);
654   gst_pad_set_chain_function (qtdemux->sinkpad, gst_qtdemux_chain);
655   gst_pad_set_event_function (qtdemux->sinkpad, gst_qtdemux_handle_sink_event);
656   gst_element_add_pad (GST_ELEMENT_CAST (qtdemux), qtdemux->sinkpad);
657
658   qtdemux->adapter = gst_adapter_new ();
659   g_queue_init (&qtdemux->protection_event_queue);
660   qtdemux->flowcombiner = gst_flow_combiner_new ();
661   g_mutex_init (&qtdemux->expose_lock);
662
663   GST_OBJECT_FLAG_SET (qtdemux, GST_ELEMENT_FLAG_INDEXABLE);
664
665   gst_qtdemux_reset (qtdemux, TRUE);
666 }
667
668 static void
669 gst_qtdemux_dispose (GObject * object)
670 {
671   GstQTDemux *qtdemux = GST_QTDEMUX (object);
672
673   if (qtdemux->adapter) {
674     g_object_unref (G_OBJECT (qtdemux->adapter));
675     qtdemux->adapter = NULL;
676   }
677   gst_tag_list_unref (qtdemux->tag_list);
678   gst_flow_combiner_free (qtdemux->flowcombiner);
679   g_queue_foreach (&qtdemux->protection_event_queue, (GFunc) gst_event_unref,
680       NULL);
681   g_queue_clear (&qtdemux->protection_event_queue);
682
683   g_free (qtdemux->cenc_aux_info_sizes);
684   qtdemux->cenc_aux_info_sizes = NULL;
685   g_mutex_clear (&qtdemux->expose_lock);
686
687   G_OBJECT_CLASS (parent_class)->dispose (object);
688 }
689
690 static void
691 gst_qtdemux_post_no_playable_stream_error (GstQTDemux * qtdemux)
692 {
693   if (qtdemux->posted_redirect) {
694     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
695         (_("This file contains no playable streams.")),
696         ("no known streams found, a redirect message has been posted"));
697   } else {
698     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
699         (_("This file contains no playable streams.")),
700         ("no known streams found"));
701   }
702 }
703
704 static GstBuffer *
705 _gst_buffer_new_wrapped (gpointer mem, gsize size, GFreeFunc free_func)
706 {
707   return gst_buffer_new_wrapped_full (free_func ? 0 : GST_MEMORY_FLAG_READONLY,
708       mem, size, 0, size, mem, free_func);
709 }
710
711 static GstFlowReturn
712 gst_qtdemux_pull_atom (GstQTDemux * qtdemux, guint64 offset, guint64 size,
713     GstBuffer ** buf)
714 {
715   GstFlowReturn flow;
716   GstMapInfo map;
717   gsize bsize;
718
719   if (G_UNLIKELY (size == 0)) {
720     GstFlowReturn ret;
721     GstBuffer *tmp = NULL;
722
723     ret = gst_qtdemux_pull_atom (qtdemux, offset, sizeof (guint32), &tmp);
724     if (ret != GST_FLOW_OK)
725       return ret;
726
727     gst_buffer_map (tmp, &map, GST_MAP_READ);
728     size = QT_UINT32 (map.data);
729     GST_DEBUG_OBJECT (qtdemux, "size 0x%08" G_GINT64_MODIFIER "x", size);
730
731     gst_buffer_unmap (tmp, &map);
732     gst_buffer_unref (tmp);
733   }
734
735   /* Sanity check: catch bogus sizes (fuzzed/broken files) */
736   if (G_UNLIKELY (size > QTDEMUX_MAX_ATOM_SIZE)) {
737     if (qtdemux->state != QTDEMUX_STATE_MOVIE && qtdemux->got_moov) {
738       /* we're pulling header but already got most interesting bits,
739        * so never mind the rest (e.g. tags) (that much) */
740       GST_WARNING_OBJECT (qtdemux, "atom has bogus size %" G_GUINT64_FORMAT,
741           size);
742       return GST_FLOW_EOS;
743     } else {
744       GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
745           (_("This file is invalid and cannot be played.")),
746           ("atom has bogus size %" G_GUINT64_FORMAT, size));
747       return GST_FLOW_ERROR;
748     }
749   }
750
751   flow = gst_pad_pull_range (qtdemux->sinkpad, offset, size, buf);
752
753   if (G_UNLIKELY (flow != GST_FLOW_OK))
754     return flow;
755
756   bsize = gst_buffer_get_size (*buf);
757   /* Catch short reads - we don't want any partial atoms */
758   if (G_UNLIKELY (bsize < size)) {
759     GST_WARNING_OBJECT (qtdemux,
760         "short read: %" G_GSIZE_FORMAT " < %" G_GUINT64_FORMAT, bsize, size);
761     gst_buffer_unref (*buf);
762     *buf = NULL;
763     return GST_FLOW_EOS;
764   }
765
766   return flow;
767 }
768
769 #if 1
770 static gboolean
771 gst_qtdemux_src_convert (GstQTDemux * qtdemux, GstPad * pad,
772     GstFormat src_format, gint64 src_value, GstFormat dest_format,
773     gint64 * dest_value)
774 {
775   gboolean res = TRUE;
776   QtDemuxStream *stream = gst_pad_get_element_private (pad);
777   gint32 index;
778
779   if (stream->subtype != FOURCC_vide) {
780     res = FALSE;
781     goto done;
782   }
783
784   switch (src_format) {
785     case GST_FORMAT_TIME:
786       switch (dest_format) {
787         case GST_FORMAT_BYTES:{
788           index = gst_qtdemux_find_index_linear (qtdemux, stream, src_value);
789           if (-1 == index) {
790             res = FALSE;
791             goto done;
792           }
793
794           *dest_value = stream->samples[index].offset;
795
796           GST_DEBUG_OBJECT (qtdemux, "Format Conversion Time->Offset :%"
797               GST_TIME_FORMAT "->%" G_GUINT64_FORMAT,
798               GST_TIME_ARGS (src_value), *dest_value);
799           break;
800         }
801         default:
802           res = FALSE;
803           break;
804       }
805       break;
806     case GST_FORMAT_BYTES:
807       switch (dest_format) {
808         case GST_FORMAT_TIME:{
809           index =
810               gst_qtdemux_find_index_for_given_media_offset_linear (qtdemux,
811               stream, src_value);
812
813           if (-1 == index) {
814             res = FALSE;
815             goto done;
816           }
817
818           *dest_value =
819               QTSTREAMTIME_TO_GSTTIME (stream,
820               stream->samples[index].timestamp);
821           GST_DEBUG_OBJECT (qtdemux,
822               "Format Conversion Offset->Time :%" G_GUINT64_FORMAT "->%"
823               GST_TIME_FORMAT, src_value, GST_TIME_ARGS (*dest_value));
824           break;
825         }
826         default:
827           res = FALSE;
828           break;
829       }
830       break;
831     default:
832       res = FALSE;
833       break;
834   }
835
836 done:
837   return res;
838 }
839 #endif
840
841 static gboolean
842 gst_qtdemux_get_duration (GstQTDemux * qtdemux, GstClockTime * duration)
843 {
844   gboolean res = FALSE;
845
846   *duration = GST_CLOCK_TIME_NONE;
847
848   if (qtdemux->duration != 0 &&
849       qtdemux->duration != G_MAXINT64 && qtdemux->timescale != 0) {
850     *duration = QTTIME_TO_GSTTIME (qtdemux, qtdemux->duration);
851     res = TRUE;
852   } else {
853     *duration = GST_CLOCK_TIME_NONE;
854   }
855
856   return res;
857 }
858
859 static gboolean
860 gst_qtdemux_handle_src_query (GstPad * pad, GstObject * parent,
861     GstQuery * query)
862 {
863   gboolean res = FALSE;
864   GstQTDemux *qtdemux = GST_QTDEMUX (parent);
865
866   GST_LOG_OBJECT (pad, "%s query", GST_QUERY_TYPE_NAME (query));
867
868   switch (GST_QUERY_TYPE (query)) {
869     case GST_QUERY_POSITION:{
870       GstFormat fmt;
871
872       gst_query_parse_position (query, &fmt, NULL);
873       if (fmt == GST_FORMAT_TIME
874           && GST_CLOCK_TIME_IS_VALID (qtdemux->segment.position)) {
875         gst_query_set_position (query, GST_FORMAT_TIME,
876             qtdemux->segment.position);
877         res = TRUE;
878       }
879     }
880       break;
881     case GST_QUERY_DURATION:{
882       GstFormat fmt;
883
884       gst_query_parse_duration (query, &fmt, NULL);
885       if (fmt == GST_FORMAT_TIME) {
886         /* First try to query upstream */
887         res = gst_pad_query_default (pad, parent, query);
888         if (!res) {
889           GstClockTime duration;
890           if (gst_qtdemux_get_duration (qtdemux, &duration) && duration > 0) {
891             gst_query_set_duration (query, GST_FORMAT_TIME, duration);
892             res = TRUE;
893           }
894         }
895       }
896       break;
897     }
898     case GST_QUERY_CONVERT:{
899       GstFormat src_fmt, dest_fmt;
900       gint64 src_value, dest_value = 0;
901
902       gst_query_parse_convert (query, &src_fmt, &src_value, &dest_fmt, NULL);
903
904       res = gst_qtdemux_src_convert (qtdemux, pad,
905           src_fmt, src_value, dest_fmt, &dest_value);
906       if (res)
907         gst_query_set_convert (query, src_fmt, src_value, dest_fmt, dest_value);
908
909       break;
910     }
911     case GST_QUERY_FORMATS:
912       gst_query_set_formats (query, 2, GST_FORMAT_TIME, GST_FORMAT_BYTES);
913       res = TRUE;
914       break;
915     case GST_QUERY_SEEKING:{
916       GstFormat fmt;
917       gboolean seekable;
918
919       /* try upstream first */
920       res = gst_pad_query_default (pad, parent, query);
921
922       if (!res) {
923         gst_query_parse_seeking (query, &fmt, NULL, NULL, NULL);
924         if (fmt == GST_FORMAT_TIME) {
925           GstClockTime duration;
926
927           gst_qtdemux_get_duration (qtdemux, &duration);
928           seekable = TRUE;
929           if (!qtdemux->pullbased) {
930             GstQuery *q;
931
932             /* we might be able with help from upstream */
933             seekable = FALSE;
934             q = gst_query_new_seeking (GST_FORMAT_BYTES);
935             if (gst_pad_peer_query (qtdemux->sinkpad, q)) {
936               gst_query_parse_seeking (q, &fmt, &seekable, NULL, NULL);
937               GST_LOG_OBJECT (qtdemux, "upstream BYTE seekable %d", seekable);
938             }
939             gst_query_unref (q);
940           }
941           gst_query_set_seeking (query, GST_FORMAT_TIME, seekable, 0, duration);
942           res = TRUE;
943         }
944       }
945       break;
946     }
947     case GST_QUERY_SEGMENT:
948     {
949       GstFormat format;
950       gint64 start, stop;
951
952       format = qtdemux->segment.format;
953
954       start =
955           gst_segment_to_stream_time (&qtdemux->segment, format,
956           qtdemux->segment.start);
957       if ((stop = qtdemux->segment.stop) == -1)
958         stop = qtdemux->segment.duration;
959       else
960         stop = gst_segment_to_stream_time (&qtdemux->segment, format, stop);
961
962       gst_query_set_segment (query, qtdemux->segment.rate, format, start, stop);
963       res = TRUE;
964       break;
965     }
966     default:
967       res = gst_pad_query_default (pad, parent, query);
968       break;
969   }
970
971   return res;
972 }
973
974 static void
975 gst_qtdemux_push_tags (GstQTDemux * qtdemux, QtDemuxStream * stream)
976 {
977   if (G_LIKELY (stream->pad)) {
978     GST_DEBUG_OBJECT (qtdemux, "Checking pad %s:%s for tags",
979         GST_DEBUG_PAD_NAME (stream->pad));
980
981     if (!gst_tag_list_is_empty (stream->stream_tags)) {
982       GST_DEBUG_OBJECT (qtdemux, "Sending tags %" GST_PTR_FORMAT,
983           stream->stream_tags);
984       gst_pad_push_event (stream->pad,
985           gst_event_new_tag (gst_tag_list_ref (stream->stream_tags)));
986     }
987
988     if (G_UNLIKELY (stream->send_global_tags)) {
989       GST_DEBUG_OBJECT (qtdemux, "Sending global tags %" GST_PTR_FORMAT,
990           qtdemux->tag_list);
991       gst_pad_push_event (stream->pad,
992           gst_event_new_tag (gst_tag_list_ref (qtdemux->tag_list)));
993       stream->send_global_tags = FALSE;
994     }
995   }
996 }
997
998 /* push event on all source pads; takes ownership of the event */
999 static void
1000 gst_qtdemux_push_event (GstQTDemux * qtdemux, GstEvent * event)
1001 {
1002   gboolean has_valid_stream = FALSE;
1003   GstEventType etype = GST_EVENT_TYPE (event);
1004   GList *iter;
1005
1006   GST_DEBUG_OBJECT (qtdemux, "pushing %s event on all source pads",
1007       GST_EVENT_TYPE_NAME (event));
1008
1009   for (iter = qtdemux->active_streams; iter; iter = g_list_next (iter)) {
1010     GstPad *pad;
1011     QtDemuxStream *stream = QTDEMUX_STREAM (iter->data);
1012     GST_DEBUG_OBJECT (qtdemux, "pushing on track-id %u", stream->track_id);
1013
1014     if ((pad = stream->pad)) {
1015       has_valid_stream = TRUE;
1016
1017       if (etype == GST_EVENT_EOS) {
1018         /* let's not send twice */
1019         if (stream->sent_eos)
1020           continue;
1021         stream->sent_eos = TRUE;
1022       }
1023
1024       gst_pad_push_event (pad, gst_event_ref (event));
1025     }
1026   }
1027
1028   gst_event_unref (event);
1029
1030   /* if it is EOS and there are no pads, post an error */
1031   if (!has_valid_stream && etype == GST_EVENT_EOS) {
1032     gst_qtdemux_post_no_playable_stream_error (qtdemux);
1033   }
1034 }
1035
1036 /* push a pending newsegment event, if any from the streaming thread */
1037 static void
1038 gst_qtdemux_push_pending_newsegment (GstQTDemux * qtdemux)
1039 {
1040   if (G_UNLIKELY (qtdemux->need_segment)) {
1041     GstEvent *newsegment;
1042
1043     if (!qtdemux->upstream_format_is_time) {
1044       GstClockTime min_ts;
1045
1046       if (!gst_qtdemux_streams_have_samples (qtdemux)) {
1047         /* No samples yet, can't decide on segment.start */
1048         GST_DEBUG_OBJECT (qtdemux, "No samples yet, postponing segment event");
1049         return;
1050       }
1051
1052       min_ts = gst_qtdemux_streams_get_first_sample_ts (qtdemux);
1053
1054       /* have_samples() above should guarantee we have a valid time */
1055       g_assert (GST_CLOCK_TIME_IS_VALID (min_ts));
1056
1057       qtdemux->segment.start = min_ts;
1058     }
1059
1060     newsegment = gst_event_new_segment (&qtdemux->segment);
1061     if (qtdemux->segment_seqnum != GST_SEQNUM_INVALID)
1062       gst_event_set_seqnum (newsegment, qtdemux->segment_seqnum);
1063     qtdemux->need_segment = FALSE;
1064     gst_qtdemux_push_event (qtdemux, newsegment);
1065   }
1066 }
1067
1068 typedef struct
1069 {
1070   guint64 media_time;
1071 } FindData;
1072
1073 static gint
1074 find_func (QtDemuxSample * s1, gint64 * media_time, gpointer user_data)
1075 {
1076   if ((gint64) s1->timestamp > *media_time)
1077     return 1;
1078   if ((gint64) s1->timestamp == *media_time)
1079     return 0;
1080
1081   return -1;
1082 }
1083
1084 /* find the index of the sample that includes the data for @media_time using a
1085  * binary search.  Only to be called in optimized cases of linear search below.
1086  *
1087  * Returns the index of the sample with the corresponding *DTS*.
1088  */
1089 static guint32
1090 gst_qtdemux_find_index (GstQTDemux * qtdemux, QtDemuxStream * str,
1091     guint64 media_time)
1092 {
1093   QtDemuxSample *result;
1094   guint32 index;
1095
1096   /* convert media_time to mov format */
1097   media_time =
1098       gst_util_uint64_scale_ceil (media_time, str->timescale, GST_SECOND);
1099
1100   result = gst_util_array_binary_search (str->samples, str->stbl_index + 1,
1101       sizeof (QtDemuxSample), (GCompareDataFunc) find_func,
1102       GST_SEARCH_MODE_BEFORE, &media_time, NULL);
1103
1104   if (G_LIKELY (result))
1105     index = result - str->samples;
1106   else
1107     index = 0;
1108
1109   return index;
1110 }
1111
1112
1113
1114 /* find the index of the sample that includes the data for @media_offset using a
1115  * linear search
1116  *
1117  * Returns the index of the sample.
1118  */
1119 static guint32
1120 gst_qtdemux_find_index_for_given_media_offset_linear (GstQTDemux * qtdemux,
1121     QtDemuxStream * str, gint64 media_offset)
1122 {
1123   QtDemuxSample *result = str->samples;
1124   guint32 index = 0;
1125
1126   if (result == NULL || str->n_samples == 0)
1127     return -1;
1128
1129   if (media_offset == result->offset)
1130     return index;
1131
1132   result++;
1133   while (index < str->n_samples - 1) {
1134     if (!qtdemux_parse_samples (qtdemux, str, index + 1))
1135       goto parse_failed;
1136
1137     if (media_offset < result->offset)
1138       break;
1139
1140     index++;
1141     result++;
1142   }
1143   return index;
1144
1145   /* ERRORS */
1146 parse_failed:
1147   {
1148     GST_LOG_OBJECT (qtdemux, "Parsing of index %u failed!", index + 1);
1149     return -1;
1150   }
1151 }
1152
1153 /* find the index of the sample that includes the data for @media_time using a
1154  * linear search, and keeping in mind that not all samples may have been parsed
1155  * yet.  If possible, it will delegate to binary search.
1156  *
1157  * Returns the index of the sample.
1158  */
1159 static guint32
1160 gst_qtdemux_find_index_linear (GstQTDemux * qtdemux, QtDemuxStream * str,
1161     GstClockTime media_time)
1162 {
1163   guint32 index = 0;
1164   guint64 mov_time;
1165   QtDemuxSample *sample;
1166
1167   /* convert media_time to mov format */
1168   mov_time =
1169       gst_util_uint64_scale_ceil (media_time, str->timescale, GST_SECOND);
1170
1171   sample = str->samples;
1172   if (mov_time == sample->timestamp + sample->pts_offset)
1173     return index;
1174
1175   /* use faster search if requested time in already parsed range */
1176   sample = str->samples + str->stbl_index;
1177   if (str->stbl_index >= 0 && mov_time <= sample->timestamp) {
1178     index = gst_qtdemux_find_index (qtdemux, str, media_time);
1179     sample = str->samples + index;
1180   } else {
1181     while (index < str->n_samples - 1) {
1182       if (!qtdemux_parse_samples (qtdemux, str, index + 1))
1183         goto parse_failed;
1184
1185       sample = str->samples + index + 1;
1186       if (mov_time < sample->timestamp) {
1187         sample = str->samples + index;
1188         break;
1189       }
1190
1191       index++;
1192     }
1193   }
1194
1195   /* sample->timestamp is now <= media_time, need to find the corresponding
1196    * PTS now by looking backwards */
1197   while (index > 0 && sample->timestamp + sample->pts_offset > mov_time) {
1198     index--;
1199     sample = str->samples + index;
1200   }
1201
1202   return index;
1203
1204   /* ERRORS */
1205 parse_failed:
1206   {
1207     GST_LOG_OBJECT (qtdemux, "Parsing of index %u failed!", index + 1);
1208     return -1;
1209   }
1210 }
1211
1212 /* find the index of the keyframe needed to decode the sample at @index
1213  * of stream @str, or of a subsequent keyframe (depending on @next)
1214  *
1215  * Returns the index of the keyframe.
1216  */
1217 static guint32
1218 gst_qtdemux_find_keyframe (GstQTDemux * qtdemux, QtDemuxStream * str,
1219     guint32 index, gboolean next)
1220 {
1221   guint32 new_index = index;
1222
1223   if (index >= str->n_samples) {
1224     new_index = str->n_samples;
1225     goto beach;
1226   }
1227
1228   /* all keyframes, return index */
1229   if (str->all_keyframe) {
1230     new_index = index;
1231     goto beach;
1232   }
1233
1234   /* else search until we have a keyframe */
1235   while (new_index < str->n_samples) {
1236     if (next && !qtdemux_parse_samples (qtdemux, str, new_index))
1237       goto parse_failed;
1238
1239     if (str->samples[new_index].keyframe)
1240       break;
1241
1242     if (new_index == 0)
1243       break;
1244
1245     if (next)
1246       new_index++;
1247     else
1248       new_index--;
1249   }
1250
1251   if (new_index == str->n_samples) {
1252     GST_DEBUG_OBJECT (qtdemux, "no next keyframe");
1253     new_index = -1;
1254   }
1255
1256 beach:
1257   GST_DEBUG_OBJECT (qtdemux, "searching for keyframe index %s index %u "
1258       "gave %u", next ? "after" : "before", index, new_index);
1259
1260   return new_index;
1261
1262   /* ERRORS */
1263 parse_failed:
1264   {
1265     GST_LOG_OBJECT (qtdemux, "Parsing of index %u failed!", new_index);
1266     return -1;
1267   }
1268 }
1269
1270 /* find the segment for @time_position for @stream
1271  *
1272  * Returns the index of the segment containing @time_position.
1273  * Returns the last segment and sets the @eos variable to TRUE
1274  * if the time is beyond the end. @eos may be NULL
1275  */
1276 static guint32
1277 gst_qtdemux_find_segment (GstQTDemux * qtdemux, QtDemuxStream * stream,
1278     GstClockTime time_position)
1279 {
1280   gint i;
1281   guint32 seg_idx;
1282
1283   GST_LOG_OBJECT (stream->pad, "finding segment for %" GST_TIME_FORMAT,
1284       GST_TIME_ARGS (time_position));
1285
1286   seg_idx = -1;
1287   for (i = 0; i < stream->n_segments; i++) {
1288     QtDemuxSegment *segment = &stream->segments[i];
1289
1290     GST_LOG_OBJECT (stream->pad,
1291         "looking at segment %" GST_TIME_FORMAT "-%" GST_TIME_FORMAT,
1292         GST_TIME_ARGS (segment->time), GST_TIME_ARGS (segment->stop_time));
1293
1294     /* For the last segment we include stop_time in the last segment */
1295     if (i < stream->n_segments - 1) {
1296       if (segment->time <= time_position && time_position < segment->stop_time) {
1297         GST_LOG_OBJECT (stream->pad, "segment %d matches", i);
1298         seg_idx = i;
1299         break;
1300       }
1301     } else {
1302       /* Last segment always matches */
1303       seg_idx = i;
1304       break;
1305     }
1306   }
1307   return seg_idx;
1308 }
1309
1310 /* move the stream @str to the sample position @index.
1311  *
1312  * Updates @str->sample_index and marks discontinuity if needed.
1313  */
1314 static void
1315 gst_qtdemux_move_stream (GstQTDemux * qtdemux, QtDemuxStream * str,
1316     guint32 index)
1317 {
1318   /* no change needed */
1319   if (index == str->sample_index)
1320     return;
1321
1322   GST_DEBUG_OBJECT (qtdemux, "moving to sample %u of %u", index,
1323       str->n_samples);
1324
1325   /* position changed, we have a discont */
1326   str->sample_index = index;
1327   str->offset_in_sample = 0;
1328   /* Each time we move in the stream we store the position where we are
1329    * starting from */
1330   str->from_sample = index;
1331   str->discont = TRUE;
1332 }
1333
1334 static void
1335 gst_qtdemux_adjust_seek (GstQTDemux * qtdemux, gint64 desired_time,
1336     gboolean use_sparse, gboolean next, gint64 * key_time, gint64 * key_offset)
1337 {
1338   guint64 min_offset;
1339   gint64 min_byte_offset = -1;
1340   GList *iter;
1341
1342   min_offset = desired_time;
1343
1344   /* for each stream, find the index of the sample in the segment
1345    * and move back to the previous keyframe. */
1346   for (iter = qtdemux->active_streams; iter; iter = g_list_next (iter)) {
1347     QtDemuxStream *str;
1348     guint32 index, kindex;
1349     guint32 seg_idx;
1350     GstClockTime media_start;
1351     GstClockTime media_time;
1352     GstClockTime seg_time;
1353     QtDemuxSegment *seg;
1354     gboolean empty_segment = FALSE;
1355
1356     str = QTDEMUX_STREAM (iter->data);
1357
1358     if (CUR_STREAM (str)->sparse && !use_sparse)
1359       continue;
1360
1361     seg_idx = gst_qtdemux_find_segment (qtdemux, str, desired_time);
1362     GST_DEBUG_OBJECT (qtdemux, "align segment %d", seg_idx);
1363
1364     /* get segment and time in the segment */
1365     seg = &str->segments[seg_idx];
1366     seg_time = (desired_time - seg->time) * seg->rate;
1367
1368     while (QTSEGMENT_IS_EMPTY (seg)) {
1369       seg_time = 0;
1370       empty_segment = TRUE;
1371       GST_DEBUG_OBJECT (str->pad, "Segment %d is empty, moving to next one",
1372           seg_idx);
1373       seg_idx++;
1374       if (seg_idx == str->n_segments)
1375         break;
1376       seg = &str->segments[seg_idx];
1377     }
1378
1379     if (seg_idx == str->n_segments) {
1380       /* FIXME track shouldn't have the last segment as empty, but if it
1381        * happens we better handle it */
1382       continue;
1383     }
1384
1385     /* get the media time in the segment */
1386     media_start = seg->media_start + seg_time;
1387
1388     /* get the index of the sample with media time */
1389     index = gst_qtdemux_find_index_linear (qtdemux, str, media_start);
1390     GST_DEBUG_OBJECT (qtdemux, "sample for %" GST_TIME_FORMAT " at %u"
1391         " at offset %" G_GUINT64_FORMAT " (empty segment: %d)",
1392         GST_TIME_ARGS (media_start), index, str->samples[index].offset,
1393         empty_segment);
1394
1395     /* shift to next frame if we are looking for next keyframe */
1396     if (next && QTSAMPLE_PTS_NO_CSLG (str, &str->samples[index]) < media_start
1397         && index < str->stbl_index)
1398       index++;
1399
1400     if (!empty_segment) {
1401       /* find previous keyframe */
1402       kindex = gst_qtdemux_find_keyframe (qtdemux, str, index, next);
1403
1404       /* we will settle for one before if none found after */
1405       if (next && kindex == -1)
1406         kindex = gst_qtdemux_find_keyframe (qtdemux, str, index, FALSE);
1407
1408       /* if the keyframe is at a different position, we need to update the
1409        * requested seek time */
1410       if (index != kindex) {
1411         index = kindex;
1412
1413         /* get timestamp of keyframe */
1414         media_time = QTSAMPLE_PTS_NO_CSLG (str, &str->samples[kindex]);
1415         GST_DEBUG_OBJECT (qtdemux,
1416             "keyframe at %u with time %" GST_TIME_FORMAT " at offset %"
1417             G_GUINT64_FORMAT, kindex, GST_TIME_ARGS (media_time),
1418             str->samples[kindex].offset);
1419
1420         /* keyframes in the segment get a chance to change the
1421          * desired_offset. keyframes out of the segment are
1422          * ignored. */
1423         if (media_time >= seg->media_start) {
1424           GstClockTime seg_time;
1425
1426           /* this keyframe is inside the segment, convert back to
1427            * segment time */
1428           seg_time = (media_time - seg->media_start) + seg->time;
1429           if ((!next && (seg_time < min_offset)) ||
1430               (next && (seg_time > min_offset)))
1431             min_offset = seg_time;
1432         }
1433       }
1434     }
1435
1436     if (min_byte_offset < 0 || str->samples[index].offset < min_byte_offset)
1437       min_byte_offset = str->samples[index].offset;
1438   }
1439
1440   if (key_time)
1441     *key_time = min_offset;
1442   if (key_offset)
1443     *key_offset = min_byte_offset;
1444 }
1445
1446 static gboolean
1447 gst_qtdemux_convert_seek (GstPad * pad, GstFormat * format,
1448     GstSeekType cur_type, gint64 * cur, GstSeekType stop_type, gint64 * stop)
1449 {
1450   gboolean res;
1451
1452   g_return_val_if_fail (format != NULL, FALSE);
1453   g_return_val_if_fail (cur != NULL, FALSE);
1454   g_return_val_if_fail (stop != NULL, FALSE);
1455
1456   if (*format == GST_FORMAT_TIME)
1457     return TRUE;
1458
1459   res = TRUE;
1460   if (cur_type != GST_SEEK_TYPE_NONE)
1461     res = gst_pad_query_convert (pad, *format, *cur, GST_FORMAT_TIME, cur);
1462   if (res && stop_type != GST_SEEK_TYPE_NONE)
1463     res = gst_pad_query_convert (pad, *format, *stop, GST_FORMAT_TIME, stop);
1464
1465   if (res)
1466     *format = GST_FORMAT_TIME;
1467
1468   return res;
1469 }
1470
1471 /* perform seek in push based mode:
1472    find BYTE position to move to based on time and delegate to upstream
1473 */
1474 static gboolean
1475 gst_qtdemux_do_push_seek (GstQTDemux * qtdemux, GstPad * pad, GstEvent * event)
1476 {
1477   gdouble rate;
1478   GstFormat format;
1479   GstSeekFlags flags;
1480   GstSeekType cur_type, stop_type;
1481   gint64 cur, stop, key_cur;
1482   gboolean res;
1483   gint64 byte_cur;
1484   gint64 original_stop;
1485   guint32 seqnum;
1486
1487   GST_DEBUG_OBJECT (qtdemux, "doing push-based seek");
1488
1489   gst_event_parse_seek (event, &rate, &format, &flags,
1490       &cur_type, &cur, &stop_type, &stop);
1491   seqnum = gst_event_get_seqnum (event);
1492
1493   /* only forward streaming and seeking is possible */
1494   if (rate <= 0)
1495     goto unsupported_seek;
1496
1497   /* convert to TIME if needed and possible */
1498   if (!gst_qtdemux_convert_seek (pad, &format, cur_type, &cur,
1499           stop_type, &stop))
1500     goto no_format;
1501
1502   /* Upstream seek in bytes will have undefined stop, but qtdemux stores
1503    * the original stop position to use when upstream pushes the new segment
1504    * for this seek */
1505   original_stop = stop;
1506   stop = -1;
1507
1508   /* find reasonable corresponding BYTE position,
1509    * also try to mind about keyframes, since we can not go back a bit for them
1510    * later on */
1511   /* determining @next here based on SNAP_BEFORE/SNAP_AFTER should
1512    * mostly just work, but let's not yet boldly go there  ... */
1513   gst_qtdemux_adjust_seek (qtdemux, cur, FALSE, FALSE, &key_cur, &byte_cur);
1514
1515   if (byte_cur == -1)
1516     goto abort_seek;
1517
1518   GST_DEBUG_OBJECT (qtdemux, "Pushing BYTE seek rate %g, "
1519       "start %" G_GINT64_FORMAT ", stop %" G_GINT64_FORMAT, rate, byte_cur,
1520       stop);
1521
1522   GST_OBJECT_LOCK (qtdemux);
1523   qtdemux->seek_offset = byte_cur;
1524   if (!(flags & GST_SEEK_FLAG_KEY_UNIT)) {
1525     qtdemux->push_seek_start = cur;
1526   } else {
1527     qtdemux->push_seek_start = key_cur;
1528   }
1529
1530   if (stop_type == GST_SEEK_TYPE_NONE) {
1531     qtdemux->push_seek_stop = qtdemux->segment.stop;
1532   } else {
1533     qtdemux->push_seek_stop = original_stop;
1534   }
1535   GST_OBJECT_UNLOCK (qtdemux);
1536
1537   /* BYTE seek event */
1538   event = gst_event_new_seek (rate, GST_FORMAT_BYTES, flags, cur_type, byte_cur,
1539       stop_type, stop);
1540   gst_event_set_seqnum (event, seqnum);
1541   res = gst_pad_push_event (qtdemux->sinkpad, event);
1542
1543   return res;
1544
1545   /* ERRORS */
1546 abort_seek:
1547   {
1548     GST_DEBUG_OBJECT (qtdemux, "could not determine byte position to seek to, "
1549         "seek aborted.");
1550     return FALSE;
1551   }
1552 unsupported_seek:
1553   {
1554     GST_DEBUG_OBJECT (qtdemux, "unsupported seek, seek aborted.");
1555     return FALSE;
1556   }
1557 no_format:
1558   {
1559     GST_DEBUG_OBJECT (qtdemux, "unsupported format given, seek aborted.");
1560     return FALSE;
1561   }
1562 }
1563
1564 /* perform the seek.
1565  *
1566  * We set all segment_indexes in the streams to unknown and
1567  * adjust the time_position to the desired position. this is enough
1568  * to trigger a segment switch in the streaming thread to start
1569  * streaming from the desired position.
1570  *
1571  * Keyframe seeking is a little more complicated when dealing with
1572  * segments. Ideally we want to move to the previous keyframe in
1573  * the segment but there might not be a keyframe in the segment. In
1574  * fact, none of the segments could contain a keyframe. We take a
1575  * practical approach: seek to the previous keyframe in the segment,
1576  * if there is none, seek to the beginning of the segment.
1577  *
1578  * Called with STREAM_LOCK
1579  */
1580 static gboolean
1581 gst_qtdemux_perform_seek (GstQTDemux * qtdemux, GstSegment * segment,
1582     guint32 seqnum, GstSeekFlags flags)
1583 {
1584   gint64 desired_offset;
1585   GList *iter;
1586
1587   desired_offset = segment->position;
1588
1589   GST_DEBUG_OBJECT (qtdemux, "seeking to %" GST_TIME_FORMAT,
1590       GST_TIME_ARGS (desired_offset));
1591
1592   /* may not have enough fragmented info to do this adjustment,
1593    * and we can't scan (and probably should not) at this time with
1594    * possibly flushing upstream */
1595   if ((flags & GST_SEEK_FLAG_KEY_UNIT) && !qtdemux->fragmented) {
1596     gint64 min_offset;
1597     gboolean next, before, after;
1598
1599     before = ! !(flags & GST_SEEK_FLAG_SNAP_BEFORE);
1600     after = ! !(flags & GST_SEEK_FLAG_SNAP_AFTER);
1601     next = after && !before;
1602     if (segment->rate < 0)
1603       next = !next;
1604
1605     gst_qtdemux_adjust_seek (qtdemux, desired_offset, TRUE, next, &min_offset,
1606         NULL);
1607     GST_DEBUG_OBJECT (qtdemux, "keyframe seek, align to %"
1608         GST_TIME_FORMAT, GST_TIME_ARGS (min_offset));
1609     desired_offset = min_offset;
1610   }
1611
1612   /* and set all streams to the final position */
1613   gst_flow_combiner_reset (qtdemux->flowcombiner);
1614   qtdemux->segment_seqnum = seqnum;
1615   for (iter = qtdemux->active_streams; iter; iter = g_list_next (iter)) {
1616     QtDemuxStream *stream = QTDEMUX_STREAM (iter->data);
1617
1618     stream->time_position = desired_offset;
1619     stream->accumulated_base = 0;
1620     stream->sample_index = -1;
1621     stream->offset_in_sample = 0;
1622     stream->segment_index = -1;
1623     stream->sent_eos = FALSE;
1624
1625     if (segment->flags & GST_SEEK_FLAG_FLUSH)
1626       gst_segment_init (&stream->segment, GST_FORMAT_TIME);
1627   }
1628   segment->position = desired_offset;
1629   segment->time = desired_offset;
1630   if (segment->rate >= 0) {
1631     segment->start = desired_offset;
1632
1633     /* we stop at the end */
1634     if (segment->stop == -1)
1635       segment->stop = segment->duration;
1636   } else {
1637     segment->stop = desired_offset;
1638   }
1639
1640   if (qtdemux->fragmented)
1641     qtdemux->fragmented_seek_pending = TRUE;
1642
1643   return TRUE;
1644 }
1645
1646 /* do a seek in pull based mode */
1647 static gboolean
1648 gst_qtdemux_do_seek (GstQTDemux * qtdemux, GstPad * pad, GstEvent * event)
1649 {
1650   gdouble rate;
1651   GstFormat format;
1652   GstSeekFlags flags;
1653   GstSeekType cur_type, stop_type;
1654   gint64 cur, stop;
1655   gboolean flush;
1656   gboolean update;
1657   GstSegment seeksegment;
1658   guint32 seqnum = GST_SEQNUM_INVALID;
1659   GstEvent *flush_event;
1660   gboolean ret;
1661
1662   if (event) {
1663     GST_DEBUG_OBJECT (qtdemux, "doing seek with event");
1664
1665     gst_event_parse_seek (event, &rate, &format, &flags,
1666         &cur_type, &cur, &stop_type, &stop);
1667     seqnum = gst_event_get_seqnum (event);
1668
1669     /* we have to have a format as the segment format. Try to convert
1670      * if not. */
1671     if (!gst_qtdemux_convert_seek (pad, &format, cur_type, &cur,
1672             stop_type, &stop))
1673       goto no_format;
1674
1675     GST_DEBUG_OBJECT (qtdemux, "seek format %s", gst_format_get_name (format));
1676   } else {
1677     GST_DEBUG_OBJECT (qtdemux, "doing seek without event");
1678     flags = 0;
1679   }
1680
1681   flush = flags & GST_SEEK_FLAG_FLUSH;
1682
1683   /* stop streaming, either by flushing or by pausing the task */
1684   if (flush) {
1685     flush_event = gst_event_new_flush_start ();
1686     if (seqnum != GST_SEQNUM_INVALID)
1687       gst_event_set_seqnum (flush_event, seqnum);
1688     /* unlock upstream pull_range */
1689     gst_pad_push_event (qtdemux->sinkpad, gst_event_ref (flush_event));
1690     /* make sure out loop function exits */
1691     gst_qtdemux_push_event (qtdemux, flush_event);
1692   } else {
1693     /* non flushing seek, pause the task */
1694     gst_pad_pause_task (qtdemux->sinkpad);
1695   }
1696
1697   /* wait for streaming to finish */
1698   GST_PAD_STREAM_LOCK (qtdemux->sinkpad);
1699
1700   /* copy segment, we need this because we still need the old
1701    * segment when we close the current segment. */
1702   memcpy (&seeksegment, &qtdemux->segment, sizeof (GstSegment));
1703
1704   if (event) {
1705     /* configure the segment with the seek variables */
1706     GST_DEBUG_OBJECT (qtdemux, "configuring seek");
1707     if (!gst_segment_do_seek (&seeksegment, rate, format, flags,
1708             cur_type, cur, stop_type, stop, &update)) {
1709       ret = FALSE;
1710       GST_ERROR_OBJECT (qtdemux, "inconsistent seek values, doing nothing");
1711     } else {
1712       /* now do the seek */
1713       ret = gst_qtdemux_perform_seek (qtdemux, &seeksegment, seqnum, flags);
1714     }
1715   } else {
1716     /* now do the seek */
1717     ret = gst_qtdemux_perform_seek (qtdemux, &seeksegment, seqnum, flags);
1718   }
1719
1720   /* prepare for streaming again */
1721   if (flush) {
1722     flush_event = gst_event_new_flush_stop (TRUE);
1723     if (seqnum != GST_SEQNUM_INVALID)
1724       gst_event_set_seqnum (flush_event, seqnum);
1725
1726     gst_pad_push_event (qtdemux->sinkpad, gst_event_ref (flush_event));
1727     gst_qtdemux_push_event (qtdemux, flush_event);
1728   }
1729
1730   /* commit the new segment */
1731   memcpy (&qtdemux->segment, &seeksegment, sizeof (GstSegment));
1732
1733   if (qtdemux->segment.flags & GST_SEEK_FLAG_SEGMENT) {
1734     GstMessage *msg = gst_message_new_segment_start (GST_OBJECT_CAST (qtdemux),
1735         qtdemux->segment.format, qtdemux->segment.position);
1736     if (seqnum != GST_SEQNUM_INVALID)
1737       gst_message_set_seqnum (msg, seqnum);
1738     gst_element_post_message (GST_ELEMENT_CAST (qtdemux), msg);
1739   }
1740
1741   /* restart streaming, NEWSEGMENT will be sent from the streaming thread. */
1742   gst_pad_start_task (qtdemux->sinkpad, (GstTaskFunction) gst_qtdemux_loop,
1743       qtdemux->sinkpad, NULL);
1744
1745   GST_PAD_STREAM_UNLOCK (qtdemux->sinkpad);
1746
1747   return ret;
1748
1749   /* ERRORS */
1750 no_format:
1751   {
1752     GST_DEBUG_OBJECT (qtdemux, "unsupported format given, seek aborted.");
1753     return FALSE;
1754   }
1755 }
1756
1757 static gboolean
1758 qtdemux_ensure_index (GstQTDemux * qtdemux)
1759 {
1760   GList *iter;
1761
1762   GST_DEBUG_OBJECT (qtdemux, "collecting all metadata for all streams");
1763
1764   /* Build complete index */
1765   for (iter = qtdemux->active_streams; iter; iter = g_list_next (iter)) {
1766     QtDemuxStream *stream = QTDEMUX_STREAM (iter->data);
1767
1768     if (!qtdemux_parse_samples (qtdemux, stream, stream->n_samples - 1)) {
1769       GST_LOG_OBJECT (qtdemux,
1770           "Building complete index of track-id %u for seeking failed!",
1771           stream->track_id);
1772       return FALSE;
1773     }
1774   }
1775
1776   return TRUE;
1777 }
1778
1779 static gboolean
1780 gst_qtdemux_handle_src_event (GstPad * pad, GstObject * parent,
1781     GstEvent * event)
1782 {
1783   gboolean res = TRUE;
1784   GstQTDemux *qtdemux = GST_QTDEMUX (parent);
1785
1786   switch (GST_EVENT_TYPE (event)) {
1787     case GST_EVENT_SEEK:
1788     {
1789 #ifndef GST_DISABLE_GST_DEBUG
1790       GstClockTime ts = gst_util_get_timestamp ();
1791 #endif
1792       guint32 seqnum = gst_event_get_seqnum (event);
1793
1794       if (seqnum == qtdemux->segment_seqnum) {
1795         GST_LOG_OBJECT (pad,
1796             "Drop duplicated SEEK event seqnum %" G_GUINT32_FORMAT, seqnum);
1797         gst_event_unref (event);
1798         return TRUE;
1799       }
1800
1801       if (qtdemux->upstream_format_is_time && qtdemux->fragmented) {
1802         /* seek should be handled by upstream, we might need to re-download fragments */
1803         GST_DEBUG_OBJECT (qtdemux,
1804             "let upstream handle seek for fragmented playback");
1805         goto upstream;
1806       }
1807
1808       /* Build complete index for seeking;
1809        * if not a fragmented file at least */
1810       if (!qtdemux->fragmented)
1811         if (!qtdemux_ensure_index (qtdemux))
1812           goto index_failed;
1813 #ifndef GST_DISABLE_GST_DEBUG
1814       ts = gst_util_get_timestamp () - ts;
1815       GST_INFO_OBJECT (qtdemux,
1816           "Time taken to parse index %" GST_TIME_FORMAT, GST_TIME_ARGS (ts));
1817 #endif
1818     }
1819       if (qtdemux->pullbased) {
1820         res = gst_qtdemux_do_seek (qtdemux, pad, event);
1821       } else if (gst_pad_push_event (qtdemux->sinkpad, gst_event_ref (event))) {
1822         GST_DEBUG_OBJECT (qtdemux, "Upstream successfully seeked");
1823         res = TRUE;
1824       } else if (qtdemux->state == QTDEMUX_STATE_MOVIE && qtdemux->n_streams
1825           && !qtdemux->fragmented) {
1826         res = gst_qtdemux_do_push_seek (qtdemux, pad, event);
1827       } else {
1828         GST_DEBUG_OBJECT (qtdemux,
1829             "ignoring seek in push mode in current state");
1830         res = FALSE;
1831       }
1832       gst_event_unref (event);
1833       break;
1834     default:
1835     upstream:
1836       res = gst_pad_event_default (pad, parent, event);
1837       break;
1838   }
1839
1840 done:
1841   return res;
1842
1843   /* ERRORS */
1844 index_failed:
1845   {
1846     GST_ERROR_OBJECT (qtdemux, "Index failed");
1847     gst_event_unref (event);
1848     res = FALSE;
1849     goto done;
1850   }
1851 }
1852
1853 /* Find, for each track, the first sample in coding order that has a file offset >= @byte_pos.
1854  *
1855  * If @fw is false, the coding order is explored backwards.
1856  *
1857  * If @set is true, each stream will be moved to its matched sample, or EOS if no matching
1858  * sample is found for that track.
1859  *
1860  * The stream and sample index of the sample with the minimum offset in the direction explored
1861  * (see @fw) is returned in the output parameters @_stream and @_index respectively.
1862  *
1863  * @_time is set to the QTSAMPLE_PTS of the matched sample with the minimum QTSAMPLE_PTS in the
1864  * direction explored, which may not always match the QTSAMPLE_PTS of the sample returned in
1865  * @_stream and @_index. */
1866 static void
1867 gst_qtdemux_find_sample (GstQTDemux * qtdemux, gint64 byte_pos, gboolean fw,
1868     gboolean set, QtDemuxStream ** _stream, gint * _index, gint64 * _time)
1869 {
1870   gint i, index;
1871   gint64 time, min_time;
1872   QtDemuxStream *stream;
1873   GList *iter;
1874
1875   min_time = -1;
1876   stream = NULL;
1877   index = -1;
1878
1879   for (iter = qtdemux->active_streams; iter; iter = g_list_next (iter)) {
1880     QtDemuxStream *str;
1881     gint inc;
1882     gboolean set_sample;
1883
1884     str = QTDEMUX_STREAM (iter->data);
1885     set_sample = !set;
1886
1887     if (fw) {
1888       i = 0;
1889       inc = 1;
1890     } else {
1891       i = str->n_samples - 1;
1892       inc = -1;
1893     }
1894
1895     for (; (i >= 0) && (i < str->n_samples); i += inc) {
1896       if (str->samples[i].size == 0)
1897         continue;
1898
1899       if (fw && (str->samples[i].offset < byte_pos))
1900         continue;
1901
1902       if (!fw && (str->samples[i].offset + str->samples[i].size > byte_pos))
1903         continue;
1904
1905       /* move stream to first available sample */
1906       if (set) {
1907         gst_qtdemux_move_stream (qtdemux, str, i);
1908         set_sample = TRUE;
1909       }
1910
1911       /* avoid index from sparse streams since they might be far away */
1912       if (!CUR_STREAM (str)->sparse) {
1913         /* determine min/max time */
1914         time = QTSAMPLE_PTS (str, &str->samples[i]);
1915         if (min_time == -1 || (!fw && time > min_time) ||
1916             (fw && time < min_time)) {
1917           min_time = time;
1918         }
1919
1920         /* determine stream with leading sample, to get its position */
1921         if (!stream ||
1922             (fw && (str->samples[i].offset < stream->samples[index].offset)) ||
1923             (!fw && (str->samples[i].offset > stream->samples[index].offset))) {
1924           stream = str;
1925           index = i;
1926         }
1927       }
1928       break;
1929     }
1930
1931     /* no sample for this stream, mark eos */
1932     if (!set_sample)
1933       gst_qtdemux_move_stream (qtdemux, str, str->n_samples);
1934   }
1935
1936   if (_time)
1937     *_time = min_time;
1938   if (_stream)
1939     *_stream = stream;
1940   if (_index)
1941     *_index = index;
1942 }
1943
1944 /* Copied from mpegtsbase code */
1945 /* FIXME: replace this function when we add new util function for stream-id creation */
1946 static gchar *
1947 _get_upstream_id (GstQTDemux * demux)
1948 {
1949   gchar *upstream_id = gst_pad_get_stream_id (demux->sinkpad);
1950
1951   if (!upstream_id) {
1952     /* Try to create one from the upstream URI, else use a randome number */
1953     GstQuery *query;
1954     gchar *uri = NULL;
1955
1956     /* Try to generate one from the URI query and
1957      * if it fails take a random number instead */
1958     query = gst_query_new_uri ();
1959     if (gst_element_query (GST_ELEMENT_CAST (demux), query)) {
1960       gst_query_parse_uri (query, &uri);
1961     }
1962
1963     if (uri) {
1964       GChecksum *cs;
1965
1966       /* And then generate an SHA256 sum of the URI */
1967       cs = g_checksum_new (G_CHECKSUM_SHA256);
1968       g_checksum_update (cs, (const guchar *) uri, strlen (uri));
1969       g_free (uri);
1970       upstream_id = g_strdup (g_checksum_get_string (cs));
1971       g_checksum_free (cs);
1972     } else {
1973       /* Just get some random number if the URI query fails */
1974       GST_FIXME_OBJECT (demux, "Creating random stream-id, consider "
1975           "implementing a deterministic way of creating a stream-id");
1976       upstream_id =
1977           g_strdup_printf ("%08x%08x%08x%08x", g_random_int (), g_random_int (),
1978           g_random_int (), g_random_int ());
1979     }
1980
1981     gst_query_unref (query);
1982   }
1983   return upstream_id;
1984 }
1985
1986 static QtDemuxStream *
1987 _create_stream (GstQTDemux * demux, guint32 track_id)
1988 {
1989   QtDemuxStream *stream;
1990   gchar *upstream_id;
1991
1992   stream = g_new0 (QtDemuxStream, 1);
1993   stream->demux = demux;
1994   stream->track_id = track_id;
1995   upstream_id = _get_upstream_id (demux);
1996   stream->stream_id = g_strdup_printf ("%s/%03u", upstream_id, track_id);
1997   g_free (upstream_id);
1998   /* new streams always need a discont */
1999   stream->discont = TRUE;
2000   /* we enable clipping for raw audio/video streams */
2001   stream->need_clip = FALSE;
2002   stream->need_process = FALSE;
2003   stream->segment_index = -1;
2004   stream->time_position = 0;
2005   stream->sample_index = -1;
2006   stream->offset_in_sample = 0;
2007   stream->new_stream = TRUE;
2008   stream->multiview_mode = GST_VIDEO_MULTIVIEW_MODE_NONE;
2009   stream->multiview_flags = GST_VIDEO_MULTIVIEW_FLAGS_NONE;
2010   stream->protected = FALSE;
2011   stream->protection_scheme_type = 0;
2012   stream->protection_scheme_version = 0;
2013   stream->protection_scheme_info = NULL;
2014   stream->n_samples_moof = 0;
2015   stream->duration_moof = 0;
2016   stream->duration_last_moof = 0;
2017   stream->alignment = 1;
2018   stream->stream_tags = gst_tag_list_new_empty ();
2019   gst_tag_list_set_scope (stream->stream_tags, GST_TAG_SCOPE_STREAM);
2020   g_queue_init (&stream->protection_scheme_event_queue);
2021   return stream;
2022 }
2023
2024 static gboolean
2025 gst_qtdemux_setcaps (GstQTDemux * demux, GstCaps * caps)
2026 {
2027   GstStructure *structure;
2028   const gchar *variant;
2029   const GstCaps *mediacaps = NULL;
2030
2031   GST_DEBUG_OBJECT (demux, "Sink set caps: %" GST_PTR_FORMAT, caps);
2032
2033   structure = gst_caps_get_structure (caps, 0);
2034   variant = gst_structure_get_string (structure, "variant");
2035
2036   if (variant && strcmp (variant, "mss-fragmented") == 0) {
2037     QtDemuxStream *stream;
2038     const GValue *value;
2039
2040     demux->fragmented = TRUE;
2041     demux->mss_mode = TRUE;
2042
2043     if (demux->n_streams > 1) {
2044       /* can't do this, we can only renegotiate for another mss format */
2045       return FALSE;
2046     }
2047
2048     value = gst_structure_get_value (structure, "media-caps");
2049     /* create stream */
2050     if (value) {
2051       const GValue *timescale_v;
2052
2053       /* TODO update when stream changes during playback */
2054
2055       if (demux->n_streams == 0) {
2056         stream = _create_stream (demux, 1);
2057         demux->active_streams = g_list_append (demux->active_streams, stream);
2058         demux->n_streams = 1;
2059         /* mss has no stsd/stsd entry, use id 0 as default */
2060         stream->stsd_entries_length = 1;
2061         stream->stsd_sample_description_id = stream->cur_stsd_entry_index = 0;
2062         stream->stsd_entries = g_new0 (QtDemuxStreamStsdEntry, 1);
2063       } else {
2064         stream = QTDEMUX_FIRST_STREAM (demux);
2065       }
2066
2067       timescale_v = gst_structure_get_value (structure, "timescale");
2068       if (timescale_v) {
2069         stream->timescale = g_value_get_uint64 (timescale_v);
2070       } else {
2071         /* default mss timescale */
2072         stream->timescale = 10000000;
2073       }
2074       demux->timescale = stream->timescale;
2075
2076       mediacaps = gst_value_get_caps (value);
2077       if (!CUR_STREAM (stream)->caps
2078           || !gst_caps_is_equal_fixed (mediacaps, CUR_STREAM (stream)->caps)) {
2079         GST_DEBUG_OBJECT (demux, "We have a new caps %" GST_PTR_FORMAT,
2080             mediacaps);
2081         stream->new_caps = TRUE;
2082       }
2083       gst_caps_replace (&CUR_STREAM (stream)->caps, (GstCaps *) mediacaps);
2084       structure = gst_caps_get_structure (mediacaps, 0);
2085       if (g_str_has_prefix (gst_structure_get_name (structure), "video")) {
2086         stream->subtype = FOURCC_vide;
2087
2088         gst_structure_get_int (structure, "width", &CUR_STREAM (stream)->width);
2089         gst_structure_get_int (structure, "height",
2090             &CUR_STREAM (stream)->height);
2091         gst_structure_get_fraction (structure, "framerate",
2092             &CUR_STREAM (stream)->fps_n, &CUR_STREAM (stream)->fps_d);
2093       } else if (g_str_has_prefix (gst_structure_get_name (structure), "audio")) {
2094         gint rate = 0;
2095         stream->subtype = FOURCC_soun;
2096         gst_structure_get_int (structure, "channels",
2097             &CUR_STREAM (stream)->n_channels);
2098         gst_structure_get_int (structure, "rate", &rate);
2099         CUR_STREAM (stream)->rate = rate;
2100       }
2101     }
2102     gst_caps_replace (&demux->media_caps, (GstCaps *) mediacaps);
2103   } else {
2104     demux->mss_mode = FALSE;
2105   }
2106
2107   return TRUE;
2108 }
2109
2110 static void
2111 gst_qtdemux_reset (GstQTDemux * qtdemux, gboolean hard)
2112 {
2113   GList *iter;
2114
2115   GST_DEBUG_OBJECT (qtdemux, "Resetting demux");
2116   gst_pad_stop_task (qtdemux->sinkpad);
2117
2118   if (hard || qtdemux->upstream_format_is_time) {
2119     qtdemux->state = QTDEMUX_STATE_INITIAL;
2120     qtdemux->neededbytes = 16;
2121     qtdemux->todrop = 0;
2122     qtdemux->pullbased = FALSE;
2123     qtdemux->posted_redirect = FALSE;
2124     qtdemux->first_mdat = -1;
2125     qtdemux->header_size = 0;
2126     qtdemux->mdatoffset = -1;
2127     qtdemux->restoredata_offset = -1;
2128     if (qtdemux->mdatbuffer)
2129       gst_buffer_unref (qtdemux->mdatbuffer);
2130     if (qtdemux->restoredata_buffer)
2131       gst_buffer_unref (qtdemux->restoredata_buffer);
2132     qtdemux->mdatbuffer = NULL;
2133     qtdemux->restoredata_buffer = NULL;
2134     qtdemux->mdatleft = 0;
2135     qtdemux->mdatsize = 0;
2136     if (qtdemux->comp_brands)
2137       gst_buffer_unref (qtdemux->comp_brands);
2138     qtdemux->comp_brands = NULL;
2139     qtdemux->last_moov_offset = -1;
2140     if (qtdemux->moov_node_compressed) {
2141       g_node_destroy (qtdemux->moov_node_compressed);
2142       if (qtdemux->moov_node)
2143         g_free (qtdemux->moov_node->data);
2144     }
2145     qtdemux->moov_node_compressed = NULL;
2146     if (qtdemux->moov_node)
2147       g_node_destroy (qtdemux->moov_node);
2148     qtdemux->moov_node = NULL;
2149     if (qtdemux->tag_list)
2150       gst_mini_object_unref (GST_MINI_OBJECT_CAST (qtdemux->tag_list));
2151     qtdemux->tag_list = gst_tag_list_new_empty ();
2152     gst_tag_list_set_scope (qtdemux->tag_list, GST_TAG_SCOPE_GLOBAL);
2153 #if 0
2154     if (qtdemux->element_index)
2155       gst_object_unref (qtdemux->element_index);
2156     qtdemux->element_index = NULL;
2157 #endif
2158     qtdemux->major_brand = 0;
2159     qtdemux->upstream_format_is_time = FALSE;
2160     qtdemux->upstream_seekable = FALSE;
2161     qtdemux->upstream_size = 0;
2162
2163     qtdemux->fragment_start = -1;
2164     qtdemux->fragment_start_offset = -1;
2165     qtdemux->duration = 0;
2166     qtdemux->moof_offset = 0;
2167     qtdemux->chapters_track_id = 0;
2168     qtdemux->have_group_id = FALSE;
2169     qtdemux->group_id = G_MAXUINT;
2170
2171     g_queue_foreach (&qtdemux->protection_event_queue, (GFunc) gst_event_unref,
2172         NULL);
2173     g_queue_clear (&qtdemux->protection_event_queue);
2174   }
2175   qtdemux->offset = 0;
2176   gst_adapter_clear (qtdemux->adapter);
2177   gst_segment_init (&qtdemux->segment, GST_FORMAT_TIME);
2178   qtdemux->segment_seqnum = GST_SEQNUM_INVALID;
2179   qtdemux->need_segment = TRUE;
2180
2181   if (hard) {
2182     g_list_free_full (qtdemux->active_streams,
2183         (GDestroyNotify) gst_qtdemux_stream_free);
2184     g_list_free_full (qtdemux->old_streams,
2185         (GDestroyNotify) gst_qtdemux_stream_free);
2186     qtdemux->active_streams = NULL;
2187     qtdemux->old_streams = NULL;
2188     qtdemux->n_streams = 0;
2189     qtdemux->n_video_streams = 0;
2190     qtdemux->n_audio_streams = 0;
2191     qtdemux->n_sub_streams = 0;
2192     qtdemux->exposed = FALSE;
2193     qtdemux->fragmented = FALSE;
2194     qtdemux->mss_mode = FALSE;
2195     gst_caps_replace (&qtdemux->media_caps, NULL);
2196     qtdemux->timescale = 0;
2197     qtdemux->got_moov = FALSE;
2198     qtdemux->cenc_aux_info_offset = 0;
2199     qtdemux->cenc_aux_info_sizes = NULL;
2200     qtdemux->cenc_aux_sample_count = 0;
2201     if (qtdemux->protection_system_ids) {
2202       g_ptr_array_free (qtdemux->protection_system_ids, TRUE);
2203       qtdemux->protection_system_ids = NULL;
2204     }
2205     qtdemux->streams_aware = GST_OBJECT_PARENT (qtdemux)
2206         && GST_OBJECT_FLAG_IS_SET (GST_OBJECT_PARENT (qtdemux),
2207         GST_BIN_FLAG_STREAMS_AWARE);
2208
2209     if (qtdemux->preferred_protection_system_id) {
2210       g_free (qtdemux->preferred_protection_system_id);
2211       qtdemux->preferred_protection_system_id = NULL;
2212     }
2213   } else if (qtdemux->mss_mode) {
2214     gst_flow_combiner_reset (qtdemux->flowcombiner);
2215     g_list_foreach (qtdemux->active_streams,
2216         (GFunc) gst_qtdemux_stream_clear, NULL);
2217   } else {
2218     gst_flow_combiner_reset (qtdemux->flowcombiner);
2219     for (iter = qtdemux->active_streams; iter; iter = g_list_next (iter)) {
2220       QtDemuxStream *stream = QTDEMUX_STREAM (iter->data);
2221       stream->sent_eos = FALSE;
2222       stream->time_position = 0;
2223       stream->accumulated_base = 0;
2224     }
2225   }
2226 }
2227
2228
2229 /* Maps the @segment to the qt edts internal segments and pushes
2230  * the correspnding segment event.
2231  *
2232  * If it ends up being at a empty segment, a gap will be pushed and the next
2233  * edts segment will be activated in sequence.
2234  *
2235  * To be used in push-mode only */
2236 static void
2237 gst_qtdemux_map_and_push_segments (GstQTDemux * qtdemux, GstSegment * segment)
2238 {
2239   gint i;
2240   GList *iter;
2241
2242   for (iter = qtdemux->active_streams; iter; iter = g_list_next (iter)) {
2243     QtDemuxStream *stream = QTDEMUX_STREAM (iter->data);
2244
2245     stream->time_position = segment->start;
2246
2247     /* in push mode we should be guaranteed that we will have empty segments
2248      * at the beginning and then one segment after, other scenarios are not
2249      * supported and are discarded when parsing the edts */
2250     for (i = 0; i < stream->n_segments; i++) {
2251       if (stream->segments[i].stop_time > segment->start) {
2252         /* push the empty segment and move to the next one */
2253         gst_qtdemux_activate_segment (qtdemux, stream, i,
2254             stream->time_position);
2255         if (QTSEGMENT_IS_EMPTY (&stream->segments[i])) {
2256           gst_qtdemux_send_gap_for_segment (qtdemux, stream, i,
2257               stream->time_position);
2258
2259           /* accumulate previous segments */
2260           if (GST_CLOCK_TIME_IS_VALID (stream->segment.stop))
2261             stream->accumulated_base +=
2262                 (stream->segment.stop -
2263                 stream->segment.start) / ABS (stream->segment.rate);
2264           continue;
2265         }
2266
2267         g_assert (i == stream->n_segments - 1);
2268       }
2269     }
2270   }
2271 }
2272
2273 static gboolean
2274 gst_qtdemux_handle_sink_event (GstPad * sinkpad, GstObject * parent,
2275     GstEvent * event)
2276 {
2277   GstQTDemux *demux = GST_QTDEMUX (parent);
2278   gboolean res = TRUE;
2279
2280   GST_LOG_OBJECT (demux, "handling %s event", GST_EVENT_TYPE_NAME (event));
2281
2282   switch (GST_EVENT_TYPE (event)) {
2283     case GST_EVENT_SEGMENT:
2284     {
2285       gint64 offset = 0;
2286       QtDemuxStream *stream;
2287       gint idx;
2288       GstSegment segment;
2289
2290       /* some debug output */
2291       gst_event_copy_segment (event, &segment);
2292       GST_DEBUG_OBJECT (demux, "received newsegment %" GST_SEGMENT_FORMAT,
2293           &segment);
2294
2295       if (segment.format == GST_FORMAT_TIME) {
2296         demux->upstream_format_is_time = TRUE;
2297       } else {
2298         GST_DEBUG_OBJECT (demux, "Not storing upstream newsegment, "
2299             "not in time format");
2300
2301         /* chain will send initial newsegment after pads have been added */
2302         if (demux->state != QTDEMUX_STATE_MOVIE || !demux->n_streams) {
2303           GST_DEBUG_OBJECT (demux, "still starting, eating event");
2304           goto exit;
2305         }
2306       }
2307
2308       /* check if this matches a time seek we received previously
2309        * FIXME for backwards compatibility reasons we use the
2310        * seek_offset here to compare. In the future we might want to
2311        * change this to use the seqnum as it uniquely should identify
2312        * the segment that corresponds to the seek. */
2313       GST_DEBUG_OBJECT (demux, "Stored seek offset: %" G_GINT64_FORMAT
2314           ", received segment offset %" G_GINT64_FORMAT,
2315           demux->seek_offset, segment.start);
2316       if (segment.format == GST_FORMAT_BYTES
2317           && demux->seek_offset == segment.start) {
2318         GST_OBJECT_LOCK (demux);
2319         offset = segment.start;
2320
2321         segment.format = GST_FORMAT_TIME;
2322         segment.start = demux->push_seek_start;
2323         segment.stop = demux->push_seek_stop;
2324         GST_DEBUG_OBJECT (demux, "Replaced segment with stored seek "
2325             "segment %" GST_TIME_FORMAT " - %" GST_TIME_FORMAT,
2326             GST_TIME_ARGS (segment.start), GST_TIME_ARGS (segment.stop));
2327         GST_OBJECT_UNLOCK (demux);
2328       }
2329
2330       /* we only expect a BYTE segment, e.g. following a seek */
2331       if (segment.format == GST_FORMAT_BYTES) {
2332         if (GST_CLOCK_TIME_IS_VALID (segment.start)) {
2333           offset = segment.start;
2334
2335           gst_qtdemux_find_sample (demux, segment.start, TRUE, FALSE, NULL,
2336               NULL, (gint64 *) & segment.start);
2337           if ((gint64) segment.start < 0)
2338             segment.start = 0;
2339         }
2340         if (GST_CLOCK_TIME_IS_VALID (segment.stop)) {
2341           gst_qtdemux_find_sample (demux, segment.stop, FALSE, FALSE, NULL,
2342               NULL, (gint64 *) & segment.stop);
2343           /* keyframe seeking should already arrange for start >= stop,
2344            * but make sure in other rare cases */
2345           segment.stop = MAX (segment.stop, segment.start);
2346         }
2347       } else if (segment.format == GST_FORMAT_TIME) {
2348         /* push all data on the adapter before starting this
2349          * new segment */
2350         gst_qtdemux_process_adapter (demux, TRUE);
2351       } else {
2352         GST_DEBUG_OBJECT (demux, "unsupported segment format, ignoring");
2353         goto exit;
2354       }
2355
2356       /* We shouldn't modify upstream driven TIME FORMAT segment */
2357       if (!demux->upstream_format_is_time) {
2358         /* accept upstream's notion of segment and distribute along */
2359         segment.format = GST_FORMAT_TIME;
2360         segment.position = segment.time = segment.start;
2361         segment.duration = demux->segment.duration;
2362         segment.base = gst_segment_to_running_time (&demux->segment,
2363             GST_FORMAT_TIME, demux->segment.position);
2364       }
2365
2366       gst_segment_copy_into (&segment, &demux->segment);
2367       GST_DEBUG_OBJECT (demux, "Pushing newseg %" GST_SEGMENT_FORMAT, &segment);
2368
2369       /* map segment to internal qt segments and push on each stream */
2370       if (demux->n_streams) {
2371         if (demux->fragmented) {
2372           GstEvent *segment_event = gst_event_new_segment (&segment);
2373
2374           gst_event_set_seqnum (segment_event, demux->segment_seqnum);
2375           gst_qtdemux_push_event (demux, segment_event);
2376         } else {
2377           gst_qtdemux_map_and_push_segments (demux, &segment);
2378         }
2379         /* keep need-segment as is in case this is the segment before
2380          * fragmented data, we might not have pads yet to push it */
2381         if (demux->exposed)
2382           demux->need_segment = FALSE;
2383       }
2384
2385       /* clear leftover in current segment, if any */
2386       gst_adapter_clear (demux->adapter);
2387
2388       /* set up streaming thread */
2389       demux->offset = offset;
2390       if (demux->upstream_format_is_time) {
2391         GST_DEBUG_OBJECT (demux, "Upstream is driving in time format, "
2392             "set values to restart reading from a new atom");
2393         demux->neededbytes = 16;
2394         demux->todrop = 0;
2395       } else {
2396         gst_qtdemux_find_sample (demux, offset, TRUE, TRUE, &stream, &idx,
2397             NULL);
2398         if (stream) {
2399           demux->todrop = stream->samples[idx].offset - offset;
2400           demux->neededbytes = demux->todrop + stream->samples[idx].size;
2401         } else {
2402           /* set up for EOS */
2403           demux->neededbytes = -1;
2404           demux->todrop = 0;
2405         }
2406       }
2407     exit:
2408       gst_event_unref (event);
2409       res = TRUE;
2410       goto drop;
2411     }
2412     case GST_EVENT_FLUSH_START:
2413     {
2414       if (gst_event_get_seqnum (event) == demux->offset_seek_seqnum) {
2415         gst_event_unref (event);
2416         goto drop;
2417       }
2418       QTDEMUX_EXPOSE_LOCK (demux);
2419       res = gst_pad_event_default (demux->sinkpad, parent, event);
2420       QTDEMUX_EXPOSE_UNLOCK (demux);
2421       goto drop;
2422     }
2423     case GST_EVENT_FLUSH_STOP:
2424     {
2425       guint64 dur;
2426
2427       dur = demux->segment.duration;
2428       gst_qtdemux_reset (demux, FALSE);
2429       demux->segment.duration = dur;
2430
2431       if (gst_event_get_seqnum (event) == demux->offset_seek_seqnum) {
2432         gst_event_unref (event);
2433         goto drop;
2434       }
2435       break;
2436     }
2437     case GST_EVENT_EOS:
2438       /* If we are in push mode, and get an EOS before we've seen any streams,
2439        * then error out - we have nowhere to send the EOS */
2440       if (!demux->pullbased) {
2441         GList *iter;
2442         gboolean has_valid_stream = FALSE;
2443         for (iter = demux->active_streams; iter; iter = g_list_next (iter)) {
2444           if (QTDEMUX_STREAM (iter->data)->pad != NULL) {
2445             has_valid_stream = TRUE;
2446             break;
2447           }
2448         }
2449         if (!has_valid_stream)
2450           gst_qtdemux_post_no_playable_stream_error (demux);
2451         else {
2452           GST_DEBUG_OBJECT (demux, "Data still available after EOS: %u",
2453               (guint) gst_adapter_available (demux->adapter));
2454           if (gst_qtdemux_process_adapter (demux, TRUE) != GST_FLOW_OK) {
2455             res = FALSE;
2456           }
2457         }
2458       }
2459       break;
2460     case GST_EVENT_CAPS:{
2461       GstCaps *caps = NULL;
2462
2463       gst_event_parse_caps (event, &caps);
2464       gst_qtdemux_setcaps (demux, caps);
2465       res = TRUE;
2466       gst_event_unref (event);
2467       goto drop;
2468     }
2469     case GST_EVENT_PROTECTION:
2470     {
2471       const gchar *system_id = NULL;
2472
2473       gst_event_parse_protection (event, &system_id, NULL, NULL);
2474       GST_DEBUG_OBJECT (demux, "Received protection event for system ID %s",
2475           system_id);
2476       gst_qtdemux_append_protection_system_id (demux, system_id);
2477       /* save the event for later, for source pads that have not been created */
2478       g_queue_push_tail (&demux->protection_event_queue, gst_event_ref (event));
2479       /* send it to all pads that already exist */
2480       gst_qtdemux_push_event (demux, event);
2481       res = TRUE;
2482       goto drop;
2483     }
2484     case GST_EVENT_STREAM_START:
2485     {
2486       res = TRUE;
2487       gst_event_unref (event);
2488
2489       /* Drain all the buffers */
2490       gst_qtdemux_process_adapter (demux, TRUE);
2491       gst_qtdemux_reset (demux, FALSE);
2492       /* We expect new moov box after new stream-start event */
2493       demux->old_streams =
2494           g_list_concat (demux->old_streams, demux->active_streams);
2495       demux->active_streams = NULL;
2496
2497       goto drop;
2498     }
2499     default:
2500       break;
2501   }
2502
2503   res = gst_pad_event_default (demux->sinkpad, parent, event) & res;
2504
2505 drop:
2506   return res;
2507 }
2508
2509 #if 0
2510 static void
2511 gst_qtdemux_set_index (GstElement * element, GstIndex * index)
2512 {
2513   GstQTDemux *demux = GST_QTDEMUX (element);
2514
2515   GST_OBJECT_LOCK (demux);
2516   if (demux->element_index)
2517     gst_object_unref (demux->element_index);
2518   if (index) {
2519     demux->element_index = gst_object_ref (index);
2520   } else {
2521     demux->element_index = NULL;
2522   }
2523   GST_OBJECT_UNLOCK (demux);
2524   /* object lock might be taken again */
2525   if (index)
2526     gst_index_get_writer_id (index, GST_OBJECT (element), &demux->index_id);
2527   GST_DEBUG_OBJECT (demux, "Set index %" GST_PTR_FORMAT "for writer id %d",
2528       demux->element_index, demux->index_id);
2529 }
2530
2531 static GstIndex *
2532 gst_qtdemux_get_index (GstElement * element)
2533 {
2534   GstIndex *result = NULL;
2535   GstQTDemux *demux = GST_QTDEMUX (element);
2536
2537   GST_OBJECT_LOCK (demux);
2538   if (demux->element_index)
2539     result = gst_object_ref (demux->element_index);
2540   GST_OBJECT_UNLOCK (demux);
2541
2542   GST_DEBUG_OBJECT (demux, "Returning index %" GST_PTR_FORMAT, result);
2543
2544   return result;
2545 }
2546 #endif
2547
2548 static void
2549 gst_qtdemux_stbl_free (QtDemuxStream * stream)
2550 {
2551   g_free ((gpointer) stream->stco.data);
2552   stream->stco.data = NULL;
2553   g_free ((gpointer) stream->stsz.data);
2554   stream->stsz.data = NULL;
2555   g_free ((gpointer) stream->stsc.data);
2556   stream->stsc.data = NULL;
2557   g_free ((gpointer) stream->stts.data);
2558   stream->stts.data = NULL;
2559   g_free ((gpointer) stream->stss.data);
2560   stream->stss.data = NULL;
2561   g_free ((gpointer) stream->stps.data);
2562   stream->stps.data = NULL;
2563   g_free ((gpointer) stream->ctts.data);
2564   stream->ctts.data = NULL;
2565 }
2566
2567 static void
2568 gst_qtdemux_stream_flush_segments_data (QtDemuxStream * stream)
2569 {
2570   g_free (stream->segments);
2571   stream->segments = NULL;
2572   stream->segment_index = -1;
2573   stream->accumulated_base = 0;
2574 }
2575
2576 static void
2577 gst_qtdemux_stream_flush_samples_data (QtDemuxStream * stream)
2578 {
2579   g_free (stream->samples);
2580   stream->samples = NULL;
2581   gst_qtdemux_stbl_free (stream);
2582
2583   /* fragments */
2584   g_free (stream->ra_entries);
2585   stream->ra_entries = NULL;
2586   stream->n_ra_entries = 0;
2587
2588   stream->sample_index = -1;
2589   stream->stbl_index = -1;
2590   stream->n_samples = 0;
2591   stream->time_position = 0;
2592
2593   stream->n_samples_moof = 0;
2594   stream->duration_moof = 0;
2595   stream->duration_last_moof = 0;
2596 }
2597
2598 static void
2599 gst_qtdemux_stream_clear (QtDemuxStream * stream)
2600 {
2601   gint i;
2602   if (stream->allocator)
2603     gst_object_unref (stream->allocator);
2604   while (stream->buffers) {
2605     gst_buffer_unref (GST_BUFFER_CAST (stream->buffers->data));
2606     stream->buffers = g_slist_delete_link (stream->buffers, stream->buffers);
2607   }
2608   for (i = 0; i < stream->stsd_entries_length; i++) {
2609     QtDemuxStreamStsdEntry *entry = &stream->stsd_entries[i];
2610     if (entry->rgb8_palette) {
2611       gst_memory_unref (entry->rgb8_palette);
2612       entry->rgb8_palette = NULL;
2613     }
2614     entry->sparse = FALSE;
2615   }
2616
2617   if (stream->stream_tags)
2618     gst_tag_list_unref (stream->stream_tags);
2619
2620   stream->stream_tags = gst_tag_list_new_empty ();
2621   gst_tag_list_set_scope (stream->stream_tags, GST_TAG_SCOPE_STREAM);
2622   g_free (stream->redirect_uri);
2623   stream->redirect_uri = NULL;
2624   stream->sent_eos = FALSE;
2625   stream->protected = FALSE;
2626   if (stream->protection_scheme_info) {
2627     if (stream->protection_scheme_type == FOURCC_cenc) {
2628       QtDemuxCencSampleSetInfo *info =
2629           (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
2630       if (info->default_properties)
2631         gst_structure_free (info->default_properties);
2632       if (info->crypto_info)
2633         g_ptr_array_free (info->crypto_info, TRUE);
2634     }
2635     g_free (stream->protection_scheme_info);
2636     stream->protection_scheme_info = NULL;
2637   }
2638   stream->protection_scheme_type = 0;
2639   stream->protection_scheme_version = 0;
2640   g_queue_foreach (&stream->protection_scheme_event_queue,
2641       (GFunc) gst_event_unref, NULL);
2642   g_queue_clear (&stream->protection_scheme_event_queue);
2643   gst_qtdemux_stream_flush_segments_data (stream);
2644   gst_qtdemux_stream_flush_samples_data (stream);
2645 }
2646
2647 static void
2648 gst_qtdemux_stream_reset (QtDemuxStream * stream)
2649 {
2650   gint i;
2651   gst_qtdemux_stream_clear (stream);
2652   for (i = 0; i < stream->stsd_entries_length; i++) {
2653     QtDemuxStreamStsdEntry *entry = &stream->stsd_entries[i];
2654     if (entry->caps) {
2655       gst_caps_unref (entry->caps);
2656       entry->caps = NULL;
2657     }
2658   }
2659   g_free (stream->stsd_entries);
2660   stream->stsd_entries = NULL;
2661   stream->stsd_entries_length = 0;
2662 }
2663
2664
2665 static void
2666 gst_qtdemux_stream_free (QtDemuxStream * stream)
2667 {
2668   gst_qtdemux_stream_reset (stream);
2669   gst_tag_list_unref (stream->stream_tags);
2670   if (stream->pad) {
2671     GstQTDemux *demux = stream->demux;
2672     gst_element_remove_pad (GST_ELEMENT_CAST (demux), stream->pad);
2673     gst_flow_combiner_remove_pad (demux->flowcombiner, stream->pad);
2674   }
2675   g_free (stream->stream_id);
2676   g_free (stream);
2677 }
2678
2679 static void
2680 gst_qtdemux_remove_stream (GstQTDemux * qtdemux, QtDemuxStream * stream)
2681 {
2682   qtdemux->active_streams = g_list_remove (qtdemux->active_streams, stream);
2683   gst_qtdemux_stream_free (stream);
2684   qtdemux->n_streams--;
2685 }
2686
2687 static GstStateChangeReturn
2688 gst_qtdemux_change_state (GstElement * element, GstStateChange transition)
2689 {
2690   GstQTDemux *qtdemux = GST_QTDEMUX (element);
2691   GstStateChangeReturn result = GST_STATE_CHANGE_FAILURE;
2692
2693   switch (transition) {
2694     case GST_STATE_CHANGE_READY_TO_PAUSED:
2695       gst_qtdemux_reset (qtdemux, TRUE);
2696       break;
2697     default:
2698       break;
2699   }
2700
2701   result = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
2702
2703   switch (transition) {
2704     case GST_STATE_CHANGE_PAUSED_TO_READY:{
2705       gst_qtdemux_reset (qtdemux, TRUE);
2706       break;
2707     }
2708     default:
2709       break;
2710   }
2711
2712   return result;
2713 }
2714
2715 static void
2716 gst_qtdemux_set_context (GstElement * element, GstContext * context)
2717 {
2718   GstQTDemux *qtdemux = GST_QTDEMUX (element);
2719
2720   g_return_if_fail (GST_IS_CONTEXT (context));
2721
2722   if (gst_context_has_context_type (context,
2723           "drm-preferred-decryption-system-id")) {
2724     const GstStructure *s;
2725
2726     s = gst_context_get_structure (context);
2727     g_free (qtdemux->preferred_protection_system_id);
2728     qtdemux->preferred_protection_system_id =
2729         g_strdup (gst_structure_get_string (s, "decryption-system-id"));
2730     GST_DEBUG_OBJECT (element, "set preferred decryption system to %s",
2731         qtdemux->preferred_protection_system_id);
2732   }
2733
2734   GST_ELEMENT_CLASS (parent_class)->set_context (element, context);
2735 }
2736
2737 static void
2738 qtdemux_parse_ftyp (GstQTDemux * qtdemux, const guint8 * buffer, gint length)
2739 {
2740   /* counts as header data */
2741   qtdemux->header_size += length;
2742
2743   /* only consider at least a sufficiently complete ftyp atom */
2744   if (length >= 20) {
2745     GstBuffer *buf;
2746
2747     qtdemux->major_brand = QT_FOURCC (buffer + 8);
2748     GST_DEBUG_OBJECT (qtdemux, "major brand: %" GST_FOURCC_FORMAT,
2749         GST_FOURCC_ARGS (qtdemux->major_brand));
2750     if (qtdemux->comp_brands)
2751       gst_buffer_unref (qtdemux->comp_brands);
2752     buf = qtdemux->comp_brands = gst_buffer_new_and_alloc (length - 16);
2753     gst_buffer_fill (buf, 0, buffer + 16, length - 16);
2754   }
2755 }
2756
2757 static void
2758 qtdemux_handle_xmp_taglist (GstQTDemux * qtdemux, GstTagList * taglist,
2759     GstTagList * xmptaglist)
2760 {
2761   /* Strip out bogus fields */
2762   if (xmptaglist) {
2763     if (gst_tag_list_get_scope (taglist) == GST_TAG_SCOPE_GLOBAL) {
2764       gst_tag_list_remove_tag (xmptaglist, GST_TAG_VIDEO_CODEC);
2765       gst_tag_list_remove_tag (xmptaglist, GST_TAG_AUDIO_CODEC);
2766     } else {
2767       gst_tag_list_remove_tag (xmptaglist, GST_TAG_CONTAINER_FORMAT);
2768     }
2769
2770     GST_DEBUG_OBJECT (qtdemux, "Found XMP tags %" GST_PTR_FORMAT, xmptaglist);
2771
2772     /* prioritize native tags using _KEEP mode */
2773     gst_tag_list_insert (taglist, xmptaglist, GST_TAG_MERGE_KEEP);
2774     gst_tag_list_unref (xmptaglist);
2775   }
2776 }
2777
2778 static void
2779 qtdemux_parse_piff (GstQTDemux * qtdemux, const guint8 * buffer, gint length,
2780     guint offset)
2781 {
2782   GstByteReader br;
2783   guint8 version;
2784   guint32 flags = 0;
2785   guint i;
2786   guint8 iv_size = 8;
2787   QtDemuxStream *stream;
2788   GstStructure *structure;
2789   QtDemuxCencSampleSetInfo *ss_info = NULL;
2790   const gchar *system_id;
2791   gboolean uses_sub_sample_encryption = FALSE;
2792   guint32 sample_count;
2793
2794   stream = QTDEMUX_FIRST_STREAM (qtdemux);
2795   if (!stream)
2796     return;
2797
2798   structure = gst_caps_get_structure (CUR_STREAM (stream)->caps, 0);
2799   if (!gst_structure_has_name (structure, "application/x-cenc")) {
2800     GST_WARNING_OBJECT (qtdemux,
2801         "Attempting PIFF box parsing on an unencrypted stream.");
2802     return;
2803   }
2804
2805   gst_structure_get (structure, GST_PROTECTION_SYSTEM_ID_CAPS_FIELD,
2806       G_TYPE_STRING, &system_id, NULL);
2807   gst_qtdemux_append_protection_system_id (qtdemux, system_id);
2808
2809   stream->protected = TRUE;
2810   stream->protection_scheme_type = FOURCC_cenc;
2811
2812   if (!stream->protection_scheme_info)
2813     stream->protection_scheme_info = g_new0 (QtDemuxCencSampleSetInfo, 1);
2814
2815   ss_info = (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
2816
2817   if (ss_info->default_properties)
2818     gst_structure_free (ss_info->default_properties);
2819
2820   ss_info->default_properties =
2821       gst_structure_new ("application/x-cenc",
2822       "iv_size", G_TYPE_UINT, iv_size, "encrypted", G_TYPE_BOOLEAN, TRUE, NULL);
2823
2824   if (ss_info->crypto_info) {
2825     GST_LOG_OBJECT (qtdemux, "unreffing existing crypto_info");
2826     g_ptr_array_free (ss_info->crypto_info, TRUE);
2827     ss_info->crypto_info = NULL;
2828   }
2829
2830   /* skip UUID */
2831   gst_byte_reader_init (&br, buffer + offset + 16, length - offset - 16);
2832
2833   if (!gst_byte_reader_get_uint8 (&br, &version)) {
2834     GST_ERROR_OBJECT (qtdemux, "Error getting box's version field");
2835     return;
2836   }
2837
2838   if (!gst_byte_reader_get_uint24_be (&br, &flags)) {
2839     GST_ERROR_OBJECT (qtdemux, "Error getting box's flags field");
2840     return;
2841   }
2842
2843   if ((flags & 0x000001)) {
2844     guint32 algorithm_id = 0;
2845     const guint8 *kid;
2846     GstBuffer *kid_buf;
2847     gboolean is_encrypted = TRUE;
2848
2849     if (!gst_byte_reader_get_uint24_le (&br, &algorithm_id)) {
2850       GST_ERROR_OBJECT (qtdemux, "Error getting box's algorithm ID field");
2851       return;
2852     }
2853
2854     algorithm_id >>= 8;
2855     if (algorithm_id == 0) {
2856       is_encrypted = FALSE;
2857     } else if (algorithm_id == 1) {
2858       /* FIXME: maybe store this in properties? */
2859       GST_DEBUG_OBJECT (qtdemux, "AES 128-bits CTR encrypted stream");
2860     } else if (algorithm_id == 2) {
2861       /* FIXME: maybe store this in properties? */
2862       GST_DEBUG_OBJECT (qtdemux, "AES 128-bits CBC encrypted stream");
2863     }
2864
2865     if (!gst_byte_reader_get_uint8 (&br, &iv_size))
2866       return;
2867
2868     if (!gst_byte_reader_get_data (&br, 16, &kid))
2869       return;
2870
2871     kid_buf = gst_buffer_new_allocate (NULL, 16, NULL);
2872     gst_buffer_fill (kid_buf, 0, kid, 16);
2873     if (ss_info->default_properties)
2874       gst_structure_free (ss_info->default_properties);
2875     ss_info->default_properties =
2876         gst_structure_new ("application/x-cenc",
2877         "iv_size", G_TYPE_UINT, iv_size,
2878         "encrypted", G_TYPE_BOOLEAN, is_encrypted,
2879         "kid", GST_TYPE_BUFFER, kid_buf, NULL);
2880     GST_DEBUG_OBJECT (qtdemux, "default sample properties: "
2881         "is_encrypted=%u, iv_size=%u", is_encrypted, iv_size);
2882     gst_buffer_unref (kid_buf);
2883   } else if ((flags & 0x000002)) {
2884     uses_sub_sample_encryption = TRUE;
2885   }
2886
2887   if (!gst_byte_reader_get_uint32_be (&br, &sample_count)) {
2888     GST_ERROR_OBJECT (qtdemux, "Error getting box's sample count field");
2889     return;
2890   }
2891
2892   ss_info->crypto_info =
2893       g_ptr_array_new_full (sample_count,
2894       (GDestroyNotify) qtdemux_gst_structure_free);
2895
2896   for (i = 0; i < sample_count; ++i) {
2897     GstStructure *properties;
2898     guint8 *data;
2899     GstBuffer *buf;
2900
2901     properties = qtdemux_get_cenc_sample_properties (qtdemux, stream, i);
2902     if (properties == NULL) {
2903       GST_ERROR_OBJECT (qtdemux, "failed to get properties for sample %u", i);
2904       qtdemux->cenc_aux_sample_count = i;
2905       return;
2906     }
2907
2908     if (!gst_byte_reader_dup_data (&br, iv_size, &data)) {
2909       GST_ERROR_OBJECT (qtdemux, "IV data not present for sample %u", i);
2910       gst_structure_free (properties);
2911       qtdemux->cenc_aux_sample_count = i;
2912       return;
2913     }
2914     buf = gst_buffer_new_wrapped (data, iv_size);
2915     gst_structure_set (properties, "iv", GST_TYPE_BUFFER, buf, NULL);
2916     gst_buffer_unref (buf);
2917
2918     if (uses_sub_sample_encryption) {
2919       guint16 n_subsamples;
2920
2921       if (!gst_byte_reader_get_uint16_be (&br, &n_subsamples)
2922           || n_subsamples == 0) {
2923         GST_ERROR_OBJECT (qtdemux,
2924             "failed to get subsample count for sample %u", i);
2925         gst_structure_free (properties);
2926         qtdemux->cenc_aux_sample_count = i;
2927         return;
2928       }
2929       GST_LOG_OBJECT (qtdemux, "subsample count: %u", n_subsamples);
2930       if (!gst_byte_reader_dup_data (&br, n_subsamples * 6, &data)) {
2931         GST_ERROR_OBJECT (qtdemux, "failed to get subsample data for sample %u",
2932             i);
2933         gst_structure_free (properties);
2934         qtdemux->cenc_aux_sample_count = i;
2935         return;
2936       }
2937       buf = gst_buffer_new_wrapped (data, n_subsamples * 6);
2938       gst_structure_set (properties,
2939           "subsample_count", G_TYPE_UINT, n_subsamples,
2940           "subsamples", GST_TYPE_BUFFER, buf, NULL);
2941       gst_buffer_unref (buf);
2942     } else {
2943       gst_structure_set (properties, "subsample_count", G_TYPE_UINT, 0, NULL);
2944     }
2945
2946     g_ptr_array_add (ss_info->crypto_info, properties);
2947   }
2948
2949   qtdemux->cenc_aux_sample_count = sample_count;
2950 }
2951
2952 static void
2953 qtdemux_parse_uuid (GstQTDemux * qtdemux, const guint8 * buffer, gint length)
2954 {
2955   static const guint8 xmp_uuid[] = { 0xBE, 0x7A, 0xCF, 0xCB,
2956     0x97, 0xA9, 0x42, 0xE8,
2957     0x9C, 0x71, 0x99, 0x94,
2958     0x91, 0xE3, 0xAF, 0xAC
2959   };
2960   static const guint8 playready_uuid[] = {
2961     0xd0, 0x8a, 0x4f, 0x18, 0x10, 0xf3, 0x4a, 0x82,
2962     0xb6, 0xc8, 0x32, 0xd8, 0xab, 0xa1, 0x83, 0xd3
2963   };
2964
2965   static const guint8 piff_sample_encryption_uuid[] = {
2966     0xa2, 0x39, 0x4f, 0x52, 0x5a, 0x9b, 0x4f, 0x14,
2967     0xa2, 0x44, 0x6c, 0x42, 0x7c, 0x64, 0x8d, 0xf4
2968   };
2969
2970   guint offset;
2971
2972   /* counts as header data */
2973   qtdemux->header_size += length;
2974
2975   offset = (QT_UINT32 (buffer) == 0) ? 16 : 8;
2976
2977   if (length <= offset + 16) {
2978     GST_DEBUG_OBJECT (qtdemux, "uuid atom is too short, skipping");
2979     return;
2980   }
2981
2982   if (memcmp (buffer + offset, xmp_uuid, 16) == 0) {
2983     GstBuffer *buf;
2984     GstTagList *taglist;
2985
2986     buf = _gst_buffer_new_wrapped ((guint8 *) buffer + offset + 16,
2987         length - offset - 16, NULL);
2988     taglist = gst_tag_list_from_xmp_buffer (buf);
2989     gst_buffer_unref (buf);
2990
2991     /* make sure we have a usable taglist */
2992     qtdemux->tag_list = gst_tag_list_make_writable (qtdemux->tag_list);
2993
2994     qtdemux_handle_xmp_taglist (qtdemux, qtdemux->tag_list, taglist);
2995
2996   } else if (memcmp (buffer + offset, playready_uuid, 16) == 0) {
2997     int len;
2998     const gunichar2 *s_utf16;
2999     char *contents;
3000
3001     len = GST_READ_UINT16_LE (buffer + offset + 0x30);
3002     s_utf16 = (const gunichar2 *) (buffer + offset + 0x32);
3003     contents = g_utf16_to_utf8 (s_utf16, len / 2, NULL, NULL, NULL);
3004     GST_ERROR_OBJECT (qtdemux, "contents: %s", contents);
3005
3006     g_free (contents);
3007
3008     GST_ELEMENT_ERROR (qtdemux, STREAM, DECRYPT,
3009         (_("Cannot play stream because it is encrypted with PlayReady DRM.")),
3010         (NULL));
3011   } else if (memcmp (buffer + offset, piff_sample_encryption_uuid, 16) == 0) {
3012     qtdemux_parse_piff (qtdemux, buffer, length, offset);
3013   } else {
3014     GST_DEBUG_OBJECT (qtdemux, "Ignoring unknown uuid: %08x-%08x-%08x-%08x",
3015         GST_READ_UINT32_LE (buffer + offset),
3016         GST_READ_UINT32_LE (buffer + offset + 4),
3017         GST_READ_UINT32_LE (buffer + offset + 8),
3018         GST_READ_UINT32_LE (buffer + offset + 12));
3019   }
3020 }
3021
3022 static void
3023 qtdemux_parse_sidx (GstQTDemux * qtdemux, const guint8 * buffer, gint length)
3024 {
3025   GstSidxParser sidx_parser;
3026   GstIsoffParserResult res;
3027   guint consumed;
3028
3029   gst_isoff_qt_sidx_parser_init (&sidx_parser);
3030
3031   res =
3032       gst_isoff_qt_sidx_parser_add_data (&sidx_parser, buffer, length,
3033       &consumed);
3034   GST_DEBUG_OBJECT (qtdemux, "sidx parse result: %d", res);
3035   if (res == GST_ISOFF_QT_PARSER_DONE) {
3036     check_update_duration (qtdemux, sidx_parser.cumulative_pts);
3037   }
3038   gst_isoff_qt_sidx_parser_clear (&sidx_parser);
3039 }
3040
3041 /* caller verifies at least 8 bytes in buf */
3042 static void
3043 extract_initial_length_and_fourcc (const guint8 * data, guint size,
3044     guint64 * plength, guint32 * pfourcc)
3045 {
3046   guint64 length;
3047   guint32 fourcc;
3048
3049   length = QT_UINT32 (data);
3050   GST_DEBUG ("length 0x%08" G_GINT64_MODIFIER "x", length);
3051   fourcc = QT_FOURCC (data + 4);
3052   GST_DEBUG ("atom type %" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (fourcc));
3053
3054   if (length == 0) {
3055     length = G_MAXUINT64;
3056   } else if (length == 1 && size >= 16) {
3057     /* this means we have an extended size, which is the 64 bit value of
3058      * the next 8 bytes */
3059     length = QT_UINT64 (data + 8);
3060     GST_DEBUG ("length 0x%08" G_GINT64_MODIFIER "x", length);
3061   }
3062
3063   if (plength)
3064     *plength = length;
3065   if (pfourcc)
3066     *pfourcc = fourcc;
3067 }
3068
3069 static gboolean
3070 qtdemux_parse_mehd (GstQTDemux * qtdemux, GstByteReader * br)
3071 {
3072   guint32 version = 0;
3073   GstClockTime duration = 0;
3074
3075   if (!gst_byte_reader_get_uint32_be (br, &version))
3076     goto failed;
3077
3078   version >>= 24;
3079   if (version == 1) {
3080     if (!gst_byte_reader_get_uint64_be (br, &duration))
3081       goto failed;
3082   } else {
3083     guint32 dur = 0;
3084
3085     if (!gst_byte_reader_get_uint32_be (br, &dur))
3086       goto failed;
3087     duration = dur;
3088   }
3089
3090   GST_INFO_OBJECT (qtdemux, "mehd duration: %" G_GUINT64_FORMAT, duration);
3091   qtdemux->duration = duration;
3092
3093   return TRUE;
3094
3095 failed:
3096   {
3097     GST_DEBUG_OBJECT (qtdemux, "parsing mehd failed");
3098     return FALSE;
3099   }
3100 }
3101
3102 static gboolean
3103 qtdemux_parse_trex (GstQTDemux * qtdemux, QtDemuxStream * stream,
3104     guint32 * ds_duration, guint32 * ds_size, guint32 * ds_flags)
3105 {
3106   if (!stream->parsed_trex && qtdemux->moov_node) {
3107     GNode *mvex, *trex;
3108     GstByteReader trex_data;
3109
3110     mvex = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_mvex);
3111     if (mvex) {
3112       trex = qtdemux_tree_get_child_by_type_full (mvex, FOURCC_trex,
3113           &trex_data);
3114       while (trex) {
3115         guint32 id = 0, sdi = 0, dur = 0, size = 0, flags = 0;
3116
3117         /* skip version/flags */
3118         if (!gst_byte_reader_skip (&trex_data, 4))
3119           goto next;
3120         if (!gst_byte_reader_get_uint32_be (&trex_data, &id))
3121           goto next;
3122         if (id != stream->track_id)
3123           goto next;
3124         if (!gst_byte_reader_get_uint32_be (&trex_data, &sdi))
3125           goto next;
3126         if (!gst_byte_reader_get_uint32_be (&trex_data, &dur))
3127           goto next;
3128         if (!gst_byte_reader_get_uint32_be (&trex_data, &size))
3129           goto next;
3130         if (!gst_byte_reader_get_uint32_be (&trex_data, &flags))
3131           goto next;
3132
3133         GST_DEBUG_OBJECT (qtdemux, "fragment defaults for stream %d; "
3134             "duration %d,  size %d, flags 0x%x", stream->track_id,
3135             dur, size, flags);
3136
3137         stream->parsed_trex = TRUE;
3138         stream->def_sample_description_index = sdi;
3139         stream->def_sample_duration = dur;
3140         stream->def_sample_size = size;
3141         stream->def_sample_flags = flags;
3142
3143       next:
3144         /* iterate all siblings */
3145         trex = qtdemux_tree_get_sibling_by_type_full (trex, FOURCC_trex,
3146             &trex_data);
3147       }
3148     }
3149   }
3150
3151   *ds_duration = stream->def_sample_duration;
3152   *ds_size = stream->def_sample_size;
3153   *ds_flags = stream->def_sample_flags;
3154
3155   /* even then, above values are better than random ... */
3156   if (G_UNLIKELY (!stream->parsed_trex)) {
3157     GST_WARNING_OBJECT (qtdemux,
3158         "failed to find fragment defaults for stream %d", stream->track_id);
3159     return FALSE;
3160   }
3161
3162   return TRUE;
3163 }
3164
3165 /* This method should be called whenever a more accurate duration might
3166  * have been found. It will update all relevant variables if/where needed
3167  */
3168 static void
3169 check_update_duration (GstQTDemux * qtdemux, GstClockTime duration)
3170 {
3171   guint i;
3172   guint64 movdur;
3173   GstClockTime prevdur;
3174   GList *iter;
3175
3176   movdur = GSTTIME_TO_QTTIME (qtdemux, duration);
3177
3178   if (movdur > qtdemux->duration) {
3179     prevdur = QTTIME_TO_GSTTIME (qtdemux, qtdemux->duration);
3180     GST_DEBUG_OBJECT (qtdemux,
3181         "Updating total duration to %" GST_TIME_FORMAT " was %" GST_TIME_FORMAT,
3182         GST_TIME_ARGS (duration), GST_TIME_ARGS (prevdur));
3183     qtdemux->duration = movdur;
3184     GST_DEBUG_OBJECT (qtdemux,
3185         "qtdemux->segment.duration: %" GST_TIME_FORMAT " .stop: %"
3186         GST_TIME_FORMAT, GST_TIME_ARGS (qtdemux->segment.duration),
3187         GST_TIME_ARGS (qtdemux->segment.stop));
3188     if (qtdemux->segment.duration == prevdur) {
3189       /* If the current segment has duration/stop identical to previous duration
3190        * update them also (because they were set at that point in time with
3191        * the wrong duration */
3192       /* We convert the value *from* the timescale version to avoid rounding errors */
3193       GstClockTime fixeddur = QTTIME_TO_GSTTIME (qtdemux, movdur);
3194       GST_DEBUG_OBJECT (qtdemux, "Updated segment.duration and segment.stop");
3195       qtdemux->segment.duration = fixeddur;
3196       qtdemux->segment.stop = fixeddur;
3197     }
3198   }
3199   for (iter = qtdemux->active_streams, i = 0; iter;
3200       iter = g_list_next (iter), i++) {
3201     QtDemuxStream *stream = QTDEMUX_STREAM (iter->data);
3202
3203     movdur = GSTTIME_TO_QTSTREAMTIME (stream, duration);
3204     if (movdur > stream->duration) {
3205       GST_DEBUG_OBJECT (qtdemux,
3206           "Updating stream #%d duration to %" GST_TIME_FORMAT, i,
3207           GST_TIME_ARGS (duration));
3208       stream->duration = movdur;
3209       /* internal duration tracking state has been updated above, so */
3210       /* preserve an open-ended dummy segment rather than repeatedly updating
3211        * it and spamming downstream accordingly with segment events */
3212       if (stream->dummy_segment &&
3213           GST_CLOCK_TIME_IS_VALID (stream->segments[0].duration)) {
3214         /* Update all dummy values to new duration */
3215         stream->segments[0].stop_time = duration;
3216         stream->segments[0].duration = duration;
3217         stream->segments[0].media_stop = duration;
3218
3219         /* let downstream know we possibly have a new stop time */
3220         if (stream->segment_index != -1) {
3221           GstClockTime pos;
3222
3223           if (qtdemux->segment.rate >= 0) {
3224             pos = stream->segment.start;
3225           } else {
3226             pos = stream->segment.stop;
3227           }
3228
3229           gst_qtdemux_stream_update_segment (qtdemux, stream,
3230               stream->segment_index, pos, NULL, NULL);
3231         }
3232       }
3233     }
3234   }
3235 }
3236
3237 static gboolean
3238 qtdemux_parse_trun (GstQTDemux * qtdemux, GstByteReader * trun,
3239     QtDemuxStream * stream, guint32 d_sample_duration, guint32 d_sample_size,
3240     guint32 d_sample_flags, gint64 moof_offset, gint64 moof_length,
3241     gint64 * base_offset, gint64 * running_offset, gint64 decode_ts,
3242     gboolean has_tfdt)
3243 {
3244   GstClockTime gst_ts = GST_CLOCK_TIME_NONE;
3245   guint64 timestamp;
3246   gint32 data_offset = 0;
3247   guint32 flags = 0, first_flags = 0, samples_count = 0;
3248   gint i;
3249   guint8 *data;
3250   guint entry_size, dur_offset, size_offset, flags_offset = 0, ct_offset = 0;
3251   QtDemuxSample *sample;
3252   gboolean ismv = FALSE;
3253   gint64 initial_offset;
3254
3255   GST_LOG_OBJECT (qtdemux, "parsing trun track-id %d; "
3256       "default dur %d, size %d, flags 0x%x, base offset %" G_GINT64_FORMAT ", "
3257       "decode ts %" G_GINT64_FORMAT, stream->track_id, d_sample_duration,
3258       d_sample_size, d_sample_flags, *base_offset, decode_ts);
3259
3260   if (stream->pending_seek && moof_offset < stream->pending_seek->moof_offset) {
3261     GST_INFO_OBJECT (stream->pad, "skipping trun before seek target fragment");
3262     return TRUE;
3263   }
3264
3265   /* presence of stss or not can't really tell us much,
3266    * and flags and so on tend to be marginally reliable in these files */
3267   if (stream->subtype == FOURCC_soun) {
3268     GST_DEBUG_OBJECT (qtdemux,
3269         "sound track in fragmented file; marking all keyframes");
3270     stream->all_keyframe = TRUE;
3271   }
3272
3273   if (!gst_byte_reader_skip (trun, 1) ||
3274       !gst_byte_reader_get_uint24_be (trun, &flags))
3275     goto fail;
3276
3277   if (!gst_byte_reader_get_uint32_be (trun, &samples_count))
3278     goto fail;
3279
3280   if (flags & TR_DATA_OFFSET) {
3281     /* note this is really signed */
3282     if (!gst_byte_reader_get_int32_be (trun, &data_offset))
3283       goto fail;
3284     GST_LOG_OBJECT (qtdemux, "trun data offset %d", data_offset);
3285     /* default base offset = first byte of moof */
3286     if (*base_offset == -1) {
3287       GST_LOG_OBJECT (qtdemux, "base_offset at moof");
3288       *base_offset = moof_offset;
3289     }
3290     *running_offset = *base_offset + data_offset;
3291   } else {
3292     /* if no offset at all, that would mean data starts at moof start,
3293      * which is a bit wrong and is ismv crappy way, so compensate
3294      * assuming data is in mdat following moof */
3295     if (*base_offset == -1) {
3296       *base_offset = moof_offset + moof_length + 8;
3297       GST_LOG_OBJECT (qtdemux, "base_offset assumed in mdat after moof");
3298       ismv = TRUE;
3299     }
3300     if (*running_offset == -1)
3301       *running_offset = *base_offset;
3302   }
3303
3304   GST_LOG_OBJECT (qtdemux, "running offset now %" G_GINT64_FORMAT,
3305       *running_offset);
3306   GST_LOG_OBJECT (qtdemux, "trun offset %d, flags 0x%x, entries %d",
3307       data_offset, flags, samples_count);
3308
3309   if (flags & TR_FIRST_SAMPLE_FLAGS) {
3310     if (G_UNLIKELY (flags & TR_SAMPLE_FLAGS)) {
3311       GST_DEBUG_OBJECT (qtdemux,
3312           "invalid flags; SAMPLE and FIRST_SAMPLE present, discarding latter");
3313       flags ^= TR_FIRST_SAMPLE_FLAGS;
3314     } else {
3315       if (!gst_byte_reader_get_uint32_be (trun, &first_flags))
3316         goto fail;
3317       GST_LOG_OBJECT (qtdemux, "first flags: 0x%x", first_flags);
3318     }
3319   }
3320
3321   /* FIXME ? spec says other bits should also be checked to determine
3322    * entry size (and prefix size for that matter) */
3323   entry_size = 0;
3324   dur_offset = size_offset = 0;
3325   if (flags & TR_SAMPLE_DURATION) {
3326     GST_LOG_OBJECT (qtdemux, "entry duration present");
3327     dur_offset = entry_size;
3328     entry_size += 4;
3329   }
3330   if (flags & TR_SAMPLE_SIZE) {
3331     GST_LOG_OBJECT (qtdemux, "entry size present");
3332     size_offset = entry_size;
3333     entry_size += 4;
3334   }
3335   if (flags & TR_SAMPLE_FLAGS) {
3336     GST_LOG_OBJECT (qtdemux, "entry flags present");
3337     flags_offset = entry_size;
3338     entry_size += 4;
3339   }
3340   if (flags & TR_COMPOSITION_TIME_OFFSETS) {
3341     GST_LOG_OBJECT (qtdemux, "entry ct offset present");
3342     ct_offset = entry_size;
3343     entry_size += 4;
3344   }
3345
3346   if (!qt_atom_parser_has_chunks (trun, samples_count, entry_size))
3347     goto fail;
3348   data = (guint8 *) gst_byte_reader_peek_data_unchecked (trun);
3349
3350   if (stream->n_samples + samples_count >=
3351       QTDEMUX_MAX_SAMPLE_INDEX_SIZE / sizeof (QtDemuxSample))
3352     goto index_too_big;
3353
3354   GST_DEBUG_OBJECT (qtdemux, "allocating n_samples %u * %u (%.2f MB)",
3355       stream->n_samples + samples_count, (guint) sizeof (QtDemuxSample),
3356       (stream->n_samples + samples_count) *
3357       sizeof (QtDemuxSample) / (1024.0 * 1024.0));
3358
3359   /* create a new array of samples if it's the first sample parsed */
3360   if (stream->n_samples == 0) {
3361     g_assert (stream->samples == NULL);
3362     stream->samples = g_try_new0 (QtDemuxSample, samples_count);
3363     /* or try to reallocate it with space enough to insert the new samples */
3364   } else
3365     stream->samples = g_try_renew (QtDemuxSample, stream->samples,
3366         stream->n_samples + samples_count);
3367   if (stream->samples == NULL)
3368     goto out_of_memory;
3369
3370   if (qtdemux->fragment_start != -1) {
3371     timestamp = GSTTIME_TO_QTSTREAMTIME (stream, qtdemux->fragment_start);
3372     qtdemux->fragment_start = -1;
3373   } else {
3374     if (stream->n_samples == 0) {
3375       if (decode_ts > 0) {
3376         timestamp = decode_ts;
3377       } else if (stream->pending_seek != NULL) {
3378         /* if we don't have a timestamp from a tfdt box, we'll use the one
3379          * from the mfra seek table */
3380         GST_INFO_OBJECT (stream->pad, "pending seek ts = %" GST_TIME_FORMAT,
3381             GST_TIME_ARGS (stream->pending_seek->ts));
3382
3383         /* FIXME: this is not fully correct, the timestamp refers to the random
3384          * access sample refered to in the tfra entry, which may not necessarily
3385          * be the first sample in the tfrag/trun (but hopefully/usually is) */
3386         timestamp = GSTTIME_TO_QTSTREAMTIME (stream, stream->pending_seek->ts);
3387       } else {
3388         timestamp = 0;
3389       }
3390
3391       gst_ts = QTSTREAMTIME_TO_GSTTIME (stream, timestamp);
3392       GST_INFO_OBJECT (stream->pad, "first sample ts %" GST_TIME_FORMAT,
3393           GST_TIME_ARGS (gst_ts));
3394     } else {
3395       /* subsequent fragments extend stream */
3396       timestamp =
3397           stream->samples[stream->n_samples - 1].timestamp +
3398           stream->samples[stream->n_samples - 1].duration;
3399
3400       /* If this is a GST_FORMAT_BYTES stream and there's a significant
3401        * difference (1 sec.) between decode_ts and timestamp, prefer the
3402        * former */
3403       if (has_tfdt && !qtdemux->upstream_format_is_time
3404           && ABSDIFF (decode_ts, timestamp) >
3405           MAX (stream->duration_last_moof / 2,
3406               GSTTIME_TO_QTSTREAMTIME (stream, GST_SECOND))) {
3407         GST_INFO_OBJECT (qtdemux,
3408             "decode_ts (%" GST_TIME_FORMAT ") and timestamp (%" GST_TIME_FORMAT
3409             ") are significantly different (more than %" GST_TIME_FORMAT
3410             "), using decode_ts",
3411             GST_TIME_ARGS (QTSTREAMTIME_TO_GSTTIME (stream, decode_ts)),
3412             GST_TIME_ARGS (QTSTREAMTIME_TO_GSTTIME (stream, timestamp)),
3413             GST_TIME_ARGS (QTSTREAMTIME_TO_GSTTIME (stream,
3414                     MAX (stream->duration_last_moof / 2,
3415                         GSTTIME_TO_QTSTREAMTIME (stream, GST_SECOND)))));
3416         timestamp = decode_ts;
3417       }
3418
3419       gst_ts = QTSTREAMTIME_TO_GSTTIME (stream, timestamp);
3420       GST_INFO_OBJECT (qtdemux, "first sample ts %" GST_TIME_FORMAT
3421           " (extends previous samples)", GST_TIME_ARGS (gst_ts));
3422     }
3423   }
3424
3425   initial_offset = *running_offset;
3426
3427   sample = stream->samples + stream->n_samples;
3428   for (i = 0; i < samples_count; i++) {
3429     guint32 dur, size, sflags, ct;
3430
3431     /* first read sample data */
3432     if (flags & TR_SAMPLE_DURATION) {
3433       dur = QT_UINT32 (data + dur_offset);
3434     } else {
3435       dur = d_sample_duration;
3436     }
3437     if (flags & TR_SAMPLE_SIZE) {
3438       size = QT_UINT32 (data + size_offset);
3439     } else {
3440       size = d_sample_size;
3441     }
3442     if (flags & TR_FIRST_SAMPLE_FLAGS) {
3443       if (i == 0) {
3444         sflags = first_flags;
3445       } else {
3446         sflags = d_sample_flags;
3447       }
3448     } else if (flags & TR_SAMPLE_FLAGS) {
3449       sflags = QT_UINT32 (data + flags_offset);
3450     } else {
3451       sflags = d_sample_flags;
3452     }
3453     if (flags & TR_COMPOSITION_TIME_OFFSETS) {
3454       ct = QT_UINT32 (data + ct_offset);
3455     } else {
3456       ct = 0;
3457     }
3458     data += entry_size;
3459
3460     /* fill the sample information */
3461     sample->offset = *running_offset;
3462     sample->pts_offset = ct;
3463     sample->size = size;
3464     sample->timestamp = timestamp;
3465     sample->duration = dur;
3466     /* sample-is-difference-sample */
3467     /* ismv seems to use 0x40 for keyframe, 0xc0 for non-keyframe,
3468      * now idea how it relates to bitfield other than massive LE/BE confusion */
3469     sample->keyframe = ismv ? ((sflags & 0xff) == 0x40) : !(sflags & 0x10000);
3470     *running_offset += size;
3471     timestamp += dur;
3472     stream->duration_moof += dur;
3473     sample++;
3474   }
3475
3476   /* Update total duration if needed */
3477   check_update_duration (qtdemux, QTSTREAMTIME_TO_GSTTIME (stream, timestamp));
3478
3479   /* Pre-emptively figure out size of mdat based on trun information.
3480    * If the [mdat] atom is effectivelly read, it will be replaced by the actual
3481    * size, else we will still be able to use this when dealing with gap'ed
3482    * input */
3483   qtdemux->mdatleft = *running_offset - initial_offset;
3484   qtdemux->mdatoffset = initial_offset;
3485   qtdemux->mdatsize = qtdemux->mdatleft;
3486
3487   stream->n_samples += samples_count;
3488   stream->n_samples_moof += samples_count;
3489
3490   if (stream->pending_seek != NULL)
3491     stream->pending_seek = NULL;
3492
3493   return TRUE;
3494
3495 fail:
3496   {
3497     GST_WARNING_OBJECT (qtdemux, "failed to parse trun");
3498     return FALSE;
3499   }
3500 out_of_memory:
3501   {
3502     GST_WARNING_OBJECT (qtdemux, "failed to allocate %d samples",
3503         stream->n_samples);
3504     return FALSE;
3505   }
3506 index_too_big:
3507   {
3508     GST_WARNING_OBJECT (qtdemux, "not allocating index of %d samples, would "
3509         "be larger than %uMB (broken file?)", stream->n_samples,
3510         QTDEMUX_MAX_SAMPLE_INDEX_SIZE >> 20);
3511     return FALSE;
3512   }
3513 }
3514
3515 /* find stream with @id */
3516 static inline QtDemuxStream *
3517 qtdemux_find_stream (GstQTDemux * qtdemux, guint32 id)
3518 {
3519   QtDemuxStream *stream;
3520   GList *iter;
3521
3522   /* check */
3523   if (G_UNLIKELY (!id)) {
3524     GST_DEBUG_OBJECT (qtdemux, "invalid track id 0");
3525     return NULL;
3526   }
3527
3528   for (iter = qtdemux->active_streams; iter; iter = g_list_next (iter)) {
3529     stream = QTDEMUX_STREAM (iter->data);
3530     if (stream->track_id == id)
3531       return stream;
3532   }
3533   if (qtdemux->mss_mode) {
3534     /* mss should have only 1 stream anyway */
3535     return QTDEMUX_FIRST_STREAM (qtdemux);
3536   }
3537
3538   return NULL;
3539 }
3540
3541 static gboolean
3542 qtdemux_parse_mfhd (GstQTDemux * qtdemux, GstByteReader * mfhd,
3543     guint32 * fragment_number)
3544 {
3545   if (!gst_byte_reader_skip (mfhd, 4))
3546     goto fail;
3547   if (!gst_byte_reader_get_uint32_be (mfhd, fragment_number))
3548     goto fail;
3549   return TRUE;
3550 fail:
3551   {
3552     GST_WARNING_OBJECT (qtdemux, "Failed to parse mfhd atom");
3553     return FALSE;
3554   }
3555 }
3556
3557 static gboolean
3558 qtdemux_parse_tfhd (GstQTDemux * qtdemux, GstByteReader * tfhd,
3559     QtDemuxStream ** stream, guint32 * default_sample_duration,
3560     guint32 * default_sample_size, guint32 * default_sample_flags,
3561     gint64 * base_offset)
3562 {
3563   guint32 flags = 0;
3564   guint32 track_id = 0;
3565
3566   if (!gst_byte_reader_skip (tfhd, 1) ||
3567       !gst_byte_reader_get_uint24_be (tfhd, &flags))
3568     goto invalid_track;
3569
3570   if (!gst_byte_reader_get_uint32_be (tfhd, &track_id))
3571     goto invalid_track;
3572
3573   *stream = qtdemux_find_stream (qtdemux, track_id);
3574   if (G_UNLIKELY (!*stream))
3575     goto unknown_stream;
3576
3577   if (flags & TF_DEFAULT_BASE_IS_MOOF)
3578     *base_offset = qtdemux->moof_offset;
3579
3580   if (flags & TF_BASE_DATA_OFFSET)
3581     if (!gst_byte_reader_get_uint64_be (tfhd, (guint64 *) base_offset))
3582       goto invalid_track;
3583
3584   /* obtain stream defaults */
3585   qtdemux_parse_trex (qtdemux, *stream,
3586       default_sample_duration, default_sample_size, default_sample_flags);
3587
3588   (*stream)->stsd_sample_description_id =
3589       (*stream)->def_sample_description_index - 1;
3590
3591   if (flags & TF_SAMPLE_DESCRIPTION_INDEX) {
3592     guint32 sample_description_index;
3593     if (!gst_byte_reader_get_uint32_be (tfhd, &sample_description_index))
3594       goto invalid_track;
3595     (*stream)->stsd_sample_description_id = sample_description_index - 1;
3596   }
3597
3598   if (qtdemux->mss_mode) {
3599     /* mss has no stsd entry */
3600     (*stream)->stsd_sample_description_id = 0;
3601   }
3602
3603   if (flags & TF_DEFAULT_SAMPLE_DURATION)
3604     if (!gst_byte_reader_get_uint32_be (tfhd, default_sample_duration))
3605       goto invalid_track;
3606
3607   if (flags & TF_DEFAULT_SAMPLE_SIZE)
3608     if (!gst_byte_reader_get_uint32_be (tfhd, default_sample_size))
3609       goto invalid_track;
3610
3611   if (flags & TF_DEFAULT_SAMPLE_FLAGS)
3612     if (!gst_byte_reader_get_uint32_be (tfhd, default_sample_flags))
3613       goto invalid_track;
3614
3615   return TRUE;
3616
3617 invalid_track:
3618   {
3619     GST_WARNING_OBJECT (qtdemux, "invalid track fragment header");
3620     return FALSE;
3621   }
3622 unknown_stream:
3623   {
3624     GST_DEBUG_OBJECT (qtdemux, "unknown stream in tfhd");
3625     return TRUE;
3626   }
3627 }
3628
3629 static gboolean
3630 qtdemux_parse_tfdt (GstQTDemux * qtdemux, GstByteReader * br,
3631     guint64 * decode_time)
3632 {
3633   guint32 version = 0;
3634
3635   if (!gst_byte_reader_get_uint32_be (br, &version))
3636     return FALSE;
3637
3638   version >>= 24;
3639   if (version == 1) {
3640     if (!gst_byte_reader_get_uint64_be (br, decode_time))
3641       goto failed;
3642   } else {
3643     guint32 dec_time = 0;
3644     if (!gst_byte_reader_get_uint32_be (br, &dec_time))
3645       goto failed;
3646     *decode_time = dec_time;
3647   }
3648
3649   GST_INFO_OBJECT (qtdemux, "Track fragment decode time: %" G_GUINT64_FORMAT,
3650       *decode_time);
3651
3652   return TRUE;
3653
3654 failed:
3655   {
3656     GST_DEBUG_OBJECT (qtdemux, "parsing tfdt failed");
3657     return FALSE;
3658   }
3659 }
3660
3661 /* Returns a pointer to a GstStructure containing the properties of
3662  * the stream sample identified by @sample_index. The caller must unref
3663  * the returned object after use. Returns NULL if unsuccessful. */
3664 static GstStructure *
3665 qtdemux_get_cenc_sample_properties (GstQTDemux * qtdemux,
3666     QtDemuxStream * stream, guint sample_index)
3667 {
3668   QtDemuxCencSampleSetInfo *info = NULL;
3669
3670   g_return_val_if_fail (stream != NULL, NULL);
3671   g_return_val_if_fail (stream->protected, NULL);
3672   g_return_val_if_fail (stream->protection_scheme_info != NULL, NULL);
3673
3674   info = (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
3675
3676   /* Currently, cenc properties for groups of samples are not supported, so
3677    * simply return a copy of the default sample properties */
3678   return gst_structure_copy (info->default_properties);
3679 }
3680
3681 /* Parses the sizes of sample auxiliary information contained within a stream,
3682  * as given in a saiz box. Returns array of sample_count guint8 size values,
3683  * or NULL on failure */
3684 static guint8 *
3685 qtdemux_parse_saiz (GstQTDemux * qtdemux, QtDemuxStream * stream,
3686     GstByteReader * br, guint32 * sample_count)
3687 {
3688   guint32 flags = 0;
3689   guint8 *info_sizes;
3690   guint8 default_info_size;
3691
3692   g_return_val_if_fail (qtdemux != NULL, NULL);
3693   g_return_val_if_fail (stream != NULL, NULL);
3694   g_return_val_if_fail (br != NULL, NULL);
3695   g_return_val_if_fail (sample_count != NULL, NULL);
3696
3697   if (!gst_byte_reader_get_uint32_be (br, &flags))
3698     return NULL;
3699
3700   if (flags & 0x1) {
3701     /* aux_info_type and aux_info_type_parameter are ignored */
3702     if (!gst_byte_reader_skip (br, 8))
3703       return NULL;
3704   }
3705
3706   if (!gst_byte_reader_get_uint8 (br, &default_info_size))
3707     return NULL;
3708   GST_DEBUG_OBJECT (qtdemux, "default_info_size: %u", default_info_size);
3709
3710   if (!gst_byte_reader_get_uint32_be (br, sample_count))
3711     return NULL;
3712   GST_DEBUG_OBJECT (qtdemux, "sample_count: %u", *sample_count);
3713
3714
3715   if (default_info_size == 0) {
3716     if (!gst_byte_reader_dup_data (br, *sample_count, &info_sizes)) {
3717       return NULL;
3718     }
3719   } else {
3720     info_sizes = g_new (guint8, *sample_count);
3721     memset (info_sizes, default_info_size, *sample_count);
3722   }
3723
3724   return info_sizes;
3725 }
3726
3727 /* Parses the offset of sample auxiliary information contained within a stream,
3728  * as given in a saio box. Returns TRUE if successful; FALSE otherwise. */
3729 static gboolean
3730 qtdemux_parse_saio (GstQTDemux * qtdemux, QtDemuxStream * stream,
3731     GstByteReader * br, guint32 * info_type, guint32 * info_type_parameter,
3732     guint64 * offset)
3733 {
3734   guint8 version = 0;
3735   guint32 flags = 0;
3736   guint32 aux_info_type = 0;
3737   guint32 aux_info_type_parameter = 0;
3738   guint32 entry_count;
3739   guint32 off_32;
3740   guint64 off_64;
3741   const guint8 *aux_info_type_data = NULL;
3742
3743   g_return_val_if_fail (qtdemux != NULL, FALSE);
3744   g_return_val_if_fail (stream != NULL, FALSE);
3745   g_return_val_if_fail (br != NULL, FALSE);
3746   g_return_val_if_fail (offset != NULL, FALSE);
3747
3748   if (!gst_byte_reader_get_uint8 (br, &version))
3749     return FALSE;
3750
3751   if (!gst_byte_reader_get_uint24_be (br, &flags))
3752     return FALSE;
3753
3754   if (flags & 0x1) {
3755
3756     if (!gst_byte_reader_get_data (br, 4, &aux_info_type_data))
3757       return FALSE;
3758     aux_info_type = QT_FOURCC (aux_info_type_data);
3759
3760     if (!gst_byte_reader_get_uint32_be (br, &aux_info_type_parameter))
3761       return FALSE;
3762   } else if (stream->protected) {
3763     aux_info_type = stream->protection_scheme_type;
3764   } else {
3765     aux_info_type = CUR_STREAM (stream)->fourcc;
3766   }
3767
3768   if (info_type)
3769     *info_type = aux_info_type;
3770   if (info_type_parameter)
3771     *info_type_parameter = aux_info_type_parameter;
3772
3773   GST_DEBUG_OBJECT (qtdemux, "aux_info_type: '%" GST_FOURCC_FORMAT "', "
3774       "aux_info_type_parameter:  %#06x",
3775       GST_FOURCC_ARGS (aux_info_type), aux_info_type_parameter);
3776
3777   if (!gst_byte_reader_get_uint32_be (br, &entry_count))
3778     return FALSE;
3779
3780   if (entry_count != 1) {
3781     GST_ERROR_OBJECT (qtdemux, "multiple offsets are not supported");
3782     return FALSE;
3783   }
3784
3785   if (version == 0) {
3786     if (!gst_byte_reader_get_uint32_be (br, &off_32))
3787       return FALSE;
3788     *offset = (guint64) off_32;
3789   } else {
3790     if (!gst_byte_reader_get_uint64_be (br, &off_64))
3791       return FALSE;
3792     *offset = off_64;
3793   }
3794
3795   GST_DEBUG_OBJECT (qtdemux, "offset: %" G_GUINT64_FORMAT, *offset);
3796   return TRUE;
3797 }
3798
3799 static void
3800 qtdemux_gst_structure_free (GstStructure * gststructure)
3801 {
3802   if (gststructure) {
3803     gst_structure_free (gststructure);
3804   }
3805 }
3806
3807 /* Parses auxiliary information relating to samples protected using Common
3808  * Encryption (cenc); the format of this information is defined in
3809  * ISO/IEC 23001-7. Returns TRUE if successful; FALSE otherwise. */
3810 static gboolean
3811 qtdemux_parse_cenc_aux_info (GstQTDemux * qtdemux, QtDemuxStream * stream,
3812     GstByteReader * br, guint8 * info_sizes, guint32 sample_count)
3813 {
3814   QtDemuxCencSampleSetInfo *ss_info = NULL;
3815   guint8 size;
3816   gint i;
3817   GPtrArray *old_crypto_info = NULL;
3818   guint old_entries = 0;
3819
3820   g_return_val_if_fail (qtdemux != NULL, FALSE);
3821   g_return_val_if_fail (stream != NULL, FALSE);
3822   g_return_val_if_fail (br != NULL, FALSE);
3823   g_return_val_if_fail (stream->protected, FALSE);
3824   g_return_val_if_fail (stream->protection_scheme_info != NULL, FALSE);
3825
3826   ss_info = (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
3827
3828   if (ss_info->crypto_info) {
3829     old_crypto_info = ss_info->crypto_info;
3830     /* Count number of non-null entries remaining at the tail end */
3831     for (i = old_crypto_info->len - 1; i >= 0; i--) {
3832       if (g_ptr_array_index (old_crypto_info, i) == NULL)
3833         break;
3834       old_entries++;
3835     }
3836   }
3837
3838   ss_info->crypto_info =
3839       g_ptr_array_new_full (sample_count + old_entries,
3840       (GDestroyNotify) qtdemux_gst_structure_free);
3841
3842   /* We preserve old entries because we parse the next moof in advance
3843    * of consuming all samples from the previous moof, and otherwise
3844    * we'd discard the corresponding crypto info for the samples
3845    * from the previous fragment. */
3846   if (old_entries) {
3847     GST_DEBUG_OBJECT (qtdemux, "Preserving %d old crypto info entries",
3848         old_entries);
3849     for (i = old_crypto_info->len - old_entries; i < old_crypto_info->len; i++) {
3850       g_ptr_array_add (ss_info->crypto_info, g_ptr_array_index (old_crypto_info,
3851               i));
3852       g_ptr_array_index (old_crypto_info, i) = NULL;
3853     }
3854   }
3855
3856   if (old_crypto_info) {
3857     /* Everything now belongs to the new array */
3858     g_ptr_array_free (old_crypto_info, TRUE);
3859   }
3860
3861   for (i = 0; i < sample_count; ++i) {
3862     GstStructure *properties;
3863     guint16 n_subsamples = 0;
3864     guint8 *data;
3865     guint iv_size;
3866     GstBuffer *buf;
3867
3868     properties = qtdemux_get_cenc_sample_properties (qtdemux, stream, i);
3869     if (properties == NULL) {
3870       GST_ERROR_OBJECT (qtdemux, "failed to get properties for sample %u", i);
3871       return FALSE;
3872     }
3873     if (!gst_structure_get_uint (properties, "iv_size", &iv_size)) {
3874       GST_ERROR_OBJECT (qtdemux, "failed to get iv_size for sample %u", i);
3875       gst_structure_free (properties);
3876       return FALSE;
3877     }
3878     if (!gst_byte_reader_dup_data (br, iv_size, &data)) {
3879       GST_ERROR_OBJECT (qtdemux, "failed to get IV for sample %u", i);
3880       gst_structure_free (properties);
3881       return FALSE;
3882     }
3883     buf = gst_buffer_new_wrapped (data, iv_size);
3884     gst_structure_set (properties, "iv", GST_TYPE_BUFFER, buf, NULL);
3885     gst_buffer_unref (buf);
3886     size = info_sizes[i];
3887     if (size > iv_size) {
3888       if (!gst_byte_reader_get_uint16_be (br, &n_subsamples)
3889           || !(n_subsamples > 0)) {
3890         gst_structure_free (properties);
3891         GST_ERROR_OBJECT (qtdemux,
3892             "failed to get subsample count for sample %u", i);
3893         return FALSE;
3894       }
3895       GST_LOG_OBJECT (qtdemux, "subsample count: %u", n_subsamples);
3896       if (!gst_byte_reader_dup_data (br, n_subsamples * 6, &data)) {
3897         GST_ERROR_OBJECT (qtdemux, "failed to get subsample data for sample %u",
3898             i);
3899         gst_structure_free (properties);
3900         return FALSE;
3901       }
3902       buf = gst_buffer_new_wrapped (data, n_subsamples * 6);
3903       if (!buf) {
3904         gst_structure_free (properties);
3905         return FALSE;
3906       }
3907       gst_structure_set (properties,
3908           "subsample_count", G_TYPE_UINT, n_subsamples,
3909           "subsamples", GST_TYPE_BUFFER, buf, NULL);
3910       gst_buffer_unref (buf);
3911     } else {
3912       gst_structure_set (properties, "subsample_count", G_TYPE_UINT, 0, NULL);
3913     }
3914     g_ptr_array_add (ss_info->crypto_info, properties);
3915   }
3916   return TRUE;
3917 }
3918
3919 /* Converts a UUID in raw byte form to a string representation, as defined in
3920  * RFC 4122. The caller takes ownership of the returned string and is
3921  * responsible for freeing it after use. */
3922 static gchar *
3923 qtdemux_uuid_bytes_to_string (gconstpointer uuid_bytes)
3924 {
3925   const guint8 *uuid = (const guint8 *) uuid_bytes;
3926
3927   return g_strdup_printf ("%02x%02x%02x%02x-%02x%02x-%02x%02x-"
3928       "%02x%02x-%02x%02x%02x%02x%02x%02x",
3929       uuid[0], uuid[1], uuid[2], uuid[3],
3930       uuid[4], uuid[5], uuid[6], uuid[7],
3931       uuid[8], uuid[9], uuid[10], uuid[11],
3932       uuid[12], uuid[13], uuid[14], uuid[15]);
3933 }
3934
3935 /* Parses a Protection System Specific Header box (pssh), as defined in the
3936  * Common Encryption (cenc) standard (ISO/IEC 23001-7), which contains
3937  * information needed by a specific content protection system in order to
3938  * decrypt cenc-protected tracks. Returns TRUE if successful; FALSE
3939  * otherwise. */
3940 static gboolean
3941 qtdemux_parse_pssh (GstQTDemux * qtdemux, GNode * node)
3942 {
3943   gchar *sysid_string;
3944   guint32 pssh_size = QT_UINT32 (node->data);
3945   GstBuffer *pssh = NULL;
3946   GstEvent *event = NULL;
3947   guint32 parent_box_type;
3948   GList *iter;
3949
3950   if (G_UNLIKELY (pssh_size < 32U)) {
3951     GST_ERROR_OBJECT (qtdemux, "invalid box size");
3952     return FALSE;
3953   }
3954
3955   sysid_string =
3956       qtdemux_uuid_bytes_to_string ((const guint8 *) node->data + 12);
3957
3958   gst_qtdemux_append_protection_system_id (qtdemux, sysid_string);
3959
3960   pssh = gst_buffer_new_wrapped (g_memdup (node->data, pssh_size), pssh_size);
3961   GST_LOG_OBJECT (qtdemux, "cenc pssh size: %" G_GSIZE_FORMAT,
3962       gst_buffer_get_size (pssh));
3963
3964   parent_box_type = QT_FOURCC ((const guint8 *) node->parent->data + 4);
3965
3966   /* Push an event containing the pssh box onto the queues of all streams. */
3967   event = gst_event_new_protection (sysid_string, pssh,
3968       (parent_box_type == FOURCC_moov) ? "isobmff/moov" : "isobmff/moof");
3969   for (iter = qtdemux->active_streams; iter; iter = g_list_next (iter)) {
3970     QtDemuxStream *stream = QTDEMUX_STREAM (iter->data);
3971     GST_TRACE_OBJECT (qtdemux,
3972         "adding protection event for stream %s and system %s",
3973         stream->stream_id, sysid_string);
3974     g_queue_push_tail (&stream->protection_scheme_event_queue,
3975         gst_event_ref (event));
3976   }
3977   g_free (sysid_string);
3978   gst_event_unref (event);
3979   gst_buffer_unref (pssh);
3980   return TRUE;
3981 }
3982
3983 static gboolean
3984 qtdemux_parse_moof (GstQTDemux * qtdemux, const guint8 * buffer, guint length,
3985     guint64 moof_offset, QtDemuxStream * stream)
3986 {
3987   GNode *moof_node, *traf_node, *tfhd_node, *trun_node, *tfdt_node, *mfhd_node;
3988   GNode *uuid_node;
3989   GstByteReader mfhd_data, trun_data, tfhd_data, tfdt_data;
3990   GNode *saiz_node, *saio_node, *pssh_node;
3991   GstByteReader saiz_data, saio_data;
3992   guint32 ds_size = 0, ds_duration = 0, ds_flags = 0;
3993   gint64 base_offset, running_offset;
3994   guint32 frag_num;
3995
3996   /* NOTE @stream ignored */
3997
3998   moof_node = g_node_new ((guint8 *) buffer);
3999   qtdemux_parse_node (qtdemux, moof_node, buffer, length);
4000   qtdemux_node_dump (qtdemux, moof_node);
4001
4002   /* Get fragment number from mfhd and check it's valid */
4003   mfhd_node =
4004       qtdemux_tree_get_child_by_type_full (moof_node, FOURCC_mfhd, &mfhd_data);
4005   if (mfhd_node == NULL)
4006     goto missing_mfhd;
4007   if (!qtdemux_parse_mfhd (qtdemux, &mfhd_data, &frag_num))
4008     goto fail;
4009   GST_DEBUG_OBJECT (qtdemux, "Fragment #%d", frag_num);
4010
4011   /* unknown base_offset to start with */
4012   base_offset = running_offset = -1;
4013   traf_node = qtdemux_tree_get_child_by_type (moof_node, FOURCC_traf);
4014   while (traf_node) {
4015     guint64 decode_time = 0;
4016
4017     /* Fragment Header node */
4018     tfhd_node =
4019         qtdemux_tree_get_child_by_type_full (traf_node, FOURCC_tfhd,
4020         &tfhd_data);
4021     if (!tfhd_node)
4022       goto missing_tfhd;
4023     if (!qtdemux_parse_tfhd (qtdemux, &tfhd_data, &stream, &ds_duration,
4024             &ds_size, &ds_flags, &base_offset))
4025       goto missing_tfhd;
4026
4027     /* The following code assumes at most a single set of sample auxiliary
4028      * data in the fragment (consisting of a saiz box and a corresponding saio
4029      * box); in theory, however, there could be multiple sets of sample
4030      * auxiliary data in a fragment. */
4031     saiz_node =
4032         qtdemux_tree_get_child_by_type_full (traf_node, FOURCC_saiz,
4033         &saiz_data);
4034     if (saiz_node) {
4035       guint32 info_type = 0;
4036       guint64 offset = 0;
4037       guint32 info_type_parameter = 0;
4038
4039       g_free (qtdemux->cenc_aux_info_sizes);
4040
4041       qtdemux->cenc_aux_info_sizes =
4042           qtdemux_parse_saiz (qtdemux, stream, &saiz_data,
4043           &qtdemux->cenc_aux_sample_count);
4044       if (qtdemux->cenc_aux_info_sizes == NULL) {
4045         GST_ERROR_OBJECT (qtdemux, "failed to parse saiz box");
4046         goto fail;
4047       }
4048       saio_node =
4049           qtdemux_tree_get_child_by_type_full (traf_node, FOURCC_saio,
4050           &saio_data);
4051       if (!saio_node) {
4052         GST_ERROR_OBJECT (qtdemux, "saiz box without a corresponding saio box");
4053         g_free (qtdemux->cenc_aux_info_sizes);
4054         qtdemux->cenc_aux_info_sizes = NULL;
4055         goto fail;
4056       }
4057
4058       if (G_UNLIKELY (!qtdemux_parse_saio (qtdemux, stream, &saio_data,
4059                   &info_type, &info_type_parameter, &offset))) {
4060         GST_ERROR_OBJECT (qtdemux, "failed to parse saio box");
4061         g_free (qtdemux->cenc_aux_info_sizes);
4062         qtdemux->cenc_aux_info_sizes = NULL;
4063         goto fail;
4064       }
4065       if (base_offset > -1 && base_offset > qtdemux->moof_offset)
4066         offset += (guint64) (base_offset - qtdemux->moof_offset);
4067       if (info_type == FOURCC_cenc && info_type_parameter == 0U) {
4068         GstByteReader br;
4069         if (offset > length) {
4070           GST_DEBUG_OBJECT (qtdemux, "cenc auxiliary info stored out of moof");
4071           qtdemux->cenc_aux_info_offset = offset;
4072         } else {
4073           gst_byte_reader_init (&br, buffer + offset, length - offset);
4074           if (!qtdemux_parse_cenc_aux_info (qtdemux, stream, &br,
4075                   qtdemux->cenc_aux_info_sizes,
4076                   qtdemux->cenc_aux_sample_count)) {
4077             GST_ERROR_OBJECT (qtdemux, "failed to parse cenc auxiliary info");
4078             g_free (qtdemux->cenc_aux_info_sizes);
4079             qtdemux->cenc_aux_info_sizes = NULL;
4080             goto fail;
4081           }
4082         }
4083       }
4084     }
4085
4086     tfdt_node =
4087         qtdemux_tree_get_child_by_type_full (traf_node, FOURCC_tfdt,
4088         &tfdt_data);
4089     if (tfdt_node) {
4090       /* We'll use decode_time to interpolate timestamps
4091        * in case the input timestamps are missing */
4092       qtdemux_parse_tfdt (qtdemux, &tfdt_data, &decode_time);
4093
4094       GST_DEBUG_OBJECT (qtdemux, "decode time %" G_GINT64_FORMAT
4095           " (%" GST_TIME_FORMAT ")", decode_time,
4096           GST_TIME_ARGS (stream ? QTSTREAMTIME_TO_GSTTIME (stream,
4097                   decode_time) : GST_CLOCK_TIME_NONE));
4098
4099       /* Discard the fragment buffer timestamp info to avoid using it.
4100        * Rely on tfdt instead as it is more accurate than the timestamp
4101        * that is fetched from a manifest/playlist and is usually
4102        * less accurate. */
4103       qtdemux->fragment_start = -1;
4104     }
4105
4106     if (G_UNLIKELY (!stream)) {
4107       /* we lost track of offset, we'll need to regain it,
4108        * but can delay complaining until later or avoid doing so altogether */
4109       base_offset = -2;
4110       goto next;
4111     }
4112     if (G_UNLIKELY (base_offset < -1))
4113       goto lost_offset;
4114
4115     if (qtdemux->upstream_format_is_time)
4116       gst_qtdemux_stream_flush_samples_data (stream);
4117
4118     /* initialise moof sample data */
4119     stream->n_samples_moof = 0;
4120     stream->duration_last_moof = stream->duration_moof;
4121     stream->duration_moof = 0;
4122
4123     /* Track Run node */
4124     trun_node =
4125         qtdemux_tree_get_child_by_type_full (traf_node, FOURCC_trun,
4126         &trun_data);
4127     while (trun_node) {
4128       qtdemux_parse_trun (qtdemux, &trun_data, stream,
4129           ds_duration, ds_size, ds_flags, moof_offset, length, &base_offset,
4130           &running_offset, decode_time, (tfdt_node != NULL));
4131       /* iterate all siblings */
4132       trun_node = qtdemux_tree_get_sibling_by_type_full (trun_node, FOURCC_trun,
4133           &trun_data);
4134     }
4135
4136     uuid_node = qtdemux_tree_get_child_by_type (traf_node, FOURCC_uuid);
4137     if (uuid_node) {
4138       guint8 *uuid_buffer = (guint8 *) uuid_node->data;
4139       guint32 box_length = QT_UINT32 (uuid_buffer);
4140
4141       qtdemux_parse_uuid (qtdemux, uuid_buffer, box_length);
4142     }
4143
4144     /* if no new base_offset provided for next traf,
4145      * base is end of current traf */
4146     base_offset = running_offset;
4147     running_offset = -1;
4148
4149     if (stream->n_samples_moof && stream->duration_moof)
4150       stream->new_caps = TRUE;
4151
4152   next:
4153     /* iterate all siblings */
4154     traf_node = qtdemux_tree_get_sibling_by_type (traf_node, FOURCC_traf);
4155   }
4156
4157   /* parse any protection system info */
4158   pssh_node = qtdemux_tree_get_child_by_type (moof_node, FOURCC_pssh);
4159   while (pssh_node) {
4160     GST_LOG_OBJECT (qtdemux, "Parsing pssh box.");
4161     qtdemux_parse_pssh (qtdemux, pssh_node);
4162     pssh_node = qtdemux_tree_get_sibling_by_type (pssh_node, FOURCC_pssh);
4163   }
4164
4165   g_node_destroy (moof_node);
4166   return TRUE;
4167
4168 missing_tfhd:
4169   {
4170     GST_DEBUG_OBJECT (qtdemux, "missing tfhd box");
4171     goto fail;
4172   }
4173 missing_mfhd:
4174   {
4175     GST_DEBUG_OBJECT (qtdemux, "Missing mfhd box");
4176     goto fail;
4177   }
4178 lost_offset:
4179   {
4180     GST_DEBUG_OBJECT (qtdemux, "lost offset");
4181     goto fail;
4182   }
4183 fail:
4184   {
4185     g_node_destroy (moof_node);
4186     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
4187         (_("This file is corrupt and cannot be played.")), (NULL));
4188     return FALSE;
4189   }
4190 }
4191
4192 #if 0
4193 /* might be used if some day we actually use mfra & co
4194  * for random access to fragments,
4195  * but that will require quite some modifications and much less relying
4196  * on a sample array */
4197 #endif
4198
4199 static gboolean
4200 qtdemux_parse_tfra (GstQTDemux * qtdemux, GNode * tfra_node)
4201 {
4202   QtDemuxStream *stream;
4203   guint32 ver_flags, track_id, len, num_entries, i;
4204   guint value_size, traf_size, trun_size, sample_size;
4205   guint64 time = 0, moof_offset = 0;
4206 #if 0
4207   GstBuffer *buf = NULL;
4208   GstFlowReturn ret;
4209 #endif
4210   GstByteReader tfra;
4211
4212   gst_byte_reader_init (&tfra, tfra_node->data, QT_UINT32 (tfra_node->data));
4213
4214   if (!gst_byte_reader_skip (&tfra, 8))
4215     return FALSE;
4216
4217   if (!gst_byte_reader_get_uint32_be (&tfra, &ver_flags))
4218     return FALSE;
4219
4220   if (!gst_byte_reader_get_uint32_be (&tfra, &track_id)
4221       || !gst_byte_reader_get_uint32_be (&tfra, &len)
4222       || !gst_byte_reader_get_uint32_be (&tfra, &num_entries))
4223     return FALSE;
4224
4225   GST_DEBUG_OBJECT (qtdemux, "parsing tfra box for track id %u", track_id);
4226
4227   stream = qtdemux_find_stream (qtdemux, track_id);
4228   if (stream == NULL)
4229     goto unknown_trackid;
4230
4231   value_size = ((ver_flags >> 24) == 1) ? sizeof (guint64) : sizeof (guint32);
4232   sample_size = (len & 3) + 1;
4233   trun_size = ((len & 12) >> 2) + 1;
4234   traf_size = ((len & 48) >> 4) + 1;
4235
4236   GST_DEBUG_OBJECT (qtdemux, "%u entries, sizes: value %u, traf %u, trun %u, "
4237       "sample %u", num_entries, value_size, traf_size, trun_size, sample_size);
4238
4239   if (num_entries == 0)
4240     goto no_samples;
4241
4242   if (!qt_atom_parser_has_chunks (&tfra, num_entries,
4243           value_size + value_size + traf_size + trun_size + sample_size))
4244     goto corrupt_file;
4245
4246   g_free (stream->ra_entries);
4247   stream->ra_entries = g_new (QtDemuxRandomAccessEntry, num_entries);
4248   stream->n_ra_entries = num_entries;
4249
4250   for (i = 0; i < num_entries; i++) {
4251     qt_atom_parser_get_offset (&tfra, value_size, &time);
4252     qt_atom_parser_get_offset (&tfra, value_size, &moof_offset);
4253     qt_atom_parser_get_uint_with_size_unchecked (&tfra, traf_size);
4254     qt_atom_parser_get_uint_with_size_unchecked (&tfra, trun_size);
4255     qt_atom_parser_get_uint_with_size_unchecked (&tfra, sample_size);
4256
4257     time = QTSTREAMTIME_TO_GSTTIME (stream, time);
4258
4259     GST_LOG_OBJECT (qtdemux, "fragment time: %" GST_TIME_FORMAT ", "
4260         " moof_offset: %" G_GUINT64_FORMAT, GST_TIME_ARGS (time), moof_offset);
4261
4262     stream->ra_entries[i].ts = time;
4263     stream->ra_entries[i].moof_offset = moof_offset;
4264
4265     /* don't want to go through the entire file and read all moofs at startup */
4266 #if 0
4267     ret = gst_qtdemux_pull_atom (qtdemux, moof_offset, 0, &buf);
4268     if (ret != GST_FLOW_OK)
4269       goto corrupt_file;
4270     qtdemux_parse_moof (qtdemux, GST_BUFFER_DATA (buf), GST_BUFFER_SIZE (buf),
4271         moof_offset, stream);
4272     gst_buffer_unref (buf);
4273 #endif
4274   }
4275
4276   check_update_duration (qtdemux, time);
4277
4278   return TRUE;
4279
4280 /* ERRORS */
4281 unknown_trackid:
4282   {
4283     GST_WARNING_OBJECT (qtdemux, "Couldn't find stream for track %u", track_id);
4284     return FALSE;
4285   }
4286 corrupt_file:
4287   {
4288     GST_WARNING_OBJECT (qtdemux, "broken traf box, ignoring");
4289     return FALSE;
4290   }
4291 no_samples:
4292   {
4293     GST_WARNING_OBJECT (qtdemux, "stream has no samples");
4294     return FALSE;
4295   }
4296 }
4297
4298 static gboolean
4299 qtdemux_pull_mfro_mfra (GstQTDemux * qtdemux)
4300 {
4301   GstMapInfo mfro_map = GST_MAP_INFO_INIT;
4302   GstMapInfo mfra_map = GST_MAP_INFO_INIT;
4303   GstBuffer *mfro = NULL, *mfra = NULL;
4304   GstFlowReturn flow;
4305   gboolean ret = FALSE;
4306   GNode *mfra_node, *tfra_node;
4307   guint64 mfra_offset = 0;
4308   guint32 fourcc, mfra_size;
4309   gint64 len;
4310
4311   /* query upstream size in bytes */
4312   if (!gst_pad_peer_query_duration (qtdemux->sinkpad, GST_FORMAT_BYTES, &len))
4313     goto size_query_failed;
4314
4315   /* mfro box should be at the very end of the file */
4316   flow = gst_qtdemux_pull_atom (qtdemux, len - 16, 16, &mfro);
4317   if (flow != GST_FLOW_OK)
4318     goto exit;
4319
4320   gst_buffer_map (mfro, &mfro_map, GST_MAP_READ);
4321
4322   fourcc = QT_FOURCC (mfro_map.data + 4);
4323   if (fourcc != FOURCC_mfro)
4324     goto exit;
4325
4326   GST_INFO_OBJECT (qtdemux, "Found mfro box");
4327   if (mfro_map.size < 16)
4328     goto invalid_mfro_size;
4329
4330   mfra_size = QT_UINT32 (mfro_map.data + 12);
4331   if (mfra_size >= len)
4332     goto invalid_mfra_size;
4333
4334   mfra_offset = len - mfra_size;
4335
4336   GST_INFO_OBJECT (qtdemux, "mfra offset: %" G_GUINT64_FORMAT ", size %u",
4337       mfra_offset, mfra_size);
4338
4339   /* now get and parse mfra box */
4340   flow = gst_qtdemux_pull_atom (qtdemux, mfra_offset, mfra_size, &mfra);
4341   if (flow != GST_FLOW_OK)
4342     goto broken_file;
4343
4344   gst_buffer_map (mfra, &mfra_map, GST_MAP_READ);
4345
4346   mfra_node = g_node_new ((guint8 *) mfra_map.data);
4347   qtdemux_parse_node (qtdemux, mfra_node, mfra_map.data, mfra_map.size);
4348
4349   tfra_node = qtdemux_tree_get_child_by_type (mfra_node, FOURCC_tfra);
4350
4351   while (tfra_node) {
4352     qtdemux_parse_tfra (qtdemux, tfra_node);
4353     /* iterate all siblings */
4354     tfra_node = qtdemux_tree_get_sibling_by_type (tfra_node, FOURCC_tfra);
4355   }
4356   g_node_destroy (mfra_node);
4357
4358   GST_INFO_OBJECT (qtdemux, "parsed movie fragment random access box (mfra)");
4359   ret = TRUE;
4360
4361 exit:
4362
4363   if (mfro) {
4364     if (mfro_map.memory != NULL)
4365       gst_buffer_unmap (mfro, &mfro_map);
4366     gst_buffer_unref (mfro);
4367   }
4368   if (mfra) {
4369     if (mfra_map.memory != NULL)
4370       gst_buffer_unmap (mfra, &mfra_map);
4371     gst_buffer_unref (mfra);
4372   }
4373   return ret;
4374
4375 /* ERRORS */
4376 size_query_failed:
4377   {
4378     GST_WARNING_OBJECT (qtdemux, "could not query upstream size");
4379     goto exit;
4380   }
4381 invalid_mfro_size:
4382   {
4383     GST_WARNING_OBJECT (qtdemux, "mfro size is too small");
4384     goto exit;
4385   }
4386 invalid_mfra_size:
4387   {
4388     GST_WARNING_OBJECT (qtdemux, "mfra_size in mfro box is invalid");
4389     goto exit;
4390   }
4391 broken_file:
4392   {
4393     GST_WARNING_OBJECT (qtdemux, "bogus mfra offset or size, broken file");
4394     goto exit;
4395   }
4396 }
4397
4398 static guint64
4399 add_offset (guint64 offset, guint64 advance)
4400 {
4401   /* Avoid 64-bit overflow by clamping */
4402   if (offset > G_MAXUINT64 - advance)
4403     return G_MAXUINT64;
4404   return offset + advance;
4405 }
4406
4407 static GstFlowReturn
4408 gst_qtdemux_loop_state_header (GstQTDemux * qtdemux)
4409 {
4410   guint64 length = 0;
4411   guint32 fourcc = 0;
4412   GstBuffer *buf = NULL;
4413   GstFlowReturn ret = GST_FLOW_OK;
4414   guint64 cur_offset = qtdemux->offset;
4415   GstMapInfo map;
4416
4417   ret = gst_pad_pull_range (qtdemux->sinkpad, cur_offset, 16, &buf);
4418   if (G_UNLIKELY (ret != GST_FLOW_OK))
4419     goto beach;
4420   gst_buffer_map (buf, &map, GST_MAP_READ);
4421   if (G_LIKELY (map.size >= 8))
4422     extract_initial_length_and_fourcc (map.data, map.size, &length, &fourcc);
4423   gst_buffer_unmap (buf, &map);
4424   gst_buffer_unref (buf);
4425
4426   /* maybe we already got most we needed, so only consider this eof */
4427   if (G_UNLIKELY (length == 0)) {
4428     GST_ELEMENT_WARNING (qtdemux, STREAM, DEMUX,
4429         (_("Invalid atom size.")),
4430         ("Header atom '%" GST_FOURCC_FORMAT "' has empty length",
4431             GST_FOURCC_ARGS (fourcc)));
4432     ret = GST_FLOW_EOS;
4433     goto beach;
4434   }
4435
4436   switch (fourcc) {
4437     case FOURCC_moof:
4438       /* record for later parsing when needed */
4439       if (!qtdemux->moof_offset) {
4440         qtdemux->moof_offset = qtdemux->offset;
4441       }
4442       if (qtdemux_pull_mfro_mfra (qtdemux)) {
4443         /* FIXME */
4444       } else {
4445         qtdemux->offset += length;      /* skip moof and keep going */
4446       }
4447       if (qtdemux->got_moov) {
4448         GST_INFO_OBJECT (qtdemux, "moof header, got moov, done with headers");
4449         ret = GST_FLOW_EOS;
4450         goto beach;
4451       }
4452       break;
4453     case FOURCC_mdat:
4454     case FOURCC_free:
4455     case FOURCC_skip:
4456     case FOURCC_wide:
4457     case FOURCC_PICT:
4458     case FOURCC_pnot:
4459     {
4460       GST_LOG_OBJECT (qtdemux,
4461           "skipping atom '%" GST_FOURCC_FORMAT "' at %" G_GUINT64_FORMAT,
4462           GST_FOURCC_ARGS (fourcc), cur_offset);
4463       qtdemux->offset = add_offset (qtdemux->offset, length);
4464       break;
4465     }
4466     case FOURCC_moov:
4467     {
4468       GstBuffer *moov = NULL;
4469
4470       if (qtdemux->got_moov) {
4471         GST_DEBUG_OBJECT (qtdemux, "Skipping moov atom as we have one already");
4472         qtdemux->offset = add_offset (qtdemux->offset, length);
4473         goto beach;
4474       }
4475
4476       ret = gst_pad_pull_range (qtdemux->sinkpad, cur_offset, length, &moov);
4477       if (ret != GST_FLOW_OK)
4478         goto beach;
4479       gst_buffer_map (moov, &map, GST_MAP_READ);
4480
4481       if (length != map.size) {
4482         /* Some files have a 'moov' atom at the end of the file which contains
4483          * a terminal 'free' atom where the body of the atom is missing.
4484          * Check for, and permit, this special case.
4485          */
4486         if (map.size >= 8) {
4487           guint8 *final_data = map.data + (map.size - 8);
4488           guint32 final_length = QT_UINT32 (final_data);
4489           guint32 final_fourcc = QT_FOURCC (final_data + 4);
4490
4491           if (final_fourcc == FOURCC_free
4492               && map.size + final_length - 8 == length) {
4493             /* Ok, we've found that special case. Allocate a new buffer with
4494              * that free atom actually present. */
4495             GstBuffer *newmoov = gst_buffer_new_and_alloc (length);
4496             gst_buffer_fill (newmoov, 0, map.data, map.size);
4497             gst_buffer_memset (newmoov, map.size, 0, final_length - 8);
4498             gst_buffer_unmap (moov, &map);
4499             gst_buffer_unref (moov);
4500             moov = newmoov;
4501             gst_buffer_map (moov, &map, GST_MAP_READ);
4502           }
4503         }
4504       }
4505
4506       if (length != map.size) {
4507         GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
4508             (_("This file is incomplete and cannot be played.")),
4509             ("We got less than expected (received %" G_GSIZE_FORMAT
4510                 ", wanted %u, offset %" G_GUINT64_FORMAT ")", map.size,
4511                 (guint) length, cur_offset));
4512         gst_buffer_unmap (moov, &map);
4513         gst_buffer_unref (moov);
4514         ret = GST_FLOW_ERROR;
4515         goto beach;
4516       }
4517       qtdemux->offset += length;
4518
4519       qtdemux_parse_moov (qtdemux, map.data, length);
4520       qtdemux_node_dump (qtdemux, qtdemux->moov_node);
4521
4522       qtdemux_parse_tree (qtdemux);
4523       if (qtdemux->moov_node_compressed) {
4524         g_node_destroy (qtdemux->moov_node_compressed);
4525         g_free (qtdemux->moov_node->data);
4526       }
4527       qtdemux->moov_node_compressed = NULL;
4528       g_node_destroy (qtdemux->moov_node);
4529       qtdemux->moov_node = NULL;
4530       gst_buffer_unmap (moov, &map);
4531       gst_buffer_unref (moov);
4532       qtdemux->got_moov = TRUE;
4533       if (!qtdemux->fragmented && !qtdemux->upstream_format_is_time) {
4534         /* in this case, parsing the edts entries will give us segments
4535            already */
4536         qtdemux->need_segment = FALSE;
4537       }
4538
4539       break;
4540     }
4541     case FOURCC_ftyp:
4542     {
4543       GstBuffer *ftyp = NULL;
4544
4545       /* extract major brand; might come in handy for ISO vs QT issues */
4546       ret = gst_qtdemux_pull_atom (qtdemux, cur_offset, length, &ftyp);
4547       if (ret != GST_FLOW_OK)
4548         goto beach;
4549       qtdemux->offset += length;
4550       gst_buffer_map (ftyp, &map, GST_MAP_READ);
4551       qtdemux_parse_ftyp (qtdemux, map.data, map.size);
4552       gst_buffer_unmap (ftyp, &map);
4553       gst_buffer_unref (ftyp);
4554       break;
4555     }
4556     case FOURCC_uuid:
4557     {
4558       GstBuffer *uuid = NULL;
4559
4560       /* uuid are extension atoms */
4561       ret = gst_qtdemux_pull_atom (qtdemux, cur_offset, length, &uuid);
4562       if (ret != GST_FLOW_OK)
4563         goto beach;
4564       qtdemux->offset += length;
4565       gst_buffer_map (uuid, &map, GST_MAP_READ);
4566       qtdemux_parse_uuid (qtdemux, map.data, map.size);
4567       gst_buffer_unmap (uuid, &map);
4568       gst_buffer_unref (uuid);
4569       break;
4570     }
4571     case FOURCC_sidx:
4572     {
4573       GstBuffer *sidx = NULL;
4574       ret = gst_qtdemux_pull_atom (qtdemux, cur_offset, length, &sidx);
4575       if (ret != GST_FLOW_OK)
4576         goto beach;
4577       qtdemux->offset += length;
4578       gst_buffer_map (sidx, &map, GST_MAP_READ);
4579       qtdemux_parse_sidx (qtdemux, map.data, map.size);
4580       gst_buffer_unmap (sidx, &map);
4581       gst_buffer_unref (sidx);
4582       break;
4583     }
4584     default:
4585     {
4586       GstBuffer *unknown = NULL;
4587
4588       GST_LOG_OBJECT (qtdemux,
4589           "unknown %08x '%" GST_FOURCC_FORMAT "' of size %" G_GUINT64_FORMAT
4590           " at %" G_GUINT64_FORMAT, fourcc, GST_FOURCC_ARGS (fourcc), length,
4591           cur_offset);
4592       ret = gst_qtdemux_pull_atom (qtdemux, cur_offset, length, &unknown);
4593       if (ret != GST_FLOW_OK)
4594         goto beach;
4595       gst_buffer_map (unknown, &map, GST_MAP_READ);
4596       GST_MEMDUMP ("Unknown tag", map.data, map.size);
4597       gst_buffer_unmap (unknown, &map);
4598       gst_buffer_unref (unknown);
4599       qtdemux->offset += length;
4600       break;
4601     }
4602   }
4603
4604 beach:
4605   if (ret == GST_FLOW_EOS && (qtdemux->got_moov || qtdemux->media_caps)) {
4606     /* digested all data, show what we have */
4607     qtdemux_prepare_streams (qtdemux);
4608     QTDEMUX_EXPOSE_LOCK (qtdemux);
4609     ret = qtdemux_expose_streams (qtdemux);
4610     QTDEMUX_EXPOSE_UNLOCK (qtdemux);
4611
4612     qtdemux->state = QTDEMUX_STATE_MOVIE;
4613     GST_DEBUG_OBJECT (qtdemux, "switching state to STATE_MOVIE (%d)",
4614         qtdemux->state);
4615     return ret;
4616   }
4617   return ret;
4618 }
4619
4620 /* Seeks to the previous keyframe of the indexed stream and
4621  * aligns other streams with respect to the keyframe timestamp
4622  * of indexed stream. Only called in case of Reverse Playback
4623  */
4624 static GstFlowReturn
4625 gst_qtdemux_seek_to_previous_keyframe (GstQTDemux * qtdemux)
4626 {
4627   guint32 seg_idx = 0, k_index = 0;
4628   guint32 ref_seg_idx, ref_k_index;
4629   GstClockTime k_pos = 0, last_stop = 0;
4630   QtDemuxSegment *seg = NULL;
4631   QtDemuxStream *ref_str = NULL;
4632   guint64 seg_media_start_mov;  /* segment media start time in mov format */
4633   guint64 target_ts;
4634   GList *iter;
4635
4636   /* Now we choose an arbitrary stream, get the previous keyframe timestamp
4637    * and finally align all the other streams on that timestamp with their
4638    * respective keyframes */
4639   for (iter = qtdemux->active_streams; iter; iter = g_list_next (iter)) {
4640     QtDemuxStream *str = QTDEMUX_STREAM (iter->data);
4641
4642     /* No candidate yet, take the first stream */
4643     if (!ref_str) {
4644       ref_str = str;
4645       continue;
4646     }
4647
4648     /* So that stream has a segment, we prefer video streams */
4649     if (str->subtype == FOURCC_vide) {
4650       ref_str = str;
4651       break;
4652     }
4653   }
4654
4655   if (G_UNLIKELY (!ref_str)) {
4656     GST_DEBUG_OBJECT (qtdemux, "couldn't find any stream");
4657     goto eos;
4658   }
4659
4660   if (G_UNLIKELY (!ref_str->from_sample)) {
4661     GST_DEBUG_OBJECT (qtdemux, "reached the beginning of the file");
4662     goto eos;
4663   }
4664
4665   /* So that stream has been playing from from_sample to to_sample. We will
4666    * get the timestamp of the previous sample and search for a keyframe before
4667    * that. For audio streams we do an arbitrary jump in the past (10 samples) */
4668   if (ref_str->subtype == FOURCC_vide) {
4669     k_index = gst_qtdemux_find_keyframe (qtdemux, ref_str,
4670         ref_str->from_sample - 1, FALSE);
4671   } else {
4672     if (ref_str->from_sample >= 10)
4673       k_index = ref_str->from_sample - 10;
4674     else
4675       k_index = 0;
4676   }
4677
4678   target_ts =
4679       ref_str->samples[k_index].timestamp +
4680       ref_str->samples[k_index].pts_offset;
4681
4682   /* get current segment for that stream */
4683   seg = &ref_str->segments[ref_str->segment_index];
4684   /* Use segment start in original timescale for comparisons */
4685   seg_media_start_mov = seg->trak_media_start;
4686
4687   GST_LOG_OBJECT (qtdemux, "keyframe index %u ts %" G_GUINT64_FORMAT
4688       " seg start %" G_GUINT64_FORMAT " %" GST_TIME_FORMAT "\n",
4689       k_index, target_ts, seg_media_start_mov,
4690       GST_TIME_ARGS (seg->media_start));
4691
4692   /* Crawl back through segments to find the one containing this I frame */
4693   while (target_ts < seg_media_start_mov) {
4694     GST_DEBUG_OBJECT (qtdemux,
4695         "keyframe position (sample %u) is out of segment %u " " target %"
4696         G_GUINT64_FORMAT " seg start %" G_GUINT64_FORMAT, k_index,
4697         ref_str->segment_index, target_ts, seg_media_start_mov);
4698
4699     if (G_UNLIKELY (!ref_str->segment_index)) {
4700       /* Reached first segment, let's consider it's EOS */
4701       goto eos;
4702     }
4703     ref_str->segment_index--;
4704     seg = &ref_str->segments[ref_str->segment_index];
4705     /* Use segment start in original timescale for comparisons */
4706     seg_media_start_mov = seg->trak_media_start;
4707   }
4708   /* Calculate time position of the keyframe and where we should stop */
4709   k_pos =
4710       QTSTREAMTIME_TO_GSTTIME (ref_str,
4711       target_ts - seg->trak_media_start) + seg->time;
4712   last_stop =
4713       QTSTREAMTIME_TO_GSTTIME (ref_str,
4714       ref_str->samples[ref_str->from_sample].timestamp -
4715       seg->trak_media_start) + seg->time;
4716
4717   GST_DEBUG_OBJECT (qtdemux, "preferred stream played from sample %u, "
4718       "now going to sample %u (pts %" GST_TIME_FORMAT ")", ref_str->from_sample,
4719       k_index, GST_TIME_ARGS (k_pos));
4720
4721   /* Set last_stop with the keyframe timestamp we pushed of that stream */
4722   qtdemux->segment.position = last_stop;
4723   GST_DEBUG_OBJECT (qtdemux, "last_stop now is %" GST_TIME_FORMAT,
4724       GST_TIME_ARGS (last_stop));
4725
4726   if (G_UNLIKELY (last_stop < qtdemux->segment.start)) {
4727     GST_DEBUG_OBJECT (qtdemux, "reached the beginning of segment");
4728     goto eos;
4729   }
4730
4731   ref_seg_idx = ref_str->segment_index;
4732   ref_k_index = k_index;
4733
4734   /* Align them all on this */
4735   for (iter = qtdemux->active_streams; iter; iter = g_list_next (iter)) {
4736     guint32 index = 0;
4737     GstClockTime seg_time = 0;
4738     QtDemuxStream *str = QTDEMUX_STREAM (iter->data);
4739
4740     /* aligning reference stream again might lead to backing up to yet another
4741      * keyframe (due to timestamp rounding issues),
4742      * potentially putting more load on downstream; so let's try to avoid */
4743     if (str == ref_str) {
4744       seg_idx = ref_seg_idx;
4745       seg = &str->segments[seg_idx];
4746       k_index = ref_k_index;
4747       GST_DEBUG_OBJECT (qtdemux, "reference track-id %u segment %d, "
4748           "sample at index %d", str->track_id, ref_str->segment_index, k_index);
4749     } else {
4750       seg_idx = gst_qtdemux_find_segment (qtdemux, str, k_pos);
4751       GST_DEBUG_OBJECT (qtdemux,
4752           "track-id %u align segment %d for keyframe pos %" GST_TIME_FORMAT,
4753           str->track_id, seg_idx, GST_TIME_ARGS (k_pos));
4754
4755       /* get segment and time in the segment */
4756       seg = &str->segments[seg_idx];
4757       seg_time = k_pos - seg->time;
4758
4759       /* get the media time in the segment.
4760        * No adjustment for empty "filler" segments */
4761       if (seg->media_start != GST_CLOCK_TIME_NONE)
4762         seg_time += seg->media_start;
4763
4764       /* get the index of the sample with media time */
4765       index = gst_qtdemux_find_index_linear (qtdemux, str, seg_time);
4766       GST_DEBUG_OBJECT (qtdemux,
4767           "track-id %u sample for %" GST_TIME_FORMAT " at %u", str->track_id,
4768           GST_TIME_ARGS (seg_time), index);
4769
4770       /* find previous keyframe */
4771       k_index = gst_qtdemux_find_keyframe (qtdemux, str, index, FALSE);
4772     }
4773
4774     /* Remember until where we want to go */
4775     str->to_sample = str->from_sample - 1;
4776     /* Define our time position */
4777     target_ts =
4778         str->samples[k_index].timestamp + str->samples[k_index].pts_offset;
4779     str->time_position = QTSTREAMTIME_TO_GSTTIME (str, target_ts) + seg->time;
4780     if (seg->media_start != GST_CLOCK_TIME_NONE)
4781       str->time_position -= seg->media_start;
4782
4783     /* Now seek back in time */
4784     gst_qtdemux_move_stream (qtdemux, str, k_index);
4785     GST_DEBUG_OBJECT (qtdemux, "track-id %u keyframe at %u, time position %"
4786         GST_TIME_FORMAT " playing from sample %u to %u", str->track_id, k_index,
4787         GST_TIME_ARGS (str->time_position), str->from_sample, str->to_sample);
4788   }
4789
4790   return GST_FLOW_OK;
4791
4792 eos:
4793   return GST_FLOW_EOS;
4794 }
4795
4796 /*
4797  * Gets the current qt segment start, stop and position for the
4798  * given time offset. This is used in update_segment()
4799  */
4800 static void
4801 gst_qtdemux_stream_segment_get_boundaries (GstQTDemux * qtdemux,
4802     QtDemuxStream * stream, GstClockTime offset,
4803     GstClockTime * _start, GstClockTime * _stop, GstClockTime * _time)
4804 {
4805   GstClockTime seg_time;
4806   GstClockTime start, stop, time;
4807   QtDemuxSegment *segment;
4808
4809   segment = &stream->segments[stream->segment_index];
4810
4811   /* get time in this segment */
4812   seg_time = (offset - segment->time) * segment->rate;
4813
4814   GST_LOG_OBJECT (stream->pad, "seg_time %" GST_TIME_FORMAT,
4815       GST_TIME_ARGS (seg_time));
4816
4817   if (G_UNLIKELY (seg_time > segment->duration)) {
4818     GST_LOG_OBJECT (stream->pad,
4819         "seg_time > segment->duration %" GST_TIME_FORMAT,
4820         GST_TIME_ARGS (segment->duration));
4821     seg_time = segment->duration;
4822   }
4823
4824   /* qtdemux->segment.stop is in outside-time-realm, whereas
4825    * segment->media_stop is in track-time-realm.
4826    *
4827    * In order to compare the two, we need to bring segment.stop
4828    * into the track-time-realm
4829    *
4830    * FIXME - does this comment still hold? Don't see any conversion here */
4831
4832   stop = qtdemux->segment.stop;
4833   if (stop == GST_CLOCK_TIME_NONE)
4834     stop = qtdemux->segment.duration;
4835   if (stop == GST_CLOCK_TIME_NONE)
4836     stop = segment->media_stop;
4837   else
4838     stop =
4839         MIN (segment->media_stop, stop - segment->time + segment->media_start);
4840
4841   if (G_UNLIKELY (QTSEGMENT_IS_EMPTY (segment))) {
4842     start = segment->time + seg_time;
4843     time = offset;
4844     stop = start - seg_time + segment->duration;
4845   } else if (qtdemux->segment.rate >= 0) {
4846     start = MIN (segment->media_start + seg_time, stop);
4847     time = offset;
4848   } else {
4849     if (segment->media_start >= qtdemux->segment.start) {
4850       time = segment->time;
4851     } else {
4852       time = segment->time + (qtdemux->segment.start - segment->media_start);
4853     }
4854
4855     start = MAX (segment->media_start, qtdemux->segment.start);
4856     stop = MIN (segment->media_start + seg_time, stop);
4857   }
4858
4859   *_start = start;
4860   *_stop = stop;
4861   *_time = time;
4862 }
4863
4864 /*
4865  * Updates the qt segment used for the stream and pushes a new segment event
4866  * downstream on this stream's pad.
4867  */
4868 static gboolean
4869 gst_qtdemux_stream_update_segment (GstQTDemux * qtdemux, QtDemuxStream * stream,
4870     gint seg_idx, GstClockTime offset, GstClockTime * _start,
4871     GstClockTime * _stop)
4872 {
4873   QtDemuxSegment *segment;
4874   GstClockTime start = 0, stop = GST_CLOCK_TIME_NONE, time = 0;
4875   GstClockTime min_ts;
4876   gdouble rate;
4877   GstEvent *event;
4878
4879   /* update the current segment */
4880   stream->segment_index = seg_idx;
4881
4882   /* get the segment */
4883   segment = &stream->segments[seg_idx];
4884
4885   if (G_UNLIKELY (offset < segment->time)) {
4886     GST_WARNING_OBJECT (stream->pad, "offset < segment->time %" GST_TIME_FORMAT,
4887         GST_TIME_ARGS (segment->time));
4888     return FALSE;
4889   }
4890
4891   /* segment lies beyond total indicated duration */
4892   if (G_UNLIKELY (qtdemux->segment.duration != GST_CLOCK_TIME_NONE &&
4893           segment->time > qtdemux->segment.duration)) {
4894     GST_WARNING_OBJECT (stream->pad, "file duration %" GST_TIME_FORMAT
4895         " < segment->time %" GST_TIME_FORMAT,
4896         GST_TIME_ARGS (qtdemux->segment.duration),
4897         GST_TIME_ARGS (segment->time));
4898     return FALSE;
4899   }
4900
4901   gst_qtdemux_stream_segment_get_boundaries (qtdemux, stream, offset,
4902       &start, &stop, &time);
4903
4904   GST_DEBUG_OBJECT (stream->pad, "new segment %d from %" GST_TIME_FORMAT
4905       " to %" GST_TIME_FORMAT ", time %" GST_TIME_FORMAT, seg_idx,
4906       GST_TIME_ARGS (start), GST_TIME_ARGS (stop), GST_TIME_ARGS (time));
4907
4908   /* combine global rate with that of the segment */
4909   rate = segment->rate * qtdemux->segment.rate;
4910
4911   /* Copy flags from main segment */
4912   stream->segment.flags = qtdemux->segment.flags;
4913
4914   /* need to offset with the start time of the first sample */
4915   min_ts = gst_qtdemux_streams_get_first_sample_ts (qtdemux);
4916
4917   /* update the segment values used for clipping */
4918   stream->segment.offset = qtdemux->segment.offset;
4919   stream->segment.base = qtdemux->segment.base + stream->accumulated_base;
4920   stream->segment.applied_rate = qtdemux->segment.applied_rate;
4921   stream->segment.rate = rate;
4922   stream->segment.start = start + QTSTREAMTIME_TO_GSTTIME (stream,
4923       stream->cslg_shift) + min_ts;
4924   if (GST_CLOCK_TIME_IS_VALID (stop)) {
4925     stream->segment.stop = stop + QTSTREAMTIME_TO_GSTTIME (stream,
4926         stream->cslg_shift) + min_ts;
4927   }
4928   stream->segment.time = time + min_ts;
4929   stream->segment.position = stream->segment.start + min_ts;
4930
4931   GST_DEBUG_OBJECT (stream->pad, "New segment: %" GST_SEGMENT_FORMAT,
4932       &stream->segment);
4933
4934   /* now prepare and send the segment */
4935   if (stream->pad) {
4936     event = gst_event_new_segment (&stream->segment);
4937     if (qtdemux->segment_seqnum != GST_SEQNUM_INVALID) {
4938       gst_event_set_seqnum (event, qtdemux->segment_seqnum);
4939     }
4940     gst_pad_push_event (stream->pad, event);
4941     /* assume we can send more data now */
4942     GST_PAD_LAST_FLOW_RETURN (stream->pad) = GST_FLOW_OK;
4943     /* clear to send tags on this pad now */
4944     gst_qtdemux_push_tags (qtdemux, stream);
4945   }
4946
4947   if (_start)
4948     *_start = start;
4949   if (_stop)
4950     *_stop = stop;
4951
4952   return TRUE;
4953 }
4954
4955 /* activate the given segment number @seg_idx of @stream at time @offset.
4956  * @offset is an absolute global position over all the segments.
4957  *
4958  * This will push out a NEWSEGMENT event with the right values and
4959  * position the stream index to the first decodable sample before
4960  * @offset.
4961  */
4962 static gboolean
4963 gst_qtdemux_activate_segment (GstQTDemux * qtdemux, QtDemuxStream * stream,
4964     guint32 seg_idx, GstClockTime offset)
4965 {
4966   QtDemuxSegment *segment;
4967   guint32 index, kf_index;
4968   GstClockTime start = 0, stop = GST_CLOCK_TIME_NONE;
4969
4970   GST_LOG_OBJECT (stream->pad, "activate segment %d, offset %" GST_TIME_FORMAT,
4971       seg_idx, GST_TIME_ARGS (offset));
4972
4973   if (!gst_qtdemux_stream_update_segment (qtdemux, stream, seg_idx, offset,
4974           &start, &stop))
4975     return FALSE;
4976
4977   segment = &stream->segments[stream->segment_index];
4978
4979   /* in the fragmented case, we pick a fragment that starts before our
4980    * desired position and rely on downstream to wait for a keyframe
4981    * (FIXME: doesn't seem to work so well with ismv and wmv, as no parser; the
4982    * tfra entries tells us which trun/sample the key unit is in, but we don't
4983    * make use of this additional information at the moment) */
4984   if (qtdemux->fragmented && !qtdemux->fragmented_seek_pending) {
4985     stream->to_sample = G_MAXUINT32;
4986     return TRUE;
4987   } else {
4988     /* well, it will be taken care of below */
4989     qtdemux->fragmented_seek_pending = FALSE;
4990     /* FIXME ideally the do_fragmented_seek can be done right here,
4991      * rather than at loop level
4992      * (which might even allow handling edit lists in a fragmented file) */
4993   }
4994
4995   /* We don't need to look for a sample in push-based */
4996   if (!qtdemux->pullbased)
4997     return TRUE;
4998
4999   /* and move to the keyframe before the indicated media time of the
5000    * segment */
5001   if (G_LIKELY (!QTSEGMENT_IS_EMPTY (segment))) {
5002     if (qtdemux->segment.rate >= 0) {
5003       index = gst_qtdemux_find_index_linear (qtdemux, stream, start);
5004       stream->to_sample = G_MAXUINT32;
5005       GST_DEBUG_OBJECT (stream->pad,
5006           "moving data pointer to %" GST_TIME_FORMAT ", index: %u, pts %"
5007           GST_TIME_FORMAT, GST_TIME_ARGS (start), index,
5008           GST_TIME_ARGS (QTSAMPLE_PTS (stream, &stream->samples[index])));
5009     } else {
5010       index = gst_qtdemux_find_index_linear (qtdemux, stream, stop);
5011       stream->to_sample = index;
5012       GST_DEBUG_OBJECT (stream->pad,
5013           "moving data pointer to %" GST_TIME_FORMAT ", index: %u, pts %"
5014           GST_TIME_FORMAT, GST_TIME_ARGS (stop), index,
5015           GST_TIME_ARGS (QTSAMPLE_PTS (stream, &stream->samples[index])));
5016     }
5017   } else {
5018     GST_DEBUG_OBJECT (stream->pad, "No need to look for keyframe, "
5019         "this is an empty segment");
5020     return TRUE;
5021   }
5022
5023   /* gst_qtdemux_parse_sample () called from gst_qtdemux_find_index_linear ()
5024    * encountered an error and printed a message so we return appropriately */
5025   if (index == -1)
5026     return FALSE;
5027
5028   /* we're at the right spot */
5029   if (index == stream->sample_index) {
5030     GST_DEBUG_OBJECT (stream->pad, "we are at the right index");
5031     return TRUE;
5032   }
5033
5034   /* find keyframe of the target index */
5035   kf_index = gst_qtdemux_find_keyframe (qtdemux, stream, index, FALSE);
5036
5037 /* *INDENT-OFF* */
5038 /* indent does stupid stuff with stream->samples[].timestamp */
5039
5040   /* if we move forwards, we don't have to go back to the previous
5041    * keyframe since we already sent that. We can also just jump to
5042    * the keyframe right before the target index if there is one. */
5043   if (index > stream->sample_index) {
5044     /* moving forwards check if we move past a keyframe */
5045     if (kf_index > stream->sample_index) {
5046       GST_DEBUG_OBJECT (stream->pad,
5047            "moving forwards to keyframe at %u (pts %" GST_TIME_FORMAT " dts %"GST_TIME_FORMAT" )", kf_index,
5048            GST_TIME_ARGS (QTSAMPLE_PTS(stream, &stream->samples[kf_index])),
5049            GST_TIME_ARGS (QTSAMPLE_DTS(stream, &stream->samples[kf_index])));
5050       gst_qtdemux_move_stream (qtdemux, stream, kf_index);
5051     } else {
5052       GST_DEBUG_OBJECT (stream->pad,
5053           "moving forwards, keyframe at %u (pts %" GST_TIME_FORMAT " dts %"GST_TIME_FORMAT" ) already sent", kf_index,
5054           GST_TIME_ARGS (QTSAMPLE_PTS (stream, &stream->samples[kf_index])),
5055           GST_TIME_ARGS (QTSAMPLE_DTS (stream, &stream->samples[kf_index])));
5056     }
5057   } else {
5058     GST_DEBUG_OBJECT (stream->pad,
5059         "moving backwards to keyframe at %u (pts %" GST_TIME_FORMAT " dts %"GST_TIME_FORMAT" )", kf_index,
5060         GST_TIME_ARGS (QTSAMPLE_PTS(stream, &stream->samples[kf_index])),
5061         GST_TIME_ARGS (QTSAMPLE_DTS(stream, &stream->samples[kf_index])));
5062     gst_qtdemux_move_stream (qtdemux, stream, kf_index);
5063   }
5064
5065 /* *INDENT-ON* */
5066
5067   return TRUE;
5068 }
5069
5070 /* prepare to get the current sample of @stream, getting essential values.
5071  *
5072  * This function will also prepare and send the segment when needed.
5073  *
5074  * Return FALSE if the stream is EOS.
5075  *
5076  * PULL-BASED
5077  */
5078 static gboolean
5079 gst_qtdemux_prepare_current_sample (GstQTDemux * qtdemux,
5080     QtDemuxStream * stream, gboolean * empty, guint64 * offset, guint * size,
5081     GstClockTime * dts, GstClockTime * pts, GstClockTime * duration,
5082     gboolean * keyframe)
5083 {
5084   QtDemuxSample *sample;
5085   GstClockTime time_position;
5086   guint32 seg_idx;
5087
5088   g_return_val_if_fail (stream != NULL, FALSE);
5089
5090   time_position = stream->time_position;
5091   if (G_UNLIKELY (time_position == GST_CLOCK_TIME_NONE))
5092     goto eos;
5093
5094   seg_idx = stream->segment_index;
5095   if (G_UNLIKELY (seg_idx == -1)) {
5096     /* find segment corresponding to time_position if we are looking
5097      * for a segment. */
5098     seg_idx = gst_qtdemux_find_segment (qtdemux, stream, time_position);
5099   }
5100
5101   /* different segment, activate it, sample_index will be set. */
5102   if (G_UNLIKELY (stream->segment_index != seg_idx))
5103     gst_qtdemux_activate_segment (qtdemux, stream, seg_idx, time_position);
5104
5105   if (G_UNLIKELY (QTSEGMENT_IS_EMPTY (&stream->segments[stream->
5106                   segment_index]))) {
5107     QtDemuxSegment *seg = &stream->segments[stream->segment_index];
5108
5109     GST_LOG_OBJECT (qtdemux, "Empty segment activated,"
5110         " prepare empty sample");
5111
5112     *empty = TRUE;
5113     *pts = *dts = time_position;
5114     *duration = seg->duration - (time_position - seg->time);
5115
5116     return TRUE;
5117   }
5118
5119   *empty = FALSE;
5120
5121   if (stream->sample_index == -1)
5122     stream->sample_index = 0;
5123
5124   GST_LOG_OBJECT (qtdemux, "segment active, index = %u of %u",
5125       stream->sample_index, stream->n_samples);
5126
5127   if (G_UNLIKELY (stream->sample_index >= stream->n_samples)) {
5128     if (!qtdemux->fragmented)
5129       goto eos;
5130
5131     GST_INFO_OBJECT (qtdemux, "out of samples, trying to add more");
5132     do {
5133       GstFlowReturn flow;
5134
5135       GST_OBJECT_LOCK (qtdemux);
5136       flow = qtdemux_add_fragmented_samples (qtdemux);
5137       GST_OBJECT_UNLOCK (qtdemux);
5138
5139       if (flow != GST_FLOW_OK)
5140         goto eos;
5141     }
5142     while (stream->sample_index >= stream->n_samples);
5143   }
5144
5145   if (!qtdemux_parse_samples (qtdemux, stream, stream->sample_index)) {
5146     GST_LOG_OBJECT (qtdemux, "Parsing of index %u failed!",
5147         stream->sample_index);
5148     return FALSE;
5149   }
5150
5151   /* now get the info for the sample we're at */
5152   sample = &stream->samples[stream->sample_index];
5153
5154   *dts = QTSAMPLE_DTS (stream, sample);
5155   *pts = QTSAMPLE_PTS (stream, sample);
5156   *offset = sample->offset;
5157   *size = sample->size;
5158   *duration = QTSAMPLE_DUR_DTS (stream, sample, *dts);
5159   *keyframe = QTSAMPLE_KEYFRAME (stream, sample);
5160
5161   return TRUE;
5162
5163   /* special cases */
5164 eos:
5165   {
5166     stream->time_position = GST_CLOCK_TIME_NONE;
5167     return FALSE;
5168   }
5169 }
5170
5171 /* move to the next sample in @stream.
5172  *
5173  * Moves to the next segment when needed.
5174  */
5175 static void
5176 gst_qtdemux_advance_sample (GstQTDemux * qtdemux, QtDemuxStream * stream)
5177 {
5178   QtDemuxSample *sample;
5179   QtDemuxSegment *segment;
5180
5181   /* get current segment */
5182   segment = &stream->segments[stream->segment_index];
5183
5184   if (G_UNLIKELY (QTSEGMENT_IS_EMPTY (segment))) {
5185     GST_DEBUG_OBJECT (qtdemux, "Empty segment, no samples to advance");
5186     goto next_segment;
5187   }
5188
5189   if (G_UNLIKELY (stream->sample_index >= stream->to_sample)) {
5190     /* Mark the stream as EOS */
5191     GST_DEBUG_OBJECT (qtdemux,
5192         "reached max allowed sample %u, mark EOS", stream->to_sample);
5193     stream->time_position = GST_CLOCK_TIME_NONE;
5194     return;
5195   }
5196
5197   /* move to next sample */
5198   stream->sample_index++;
5199   stream->offset_in_sample = 0;
5200
5201   /* reached the last sample, we need the next segment */
5202   if (G_UNLIKELY (stream->sample_index >= stream->n_samples))
5203     goto next_segment;
5204
5205   if (!qtdemux_parse_samples (qtdemux, stream, stream->sample_index)) {
5206     GST_LOG_OBJECT (qtdemux, "Parsing of index %u failed!",
5207         stream->sample_index);
5208     return;
5209   }
5210
5211   /* get next sample */
5212   sample = &stream->samples[stream->sample_index];
5213
5214   /* see if we are past the segment */
5215   if (G_UNLIKELY (QTSAMPLE_DTS (stream, sample) >= segment->media_stop))
5216     goto next_segment;
5217
5218   if (QTSAMPLE_DTS (stream, sample) >= segment->media_start) {
5219     /* inside the segment, update time_position, looks very familiar to
5220      * GStreamer segments, doesn't it? */
5221     stream->time_position =
5222         QTSAMPLE_DTS (stream, sample) - segment->media_start + segment->time;
5223   } else {
5224     /* not yet in segment, time does not yet increment. This means
5225      * that we are still prerolling keyframes to the decoder so it can
5226      * decode the first sample of the segment. */
5227     stream->time_position = segment->time;
5228   }
5229   return;
5230
5231   /* move to the next segment */
5232 next_segment:
5233   {
5234     GST_DEBUG_OBJECT (qtdemux, "segment %d ended ", stream->segment_index);
5235
5236     if (stream->segment_index == stream->n_segments - 1) {
5237       /* are we at the end of the last segment, we're EOS */
5238       stream->time_position = GST_CLOCK_TIME_NONE;
5239     } else {
5240       /* else we're only at the end of the current segment */
5241       stream->time_position = segment->stop_time;
5242     }
5243     /* make sure we select a new segment */
5244
5245     /* accumulate previous segments */
5246     if (GST_CLOCK_TIME_IS_VALID (stream->segment.stop))
5247       stream->accumulated_base +=
5248           (stream->segment.stop -
5249           stream->segment.start) / ABS (stream->segment.rate);
5250
5251     stream->segment_index = -1;
5252   }
5253 }
5254
5255 static void
5256 gst_qtdemux_sync_streams (GstQTDemux * demux)
5257 {
5258   GList *iter;
5259
5260   if (demux->n_streams <= 1)
5261     return;
5262
5263   for (iter = demux->active_streams; iter; iter = g_list_next (iter)) {
5264     QtDemuxStream *stream;
5265     GstClockTime end_time;
5266
5267     stream = QTDEMUX_STREAM (iter->data);
5268
5269     if (!stream->pad)
5270       continue;
5271
5272     /* TODO advance time on subtitle streams here, if any some day */
5273
5274     /* some clips/trailers may have unbalanced streams at the end,
5275      * so send EOS on shorter stream to prevent stalling others */
5276
5277     /* do not mess with EOS if SEGMENT seeking */
5278     if (demux->segment.flags & GST_SEEK_FLAG_SEGMENT)
5279       continue;
5280
5281     if (demux->pullbased) {
5282       /* loop mode is sample time based */
5283       if (!STREAM_IS_EOS (stream))
5284         continue;
5285     } else {
5286       /* push mode is byte position based */
5287       if (stream->n_samples &&
5288           stream->samples[stream->n_samples - 1].offset >= demux->offset)
5289         continue;
5290     }
5291
5292     if (stream->sent_eos)
5293       continue;
5294
5295     /* only act if some gap */
5296     end_time = stream->segments[stream->n_segments - 1].stop_time;
5297     GST_LOG_OBJECT (demux, "current position: %" GST_TIME_FORMAT
5298         ", stream end: %" GST_TIME_FORMAT,
5299         GST_TIME_ARGS (demux->segment.position), GST_TIME_ARGS (end_time));
5300     if (GST_CLOCK_TIME_IS_VALID (end_time)
5301         && (end_time + 2 * GST_SECOND < demux->segment.position)) {
5302       GstEvent *event;
5303
5304       GST_DEBUG_OBJECT (demux, "sending EOS for stream %s",
5305           GST_PAD_NAME (stream->pad));
5306       stream->sent_eos = TRUE;
5307       event = gst_event_new_eos ();
5308       if (demux->segment_seqnum != GST_SEQNUM_INVALID)
5309         gst_event_set_seqnum (event, demux->segment_seqnum);
5310       gst_pad_push_event (stream->pad, event);
5311     }
5312   }
5313 }
5314
5315 /* EOS and NOT_LINKED need to be combined. This means that we return:
5316  *
5317  *  GST_FLOW_NOT_LINKED: when all pads NOT_LINKED.
5318  *  GST_FLOW_EOS: when all pads EOS or NOT_LINKED.
5319  */
5320 static GstFlowReturn
5321 gst_qtdemux_combine_flows (GstQTDemux * demux, QtDemuxStream * stream,
5322     GstFlowReturn ret)
5323 {
5324   GST_LOG_OBJECT (demux, "flow return: %s", gst_flow_get_name (ret));
5325
5326   if (stream->pad)
5327     ret = gst_flow_combiner_update_pad_flow (demux->flowcombiner, stream->pad,
5328         ret);
5329   else
5330     ret = gst_flow_combiner_update_flow (demux->flowcombiner, ret);
5331
5332   GST_LOG_OBJECT (demux, "combined flow return: %s", gst_flow_get_name (ret));
5333   return ret;
5334 }
5335
5336 /* the input buffer metadata must be writable. Returns NULL when the buffer is
5337  * completely clipped
5338  *
5339  * Should be used only with raw buffers */
5340 static GstBuffer *
5341 gst_qtdemux_clip_buffer (GstQTDemux * qtdemux, QtDemuxStream * stream,
5342     GstBuffer * buf)
5343 {
5344   guint64 start, stop, cstart, cstop, diff;
5345   GstClockTime pts, duration;
5346   gsize size, osize;
5347   gint num_rate, denom_rate;
5348   gint frame_size;
5349   gboolean clip_data;
5350   guint offset;
5351
5352   osize = size = gst_buffer_get_size (buf);
5353   offset = 0;
5354
5355   /* depending on the type, setup the clip parameters */
5356   if (stream->subtype == FOURCC_soun) {
5357     frame_size = CUR_STREAM (stream)->bytes_per_frame;
5358     num_rate = GST_SECOND;
5359     denom_rate = (gint) CUR_STREAM (stream)->rate;
5360     clip_data = TRUE;
5361   } else if (stream->subtype == FOURCC_vide) {
5362     frame_size = size;
5363     num_rate = CUR_STREAM (stream)->fps_n;
5364     denom_rate = CUR_STREAM (stream)->fps_d;
5365     clip_data = FALSE;
5366   } else
5367     goto wrong_type;
5368
5369   if (frame_size <= 0)
5370     goto bad_frame_size;
5371
5372   /* we can only clip if we have a valid pts */
5373   pts = GST_BUFFER_PTS (buf);
5374   if (G_UNLIKELY (!GST_CLOCK_TIME_IS_VALID (pts)))
5375     goto no_pts;
5376
5377   duration = GST_BUFFER_DURATION (buf);
5378
5379   if (G_UNLIKELY (!GST_CLOCK_TIME_IS_VALID (duration))) {
5380     duration =
5381         gst_util_uint64_scale_int (size / frame_size, num_rate, denom_rate);
5382   }
5383
5384   start = pts;
5385   stop = start + duration;
5386
5387   if (G_UNLIKELY (!gst_segment_clip (&stream->segment,
5388               GST_FORMAT_TIME, start, stop, &cstart, &cstop)))
5389     goto clipped;
5390
5391   /* see if some clipping happened */
5392   diff = cstart - start;
5393   if (diff > 0) {
5394     pts += diff;
5395     duration -= diff;
5396
5397     if (clip_data) {
5398       /* bring clipped time to samples and to bytes */
5399       diff = gst_util_uint64_scale_int (diff, denom_rate, num_rate);
5400       diff *= frame_size;
5401
5402       GST_DEBUG_OBJECT (qtdemux,
5403           "clipping start to %" GST_TIME_FORMAT " %"
5404           G_GUINT64_FORMAT " bytes", GST_TIME_ARGS (cstart), diff);
5405
5406       offset = diff;
5407       size -= diff;
5408     }
5409   }
5410   diff = stop - cstop;
5411   if (diff > 0) {
5412     duration -= diff;
5413
5414     if (clip_data) {
5415       /* bring clipped time to samples and then to bytes */
5416       diff = gst_util_uint64_scale_int (diff, denom_rate, num_rate);
5417       diff *= frame_size;
5418       GST_DEBUG_OBJECT (qtdemux,
5419           "clipping stop to %" GST_TIME_FORMAT " %" G_GUINT64_FORMAT
5420           " bytes", GST_TIME_ARGS (cstop), diff);
5421       size -= diff;
5422     }
5423   }
5424
5425   if (offset != 0 || size != osize)
5426     gst_buffer_resize (buf, offset, size);
5427
5428   GST_BUFFER_DTS (buf) = GST_CLOCK_TIME_NONE;
5429   GST_BUFFER_PTS (buf) = pts;
5430   GST_BUFFER_DURATION (buf) = duration;
5431
5432   return buf;
5433
5434   /* dropped buffer */
5435 wrong_type:
5436   {
5437     GST_DEBUG_OBJECT (qtdemux, "unknown stream type");
5438     return buf;
5439   }
5440 bad_frame_size:
5441   {
5442     GST_DEBUG_OBJECT (qtdemux, "bad frame size");
5443     return buf;
5444   }
5445 no_pts:
5446   {
5447     GST_DEBUG_OBJECT (qtdemux, "no pts on buffer");
5448     return buf;
5449   }
5450 clipped:
5451   {
5452     GST_DEBUG_OBJECT (qtdemux, "clipped buffer");
5453     gst_buffer_unref (buf);
5454     return NULL;
5455   }
5456 }
5457
5458 static GstBuffer *
5459 gst_qtdemux_align_buffer (GstQTDemux * demux,
5460     GstBuffer * buffer, gsize alignment)
5461 {
5462   GstMapInfo map;
5463
5464   gst_buffer_map (buffer, &map, GST_MAP_READ);
5465
5466   if (map.size < sizeof (guintptr)) {
5467     gst_buffer_unmap (buffer, &map);
5468     return buffer;
5469   }
5470
5471   if (((guintptr) map.data) & (alignment - 1)) {
5472     GstBuffer *new_buffer;
5473     GstAllocationParams params = { 0, alignment - 1, 0, 0, };
5474
5475     new_buffer = gst_buffer_new_allocate (NULL,
5476         gst_buffer_get_size (buffer), &params);
5477
5478     /* Copy data "by hand", so ensure alignment is kept: */
5479     gst_buffer_fill (new_buffer, 0, map.data, map.size);
5480
5481     gst_buffer_copy_into (new_buffer, buffer, GST_BUFFER_COPY_METADATA, 0, -1);
5482     GST_DEBUG_OBJECT (demux,
5483         "We want output aligned on %" G_GSIZE_FORMAT ", reallocated",
5484         alignment);
5485
5486     gst_buffer_unmap (buffer, &map);
5487     gst_buffer_unref (buffer);
5488
5489     return new_buffer;
5490   }
5491
5492   gst_buffer_unmap (buffer, &map);
5493   return buffer;
5494 }
5495
5496 static guint8 *
5497 convert_to_ccdata (const guint8 * ccpair, guint8 ccpair_size, guint field,
5498     gsize * res)
5499 {
5500   guint8 *storage;
5501   gsize i;
5502
5503   /* We are converting from pairs to triplets */
5504   *res = ccpair_size / 2 * 3;
5505   storage = g_malloc (*res);
5506   for (i = 0; i * 2 < ccpair_size; i += 1) {
5507     if (field == 1)
5508       storage[i * 3] = 0xfc;
5509     else
5510       storage[i * 3] = 0xfd;
5511     storage[i * 3 + 1] = ccpair[i * 2];
5512     storage[i * 3 + 2] = ccpair[i * 2 + 1];
5513   }
5514
5515   return storage;
5516 }
5517
5518 static guint8 *
5519 extract_cc_from_data (QtDemuxStream * stream, const guint8 * data, gsize size,
5520     gsize * cclen)
5521 {
5522   guint8 *res = NULL;
5523   guint32 atom_length, fourcc;
5524   QtDemuxStreamStsdEntry *stsd_entry;
5525
5526   GST_MEMDUMP ("caption atom", data, size);
5527
5528   /* There might be multiple atoms */
5529
5530   *cclen = 0;
5531   if (size < 8)
5532     goto invalid_cdat;
5533   atom_length = QT_UINT32 (data);
5534   fourcc = QT_FOURCC (data + 4);
5535   if (G_UNLIKELY (atom_length > size || atom_length == 8))
5536     goto invalid_cdat;
5537
5538   GST_DEBUG_OBJECT (stream->pad, "here");
5539
5540   /* Check if we have somethig compatible */
5541   stsd_entry = CUR_STREAM (stream);
5542   switch (stsd_entry->fourcc) {
5543     case FOURCC_c608:{
5544       guint8 *cdat = NULL, *cdt2 = NULL;
5545       gsize cdat_size = 0, cdt2_size = 0;
5546       /* Should be cdat or cdt2 */
5547       if (fourcc != FOURCC_cdat && fourcc != FOURCC_cdt2) {
5548         GST_WARNING_OBJECT (stream->pad,
5549             "Unknown data atom (%" GST_FOURCC_FORMAT ") for CEA608",
5550             GST_FOURCC_ARGS (fourcc));
5551         goto invalid_cdat;
5552       }
5553
5554       /* Convert to cc_data triplet */
5555       if (fourcc == FOURCC_cdat)
5556         cdat = convert_to_ccdata (data + 8, atom_length - 8, 1, &cdat_size);
5557       else
5558         cdt2 = convert_to_ccdata (data + 8, atom_length - 8, 2, &cdt2_size);
5559       GST_DEBUG_OBJECT (stream->pad, "size:%" G_GSIZE_FORMAT " atom_length:%u",
5560           size, atom_length);
5561
5562       /* Check for another atom ? */
5563       if (size > atom_length + 8) {
5564         guint32 new_atom_length = QT_UINT32 (data + atom_length);
5565         if (size >= atom_length + new_atom_length) {
5566           fourcc = QT_FOURCC (data + atom_length + 4);
5567           if (fourcc == FOURCC_cdat) {
5568             if (cdat == NULL)
5569               cdat =
5570                   convert_to_ccdata (data + atom_length + 8,
5571                   new_atom_length - 8, 1, &cdat_size);
5572             else
5573               GST_WARNING_OBJECT (stream->pad,
5574                   "Got multiple [cdat] atoms in a c608 sample. This is unsupported for now. Please file a bug");
5575           } else {
5576             if (cdt2 == NULL)
5577               cdt2 =
5578                   convert_to_ccdata (data + atom_length + 8,
5579                   new_atom_length - 8, 2, &cdt2_size);
5580             else
5581               GST_WARNING_OBJECT (stream->pad,
5582                   "Got multiple [cdt2] atoms in a c608 sample. This is unsupported for now. Please file a bug");
5583           }
5584         }
5585       }
5586
5587       *cclen = cdat_size + cdt2_size;
5588       res = g_malloc (*cclen);
5589       if (cdat_size)
5590         memcpy (res, cdat, cdat_size);
5591       if (cdt2_size)
5592         memcpy (res + cdat_size, cdt2, cdt2_size);
5593       g_free (cdat);
5594       g_free (cdt2);
5595     }
5596       break;
5597     case FOURCC_c708:
5598       if (fourcc != FOURCC_ccdp) {
5599         GST_WARNING_OBJECT (stream->pad,
5600             "Unknown data atom (%" GST_FOURCC_FORMAT ") for CEA708",
5601             GST_FOURCC_ARGS (fourcc));
5602         goto invalid_cdat;
5603       }
5604       *cclen = atom_length - 8;
5605       res = g_memdup (data + 8, *cclen);
5606       break;
5607     default:
5608       /* Keep this here in case other closed caption formats are added */
5609       g_assert_not_reached ();
5610       break;
5611   }
5612
5613   GST_MEMDUMP ("Output", res, *cclen);
5614   return res;
5615
5616   /* Errors */
5617 invalid_cdat:
5618   GST_WARNING ("[cdat] atom is too small or invalid");
5619   return NULL;
5620 }
5621
5622 /* the input buffer metadata must be writable,
5623  * but time/duration etc not yet set and need not be preserved */
5624 static GstBuffer *
5625 gst_qtdemux_process_buffer (GstQTDemux * qtdemux, QtDemuxStream * stream,
5626     GstBuffer * buf)
5627 {
5628   GstMapInfo map;
5629   guint nsize = 0;
5630   gchar *str;
5631
5632   /* not many cases for now */
5633   if (G_UNLIKELY (CUR_STREAM (stream)->fourcc == FOURCC_mp4s)) {
5634     /* send a one time dvd clut event */
5635     if (stream->pending_event && stream->pad)
5636       gst_pad_push_event (stream->pad, stream->pending_event);
5637     stream->pending_event = NULL;
5638   }
5639
5640   if (G_UNLIKELY (stream->subtype != FOURCC_text
5641           && stream->subtype != FOURCC_sbtl &&
5642           stream->subtype != FOURCC_subp && stream->subtype != FOURCC_clcp)) {
5643     return buf;
5644   }
5645
5646   gst_buffer_map (buf, &map, GST_MAP_READ);
5647
5648   /* empty buffer is sent to terminate previous subtitle */
5649   if (map.size <= 2) {
5650     gst_buffer_unmap (buf, &map);
5651     gst_buffer_unref (buf);
5652     return NULL;
5653   }
5654   if (stream->subtype == FOURCC_subp) {
5655     /* That's all the processing needed for subpictures */
5656     gst_buffer_unmap (buf, &map);
5657     return buf;
5658   }
5659
5660   if (stream->subtype == FOURCC_clcp) {
5661     guint8 *cc;
5662     gsize cclen = 0;
5663     /* For closed caption, we need to extract the information from the
5664      * [cdat],[cdt2] or [ccdp] atom */
5665     cc = extract_cc_from_data (stream, map.data, map.size, &cclen);
5666     gst_buffer_unmap (buf, &map);
5667     gst_buffer_unref (buf);
5668     if (cc) {
5669       buf = _gst_buffer_new_wrapped (cc, cclen, g_free);
5670     } else {
5671       /* Conversion failed or there's nothing */
5672       buf = NULL;
5673     }
5674     return buf;
5675   }
5676
5677   nsize = GST_READ_UINT16_BE (map.data);
5678   nsize = MIN (nsize, map.size - 2);
5679
5680   GST_LOG_OBJECT (qtdemux, "3GPP timed text subtitle: %d/%" G_GSIZE_FORMAT "",
5681       nsize, map.size);
5682
5683   /* takes care of UTF-8 validation or UTF-16 recognition,
5684    * no other encoding expected */
5685   str = gst_tag_freeform_string_to_utf8 ((gchar *) map.data + 2, nsize, NULL);
5686   gst_buffer_unmap (buf, &map);
5687   if (str) {
5688     gst_buffer_unref (buf);
5689     buf = _gst_buffer_new_wrapped (str, strlen (str), g_free);
5690   } else {
5691     /* this should not really happen unless the subtitle is corrupted */
5692     gst_buffer_unref (buf);
5693     buf = NULL;
5694   }
5695
5696   /* FIXME ? convert optional subsequent style info to markup */
5697
5698   return buf;
5699 }
5700
5701 /* Sets a buffer's attributes properly and pushes it downstream.
5702  * Also checks for additional actions and custom processing that may
5703  * need to be done first.
5704  */
5705 static GstFlowReturn
5706 gst_qtdemux_decorate_and_push_buffer (GstQTDemux * qtdemux,
5707     QtDemuxStream * stream, GstBuffer * buf,
5708     GstClockTime dts, GstClockTime pts, GstClockTime duration,
5709     gboolean keyframe, GstClockTime position, guint64 byte_position)
5710 {
5711   GstFlowReturn ret = GST_FLOW_OK;
5712
5713   /* offset the timestamps according to the edit list */
5714
5715   if (G_UNLIKELY (CUR_STREAM (stream)->fourcc == FOURCC_rtsp)) {
5716     gchar *url;
5717     GstMapInfo map;
5718
5719     gst_buffer_map (buf, &map, GST_MAP_READ);
5720     url = g_strndup ((gchar *) map.data, map.size);
5721     gst_buffer_unmap (buf, &map);
5722     if (url != NULL && strlen (url) != 0) {
5723       /* we have RTSP redirect now */
5724       gst_element_post_message (GST_ELEMENT_CAST (qtdemux),
5725           gst_message_new_element (GST_OBJECT_CAST (qtdemux),
5726               gst_structure_new ("redirect",
5727                   "new-location", G_TYPE_STRING, url, NULL)));
5728       qtdemux->posted_redirect = TRUE;
5729     } else {
5730       GST_WARNING_OBJECT (qtdemux, "Redirect URI of stream is empty, not "
5731           "posting");
5732     }
5733     g_free (url);
5734   }
5735
5736   /* position reporting */
5737   if (qtdemux->segment.rate >= 0) {
5738     qtdemux->segment.position = position;
5739     gst_qtdemux_sync_streams (qtdemux);
5740   }
5741
5742   if (G_UNLIKELY (!stream->pad)) {
5743     GST_DEBUG_OBJECT (qtdemux, "No output pad for stream, ignoring");
5744     gst_buffer_unref (buf);
5745     goto exit;
5746   }
5747
5748   /* send out pending buffers */
5749   while (stream->buffers) {
5750     GstBuffer *buffer = (GstBuffer *) stream->buffers->data;
5751
5752     if (G_UNLIKELY (stream->discont)) {
5753       GST_LOG_OBJECT (qtdemux, "marking discont buffer");
5754       GST_BUFFER_FLAG_SET (buffer, GST_BUFFER_FLAG_DISCONT);
5755       stream->discont = FALSE;
5756     } else {
5757       GST_BUFFER_FLAG_UNSET (buf, GST_BUFFER_FLAG_DISCONT);
5758     }
5759
5760     if (stream->alignment > 1)
5761       buffer = gst_qtdemux_align_buffer (qtdemux, buffer, stream->alignment);
5762     gst_pad_push (stream->pad, buffer);
5763
5764     stream->buffers = g_slist_delete_link (stream->buffers, stream->buffers);
5765   }
5766
5767   /* we're going to modify the metadata */
5768   buf = gst_buffer_make_writable (buf);
5769
5770   if (G_UNLIKELY (stream->need_process))
5771     buf = gst_qtdemux_process_buffer (qtdemux, stream, buf);
5772
5773   if (!buf) {
5774     goto exit;
5775   }
5776
5777   GST_BUFFER_DTS (buf) = dts;
5778   GST_BUFFER_PTS (buf) = pts;
5779   GST_BUFFER_DURATION (buf) = duration;
5780   GST_BUFFER_OFFSET (buf) = -1;
5781   GST_BUFFER_OFFSET_END (buf) = -1;
5782
5783   if (G_UNLIKELY (CUR_STREAM (stream)->rgb8_palette))
5784     gst_buffer_append_memory (buf,
5785         gst_memory_ref (CUR_STREAM (stream)->rgb8_palette));
5786
5787   if (G_UNLIKELY (CUR_STREAM (stream)->padding)) {
5788     gst_buffer_resize (buf, CUR_STREAM (stream)->padding, -1);
5789   }
5790 #if 0
5791   if (G_UNLIKELY (qtdemux->element_index)) {
5792     GstClockTime stream_time;
5793
5794     stream_time =
5795         gst_segment_to_stream_time (&stream->segment, GST_FORMAT_TIME,
5796         timestamp);
5797     if (GST_CLOCK_TIME_IS_VALID (stream_time)) {
5798       GST_LOG_OBJECT (qtdemux,
5799           "adding association %" GST_TIME_FORMAT "-> %"
5800           G_GUINT64_FORMAT, GST_TIME_ARGS (stream_time), byte_position);
5801       gst_index_add_association (qtdemux->element_index,
5802           qtdemux->index_id,
5803           keyframe ? GST_ASSOCIATION_FLAG_KEY_UNIT :
5804           GST_ASSOCIATION_FLAG_DELTA_UNIT, GST_FORMAT_TIME, stream_time,
5805           GST_FORMAT_BYTES, byte_position, NULL);
5806     }
5807   }
5808 #endif
5809
5810   if (stream->need_clip)
5811     buf = gst_qtdemux_clip_buffer (qtdemux, stream, buf);
5812
5813   if (G_UNLIKELY (buf == NULL))
5814     goto exit;
5815
5816   if (G_UNLIKELY (stream->discont)) {
5817     GST_LOG_OBJECT (qtdemux, "marking discont buffer");
5818     GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_DISCONT);
5819     stream->discont = FALSE;
5820   } else {
5821     GST_BUFFER_FLAG_UNSET (buf, GST_BUFFER_FLAG_DISCONT);
5822   }
5823
5824   if (!keyframe) {
5825     GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_DELTA_UNIT);
5826     stream->on_keyframe = FALSE;
5827   } else {
5828     stream->on_keyframe = TRUE;
5829   }
5830
5831
5832   GST_LOG_OBJECT (qtdemux,
5833       "Pushing buffer with dts %" GST_TIME_FORMAT ", pts %" GST_TIME_FORMAT
5834       ", duration %" GST_TIME_FORMAT " on pad %s", GST_TIME_ARGS (dts),
5835       GST_TIME_ARGS (pts), GST_TIME_ARGS (duration),
5836       GST_PAD_NAME (stream->pad));
5837
5838   if (stream->protected && stream->protection_scheme_type == FOURCC_cenc) {
5839     GstStructure *crypto_info;
5840     QtDemuxCencSampleSetInfo *info =
5841         (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
5842     gint index;
5843     GstEvent *event;
5844
5845     while ((event = g_queue_pop_head (&stream->protection_scheme_event_queue))) {
5846       GST_TRACE_OBJECT (stream->pad, "pushing protection event: %"
5847           GST_PTR_FORMAT, event);
5848       gst_pad_push_event (stream->pad, event);
5849     }
5850
5851     if (info->crypto_info == NULL) {
5852       GST_DEBUG_OBJECT (qtdemux,
5853           "cenc metadata hasn't been parsed yet, pushing buffer as if it wasn't encrypted");
5854     } else {
5855       /* The end of the crypto_info array matches our n_samples position,
5856        * so count backward from there */
5857       index = stream->sample_index - stream->n_samples + info->crypto_info->len;
5858       if (G_LIKELY (index >= 0 && index < info->crypto_info->len)) {
5859         /* steal structure from array */
5860         crypto_info = g_ptr_array_index (info->crypto_info, index);
5861         g_ptr_array_index (info->crypto_info, index) = NULL;
5862         GST_LOG_OBJECT (qtdemux, "attaching cenc metadata [%u/%u]", index,
5863             info->crypto_info->len);
5864         if (!crypto_info || !gst_buffer_add_protection_meta (buf, crypto_info))
5865           GST_ERROR_OBJECT (qtdemux,
5866               "failed to attach cenc metadata to buffer");
5867       } else {
5868         GST_INFO_OBJECT (qtdemux, "No crypto info with index %d and sample %d",
5869             index, stream->sample_index);
5870       }
5871     }
5872   }
5873
5874   if (stream->alignment > 1)
5875     buf = gst_qtdemux_align_buffer (qtdemux, buf, stream->alignment);
5876
5877   ret = gst_pad_push (stream->pad, buf);
5878
5879   if (GST_CLOCK_TIME_IS_VALID (pts) && GST_CLOCK_TIME_IS_VALID (duration)) {
5880     /* mark position in stream, we'll need this to know when to send GAP event */
5881     stream->segment.position = pts + duration;
5882   }
5883
5884 exit:
5885   return ret;
5886 }
5887
5888 static const QtDemuxRandomAccessEntry *
5889 gst_qtdemux_stream_seek_fragment (GstQTDemux * qtdemux, QtDemuxStream * stream,
5890     GstClockTime pos, gboolean after)
5891 {
5892   QtDemuxRandomAccessEntry *entries = stream->ra_entries;
5893   guint n_entries = stream->n_ra_entries;
5894   guint i;
5895
5896   /* we assume the table is sorted */
5897   for (i = 0; i < n_entries; ++i) {
5898     if (entries[i].ts > pos)
5899       break;
5900   }
5901
5902   /* FIXME: maybe save first moof_offset somewhere instead, but for now it's
5903    * probably okay to assume that the index lists the very first fragment */
5904   if (i == 0)
5905     return &entries[0];
5906
5907   if (after)
5908     return &entries[i];
5909   else
5910     return &entries[i - 1];
5911 }
5912
5913 static gboolean
5914 gst_qtdemux_do_fragmented_seek (GstQTDemux * qtdemux)
5915 {
5916   const QtDemuxRandomAccessEntry *best_entry = NULL;
5917   GList *iter;
5918
5919   GST_OBJECT_LOCK (qtdemux);
5920
5921   g_assert (qtdemux->n_streams > 0);
5922
5923   /* first see if we can determine where to go to using mfra,
5924    * before we start clearing things */
5925   for (iter = qtdemux->active_streams; iter; iter = g_list_next (iter)) {
5926     const QtDemuxRandomAccessEntry *entry;
5927     QtDemuxStream *stream;
5928     gboolean is_audio_or_video;
5929
5930     stream = QTDEMUX_STREAM (iter->data);
5931
5932     if (stream->ra_entries == NULL)
5933       continue;
5934
5935     if (stream->subtype == FOURCC_vide || stream->subtype == FOURCC_soun)
5936       is_audio_or_video = TRUE;
5937     else
5938       is_audio_or_video = FALSE;
5939
5940     entry =
5941         gst_qtdemux_stream_seek_fragment (qtdemux, stream,
5942         stream->time_position, !is_audio_or_video);
5943
5944     GST_INFO_OBJECT (stream->pad, "%" GST_TIME_FORMAT " at offset "
5945         "%" G_GUINT64_FORMAT, GST_TIME_ARGS (entry->ts), entry->moof_offset);
5946
5947     stream->pending_seek = entry;
5948
5949     /* decide position to jump to just based on audio/video tracks, not subs */
5950     if (!is_audio_or_video)
5951       continue;
5952
5953     if (best_entry == NULL || entry->moof_offset < best_entry->moof_offset)
5954       best_entry = entry;
5955   }
5956
5957   /* no luck, will handle seek otherwise */
5958   if (best_entry == NULL) {
5959     GST_OBJECT_UNLOCK (qtdemux);
5960     return FALSE;
5961   }
5962
5963   /* ok, now we can prepare for processing as of located moof */
5964   for (iter = qtdemux->active_streams; iter; iter = g_list_next (iter)) {
5965     QtDemuxStream *stream;
5966
5967     stream = QTDEMUX_STREAM (iter->data);
5968
5969     g_free (stream->samples);
5970     stream->samples = NULL;
5971     stream->n_samples = 0;
5972     stream->stbl_index = -1;    /* no samples have yet been parsed */
5973     stream->sample_index = -1;
5974
5975     if (stream->protection_scheme_info) {
5976       /* Clear out any old cenc crypto info entries as we'll move to a new moof */
5977       if (stream->protection_scheme_type == FOURCC_cenc) {
5978         QtDemuxCencSampleSetInfo *info =
5979             (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
5980         if (info->crypto_info) {
5981           g_ptr_array_free (info->crypto_info, TRUE);
5982           info->crypto_info = NULL;
5983         }
5984       }
5985     }
5986   }
5987
5988   GST_INFO_OBJECT (qtdemux, "seek to %" GST_TIME_FORMAT ", best fragment "
5989       "moof offset: %" G_GUINT64_FORMAT ", ts %" GST_TIME_FORMAT,
5990       GST_TIME_ARGS (QTDEMUX_FIRST_STREAM (qtdemux)->time_position),
5991       best_entry->moof_offset, GST_TIME_ARGS (best_entry->ts));
5992
5993   qtdemux->moof_offset = best_entry->moof_offset;
5994
5995   qtdemux_add_fragmented_samples (qtdemux);
5996
5997   GST_OBJECT_UNLOCK (qtdemux);
5998   return TRUE;
5999 }
6000
6001 static GstFlowReturn
6002 gst_qtdemux_loop_state_movie (GstQTDemux * qtdemux)
6003 {
6004   GstFlowReturn ret = GST_FLOW_OK;
6005   GstBuffer *buf = NULL;
6006   QtDemuxStream *stream, *target_stream = NULL;
6007   GstClockTime min_time;
6008   guint64 offset = 0;
6009   GstClockTime dts = GST_CLOCK_TIME_NONE;
6010   GstClockTime pts = GST_CLOCK_TIME_NONE;
6011   GstClockTime duration = 0;
6012   gboolean keyframe = FALSE;
6013   guint sample_size = 0;
6014   gboolean empty = 0;
6015   guint size;
6016   GList *iter;
6017
6018   gst_qtdemux_push_pending_newsegment (qtdemux);
6019
6020   if (qtdemux->fragmented_seek_pending) {
6021     GST_INFO_OBJECT (qtdemux, "pending fragmented seek");
6022     if (gst_qtdemux_do_fragmented_seek (qtdemux)) {
6023       GST_INFO_OBJECT (qtdemux, "fragmented seek done!");
6024       qtdemux->fragmented_seek_pending = FALSE;
6025     } else {
6026       GST_INFO_OBJECT (qtdemux, "fragmented seek still pending");
6027     }
6028   }
6029
6030   /* Figure out the next stream sample to output, min_time is expressed in
6031    * global time and runs over the edit list segments. */
6032   min_time = G_MAXUINT64;
6033   for (iter = qtdemux->active_streams; iter; iter = g_list_next (iter)) {
6034     GstClockTime position;
6035
6036     stream = QTDEMUX_STREAM (iter->data);
6037     position = stream->time_position;
6038
6039     /* position of -1 is EOS */
6040     if (position != GST_CLOCK_TIME_NONE && position < min_time) {
6041       min_time = position;
6042       target_stream = stream;
6043     }
6044   }
6045   /* all are EOS */
6046   if (G_UNLIKELY (target_stream == NULL)) {
6047     GST_DEBUG_OBJECT (qtdemux, "all streams are EOS");
6048     goto eos;
6049   }
6050
6051   /* check for segment end */
6052   if (G_UNLIKELY (qtdemux->segment.stop != -1
6053           && ((qtdemux->segment.rate >= 0 && qtdemux->segment.stop <= min_time)
6054               || (qtdemux->segment.rate < 0
6055                   && qtdemux->segment.start > min_time))
6056           && target_stream->on_keyframe)) {
6057     GST_DEBUG_OBJECT (qtdemux, "we reached the end of our segment.");
6058     target_stream->time_position = GST_CLOCK_TIME_NONE;
6059     goto eos_stream;
6060   }
6061
6062   /* gap events for subtitle streams */
6063   for (iter = qtdemux->active_streams; iter; iter = g_list_next (iter)) {
6064     stream = QTDEMUX_STREAM (iter->data);
6065     if (stream->pad && (stream->subtype == FOURCC_subp
6066             || stream->subtype == FOURCC_text
6067             || stream->subtype == FOURCC_sbtl)) {
6068       /* send one second gap events until the stream catches up */
6069       /* gaps can only be sent after segment is activated (segment.stop is no longer -1) */
6070       while (GST_CLOCK_TIME_IS_VALID (stream->segment.stop) &&
6071           GST_CLOCK_TIME_IS_VALID (stream->segment.position) &&
6072           stream->segment.position + GST_SECOND < min_time) {
6073         GstEvent *gap =
6074             gst_event_new_gap (stream->segment.position, GST_SECOND);
6075         gst_pad_push_event (stream->pad, gap);
6076         stream->segment.position += GST_SECOND;
6077       }
6078     }
6079   }
6080
6081   stream = target_stream;
6082   /* fetch info for the current sample of this stream */
6083   if (G_UNLIKELY (!gst_qtdemux_prepare_current_sample (qtdemux, stream, &empty,
6084               &offset, &sample_size, &dts, &pts, &duration, &keyframe)))
6085     goto eos_stream;
6086
6087   gst_qtdemux_stream_check_and_change_stsd_index (qtdemux, stream);
6088   if (stream->new_caps) {
6089     gst_qtdemux_configure_stream (qtdemux, stream);
6090     qtdemux_do_allocation (qtdemux, stream);
6091   }
6092
6093   /* If we're doing a keyframe-only trickmode, only push keyframes on video streams */
6094   if (G_UNLIKELY (qtdemux->
6095           segment.flags & GST_SEGMENT_FLAG_TRICKMODE_KEY_UNITS)) {
6096     if (stream->subtype == FOURCC_vide && !keyframe) {
6097       GST_LOG_OBJECT (qtdemux, "Skipping non-keyframe on track-id %u",
6098           stream->track_id);
6099       goto next;
6100     }
6101   }
6102
6103   GST_DEBUG_OBJECT (qtdemux,
6104       "pushing from track-id %u, empty %d offset %" G_GUINT64_FORMAT
6105       ", size %d, dts=%" GST_TIME_FORMAT ", pts=%" GST_TIME_FORMAT
6106       ", duration %" GST_TIME_FORMAT, stream->track_id, empty, offset,
6107       sample_size, GST_TIME_ARGS (dts), GST_TIME_ARGS (pts),
6108       GST_TIME_ARGS (duration));
6109
6110   if (G_UNLIKELY (empty)) {
6111     /* empty segment, push a gap if there's a second or more
6112      * difference and move to the next one */
6113     if ((pts + duration - stream->segment.position) >= GST_SECOND)
6114       gst_pad_push_event (stream->pad, gst_event_new_gap (pts, duration));
6115     stream->segment.position = pts + duration;
6116     goto next;
6117   }
6118
6119   /* hmm, empty sample, skip and move to next sample */
6120   if (G_UNLIKELY (sample_size <= 0))
6121     goto next;
6122
6123   /* last pushed sample was out of boundary, goto next sample */
6124   if (G_UNLIKELY (GST_PAD_LAST_FLOW_RETURN (stream->pad) == GST_FLOW_EOS))
6125     goto next;
6126
6127   if (stream->max_buffer_size == 0 || sample_size <= stream->max_buffer_size) {
6128     size = sample_size;
6129   } else {
6130     GST_DEBUG_OBJECT (qtdemux,
6131         "size %d larger than stream max_buffer_size %d, trimming",
6132         sample_size, stream->max_buffer_size);
6133     size =
6134         MIN (sample_size - stream->offset_in_sample, stream->max_buffer_size);
6135   }
6136
6137   if (qtdemux->cenc_aux_info_offset > 0) {
6138     GstMapInfo map;
6139     GstByteReader br;
6140     GstBuffer *aux_info = NULL;
6141
6142     /* pull the data stored before the sample */
6143     ret =
6144         gst_qtdemux_pull_atom (qtdemux, qtdemux->offset,
6145         offset + stream->offset_in_sample - qtdemux->offset, &aux_info);
6146     if (G_UNLIKELY (ret != GST_FLOW_OK))
6147       goto beach;
6148     gst_buffer_map (aux_info, &map, GST_MAP_READ);
6149     GST_DEBUG_OBJECT (qtdemux, "parsing cenc auxiliary info");
6150     gst_byte_reader_init (&br, map.data + 8, map.size);
6151     if (!qtdemux_parse_cenc_aux_info (qtdemux, stream, &br,
6152             qtdemux->cenc_aux_info_sizes, qtdemux->cenc_aux_sample_count)) {
6153       GST_ERROR_OBJECT (qtdemux, "failed to parse cenc auxiliary info");
6154       gst_buffer_unmap (aux_info, &map);
6155       gst_buffer_unref (aux_info);
6156       ret = GST_FLOW_ERROR;
6157       goto beach;
6158     }
6159     gst_buffer_unmap (aux_info, &map);
6160     gst_buffer_unref (aux_info);
6161   }
6162
6163   GST_LOG_OBJECT (qtdemux, "reading %d bytes @ %" G_GUINT64_FORMAT, size,
6164       offset);
6165
6166   if (stream->use_allocator) {
6167     /* if we have a per-stream allocator, use it */
6168     buf = gst_buffer_new_allocate (stream->allocator, size, &stream->params);
6169   }
6170
6171   ret = gst_qtdemux_pull_atom (qtdemux, offset + stream->offset_in_sample,
6172       size, &buf);
6173   if (G_UNLIKELY (ret != GST_FLOW_OK))
6174     goto beach;
6175
6176   if (size != sample_size) {
6177     pts += gst_util_uint64_scale_int (GST_SECOND,
6178         stream->offset_in_sample / CUR_STREAM (stream)->bytes_per_frame,
6179         stream->timescale);
6180     dts +=
6181         gst_util_uint64_scale_int (GST_SECOND,
6182         stream->offset_in_sample / CUR_STREAM (stream)->bytes_per_frame,
6183         stream->timescale);
6184     duration =
6185         gst_util_uint64_scale_int (GST_SECOND,
6186         size / CUR_STREAM (stream)->bytes_per_frame, stream->timescale);
6187   }
6188
6189   ret = gst_qtdemux_decorate_and_push_buffer (qtdemux, stream, buf,
6190       dts, pts, duration, keyframe, min_time, offset);
6191
6192   if (size != sample_size) {
6193     QtDemuxSample *sample = &stream->samples[stream->sample_index];
6194     QtDemuxSegment *segment = &stream->segments[stream->segment_index];
6195
6196     GstClockTime time_position = QTSTREAMTIME_TO_GSTTIME (stream,
6197         sample->timestamp +
6198         stream->offset_in_sample / CUR_STREAM (stream)->bytes_per_frame);
6199     if (time_position >= segment->media_start) {
6200       /* inside the segment, update time_position, looks very familiar to
6201        * GStreamer segments, doesn't it? */
6202       stream->time_position = (time_position - segment->media_start) +
6203           segment->time;
6204     } else {
6205       /* not yet in segment, time does not yet increment. This means
6206        * that we are still prerolling keyframes to the decoder so it can
6207        * decode the first sample of the segment. */
6208       stream->time_position = segment->time;
6209     }
6210   }
6211
6212   /* combine flows */
6213   ret = gst_qtdemux_combine_flows (qtdemux, stream, ret);
6214   /* ignore unlinked, we will not push on the pad anymore and we will EOS when
6215    * we have no more data for the pad to push */
6216   if (ret == GST_FLOW_EOS)
6217     ret = GST_FLOW_OK;
6218
6219   stream->offset_in_sample += size;
6220   if (stream->offset_in_sample >= sample_size) {
6221     gst_qtdemux_advance_sample (qtdemux, stream);
6222   }
6223   goto beach;
6224
6225 next:
6226   gst_qtdemux_advance_sample (qtdemux, stream);
6227
6228 beach:
6229   return ret;
6230
6231   /* special cases */
6232 eos:
6233   {
6234     GST_DEBUG_OBJECT (qtdemux, "No samples left for any streams - EOS");
6235     ret = GST_FLOW_EOS;
6236     goto beach;
6237   }
6238 eos_stream:
6239   {
6240     GST_DEBUG_OBJECT (qtdemux, "No samples left for stream");
6241     /* EOS will be raised if all are EOS */
6242     ret = GST_FLOW_OK;
6243     goto beach;
6244   }
6245 }
6246
6247 static void
6248 gst_qtdemux_loop (GstPad * pad)
6249 {
6250   GstQTDemux *qtdemux;
6251   guint64 cur_offset;
6252   GstFlowReturn ret;
6253
6254   qtdemux = GST_QTDEMUX (gst_pad_get_parent (pad));
6255
6256   cur_offset = qtdemux->offset;
6257   GST_LOG_OBJECT (qtdemux, "loop at position %" G_GUINT64_FORMAT ", state %s",
6258       cur_offset, qt_demux_state_string (qtdemux->state));
6259
6260   switch (qtdemux->state) {
6261     case QTDEMUX_STATE_INITIAL:
6262     case QTDEMUX_STATE_HEADER:
6263       ret = gst_qtdemux_loop_state_header (qtdemux);
6264       break;
6265     case QTDEMUX_STATE_MOVIE:
6266       ret = gst_qtdemux_loop_state_movie (qtdemux);
6267       if (qtdemux->segment.rate < 0 && ret == GST_FLOW_EOS) {
6268         ret = gst_qtdemux_seek_to_previous_keyframe (qtdemux);
6269       }
6270       break;
6271     default:
6272       /* ouch */
6273       goto invalid_state;
6274   }
6275
6276   /* if something went wrong, pause */
6277   if (ret != GST_FLOW_OK)
6278     goto pause;
6279
6280 done:
6281   gst_object_unref (qtdemux);
6282   return;
6283
6284   /* ERRORS */
6285 invalid_state:
6286   {
6287     GST_ELEMENT_ERROR (qtdemux, STREAM, FAILED,
6288         (NULL), ("streaming stopped, invalid state"));
6289     gst_pad_pause_task (pad);
6290     gst_qtdemux_push_event (qtdemux, gst_event_new_eos ());
6291     goto done;
6292   }
6293 pause:
6294   {
6295     const gchar *reason = gst_flow_get_name (ret);
6296
6297     GST_LOG_OBJECT (qtdemux, "pausing task, reason %s", reason);
6298
6299     gst_pad_pause_task (pad);
6300
6301     /* fatal errors need special actions */
6302     /* check EOS */
6303     if (ret == GST_FLOW_EOS) {
6304       if (qtdemux->n_streams == 0) {
6305         /* we have no streams, post an error */
6306         gst_qtdemux_post_no_playable_stream_error (qtdemux);
6307       }
6308       if (qtdemux->segment.flags & GST_SEEK_FLAG_SEGMENT) {
6309         gint64 stop;
6310
6311         if ((stop = qtdemux->segment.stop) == -1)
6312           stop = qtdemux->segment.duration;
6313
6314         if (qtdemux->segment.rate >= 0) {
6315           GstMessage *message;
6316           GstEvent *event;
6317
6318           GST_LOG_OBJECT (qtdemux, "Sending segment done, at end of segment");
6319           message = gst_message_new_segment_done (GST_OBJECT_CAST (qtdemux),
6320               GST_FORMAT_TIME, stop);
6321           event = gst_event_new_segment_done (GST_FORMAT_TIME, stop);
6322           if (qtdemux->segment_seqnum != GST_SEQNUM_INVALID) {
6323             gst_message_set_seqnum (message, qtdemux->segment_seqnum);
6324             gst_event_set_seqnum (event, qtdemux->segment_seqnum);
6325           }
6326           gst_element_post_message (GST_ELEMENT_CAST (qtdemux), message);
6327           gst_qtdemux_push_event (qtdemux, event);
6328         } else {
6329           GstMessage *message;
6330           GstEvent *event;
6331
6332           /*  For Reverse Playback */
6333           GST_LOG_OBJECT (qtdemux, "Sending segment done, at start of segment");
6334           message = gst_message_new_segment_done (GST_OBJECT_CAST (qtdemux),
6335               GST_FORMAT_TIME, qtdemux->segment.start);
6336           event = gst_event_new_segment_done (GST_FORMAT_TIME,
6337               qtdemux->segment.start);
6338           if (qtdemux->segment_seqnum != GST_SEQNUM_INVALID) {
6339             gst_message_set_seqnum (message, qtdemux->segment_seqnum);
6340             gst_event_set_seqnum (event, qtdemux->segment_seqnum);
6341           }
6342           gst_element_post_message (GST_ELEMENT_CAST (qtdemux), message);
6343           gst_qtdemux_push_event (qtdemux, event);
6344         }
6345       } else {
6346         GstEvent *event;
6347
6348         GST_LOG_OBJECT (qtdemux, "Sending EOS at end of segment");
6349         event = gst_event_new_eos ();
6350         if (qtdemux->segment_seqnum != GST_SEQNUM_INVALID)
6351           gst_event_set_seqnum (event, qtdemux->segment_seqnum);
6352         gst_qtdemux_push_event (qtdemux, event);
6353       }
6354     } else if (ret == GST_FLOW_NOT_LINKED || ret < GST_FLOW_EOS) {
6355       GST_ELEMENT_FLOW_ERROR (qtdemux, ret);
6356       gst_qtdemux_push_event (qtdemux, gst_event_new_eos ());
6357     }
6358     goto done;
6359   }
6360 }
6361
6362 /*
6363  * has_next_entry
6364  *
6365  * Returns if there are samples to be played.
6366  */
6367 static gboolean
6368 has_next_entry (GstQTDemux * demux)
6369 {
6370   QtDemuxStream *stream;
6371   GList *iter;
6372
6373   GST_DEBUG_OBJECT (demux, "Checking if there are samples not played yet");
6374
6375   for (iter = demux->active_streams; iter; iter = g_list_next (iter)) {
6376     stream = QTDEMUX_STREAM (iter->data);
6377
6378     if (stream->sample_index == -1) {
6379       stream->sample_index = 0;
6380       stream->offset_in_sample = 0;
6381     }
6382
6383     if (stream->sample_index >= stream->n_samples) {
6384       GST_LOG_OBJECT (demux, "track-id %u samples exhausted", stream->track_id);
6385       continue;
6386     }
6387     GST_DEBUG_OBJECT (demux, "Found a sample");
6388     return TRUE;
6389   }
6390
6391   GST_DEBUG_OBJECT (demux, "There wasn't any next sample");
6392   return FALSE;
6393 }
6394
6395 /*
6396  * next_entry_size
6397  *
6398  * Returns the size of the first entry at the current offset.
6399  * If -1, there are none (which means EOS or empty file).
6400  */
6401 static guint64
6402 next_entry_size (GstQTDemux * demux)
6403 {
6404   QtDemuxStream *stream, *target_stream = NULL;
6405   guint64 smalloffs = (guint64) - 1;
6406   QtDemuxSample *sample;
6407   GList *iter;
6408
6409   GST_LOG_OBJECT (demux, "Finding entry at offset %" G_GUINT64_FORMAT,
6410       demux->offset);
6411
6412   for (iter = demux->active_streams; iter; iter = g_list_next (iter)) {
6413     stream = QTDEMUX_STREAM (iter->data);
6414
6415     if (stream->sample_index == -1) {
6416       stream->sample_index = 0;
6417       stream->offset_in_sample = 0;
6418     }
6419
6420     if (stream->sample_index >= stream->n_samples) {
6421       GST_LOG_OBJECT (demux, "track-id %u samples exhausted", stream->track_id);
6422       continue;
6423     }
6424
6425     if (!qtdemux_parse_samples (demux, stream, stream->sample_index)) {
6426       GST_LOG_OBJECT (demux, "Parsing of index %u from stbl atom failed!",
6427           stream->sample_index);
6428       return -1;
6429     }
6430
6431     sample = &stream->samples[stream->sample_index];
6432
6433     GST_LOG_OBJECT (demux,
6434         "Checking track-id %u (sample_index:%d / offset:%" G_GUINT64_FORMAT
6435         " / size:%" G_GUINT32_FORMAT ")", stream->track_id,
6436         stream->sample_index, sample->offset, sample->size);
6437
6438     if (((smalloffs == -1)
6439             || (sample->offset < smalloffs)) && (sample->size)) {
6440       smalloffs = sample->offset;
6441       target_stream = stream;
6442     }
6443   }
6444
6445   if (!target_stream)
6446     return -1;
6447
6448   GST_LOG_OBJECT (demux,
6449       "track-id %u offset %" G_GUINT64_FORMAT " demux->offset :%"
6450       G_GUINT64_FORMAT, target_stream->track_id, smalloffs, demux->offset);
6451
6452   stream = target_stream;
6453   sample = &stream->samples[stream->sample_index];
6454
6455   if (sample->offset >= demux->offset) {
6456     demux->todrop = sample->offset - demux->offset;
6457     return sample->size + demux->todrop;
6458   }
6459
6460   GST_DEBUG_OBJECT (demux,
6461       "There wasn't any entry at offset %" G_GUINT64_FORMAT, demux->offset);
6462   return -1;
6463 }
6464
6465 static void
6466 gst_qtdemux_post_progress (GstQTDemux * demux, gint num, gint denom)
6467 {
6468   gint perc = (gint) ((gdouble) num * 100.0 / (gdouble) denom);
6469
6470   gst_element_post_message (GST_ELEMENT_CAST (demux),
6471       gst_message_new_element (GST_OBJECT_CAST (demux),
6472           gst_structure_new ("progress", "percent", G_TYPE_INT, perc, NULL)));
6473 }
6474
6475 static gboolean
6476 qtdemux_seek_offset (GstQTDemux * demux, guint64 offset)
6477 {
6478   GstEvent *event;
6479   gboolean res = 0;
6480
6481   GST_DEBUG_OBJECT (demux, "Seeking to %" G_GUINT64_FORMAT, offset);
6482
6483   event =
6484       gst_event_new_seek (1.0, GST_FORMAT_BYTES,
6485       GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_ACCURATE, GST_SEEK_TYPE_SET, offset,
6486       GST_SEEK_TYPE_NONE, -1);
6487
6488   /* store seqnum to drop flush events, they don't need to reach downstream */
6489   demux->offset_seek_seqnum = gst_event_get_seqnum (event);
6490   res = gst_pad_push_event (demux->sinkpad, event);
6491   demux->offset_seek_seqnum = GST_SEQNUM_INVALID;
6492
6493   return res;
6494 }
6495
6496 /* check for seekable upstream, above and beyond a mere query */
6497 static void
6498 gst_qtdemux_check_seekability (GstQTDemux * demux)
6499 {
6500   GstQuery *query;
6501   gboolean seekable = FALSE;
6502   gint64 start = -1, stop = -1;
6503
6504   if (demux->upstream_size)
6505     return;
6506
6507   if (demux->upstream_format_is_time)
6508     return;
6509
6510   query = gst_query_new_seeking (GST_FORMAT_BYTES);
6511   if (!gst_pad_peer_query (demux->sinkpad, query)) {
6512     GST_DEBUG_OBJECT (demux, "seeking query failed");
6513     goto done;
6514   }
6515
6516   gst_query_parse_seeking (query, NULL, &seekable, &start, &stop);
6517
6518   /* try harder to query upstream size if we didn't get it the first time */
6519   if (seekable && stop == -1) {
6520     GST_DEBUG_OBJECT (demux, "doing duration query to fix up unset stop");
6521     gst_pad_peer_query_duration (demux->sinkpad, GST_FORMAT_BYTES, &stop);
6522   }
6523
6524   /* if upstream doesn't know the size, it's likely that it's not seekable in
6525    * practice even if it technically may be seekable */
6526   if (seekable && (start != 0 || stop <= start)) {
6527     GST_DEBUG_OBJECT (demux, "seekable but unknown start/stop -> disable");
6528     seekable = FALSE;
6529   }
6530
6531 done:
6532   gst_query_unref (query);
6533
6534   GST_DEBUG_OBJECT (demux, "seekable: %d (%" G_GUINT64_FORMAT " - %"
6535       G_GUINT64_FORMAT ")", seekable, start, stop);
6536   demux->upstream_seekable = seekable;
6537   demux->upstream_size = seekable ? stop : -1;
6538 }
6539
6540 static void
6541 gst_qtdemux_drop_data (GstQTDemux * demux, gint bytes)
6542 {
6543   g_return_if_fail (bytes <= demux->todrop);
6544
6545   GST_LOG_OBJECT (demux, "Dropping %d bytes", bytes);
6546   gst_adapter_flush (demux->adapter, bytes);
6547   demux->neededbytes -= bytes;
6548   demux->offset += bytes;
6549   demux->todrop -= bytes;
6550 }
6551
6552 static void
6553 gst_qtdemux_check_send_pending_segment (GstQTDemux * demux)
6554 {
6555   if (G_UNLIKELY (demux->need_segment)) {
6556     gint i;
6557     GList *iter;
6558
6559     gst_qtdemux_push_pending_newsegment (demux);
6560     /* clear to send tags on all streams */
6561     for (iter = demux->active_streams, i = 0; iter;
6562         iter = g_list_next (iter), i++) {
6563       QtDemuxStream *stream = QTDEMUX_STREAM (iter->data);
6564       gst_qtdemux_push_tags (demux, stream);
6565       if (CUR_STREAM (stream)->sparse) {
6566         GST_INFO_OBJECT (demux, "Sending gap event on stream %d", i);
6567         gst_pad_push_event (stream->pad,
6568             gst_event_new_gap (stream->segment.position, GST_CLOCK_TIME_NONE));
6569       }
6570     }
6571   }
6572 }
6573
6574 /* Used for push mode only. */
6575 static void
6576 gst_qtdemux_send_gap_for_segment (GstQTDemux * demux,
6577     QtDemuxStream * stream, gint segment_index, GstClockTime pos)
6578 {
6579   GstClockTime ts, dur;
6580
6581   ts = pos;
6582   dur =
6583       stream->segments[segment_index].duration - (pos -
6584       stream->segments[segment_index].time);
6585   stream->time_position += dur;
6586
6587   /* Only gaps with a duration of at least one second are propagated.
6588    * Same workaround as in pull mode.
6589    * (See 2e45926a96ec5298c6ef29bf912e5e6a06dc3e0e) */
6590   if (dur >= GST_SECOND) {
6591     GstEvent *gap;
6592     gap = gst_event_new_gap (ts, dur);
6593
6594     GST_DEBUG_OBJECT (stream->pad, "Pushing gap for empty "
6595         "segment: %" GST_PTR_FORMAT, gap);
6596     gst_pad_push_event (stream->pad, gap);
6597   }
6598 }
6599
6600 static GstClockTime
6601 gst_qtdemux_streams_get_first_sample_ts (GstQTDemux * demux)
6602 {
6603   GstClockTime res = GST_CLOCK_TIME_NONE;
6604   GList *iter;
6605
6606   for (iter = demux->active_streams; iter; iter = g_list_next (iter)) {
6607     QtDemuxStream *stream = QTDEMUX_STREAM (iter->data);
6608     if (stream->n_samples) {
6609       res = MIN (QTSAMPLE_PTS (stream, &stream->samples[0]), res);
6610       res = MIN (QTSAMPLE_DTS (stream, &stream->samples[0]), res);
6611     }
6612   }
6613   return res;
6614 }
6615
6616 static GstClockTime
6617 gst_qtdemux_streams_have_samples (GstQTDemux * demux)
6618 {
6619   GList *iter;
6620
6621   for (iter = demux->active_streams; iter; iter = g_list_next (iter)) {
6622     QtDemuxStream *stream = QTDEMUX_STREAM (iter->data);
6623     if (stream->n_samples)
6624       return TRUE;
6625   }
6626   return FALSE;
6627 }
6628
6629 static GstFlowReturn
6630 gst_qtdemux_chain (GstPad * sinkpad, GstObject * parent, GstBuffer * inbuf)
6631 {
6632   GstQTDemux *demux;
6633
6634   demux = GST_QTDEMUX (parent);
6635
6636   GST_DEBUG_OBJECT (demux,
6637       "Received buffer pts:%" GST_TIME_FORMAT " dts:%" GST_TIME_FORMAT
6638       " offset:%" G_GUINT64_FORMAT " size:%" G_GSIZE_FORMAT " demux offset:%"
6639       G_GUINT64_FORMAT, GST_TIME_ARGS (GST_BUFFER_PTS (inbuf)),
6640       GST_TIME_ARGS (GST_BUFFER_DTS (inbuf)), GST_BUFFER_OFFSET (inbuf),
6641       gst_buffer_get_size (inbuf), demux->offset);
6642
6643   if (GST_BUFFER_FLAG_IS_SET (inbuf, GST_BUFFER_FLAG_DISCONT)) {
6644     gboolean is_gap_input = FALSE;
6645     GList *iter;
6646
6647     GST_DEBUG_OBJECT (demux, "Got DISCONT, marking all streams as DISCONT");
6648
6649     for (iter = demux->active_streams; iter; iter = g_list_next (iter)) {
6650       QTDEMUX_STREAM (iter->data)->discont = TRUE;
6651     }
6652
6653     /* Check if we can land back on our feet in the case where upstream is
6654      * handling the seeking/pushing of samples with gaps in between (like
6655      * in the case of trick-mode DASH for example) */
6656     if (demux->upstream_format_is_time
6657         && GST_BUFFER_OFFSET (inbuf) != GST_BUFFER_OFFSET_NONE) {
6658       for (iter = demux->active_streams; iter; iter = g_list_next (iter)) {
6659         guint32 res;
6660         QtDemuxStream *stream = QTDEMUX_STREAM (iter->data);
6661         GST_LOG_OBJECT (demux,
6662             "track-id #%u , checking if offset %" G_GUINT64_FORMAT
6663             " is a sample start", stream->track_id, GST_BUFFER_OFFSET (inbuf));
6664         res =
6665             gst_qtdemux_find_index_for_given_media_offset_linear (demux,
6666             stream, GST_BUFFER_OFFSET (inbuf));
6667         if (res != -1) {
6668           QtDemuxSample *sample = &stream->samples[res];
6669           GST_LOG_OBJECT (demux,
6670               "Checking if sample %d from track-id %u is valid (offset:%"
6671               G_GUINT64_FORMAT " size:%" G_GUINT32_FORMAT ")", res,
6672               stream->track_id, sample->offset, sample->size);
6673           if (sample->offset == GST_BUFFER_OFFSET (inbuf)) {
6674             GST_LOG_OBJECT (demux,
6675                 "new buffer corresponds to a valid sample : %" G_GUINT32_FORMAT,
6676                 res);
6677             is_gap_input = TRUE;
6678             /* We can go back to standard playback mode */
6679             demux->state = QTDEMUX_STATE_MOVIE;
6680             /* Remember which sample this stream is at */
6681             stream->sample_index = res;
6682             /* Finally update all push-based values to the expected values */
6683             demux->neededbytes = stream->samples[res].size;
6684             demux->offset = GST_BUFFER_OFFSET (inbuf);
6685             demux->mdatleft =
6686                 demux->mdatsize - demux->offset + demux->mdatoffset;
6687             demux->todrop = 0;
6688           }
6689         }
6690       }
6691       if (!is_gap_input) {
6692         GST_DEBUG_OBJECT (demux, "Resetting, actual DISCONT");
6693         /* Reset state if it's a real discont */
6694         demux->neededbytes = 16;
6695         demux->state = QTDEMUX_STATE_INITIAL;
6696         demux->offset = GST_BUFFER_OFFSET (inbuf);
6697         gst_adapter_clear (demux->adapter);
6698       }
6699     }
6700     /* Reverse fragmented playback, need to flush all we have before
6701      * consuming a new fragment.
6702      * The samples array have the timestamps calculated by accumulating the
6703      * durations but this won't work for reverse playback of fragments as
6704      * the timestamps of a subsequent fragment should be smaller than the
6705      * previously received one. */
6706     if (!is_gap_input && demux->fragmented && demux->segment.rate < 0) {
6707       gst_qtdemux_process_adapter (demux, TRUE);
6708       g_list_foreach (demux->active_streams,
6709           (GFunc) gst_qtdemux_stream_flush_samples_data, NULL);
6710     }
6711   }
6712
6713   gst_adapter_push (demux->adapter, inbuf);
6714
6715   GST_DEBUG_OBJECT (demux,
6716       "pushing in inbuf %p, neededbytes:%u, available:%" G_GSIZE_FORMAT, inbuf,
6717       demux->neededbytes, gst_adapter_available (demux->adapter));
6718
6719   return gst_qtdemux_process_adapter (demux, FALSE);
6720 }
6721
6722 static GstFlowReturn
6723 gst_qtdemux_process_adapter (GstQTDemux * demux, gboolean force)
6724 {
6725   GstFlowReturn ret = GST_FLOW_OK;
6726
6727   /* we never really mean to buffer that much */
6728   if (demux->neededbytes == -1) {
6729     goto eos;
6730   }
6731
6732   while (((gst_adapter_available (demux->adapter)) >= demux->neededbytes) &&
6733       (ret == GST_FLOW_OK || (ret == GST_FLOW_NOT_LINKED && force))) {
6734
6735 #ifndef GST_DISABLE_GST_DEBUG
6736     {
6737       guint64 discont_offset, distance_from_discont;
6738
6739       discont_offset = gst_adapter_offset_at_discont (demux->adapter);
6740       distance_from_discont =
6741           gst_adapter_distance_from_discont (demux->adapter);
6742
6743       GST_DEBUG_OBJECT (demux,
6744           "state:%s , demux->neededbytes:%d, demux->offset:%" G_GUINT64_FORMAT
6745           " adapter offset :%" G_GUINT64_FORMAT " (+ %" G_GUINT64_FORMAT
6746           " bytes)", qt_demux_state_string (demux->state), demux->neededbytes,
6747           demux->offset, discont_offset, distance_from_discont);
6748     }
6749 #endif
6750
6751     switch (demux->state) {
6752       case QTDEMUX_STATE_INITIAL:{
6753         const guint8 *data;
6754         guint32 fourcc;
6755         guint64 size;
6756
6757         gst_qtdemux_check_seekability (demux);
6758
6759         data = gst_adapter_map (demux->adapter, demux->neededbytes);
6760
6761         /* get fourcc/length, set neededbytes */
6762         extract_initial_length_and_fourcc ((guint8 *) data, demux->neededbytes,
6763             &size, &fourcc);
6764         gst_adapter_unmap (demux->adapter);
6765         data = NULL;
6766         GST_DEBUG_OBJECT (demux, "Peeking found [%" GST_FOURCC_FORMAT "] "
6767             "size: %" G_GUINT64_FORMAT, GST_FOURCC_ARGS (fourcc), size);
6768         if (size == 0) {
6769           GST_ELEMENT_ERROR (demux, STREAM, DEMUX,
6770               (_("This file is invalid and cannot be played.")),
6771               ("initial atom '%" GST_FOURCC_FORMAT "' has empty length",
6772                   GST_FOURCC_ARGS (fourcc)));
6773           ret = GST_FLOW_ERROR;
6774           break;
6775         }
6776         if (fourcc == FOURCC_mdat) {
6777           gint next_entry = next_entry_size (demux);
6778           if (demux->n_streams > 0 && (next_entry != -1 || !demux->fragmented)) {
6779             /* we have the headers, start playback */
6780             demux->state = QTDEMUX_STATE_MOVIE;
6781             demux->neededbytes = next_entry;
6782             demux->mdatleft = size;
6783             demux->mdatsize = demux->mdatleft;
6784           } else {
6785             /* no headers yet, try to get them */
6786             guint bs;
6787             gboolean res;
6788             guint64 old, target;
6789
6790           buffer_data:
6791             old = demux->offset;
6792             target = old + size;
6793
6794             /* try to jump over the atom with a seek */
6795             /* only bother if it seems worth doing so,
6796              * and avoids possible upstream/server problems */
6797             if (demux->upstream_seekable &&
6798                 demux->upstream_size > 4 * (1 << 20)) {
6799               res = qtdemux_seek_offset (demux, target);
6800             } else {
6801               GST_DEBUG_OBJECT (demux, "skipping seek");
6802               res = FALSE;
6803             }
6804
6805             if (res) {
6806               GST_DEBUG_OBJECT (demux, "seek success");
6807               /* remember the offset fo the first mdat so we can seek back to it
6808                * after we have the headers */
6809               if (fourcc == FOURCC_mdat && demux->first_mdat == -1) {
6810                 demux->first_mdat = old;
6811                 GST_DEBUG_OBJECT (demux, "first mdat at %" G_GUINT64_FORMAT,
6812                     demux->first_mdat);
6813               }
6814               /* seek worked, continue reading */
6815               demux->offset = target;
6816               demux->neededbytes = 16;
6817               demux->state = QTDEMUX_STATE_INITIAL;
6818             } else {
6819               /* seek failed, need to buffer */
6820               demux->offset = old;
6821               GST_DEBUG_OBJECT (demux, "seek failed/skipped");
6822               /* there may be multiple mdat (or alike) buffers */
6823               /* sanity check */
6824               if (demux->mdatbuffer)
6825                 bs = gst_buffer_get_size (demux->mdatbuffer);
6826               else
6827                 bs = 0;
6828               if (size + bs > 10 * (1 << 20))
6829                 goto no_moov;
6830               demux->state = QTDEMUX_STATE_BUFFER_MDAT;
6831               demux->neededbytes = size;
6832               if (!demux->mdatbuffer)
6833                 demux->mdatoffset = demux->offset;
6834             }
6835           }
6836         } else if (G_UNLIKELY (size > QTDEMUX_MAX_ATOM_SIZE)) {
6837           GST_ELEMENT_ERROR (demux, STREAM, DEMUX,
6838               (_("This file is invalid and cannot be played.")),
6839               ("atom %" GST_FOURCC_FORMAT " has bogus size %" G_GUINT64_FORMAT,
6840                   GST_FOURCC_ARGS (fourcc), size));
6841           ret = GST_FLOW_ERROR;
6842           break;
6843         } else {
6844           /* this means we already started buffering and still no moov header,
6845            * let's continue buffering everything till we get moov */
6846           if (demux->mdatbuffer && !(fourcc == FOURCC_moov
6847                   || fourcc == FOURCC_moof))
6848             goto buffer_data;
6849           demux->neededbytes = size;
6850           demux->state = QTDEMUX_STATE_HEADER;
6851         }
6852         break;
6853       }
6854       case QTDEMUX_STATE_HEADER:{
6855         const guint8 *data;
6856         guint32 fourcc;
6857
6858         GST_DEBUG_OBJECT (demux, "In header");
6859
6860         data = gst_adapter_map (demux->adapter, demux->neededbytes);
6861
6862         /* parse the header */
6863         extract_initial_length_and_fourcc (data, demux->neededbytes, NULL,
6864             &fourcc);
6865         if (fourcc == FOURCC_moov) {
6866           /* in usual fragmented setup we could try to scan for more
6867            * and end up at the the moov (after mdat) again */
6868           if (demux->got_moov && demux->n_streams > 0 &&
6869               (!demux->fragmented
6870                   || demux->last_moov_offset == demux->offset)) {
6871             GST_DEBUG_OBJECT (demux,
6872                 "Skipping moov atom as we have (this) one already");
6873           } else {
6874             GST_DEBUG_OBJECT (demux, "Parsing [moov]");
6875
6876             if (demux->got_moov && demux->fragmented) {
6877               GST_DEBUG_OBJECT (demux,
6878                   "Got a second moov, clean up data from old one");
6879               if (demux->moov_node_compressed) {
6880                 g_node_destroy (demux->moov_node_compressed);
6881                 if (demux->moov_node)
6882                   g_free (demux->moov_node->data);
6883               }
6884               demux->moov_node_compressed = NULL;
6885               if (demux->moov_node)
6886                 g_node_destroy (demux->moov_node);
6887               demux->moov_node = NULL;
6888             }
6889
6890             demux->last_moov_offset = demux->offset;
6891
6892             /* Update streams with new moov */
6893             demux->old_streams =
6894                 g_list_concat (demux->old_streams, demux->active_streams);
6895             demux->active_streams = NULL;
6896
6897             qtdemux_parse_moov (demux, data, demux->neededbytes);
6898             qtdemux_node_dump (demux, demux->moov_node);
6899             qtdemux_parse_tree (demux);
6900             qtdemux_prepare_streams (demux);
6901             QTDEMUX_EXPOSE_LOCK (demux);
6902             qtdemux_expose_streams (demux);
6903             QTDEMUX_EXPOSE_UNLOCK (demux);
6904
6905             demux->got_moov = TRUE;
6906             demux->need_segment = TRUE;
6907
6908             /* Forward upstream driven time format segment, and also do not try
6909              * to map edit list with the upstream time format segment.
6910              * It's upstream element's role (the origin of time format segment)
6911              */
6912             if (demux->upstream_format_is_time)
6913               gst_qtdemux_check_send_pending_segment (demux);
6914             else
6915               gst_qtdemux_map_and_push_segments (demux, &demux->segment);
6916
6917             if (demux->exposed)
6918               demux->need_segment = FALSE;
6919
6920             if (demux->moov_node_compressed) {
6921               g_node_destroy (demux->moov_node_compressed);
6922               g_free (demux->moov_node->data);
6923             }
6924             demux->moov_node_compressed = NULL;
6925             g_node_destroy (demux->moov_node);
6926             demux->moov_node = NULL;
6927             GST_DEBUG_OBJECT (demux, "Finished parsing the header");
6928           }
6929         } else if (fourcc == FOURCC_moof) {
6930           if ((demux->got_moov || demux->media_caps) && demux->fragmented) {
6931             guint64 dist = 0;
6932             GstClockTime prev_pts;
6933             guint64 prev_offset;
6934             guint64 adapter_discont_offset, adapter_discont_dist;
6935
6936             GST_DEBUG_OBJECT (demux, "Parsing [moof]");
6937
6938             /*
6939              * The timestamp of the moof buffer is relevant as some scenarios
6940              * won't have the initial timestamp in the atoms. Whenever a new
6941              * buffer has started, we get that buffer's PTS and use it as a base
6942              * timestamp for the trun entries.
6943              *
6944              * To keep track of the current buffer timestamp and starting point
6945              * we use gst_adapter_prev_pts that gives us the PTS and the distance
6946              * from the beggining of the buffer, with the distance and demux->offset
6947              * we know if it is still the same buffer or not.
6948              */
6949             prev_pts = gst_adapter_prev_pts (demux->adapter, &dist);
6950             prev_offset = demux->offset - dist;
6951             if (demux->fragment_start_offset == -1
6952                 || prev_offset > demux->fragment_start_offset) {
6953               demux->fragment_start_offset = prev_offset;
6954               demux->fragment_start = prev_pts;
6955               GST_DEBUG_OBJECT (demux,
6956                   "New fragment start found at: %" G_GUINT64_FORMAT " : %"
6957                   GST_TIME_FORMAT, demux->fragment_start_offset,
6958                   GST_TIME_ARGS (demux->fragment_start));
6959             }
6960
6961             /* We can't use prev_offset() here because this would require
6962              * upstream to set consistent and correct offsets on all buffers
6963              * since the discont. Nothing ever did that in the past and we
6964              * would break backwards compatibility here then.
6965              * Instead take the offset we had at the last discont and count
6966              * the bytes from there. This works with old code as there would
6967              * be no discont between moov and moof, and also works with
6968              * adaptivedemux which correctly sets offset and will set the
6969              * DISCONT flag accordingly when needed.
6970              *
6971              * We also only do this for upstream TIME segments as otherwise
6972              * there are potential backwards compatibility problems with
6973              * seeking in PUSH mode and upstream providing inconsistent
6974              * timestamps. */
6975             adapter_discont_offset =
6976                 gst_adapter_offset_at_discont (demux->adapter);
6977             adapter_discont_dist =
6978                 gst_adapter_distance_from_discont (demux->adapter);
6979
6980             GST_DEBUG_OBJECT (demux,
6981                 "demux offset %" G_GUINT64_FORMAT " adapter offset %"
6982                 G_GUINT64_FORMAT " (+ %" G_GUINT64_FORMAT " bytes)",
6983                 demux->offset, adapter_discont_offset, adapter_discont_dist);
6984
6985             if (demux->upstream_format_is_time) {
6986               demux->moof_offset = adapter_discont_offset;
6987               if (demux->moof_offset != GST_BUFFER_OFFSET_NONE)
6988                 demux->moof_offset += adapter_discont_dist;
6989               if (demux->moof_offset == GST_BUFFER_OFFSET_NONE)
6990                 demux->moof_offset = demux->offset;
6991             } else {
6992               demux->moof_offset = demux->offset;
6993             }
6994
6995             if (!qtdemux_parse_moof (demux, data, demux->neededbytes,
6996                     demux->moof_offset, NULL)) {
6997               gst_adapter_unmap (demux->adapter);
6998               ret = GST_FLOW_ERROR;
6999               goto done;
7000             }
7001
7002             /* in MSS we need to expose the pads after the first moof as we won't get a moov */
7003             if (demux->mss_mode && !demux->exposed) {
7004               QTDEMUX_EXPOSE_LOCK (demux);
7005               qtdemux_expose_streams (demux);
7006               QTDEMUX_EXPOSE_UNLOCK (demux);
7007             }
7008
7009             gst_qtdemux_check_send_pending_segment (demux);
7010           } else {
7011             GST_DEBUG_OBJECT (demux, "Discarding [moof]");
7012           }
7013         } else if (fourcc == FOURCC_ftyp) {
7014           GST_DEBUG_OBJECT (demux, "Parsing [ftyp]");
7015           qtdemux_parse_ftyp (demux, data, demux->neededbytes);
7016         } else if (fourcc == FOURCC_uuid) {
7017           GST_DEBUG_OBJECT (demux, "Parsing [uuid]");
7018           qtdemux_parse_uuid (demux, data, demux->neededbytes);
7019         } else if (fourcc == FOURCC_sidx) {
7020           GST_DEBUG_OBJECT (demux, "Parsing [sidx]");
7021           qtdemux_parse_sidx (demux, data, demux->neededbytes);
7022         } else {
7023           switch (fourcc) {
7024             case FOURCC_styp:
7025               /* [styp] is like a [ftyp], but in fragment header. We ignore it for now
7026                * FALLTHROUGH */
7027             case FOURCC_skip:
7028             case FOURCC_free:
7029               /* [free] and [skip] are padding atoms */
7030               GST_DEBUG_OBJECT (demux,
7031                   "Skipping fourcc while parsing header : %" GST_FOURCC_FORMAT,
7032                   GST_FOURCC_ARGS (fourcc));
7033               break;
7034             default:
7035               GST_WARNING_OBJECT (demux,
7036                   "Unknown fourcc while parsing header : %" GST_FOURCC_FORMAT,
7037                   GST_FOURCC_ARGS (fourcc));
7038               /* Let's jump that one and go back to initial state */
7039               break;
7040           }
7041         }
7042         gst_adapter_unmap (demux->adapter);
7043         data = NULL;
7044
7045         if (demux->mdatbuffer && demux->n_streams) {
7046           gsize remaining_data_size = 0;
7047
7048           /* the mdat was before the header */
7049           GST_DEBUG_OBJECT (demux, "We have n_streams:%d and mdatbuffer:%p",
7050               demux->n_streams, demux->mdatbuffer);
7051           /* restore our adapter/offset view of things with upstream;
7052            * put preceding buffered data ahead of current moov data.
7053            * This should also handle evil mdat, moov, mdat cases and alike */
7054           gst_adapter_flush (demux->adapter, demux->neededbytes);
7055
7056           /* Store any remaining data after the mdat for later usage */
7057           remaining_data_size = gst_adapter_available (demux->adapter);
7058           if (remaining_data_size > 0) {
7059             g_assert (demux->restoredata_buffer == NULL);
7060             demux->restoredata_buffer =
7061                 gst_adapter_take_buffer (demux->adapter, remaining_data_size);
7062             demux->restoredata_offset = demux->offset + demux->neededbytes;
7063             GST_DEBUG_OBJECT (demux,
7064                 "Stored %" G_GSIZE_FORMAT " post mdat bytes at offset %"
7065                 G_GUINT64_FORMAT, remaining_data_size,
7066                 demux->restoredata_offset);
7067           }
7068
7069           gst_adapter_push (demux->adapter, demux->mdatbuffer);
7070           demux->mdatbuffer = NULL;
7071           demux->offset = demux->mdatoffset;
7072           demux->neededbytes = next_entry_size (demux);
7073           demux->state = QTDEMUX_STATE_MOVIE;
7074           demux->mdatleft = gst_adapter_available (demux->adapter);
7075           demux->mdatsize = demux->mdatleft;
7076         } else {
7077           GST_DEBUG_OBJECT (demux, "Carrying on normally");
7078           gst_adapter_flush (demux->adapter, demux->neededbytes);
7079
7080           /* only go back to the mdat if there are samples to play */
7081           if (demux->got_moov && demux->first_mdat != -1
7082               && has_next_entry (demux)) {
7083             gboolean res;
7084
7085             /* we need to seek back */
7086             res = qtdemux_seek_offset (demux, demux->first_mdat);
7087             if (res) {
7088               demux->offset = demux->first_mdat;
7089             } else {
7090               GST_DEBUG_OBJECT (demux, "Seek back failed");
7091             }
7092           } else {
7093             demux->offset += demux->neededbytes;
7094           }
7095           demux->neededbytes = 16;
7096           demux->state = QTDEMUX_STATE_INITIAL;
7097         }
7098
7099         break;
7100       }
7101       case QTDEMUX_STATE_BUFFER_MDAT:{
7102         GstBuffer *buf;
7103         guint8 fourcc[4];
7104
7105         GST_DEBUG_OBJECT (demux, "Got our buffer at offset %" G_GUINT64_FORMAT,
7106             demux->offset);
7107         buf = gst_adapter_take_buffer (demux->adapter, demux->neededbytes);
7108         gst_buffer_extract (buf, 0, fourcc, 4);
7109         GST_DEBUG_OBJECT (demux, "mdatbuffer starts with %" GST_FOURCC_FORMAT,
7110             GST_FOURCC_ARGS (QT_FOURCC (fourcc)));
7111         if (demux->mdatbuffer)
7112           demux->mdatbuffer = gst_buffer_append (demux->mdatbuffer, buf);
7113         else
7114           demux->mdatbuffer = buf;
7115         demux->offset += demux->neededbytes;
7116         demux->neededbytes = 16;
7117         demux->state = QTDEMUX_STATE_INITIAL;
7118         gst_qtdemux_post_progress (demux, 1, 1);
7119
7120         break;
7121       }
7122       case QTDEMUX_STATE_MOVIE:{
7123         QtDemuxStream *stream = NULL;
7124         QtDemuxSample *sample;
7125         GstClockTime dts, pts, duration;
7126         gboolean keyframe;
7127         GList *iter;
7128
7129         GST_DEBUG_OBJECT (demux,
7130             "BEGIN // in MOVIE for offset %" G_GUINT64_FORMAT, demux->offset);
7131
7132         if (demux->fragmented) {
7133           GST_DEBUG_OBJECT (demux, "mdat remaining %" G_GUINT64_FORMAT,
7134               demux->mdatleft);
7135           if (G_LIKELY (demux->todrop < demux->mdatleft)) {
7136             /* if needed data starts within this atom,
7137              * then it should not exceed this atom */
7138             if (G_UNLIKELY (demux->neededbytes > demux->mdatleft)) {
7139               GST_ELEMENT_ERROR (demux, STREAM, DEMUX,
7140                   (_("This file is invalid and cannot be played.")),
7141                   ("sample data crosses atom boundary"));
7142               ret = GST_FLOW_ERROR;
7143               break;
7144             }
7145             demux->mdatleft -= demux->neededbytes;
7146           } else {
7147             GST_DEBUG_OBJECT (demux, "data atom emptied; resuming atom scan");
7148             /* so we are dropping more than left in this atom */
7149             gst_qtdemux_drop_data (demux, demux->mdatleft);
7150             demux->mdatleft = 0;
7151
7152             /* need to resume atom parsing so we do not miss any other pieces */
7153             demux->state = QTDEMUX_STATE_INITIAL;
7154             demux->neededbytes = 16;
7155
7156             /* check if there was any stored post mdat data from previous buffers */
7157             if (demux->restoredata_buffer) {
7158               g_assert (gst_adapter_available (demux->adapter) == 0);
7159
7160               gst_adapter_push (demux->adapter, demux->restoredata_buffer);
7161               demux->restoredata_buffer = NULL;
7162               demux->offset = demux->restoredata_offset;
7163             }
7164
7165             break;
7166           }
7167         }
7168
7169         if (demux->todrop) {
7170           if (demux->cenc_aux_info_offset > 0) {
7171             GstByteReader br;
7172             const guint8 *data;
7173
7174             GST_DEBUG_OBJECT (demux, "parsing cenc auxiliary info");
7175             data = gst_adapter_map (demux->adapter, demux->todrop);
7176             gst_byte_reader_init (&br, data + 8, demux->todrop);
7177             if (!qtdemux_parse_cenc_aux_info (demux,
7178                     QTDEMUX_FIRST_STREAM (demux), &br,
7179                     demux->cenc_aux_info_sizes, demux->cenc_aux_sample_count)) {
7180               GST_ERROR_OBJECT (demux, "failed to parse cenc auxiliary info");
7181               ret = GST_FLOW_ERROR;
7182               gst_adapter_unmap (demux->adapter);
7183               g_free (demux->cenc_aux_info_sizes);
7184               demux->cenc_aux_info_sizes = NULL;
7185               goto done;
7186             }
7187             demux->cenc_aux_info_offset = 0;
7188             g_free (demux->cenc_aux_info_sizes);
7189             demux->cenc_aux_info_sizes = NULL;
7190             gst_adapter_unmap (demux->adapter);
7191           }
7192           gst_qtdemux_drop_data (demux, demux->todrop);
7193         }
7194
7195         /* first buffer? */
7196         /* initial newsegment sent here after having added pads,
7197          * possible others in sink_event */
7198         gst_qtdemux_check_send_pending_segment (demux);
7199
7200         /* Figure out which stream this packet belongs to */
7201         for (iter = demux->active_streams; iter; iter = g_list_next (iter)) {
7202           stream = QTDEMUX_STREAM (iter->data);
7203           if (stream->sample_index >= stream->n_samples) {
7204             /* reset to be checked below G_UNLIKELY (stream == NULL) */
7205             stream = NULL;
7206             continue;
7207           }
7208           GST_LOG_OBJECT (demux,
7209               "Checking track-id %u (sample_index:%d / offset:%"
7210               G_GUINT64_FORMAT " / size:%d)", stream->track_id,
7211               stream->sample_index,
7212               stream->samples[stream->sample_index].offset,
7213               stream->samples[stream->sample_index].size);
7214
7215           if (stream->samples[stream->sample_index].offset == demux->offset)
7216             break;
7217         }
7218
7219         if (G_UNLIKELY (stream == NULL))
7220           goto unknown_stream;
7221
7222         gst_qtdemux_stream_check_and_change_stsd_index (demux, stream);
7223
7224         if (stream->new_caps) {
7225           gst_qtdemux_configure_stream (demux, stream);
7226         }
7227
7228         /* Put data in a buffer, set timestamps, caps, ... */
7229         sample = &stream->samples[stream->sample_index];
7230
7231         if (G_LIKELY (!(STREAM_IS_EOS (stream)))) {
7232           GST_DEBUG_OBJECT (demux, "stream : %" GST_FOURCC_FORMAT,
7233               GST_FOURCC_ARGS (CUR_STREAM (stream)->fourcc));
7234
7235           dts = QTSAMPLE_DTS (stream, sample);
7236           pts = QTSAMPLE_PTS (stream, sample);
7237           duration = QTSAMPLE_DUR_DTS (stream, sample, dts);
7238           keyframe = QTSAMPLE_KEYFRAME (stream, sample);
7239
7240           /* check for segment end */
7241           if (G_UNLIKELY (demux->segment.stop != -1
7242                   && demux->segment.stop <= pts && stream->on_keyframe)) {
7243             GST_DEBUG_OBJECT (demux, "we reached the end of our segment.");
7244             stream->time_position = GST_CLOCK_TIME_NONE;        /* this means EOS */
7245
7246             /* skip this data, stream is EOS */
7247             gst_adapter_flush (demux->adapter, demux->neededbytes);
7248             demux->offset += demux->neededbytes;
7249
7250             /* check if all streams are eos */
7251             ret = GST_FLOW_EOS;
7252             for (iter = demux->active_streams; iter; iter = g_list_next (iter)) {
7253               if (!STREAM_IS_EOS (QTDEMUX_STREAM (iter->data))) {
7254                 ret = GST_FLOW_OK;
7255                 break;
7256               }
7257             }
7258           } else {
7259             GstBuffer *outbuf;
7260
7261             outbuf =
7262                 gst_adapter_take_buffer (demux->adapter, demux->neededbytes);
7263
7264             /* FIXME: should either be an assert or a plain check */
7265             g_return_val_if_fail (outbuf != NULL, GST_FLOW_ERROR);
7266
7267             ret = gst_qtdemux_decorate_and_push_buffer (demux, stream, outbuf,
7268                 dts, pts, duration, keyframe, dts, demux->offset);
7269           }
7270
7271           /* combine flows */
7272           ret = gst_qtdemux_combine_flows (demux, stream, ret);
7273         } else {
7274           /* skip this data, stream is EOS */
7275           gst_adapter_flush (demux->adapter, demux->neededbytes);
7276         }
7277
7278         stream->sample_index++;
7279         stream->offset_in_sample = 0;
7280
7281         /* update current offset and figure out size of next buffer */
7282         GST_LOG_OBJECT (demux, "increasing offset %" G_GUINT64_FORMAT " by %u",
7283             demux->offset, demux->neededbytes);
7284         demux->offset += demux->neededbytes;
7285         GST_LOG_OBJECT (demux, "offset is now %" G_GUINT64_FORMAT,
7286             demux->offset);
7287
7288
7289         if (ret == GST_FLOW_EOS) {
7290           GST_DEBUG_OBJECT (demux, "All streams are EOS, signal upstream");
7291           demux->neededbytes = -1;
7292           goto eos;
7293         }
7294
7295         if ((demux->neededbytes = next_entry_size (demux)) == -1) {
7296           if (demux->fragmented) {
7297             GST_DEBUG_OBJECT (demux, "(temporarily) out of fragmented samples");
7298             /* there may be more to follow, only finish this atom */
7299             demux->todrop = demux->mdatleft;
7300             demux->neededbytes = demux->todrop;
7301             break;
7302           }
7303           goto eos;
7304         }
7305         if (ret != GST_FLOW_OK && ret != GST_FLOW_NOT_LINKED) {
7306           goto non_ok_unlinked_flow;
7307         }
7308         break;
7309       }
7310       default:
7311         goto invalid_state;
7312     }
7313   }
7314
7315   /* when buffering movie data, at least show user something is happening */
7316   if (ret == GST_FLOW_OK && demux->state == QTDEMUX_STATE_BUFFER_MDAT &&
7317       gst_adapter_available (demux->adapter) <= demux->neededbytes) {
7318     gst_qtdemux_post_progress (demux, gst_adapter_available (demux->adapter),
7319         demux->neededbytes);
7320   }
7321 done:
7322
7323   return ret;
7324
7325   /* ERRORS */
7326 non_ok_unlinked_flow:
7327   {
7328     GST_DEBUG_OBJECT (demux, "Stopping, combined return flow %s",
7329         gst_flow_get_name (ret));
7330     return ret;
7331   }
7332 unknown_stream:
7333   {
7334     GST_ELEMENT_ERROR (demux, STREAM, FAILED, (NULL), ("unknown stream found"));
7335     ret = GST_FLOW_ERROR;
7336     goto done;
7337   }
7338 eos:
7339   {
7340     GST_DEBUG_OBJECT (demux, "no next entry, EOS");
7341     ret = GST_FLOW_EOS;
7342     goto done;
7343   }
7344 invalid_state:
7345   {
7346     GST_ELEMENT_ERROR (demux, STREAM, FAILED,
7347         (NULL), ("qtdemuxer invalid state %d", demux->state));
7348     ret = GST_FLOW_ERROR;
7349     goto done;
7350   }
7351 no_moov:
7352   {
7353     GST_ELEMENT_ERROR (demux, STREAM, FAILED,
7354         (NULL), ("no 'moov' atom within the first 10 MB"));
7355     ret = GST_FLOW_ERROR;
7356     goto done;
7357   }
7358 }
7359
7360 static gboolean
7361 qtdemux_sink_activate (GstPad * sinkpad, GstObject * parent)
7362 {
7363   GstQuery *query;
7364   gboolean pull_mode;
7365
7366   query = gst_query_new_scheduling ();
7367
7368   if (!gst_pad_peer_query (sinkpad, query)) {
7369     gst_query_unref (query);
7370     goto activate_push;
7371   }
7372
7373   pull_mode = gst_query_has_scheduling_mode_with_flags (query,
7374       GST_PAD_MODE_PULL, GST_SCHEDULING_FLAG_SEEKABLE);
7375   gst_query_unref (query);
7376
7377   if (!pull_mode)
7378     goto activate_push;
7379
7380   GST_DEBUG_OBJECT (sinkpad, "activating pull");
7381   return gst_pad_activate_mode (sinkpad, GST_PAD_MODE_PULL, TRUE);
7382
7383 activate_push:
7384   {
7385     GST_DEBUG_OBJECT (sinkpad, "activating push");
7386     return gst_pad_activate_mode (sinkpad, GST_PAD_MODE_PUSH, TRUE);
7387   }
7388 }
7389
7390 static gboolean
7391 qtdemux_sink_activate_mode (GstPad * sinkpad, GstObject * parent,
7392     GstPadMode mode, gboolean active)
7393 {
7394   gboolean res;
7395   GstQTDemux *demux = GST_QTDEMUX (parent);
7396
7397   switch (mode) {
7398     case GST_PAD_MODE_PUSH:
7399       demux->pullbased = FALSE;
7400       res = TRUE;
7401       break;
7402     case GST_PAD_MODE_PULL:
7403       if (active) {
7404         demux->pullbased = TRUE;
7405         res = gst_pad_start_task (sinkpad, (GstTaskFunction) gst_qtdemux_loop,
7406             sinkpad, NULL);
7407       } else {
7408         res = gst_pad_stop_task (sinkpad);
7409       }
7410       break;
7411     default:
7412       res = FALSE;
7413       break;
7414   }
7415   return res;
7416 }
7417
7418 #ifdef HAVE_ZLIB
7419 static void *
7420 qtdemux_inflate (void *z_buffer, guint z_length, guint * length)
7421 {
7422   guint8 *buffer;
7423   z_stream z;
7424   int ret;
7425
7426   memset (&z, 0, sizeof (z));
7427   z.zalloc = NULL;
7428   z.zfree = NULL;
7429   z.opaque = NULL;
7430
7431   if ((ret = inflateInit (&z)) != Z_OK) {
7432     GST_ERROR ("inflateInit() returned %d", ret);
7433     return NULL;
7434   }
7435
7436   z.next_in = z_buffer;
7437   z.avail_in = z_length;
7438
7439   buffer = (guint8 *) g_malloc (*length);
7440   z.avail_out = *length;
7441   z.next_out = (Bytef *) buffer;
7442   do {
7443     ret = inflate (&z, Z_NO_FLUSH);
7444     if (ret == Z_STREAM_END) {
7445       break;
7446     } else if (ret != Z_OK) {
7447       GST_WARNING ("inflate() returned %d", ret);
7448       break;
7449     }
7450
7451     *length += 4096;
7452     buffer = (guint8 *) g_realloc (buffer, *length);
7453     z.next_out = (Bytef *) (buffer + z.total_out);
7454     z.avail_out += 4096;
7455   } while (z.avail_in > 0);
7456
7457   if (ret != Z_STREAM_END) {
7458     g_free (buffer);
7459     buffer = NULL;
7460     *length = 0;
7461   } else {
7462     *length = z.total_out;
7463   }
7464
7465   inflateEnd (&z);
7466
7467   return buffer;
7468 }
7469 #endif /* HAVE_ZLIB */
7470
7471 static gboolean
7472 qtdemux_parse_moov (GstQTDemux * qtdemux, const guint8 * buffer, guint length)
7473 {
7474   GNode *cmov;
7475
7476   qtdemux->moov_node = g_node_new ((guint8 *) buffer);
7477
7478   /* counts as header data */
7479   qtdemux->header_size += length;
7480
7481   GST_DEBUG_OBJECT (qtdemux, "parsing 'moov' atom");
7482   qtdemux_parse_node (qtdemux, qtdemux->moov_node, buffer, length);
7483
7484   cmov = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_cmov);
7485   if (cmov) {
7486     guint32 method;
7487     GNode *dcom;
7488     GNode *cmvd;
7489     guint32 dcom_len;
7490
7491     dcom = qtdemux_tree_get_child_by_type (cmov, FOURCC_dcom);
7492     cmvd = qtdemux_tree_get_child_by_type (cmov, FOURCC_cmvd);
7493     if (dcom == NULL || cmvd == NULL)
7494       goto invalid_compression;
7495
7496     dcom_len = QT_UINT32 (dcom->data);
7497     if (dcom_len < 12)
7498       goto invalid_compression;
7499
7500     method = QT_FOURCC ((guint8 *) dcom->data + 8);
7501     switch (method) {
7502 #ifdef HAVE_ZLIB
7503       case FOURCC_zlib:{
7504         guint uncompressed_length;
7505         guint compressed_length;
7506         guint8 *buf;
7507         guint32 cmvd_len;
7508
7509         cmvd_len = QT_UINT32 ((guint8 *) cmvd->data);
7510         if (cmvd_len < 12)
7511           goto invalid_compression;
7512
7513         uncompressed_length = QT_UINT32 ((guint8 *) cmvd->data + 8);
7514         compressed_length = cmvd_len - 12;
7515         GST_LOG ("length = %u", uncompressed_length);
7516
7517         buf =
7518             (guint8 *) qtdemux_inflate ((guint8 *) cmvd->data + 12,
7519             compressed_length, &uncompressed_length);
7520
7521         if (buf) {
7522           qtdemux->moov_node_compressed = qtdemux->moov_node;
7523           qtdemux->moov_node = g_node_new (buf);
7524
7525           qtdemux_parse_node (qtdemux, qtdemux->moov_node, buf,
7526               uncompressed_length);
7527         }
7528         break;
7529       }
7530 #endif /* HAVE_ZLIB */
7531       default:
7532         GST_WARNING_OBJECT (qtdemux, "unknown or unhandled header compression "
7533             "type %" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (method));
7534         break;
7535     }
7536   }
7537   return TRUE;
7538
7539   /* ERRORS */
7540 invalid_compression:
7541   {
7542     GST_ERROR_OBJECT (qtdemux, "invalid compressed header");
7543     return FALSE;
7544   }
7545 }
7546
7547 static gboolean
7548 qtdemux_parse_container (GstQTDemux * qtdemux, GNode * node, const guint8 * buf,
7549     const guint8 * end)
7550 {
7551   while (G_UNLIKELY (buf < end)) {
7552     GNode *child;
7553     guint32 len;
7554
7555     if (G_UNLIKELY (buf + 4 > end)) {
7556       GST_LOG_OBJECT (qtdemux, "buffer overrun");
7557       break;
7558     }
7559     len = QT_UINT32 (buf);
7560     if (G_UNLIKELY (len == 0)) {
7561       GST_LOG_OBJECT (qtdemux, "empty container");
7562       break;
7563     }
7564     if (G_UNLIKELY (len < 8)) {
7565       GST_WARNING_OBJECT (qtdemux, "length too short (%d < 8)", len);
7566       break;
7567     }
7568     if (G_UNLIKELY (len > (end - buf))) {
7569       GST_WARNING_OBJECT (qtdemux, "length too long (%d > %d)", len,
7570           (gint) (end - buf));
7571       break;
7572     }
7573
7574     child = g_node_new ((guint8 *) buf);
7575     g_node_append (node, child);
7576     GST_LOG_OBJECT (qtdemux, "adding new node of len %d", len);
7577     qtdemux_parse_node (qtdemux, child, buf, len);
7578
7579     buf += len;
7580   }
7581   return TRUE;
7582 }
7583
7584 static gboolean
7585 qtdemux_parse_theora_extension (GstQTDemux * qtdemux, QtDemuxStream * stream,
7586     GNode * xdxt)
7587 {
7588   int len = QT_UINT32 (xdxt->data);
7589   guint8 *buf = xdxt->data;
7590   guint8 *end = buf + len;
7591   GstBuffer *buffer;
7592
7593   /* skip size and type */
7594   buf += 8;
7595   end -= 8;
7596
7597   while (buf < end) {
7598     gint size;
7599     guint32 type;
7600
7601     size = QT_UINT32 (buf);
7602     type = QT_FOURCC (buf + 4);
7603
7604     GST_LOG_OBJECT (qtdemux, "%p %p", buf, end);
7605
7606     if (buf + size > end || size <= 0)
7607       break;
7608
7609     buf += 8;
7610     size -= 8;
7611
7612     GST_WARNING_OBJECT (qtdemux, "have cookie %" GST_FOURCC_FORMAT,
7613         GST_FOURCC_ARGS (type));
7614
7615     switch (type) {
7616       case FOURCC_tCtH:
7617         buffer = gst_buffer_new_and_alloc (size);
7618         gst_buffer_fill (buffer, 0, buf, size);
7619         stream->buffers = g_slist_append (stream->buffers, buffer);
7620         GST_LOG_OBJECT (qtdemux, "parsing theora header");
7621         break;
7622       case FOURCC_tCt_:
7623         buffer = gst_buffer_new_and_alloc (size);
7624         gst_buffer_fill (buffer, 0, buf, size);
7625         stream->buffers = g_slist_append (stream->buffers, buffer);
7626         GST_LOG_OBJECT (qtdemux, "parsing theora comment");
7627         break;
7628       case FOURCC_tCtC:
7629         buffer = gst_buffer_new_and_alloc (size);
7630         gst_buffer_fill (buffer, 0, buf, size);
7631         stream->buffers = g_slist_append (stream->buffers, buffer);
7632         GST_LOG_OBJECT (qtdemux, "parsing theora codebook");
7633         break;
7634       default:
7635         GST_WARNING_OBJECT (qtdemux,
7636             "unknown theora cookie %" GST_FOURCC_FORMAT,
7637             GST_FOURCC_ARGS (type));
7638         break;
7639     }
7640     buf += size;
7641   }
7642   return TRUE;
7643 }
7644
7645 static gboolean
7646 qtdemux_parse_node (GstQTDemux * qtdemux, GNode * node, const guint8 * buffer,
7647     guint length)
7648 {
7649   guint32 fourcc = 0;
7650   guint32 node_length = 0;
7651   const QtNodeType *type;
7652   const guint8 *end;
7653
7654   GST_LOG_OBJECT (qtdemux, "qtdemux_parse buffer %p length %u", buffer, length);
7655
7656   if (G_UNLIKELY (length < 8))
7657     goto not_enough_data;
7658
7659   node_length = QT_UINT32 (buffer);
7660   fourcc = QT_FOURCC (buffer + 4);
7661
7662   /* ignore empty nodes */
7663   if (G_UNLIKELY (fourcc == 0 || node_length == 8))
7664     return TRUE;
7665
7666   type = qtdemux_type_get (fourcc);
7667
7668   end = buffer + length;
7669
7670   GST_LOG_OBJECT (qtdemux,
7671       "parsing '%" GST_FOURCC_FORMAT "', length=%u, name '%s'",
7672       GST_FOURCC_ARGS (fourcc), node_length, type->name);
7673
7674   if (node_length > length)
7675     goto broken_atom_size;
7676
7677   if (type->flags & QT_FLAG_CONTAINER) {
7678     qtdemux_parse_container (qtdemux, node, buffer + 8, end);
7679   } else {
7680     switch (fourcc) {
7681       case FOURCC_stsd:
7682       {
7683         if (node_length < 20) {
7684           GST_LOG_OBJECT (qtdemux, "skipping small stsd box");
7685           break;
7686         }
7687         GST_DEBUG_OBJECT (qtdemux,
7688             "parsing stsd (sample table, sample description) atom");
7689         /* Skip over 8 byte atom hdr + 1 byte version, 3 bytes flags, 4 byte num_entries */
7690         qtdemux_parse_container (qtdemux, node, buffer + 16, end);
7691         break;
7692       }
7693       case FOURCC_mp4a:
7694       case FOURCC_alac:
7695       case FOURCC_fLaC:
7696       {
7697         guint32 version;
7698         guint32 offset;
7699         guint min_size;
7700
7701         /* also read alac (or whatever) in stead of mp4a in the following,
7702          * since a similar layout is used in other cases as well */
7703         if (fourcc == FOURCC_mp4a)
7704           min_size = 20;
7705         else if (fourcc == FOURCC_fLaC)
7706           min_size = 86;
7707         else
7708           min_size = 40;
7709
7710         /* There are two things we might encounter here: a true mp4a atom, and
7711            an mp4a entry in an stsd atom. The latter is what we're interested
7712            in, and it looks like an atom, but isn't really one. The true mp4a
7713            atom is short, so we detect it based on length here. */
7714         if (length < min_size) {
7715           GST_LOG_OBJECT (qtdemux, "skipping small %" GST_FOURCC_FORMAT " box",
7716               GST_FOURCC_ARGS (fourcc));
7717           break;
7718         }
7719
7720         /* 'version' here is the sound sample description version. Types 0 and
7721            1 are documented in the QTFF reference, but type 2 is not: it's
7722            described in Apple header files instead (struct SoundDescriptionV2
7723            in Movies.h) */
7724         version = QT_UINT16 (buffer + 16);
7725
7726         GST_DEBUG_OBJECT (qtdemux, "%" GST_FOURCC_FORMAT " version 0x%08x",
7727             GST_FOURCC_ARGS (fourcc), version);
7728
7729         /* parse any esds descriptors */
7730         switch (version) {
7731           case 0:
7732             offset = 0x24;
7733             break;
7734           case 1:
7735             offset = 0x34;
7736             break;
7737           case 2:
7738             offset = 0x48;
7739             break;
7740           default:
7741             GST_WARNING_OBJECT (qtdemux,
7742                 "unhandled %" GST_FOURCC_FORMAT " version 0x%08x",
7743                 GST_FOURCC_ARGS (fourcc), version);
7744             offset = 0;
7745             break;
7746         }
7747         if (offset)
7748           qtdemux_parse_container (qtdemux, node, buffer + offset, end);
7749         break;
7750       }
7751       case FOURCC_mp4v:
7752       case FOURCC_MP4V:
7753       case FOURCC_fmp4:
7754       case FOURCC_FMP4:
7755       case FOURCC_apcs:
7756       case FOURCC_apch:
7757       case FOURCC_apcn:
7758       case FOURCC_apco:
7759       case FOURCC_ap4h:
7760       case FOURCC_xvid:
7761       case FOURCC_XVID:
7762       case FOURCC_H264:
7763       case FOURCC_avc1:
7764       case FOURCC_avc3:
7765       case FOURCC_H265:
7766       case FOURCC_hvc1:
7767       case FOURCC_hev1:
7768       case FOURCC_mjp2:
7769       case FOURCC_encv:
7770       {
7771         guint32 version;
7772         guint32 str_len;
7773
7774         /* codec_data is contained inside these atoms, which all have
7775          * the same format. */
7776         /* video sample description size is 86 bytes without extension.
7777          * node_length have to be bigger than 86 bytes because video sample
7778          * description can include extenstions such as esds, fiel, glbl, etc. */
7779         if (node_length < 86) {
7780           GST_WARNING_OBJECT (qtdemux, "%" GST_FOURCC_FORMAT
7781               " sample description length too short (%u < 86)",
7782               GST_FOURCC_ARGS (fourcc), node_length);
7783           break;
7784         }
7785
7786         GST_DEBUG_OBJECT (qtdemux, "parsing in %" GST_FOURCC_FORMAT,
7787             GST_FOURCC_ARGS (fourcc));
7788
7789         /* version (2 bytes) : this is set to 0, unless a compressor has changed
7790          *              its data format.
7791          * revision level (2 bytes) : must be set to 0. */
7792         version = QT_UINT32 (buffer + 16);
7793         GST_DEBUG_OBJECT (qtdemux, "version %08x", version);
7794
7795         /* compressor name : PASCAL string and informative purposes
7796          * first byte : the number of bytes to be displayed.
7797          *              it has to be less than 32 because it is reserved
7798          *              space of 32 bytes total including itself. */
7799         str_len = QT_UINT8 (buffer + 50);
7800         if (str_len < 32)
7801           GST_DEBUG_OBJECT (qtdemux, "compressorname = %.*s", str_len,
7802               (char *) buffer + 51);
7803         else
7804           GST_WARNING_OBJECT (qtdemux,
7805               "compressorname length too big (%u > 31)", str_len);
7806
7807         GST_MEMDUMP_OBJECT (qtdemux, "video sample description", buffer,
7808             end - buffer);
7809         qtdemux_parse_container (qtdemux, node, buffer + 86, end);
7810         break;
7811       }
7812       case FOURCC_meta:
7813       {
7814         GST_DEBUG_OBJECT (qtdemux, "parsing meta atom");
7815
7816         /* You are reading this correctly. QTFF specifies that the
7817          * metadata atom is a short atom, whereas ISO BMFF specifies
7818          * it's a full atom. But since so many people are doing things
7819          * differently, we actually peek into the atom to see which
7820          * variant it is */
7821         if (length < 16) {
7822           GST_LOG_OBJECT (qtdemux, "skipping small %" GST_FOURCC_FORMAT " box",
7823               GST_FOURCC_ARGS (fourcc));
7824           break;
7825         }
7826         if (QT_FOURCC (buffer + 12) == FOURCC_hdlr) {
7827           /* Variant 1: What QTFF specifies. 'meta' is a short header which
7828            * starts with a 'hdlr' atom */
7829           qtdemux_parse_container (qtdemux, node, buffer + 8, end);
7830         } else if (QT_UINT32 (buffer + 8) == 0x00000000) {
7831           /* Variant 2: What ISO BMFF specifies. 'meta' is a _full_ atom
7832            * with version/flags both set to zero */
7833           qtdemux_parse_container (qtdemux, node, buffer + 12, end);
7834         } else
7835           GST_WARNING_OBJECT (qtdemux, "Unknown 'meta' atom format");
7836         break;
7837       }
7838       case FOURCC_mp4s:
7839       {
7840         GST_MEMDUMP_OBJECT (qtdemux, "mp4s", buffer, end - buffer);
7841         /* Skip 8 byte header, plus 8 byte version + flags + entry_count */
7842         qtdemux_parse_container (qtdemux, node, buffer + 16, end);
7843         break;
7844       }
7845       case FOURCC_XiTh:
7846       {
7847         guint32 version;
7848         guint32 offset;
7849
7850         if (length < 16) {
7851           GST_LOG_OBJECT (qtdemux, "skipping small %" GST_FOURCC_FORMAT " box",
7852               GST_FOURCC_ARGS (fourcc));
7853           break;
7854         }
7855
7856         version = QT_UINT32 (buffer + 12);
7857         GST_DEBUG_OBJECT (qtdemux, "parsing XiTh atom version 0x%08x", version);
7858
7859         switch (version) {
7860           case 0x00000001:
7861             offset = 0x62;
7862             break;
7863           default:
7864             GST_DEBUG_OBJECT (qtdemux, "unknown version 0x%08x", version);
7865             offset = 0;
7866             break;
7867         }
7868         if (offset) {
7869           if (length < offset) {
7870             GST_WARNING_OBJECT (qtdemux,
7871                 "skipping too small %" GST_FOURCC_FORMAT " box",
7872                 GST_FOURCC_ARGS (fourcc));
7873             break;
7874           }
7875           qtdemux_parse_container (qtdemux, node, buffer + offset, end);
7876         }
7877         break;
7878       }
7879       case FOURCC_in24:
7880       {
7881         qtdemux_parse_container (qtdemux, node, buffer + 0x34, end);
7882         break;
7883       }
7884       case FOURCC_uuid:
7885       {
7886         qtdemux_parse_uuid (qtdemux, buffer, end - buffer);
7887         break;
7888       }
7889       case FOURCC_enca:
7890       {
7891         qtdemux_parse_container (qtdemux, node, buffer + 36, end);
7892         break;
7893       }
7894       default:
7895         if (!strcmp (type->name, "unknown"))
7896           GST_MEMDUMP ("Unknown tag", buffer + 4, end - buffer - 4);
7897         break;
7898     }
7899   }
7900   GST_LOG_OBJECT (qtdemux, "parsed '%" GST_FOURCC_FORMAT "'",
7901       GST_FOURCC_ARGS (fourcc));
7902   return TRUE;
7903
7904 /* ERRORS */
7905 not_enough_data:
7906   {
7907     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
7908         (_("This file is corrupt and cannot be played.")),
7909         ("Not enough data for an atom header, got only %u bytes", length));
7910     return FALSE;
7911   }
7912 broken_atom_size:
7913   {
7914     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
7915         (_("This file is corrupt and cannot be played.")),
7916         ("Atom '%" GST_FOURCC_FORMAT "' has size of %u bytes, but we have only "
7917             "%u bytes available.", GST_FOURCC_ARGS (fourcc), node_length,
7918             length));
7919     return FALSE;
7920   }
7921 }
7922
7923 static GNode *
7924 qtdemux_tree_get_child_by_type (GNode * node, guint32 fourcc)
7925 {
7926   GNode *child;
7927   guint8 *buffer;
7928   guint32 child_fourcc;
7929
7930   for (child = g_node_first_child (node); child;
7931       child = g_node_next_sibling (child)) {
7932     buffer = (guint8 *) child->data;
7933
7934     child_fourcc = QT_FOURCC (buffer + 4);
7935
7936     if (G_UNLIKELY (child_fourcc == fourcc)) {
7937       return child;
7938     }
7939   }
7940   return NULL;
7941 }
7942
7943 static GNode *
7944 qtdemux_tree_get_child_by_type_full (GNode * node, guint32 fourcc,
7945     GstByteReader * parser)
7946 {
7947   GNode *child;
7948   guint8 *buffer;
7949   guint32 child_fourcc, child_len;
7950
7951   for (child = g_node_first_child (node); child;
7952       child = g_node_next_sibling (child)) {
7953     buffer = (guint8 *) child->data;
7954
7955     child_len = QT_UINT32 (buffer);
7956     child_fourcc = QT_FOURCC (buffer + 4);
7957
7958     if (G_UNLIKELY (child_fourcc == fourcc)) {
7959       if (G_UNLIKELY (child_len < (4 + 4)))
7960         return NULL;
7961       /* FIXME: must verify if atom length < parent atom length */
7962       gst_byte_reader_init (parser, buffer + (4 + 4), child_len - (4 + 4));
7963       return child;
7964     }
7965   }
7966   return NULL;
7967 }
7968
7969 static GNode *
7970 qtdemux_tree_get_child_by_index (GNode * node, guint index)
7971 {
7972   return g_node_nth_child (node, index);
7973 }
7974
7975 static GNode *
7976 qtdemux_tree_get_sibling_by_type_full (GNode * node, guint32 fourcc,
7977     GstByteReader * parser)
7978 {
7979   GNode *child;
7980   guint8 *buffer;
7981   guint32 child_fourcc, child_len;
7982
7983   for (child = g_node_next_sibling (node); child;
7984       child = g_node_next_sibling (child)) {
7985     buffer = (guint8 *) child->data;
7986
7987     child_fourcc = QT_FOURCC (buffer + 4);
7988
7989     if (child_fourcc == fourcc) {
7990       if (parser) {
7991         child_len = QT_UINT32 (buffer);
7992         if (G_UNLIKELY (child_len < (4 + 4)))
7993           return NULL;
7994         /* FIXME: must verify if atom length < parent atom length */
7995         gst_byte_reader_init (parser, buffer + (4 + 4), child_len - (4 + 4));
7996       }
7997       return child;
7998     }
7999   }
8000   return NULL;
8001 }
8002
8003 static GNode *
8004 qtdemux_tree_get_sibling_by_type (GNode * node, guint32 fourcc)
8005 {
8006   return qtdemux_tree_get_sibling_by_type_full (node, fourcc, NULL);
8007 }
8008
8009 static void
8010 qtdemux_do_allocation (GstQTDemux * qtdemux, QtDemuxStream * stream)
8011 {
8012 /* FIXME: This can only reliably work if demuxers have a
8013  * separate streaming thread per srcpad. This should be
8014  * done in a demuxer base class, which integrates parts
8015  * of multiqueue
8016  *
8017  * https://bugzilla.gnome.org/show_bug.cgi?id=701856
8018  */
8019 #if 0
8020   GstQuery *query;
8021
8022   query = gst_query_new_allocation (stream->caps, FALSE);
8023
8024   if (!gst_pad_peer_query (stream->pad, query)) {
8025     /* not a problem, just debug a little */
8026     GST_DEBUG_OBJECT (qtdemux, "peer ALLOCATION query failed");
8027   }
8028
8029   if (stream->allocator)
8030     gst_object_unref (stream->allocator);
8031
8032   if (gst_query_get_n_allocation_params (query) > 0) {
8033     /* try the allocator */
8034     gst_query_parse_nth_allocation_param (query, 0, &stream->allocator,
8035         &stream->params);
8036     stream->use_allocator = TRUE;
8037   } else {
8038     stream->allocator = NULL;
8039     gst_allocation_params_init (&stream->params);
8040     stream->use_allocator = FALSE;
8041   }
8042   gst_query_unref (query);
8043 #endif
8044 }
8045
8046 static gboolean
8047 pad_query (const GValue * item, GValue * value, gpointer user_data)
8048 {
8049   GstPad *pad = g_value_get_object (item);
8050   GstQuery *query = user_data;
8051   gboolean res;
8052
8053   res = gst_pad_peer_query (pad, query);
8054
8055   if (res) {
8056     g_value_set_boolean (value, TRUE);
8057     return FALSE;
8058   }
8059
8060   GST_INFO_OBJECT (pad, "pad peer query failed");
8061   return TRUE;
8062 }
8063
8064 static gboolean
8065 gst_qtdemux_run_query (GstElement * element, GstQuery * query,
8066     GstPadDirection direction)
8067 {
8068   GstIterator *it;
8069   GstIteratorFoldFunction func = pad_query;
8070   GValue res = { 0, };
8071
8072   g_value_init (&res, G_TYPE_BOOLEAN);
8073   g_value_set_boolean (&res, FALSE);
8074
8075   /* Ask neighbor */
8076   if (direction == GST_PAD_SRC)
8077     it = gst_element_iterate_src_pads (element);
8078   else
8079     it = gst_element_iterate_sink_pads (element);
8080
8081   while (gst_iterator_fold (it, func, &res, query) == GST_ITERATOR_RESYNC)
8082     gst_iterator_resync (it);
8083
8084   gst_iterator_free (it);
8085
8086   return g_value_get_boolean (&res);
8087 }
8088
8089 static void
8090 gst_qtdemux_request_protection_context (GstQTDemux * qtdemux,
8091     QtDemuxStream * stream)
8092 {
8093   GstQuery *query;
8094   GstContext *ctxt;
8095   GstElement *element = GST_ELEMENT (qtdemux);
8096   GstStructure *st;
8097   gchar **filtered_sys_ids;
8098   GValue event_list = G_VALUE_INIT;
8099   GList *walk;
8100
8101   /* 1. Check if we already have the context. */
8102   if (qtdemux->preferred_protection_system_id != NULL) {
8103     GST_LOG_OBJECT (element,
8104         "already have the protection context, no need to request it again");
8105     return;
8106   }
8107
8108   g_ptr_array_add (qtdemux->protection_system_ids, NULL);
8109   filtered_sys_ids = gst_protection_filter_systems_by_available_decryptors (
8110       (const gchar **) qtdemux->protection_system_ids->pdata);
8111
8112   g_ptr_array_remove_index (qtdemux->protection_system_ids,
8113       qtdemux->protection_system_ids->len - 1);
8114   GST_TRACE_OBJECT (qtdemux, "detected %u protection systems, we have "
8115       "decryptors for %u of them, running context request",
8116       qtdemux->protection_system_ids->len, g_strv_length (filtered_sys_ids));
8117
8118   if (stream->protection_scheme_event_queue.length) {
8119     GST_TRACE_OBJECT (qtdemux, "using stream event queue, length %u",
8120         stream->protection_scheme_event_queue.length);
8121     walk = stream->protection_scheme_event_queue.tail;
8122   } else {
8123     GST_TRACE_OBJECT (qtdemux, "using demuxer event queue, length %u",
8124         qtdemux->protection_event_queue.length);
8125     walk = qtdemux->protection_event_queue.tail;
8126   }
8127
8128   g_value_init (&event_list, GST_TYPE_LIST);
8129   for (; walk; walk = g_list_previous (walk)) {
8130     GValue *event_value = g_new0 (GValue, 1);
8131     g_value_init (event_value, GST_TYPE_EVENT);
8132     g_value_set_boxed (event_value, walk->data);
8133     gst_value_list_append_and_take_value (&event_list, event_value);
8134   }
8135
8136   /*  2a) Query downstream with GST_QUERY_CONTEXT for the context and
8137    *      check if downstream already has a context of the specific type
8138    *  2b) Query upstream as above.
8139    */
8140   query = gst_query_new_context ("drm-preferred-decryption-system-id");
8141   st = gst_query_writable_structure (query);
8142   gst_structure_set (st, "track-id", G_TYPE_UINT, stream->track_id,
8143       "available-stream-encryption-systems", G_TYPE_STRV, filtered_sys_ids,
8144       NULL);
8145   gst_structure_set_value (st, "stream-encryption-events", &event_list);
8146   if (gst_qtdemux_run_query (element, query, GST_PAD_SRC)) {
8147     gst_query_parse_context (query, &ctxt);
8148     GST_INFO_OBJECT (element, "found context (%p) in downstream query", ctxt);
8149     gst_element_set_context (element, ctxt);
8150   } else if (gst_qtdemux_run_query (element, query, GST_PAD_SINK)) {
8151     gst_query_parse_context (query, &ctxt);
8152     GST_INFO_OBJECT (element, "found context (%p) in upstream query", ctxt);
8153     gst_element_set_context (element, ctxt);
8154   } else {
8155     /* 3) Post a GST_MESSAGE_NEED_CONTEXT message on the bus with
8156      *    the required context type and afterwards check if a
8157      *    usable context was set now as in 1). The message could
8158      *    be handled by the parent bins of the element and the
8159      *    application.
8160      */
8161     GstMessage *msg;
8162
8163     GST_INFO_OBJECT (element, "posting need context message");
8164     msg = gst_message_new_need_context (GST_OBJECT_CAST (element),
8165         "drm-preferred-decryption-system-id");
8166     st = (GstStructure *) gst_message_get_structure (msg);
8167     gst_structure_set (st, "track-id", G_TYPE_UINT, stream->track_id,
8168         "available-stream-encryption-systems", G_TYPE_STRV, filtered_sys_ids,
8169         NULL);
8170
8171     gst_structure_set_value (st, "stream-encryption-events", &event_list);
8172     gst_element_post_message (element, msg);
8173   }
8174
8175   g_strfreev (filtered_sys_ids);
8176   g_value_unset (&event_list);
8177   gst_query_unref (query);
8178 }
8179
8180 static gboolean
8181 gst_qtdemux_configure_protected_caps (GstQTDemux * qtdemux,
8182     QtDemuxStream * stream)
8183 {
8184   GstStructure *s;
8185   const gchar *selected_system = NULL;
8186
8187   g_return_val_if_fail (qtdemux != NULL, FALSE);
8188   g_return_val_if_fail (stream != NULL, FALSE);
8189   g_return_val_if_fail (gst_caps_get_size (CUR_STREAM (stream)->caps) == 1,
8190       FALSE);
8191
8192   if (stream->protection_scheme_type != FOURCC_cenc) {
8193     GST_ERROR_OBJECT (qtdemux, "unsupported protection scheme");
8194     return FALSE;
8195   }
8196   if (qtdemux->protection_system_ids == NULL) {
8197     GST_ERROR_OBJECT (qtdemux, "stream is protected using cenc, but no "
8198         "cenc protection system information has been found");
8199     return FALSE;
8200   }
8201
8202   gst_qtdemux_request_protection_context (qtdemux, stream);
8203   if (qtdemux->preferred_protection_system_id != NULL) {
8204     const gchar *preferred_system_array[] =
8205         { qtdemux->preferred_protection_system_id, NULL };
8206
8207     selected_system = gst_protection_select_system (preferred_system_array);
8208
8209     if (selected_system) {
8210       GST_TRACE_OBJECT (qtdemux, "selected preferred system %s",
8211           qtdemux->preferred_protection_system_id);
8212     } else {
8213       GST_WARNING_OBJECT (qtdemux, "could not select preferred system %s "
8214           "because there is no available decryptor",
8215           qtdemux->preferred_protection_system_id);
8216     }
8217   }
8218
8219   if (!selected_system) {
8220     g_ptr_array_add (qtdemux->protection_system_ids, NULL);
8221     selected_system = gst_protection_select_system ((const gchar **)
8222         qtdemux->protection_system_ids->pdata);
8223     g_ptr_array_remove_index (qtdemux->protection_system_ids,
8224         qtdemux->protection_system_ids->len - 1);
8225   }
8226
8227   if (!selected_system) {
8228     GST_ERROR_OBJECT (qtdemux, "stream is protected, but no "
8229         "suitable decryptor element has been found");
8230     return FALSE;
8231   }
8232
8233   GST_DEBUG_OBJECT (qtdemux, "selected protection system is %s",
8234       selected_system);
8235
8236   s = gst_caps_get_structure (CUR_STREAM (stream)->caps, 0);
8237   if (!gst_structure_has_name (s, "application/x-cenc")) {
8238     gst_structure_set (s,
8239         "original-media-type", G_TYPE_STRING, gst_structure_get_name (s),
8240         GST_PROTECTION_SYSTEM_ID_CAPS_FIELD, G_TYPE_STRING, selected_system,
8241         NULL);
8242     gst_structure_set_name (s, "application/x-cenc");
8243   }
8244   return TRUE;
8245 }
8246
8247 static gboolean
8248 gst_qtdemux_configure_stream (GstQTDemux * qtdemux, QtDemuxStream * stream)
8249 {
8250   if (stream->subtype == FOURCC_vide) {
8251     /* fps is calculated base on the duration of the average framerate since
8252      * qt does not have a fixed framerate. */
8253     gboolean fps_available = TRUE;
8254     guint32 first_duration = 0;
8255
8256     if (stream->n_samples > 0)
8257       first_duration = stream->samples[0].duration;
8258
8259     if ((stream->n_samples == 1 && first_duration == 0)
8260         || (qtdemux->fragmented && stream->n_samples_moof == 1)) {
8261       /* still frame */
8262       CUR_STREAM (stream)->fps_n = 0;
8263       CUR_STREAM (stream)->fps_d = 1;
8264     } else {
8265       if (stream->duration == 0 || stream->n_samples < 2) {
8266         CUR_STREAM (stream)->fps_n = stream->timescale;
8267         CUR_STREAM (stream)->fps_d = 1;
8268         fps_available = FALSE;
8269       } else {
8270         GstClockTime avg_duration;
8271         guint64 duration;
8272         guint32 n_samples;
8273
8274         /* duration and n_samples can be updated for fragmented format
8275          * so, framerate of fragmented format is calculated using data in a moof */
8276         if (qtdemux->fragmented && stream->n_samples_moof > 0
8277             && stream->duration_moof > 0) {
8278           n_samples = stream->n_samples_moof;
8279           duration = stream->duration_moof;
8280         } else {
8281           n_samples = stream->n_samples;
8282           duration = stream->duration;
8283         }
8284
8285         /* Calculate a framerate, ignoring the first sample which is sometimes truncated */
8286         /* stream->duration is guint64, timescale, n_samples are guint32 */
8287         avg_duration =
8288             gst_util_uint64_scale_round (duration -
8289             first_duration, GST_SECOND,
8290             (guint64) (stream->timescale) * (n_samples - 1));
8291
8292         GST_LOG_OBJECT (qtdemux,
8293             "Calculating avg sample duration based on stream (or moof) duration %"
8294             G_GUINT64_FORMAT
8295             " minus first sample %u, leaving %d samples gives %"
8296             GST_TIME_FORMAT, duration, first_duration,
8297             n_samples - 1, GST_TIME_ARGS (avg_duration));
8298
8299         gst_video_guess_framerate (avg_duration, &CUR_STREAM (stream)->fps_n,
8300             &CUR_STREAM (stream)->fps_d);
8301
8302         GST_DEBUG_OBJECT (qtdemux,
8303             "Calculating framerate, timescale %u gave fps_n %d fps_d %d",
8304             stream->timescale, CUR_STREAM (stream)->fps_n,
8305             CUR_STREAM (stream)->fps_d);
8306       }
8307     }
8308
8309     if (CUR_STREAM (stream)->caps) {
8310       CUR_STREAM (stream)->caps =
8311           gst_caps_make_writable (CUR_STREAM (stream)->caps);
8312
8313       gst_caps_set_simple (CUR_STREAM (stream)->caps,
8314           "width", G_TYPE_INT, CUR_STREAM (stream)->width,
8315           "height", G_TYPE_INT, CUR_STREAM (stream)->height, NULL);
8316
8317       /* set framerate if calculated framerate is reliable */
8318       if (fps_available) {
8319         gst_caps_set_simple (CUR_STREAM (stream)->caps,
8320             "framerate", GST_TYPE_FRACTION, CUR_STREAM (stream)->fps_n,
8321             CUR_STREAM (stream)->fps_d, NULL);
8322       }
8323
8324       /* calculate pixel-aspect-ratio using display width and height */
8325       GST_DEBUG_OBJECT (qtdemux,
8326           "video size %dx%d, target display size %dx%d",
8327           CUR_STREAM (stream)->width, CUR_STREAM (stream)->height,
8328           stream->display_width, stream->display_height);
8329       /* qt file might have pasp atom */
8330       if (CUR_STREAM (stream)->par_w > 0 && CUR_STREAM (stream)->par_h > 0) {
8331         GST_DEBUG_OBJECT (qtdemux, "par %d:%d", CUR_STREAM (stream)->par_w,
8332             CUR_STREAM (stream)->par_h);
8333         gst_caps_set_simple (CUR_STREAM (stream)->caps, "pixel-aspect-ratio",
8334             GST_TYPE_FRACTION, CUR_STREAM (stream)->par_w,
8335             CUR_STREAM (stream)->par_h, NULL);
8336       } else if (stream->display_width > 0 && stream->display_height > 0
8337           && CUR_STREAM (stream)->width > 0
8338           && CUR_STREAM (stream)->height > 0) {
8339         gint n, d;
8340
8341         /* calculate the pixel aspect ratio using the display and pixel w/h */
8342         n = stream->display_width * CUR_STREAM (stream)->height;
8343         d = stream->display_height * CUR_STREAM (stream)->width;
8344         if (n == d)
8345           n = d = 1;
8346         GST_DEBUG_OBJECT (qtdemux, "setting PAR to %d/%d", n, d);
8347         CUR_STREAM (stream)->par_w = n;
8348         CUR_STREAM (stream)->par_h = d;
8349         gst_caps_set_simple (CUR_STREAM (stream)->caps, "pixel-aspect-ratio",
8350             GST_TYPE_FRACTION, CUR_STREAM (stream)->par_w,
8351             CUR_STREAM (stream)->par_h, NULL);
8352       }
8353
8354       if (CUR_STREAM (stream)->interlace_mode > 0) {
8355         if (CUR_STREAM (stream)->interlace_mode == 1) {
8356           gst_caps_set_simple (CUR_STREAM (stream)->caps, "interlace-mode",
8357               G_TYPE_STRING, "progressive", NULL);
8358         } else if (CUR_STREAM (stream)->interlace_mode == 2) {
8359           gst_caps_set_simple (CUR_STREAM (stream)->caps, "interlace-mode",
8360               G_TYPE_STRING, "interleaved", NULL);
8361           if (CUR_STREAM (stream)->field_order == 9) {
8362             gst_caps_set_simple (CUR_STREAM (stream)->caps, "field-order",
8363                 G_TYPE_STRING, "top-field-first", NULL);
8364           } else if (CUR_STREAM (stream)->field_order == 14) {
8365             gst_caps_set_simple (CUR_STREAM (stream)->caps, "field-order",
8366                 G_TYPE_STRING, "bottom-field-first", NULL);
8367           }
8368         }
8369       }
8370
8371       /* Create incomplete colorimetry here if needed */
8372       if (CUR_STREAM (stream)->colorimetry.range ||
8373           CUR_STREAM (stream)->colorimetry.matrix ||
8374           CUR_STREAM (stream)->colorimetry.transfer
8375           || CUR_STREAM (stream)->colorimetry.primaries) {
8376         gchar *colorimetry =
8377             gst_video_colorimetry_to_string (&CUR_STREAM (stream)->colorimetry);
8378         gst_caps_set_simple (CUR_STREAM (stream)->caps, "colorimetry",
8379             G_TYPE_STRING, colorimetry, NULL);
8380         g_free (colorimetry);
8381       }
8382
8383       if (stream->multiview_mode != GST_VIDEO_MULTIVIEW_MODE_NONE) {
8384         guint par_w = 1, par_h = 1;
8385
8386         if (CUR_STREAM (stream)->par_w > 0 && CUR_STREAM (stream)->par_h > 0) {
8387           par_w = CUR_STREAM (stream)->par_w;
8388           par_h = CUR_STREAM (stream)->par_h;
8389         }
8390
8391         if (gst_video_multiview_guess_half_aspect (stream->multiview_mode,
8392                 CUR_STREAM (stream)->width, CUR_STREAM (stream)->height, par_w,
8393                 par_h)) {
8394           stream->multiview_flags |= GST_VIDEO_MULTIVIEW_FLAGS_HALF_ASPECT;
8395         }
8396
8397         gst_caps_set_simple (CUR_STREAM (stream)->caps,
8398             "multiview-mode", G_TYPE_STRING,
8399             gst_video_multiview_mode_to_caps_string (stream->multiview_mode),
8400             "multiview-flags", GST_TYPE_VIDEO_MULTIVIEW_FLAGSET,
8401             stream->multiview_flags, GST_FLAG_SET_MASK_EXACT, NULL);
8402       }
8403     }
8404   }
8405
8406   else if (stream->subtype == FOURCC_soun) {
8407     if (CUR_STREAM (stream)->caps) {
8408       CUR_STREAM (stream)->caps =
8409           gst_caps_make_writable (CUR_STREAM (stream)->caps);
8410       if (CUR_STREAM (stream)->rate > 0)
8411         gst_caps_set_simple (CUR_STREAM (stream)->caps,
8412             "rate", G_TYPE_INT, (int) CUR_STREAM (stream)->rate, NULL);
8413       if (CUR_STREAM (stream)->n_channels > 0)
8414         gst_caps_set_simple (CUR_STREAM (stream)->caps,
8415             "channels", G_TYPE_INT, CUR_STREAM (stream)->n_channels, NULL);
8416       if (CUR_STREAM (stream)->n_channels > 2) {
8417         /* FIXME: Need to parse the 'chan' atom to get channel layouts
8418          * correctly; this is just the minimum we can do - assume
8419          * we don't actually have any channel positions. */
8420         gst_caps_set_simple (CUR_STREAM (stream)->caps,
8421             "channel-mask", GST_TYPE_BITMASK, G_GUINT64_CONSTANT (0), NULL);
8422       }
8423     }
8424   }
8425
8426   if (stream->pad) {
8427     GstCaps *prev_caps = NULL;
8428
8429     GST_PAD_ELEMENT_PRIVATE (stream->pad) = stream;
8430     gst_pad_set_event_function (stream->pad, gst_qtdemux_handle_src_event);
8431     gst_pad_set_query_function (stream->pad, gst_qtdemux_handle_src_query);
8432     gst_pad_set_active (stream->pad, TRUE);
8433
8434     gst_pad_use_fixed_caps (stream->pad);
8435
8436     if (stream->protected) {
8437       if (!gst_qtdemux_configure_protected_caps (qtdemux, stream)) {
8438         GST_ERROR_OBJECT (qtdemux,
8439             "Failed to configure protected stream caps.");
8440         return FALSE;
8441       }
8442     }
8443
8444     GST_DEBUG_OBJECT (qtdemux, "setting caps %" GST_PTR_FORMAT,
8445         CUR_STREAM (stream)->caps);
8446     if (stream->new_stream) {
8447       GstEvent *event;
8448       GstStreamFlags stream_flags = GST_STREAM_FLAG_NONE;
8449
8450       event =
8451           gst_pad_get_sticky_event (qtdemux->sinkpad, GST_EVENT_STREAM_START,
8452           0);
8453       if (event) {
8454         gst_event_parse_stream_flags (event, &stream_flags);
8455         if (gst_event_parse_group_id (event, &qtdemux->group_id))
8456           qtdemux->have_group_id = TRUE;
8457         else
8458           qtdemux->have_group_id = FALSE;
8459         gst_event_unref (event);
8460       } else if (!qtdemux->have_group_id) {
8461         qtdemux->have_group_id = TRUE;
8462         qtdemux->group_id = gst_util_group_id_next ();
8463       }
8464
8465       stream->new_stream = FALSE;
8466       event = gst_event_new_stream_start (stream->stream_id);
8467       if (qtdemux->have_group_id)
8468         gst_event_set_group_id (event, qtdemux->group_id);
8469       if (stream->disabled)
8470         stream_flags |= GST_STREAM_FLAG_UNSELECT;
8471       if (CUR_STREAM (stream)->sparse) {
8472         stream_flags |= GST_STREAM_FLAG_SPARSE;
8473       } else {
8474         stream_flags &= ~GST_STREAM_FLAG_SPARSE;
8475       }
8476       gst_event_set_stream_flags (event, stream_flags);
8477       gst_pad_push_event (stream->pad, event);
8478     }
8479
8480     prev_caps = gst_pad_get_current_caps (stream->pad);
8481
8482     if (CUR_STREAM (stream)->caps) {
8483       if (!prev_caps
8484           || !gst_caps_is_equal_fixed (prev_caps, CUR_STREAM (stream)->caps)) {
8485         GST_DEBUG_OBJECT (qtdemux, "setting caps %" GST_PTR_FORMAT,
8486             CUR_STREAM (stream)->caps);
8487         gst_pad_set_caps (stream->pad, CUR_STREAM (stream)->caps);
8488       } else {
8489         GST_DEBUG_OBJECT (qtdemux, "ignore duplicated caps");
8490       }
8491     } else {
8492       GST_WARNING_OBJECT (qtdemux, "stream without caps");
8493     }
8494
8495     if (prev_caps)
8496       gst_caps_unref (prev_caps);
8497     stream->new_caps = FALSE;
8498   }
8499   return TRUE;
8500 }
8501
8502 static void
8503 gst_qtdemux_stream_check_and_change_stsd_index (GstQTDemux * demux,
8504     QtDemuxStream * stream)
8505 {
8506   if (stream->cur_stsd_entry_index == stream->stsd_sample_description_id)
8507     return;
8508
8509   GST_DEBUG_OBJECT (stream->pad, "Changing stsd index from '%u' to '%u'",
8510       stream->cur_stsd_entry_index, stream->stsd_sample_description_id);
8511   if (G_UNLIKELY (stream->stsd_sample_description_id >=
8512           stream->stsd_entries_length)) {
8513     GST_ELEMENT_ERROR (demux, STREAM, DEMUX,
8514         (_("This file is invalid and cannot be played.")),
8515         ("New sample description id is out of bounds (%d >= %d)",
8516             stream->stsd_sample_description_id, stream->stsd_entries_length));
8517   } else {
8518     stream->cur_stsd_entry_index = stream->stsd_sample_description_id;
8519     stream->new_caps = TRUE;
8520   }
8521 }
8522
8523 static gboolean
8524 gst_qtdemux_add_stream (GstQTDemux * qtdemux,
8525     QtDemuxStream * stream, GstTagList * list)
8526 {
8527   gboolean ret = TRUE;
8528   /* consistent default for push based mode */
8529   gst_segment_init (&stream->segment, GST_FORMAT_TIME);
8530
8531   if (stream->subtype == FOURCC_vide) {
8532     gchar *name = g_strdup_printf ("video_%u", qtdemux->n_video_streams);
8533
8534     stream->pad =
8535         gst_pad_new_from_static_template (&gst_qtdemux_videosrc_template, name);
8536     g_free (name);
8537
8538     if (!gst_qtdemux_configure_stream (qtdemux, stream)) {
8539       gst_object_unref (stream->pad);
8540       stream->pad = NULL;
8541       ret = FALSE;
8542       goto done;
8543     }
8544
8545     qtdemux->n_video_streams++;
8546   } else if (stream->subtype == FOURCC_soun) {
8547     gchar *name = g_strdup_printf ("audio_%u", qtdemux->n_audio_streams);
8548
8549     stream->pad =
8550         gst_pad_new_from_static_template (&gst_qtdemux_audiosrc_template, name);
8551     g_free (name);
8552     if (!gst_qtdemux_configure_stream (qtdemux, stream)) {
8553       gst_object_unref (stream->pad);
8554       stream->pad = NULL;
8555       ret = FALSE;
8556       goto done;
8557     }
8558     qtdemux->n_audio_streams++;
8559   } else if (stream->subtype == FOURCC_strm) {
8560     GST_DEBUG_OBJECT (qtdemux, "stream type, not creating pad");
8561   } else if (stream->subtype == FOURCC_subp || stream->subtype == FOURCC_text
8562       || stream->subtype == FOURCC_sbtl || stream->subtype == FOURCC_subt) {
8563     gchar *name = g_strdup_printf ("subtitle_%u", qtdemux->n_sub_streams);
8564
8565     stream->pad =
8566         gst_pad_new_from_static_template (&gst_qtdemux_subsrc_template, name);
8567     g_free (name);
8568     if (!gst_qtdemux_configure_stream (qtdemux, stream)) {
8569       gst_object_unref (stream->pad);
8570       stream->pad = NULL;
8571       ret = FALSE;
8572       goto done;
8573     }
8574     qtdemux->n_sub_streams++;
8575   } else if (CUR_STREAM (stream)->caps) {
8576     gchar *name = g_strdup_printf ("video_%u", qtdemux->n_video_streams);
8577
8578     stream->pad =
8579         gst_pad_new_from_static_template (&gst_qtdemux_videosrc_template, name);
8580     g_free (name);
8581     if (!gst_qtdemux_configure_stream (qtdemux, stream)) {
8582       gst_object_unref (stream->pad);
8583       stream->pad = NULL;
8584       ret = FALSE;
8585       goto done;
8586     }
8587     qtdemux->n_video_streams++;
8588   } else {
8589     GST_DEBUG_OBJECT (qtdemux, "unknown stream type");
8590     goto done;
8591   }
8592
8593   if (stream->pad) {
8594     GList *l;
8595
8596     GST_DEBUG_OBJECT (qtdemux, "adding pad %s %p to qtdemux %p",
8597         GST_OBJECT_NAME (stream->pad), stream->pad, qtdemux);
8598     gst_element_add_pad (GST_ELEMENT_CAST (qtdemux), stream->pad);
8599     gst_flow_combiner_add_pad (qtdemux->flowcombiner, stream->pad);
8600
8601     if (stream->stream_tags)
8602       gst_tag_list_unref (stream->stream_tags);
8603     stream->stream_tags = list;
8604     list = NULL;
8605     /* global tags go on each pad anyway */
8606     stream->send_global_tags = TRUE;
8607     /* send upstream GST_EVENT_PROTECTION events that were received before
8608        this source pad was created */
8609     for (l = qtdemux->protection_event_queue.head; l != NULL; l = l->next)
8610       gst_pad_push_event (stream->pad, gst_event_ref (l->data));
8611   }
8612 done:
8613   if (list)
8614     gst_tag_list_unref (list);
8615   return ret;
8616 }
8617
8618 /* find next atom with @fourcc starting at @offset */
8619 static GstFlowReturn
8620 qtdemux_find_atom (GstQTDemux * qtdemux, guint64 * offset,
8621     guint64 * length, guint32 fourcc)
8622 {
8623   GstFlowReturn ret;
8624   guint32 lfourcc;
8625   GstBuffer *buf;
8626
8627   GST_LOG_OBJECT (qtdemux, "finding fourcc %" GST_FOURCC_FORMAT " at offset %"
8628       G_GUINT64_FORMAT, GST_FOURCC_ARGS (fourcc), *offset);
8629
8630   while (TRUE) {
8631     GstMapInfo map;
8632
8633     buf = NULL;
8634     ret = gst_pad_pull_range (qtdemux->sinkpad, *offset, 16, &buf);
8635     if (G_UNLIKELY (ret != GST_FLOW_OK))
8636       goto locate_failed;
8637     if (G_UNLIKELY (gst_buffer_get_size (buf) != 16)) {
8638       /* likely EOF */
8639       ret = GST_FLOW_EOS;
8640       gst_buffer_unref (buf);
8641       goto locate_failed;
8642     }
8643     gst_buffer_map (buf, &map, GST_MAP_READ);
8644     extract_initial_length_and_fourcc (map.data, 16, length, &lfourcc);
8645     gst_buffer_unmap (buf, &map);
8646     gst_buffer_unref (buf);
8647
8648     if (G_UNLIKELY (*length == 0)) {
8649       GST_DEBUG_OBJECT (qtdemux, "invalid length 0");
8650       ret = GST_FLOW_ERROR;
8651       goto locate_failed;
8652     }
8653
8654     if (lfourcc == fourcc) {
8655       GST_DEBUG_OBJECT (qtdemux, "found fourcc at offset %" G_GUINT64_FORMAT,
8656           *offset);
8657       break;
8658     } else {
8659       GST_LOG_OBJECT (qtdemux,
8660           "skipping atom '%" GST_FOURCC_FORMAT "' at %" G_GUINT64_FORMAT,
8661           GST_FOURCC_ARGS (fourcc), *offset);
8662       *offset += *length;
8663     }
8664   }
8665
8666   return GST_FLOW_OK;
8667
8668 locate_failed:
8669   {
8670     /* might simply have had last one */
8671     GST_DEBUG_OBJECT (qtdemux, "fourcc not found");
8672     return ret;
8673   }
8674 }
8675
8676 /* should only do something in pull mode */
8677 /* call with OBJECT lock */
8678 static GstFlowReturn
8679 qtdemux_add_fragmented_samples (GstQTDemux * qtdemux)
8680 {
8681   guint64 length, offset;
8682   GstBuffer *buf = NULL;
8683   GstFlowReturn ret = GST_FLOW_OK;
8684   GstFlowReturn res = GST_FLOW_OK;
8685   GstMapInfo map;
8686
8687   offset = qtdemux->moof_offset;
8688   GST_DEBUG_OBJECT (qtdemux, "next moof at offset %" G_GUINT64_FORMAT, offset);
8689
8690   if (!offset) {
8691     GST_DEBUG_OBJECT (qtdemux, "no next moof");
8692     return GST_FLOW_EOS;
8693   }
8694
8695   /* best not do pull etc with lock held */
8696   GST_OBJECT_UNLOCK (qtdemux);
8697
8698   ret = qtdemux_find_atom (qtdemux, &offset, &length, FOURCC_moof);
8699   if (ret != GST_FLOW_OK)
8700     goto flow_failed;
8701
8702   ret = gst_qtdemux_pull_atom (qtdemux, offset, length, &buf);
8703   if (G_UNLIKELY (ret != GST_FLOW_OK))
8704     goto flow_failed;
8705   gst_buffer_map (buf, &map, GST_MAP_READ);
8706   if (!qtdemux_parse_moof (qtdemux, map.data, map.size, offset, NULL)) {
8707     gst_buffer_unmap (buf, &map);
8708     gst_buffer_unref (buf);
8709     buf = NULL;
8710     goto parse_failed;
8711   }
8712
8713   gst_buffer_unmap (buf, &map);
8714   gst_buffer_unref (buf);
8715   buf = NULL;
8716
8717   offset += length;
8718   /* look for next moof */
8719   ret = qtdemux_find_atom (qtdemux, &offset, &length, FOURCC_moof);
8720   if (G_UNLIKELY (ret != GST_FLOW_OK))
8721     goto flow_failed;
8722
8723 exit:
8724   GST_OBJECT_LOCK (qtdemux);
8725
8726   qtdemux->moof_offset = offset;
8727
8728   return res;
8729
8730 parse_failed:
8731   {
8732     GST_DEBUG_OBJECT (qtdemux, "failed to parse moof");
8733     offset = 0;
8734     res = GST_FLOW_ERROR;
8735     goto exit;
8736   }
8737 flow_failed:
8738   {
8739     /* maybe upstream temporarily flushing */
8740     if (ret != GST_FLOW_FLUSHING) {
8741       GST_DEBUG_OBJECT (qtdemux, "no next moof");
8742       offset = 0;
8743     } else {
8744       GST_DEBUG_OBJECT (qtdemux, "upstream WRONG_STATE");
8745       /* resume at current position next time */
8746     }
8747     res = ret;
8748     goto exit;
8749   }
8750 }
8751
8752 /* initialise bytereaders for stbl sub-atoms */
8753 static gboolean
8754 qtdemux_stbl_init (GstQTDemux * qtdemux, QtDemuxStream * stream, GNode * stbl)
8755 {
8756   stream->stbl_index = -1;      /* no samples have yet been parsed */
8757   stream->sample_index = -1;
8758
8759   /* time-to-sample atom */
8760   if (!qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stts, &stream->stts))
8761     goto corrupt_file;
8762
8763   /* copy atom data into a new buffer for later use */
8764   stream->stts.data = g_memdup (stream->stts.data, stream->stts.size);
8765
8766   /* skip version + flags */
8767   if (!gst_byte_reader_skip (&stream->stts, 1 + 3) ||
8768       !gst_byte_reader_get_uint32_be (&stream->stts, &stream->n_sample_times))
8769     goto corrupt_file;
8770   GST_LOG_OBJECT (qtdemux, "%u timestamp blocks", stream->n_sample_times);
8771
8772   /* make sure there's enough data */
8773   if (!qt_atom_parser_has_chunks (&stream->stts, stream->n_sample_times, 8)) {
8774     stream->n_sample_times = gst_byte_reader_get_remaining (&stream->stts) / 8;
8775     GST_LOG_OBJECT (qtdemux, "overriding to %u timestamp blocks",
8776         stream->n_sample_times);
8777     if (!stream->n_sample_times)
8778       goto corrupt_file;
8779   }
8780
8781   /* sync sample atom */
8782   stream->stps_present = FALSE;
8783   if ((stream->stss_present =
8784           ! !qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stss,
8785               &stream->stss) ? TRUE : FALSE) == TRUE) {
8786     /* copy atom data into a new buffer for later use */
8787     stream->stss.data = g_memdup (stream->stss.data, stream->stss.size);
8788
8789     /* skip version + flags */
8790     if (!gst_byte_reader_skip (&stream->stss, 1 + 3) ||
8791         !gst_byte_reader_get_uint32_be (&stream->stss, &stream->n_sample_syncs))
8792       goto corrupt_file;
8793
8794     if (stream->n_sample_syncs) {
8795       /* make sure there's enough data */
8796       if (!qt_atom_parser_has_chunks (&stream->stss, stream->n_sample_syncs, 4))
8797         goto corrupt_file;
8798     }
8799
8800     /* partial sync sample atom */
8801     if ((stream->stps_present =
8802             ! !qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stps,
8803                 &stream->stps) ? TRUE : FALSE) == TRUE) {
8804       /* copy atom data into a new buffer for later use */
8805       stream->stps.data = g_memdup (stream->stps.data, stream->stps.size);
8806
8807       /* skip version + flags */
8808       if (!gst_byte_reader_skip (&stream->stps, 1 + 3) ||
8809           !gst_byte_reader_get_uint32_be (&stream->stps,
8810               &stream->n_sample_partial_syncs))
8811         goto corrupt_file;
8812
8813       /* if there are no entries, the stss table contains the real
8814        * sync samples */
8815       if (stream->n_sample_partial_syncs) {
8816         /* make sure there's enough data */
8817         if (!qt_atom_parser_has_chunks (&stream->stps,
8818                 stream->n_sample_partial_syncs, 4))
8819           goto corrupt_file;
8820       }
8821     }
8822   }
8823
8824   /* sample size */
8825   if (!qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stsz, &stream->stsz))
8826     goto no_samples;
8827
8828   /* copy atom data into a new buffer for later use */
8829   stream->stsz.data = g_memdup (stream->stsz.data, stream->stsz.size);
8830
8831   /* skip version + flags */
8832   if (!gst_byte_reader_skip (&stream->stsz, 1 + 3) ||
8833       !gst_byte_reader_get_uint32_be (&stream->stsz, &stream->sample_size))
8834     goto corrupt_file;
8835
8836   if (!gst_byte_reader_get_uint32_be (&stream->stsz, &stream->n_samples))
8837     goto corrupt_file;
8838
8839   if (!stream->n_samples)
8840     goto no_samples;
8841
8842   /* sample-to-chunk atom */
8843   if (!qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stsc, &stream->stsc))
8844     goto corrupt_file;
8845
8846   /* copy atom data into a new buffer for later use */
8847   stream->stsc.data = g_memdup (stream->stsc.data, stream->stsc.size);
8848
8849   /* skip version + flags */
8850   if (!gst_byte_reader_skip (&stream->stsc, 1 + 3) ||
8851       !gst_byte_reader_get_uint32_be (&stream->stsc,
8852           &stream->n_samples_per_chunk))
8853     goto corrupt_file;
8854
8855   GST_DEBUG_OBJECT (qtdemux, "n_samples_per_chunk %u",
8856       stream->n_samples_per_chunk);
8857
8858   /* make sure there's enough data */
8859   if (!qt_atom_parser_has_chunks (&stream->stsc, stream->n_samples_per_chunk,
8860           12))
8861     goto corrupt_file;
8862
8863
8864   /* chunk offset */
8865   if (qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stco, &stream->stco))
8866     stream->co_size = sizeof (guint32);
8867   else if (qtdemux_tree_get_child_by_type_full (stbl, FOURCC_co64,
8868           &stream->stco))
8869     stream->co_size = sizeof (guint64);
8870   else
8871     goto corrupt_file;
8872
8873   /* copy atom data into a new buffer for later use */
8874   stream->stco.data = g_memdup (stream->stco.data, stream->stco.size);
8875
8876   /* skip version + flags */
8877   if (!gst_byte_reader_skip (&stream->stco, 1 + 3))
8878     goto corrupt_file;
8879
8880   /* chunks_are_samples == TRUE means treat chunks as samples */
8881   stream->chunks_are_samples = stream->sample_size
8882       && !CUR_STREAM (stream)->sampled;
8883   if (stream->chunks_are_samples) {
8884     /* treat chunks as samples */
8885     if (!gst_byte_reader_get_uint32_be (&stream->stco, &stream->n_samples))
8886       goto corrupt_file;
8887   } else {
8888     /* skip number of entries */
8889     if (!gst_byte_reader_skip (&stream->stco, 4))
8890       goto corrupt_file;
8891
8892     /* make sure there are enough data in the stsz atom */
8893     if (!stream->sample_size) {
8894       /* different sizes for each sample */
8895       if (!qt_atom_parser_has_chunks (&stream->stsz, stream->n_samples, 4))
8896         goto corrupt_file;
8897     }
8898   }
8899
8900   GST_DEBUG_OBJECT (qtdemux, "allocating n_samples %u * %u (%.2f MB)",
8901       stream->n_samples, (guint) sizeof (QtDemuxSample),
8902       stream->n_samples * sizeof (QtDemuxSample) / (1024.0 * 1024.0));
8903
8904   if (stream->n_samples >=
8905       QTDEMUX_MAX_SAMPLE_INDEX_SIZE / sizeof (QtDemuxSample)) {
8906     GST_WARNING_OBJECT (qtdemux, "not allocating index of %d samples, would "
8907         "be larger than %uMB (broken file?)", stream->n_samples,
8908         QTDEMUX_MAX_SAMPLE_INDEX_SIZE >> 20);
8909     return FALSE;
8910   }
8911
8912   g_assert (stream->samples == NULL);
8913   stream->samples = g_try_new0 (QtDemuxSample, stream->n_samples);
8914   if (!stream->samples) {
8915     GST_WARNING_OBJECT (qtdemux, "failed to allocate %d samples",
8916         stream->n_samples);
8917     return FALSE;
8918   }
8919
8920   /* composition time-to-sample */
8921   if ((stream->ctts_present =
8922           ! !qtdemux_tree_get_child_by_type_full (stbl, FOURCC_ctts,
8923               &stream->ctts) ? TRUE : FALSE) == TRUE) {
8924     GstByteReader cslg = GST_BYTE_READER_INIT (NULL, 0);
8925
8926     /* copy atom data into a new buffer for later use */
8927     stream->ctts.data = g_memdup (stream->ctts.data, stream->ctts.size);
8928
8929     /* skip version + flags */
8930     if (!gst_byte_reader_skip (&stream->ctts, 1 + 3)
8931         || !gst_byte_reader_get_uint32_be (&stream->ctts,
8932             &stream->n_composition_times))
8933       goto corrupt_file;
8934
8935     /* make sure there's enough data */
8936     if (!qt_atom_parser_has_chunks (&stream->ctts, stream->n_composition_times,
8937             4 + 4))
8938       goto corrupt_file;
8939
8940     /* This is optional, if missing we iterate the ctts */
8941     if (qtdemux_tree_get_child_by_type_full (stbl, FOURCC_cslg, &cslg)) {
8942       if (!gst_byte_reader_skip (&cslg, 1 + 3)
8943           || !gst_byte_reader_get_uint32_be (&cslg, &stream->cslg_shift)) {
8944         g_free ((gpointer) cslg.data);
8945         goto corrupt_file;
8946       }
8947     } else {
8948       gint32 cslg_least = 0;
8949       guint num_entries, pos;
8950       gint i;
8951
8952       pos = gst_byte_reader_get_pos (&stream->ctts);
8953       num_entries = stream->n_composition_times;
8954
8955       stream->cslg_shift = 0;
8956
8957       for (i = 0; i < num_entries; i++) {
8958         gint32 offset;
8959
8960         gst_byte_reader_skip_unchecked (&stream->ctts, 4);
8961         offset = gst_byte_reader_get_int32_be_unchecked (&stream->ctts);
8962
8963         if (offset < cslg_least)
8964           cslg_least = offset;
8965       }
8966
8967       if (cslg_least < 0)
8968         stream->cslg_shift = ABS (cslg_least);
8969       else
8970         stream->cslg_shift = 0;
8971
8972       /* reset the reader so we can generate sample table */
8973       gst_byte_reader_set_pos (&stream->ctts, pos);
8974     }
8975   } else {
8976     /* Ensure the cslg_shift value is consistent so we can use it
8977      * unconditionnally to produce TS and Segment */
8978     stream->cslg_shift = 0;
8979   }
8980
8981   return TRUE;
8982
8983 corrupt_file:
8984   {
8985     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
8986         (_("This file is corrupt and cannot be played.")), (NULL));
8987     return FALSE;
8988   }
8989 no_samples:
8990   {
8991     gst_qtdemux_stbl_free (stream);
8992     if (!qtdemux->fragmented) {
8993       /* not quite good */
8994       GST_WARNING_OBJECT (qtdemux, "stream has no samples");
8995       return FALSE;
8996     } else {
8997       /* may pick up samples elsewhere */
8998       return TRUE;
8999     }
9000   }
9001 }
9002
9003 /* collect samples from the next sample to be parsed up to sample @n for @stream
9004  * by reading the info from @stbl
9005  *
9006  * This code can be executed from both the streaming thread and the seeking
9007  * thread so it takes the object lock to protect itself
9008  */
9009 static gboolean
9010 qtdemux_parse_samples (GstQTDemux * qtdemux, QtDemuxStream * stream, guint32 n)
9011 {
9012   gint i, j, k;
9013   QtDemuxSample *samples, *first, *cur, *last;
9014   guint32 n_samples_per_chunk;
9015   guint32 n_samples;
9016
9017   GST_LOG_OBJECT (qtdemux, "parsing samples for stream fourcc %"
9018       GST_FOURCC_FORMAT ", pad %s",
9019       GST_FOURCC_ARGS (CUR_STREAM (stream)->fourcc),
9020       stream->pad ? GST_PAD_NAME (stream->pad) : "(NULL)");
9021
9022   n_samples = stream->n_samples;
9023
9024   if (n >= n_samples)
9025     goto out_of_samples;
9026
9027   GST_OBJECT_LOCK (qtdemux);
9028   if (n <= stream->stbl_index)
9029     goto already_parsed;
9030
9031   GST_DEBUG_OBJECT (qtdemux, "parsing up to sample %u", n);
9032
9033   if (!stream->stsz.data) {
9034     /* so we already parsed and passed all the moov samples;
9035      * onto fragmented ones */
9036     g_assert (qtdemux->fragmented);
9037     goto done;
9038   }
9039
9040   /* pointer to the sample table */
9041   samples = stream->samples;
9042
9043   /* starts from -1, moves to the next sample index to parse */
9044   stream->stbl_index++;
9045
9046   /* keep track of the first and last sample to fill */
9047   first = &samples[stream->stbl_index];
9048   last = &samples[n];
9049
9050   if (!stream->chunks_are_samples) {
9051     /* set the sample sizes */
9052     if (stream->sample_size == 0) {
9053       /* different sizes for each sample */
9054       for (cur = first; cur <= last; cur++) {
9055         cur->size = gst_byte_reader_get_uint32_be_unchecked (&stream->stsz);
9056         GST_LOG_OBJECT (qtdemux, "sample %d has size %u",
9057             (guint) (cur - samples), cur->size);
9058       }
9059     } else {
9060       /* samples have the same size */
9061       GST_LOG_OBJECT (qtdemux, "all samples have size %u", stream->sample_size);
9062       for (cur = first; cur <= last; cur++)
9063         cur->size = stream->sample_size;
9064     }
9065   }
9066
9067   n_samples_per_chunk = stream->n_samples_per_chunk;
9068   cur = first;
9069
9070   for (i = stream->stsc_index; i < n_samples_per_chunk; i++) {
9071     guint32 last_chunk;
9072
9073     if (stream->stsc_chunk_index >= stream->last_chunk
9074         || stream->stsc_chunk_index < stream->first_chunk) {
9075       stream->first_chunk =
9076           gst_byte_reader_get_uint32_be_unchecked (&stream->stsc);
9077       stream->samples_per_chunk =
9078           gst_byte_reader_get_uint32_be_unchecked (&stream->stsc);
9079       /* starts from 1 */
9080       stream->stsd_sample_description_id =
9081           gst_byte_reader_get_uint32_be_unchecked (&stream->stsc) - 1;
9082
9083       /* chunk numbers are counted from 1 it seems */
9084       if (G_UNLIKELY (stream->first_chunk == 0))
9085         goto corrupt_file;
9086
9087       --stream->first_chunk;
9088
9089       /* the last chunk of each entry is calculated by taking the first chunk
9090        * of the next entry; except if there is no next, where we fake it with
9091        * INT_MAX */
9092       if (G_UNLIKELY (i == (stream->n_samples_per_chunk - 1))) {
9093         stream->last_chunk = G_MAXUINT32;
9094       } else {
9095         stream->last_chunk =
9096             gst_byte_reader_peek_uint32_be_unchecked (&stream->stsc);
9097         if (G_UNLIKELY (stream->last_chunk == 0))
9098           goto corrupt_file;
9099
9100         --stream->last_chunk;
9101       }
9102
9103       GST_LOG_OBJECT (qtdemux,
9104           "entry %d has first_chunk %d, last_chunk %d, samples_per_chunk %d"
9105           "sample desc ID: %d", i, stream->first_chunk, stream->last_chunk,
9106           stream->samples_per_chunk, stream->stsd_sample_description_id);
9107
9108       if (G_UNLIKELY (stream->last_chunk < stream->first_chunk))
9109         goto corrupt_file;
9110
9111       if (stream->last_chunk != G_MAXUINT32) {
9112         if (!qt_atom_parser_peek_sub (&stream->stco,
9113                 stream->first_chunk * stream->co_size,
9114                 (stream->last_chunk - stream->first_chunk) * stream->co_size,
9115                 &stream->co_chunk))
9116           goto corrupt_file;
9117
9118       } else {
9119         stream->co_chunk = stream->stco;
9120         if (!gst_byte_reader_skip (&stream->co_chunk,
9121                 stream->first_chunk * stream->co_size))
9122           goto corrupt_file;
9123       }
9124
9125       stream->stsc_chunk_index = stream->first_chunk;
9126     }
9127
9128     last_chunk = stream->last_chunk;
9129
9130     if (stream->chunks_are_samples) {
9131       cur = &samples[stream->stsc_chunk_index];
9132
9133       for (j = stream->stsc_chunk_index; j < last_chunk; j++) {
9134         if (j > n) {
9135           /* save state */
9136           stream->stsc_chunk_index = j;
9137           goto done;
9138         }
9139
9140         cur->offset =
9141             qt_atom_parser_get_offset_unchecked (&stream->co_chunk,
9142             stream->co_size);
9143
9144         GST_LOG_OBJECT (qtdemux, "Created entry %d with offset "
9145             "%" G_GUINT64_FORMAT, j, cur->offset);
9146
9147         if (CUR_STREAM (stream)->samples_per_frame > 0 &&
9148             CUR_STREAM (stream)->bytes_per_frame > 0) {
9149           cur->size =
9150               (stream->samples_per_chunk * CUR_STREAM (stream)->n_channels) /
9151               CUR_STREAM (stream)->samples_per_frame *
9152               CUR_STREAM (stream)->bytes_per_frame;
9153         } else {
9154           cur->size = stream->samples_per_chunk;
9155         }
9156
9157         GST_DEBUG_OBJECT (qtdemux,
9158             "keyframe sample %d: timestamp %" GST_TIME_FORMAT ", size %u",
9159             j, GST_TIME_ARGS (QTSTREAMTIME_TO_GSTTIME (stream,
9160                     stream->stco_sample_index)), cur->size);
9161
9162         cur->timestamp = stream->stco_sample_index;
9163         cur->duration = stream->samples_per_chunk;
9164         cur->keyframe = TRUE;
9165         cur++;
9166
9167         stream->stco_sample_index += stream->samples_per_chunk;
9168       }
9169       stream->stsc_chunk_index = j;
9170     } else {
9171       for (j = stream->stsc_chunk_index; j < last_chunk; j++) {
9172         guint32 samples_per_chunk;
9173         guint64 chunk_offset;
9174
9175         if (!stream->stsc_sample_index
9176             && !qt_atom_parser_get_offset (&stream->co_chunk, stream->co_size,
9177                 &stream->chunk_offset))
9178           goto corrupt_file;
9179
9180         samples_per_chunk = stream->samples_per_chunk;
9181         chunk_offset = stream->chunk_offset;
9182
9183         for (k = stream->stsc_sample_index; k < samples_per_chunk; k++) {
9184           GST_LOG_OBJECT (qtdemux, "creating entry %d with offset %"
9185               G_GUINT64_FORMAT " and size %d",
9186               (guint) (cur - samples), chunk_offset, cur->size);
9187
9188           cur->offset = chunk_offset;
9189           chunk_offset += cur->size;
9190           cur++;
9191
9192           if (G_UNLIKELY (cur > last)) {
9193             /* save state */
9194             stream->stsc_sample_index = k + 1;
9195             stream->chunk_offset = chunk_offset;
9196             stream->stsc_chunk_index = j;
9197             goto done2;
9198           }
9199         }
9200         stream->stsc_sample_index = 0;
9201       }
9202       stream->stsc_chunk_index = j;
9203     }
9204     stream->stsc_index++;
9205   }
9206
9207   if (stream->chunks_are_samples)
9208     goto ctts;
9209 done2:
9210   {
9211     guint32 n_sample_times;
9212
9213     n_sample_times = stream->n_sample_times;
9214     cur = first;
9215
9216     for (i = stream->stts_index; i < n_sample_times; i++) {
9217       guint32 stts_samples;
9218       gint32 stts_duration;
9219       gint64 stts_time;
9220
9221       if (stream->stts_sample_index >= stream->stts_samples
9222           || !stream->stts_sample_index) {
9223
9224         stream->stts_samples =
9225             gst_byte_reader_get_uint32_be_unchecked (&stream->stts);
9226         stream->stts_duration =
9227             gst_byte_reader_get_uint32_be_unchecked (&stream->stts);
9228
9229         GST_LOG_OBJECT (qtdemux, "block %d, %u timestamps, duration %u",
9230             i, stream->stts_samples, stream->stts_duration);
9231
9232         stream->stts_sample_index = 0;
9233       }
9234
9235       stts_samples = stream->stts_samples;
9236       stts_duration = stream->stts_duration;
9237       stts_time = stream->stts_time;
9238
9239       for (j = stream->stts_sample_index; j < stts_samples; j++) {
9240         GST_DEBUG_OBJECT (qtdemux,
9241             "sample %d: index %d, timestamp %" GST_TIME_FORMAT,
9242             (guint) (cur - samples), j,
9243             GST_TIME_ARGS (QTSTREAMTIME_TO_GSTTIME (stream, stts_time)));
9244
9245         cur->timestamp = stts_time;
9246         cur->duration = stts_duration;
9247
9248         /* avoid 32-bit wrap-around,
9249          * but still mind possible 'negative' duration */
9250         stts_time += (gint64) stts_duration;
9251         cur++;
9252
9253         if (G_UNLIKELY (cur > last)) {
9254           /* save values */
9255           stream->stts_time = stts_time;
9256           stream->stts_sample_index = j + 1;
9257           if (stream->stts_sample_index >= stream->stts_samples)
9258             stream->stts_index++;
9259           goto done3;
9260         }
9261       }
9262       stream->stts_sample_index = 0;
9263       stream->stts_time = stts_time;
9264       stream->stts_index++;
9265     }
9266     /* fill up empty timestamps with the last timestamp, this can happen when
9267      * the last samples do not decode and so we don't have timestamps for them.
9268      * We however look at the last timestamp to estimate the track length so we
9269      * need something in here. */
9270     for (; cur < last; cur++) {
9271       GST_DEBUG_OBJECT (qtdemux,
9272           "fill sample %d: timestamp %" GST_TIME_FORMAT,
9273           (guint) (cur - samples),
9274           GST_TIME_ARGS (QTSTREAMTIME_TO_GSTTIME (stream, stream->stts_time)));
9275       cur->timestamp = stream->stts_time;
9276       cur->duration = -1;
9277     }
9278   }
9279 done3:
9280   {
9281     /* sample sync, can be NULL */
9282     if (stream->stss_present == TRUE) {
9283       guint32 n_sample_syncs;
9284
9285       n_sample_syncs = stream->n_sample_syncs;
9286
9287       if (!n_sample_syncs) {
9288         GST_DEBUG_OBJECT (qtdemux, "all samples are keyframes");
9289         stream->all_keyframe = TRUE;
9290       } else {
9291         for (i = stream->stss_index; i < n_sample_syncs; i++) {
9292           /* note that the first sample is index 1, not 0 */
9293           guint32 index;
9294
9295           index = gst_byte_reader_get_uint32_be_unchecked (&stream->stss);
9296
9297           if (G_LIKELY (index > 0 && index <= n_samples)) {
9298             index -= 1;
9299             samples[index].keyframe = TRUE;
9300             GST_DEBUG_OBJECT (qtdemux, "samples at %u is keyframe", index);
9301             /* and exit if we have enough samples */
9302             if (G_UNLIKELY (index >= n)) {
9303               i++;
9304               break;
9305             }
9306           }
9307         }
9308         /* save state */
9309         stream->stss_index = i;
9310       }
9311
9312       /* stps marks partial sync frames like open GOP I-Frames */
9313       if (stream->stps_present == TRUE) {
9314         guint32 n_sample_partial_syncs;
9315
9316         n_sample_partial_syncs = stream->n_sample_partial_syncs;
9317
9318         /* if there are no entries, the stss table contains the real
9319          * sync samples */
9320         if (n_sample_partial_syncs) {
9321           for (i = stream->stps_index; i < n_sample_partial_syncs; i++) {
9322             /* note that the first sample is index 1, not 0 */
9323             guint32 index;
9324
9325             index = gst_byte_reader_get_uint32_be_unchecked (&stream->stps);
9326
9327             if (G_LIKELY (index > 0 && index <= n_samples)) {
9328               index -= 1;
9329               samples[index].keyframe = TRUE;
9330               GST_DEBUG_OBJECT (qtdemux, "samples at %u is keyframe", index);
9331               /* and exit if we have enough samples */
9332               if (G_UNLIKELY (index >= n)) {
9333                 i++;
9334                 break;
9335               }
9336             }
9337           }
9338           /* save state */
9339           stream->stps_index = i;
9340         }
9341       }
9342     } else {
9343       /* no stss, all samples are keyframes */
9344       stream->all_keyframe = TRUE;
9345       GST_DEBUG_OBJECT (qtdemux, "setting all keyframes");
9346     }
9347   }
9348
9349 ctts:
9350   /* composition time to sample */
9351   if (stream->ctts_present == TRUE) {
9352     guint32 n_composition_times;
9353     guint32 ctts_count;
9354     gint32 ctts_soffset;
9355
9356     /* Fill in the pts_offsets */
9357     cur = first;
9358     n_composition_times = stream->n_composition_times;
9359
9360     for (i = stream->ctts_index; i < n_composition_times; i++) {
9361       if (stream->ctts_sample_index >= stream->ctts_count
9362           || !stream->ctts_sample_index) {
9363         stream->ctts_count =
9364             gst_byte_reader_get_uint32_be_unchecked (&stream->ctts);
9365         stream->ctts_soffset =
9366             gst_byte_reader_get_int32_be_unchecked (&stream->ctts);
9367         stream->ctts_sample_index = 0;
9368       }
9369
9370       ctts_count = stream->ctts_count;
9371       ctts_soffset = stream->ctts_soffset;
9372
9373       for (j = stream->ctts_sample_index; j < ctts_count; j++) {
9374         cur->pts_offset = ctts_soffset;
9375         cur++;
9376
9377         if (G_UNLIKELY (cur > last)) {
9378           /* save state */
9379           stream->ctts_sample_index = j + 1;
9380           goto done;
9381         }
9382       }
9383       stream->ctts_sample_index = 0;
9384       stream->ctts_index++;
9385     }
9386   }
9387 done:
9388   stream->stbl_index = n;
9389   /* if index has been completely parsed, free data that is no-longer needed */
9390   if (n + 1 == stream->n_samples) {
9391     gst_qtdemux_stbl_free (stream);
9392     GST_DEBUG_OBJECT (qtdemux, "parsed all available samples;");
9393     if (qtdemux->pullbased) {
9394       GST_DEBUG_OBJECT (qtdemux, "checking for more samples");
9395       while (n + 1 == stream->n_samples)
9396         if (qtdemux_add_fragmented_samples (qtdemux) != GST_FLOW_OK)
9397           break;
9398     }
9399   }
9400   GST_OBJECT_UNLOCK (qtdemux);
9401
9402   return TRUE;
9403
9404   /* SUCCESS */
9405 already_parsed:
9406   {
9407     GST_LOG_OBJECT (qtdemux,
9408         "Tried to parse up to sample %u but this sample has already been parsed",
9409         n);
9410     /* if fragmented, there may be more */
9411     if (qtdemux->fragmented && n == stream->stbl_index)
9412       goto done;
9413     GST_OBJECT_UNLOCK (qtdemux);
9414     return TRUE;
9415   }
9416   /* ERRORS */
9417 out_of_samples:
9418   {
9419     GST_LOG_OBJECT (qtdemux,
9420         "Tried to parse up to sample %u but there are only %u samples", n + 1,
9421         stream->n_samples);
9422     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
9423         (_("This file is corrupt and cannot be played.")), (NULL));
9424     return FALSE;
9425   }
9426 corrupt_file:
9427   {
9428     GST_OBJECT_UNLOCK (qtdemux);
9429     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
9430         (_("This file is corrupt and cannot be played.")), (NULL));
9431     return FALSE;
9432   }
9433 }
9434
9435 /* collect all segment info for @stream.
9436  */
9437 static gboolean
9438 qtdemux_parse_segments (GstQTDemux * qtdemux, QtDemuxStream * stream,
9439     GNode * trak)
9440 {
9441   GNode *edts;
9442   /* accept edts if they contain gaps at start and there is only
9443    * one media segment */
9444   gboolean allow_pushbased_edts = TRUE;
9445   gint media_segments_count = 0;
9446
9447   /* parse and prepare segment info from the edit list */
9448   GST_DEBUG_OBJECT (qtdemux, "looking for edit list container");
9449   stream->n_segments = 0;
9450   stream->segments = NULL;
9451   if ((edts = qtdemux_tree_get_child_by_type (trak, FOURCC_edts))) {
9452     GNode *elst;
9453     gint n_segments;
9454     gint segment_number, entry_size;
9455     guint64 time;
9456     GstClockTime stime;
9457     const guint8 *buffer;
9458     guint8 version;
9459     guint32 size;
9460
9461     GST_DEBUG_OBJECT (qtdemux, "looking for edit list");
9462     if (!(elst = qtdemux_tree_get_child_by_type (edts, FOURCC_elst)))
9463       goto done;
9464
9465     buffer = elst->data;
9466
9467     size = QT_UINT32 (buffer);
9468     /* version, flags, n_segments */
9469     if (size < 16) {
9470       GST_WARNING_OBJECT (qtdemux, "Invalid edit list");
9471       goto done;
9472     }
9473     version = QT_UINT8 (buffer + 8);
9474     entry_size = (version == 1) ? 20 : 12;
9475
9476     n_segments = QT_UINT32 (buffer + 12);
9477
9478     if (n_segments > 100000 || size < 16 + n_segments * entry_size) {
9479       GST_WARNING_OBJECT (qtdemux, "Invalid edit list");
9480       goto done;
9481     }
9482
9483     /* we might allocate a bit too much, at least allocate 1 segment */
9484     stream->segments = g_new (QtDemuxSegment, MAX (n_segments, 1));
9485
9486     /* segments always start from 0 */
9487     time = 0;
9488     stime = 0;
9489     buffer += 16;
9490     for (segment_number = 0; segment_number < n_segments; segment_number++) {
9491       guint64 duration;
9492       guint64 media_time;
9493       gboolean empty_edit = FALSE;
9494       QtDemuxSegment *segment;
9495       guint32 rate_int;
9496       GstClockTime media_start = GST_CLOCK_TIME_NONE;
9497
9498       if (version == 1) {
9499         media_time = QT_UINT64 (buffer + 8);
9500         duration = QT_UINT64 (buffer);
9501         if (media_time == G_MAXUINT64)
9502           empty_edit = TRUE;
9503       } else {
9504         media_time = QT_UINT32 (buffer + 4);
9505         duration = QT_UINT32 (buffer);
9506         if (media_time == G_MAXUINT32)
9507           empty_edit = TRUE;
9508       }
9509
9510       if (!empty_edit)
9511         media_start = QTSTREAMTIME_TO_GSTTIME (stream, media_time);
9512
9513       segment = &stream->segments[segment_number];
9514
9515       /* time and duration expressed in global timescale */
9516       segment->time = stime;
9517       if (duration != 0 || empty_edit) {
9518         /* edge case: empty edits with duration=zero are treated here.
9519          * (files should not have these anyway). */
9520
9521         /* add non scaled values so we don't cause roundoff errors */
9522         time += duration;
9523         stime = QTTIME_TO_GSTTIME (qtdemux, time);
9524         segment->duration = stime - segment->time;
9525       } else {
9526         /* zero duration does not imply media_start == media_stop
9527          * but, only specify media_start. The edit ends with the track. */
9528         stime = segment->duration = GST_CLOCK_TIME_NONE;
9529         /* Don't allow more edits after this one. */
9530         n_segments = segment_number + 1;
9531       }
9532       segment->stop_time = stime;
9533
9534       segment->trak_media_start = media_time;
9535       /* media_time expressed in stream timescale */
9536       if (!empty_edit) {
9537         segment->media_start = media_start;
9538         segment->media_stop = GST_CLOCK_TIME_IS_VALID (segment->duration)
9539             ? segment->media_start + segment->duration : GST_CLOCK_TIME_NONE;
9540         media_segments_count++;
9541       } else {
9542         segment->media_start = GST_CLOCK_TIME_NONE;
9543         segment->media_stop = GST_CLOCK_TIME_NONE;
9544       }
9545       rate_int = QT_UINT32 (buffer + ((version == 1) ? 16 : 8));
9546
9547       if (rate_int <= 1) {
9548         /* 0 is not allowed, some programs write 1 instead of the floating point
9549          * value */
9550         GST_WARNING_OBJECT (qtdemux, "found suspicious rate %" G_GUINT32_FORMAT,
9551             rate_int);
9552         segment->rate = 1;
9553       } else {
9554         segment->rate = rate_int / 65536.0;
9555       }
9556
9557       GST_DEBUG_OBJECT (qtdemux, "created segment %d time %" GST_TIME_FORMAT
9558           ", duration %" GST_TIME_FORMAT ", media_start %" GST_TIME_FORMAT
9559           " (%" G_GUINT64_FORMAT ") , media_stop %" GST_TIME_FORMAT
9560           " stop_time %" GST_TIME_FORMAT " rate %g, (%d) timescale %u",
9561           segment_number, GST_TIME_ARGS (segment->time),
9562           GST_TIME_ARGS (segment->duration),
9563           GST_TIME_ARGS (segment->media_start), media_time,
9564           GST_TIME_ARGS (segment->media_stop),
9565           GST_TIME_ARGS (segment->stop_time), segment->rate, rate_int,
9566           stream->timescale);
9567       if (segment->stop_time > qtdemux->segment.stop) {
9568         GST_WARNING_OBJECT (qtdemux, "Segment %d "
9569             " extends to %" GST_TIME_FORMAT
9570             " past the end of the file duration %" GST_TIME_FORMAT
9571             " it will be truncated", segment_number,
9572             GST_TIME_ARGS (segment->stop_time),
9573             GST_TIME_ARGS (qtdemux->segment.stop));
9574         qtdemux->segment.stop = segment->stop_time;
9575       }
9576
9577       buffer += entry_size;
9578     }
9579     GST_DEBUG_OBJECT (qtdemux, "found %d segments", n_segments);
9580     stream->n_segments = n_segments;
9581     if (media_segments_count != 1)
9582       allow_pushbased_edts = FALSE;
9583   }
9584 done:
9585
9586   /* push based does not handle segments, so act accordingly here,
9587    * and warn if applicable */
9588   if (!qtdemux->pullbased && !allow_pushbased_edts) {
9589     GST_WARNING_OBJECT (qtdemux, "streaming; discarding edit list segments");
9590     /* remove and use default one below, we stream like it anyway */
9591     g_free (stream->segments);
9592     stream->segments = NULL;
9593     stream->n_segments = 0;
9594   }
9595
9596   /* no segments, create one to play the complete trak */
9597   if (stream->n_segments == 0) {
9598     GstClockTime stream_duration =
9599         QTSTREAMTIME_TO_GSTTIME (stream, stream->duration);
9600
9601     if (stream->segments == NULL)
9602       stream->segments = g_new (QtDemuxSegment, 1);
9603
9604     /* represent unknown our way */
9605     if (stream_duration == 0)
9606       stream_duration = GST_CLOCK_TIME_NONE;
9607
9608     stream->segments[0].time = 0;
9609     stream->segments[0].stop_time = stream_duration;
9610     stream->segments[0].duration = stream_duration;
9611     stream->segments[0].media_start = 0;
9612     stream->segments[0].media_stop = stream_duration;
9613     stream->segments[0].rate = 1.0;
9614     stream->segments[0].trak_media_start = 0;
9615
9616     GST_DEBUG_OBJECT (qtdemux, "created dummy segment %" GST_TIME_FORMAT,
9617         GST_TIME_ARGS (stream_duration));
9618     stream->n_segments = 1;
9619     stream->dummy_segment = TRUE;
9620   }
9621   GST_DEBUG_OBJECT (qtdemux, "using %d segments", stream->n_segments);
9622
9623   return TRUE;
9624 }
9625
9626 /*
9627  * Parses the stsd atom of a svq3 trak looking for
9628  * the SMI and gama atoms.
9629  */
9630 static void
9631 qtdemux_parse_svq3_stsd_data (GstQTDemux * qtdemux,
9632     const guint8 * stsd_entry_data, const guint8 ** gamma, GstBuffer ** seqh)
9633 {
9634   const guint8 *_gamma = NULL;
9635   GstBuffer *_seqh = NULL;
9636   const guint8 *stsd_data = stsd_entry_data;
9637   guint32 length = QT_UINT32 (stsd_data);
9638   guint16 version;
9639
9640   if (length < 32) {
9641     GST_WARNING_OBJECT (qtdemux, "stsd too short");
9642     goto end;
9643   }
9644
9645   stsd_data += 16;
9646   length -= 16;
9647   version = QT_UINT16 (stsd_data);
9648   if (version == 3) {
9649     if (length >= 70) {
9650       length -= 70;
9651       stsd_data += 70;
9652       while (length > 8) {
9653         guint32 fourcc, size;
9654         const guint8 *data;
9655         size = QT_UINT32 (stsd_data);
9656         fourcc = QT_FOURCC (stsd_data + 4);
9657         data = stsd_data + 8;
9658
9659         if (size == 0) {
9660           GST_WARNING_OBJECT (qtdemux, "Atom of size 0 found, aborting "
9661               "svq3 atom parsing");
9662           goto end;
9663         }
9664
9665         switch (fourcc) {
9666           case FOURCC_gama:{
9667             if (size == 12) {
9668               _gamma = data;
9669             } else {
9670               GST_WARNING_OBJECT (qtdemux, "Unexpected size %" G_GUINT32_FORMAT
9671                   " for gama atom, expected 12", size);
9672             }
9673             break;
9674           }
9675           case FOURCC_SMI_:{
9676             if (size > 16 && QT_FOURCC (data) == FOURCC_SEQH) {
9677               guint32 seqh_size;
9678               if (_seqh != NULL) {
9679                 GST_WARNING_OBJECT (qtdemux, "Unexpected second SEQH SMI atom "
9680                     " found, ignoring");
9681               } else {
9682                 seqh_size = QT_UINT32 (data + 4);
9683                 if (seqh_size > 0) {
9684                   _seqh = gst_buffer_new_and_alloc (seqh_size);
9685                   gst_buffer_fill (_seqh, 0, data + 8, seqh_size);
9686                 }
9687               }
9688             }
9689             break;
9690           }
9691           default:{
9692             GST_WARNING_OBJECT (qtdemux, "Unhandled atom %" GST_FOURCC_FORMAT
9693                 " in SVQ3 entry in stsd atom", GST_FOURCC_ARGS (fourcc));
9694           }
9695         }
9696
9697         if (size <= length) {
9698           length -= size;
9699           stsd_data += size;
9700         }
9701       }
9702     } else {
9703       GST_WARNING_OBJECT (qtdemux, "SVQ3 entry too short in stsd atom");
9704     }
9705   } else {
9706     GST_WARNING_OBJECT (qtdemux, "Unexpected version for SVQ3 entry %"
9707         G_GUINT16_FORMAT, version);
9708     goto end;
9709   }
9710
9711 end:
9712   if (gamma) {
9713     *gamma = _gamma;
9714   }
9715   if (seqh) {
9716     *seqh = _seqh;
9717   } else if (_seqh) {
9718     gst_buffer_unref (_seqh);
9719   }
9720 }
9721
9722 static gchar *
9723 qtdemux_get_rtsp_uri_from_hndl (GstQTDemux * qtdemux, GNode * minf)
9724 {
9725   GNode *dinf;
9726   GstByteReader dref;
9727   gchar *uri = NULL;
9728
9729   /*
9730    * Get 'dinf', to get its child 'dref', that might contain a 'hndl'
9731    * atom that might contain a 'data' atom with the rtsp uri.
9732    * This case was reported in bug #597497, some info about
9733    * the hndl atom can be found in TN1195
9734    */
9735   dinf = qtdemux_tree_get_child_by_type (minf, FOURCC_dinf);
9736   GST_DEBUG_OBJECT (qtdemux, "Trying to obtain rtsp URI for stream trak");
9737
9738   if (dinf) {
9739     guint32 dref_num_entries = 0;
9740     if (qtdemux_tree_get_child_by_type_full (dinf, FOURCC_dref, &dref) &&
9741         gst_byte_reader_skip (&dref, 4) &&
9742         gst_byte_reader_get_uint32_be (&dref, &dref_num_entries)) {
9743       gint i;
9744
9745       /* search dref entries for hndl atom */
9746       for (i = 0; i < dref_num_entries; i++) {
9747         guint32 size = 0, type;
9748         guint8 string_len = 0;
9749         if (gst_byte_reader_get_uint32_be (&dref, &size) &&
9750             qt_atom_parser_get_fourcc (&dref, &type)) {
9751           if (type == FOURCC_hndl) {
9752             GST_DEBUG_OBJECT (qtdemux, "Found hndl atom");
9753
9754             /* skip data reference handle bytes and the
9755              * following pascal string and some extra 4
9756              * bytes I have no idea what are */
9757             if (!gst_byte_reader_skip (&dref, 4) ||
9758                 !gst_byte_reader_get_uint8 (&dref, &string_len) ||
9759                 !gst_byte_reader_skip (&dref, string_len + 4)) {
9760               GST_WARNING_OBJECT (qtdemux, "Failed to parse hndl atom");
9761               break;
9762             }
9763
9764             /* iterate over the atoms to find the data atom */
9765             while (gst_byte_reader_get_remaining (&dref) >= 8) {
9766               guint32 atom_size;
9767               guint32 atom_type;
9768
9769               if (gst_byte_reader_get_uint32_be (&dref, &atom_size) &&
9770                   qt_atom_parser_get_fourcc (&dref, &atom_type)) {
9771                 if (atom_type == FOURCC_data) {
9772                   const guint8 *uri_aux = NULL;
9773
9774                   /* found the data atom that might contain the rtsp uri */
9775                   GST_DEBUG_OBJECT (qtdemux, "Found data atom inside "
9776                       "hndl atom, interpreting it as an URI");
9777                   if (gst_byte_reader_peek_data (&dref, atom_size - 8,
9778                           &uri_aux)) {
9779                     if (g_strstr_len ((gchar *) uri_aux, 7, "rtsp://") != NULL)
9780                       uri = g_strndup ((gchar *) uri_aux, atom_size - 8);
9781                     else
9782                       GST_WARNING_OBJECT (qtdemux, "Data atom in hndl atom "
9783                           "didn't contain a rtsp address");
9784                   } else {
9785                     GST_WARNING_OBJECT (qtdemux, "Failed to get the data "
9786                         "atom contents");
9787                   }
9788                   break;
9789                 }
9790                 /* skipping to the next entry */
9791                 if (!gst_byte_reader_skip (&dref, atom_size - 8))
9792                   break;
9793               } else {
9794                 GST_WARNING_OBJECT (qtdemux, "Failed to parse hndl child "
9795                     "atom header");
9796                 break;
9797               }
9798             }
9799             break;
9800           }
9801           /* skip to the next entry */
9802           if (!gst_byte_reader_skip (&dref, size - 8))
9803             break;
9804         } else {
9805           GST_WARNING_OBJECT (qtdemux, "Error parsing dref atom");
9806         }
9807       }
9808       GST_DEBUG_OBJECT (qtdemux, "Finished parsing dref atom");
9809     }
9810   }
9811   return uri;
9812 }
9813
9814 #define AMR_NB_ALL_MODES        0x81ff
9815 #define AMR_WB_ALL_MODES        0x83ff
9816 static guint
9817 qtdemux_parse_amr_bitrate (GstBuffer * buf, gboolean wb)
9818 {
9819   /* The 'damr' atom is of the form:
9820    *
9821    * | vendor | decoder_ver | mode_set | mode_change_period | frames/sample |
9822    *    32 b       8 b          16 b           8 b                 8 b
9823    *
9824    * The highest set bit of the first 7 (AMR-NB) or 8 (AMR-WB) bits of mode_set
9825    * represents the highest mode used in the stream (and thus the maximum
9826    * bitrate), with a couple of special cases as seen below.
9827    */
9828
9829   /* Map of frame type ID -> bitrate */
9830   static const guint nb_bitrates[] = {
9831     4750, 5150, 5900, 6700, 7400, 7950, 10200, 12200
9832   };
9833   static const guint wb_bitrates[] = {
9834     6600, 8850, 12650, 14250, 15850, 18250, 19850, 23050, 23850
9835   };
9836   GstMapInfo map;
9837   gsize max_mode;
9838   guint16 mode_set;
9839
9840   gst_buffer_map (buf, &map, GST_MAP_READ);
9841
9842   if (map.size != 0x11) {
9843     GST_DEBUG ("Atom should have size 0x11, not %" G_GSIZE_FORMAT, map.size);
9844     goto bad_data;
9845   }
9846
9847   if (QT_FOURCC (map.data + 4) != FOURCC_damr) {
9848     GST_DEBUG ("Unknown atom in %" GST_FOURCC_FORMAT,
9849         GST_FOURCC_ARGS (QT_UINT32 (map.data + 4)));
9850     goto bad_data;
9851   }
9852
9853   mode_set = QT_UINT16 (map.data + 13);
9854
9855   if (mode_set == (wb ? AMR_WB_ALL_MODES : AMR_NB_ALL_MODES))
9856     max_mode = 7 + (wb ? 1 : 0);
9857   else
9858     /* AMR-NB modes fo from 0-7, and AMR-WB modes go from 0-8 */
9859     max_mode = g_bit_nth_msf ((gulong) mode_set & (wb ? 0x1ff : 0xff), -1);
9860
9861   if (max_mode == -1) {
9862     GST_DEBUG ("No mode indication was found (mode set) = %x",
9863         (guint) mode_set);
9864     goto bad_data;
9865   }
9866
9867   gst_buffer_unmap (buf, &map);
9868   return wb ? wb_bitrates[max_mode] : nb_bitrates[max_mode];
9869
9870 bad_data:
9871   gst_buffer_unmap (buf, &map);
9872   return 0;
9873 }
9874
9875 static gboolean
9876 qtdemux_parse_transformation_matrix (GstQTDemux * qtdemux,
9877     GstByteReader * reader, guint32 * matrix, const gchar * atom)
9878 {
9879   /*
9880    * 9 values of 32 bits (fixed point 16.16, except 2 5 and 8 that are 2.30)
9881    * [0 1 2]
9882    * [3 4 5]
9883    * [6 7 8]
9884    */
9885
9886   if (gst_byte_reader_get_remaining (reader) < 36)
9887     return FALSE;
9888
9889   matrix[0] = gst_byte_reader_get_uint32_be_unchecked (reader);
9890   matrix[1] = gst_byte_reader_get_uint32_be_unchecked (reader);
9891   matrix[2] = gst_byte_reader_get_uint32_be_unchecked (reader);
9892   matrix[3] = gst_byte_reader_get_uint32_be_unchecked (reader);
9893   matrix[4] = gst_byte_reader_get_uint32_be_unchecked (reader);
9894   matrix[5] = gst_byte_reader_get_uint32_be_unchecked (reader);
9895   matrix[6] = gst_byte_reader_get_uint32_be_unchecked (reader);
9896   matrix[7] = gst_byte_reader_get_uint32_be_unchecked (reader);
9897   matrix[8] = gst_byte_reader_get_uint32_be_unchecked (reader);
9898
9899   GST_DEBUG_OBJECT (qtdemux, "Transformation matrix from atom %s", atom);
9900   GST_DEBUG_OBJECT (qtdemux, "%u.%u %u.%u %u.%u", matrix[0] >> 16,
9901       matrix[0] & 0xFFFF, matrix[1] >> 16, matrix[1] & 0xFF, matrix[2] >> 16,
9902       matrix[2] & 0xFF);
9903   GST_DEBUG_OBJECT (qtdemux, "%u.%u %u.%u %u.%u", matrix[3] >> 16,
9904       matrix[3] & 0xFFFF, matrix[4] >> 16, matrix[4] & 0xFF, matrix[5] >> 16,
9905       matrix[5] & 0xFF);
9906   GST_DEBUG_OBJECT (qtdemux, "%u.%u %u.%u %u.%u", matrix[6] >> 16,
9907       matrix[6] & 0xFFFF, matrix[7] >> 16, matrix[7] & 0xFF, matrix[8] >> 16,
9908       matrix[8] & 0xFF);
9909
9910   return TRUE;
9911 }
9912
9913 static void
9914 qtdemux_inspect_transformation_matrix (GstQTDemux * qtdemux,
9915     QtDemuxStream * stream, guint32 * matrix, GstTagList ** taglist)
9916 {
9917
9918 /* [a b c]
9919  * [d e f]
9920  * [g h i]
9921  *
9922  * This macro will only compare value abdegh, it expects cfi to have already
9923  * been checked
9924  */
9925 #define QTCHECK_MATRIX(m,a,b,d,e) ((m)[0] == (a << 16) && (m)[1] == (b << 16) && \
9926                                    (m)[3] == (d << 16) && (m)[4] == (e << 16))
9927
9928   /* only handle the cases where the last column has standard values */
9929   if (matrix[2] == 0 && matrix[5] == 0 && matrix[8] == 1 << 30) {
9930     const gchar *rotation_tag = NULL;
9931
9932     /* no rotation needed */
9933     if (QTCHECK_MATRIX (matrix, 1, 0, 0, 1)) {
9934       /* NOP */
9935     } else if (QTCHECK_MATRIX (matrix, 0, 1, G_MAXUINT16, 0)) {
9936       rotation_tag = "rotate-90";
9937     } else if (QTCHECK_MATRIX (matrix, G_MAXUINT16, 0, 0, G_MAXUINT16)) {
9938       rotation_tag = "rotate-180";
9939     } else if (QTCHECK_MATRIX (matrix, 0, G_MAXUINT16, 1, 0)) {
9940       rotation_tag = "rotate-270";
9941     } else {
9942       GST_FIXME_OBJECT (qtdemux, "Unhandled transformation matrix values");
9943     }
9944
9945     GST_DEBUG_OBJECT (qtdemux, "Transformation matrix rotation %s",
9946         rotation_tag);
9947     if (rotation_tag != NULL) {
9948       if (*taglist == NULL)
9949         *taglist = gst_tag_list_new_empty ();
9950       gst_tag_list_add (*taglist, GST_TAG_MERGE_REPLACE,
9951           GST_TAG_IMAGE_ORIENTATION, rotation_tag, NULL);
9952     }
9953   } else {
9954     GST_FIXME_OBJECT (qtdemux, "Unhandled transformation matrix values");
9955   }
9956 }
9957
9958 /* Parses the boxes defined in ISO/IEC 14496-12 that enable support for
9959  * protected streams (sinf, frma, schm and schi); if the protection scheme is
9960  * Common Encryption (cenc), the function will also parse the tenc box (defined
9961  * in ISO/IEC 23001-7). @container points to the node that contains these boxes
9962  * (typically an enc[v|a|t|s] sample entry); the function will set
9963  * @original_fmt to the fourcc of the original unencrypted stream format.
9964  * Returns TRUE if successful; FALSE otherwise. */
9965 static gboolean
9966 qtdemux_parse_protection_scheme_info (GstQTDemux * qtdemux,
9967     QtDemuxStream * stream, GNode * container, guint32 * original_fmt)
9968 {
9969   GNode *sinf;
9970   GNode *frma;
9971   GNode *schm;
9972   GNode *schi;
9973
9974   g_return_val_if_fail (qtdemux != NULL, FALSE);
9975   g_return_val_if_fail (stream != NULL, FALSE);
9976   g_return_val_if_fail (container != NULL, FALSE);
9977   g_return_val_if_fail (original_fmt != NULL, FALSE);
9978
9979   sinf = qtdemux_tree_get_child_by_type (container, FOURCC_sinf);
9980   if (G_UNLIKELY (!sinf)) {
9981     if (stream->protection_scheme_type == FOURCC_cenc) {
9982       GST_ERROR_OBJECT (qtdemux, "sinf box does not contain schi box, which is "
9983           "mandatory for Common Encryption");
9984       return FALSE;
9985     }
9986     return TRUE;
9987   }
9988
9989   frma = qtdemux_tree_get_child_by_type (sinf, FOURCC_frma);
9990   if (G_UNLIKELY (!frma)) {
9991     GST_ERROR_OBJECT (qtdemux, "sinf box does not contain mandatory frma box");
9992     return FALSE;
9993   }
9994
9995   *original_fmt = QT_FOURCC ((const guint8 *) frma->data + 8);
9996   GST_DEBUG_OBJECT (qtdemux, "original stream format: '%" GST_FOURCC_FORMAT "'",
9997       GST_FOURCC_ARGS (*original_fmt));
9998
9999   schm = qtdemux_tree_get_child_by_type (sinf, FOURCC_schm);
10000   if (!schm) {
10001     GST_DEBUG_OBJECT (qtdemux, "sinf box does not contain schm box");
10002     return FALSE;
10003   }
10004   stream->protection_scheme_type = QT_FOURCC ((const guint8 *) schm->data + 12);
10005   stream->protection_scheme_version =
10006       QT_UINT32 ((const guint8 *) schm->data + 16);
10007
10008   GST_DEBUG_OBJECT (qtdemux,
10009       "protection_scheme_type: %" GST_FOURCC_FORMAT ", "
10010       "protection_scheme_version: %#010x",
10011       GST_FOURCC_ARGS (stream->protection_scheme_type),
10012       stream->protection_scheme_version);
10013
10014   schi = qtdemux_tree_get_child_by_type (sinf, FOURCC_schi);
10015   if (!schi) {
10016     GST_DEBUG_OBJECT (qtdemux, "sinf box does not contain schi box");
10017     return FALSE;
10018   }
10019   if (stream->protection_scheme_type == FOURCC_cenc) {
10020     QtDemuxCencSampleSetInfo *info;
10021     GNode *tenc;
10022     const guint8 *tenc_data;
10023     guint32 isEncrypted;
10024     guint8 iv_size;
10025     const guint8 *default_kid;
10026     GstBuffer *kid_buf;
10027
10028     if (G_UNLIKELY (!stream->protection_scheme_info))
10029       stream->protection_scheme_info =
10030           g_malloc0 (sizeof (QtDemuxCencSampleSetInfo));
10031
10032     info = (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
10033
10034     tenc = qtdemux_tree_get_child_by_type (schi, FOURCC_tenc);
10035     if (!tenc) {
10036       GST_ERROR_OBJECT (qtdemux, "schi box does not contain tenc box, "
10037           "which is mandatory for Common Encryption");
10038       return FALSE;
10039     }
10040     tenc_data = (const guint8 *) tenc->data + 12;
10041     isEncrypted = QT_UINT24 (tenc_data);
10042     iv_size = QT_UINT8 (tenc_data + 3);
10043     default_kid = (tenc_data + 4);
10044     kid_buf = gst_buffer_new_allocate (NULL, 16, NULL);
10045     gst_buffer_fill (kid_buf, 0, default_kid, 16);
10046     if (info->default_properties)
10047       gst_structure_free (info->default_properties);
10048     info->default_properties =
10049         gst_structure_new ("application/x-cenc",
10050         "iv_size", G_TYPE_UINT, iv_size,
10051         "encrypted", G_TYPE_BOOLEAN, (isEncrypted == 1),
10052         "kid", GST_TYPE_BUFFER, kid_buf, NULL);
10053     GST_DEBUG_OBJECT (qtdemux, "default sample properties: "
10054         "is_encrypted=%u, iv_size=%u", isEncrypted, iv_size);
10055     gst_buffer_unref (kid_buf);
10056   }
10057   return TRUE;
10058 }
10059
10060 static gint
10061 qtdemux_track_id_compare_func (QtDemuxStream * stream1, QtDemuxStream * stream2)
10062 {
10063   return (gint) stream1->track_id - (gint) stream2->track_id;
10064 }
10065
10066 /* parse the traks.
10067  * With each track we associate a new QtDemuxStream that contains all the info
10068  * about the trak.
10069  * traks that do not decode to something (like strm traks) will not have a pad.
10070  */
10071 static gboolean
10072 qtdemux_parse_trak (GstQTDemux * qtdemux, GNode * trak)
10073 {
10074   GstByteReader tkhd;
10075   int offset;
10076   GNode *mdia;
10077   GNode *mdhd;
10078   GNode *hdlr;
10079   GNode *minf;
10080   GNode *stbl;
10081   GNode *stsd;
10082   GNode *mp4a;
10083   GNode *mp4v;
10084   GNode *esds;
10085   GNode *tref;
10086   GNode *udta;
10087   GNode *svmi;
10088
10089   QtDemuxStream *stream = NULL;
10090   const guint8 *stsd_data;
10091   const guint8 *stsd_entry_data;
10092   guint remaining_stsd_len;
10093   guint stsd_entry_count;
10094   guint stsd_index;
10095   guint16 lang_code;            /* quicktime lang code or packed iso code */
10096   guint32 version;
10097   guint32 tkhd_flags = 0;
10098   guint8 tkhd_version = 0;
10099   guint32 w = 0, h = 0;
10100   guint value_size, stsd_len, len;
10101   guint32 track_id;
10102   guint32 dummy;
10103
10104   GST_DEBUG_OBJECT (qtdemux, "parse_trak");
10105
10106   if (!qtdemux_tree_get_child_by_type_full (trak, FOURCC_tkhd, &tkhd)
10107       || !gst_byte_reader_get_uint8 (&tkhd, &tkhd_version)
10108       || !gst_byte_reader_get_uint24_be (&tkhd, &tkhd_flags))
10109     goto corrupt_file;
10110
10111   /* pick between 64 or 32 bits */
10112   value_size = tkhd_version == 1 ? 8 : 4;
10113   if (!gst_byte_reader_skip (&tkhd, value_size * 2) ||
10114       !gst_byte_reader_get_uint32_be (&tkhd, &track_id))
10115     goto corrupt_file;
10116
10117   /* Check if current moov has duplicated track_id */
10118   if (qtdemux_find_stream (qtdemux, track_id))
10119     goto existing_stream;
10120
10121   stream = _create_stream (qtdemux, track_id);
10122   stream->stream_tags = gst_tag_list_make_writable (stream->stream_tags);
10123
10124   /* need defaults for fragments */
10125   qtdemux_parse_trex (qtdemux, stream, &dummy, &dummy, &dummy);
10126
10127   if ((tkhd_flags & 1) == 0)
10128     stream->disabled = TRUE;
10129
10130   GST_LOG_OBJECT (qtdemux, "track[tkhd] version/flags/id: 0x%02x/%06x/%u",
10131       tkhd_version, tkhd_flags, stream->track_id);
10132
10133   if (!(mdia = qtdemux_tree_get_child_by_type (trak, FOURCC_mdia)))
10134     goto corrupt_file;
10135
10136   if (!(mdhd = qtdemux_tree_get_child_by_type (mdia, FOURCC_mdhd))) {
10137     /* be nice for some crooked mjp2 files that use mhdr for mdhd */
10138     if (qtdemux->major_brand != FOURCC_mjp2 ||
10139         !(mdhd = qtdemux_tree_get_child_by_type (mdia, FOURCC_mhdr)))
10140       goto corrupt_file;
10141   }
10142
10143   len = QT_UINT32 ((guint8 *) mdhd->data);
10144   version = QT_UINT32 ((guint8 *) mdhd->data + 8);
10145   GST_LOG_OBJECT (qtdemux, "track version/flags: %08x", version);
10146   if (version == 0x01000000) {
10147     if (len < 38)
10148       goto corrupt_file;
10149     stream->timescale = QT_UINT32 ((guint8 *) mdhd->data + 28);
10150     stream->duration = QT_UINT64 ((guint8 *) mdhd->data + 32);
10151     lang_code = QT_UINT16 ((guint8 *) mdhd->data + 36);
10152   } else {
10153     if (len < 30)
10154       goto corrupt_file;
10155     stream->timescale = QT_UINT32 ((guint8 *) mdhd->data + 20);
10156     stream->duration = QT_UINT32 ((guint8 *) mdhd->data + 24);
10157     lang_code = QT_UINT16 ((guint8 *) mdhd->data + 28);
10158   }
10159
10160   if (lang_code < 0x400) {
10161     qtdemux_lang_map_qt_code_to_iso (stream->lang_id, lang_code);
10162   } else if (lang_code == 0x7fff) {
10163     stream->lang_id[0] = 0;     /* unspecified */
10164   } else {
10165     stream->lang_id[0] = 0x60 + ((lang_code >> 10) & 0x1F);
10166     stream->lang_id[1] = 0x60 + ((lang_code >> 5) & 0x1F);
10167     stream->lang_id[2] = 0x60 + (lang_code & 0x1F);
10168     stream->lang_id[3] = 0;
10169   }
10170
10171   GST_LOG_OBJECT (qtdemux, "track timescale: %" G_GUINT32_FORMAT,
10172       stream->timescale);
10173   GST_LOG_OBJECT (qtdemux, "track duration: %" G_GUINT64_FORMAT,
10174       stream->duration);
10175   GST_LOG_OBJECT (qtdemux, "track language code/id: 0x%04x/%s",
10176       lang_code, stream->lang_id);
10177
10178   if (G_UNLIKELY (stream->timescale == 0 || qtdemux->timescale == 0))
10179     goto corrupt_file;
10180
10181   if ((tref = qtdemux_tree_get_child_by_type (trak, FOURCC_tref))) {
10182     /* chapters track reference */
10183     GNode *chap = qtdemux_tree_get_child_by_type (tref, FOURCC_chap);
10184     if (chap) {
10185       gsize length = GST_READ_UINT32_BE (chap->data);
10186       if (qtdemux->chapters_track_id)
10187         GST_FIXME_OBJECT (qtdemux, "Multiple CHAP tracks");
10188
10189       if (length >= 12) {
10190         qtdemux->chapters_track_id =
10191             GST_READ_UINT32_BE ((gint8 *) chap->data + 8);
10192       }
10193     }
10194   }
10195
10196   /* fragmented files may have bogus duration in moov */
10197   if (!qtdemux->fragmented &&
10198       qtdemux->duration != G_MAXINT64 && stream->duration != G_MAXINT32) {
10199     guint64 tdur1, tdur2;
10200
10201     /* don't overflow */
10202     tdur1 = stream->timescale * (guint64) qtdemux->duration;
10203     tdur2 = qtdemux->timescale * (guint64) stream->duration;
10204
10205     /* HACK:
10206      * some of those trailers, nowadays, have prologue images that are
10207      * themselves video tracks as well. I haven't really found a way to
10208      * identify those yet, except for just looking at their duration. */
10209     if (tdur1 != 0 && (tdur2 * 10 / tdur1) < 2) {
10210       GST_WARNING_OBJECT (qtdemux,
10211           "Track shorter than 20%% (%" G_GUINT64_FORMAT "/%" G_GUINT32_FORMAT
10212           " vs. %" G_GUINT64_FORMAT "/%" G_GUINT32_FORMAT ") of the stream "
10213           "found, assuming preview image or something; skipping track",
10214           stream->duration, stream->timescale, qtdemux->duration,
10215           qtdemux->timescale);
10216       gst_qtdemux_stream_free (stream);
10217       return TRUE;
10218     }
10219   }
10220
10221   if (!(hdlr = qtdemux_tree_get_child_by_type (mdia, FOURCC_hdlr)))
10222     goto corrupt_file;
10223
10224   GST_LOG_OBJECT (qtdemux, "track type: %" GST_FOURCC_FORMAT,
10225       GST_FOURCC_ARGS (QT_FOURCC ((guint8 *) hdlr->data + 12)));
10226
10227   len = QT_UINT32 ((guint8 *) hdlr->data);
10228   if (len >= 20)
10229     stream->subtype = QT_FOURCC ((guint8 *) hdlr->data + 16);
10230   GST_LOG_OBJECT (qtdemux, "track subtype: %" GST_FOURCC_FORMAT,
10231       GST_FOURCC_ARGS (stream->subtype));
10232
10233   if (!(minf = qtdemux_tree_get_child_by_type (mdia, FOURCC_minf)))
10234     goto corrupt_file;
10235
10236   if (!(stbl = qtdemux_tree_get_child_by_type (minf, FOURCC_stbl)))
10237     goto corrupt_file;
10238
10239   /*parse svmi header if existing */
10240   svmi = qtdemux_tree_get_child_by_type (stbl, FOURCC_svmi);
10241   if (svmi) {
10242     len = QT_UINT32 ((guint8 *) svmi->data);
10243     version = QT_UINT32 ((guint8 *) svmi->data + 8);
10244     if (!version) {
10245       GstVideoMultiviewMode mode = GST_VIDEO_MULTIVIEW_MODE_NONE;
10246       GstVideoMultiviewFlags flags = GST_VIDEO_MULTIVIEW_FLAGS_NONE;
10247       guint8 frame_type, frame_layout;
10248
10249       /* MPEG-A stereo video */
10250       if (qtdemux->major_brand == FOURCC_ss02)
10251         flags |= GST_VIDEO_MULTIVIEW_FLAGS_MIXED_MONO;
10252
10253       frame_type = QT_UINT8 ((guint8 *) svmi->data + 12);
10254       frame_layout = QT_UINT8 ((guint8 *) svmi->data + 13) & 0x01;
10255       switch (frame_type) {
10256         case 0:
10257           mode = GST_VIDEO_MULTIVIEW_MODE_SIDE_BY_SIDE;
10258           break;
10259         case 1:
10260           mode = GST_VIDEO_MULTIVIEW_MODE_ROW_INTERLEAVED;
10261           break;
10262         case 2:
10263           mode = GST_VIDEO_MULTIVIEW_MODE_FRAME_BY_FRAME;
10264           break;
10265         case 3:
10266           /* mode 3 is primary/secondary view sequence, ie
10267            * left/right views in separate tracks. See section 7.2
10268            * of ISO/IEC 23000-11:2009 */
10269           GST_FIXME_OBJECT (qtdemux,
10270               "Implement stereo video in separate streams");
10271       }
10272
10273       if ((frame_layout & 0x1) == 0)
10274         flags |= GST_VIDEO_MULTIVIEW_FLAGS_RIGHT_VIEW_FIRST;
10275
10276       GST_LOG_OBJECT (qtdemux,
10277           "StereoVideo: composition type: %u, is_left_first: %u",
10278           frame_type, frame_layout);
10279       stream->multiview_mode = mode;
10280       stream->multiview_flags = flags;
10281     }
10282   }
10283
10284   /* parse rest of tkhd */
10285   if (stream->subtype == FOURCC_vide) {
10286     guint32 matrix[9];
10287
10288     /* version 1 uses some 64-bit ints */
10289     if (!gst_byte_reader_skip (&tkhd, 20 + value_size))
10290       goto corrupt_file;
10291
10292     if (!qtdemux_parse_transformation_matrix (qtdemux, &tkhd, matrix, "tkhd"))
10293       goto corrupt_file;
10294
10295     if (!gst_byte_reader_get_uint32_be (&tkhd, &w)
10296         || !gst_byte_reader_get_uint32_be (&tkhd, &h))
10297       goto corrupt_file;
10298
10299     qtdemux_inspect_transformation_matrix (qtdemux, stream, matrix,
10300         &stream->stream_tags);
10301   }
10302
10303   /* parse stsd */
10304   if (!(stsd = qtdemux_tree_get_child_by_type (stbl, FOURCC_stsd)))
10305     goto corrupt_file;
10306   stsd_data = (const guint8 *) stsd->data;
10307
10308   /* stsd should at least have one entry */
10309   stsd_len = QT_UINT32 (stsd_data);
10310   if (stsd_len < 24) {
10311     /* .. but skip stream with empty stsd produced by some Vivotek cameras */
10312     if (stream->subtype == FOURCC_vivo) {
10313       gst_qtdemux_stream_free (stream);
10314       return TRUE;
10315     } else {
10316       goto corrupt_file;
10317     }
10318   }
10319
10320   stream->stsd_entries_length = stsd_entry_count = QT_UINT32 (stsd_data + 12);
10321   stream->stsd_entries = g_new0 (QtDemuxStreamStsdEntry, stsd_entry_count);
10322   GST_LOG_OBJECT (qtdemux, "stsd len:           %d", stsd_len);
10323   GST_LOG_OBJECT (qtdemux, "stsd entry count:   %u", stsd_entry_count);
10324
10325   stsd_entry_data = stsd_data + 16;
10326   remaining_stsd_len = stsd_len - 16;
10327   for (stsd_index = 0; stsd_index < stsd_entry_count; stsd_index++) {
10328     guint32 fourcc;
10329     gchar *codec = NULL;
10330     QtDemuxStreamStsdEntry *entry = &stream->stsd_entries[stsd_index];
10331
10332     /* and that entry should fit within stsd */
10333     len = QT_UINT32 (stsd_entry_data);
10334     if (len > remaining_stsd_len)
10335       goto corrupt_file;
10336
10337     entry->fourcc = fourcc = QT_FOURCC (stsd_entry_data + 4);
10338     GST_LOG_OBJECT (qtdemux, "stsd type:          %" GST_FOURCC_FORMAT,
10339         GST_FOURCC_ARGS (entry->fourcc));
10340     GST_LOG_OBJECT (qtdemux, "stsd type len:      %d", len);
10341
10342     if ((fourcc == FOURCC_drms) || (fourcc == FOURCC_drmi))
10343       goto error_encrypted;
10344
10345     if (fourcc == FOURCC_encv || fourcc == FOURCC_enca) {
10346       /* FIXME this looks wrong, there might be multiple children
10347        * with the same type */
10348       GNode *enc = qtdemux_tree_get_child_by_type (stsd, fourcc);
10349       stream->protected = TRUE;
10350       if (!qtdemux_parse_protection_scheme_info (qtdemux, stream, enc, &fourcc))
10351         GST_ERROR_OBJECT (qtdemux, "Failed to parse protection scheme info");
10352     }
10353
10354     if (stream->subtype == FOURCC_vide) {
10355       GNode *colr;
10356       GNode *fiel;
10357       GNode *pasp;
10358       gboolean gray;
10359       gint depth, palette_size, palette_count;
10360       guint32 *palette_data = NULL;
10361
10362       entry->sampled = TRUE;
10363
10364       stream->display_width = w >> 16;
10365       stream->display_height = h >> 16;
10366
10367       offset = 16;
10368       if (len < 86)             /* TODO verify */
10369         goto corrupt_file;
10370
10371       entry->width = QT_UINT16 (stsd_entry_data + offset + 16);
10372       entry->height = QT_UINT16 (stsd_entry_data + offset + 18);
10373       entry->fps_n = 0;         /* this is filled in later */
10374       entry->fps_d = 0;         /* this is filled in later */
10375       entry->bits_per_sample = QT_UINT16 (stsd_entry_data + offset + 66);
10376       entry->color_table_id = QT_UINT16 (stsd_entry_data + offset + 68);
10377
10378       /* if color_table_id is 0, ctab atom must follow; however some files
10379        * produced by TMPEGEnc have color_table_id = 0 and no ctab atom, so
10380        * if color table is not present we'll correct the value */
10381       if (entry->color_table_id == 0 &&
10382           (len < 90
10383               || QT_FOURCC (stsd_entry_data + offset + 70) != FOURCC_ctab)) {
10384         entry->color_table_id = -1;
10385       }
10386
10387       GST_LOG_OBJECT (qtdemux, "width %d, height %d, bps %d, color table id %d",
10388           entry->width, entry->height, entry->bits_per_sample,
10389           entry->color_table_id);
10390
10391       depth = entry->bits_per_sample;
10392
10393       /* more than 32 bits means grayscale */
10394       gray = (depth > 32);
10395       /* low 32 bits specify the depth  */
10396       depth &= 0x1F;
10397
10398       /* different number of palette entries is determined by depth. */
10399       palette_count = 0;
10400       if ((depth == 1) || (depth == 2) || (depth == 4) || (depth == 8))
10401         palette_count = (1 << depth);
10402       palette_size = palette_count * 4;
10403
10404       if (entry->color_table_id) {
10405         switch (palette_count) {
10406           case 0:
10407             break;
10408           case 2:
10409             palette_data = g_memdup (ff_qt_default_palette_2, palette_size);
10410             break;
10411           case 4:
10412             palette_data = g_memdup (ff_qt_default_palette_4, palette_size);
10413             break;
10414           case 16:
10415             if (gray)
10416               palette_data =
10417                   g_memdup (ff_qt_grayscale_palette_16, palette_size);
10418             else
10419               palette_data = g_memdup (ff_qt_default_palette_16, palette_size);
10420             break;
10421           case 256:
10422             if (gray)
10423               palette_data =
10424                   g_memdup (ff_qt_grayscale_palette_256, palette_size);
10425             else
10426               palette_data = g_memdup (ff_qt_default_palette_256, palette_size);
10427             break;
10428           default:
10429             GST_ELEMENT_WARNING (qtdemux, STREAM, DEMUX,
10430                 (_("The video in this file might not play correctly.")),
10431                 ("unsupported palette depth %d", depth));
10432             break;
10433         }
10434       } else {
10435         gint i, j, start, end;
10436
10437         if (len < 94)
10438           goto corrupt_file;
10439
10440         /* read table */
10441         start = QT_UINT32 (stsd_entry_data + offset + 70);
10442         palette_count = QT_UINT16 (stsd_entry_data + offset + 74);
10443         end = QT_UINT16 (stsd_entry_data + offset + 76);
10444
10445         GST_LOG_OBJECT (qtdemux, "start %d, end %d, palette_count %d",
10446             start, end, palette_count);
10447
10448         if (end > 255)
10449           end = 255;
10450         if (start > end)
10451           start = end;
10452
10453         if (len < 94 + (end - start) * 8)
10454           goto corrupt_file;
10455
10456         /* palette is always the same size */
10457         palette_data = g_malloc0 (256 * 4);
10458         palette_size = 256 * 4;
10459
10460         for (j = 0, i = start; i <= end; j++, i++) {
10461           guint32 a, r, g, b;
10462
10463           a = QT_UINT16 (stsd_entry_data + offset + 78 + (j * 8));
10464           r = QT_UINT16 (stsd_entry_data + offset + 80 + (j * 8));
10465           g = QT_UINT16 (stsd_entry_data + offset + 82 + (j * 8));
10466           b = QT_UINT16 (stsd_entry_data + offset + 84 + (j * 8));
10467
10468           palette_data[i] = ((a & 0xff00) << 16) | ((r & 0xff00) << 8) |
10469               (g & 0xff00) | (b >> 8);
10470         }
10471       }
10472
10473       if (entry->caps)
10474         gst_caps_unref (entry->caps);
10475
10476       entry->caps =
10477           qtdemux_video_caps (qtdemux, stream, entry, fourcc, stsd_entry_data,
10478           &codec);
10479       if (G_UNLIKELY (!entry->caps)) {
10480         g_free (palette_data);
10481         goto unknown_stream;
10482       }
10483
10484       if (codec) {
10485         gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
10486             GST_TAG_VIDEO_CODEC, codec, NULL);
10487         g_free (codec);
10488         codec = NULL;
10489       }
10490
10491       if (palette_data) {
10492         GstStructure *s;
10493
10494         if (entry->rgb8_palette)
10495           gst_memory_unref (entry->rgb8_palette);
10496         entry->rgb8_palette = gst_memory_new_wrapped (GST_MEMORY_FLAG_READONLY,
10497             palette_data, palette_size, 0, palette_size, palette_data, g_free);
10498
10499         s = gst_caps_get_structure (entry->caps, 0);
10500
10501         /* non-raw video has a palette_data property. raw video has the palette as
10502          * an extra plane that we append to the output buffers before we push
10503          * them*/
10504         if (!gst_structure_has_name (s, "video/x-raw")) {
10505           GstBuffer *palette;
10506
10507           palette = gst_buffer_new ();
10508           gst_buffer_append_memory (palette, entry->rgb8_palette);
10509           entry->rgb8_palette = NULL;
10510
10511           gst_caps_set_simple (entry->caps, "palette_data",
10512               GST_TYPE_BUFFER, palette, NULL);
10513           gst_buffer_unref (palette);
10514         }
10515       } else if (palette_count != 0) {
10516         GST_ELEMENT_WARNING (qtdemux, STREAM, NOT_IMPLEMENTED,
10517             (NULL), ("Unsupported palette depth %d", depth));
10518       }
10519
10520       GST_LOG_OBJECT (qtdemux, "frame count:   %u",
10521           QT_UINT16 (stsd_entry_data + offset + 32));
10522
10523       esds = NULL;
10524       pasp = NULL;
10525       colr = NULL;
10526       fiel = NULL;
10527       /* pick 'the' stsd child */
10528       mp4v = qtdemux_tree_get_child_by_index (stsd, stsd_index);
10529       if (!stream->protected) {
10530         if (QTDEMUX_TREE_NODE_FOURCC (mp4v) != fourcc) {
10531           mp4v = NULL;
10532         }
10533       } else {
10534         if (QTDEMUX_TREE_NODE_FOURCC (mp4v) != FOURCC_encv) {
10535           mp4v = NULL;
10536         }
10537       }
10538
10539       if (mp4v) {
10540         esds = qtdemux_tree_get_child_by_type (mp4v, FOURCC_esds);
10541         pasp = qtdemux_tree_get_child_by_type (mp4v, FOURCC_pasp);
10542         colr = qtdemux_tree_get_child_by_type (mp4v, FOURCC_colr);
10543         fiel = qtdemux_tree_get_child_by_type (mp4v, FOURCC_fiel);
10544       }
10545
10546       if (pasp) {
10547         const guint8 *pasp_data = (const guint8 *) pasp->data;
10548         gint len = QT_UINT32 (pasp_data);
10549
10550         if (len == 16) {
10551           CUR_STREAM (stream)->par_w = QT_UINT32 (pasp_data + 8);
10552           CUR_STREAM (stream)->par_h = QT_UINT32 (pasp_data + 12);
10553         } else {
10554           CUR_STREAM (stream)->par_w = 0;
10555           CUR_STREAM (stream)->par_h = 0;
10556         }
10557       } else {
10558         CUR_STREAM (stream)->par_w = 0;
10559         CUR_STREAM (stream)->par_h = 0;
10560       }
10561
10562       if (fiel) {
10563         const guint8 *fiel_data = (const guint8 *) fiel->data;
10564         gint len = QT_UINT32 (fiel_data);
10565
10566         if (len == 10) {
10567           CUR_STREAM (stream)->interlace_mode = GST_READ_UINT8 (fiel_data + 8);
10568           CUR_STREAM (stream)->field_order = GST_READ_UINT8 (fiel_data + 9);
10569         }
10570       }
10571
10572       if (colr) {
10573         const guint8 *colr_data = (const guint8 *) colr->data;
10574         gint len = QT_UINT32 (colr_data);
10575
10576         if (len == 19 || len == 18) {
10577           guint32 color_type = GST_READ_UINT32_LE (colr_data + 8);
10578
10579           if (color_type == FOURCC_nclx || color_type == FOURCC_nclc) {
10580             guint16 primaries = GST_READ_UINT16_BE (colr_data + 12);
10581             guint16 transfer_function = GST_READ_UINT16_BE (colr_data + 14);
10582             guint16 matrix = GST_READ_UINT16_BE (colr_data + 16);
10583             gboolean full_range = len == 19 ? colr_data[17] >> 7 : FALSE;
10584
10585             switch (primaries) {
10586               case 1:
10587                 CUR_STREAM (stream)->colorimetry.primaries =
10588                     GST_VIDEO_COLOR_PRIMARIES_BT709;
10589                 break;
10590               case 5:
10591                 CUR_STREAM (stream)->colorimetry.primaries =
10592                     GST_VIDEO_COLOR_PRIMARIES_BT470BG;
10593                 break;
10594               case 6:
10595                 CUR_STREAM (stream)->colorimetry.primaries =
10596                     GST_VIDEO_COLOR_PRIMARIES_SMPTE170M;
10597                 break;
10598               case 9:
10599                 CUR_STREAM (stream)->colorimetry.primaries =
10600                     GST_VIDEO_COLOR_PRIMARIES_BT2020;
10601                 break;
10602               default:
10603                 break;
10604             }
10605
10606             switch (transfer_function) {
10607               case 1:
10608                 CUR_STREAM (stream)->colorimetry.transfer =
10609                     GST_VIDEO_TRANSFER_BT709;
10610                 break;
10611               case 7:
10612                 CUR_STREAM (stream)->colorimetry.transfer =
10613                     GST_VIDEO_TRANSFER_SMPTE240M;
10614                 break;
10615               default:
10616                 break;
10617             }
10618
10619             switch (matrix) {
10620               case 1:
10621                 CUR_STREAM (stream)->colorimetry.matrix =
10622                     GST_VIDEO_COLOR_MATRIX_BT709;
10623                 break;
10624               case 6:
10625                 CUR_STREAM (stream)->colorimetry.matrix =
10626                     GST_VIDEO_COLOR_MATRIX_BT601;
10627                 break;
10628               case 7:
10629                 CUR_STREAM (stream)->colorimetry.matrix =
10630                     GST_VIDEO_COLOR_MATRIX_SMPTE240M;
10631                 break;
10632               case 9:
10633                 CUR_STREAM (stream)->colorimetry.matrix =
10634                     GST_VIDEO_COLOR_MATRIX_BT2020;
10635                 break;
10636               default:
10637                 break;
10638             }
10639
10640             CUR_STREAM (stream)->colorimetry.range =
10641                 full_range ? GST_VIDEO_COLOR_RANGE_0_255 :
10642                 GST_VIDEO_COLOR_RANGE_16_235;
10643           } else {
10644             GST_DEBUG_OBJECT (qtdemux, "Unsupported color type");
10645           }
10646         } else {
10647           GST_WARNING_OBJECT (qtdemux, "Invalid colr atom size");
10648         }
10649       }
10650
10651       if (esds) {
10652         gst_qtdemux_handle_esds (qtdemux, stream, entry, esds,
10653             stream->stream_tags);
10654       } else {
10655         switch (fourcc) {
10656           case FOURCC_H264:
10657           case FOURCC_avc1:
10658           case FOURCC_avc3:
10659           {
10660             gint len = QT_UINT32 (stsd_entry_data) - 0x56;
10661             const guint8 *avc_data = stsd_entry_data + 0x56;
10662
10663             /* find avcC */
10664             while (len >= 0x8) {
10665               gint size;
10666
10667               if (QT_UINT32 (avc_data) <= len)
10668                 size = QT_UINT32 (avc_data) - 0x8;
10669               else
10670                 size = len - 0x8;
10671
10672               if (size < 1)
10673                 /* No real data, so break out */
10674                 break;
10675
10676               switch (QT_FOURCC (avc_data + 0x4)) {
10677                 case FOURCC_avcC:
10678                 {
10679                   /* parse, if found */
10680                   GstBuffer *buf;
10681
10682                   GST_DEBUG_OBJECT (qtdemux, "found avcC codec_data in stsd");
10683
10684                   /* First 4 bytes are the length of the atom, the next 4 bytes
10685                    * are the fourcc, the next 1 byte is the version, and the
10686                    * subsequent bytes are profile_tier_level structure like data. */
10687                   gst_codec_utils_h264_caps_set_level_and_profile (entry->caps,
10688                       avc_data + 8 + 1, size - 1);
10689                   buf = gst_buffer_new_and_alloc (size);
10690                   gst_buffer_fill (buf, 0, avc_data + 0x8, size);
10691                   gst_caps_set_simple (entry->caps,
10692                       "codec_data", GST_TYPE_BUFFER, buf, NULL);
10693                   gst_buffer_unref (buf);
10694
10695                   break;
10696                 }
10697                 case FOURCC_strf:
10698                 {
10699                   GstBuffer *buf;
10700
10701                   GST_DEBUG_OBJECT (qtdemux, "found strf codec_data in stsd");
10702
10703                   /* First 4 bytes are the length of the atom, the next 4 bytes
10704                    * are the fourcc, next 40 bytes are BITMAPINFOHEADER,
10705                    * next 1 byte is the version, and the
10706                    * subsequent bytes are sequence parameter set like data. */
10707
10708                   size -= 40;   /* we'll be skipping BITMAPINFOHEADER */
10709                   if (size > 1) {
10710                     gst_codec_utils_h264_caps_set_level_and_profile
10711                         (entry->caps, avc_data + 8 + 40 + 1, size - 1);
10712
10713                     buf = gst_buffer_new_and_alloc (size);
10714                     gst_buffer_fill (buf, 0, avc_data + 8 + 40, size);
10715                     gst_caps_set_simple (entry->caps,
10716                         "codec_data", GST_TYPE_BUFFER, buf, NULL);
10717                     gst_buffer_unref (buf);
10718                   }
10719                   break;
10720                 }
10721                 case FOURCC_btrt:
10722                 {
10723                   guint avg_bitrate, max_bitrate;
10724
10725                   /* bufferSizeDB, maxBitrate and avgBitrate - 4 bytes each */
10726                   if (size < 12)
10727                     break;
10728
10729                   max_bitrate = QT_UINT32 (avc_data + 0xc);
10730                   avg_bitrate = QT_UINT32 (avc_data + 0x10);
10731
10732                   if (!max_bitrate && !avg_bitrate)
10733                     break;
10734
10735                   /* Some muxers seem to swap the average and maximum bitrates
10736                    * (I'm looking at you, YouTube), so we swap for sanity. */
10737                   if (max_bitrate > 0 && max_bitrate < avg_bitrate) {
10738                     guint temp = avg_bitrate;
10739
10740                     avg_bitrate = max_bitrate;
10741                     max_bitrate = temp;
10742                   }
10743
10744                   if (max_bitrate > 0 && max_bitrate < G_MAXUINT32) {
10745                     gst_tag_list_add (stream->stream_tags,
10746                         GST_TAG_MERGE_REPLACE, GST_TAG_MAXIMUM_BITRATE,
10747                         max_bitrate, NULL);
10748                   }
10749                   if (avg_bitrate > 0 && avg_bitrate < G_MAXUINT32) {
10750                     gst_tag_list_add (stream->stream_tags,
10751                         GST_TAG_MERGE_REPLACE, GST_TAG_BITRATE, avg_bitrate,
10752                         NULL);
10753                   }
10754
10755                   break;
10756                 }
10757
10758                 default:
10759                   break;
10760               }
10761
10762               len -= size + 8;
10763               avc_data += size + 8;
10764             }
10765
10766             break;
10767           }
10768           case FOURCC_H265:
10769           case FOURCC_hvc1:
10770           case FOURCC_hev1:
10771           {
10772             gint len = QT_UINT32 (stsd_entry_data) - 0x56;
10773             const guint8 *hevc_data = stsd_entry_data + 0x56;
10774
10775             /* find hevc */
10776             while (len >= 0x8) {
10777               gint size;
10778
10779               if (QT_UINT32 (hevc_data) <= len)
10780                 size = QT_UINT32 (hevc_data) - 0x8;
10781               else
10782                 size = len - 0x8;
10783
10784               if (size < 1)
10785                 /* No real data, so break out */
10786                 break;
10787
10788               switch (QT_FOURCC (hevc_data + 0x4)) {
10789                 case FOURCC_hvcC:
10790                 {
10791                   /* parse, if found */
10792                   GstBuffer *buf;
10793
10794                   GST_DEBUG_OBJECT (qtdemux, "found hvcC codec_data in stsd");
10795
10796                   /* First 4 bytes are the length of the atom, the next 4 bytes
10797                    * are the fourcc, the next 1 byte is the version, and the
10798                    * subsequent bytes are sequence parameter set like data. */
10799                   gst_codec_utils_h265_caps_set_level_tier_and_profile
10800                       (entry->caps, hevc_data + 8 + 1, size - 1);
10801
10802                   buf = gst_buffer_new_and_alloc (size);
10803                   gst_buffer_fill (buf, 0, hevc_data + 0x8, size);
10804                   gst_caps_set_simple (entry->caps,
10805                       "codec_data", GST_TYPE_BUFFER, buf, NULL);
10806                   gst_buffer_unref (buf);
10807                   break;
10808                 }
10809                 default:
10810                   break;
10811               }
10812               len -= size + 8;
10813               hevc_data += size + 8;
10814             }
10815             break;
10816           }
10817           case FOURCC_mp4v:
10818           case FOURCC_MP4V:
10819           case FOURCC_fmp4:
10820           case FOURCC_FMP4:
10821           case FOURCC_xvid:
10822           case FOURCC_XVID:
10823           {
10824             GNode *glbl;
10825
10826             GST_DEBUG_OBJECT (qtdemux, "found %" GST_FOURCC_FORMAT,
10827                 GST_FOURCC_ARGS (fourcc));
10828
10829             /* codec data might be in glbl extension atom */
10830             glbl = mp4v ?
10831                 qtdemux_tree_get_child_by_type (mp4v, FOURCC_glbl) : NULL;
10832             if (glbl) {
10833               guint8 *data;
10834               GstBuffer *buf;
10835               gint len;
10836
10837               GST_DEBUG_OBJECT (qtdemux, "found glbl data in stsd");
10838               data = glbl->data;
10839               len = QT_UINT32 (data);
10840               if (len > 0x8) {
10841                 len -= 0x8;
10842                 buf = gst_buffer_new_and_alloc (len);
10843                 gst_buffer_fill (buf, 0, data + 8, len);
10844                 gst_caps_set_simple (entry->caps,
10845                     "codec_data", GST_TYPE_BUFFER, buf, NULL);
10846                 gst_buffer_unref (buf);
10847               }
10848             }
10849             break;
10850           }
10851           case FOURCC_mjp2:
10852           {
10853             /* see annex I of the jpeg2000 spec */
10854             GNode *jp2h, *ihdr, *colr, *mjp2, *field, *prefix, *cmap, *cdef;
10855             const guint8 *data;
10856             const gchar *colorspace = NULL;
10857             gint ncomp = 0;
10858             guint32 ncomp_map = 0;
10859             gint32 *comp_map = NULL;
10860             guint32 nchan_def = 0;
10861             gint32 *chan_def = NULL;
10862
10863             GST_DEBUG_OBJECT (qtdemux, "found mjp2");
10864             /* some required atoms */
10865             mjp2 = qtdemux_tree_get_child_by_index (stsd, stsd_index);
10866             if (!mjp2)
10867               break;
10868             jp2h = qtdemux_tree_get_child_by_type (mjp2, FOURCC_jp2h);
10869             if (!jp2h)
10870               break;
10871
10872             /* number of components; redundant with info in codestream, but useful
10873                to a muxer */
10874             ihdr = qtdemux_tree_get_child_by_type (jp2h, FOURCC_ihdr);
10875             if (!ihdr || QT_UINT32 (ihdr->data) != 22)
10876               break;
10877             ncomp = QT_UINT16 (((guint8 *) ihdr->data) + 16);
10878
10879             colr = qtdemux_tree_get_child_by_type (jp2h, FOURCC_colr);
10880             if (!colr)
10881               break;
10882             GST_DEBUG_OBJECT (qtdemux, "found colr");
10883             /* extract colour space info */
10884             if (QT_UINT8 ((guint8 *) colr->data + 8) == 1) {
10885               switch (QT_UINT32 ((guint8 *) colr->data + 11)) {
10886                 case 16:
10887                   colorspace = "sRGB";
10888                   break;
10889                 case 17:
10890                   colorspace = "GRAY";
10891                   break;
10892                 case 18:
10893                   colorspace = "sYUV";
10894                   break;
10895                 default:
10896                   colorspace = NULL;
10897                   break;
10898               }
10899             }
10900             if (!colorspace)
10901               /* colr is required, and only values 16, 17, and 18 are specified,
10902                  so error if we have no colorspace */
10903               break;
10904
10905             /* extract component mapping */
10906             cmap = qtdemux_tree_get_child_by_type (jp2h, FOURCC_cmap);
10907             if (cmap) {
10908               guint32 cmap_len = 0;
10909               int i;
10910               cmap_len = QT_UINT32 (cmap->data);
10911               if (cmap_len >= 8) {
10912                 /* normal box, subtract off header */
10913                 cmap_len -= 8;
10914                 /* cmap: { u16 cmp; u8 mtyp; u8 pcol; }* */
10915                 if (cmap_len % 4 == 0) {
10916                   ncomp_map = (cmap_len / 4);
10917                   comp_map = g_new0 (gint32, ncomp_map);
10918                   for (i = 0; i < ncomp_map; i++) {
10919                     guint16 cmp;
10920                     guint8 mtyp, pcol;
10921                     cmp = QT_UINT16 (((guint8 *) cmap->data) + 8 + i * 4);
10922                     mtyp = QT_UINT8 (((guint8 *) cmap->data) + 8 + i * 4 + 2);
10923                     pcol = QT_UINT8 (((guint8 *) cmap->data) + 8 + i * 4 + 3);
10924                     comp_map[i] = (mtyp << 24) | (pcol << 16) | cmp;
10925                   }
10926                 }
10927               }
10928             }
10929             /* extract channel definitions */
10930             cdef = qtdemux_tree_get_child_by_type (jp2h, FOURCC_cdef);
10931             if (cdef) {
10932               guint32 cdef_len = 0;
10933               int i;
10934               cdef_len = QT_UINT32 (cdef->data);
10935               if (cdef_len >= 10) {
10936                 /* normal box, subtract off header and len */
10937                 cdef_len -= 10;
10938                 /* cdef: u16 n; { u16 cn; u16 typ; u16 asoc; }* */
10939                 if (cdef_len % 6 == 0) {
10940                   nchan_def = (cdef_len / 6);
10941                   chan_def = g_new0 (gint32, nchan_def);
10942                   for (i = 0; i < nchan_def; i++)
10943                     chan_def[i] = -1;
10944                   for (i = 0; i < nchan_def; i++) {
10945                     guint16 cn, typ, asoc;
10946                     cn = QT_UINT16 (((guint8 *) cdef->data) + 10 + i * 6);
10947                     typ = QT_UINT16 (((guint8 *) cdef->data) + 10 + i * 6 + 2);
10948                     asoc = QT_UINT16 (((guint8 *) cdef->data) + 10 + i * 6 + 4);
10949                     if (cn < nchan_def) {
10950                       switch (typ) {
10951                         case 0:
10952                           chan_def[cn] = asoc;
10953                           break;
10954                         case 1:
10955                           chan_def[cn] = 0;     /* alpha */
10956                           break;
10957                         default:
10958                           chan_def[cn] = -typ;
10959                       }
10960                     }
10961                   }
10962                 }
10963               }
10964             }
10965
10966             gst_caps_set_simple (entry->caps,
10967                 "num-components", G_TYPE_INT, ncomp, NULL);
10968             gst_caps_set_simple (entry->caps,
10969                 "colorspace", G_TYPE_STRING, colorspace, NULL);
10970
10971             if (comp_map) {
10972               GValue arr = { 0, };
10973               GValue elt = { 0, };
10974               int i;
10975               g_value_init (&arr, GST_TYPE_ARRAY);
10976               g_value_init (&elt, G_TYPE_INT);
10977               for (i = 0; i < ncomp_map; i++) {
10978                 g_value_set_int (&elt, comp_map[i]);
10979                 gst_value_array_append_value (&arr, &elt);
10980               }
10981               gst_structure_set_value (gst_caps_get_structure (entry->caps, 0),
10982                   "component-map", &arr);
10983               g_value_unset (&elt);
10984               g_value_unset (&arr);
10985               g_free (comp_map);
10986             }
10987
10988             if (chan_def) {
10989               GValue arr = { 0, };
10990               GValue elt = { 0, };
10991               int i;
10992               g_value_init (&arr, GST_TYPE_ARRAY);
10993               g_value_init (&elt, G_TYPE_INT);
10994               for (i = 0; i < nchan_def; i++) {
10995                 g_value_set_int (&elt, chan_def[i]);
10996                 gst_value_array_append_value (&arr, &elt);
10997               }
10998               gst_structure_set_value (gst_caps_get_structure (entry->caps, 0),
10999                   "channel-definitions", &arr);
11000               g_value_unset (&elt);
11001               g_value_unset (&arr);
11002               g_free (chan_def);
11003             }
11004
11005             /* some optional atoms */
11006             field = qtdemux_tree_get_child_by_type (mjp2, FOURCC_fiel);
11007             prefix = qtdemux_tree_get_child_by_type (mjp2, FOURCC_jp2x);
11008
11009             /* indicate possible fields in caps */
11010             if (field) {
11011               data = (guint8 *) field->data + 8;
11012               if (*data != 1)
11013                 gst_caps_set_simple (entry->caps, "fields", G_TYPE_INT,
11014                     (gint) * data, NULL);
11015             }
11016             /* add codec_data if provided */
11017             if (prefix) {
11018               GstBuffer *buf;
11019               gint len;
11020
11021               GST_DEBUG_OBJECT (qtdemux, "found prefix data in stsd");
11022               data = prefix->data;
11023               len = QT_UINT32 (data);
11024               if (len > 0x8) {
11025                 len -= 0x8;
11026                 buf = gst_buffer_new_and_alloc (len);
11027                 gst_buffer_fill (buf, 0, data + 8, len);
11028                 gst_caps_set_simple (entry->caps,
11029                     "codec_data", GST_TYPE_BUFFER, buf, NULL);
11030                 gst_buffer_unref (buf);
11031               }
11032             }
11033             break;
11034           }
11035           case FOURCC_SVQ3:
11036           case FOURCC_VP31:
11037           {
11038             GstBuffer *buf;
11039             GstBuffer *seqh = NULL;
11040             const guint8 *gamma_data = NULL;
11041             gint len = QT_UINT32 (stsd_data);   /* FIXME review - why put the whole stsd in codec data? */
11042
11043             qtdemux_parse_svq3_stsd_data (qtdemux, stsd_entry_data, &gamma_data,
11044                 &seqh);
11045             if (gamma_data) {
11046               gst_caps_set_simple (entry->caps, "applied-gamma", G_TYPE_DOUBLE,
11047                   QT_FP32 (gamma_data), NULL);
11048             }
11049             if (seqh) {
11050               /* sorry for the bad name, but we don't know what this is, other
11051                * than its own fourcc */
11052               gst_caps_set_simple (entry->caps, "seqh", GST_TYPE_BUFFER, seqh,
11053                   NULL);
11054               gst_buffer_unref (seqh);
11055             }
11056
11057             GST_DEBUG_OBJECT (qtdemux, "found codec_data in stsd");
11058             buf = gst_buffer_new_and_alloc (len);
11059             gst_buffer_fill (buf, 0, stsd_data, len);
11060             gst_caps_set_simple (entry->caps,
11061                 "codec_data", GST_TYPE_BUFFER, buf, NULL);
11062             gst_buffer_unref (buf);
11063             break;
11064           }
11065           case FOURCC_jpeg:
11066           {
11067             /* https://developer.apple.com/standards/qtff-2001.pdf,
11068              * page 92, "Video Sample Description", under table 3.1 */
11069             GstByteReader br;
11070
11071             const gint compressor_offset =
11072                 16 + 4 + 4 * 3 + 2 * 2 + 2 * 4 + 4 + 2;
11073             const gint min_size = compressor_offset + 32 + 2 + 2;
11074             GNode *jpeg;
11075             guint32 len;
11076             guint16 color_table_id = 0;
11077             gboolean ok;
11078
11079             GST_DEBUG_OBJECT (qtdemux, "found jpeg");
11080
11081             /* recover information on interlaced/progressive */
11082             jpeg = qtdemux_tree_get_child_by_type (stsd, FOURCC_jpeg);
11083             if (!jpeg)
11084               break;
11085
11086             len = QT_UINT32 (jpeg->data);
11087             GST_DEBUG_OBJECT (qtdemux, "Found jpeg: len %u, need %d", len,
11088                 min_size);
11089             if (len >= min_size) {
11090               gst_byte_reader_init (&br, jpeg->data, len);
11091
11092               gst_byte_reader_skip (&br, compressor_offset + 32 + 2);
11093               gst_byte_reader_get_uint16_le (&br, &color_table_id);
11094               if (color_table_id != 0) {
11095                 /* the spec says there can be concatenated chunks in the data, and we want
11096                  * to find one called field. Walk through them. */
11097                 gint offset = min_size;
11098                 while (offset + 8 < len) {
11099                   guint32 size = 0, tag;
11100                   ok = gst_byte_reader_get_uint32_le (&br, &size);
11101                   ok &= gst_byte_reader_get_uint32_le (&br, &tag);
11102                   if (!ok || size < 8) {
11103                     GST_WARNING_OBJECT (qtdemux,
11104                         "Failed to walk optional chunk list");
11105                     break;
11106                   }
11107                   GST_DEBUG_OBJECT (qtdemux,
11108                       "Found optional %4.4s chunk, size %u",
11109                       (const char *) &tag, size);
11110                   if (tag == FOURCC_fiel) {
11111                     guint8 n_fields = 0, ordering = 0;
11112                     gst_byte_reader_get_uint8 (&br, &n_fields);
11113                     gst_byte_reader_get_uint8 (&br, &ordering);
11114                     if (n_fields == 1 || n_fields == 2) {
11115                       GST_DEBUG_OBJECT (qtdemux,
11116                           "Found fiel tag with %u fields, ordering %u",
11117                           n_fields, ordering);
11118                       if (n_fields == 2)
11119                         gst_caps_set_simple (CUR_STREAM (stream)->caps,
11120                             "interlace-mode", G_TYPE_STRING, "interleaved",
11121                             NULL);
11122                     } else {
11123                       GST_WARNING_OBJECT (qtdemux,
11124                           "Found fiel tag with invalid fields (%u)", n_fields);
11125                     }
11126                   }
11127                   offset += size;
11128                 }
11129               } else {
11130                 GST_DEBUG_OBJECT (qtdemux,
11131                     "Color table ID is 0, not trying to get interlacedness");
11132               }
11133             } else {
11134               GST_WARNING_OBJECT (qtdemux,
11135                   "Length of jpeg chunk is too small, not trying to get interlacedness");
11136             }
11137
11138             break;
11139           }
11140           case FOURCC_rle_:
11141           case FOURCC_WRLE:
11142           {
11143             gst_caps_set_simple (entry->caps,
11144                 "depth", G_TYPE_INT, QT_UINT16 (stsd_entry_data + offset + 66),
11145                 NULL);
11146             break;
11147           }
11148           case FOURCC_XiTh:
11149           {
11150             GNode *xith, *xdxt;
11151
11152             GST_DEBUG_OBJECT (qtdemux, "found XiTh");
11153             xith = qtdemux_tree_get_child_by_index (stsd, stsd_index);
11154             if (!xith)
11155               break;
11156
11157             xdxt = qtdemux_tree_get_child_by_type (xith, FOURCC_XdxT);
11158             if (!xdxt)
11159               break;
11160
11161             GST_DEBUG_OBJECT (qtdemux, "found XdxT node");
11162             /* collect the headers and store them in a stream list so that we can
11163              * send them out first */
11164             qtdemux_parse_theora_extension (qtdemux, stream, xdxt);
11165             break;
11166           }
11167           case FOURCC_ovc1:
11168           {
11169             GNode *ovc1;
11170             guint8 *ovc1_data;
11171             guint ovc1_len;
11172             GstBuffer *buf;
11173
11174             GST_DEBUG_OBJECT (qtdemux, "parse ovc1 header");
11175             ovc1 = qtdemux_tree_get_child_by_index (stsd, stsd_index);
11176             if (!ovc1)
11177               break;
11178             ovc1_data = ovc1->data;
11179             ovc1_len = QT_UINT32 (ovc1_data);
11180             if (ovc1_len <= 198) {
11181               GST_WARNING_OBJECT (qtdemux, "Too small ovc1 header, skipping");
11182               break;
11183             }
11184             buf = gst_buffer_new_and_alloc (ovc1_len - 198);
11185             gst_buffer_fill (buf, 0, ovc1_data + 198, ovc1_len - 198);
11186             gst_caps_set_simple (entry->caps,
11187                 "codec_data", GST_TYPE_BUFFER, buf, NULL);
11188             gst_buffer_unref (buf);
11189             break;
11190           }
11191           case FOURCC_vc_1:
11192           {
11193             gint len = QT_UINT32 (stsd_entry_data) - 0x56;
11194             const guint8 *vc1_data = stsd_entry_data + 0x56;
11195
11196             /* find dvc1 */
11197             while (len >= 8) {
11198               gint size;
11199
11200               if (QT_UINT32 (vc1_data) <= len)
11201                 size = QT_UINT32 (vc1_data) - 8;
11202               else
11203                 size = len - 8;
11204
11205               if (size < 1)
11206                 /* No real data, so break out */
11207                 break;
11208
11209               switch (QT_FOURCC (vc1_data + 0x4)) {
11210                 case GST_MAKE_FOURCC ('d', 'v', 'c', '1'):
11211                 {
11212                   GstBuffer *buf;
11213
11214                   GST_DEBUG_OBJECT (qtdemux, "found dvc1 codec_data in stsd");
11215                   buf = gst_buffer_new_and_alloc (size);
11216                   gst_buffer_fill (buf, 0, vc1_data + 8, size);
11217                   gst_caps_set_simple (entry->caps,
11218                       "codec_data", GST_TYPE_BUFFER, buf, NULL);
11219                   gst_buffer_unref (buf);
11220                   break;
11221                 }
11222                 default:
11223                   break;
11224               }
11225               len -= size + 8;
11226               vc1_data += size + 8;
11227             }
11228             break;
11229           }
11230           default:
11231             break;
11232         }
11233       }
11234
11235       GST_INFO_OBJECT (qtdemux,
11236           "type %" GST_FOURCC_FORMAT " caps %" GST_PTR_FORMAT,
11237           GST_FOURCC_ARGS (fourcc), entry->caps);
11238
11239     } else if (stream->subtype == FOURCC_soun) {
11240       GNode *wave;
11241       int version, samplesize;
11242       guint16 compression_id;
11243       gboolean amrwb = FALSE;
11244
11245       offset = 16;
11246       /* sample description entry (16) + sound sample description v0 (20) */
11247       if (len < 36)
11248         goto corrupt_file;
11249
11250       version = QT_UINT32 (stsd_entry_data + offset);
11251       entry->n_channels = QT_UINT16 (stsd_entry_data + offset + 8);
11252       samplesize = QT_UINT16 (stsd_entry_data + offset + 10);
11253       compression_id = QT_UINT16 (stsd_entry_data + offset + 12);
11254       entry->rate = QT_FP32 (stsd_entry_data + offset + 16);
11255
11256       GST_LOG_OBJECT (qtdemux, "version/rev:      %08x", version);
11257       GST_LOG_OBJECT (qtdemux, "vendor:           %08x",
11258           QT_UINT32 (stsd_entry_data + offset + 4));
11259       GST_LOG_OBJECT (qtdemux, "n_channels:       %d", entry->n_channels);
11260       GST_LOG_OBJECT (qtdemux, "sample_size:      %d", samplesize);
11261       GST_LOG_OBJECT (qtdemux, "compression_id:   %d", compression_id);
11262       GST_LOG_OBJECT (qtdemux, "packet size:      %d",
11263           QT_UINT16 (stsd_entry_data + offset + 14));
11264       GST_LOG_OBJECT (qtdemux, "sample rate:      %g", entry->rate);
11265
11266       if (compression_id == 0xfffe)
11267         entry->sampled = TRUE;
11268
11269       /* first assume uncompressed audio */
11270       entry->bytes_per_sample = samplesize / 8;
11271       entry->samples_per_frame = entry->n_channels;
11272       entry->bytes_per_frame = entry->n_channels * entry->bytes_per_sample;
11273       entry->samples_per_packet = entry->samples_per_frame;
11274       entry->bytes_per_packet = entry->bytes_per_sample;
11275
11276       offset = 36;
11277       switch (fourcc) {
11278           /* Yes, these have to be hard-coded */
11279         case FOURCC_MAC6:
11280         {
11281           entry->samples_per_packet = 6;
11282           entry->bytes_per_packet = 1;
11283           entry->bytes_per_frame = 1 * entry->n_channels;
11284           entry->bytes_per_sample = 1;
11285           entry->samples_per_frame = 6 * entry->n_channels;
11286           break;
11287         }
11288         case FOURCC_MAC3:
11289         {
11290           entry->samples_per_packet = 3;
11291           entry->bytes_per_packet = 1;
11292           entry->bytes_per_frame = 1 * entry->n_channels;
11293           entry->bytes_per_sample = 1;
11294           entry->samples_per_frame = 3 * entry->n_channels;
11295           break;
11296         }
11297         case FOURCC_ima4:
11298         {
11299           entry->samples_per_packet = 64;
11300           entry->bytes_per_packet = 34;
11301           entry->bytes_per_frame = 34 * entry->n_channels;
11302           entry->bytes_per_sample = 2;
11303           entry->samples_per_frame = 64 * entry->n_channels;
11304           break;
11305         }
11306         case FOURCC_ulaw:
11307         case FOURCC_alaw:
11308         {
11309           entry->samples_per_packet = 1;
11310           entry->bytes_per_packet = 1;
11311           entry->bytes_per_frame = 1 * entry->n_channels;
11312           entry->bytes_per_sample = 1;
11313           entry->samples_per_frame = 1 * entry->n_channels;
11314           break;
11315         }
11316         case FOURCC_agsm:
11317         {
11318           entry->samples_per_packet = 160;
11319           entry->bytes_per_packet = 33;
11320           entry->bytes_per_frame = 33 * entry->n_channels;
11321           entry->bytes_per_sample = 2;
11322           entry->samples_per_frame = 160 * entry->n_channels;
11323           break;
11324         }
11325         default:
11326           break;
11327       }
11328
11329       if (version == 0x00010000) {
11330         /* sample description entry (16) + sound sample description v1 (20+16) */
11331         if (len < 52)
11332           goto corrupt_file;
11333
11334         switch (fourcc) {
11335           case FOURCC_twos:
11336           case FOURCC_sowt:
11337           case FOURCC_raw_:
11338           case FOURCC_lpcm:
11339             break;
11340           default:
11341           {
11342             /* only parse extra decoding config for non-pcm audio */
11343             entry->samples_per_packet = QT_UINT32 (stsd_entry_data + offset);
11344             entry->bytes_per_packet = QT_UINT32 (stsd_entry_data + offset + 4);
11345             entry->bytes_per_frame = QT_UINT32 (stsd_entry_data + offset + 8);
11346             entry->bytes_per_sample = QT_UINT32 (stsd_entry_data + offset + 12);
11347
11348             GST_LOG_OBJECT (qtdemux, "samples/packet:   %d",
11349                 entry->samples_per_packet);
11350             GST_LOG_OBJECT (qtdemux, "bytes/packet:     %d",
11351                 entry->bytes_per_packet);
11352             GST_LOG_OBJECT (qtdemux, "bytes/frame:      %d",
11353                 entry->bytes_per_frame);
11354             GST_LOG_OBJECT (qtdemux, "bytes/sample:     %d",
11355                 entry->bytes_per_sample);
11356
11357             if (!entry->sampled && entry->bytes_per_packet) {
11358               entry->samples_per_frame = (entry->bytes_per_frame /
11359                   entry->bytes_per_packet) * entry->samples_per_packet;
11360               GST_LOG_OBJECT (qtdemux, "samples/frame:    %d",
11361                   entry->samples_per_frame);
11362             }
11363             break;
11364           }
11365         }
11366       } else if (version == 0x00020000) {
11367         union
11368         {
11369           gdouble fp;
11370           guint64 val;
11371         } qtfp;
11372
11373         /* sample description entry (16) + sound sample description v2 (56) */
11374         if (len < 72)
11375           goto corrupt_file;
11376
11377         qtfp.val = QT_UINT64 (stsd_entry_data + offset + 4);
11378         entry->rate = qtfp.fp;
11379         entry->n_channels = QT_UINT32 (stsd_entry_data + offset + 12);
11380
11381         GST_LOG_OBJECT (qtdemux, "Sound sample description Version 2");
11382         GST_LOG_OBJECT (qtdemux, "sample rate:        %g", entry->rate);
11383         GST_LOG_OBJECT (qtdemux, "n_channels:         %d", entry->n_channels);
11384         GST_LOG_OBJECT (qtdemux, "bits/channel:       %d",
11385             QT_UINT32 (stsd_entry_data + offset + 20));
11386         GST_LOG_OBJECT (qtdemux, "format flags:       %X",
11387             QT_UINT32 (stsd_entry_data + offset + 24));
11388         GST_LOG_OBJECT (qtdemux, "bytes/packet:       %d",
11389             QT_UINT32 (stsd_entry_data + offset + 28));
11390         GST_LOG_OBJECT (qtdemux, "LPCM frames/packet: %d",
11391             QT_UINT32 (stsd_entry_data + offset + 32));
11392       } else if (version != 0x00000) {
11393         GST_WARNING_OBJECT (qtdemux, "unknown audio STSD version %08x",
11394             version);
11395       }
11396
11397       if (entry->caps)
11398         gst_caps_unref (entry->caps);
11399
11400       entry->caps = qtdemux_audio_caps (qtdemux, stream, entry, fourcc,
11401           stsd_entry_data + 32, len - 16, &codec);
11402
11403       switch (fourcc) {
11404         case FOURCC_in24:
11405         {
11406           GNode *enda;
11407           GNode *in24;
11408
11409           in24 = qtdemux_tree_get_child_by_type (stsd, FOURCC_in24);
11410
11411           enda = qtdemux_tree_get_child_by_type (in24, FOURCC_enda);
11412           if (!enda) {
11413             wave = qtdemux_tree_get_child_by_type (in24, FOURCC_wave);
11414             if (wave)
11415               enda = qtdemux_tree_get_child_by_type (wave, FOURCC_enda);
11416           }
11417           if (enda) {
11418             int enda_value = QT_UINT16 ((guint8 *) enda->data + 8);
11419             gst_caps_set_simple (entry->caps,
11420                 "format", G_TYPE_STRING, (enda_value) ? "S24LE" : "S24BE",
11421                 NULL);
11422           }
11423           break;
11424         }
11425         case FOURCC_owma:
11426         {
11427           const guint8 *owma_data;
11428           const gchar *codec_name = NULL;
11429           guint owma_len;
11430           GstBuffer *buf;
11431           gint version = 1;
11432           /* from http://msdn.microsoft.com/en-us/library/dd757720(VS.85).aspx */
11433           /* FIXME this should also be gst_riff_strf_auds,
11434            * but the latter one is actually missing bits-per-sample :( */
11435           typedef struct
11436           {
11437             gint16 wFormatTag;
11438             gint16 nChannels;
11439             gint32 nSamplesPerSec;
11440             gint32 nAvgBytesPerSec;
11441             gint16 nBlockAlign;
11442             gint16 wBitsPerSample;
11443             gint16 cbSize;
11444           } WAVEFORMATEX;
11445           WAVEFORMATEX *wfex;
11446
11447           GST_DEBUG_OBJECT (qtdemux, "parse owma");
11448           owma_data = stsd_entry_data;
11449           owma_len = QT_UINT32 (owma_data);
11450           if (owma_len <= 54) {
11451             GST_WARNING_OBJECT (qtdemux, "Too small owma header, skipping");
11452             break;
11453           }
11454           wfex = (WAVEFORMATEX *) (owma_data + 36);
11455           buf = gst_buffer_new_and_alloc (owma_len - 54);
11456           gst_buffer_fill (buf, 0, owma_data + 54, owma_len - 54);
11457           if (wfex->wFormatTag == 0x0161) {
11458             codec_name = "Windows Media Audio";
11459             version = 2;
11460           } else if (wfex->wFormatTag == 0x0162) {
11461             codec_name = "Windows Media Audio 9 Pro";
11462             version = 3;
11463           } else if (wfex->wFormatTag == 0x0163) {
11464             codec_name = "Windows Media Audio 9 Lossless";
11465             /* is that correct? gstffmpegcodecmap.c is missing it, but
11466              * fluendo codec seems to support it */
11467             version = 4;
11468           }
11469
11470           gst_caps_set_simple (entry->caps,
11471               "codec_data", GST_TYPE_BUFFER, buf,
11472               "wmaversion", G_TYPE_INT, version,
11473               "block_align", G_TYPE_INT,
11474               GST_READ_UINT16_LE (&wfex->nBlockAlign), "bitrate", G_TYPE_INT,
11475               GST_READ_UINT32_LE (&wfex->nAvgBytesPerSec), "width", G_TYPE_INT,
11476               GST_READ_UINT16_LE (&wfex->wBitsPerSample), "depth", G_TYPE_INT,
11477               GST_READ_UINT16_LE (&wfex->wBitsPerSample), NULL);
11478           gst_buffer_unref (buf);
11479
11480           if (codec_name) {
11481             g_free (codec);
11482             codec = g_strdup (codec_name);
11483           }
11484           break;
11485         }
11486         case FOURCC_wma_:
11487         {
11488           gint len = QT_UINT32 (stsd_entry_data) - offset;
11489           const guint8 *wfex_data = stsd_entry_data + offset;
11490           const gchar *codec_name = NULL;
11491           gint version = 1;
11492           /* from http://msdn.microsoft.com/en-us/library/dd757720(VS.85).aspx */
11493           /* FIXME this should also be gst_riff_strf_auds,
11494            * but the latter one is actually missing bits-per-sample :( */
11495           typedef struct
11496           {
11497             gint16 wFormatTag;
11498             gint16 nChannels;
11499             gint32 nSamplesPerSec;
11500             gint32 nAvgBytesPerSec;
11501             gint16 nBlockAlign;
11502             gint16 wBitsPerSample;
11503             gint16 cbSize;
11504           } WAVEFORMATEX;
11505           WAVEFORMATEX wfex;
11506
11507           /* FIXME: unify with similar wavformatex parsing code above */
11508           GST_DEBUG_OBJECT (qtdemux, "parse wma, looking for wfex");
11509
11510           /* find wfex */
11511           while (len >= 8) {
11512             gint size;
11513
11514             if (QT_UINT32 (wfex_data) <= len)
11515               size = QT_UINT32 (wfex_data) - 8;
11516             else
11517               size = len - 8;
11518
11519             if (size < 1)
11520               /* No real data, so break out */
11521               break;
11522
11523             switch (QT_FOURCC (wfex_data + 4)) {
11524               case GST_MAKE_FOURCC ('w', 'f', 'e', 'x'):
11525               {
11526                 GST_DEBUG_OBJECT (qtdemux, "found wfex in stsd");
11527
11528                 if (size < 8 + 18)
11529                   break;
11530
11531                 wfex.wFormatTag = GST_READ_UINT16_LE (wfex_data + 8 + 0);
11532                 wfex.nChannels = GST_READ_UINT16_LE (wfex_data + 8 + 2);
11533                 wfex.nSamplesPerSec = GST_READ_UINT32_LE (wfex_data + 8 + 4);
11534                 wfex.nAvgBytesPerSec = GST_READ_UINT32_LE (wfex_data + 8 + 8);
11535                 wfex.nBlockAlign = GST_READ_UINT16_LE (wfex_data + 8 + 12);
11536                 wfex.wBitsPerSample = GST_READ_UINT16_LE (wfex_data + 8 + 14);
11537                 wfex.cbSize = GST_READ_UINT16_LE (wfex_data + 8 + 16);
11538
11539                 GST_LOG_OBJECT (qtdemux, "Found wfex box in stsd:");
11540                 GST_LOG_OBJECT (qtdemux, "FormatTag = 0x%04x, Channels = %u, "
11541                     "SamplesPerSec = %u, AvgBytesPerSec = %u, BlockAlign = %u, "
11542                     "BitsPerSample = %u, Size = %u", wfex.wFormatTag,
11543                     wfex.nChannels, wfex.nSamplesPerSec, wfex.nAvgBytesPerSec,
11544                     wfex.nBlockAlign, wfex.wBitsPerSample, wfex.cbSize);
11545
11546                 if (wfex.wFormatTag == 0x0161) {
11547                   codec_name = "Windows Media Audio";
11548                   version = 2;
11549                 } else if (wfex.wFormatTag == 0x0162) {
11550                   codec_name = "Windows Media Audio 9 Pro";
11551                   version = 3;
11552                 } else if (wfex.wFormatTag == 0x0163) {
11553                   codec_name = "Windows Media Audio 9 Lossless";
11554                   /* is that correct? gstffmpegcodecmap.c is missing it, but
11555                    * fluendo codec seems to support it */
11556                   version = 4;
11557                 }
11558
11559                 gst_caps_set_simple (entry->caps,
11560                     "wmaversion", G_TYPE_INT, version,
11561                     "block_align", G_TYPE_INT, wfex.nBlockAlign,
11562                     "bitrate", G_TYPE_INT, wfex.nAvgBytesPerSec,
11563                     "width", G_TYPE_INT, wfex.wBitsPerSample,
11564                     "depth", G_TYPE_INT, wfex.wBitsPerSample, NULL);
11565
11566                 if (size > wfex.cbSize) {
11567                   GstBuffer *buf;
11568
11569                   buf = gst_buffer_new_and_alloc (size - wfex.cbSize);
11570                   gst_buffer_fill (buf, 0, wfex_data + 8 + wfex.cbSize,
11571                       size - wfex.cbSize);
11572                   gst_caps_set_simple (entry->caps,
11573                       "codec_data", GST_TYPE_BUFFER, buf, NULL);
11574                   gst_buffer_unref (buf);
11575                 } else {
11576                   GST_WARNING_OBJECT (qtdemux, "no codec data");
11577                 }
11578
11579                 if (codec_name) {
11580                   g_free (codec);
11581                   codec = g_strdup (codec_name);
11582                 }
11583                 break;
11584               }
11585               default:
11586                 break;
11587             }
11588             len -= size + 8;
11589             wfex_data += size + 8;
11590           }
11591           break;
11592         }
11593         case FOURCC_opus:
11594         {
11595           const guint8 *opus_data;
11596           guint8 *channel_mapping = NULL;
11597           guint32 rate;
11598           guint8 channels;
11599           guint8 channel_mapping_family;
11600           guint8 stream_count;
11601           guint8 coupled_count;
11602           guint8 i;
11603
11604           opus_data = stsd_entry_data;
11605
11606           channels = GST_READ_UINT8 (opus_data + 45);
11607           rate = GST_READ_UINT32_LE (opus_data + 48);
11608           channel_mapping_family = GST_READ_UINT8 (opus_data + 54);
11609           stream_count = GST_READ_UINT8 (opus_data + 55);
11610           coupled_count = GST_READ_UINT8 (opus_data + 56);
11611
11612           if (channels > 0) {
11613             channel_mapping = g_malloc (channels * sizeof (guint8));
11614             for (i = 0; i < channels; i++)
11615               channel_mapping[i] = GST_READ_UINT8 (opus_data + i + 57);
11616           }
11617
11618           entry->caps = gst_codec_utils_opus_create_caps (rate, channels,
11619               channel_mapping_family, stream_count, coupled_count,
11620               channel_mapping);
11621           break;
11622         }
11623         default:
11624           break;
11625       }
11626
11627       if (codec) {
11628         GstStructure *s;
11629         gint bitrate = 0;
11630
11631         gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
11632             GST_TAG_AUDIO_CODEC, codec, NULL);
11633         g_free (codec);
11634         codec = NULL;
11635
11636         /* some bitrate info may have ended up in caps */
11637         s = gst_caps_get_structure (entry->caps, 0);
11638         gst_structure_get_int (s, "bitrate", &bitrate);
11639         if (bitrate > 0)
11640           gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
11641               GST_TAG_BITRATE, bitrate, NULL);
11642       }
11643
11644       mp4a = qtdemux_tree_get_child_by_index (stsd, stsd_index);
11645       if (!stream->protected) {
11646       } else {
11647         if (QTDEMUX_TREE_NODE_FOURCC (mp4v) != FOURCC_encv) {
11648           mp4v = NULL;
11649         }
11650       }
11651       if (stream->protected && fourcc == FOURCC_mp4a) {
11652         if (QTDEMUX_TREE_NODE_FOURCC (mp4a) != FOURCC_enca) {
11653           mp4a = NULL;
11654         }
11655       } else {
11656         if (QTDEMUX_TREE_NODE_FOURCC (mp4a) != FOURCC_mp4a) {
11657           mp4a = NULL;
11658         }
11659       }
11660
11661       wave = NULL;
11662       esds = NULL;
11663       if (mp4a) {
11664         wave = qtdemux_tree_get_child_by_type (mp4a, FOURCC_wave);
11665         if (wave)
11666           esds = qtdemux_tree_get_child_by_type (wave, FOURCC_esds);
11667         if (!esds)
11668           esds = qtdemux_tree_get_child_by_type (mp4a, FOURCC_esds);
11669       }
11670
11671
11672       /* If the fourcc's bottom 16 bits gives 'sm', then the top
11673          16 bits is a byte-swapped wave-style codec identifier,
11674          and we can find a WAVE header internally to a 'wave' atom here.
11675          This can more clearly be thought of as 'ms' as the top 16 bits, and a
11676          codec id as the bottom 16 bits - but byte-swapped to store in QT (which
11677          is big-endian).
11678        */
11679       if ((fourcc & 0xffff) == (('s' << 8) | 'm')) {
11680         if (len < offset + 20) {
11681           GST_WARNING_OBJECT (qtdemux, "No wave atom in MS-style audio");
11682         } else {
11683           guint32 datalen = QT_UINT32 (stsd_entry_data + offset + 16);
11684           const guint8 *data = stsd_entry_data + offset + 16;
11685           GNode *wavenode;
11686           GNode *waveheadernode;
11687
11688           wavenode = g_node_new ((guint8 *) data);
11689           if (qtdemux_parse_node (qtdemux, wavenode, data, datalen)) {
11690             const guint8 *waveheader;
11691             guint32 headerlen;
11692
11693             waveheadernode = qtdemux_tree_get_child_by_type (wavenode, fourcc);
11694             if (waveheadernode) {
11695               waveheader = (const guint8 *) waveheadernode->data;
11696               headerlen = QT_UINT32 (waveheader);
11697
11698               if (headerlen > 8) {
11699                 gst_riff_strf_auds *header = NULL;
11700                 GstBuffer *headerbuf;
11701                 GstBuffer *extra;
11702
11703                 waveheader += 8;
11704                 headerlen -= 8;
11705
11706                 headerbuf = gst_buffer_new_and_alloc (headerlen);
11707                 gst_buffer_fill (headerbuf, 0, waveheader, headerlen);
11708
11709                 if (gst_riff_parse_strf_auds (GST_ELEMENT_CAST (qtdemux),
11710                         headerbuf, &header, &extra)) {
11711                   gst_caps_unref (entry->caps);
11712                   /* FIXME: Need to do something with the channel reorder map */
11713                   entry->caps =
11714                       gst_riff_create_audio_caps (header->format, NULL, header,
11715                       extra, NULL, NULL, NULL);
11716
11717                   if (extra)
11718                     gst_buffer_unref (extra);
11719                   g_free (header);
11720                 }
11721               }
11722             } else
11723               GST_DEBUG ("Didn't find waveheadernode for this codec");
11724           }
11725           g_node_destroy (wavenode);
11726         }
11727       } else if (esds) {
11728         gst_qtdemux_handle_esds (qtdemux, stream, entry, esds,
11729             stream->stream_tags);
11730       } else {
11731         switch (fourcc) {
11732 #if 0
11733             /* FIXME: what is in the chunk? */
11734           case FOURCC_QDMC:
11735           {
11736             gint len = QT_UINT32 (stsd_data);
11737
11738             /* seems to be always = 116 = 0x74 */
11739             break;
11740           }
11741 #endif
11742           case FOURCC_QDM2:
11743           {
11744             gint len = QT_UINT32 (stsd_entry_data);
11745
11746             if (len > 0x3C) {
11747               GstBuffer *buf = gst_buffer_new_and_alloc (len - 0x3C);
11748
11749               gst_buffer_fill (buf, 0, stsd_entry_data + 0x3C, len - 0x3C);
11750               gst_caps_set_simple (entry->caps,
11751                   "codec_data", GST_TYPE_BUFFER, buf, NULL);
11752               gst_buffer_unref (buf);
11753             }
11754             gst_caps_set_simple (entry->caps,
11755                 "samplesize", G_TYPE_INT, samplesize, NULL);
11756             break;
11757           }
11758           case FOURCC_alac:
11759           {
11760             GNode *alac, *wave = NULL;
11761
11762             /* apparently, m4a has this atom appended directly in the stsd entry,
11763              * while mov has it in a wave atom */
11764             alac = qtdemux_tree_get_child_by_type (stsd, FOURCC_alac);
11765             if (alac) {
11766               /* alac now refers to stsd entry atom */
11767               wave = qtdemux_tree_get_child_by_type (alac, FOURCC_wave);
11768               if (wave)
11769                 alac = qtdemux_tree_get_child_by_type (wave, FOURCC_alac);
11770               else
11771                 alac = qtdemux_tree_get_child_by_type (alac, FOURCC_alac);
11772             }
11773             if (alac) {
11774               const guint8 *alac_data = alac->data;
11775               gint len = QT_UINT32 (alac->data);
11776               GstBuffer *buf;
11777
11778               if (len < 36) {
11779                 GST_DEBUG_OBJECT (qtdemux,
11780                     "discarding alac atom with unexpected len %d", len);
11781               } else {
11782                 /* codec-data contains alac atom size and prefix,
11783                  * ffmpeg likes it that way, not quite gst-ish though ...*/
11784                 buf = gst_buffer_new_and_alloc (len);
11785                 gst_buffer_fill (buf, 0, alac->data, len);
11786                 gst_caps_set_simple (entry->caps,
11787                     "codec_data", GST_TYPE_BUFFER, buf, NULL);
11788                 gst_buffer_unref (buf);
11789
11790                 entry->bytes_per_frame = QT_UINT32 (alac_data + 12);
11791                 entry->n_channels = QT_UINT8 (alac_data + 21);
11792                 entry->rate = QT_UINT32 (alac_data + 32);
11793               }
11794             }
11795             gst_caps_set_simple (entry->caps,
11796                 "samplesize", G_TYPE_INT, samplesize, NULL);
11797             break;
11798           }
11799           case FOURCC_fLaC:
11800           {
11801             /* The codingname of the sample entry is 'fLaC' */
11802             GNode *flac = qtdemux_tree_get_child_by_type (stsd, FOURCC_fLaC);
11803
11804             if (flac) {
11805               /* The 'dfLa' box is added to the sample entry to convey
11806                  initializing information for the decoder. */
11807               const GNode *dfla =
11808                   qtdemux_tree_get_child_by_type (flac, FOURCC_dfLa);
11809
11810               if (dfla) {
11811                 const guint32 len = QT_UINT32 (dfla->data);
11812
11813                 /* Must contain at least dfLa box header (12),
11814                  * METADATA_BLOCK_HEADER (4), METADATA_BLOCK_STREAMINFO (34) */
11815                 if (len < 50) {
11816                   GST_DEBUG_OBJECT (qtdemux,
11817                       "discarding dfla atom with unexpected len %d", len);
11818                 } else {
11819                   /* skip dfLa header to get the METADATA_BLOCKs */
11820                   const guint8 *metadata_blocks = (guint8 *) dfla->data + 12;
11821                   const guint32 metadata_blocks_len = len - 12;
11822
11823                   gchar *stream_marker = g_strdup ("fLaC");
11824                   GstBuffer *block = gst_buffer_new_wrapped (stream_marker,
11825                       strlen (stream_marker));
11826
11827                   guint32 index = 0;
11828                   guint32 remainder = 0;
11829                   guint32 block_size = 0;
11830                   gboolean is_last = FALSE;
11831
11832                   GValue array = G_VALUE_INIT;
11833                   GValue value = G_VALUE_INIT;
11834
11835                   g_value_init (&array, GST_TYPE_ARRAY);
11836                   g_value_init (&value, GST_TYPE_BUFFER);
11837
11838                   gst_value_set_buffer (&value, block);
11839                   gst_value_array_append_value (&array, &value);
11840                   g_value_reset (&value);
11841
11842                   gst_buffer_unref (block);
11843
11844                   /* check there's at least one METADATA_BLOCK_HEADER's worth
11845                    * of data, and we haven't already finished parsing */
11846                   while (!is_last && ((index + 3) < metadata_blocks_len)) {
11847                     remainder = metadata_blocks_len - index;
11848
11849                     /* add the METADATA_BLOCK_HEADER size to the signalled size */
11850                     block_size = 4 +
11851                         (metadata_blocks[index + 1] << 16) +
11852                         (metadata_blocks[index + 2] << 8) +
11853                         metadata_blocks[index + 3];
11854
11855                     /* be careful not to read off end of box */
11856                     if (block_size > remainder) {
11857                       break;
11858                     }
11859
11860                     is_last = metadata_blocks[index] >> 7;
11861
11862                     block = gst_buffer_new_and_alloc (block_size);
11863
11864                     gst_buffer_fill (block, 0, &metadata_blocks[index],
11865                         block_size);
11866
11867                     gst_value_set_buffer (&value, block);
11868                     gst_value_array_append_value (&array, &value);
11869                     g_value_reset (&value);
11870
11871                     gst_buffer_unref (block);
11872
11873                     index += block_size;
11874                   }
11875
11876                   /* only append the metadata if we successfully read all of it */
11877                   if (is_last) {
11878                     gst_structure_set_value (gst_caps_get_structure (CUR_STREAM
11879                             (stream)->caps, 0), "streamheader", &array);
11880                   } else {
11881                     GST_WARNING_OBJECT (qtdemux,
11882                         "discarding all METADATA_BLOCKs due to invalid "
11883                         "block_size %d at idx %d, rem %d", block_size, index,
11884                         remainder);
11885                   }
11886
11887                   g_value_unset (&value);
11888                   g_value_unset (&array);
11889
11890                   /* The sample rate obtained from the stsd may not be accurate
11891                    * since it cannot represent rates greater than 65535Hz, so
11892                    * override that value with the sample rate from the
11893                    * METADATA_BLOCK_STREAMINFO block */
11894                   CUR_STREAM (stream)->rate =
11895                       (QT_UINT32 (metadata_blocks + 14) >> 12) & 0xFFFFF;
11896                 }
11897               }
11898             }
11899             break;
11900           }
11901           case FOURCC_sawb:
11902             /* Fallthrough! */
11903             amrwb = TRUE;
11904           case FOURCC_samr:
11905           {
11906             gint len = QT_UINT32 (stsd_entry_data);
11907
11908             if (len > 0x24) {
11909               GstBuffer *buf = gst_buffer_new_and_alloc (len - 0x24);
11910               guint bitrate;
11911
11912               gst_buffer_fill (buf, 0, stsd_entry_data + 0x24, len - 0x24);
11913
11914               /* If we have enough data, let's try to get the 'damr' atom. See
11915                * the 3GPP container spec (26.244) for more details. */
11916               if ((len - 0x34) > 8 &&
11917                   (bitrate = qtdemux_parse_amr_bitrate (buf, amrwb))) {
11918                 gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
11919                     GST_TAG_MAXIMUM_BITRATE, bitrate, NULL);
11920               }
11921
11922               gst_caps_set_simple (entry->caps,
11923                   "codec_data", GST_TYPE_BUFFER, buf, NULL);
11924               gst_buffer_unref (buf);
11925             }
11926             break;
11927           }
11928           case FOURCC_mp4a:
11929           {
11930             /* mp4a atom withtout ESDS; Attempt to build codec data from atom */
11931             gint len = QT_UINT32 (stsd_entry_data);
11932
11933             if (len >= 34) {
11934               guint16 sound_version = QT_UINT16 (stsd_entry_data + 16);
11935
11936               if (sound_version == 1) {
11937                 guint16 channels = QT_UINT16 (stsd_entry_data + 24);
11938                 guint32 time_scale = QT_UINT32 (stsd_entry_data + 30);
11939                 guint8 codec_data[2];
11940                 GstBuffer *buf;
11941                 gint profile = 2;       /* FIXME: Can this be determined somehow? There doesn't seem to be anything in mp4a atom that specifis compression */
11942
11943                 gint sample_rate_index =
11944                     gst_codec_utils_aac_get_index_from_sample_rate (time_scale);
11945
11946                 /* build AAC codec data */
11947                 codec_data[0] = profile << 3;
11948                 codec_data[0] |= ((sample_rate_index >> 1) & 0x7);
11949                 codec_data[1] = (sample_rate_index & 0x01) << 7;
11950                 codec_data[1] |= (channels & 0xF) << 3;
11951
11952                 buf = gst_buffer_new_and_alloc (2);
11953                 gst_buffer_fill (buf, 0, codec_data, 2);
11954                 gst_caps_set_simple (entry->caps,
11955                     "codec_data", GST_TYPE_BUFFER, buf, NULL);
11956                 gst_buffer_unref (buf);
11957               }
11958             }
11959             break;
11960           }
11961           case FOURCC_lpcm:
11962             /* Fully handled elsewhere */
11963             break;
11964           default:
11965             GST_INFO_OBJECT (qtdemux,
11966                 "unhandled type %" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (fourcc));
11967             break;
11968         }
11969       }
11970       GST_INFO_OBJECT (qtdemux,
11971           "type %" GST_FOURCC_FORMAT " caps %" GST_PTR_FORMAT,
11972           GST_FOURCC_ARGS (fourcc), entry->caps);
11973
11974     } else if (stream->subtype == FOURCC_strm) {
11975       if (fourcc == FOURCC_rtsp) {
11976         stream->redirect_uri = qtdemux_get_rtsp_uri_from_hndl (qtdemux, minf);
11977       } else {
11978         GST_INFO_OBJECT (qtdemux, "unhandled stream type %" GST_FOURCC_FORMAT,
11979             GST_FOURCC_ARGS (fourcc));
11980         goto unknown_stream;
11981       }
11982       entry->sampled = TRUE;
11983     } else if (stream->subtype == FOURCC_subp || stream->subtype == FOURCC_text
11984         || stream->subtype == FOURCC_sbtl || stream->subtype == FOURCC_subt
11985         || stream->subtype == FOURCC_clcp) {
11986
11987       entry->sampled = TRUE;
11988       entry->sparse = TRUE;
11989
11990       entry->caps =
11991           qtdemux_sub_caps (qtdemux, stream, entry, fourcc, stsd_entry_data,
11992           &codec);
11993       if (codec) {
11994         gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
11995             GST_TAG_SUBTITLE_CODEC, codec, NULL);
11996         g_free (codec);
11997         codec = NULL;
11998       }
11999
12000       /* hunt for sort-of codec data */
12001       switch (fourcc) {
12002         case FOURCC_mp4s:
12003         {
12004           GNode *mp4s = NULL;
12005           GNode *esds = NULL;
12006
12007           /* look for palette in a stsd->mp4s->esds sub-atom */
12008           mp4s = qtdemux_tree_get_child_by_type (stsd, FOURCC_mp4s);
12009           if (mp4s)
12010             esds = qtdemux_tree_get_child_by_type (mp4s, FOURCC_esds);
12011           if (esds == NULL) {
12012             /* Invalid STSD */
12013             GST_LOG_OBJECT (qtdemux, "Skipping invalid stsd: no esds child");
12014             break;
12015           }
12016
12017           gst_qtdemux_handle_esds (qtdemux, stream, entry, esds,
12018               stream->stream_tags);
12019           break;
12020         }
12021         default:
12022           GST_INFO_OBJECT (qtdemux,
12023               "unhandled type %" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (fourcc));
12024           break;
12025       }
12026       GST_INFO_OBJECT (qtdemux,
12027           "type %" GST_FOURCC_FORMAT " caps %" GST_PTR_FORMAT,
12028           GST_FOURCC_ARGS (fourcc), entry->caps);
12029     } else {
12030       /* everything in 1 sample */
12031       entry->sampled = TRUE;
12032
12033       entry->caps =
12034           qtdemux_generic_caps (qtdemux, stream, entry, fourcc, stsd_entry_data,
12035           &codec);
12036
12037       if (entry->caps == NULL)
12038         goto unknown_stream;
12039
12040       if (codec) {
12041         gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
12042             GST_TAG_SUBTITLE_CODEC, codec, NULL);
12043         g_free (codec);
12044         codec = NULL;
12045       }
12046     }
12047
12048     /* promote to sampled format */
12049     if (entry->fourcc == FOURCC_samr) {
12050       /* force mono 8000 Hz for AMR */
12051       entry->sampled = TRUE;
12052       entry->n_channels = 1;
12053       entry->rate = 8000;
12054     } else if (entry->fourcc == FOURCC_sawb) {
12055       /* force mono 16000 Hz for AMR-WB */
12056       entry->sampled = TRUE;
12057       entry->n_channels = 1;
12058       entry->rate = 16000;
12059     } else if (entry->fourcc == FOURCC_mp4a) {
12060       entry->sampled = TRUE;
12061     }
12062
12063
12064     stsd_entry_data += len;
12065     remaining_stsd_len -= len;
12066
12067   }
12068
12069   /* collect sample information */
12070   if (!qtdemux_stbl_init (qtdemux, stream, stbl))
12071     goto samples_failed;
12072
12073   if (qtdemux->fragmented) {
12074     guint64 offset;
12075
12076     /* need all moov samples as basis; probably not many if any at all */
12077     /* prevent moof parsing taking of at this time */
12078     offset = qtdemux->moof_offset;
12079     qtdemux->moof_offset = 0;
12080     if (stream->n_samples &&
12081         !qtdemux_parse_samples (qtdemux, stream, stream->n_samples - 1)) {
12082       qtdemux->moof_offset = offset;
12083       goto samples_failed;
12084     }
12085     qtdemux->moof_offset = 0;
12086     /* movie duration more reliable in this case (e.g. mehd) */
12087     if (qtdemux->segment.duration &&
12088         GST_CLOCK_TIME_IS_VALID (qtdemux->segment.duration))
12089       stream->duration =
12090           GSTTIME_TO_QTSTREAMTIME (stream, qtdemux->segment.duration);
12091   }
12092
12093   /* configure segments */
12094   if (!qtdemux_parse_segments (qtdemux, stream, trak))
12095     goto segments_failed;
12096
12097   /* add some language tag, if useful */
12098   if (stream->lang_id[0] != '\0' && strcmp (stream->lang_id, "unk") &&
12099       strcmp (stream->lang_id, "und")) {
12100     const gchar *lang_code;
12101
12102     /* convert ISO 639-2 code to ISO 639-1 */
12103     lang_code = gst_tag_get_language_code (stream->lang_id);
12104     gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
12105         GST_TAG_LANGUAGE_CODE, (lang_code) ? lang_code : stream->lang_id, NULL);
12106   }
12107
12108   /* Check for UDTA tags */
12109   if ((udta = qtdemux_tree_get_child_by_type (trak, FOURCC_udta))) {
12110     qtdemux_parse_udta (qtdemux, stream->stream_tags, udta);
12111   }
12112
12113   /* Insert and sort new stream in track-id order.
12114    * This will help in comparing old/new streams during stream update check */
12115   qtdemux->active_streams =
12116       g_list_insert_sorted (qtdemux->active_streams, stream,
12117       (GCompareFunc) qtdemux_track_id_compare_func);
12118   qtdemux->n_streams++;
12119   GST_DEBUG_OBJECT (qtdemux, "n_streams is now %d", qtdemux->n_streams);
12120
12121   return TRUE;
12122
12123 /* ERRORS */
12124 corrupt_file:
12125   {
12126     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
12127         (_("This file is corrupt and cannot be played.")), (NULL));
12128     if (stream)
12129       gst_qtdemux_stream_free (stream);
12130     return FALSE;
12131   }
12132 error_encrypted:
12133   {
12134     GST_ELEMENT_ERROR (qtdemux, STREAM, DECRYPT, (NULL), (NULL));
12135     gst_qtdemux_stream_free (stream);
12136     return FALSE;
12137   }
12138 samples_failed:
12139 segments_failed:
12140   {
12141     /* we posted an error already */
12142     /* free stbl sub-atoms */
12143     gst_qtdemux_stbl_free (stream);
12144     gst_qtdemux_stream_free (stream);
12145     return FALSE;
12146   }
12147 existing_stream:
12148   {
12149     GST_INFO_OBJECT (qtdemux, "stream with track id %i already exists",
12150         track_id);
12151     return TRUE;
12152   }
12153 unknown_stream:
12154   {
12155     GST_INFO_OBJECT (qtdemux, "unknown subtype %" GST_FOURCC_FORMAT,
12156         GST_FOURCC_ARGS (stream->subtype));
12157     gst_qtdemux_stream_free (stream);
12158     return TRUE;
12159   }
12160 }
12161
12162 /* If we can estimate the overall bitrate, and don't have information about the
12163  * stream bitrate for exactly one stream, this guesses the stream bitrate as
12164  * the overall bitrate minus the sum of the bitrates of all other streams. This
12165  * should be useful for the common case where we have one audio and one video
12166  * stream and can estimate the bitrate of one, but not the other. */
12167 static void
12168 gst_qtdemux_guess_bitrate (GstQTDemux * qtdemux)
12169 {
12170   QtDemuxStream *stream = NULL;
12171   gint64 size, sys_bitrate, sum_bitrate = 0;
12172   GstClockTime duration;
12173   guint bitrate;
12174   GList *iter;
12175
12176   if (qtdemux->fragmented)
12177     return;
12178
12179   GST_DEBUG_OBJECT (qtdemux, "Looking for streams with unknown bitrate");
12180
12181   if (!gst_pad_peer_query_duration (qtdemux->sinkpad, GST_FORMAT_BYTES, &size)
12182       || size <= 0) {
12183     GST_DEBUG_OBJECT (qtdemux,
12184         "Size in bytes of the stream not known - bailing");
12185     return;
12186   }
12187
12188   /* Subtract the header size */
12189   GST_DEBUG_OBJECT (qtdemux, "Total size %" G_GINT64_FORMAT ", header size %u",
12190       size, qtdemux->header_size);
12191
12192   if (size < qtdemux->header_size)
12193     return;
12194
12195   size = size - qtdemux->header_size;
12196
12197   if (!gst_qtdemux_get_duration (qtdemux, &duration)) {
12198     GST_DEBUG_OBJECT (qtdemux, "Stream duration not known - bailing");
12199     return;
12200   }
12201
12202   for (iter = qtdemux->active_streams; iter; iter = g_list_next (iter)) {
12203     QtDemuxStream *str = QTDEMUX_STREAM (iter->data);
12204     switch (str->subtype) {
12205       case FOURCC_soun:
12206       case FOURCC_vide:
12207         GST_DEBUG_OBJECT (qtdemux, "checking bitrate for %" GST_PTR_FORMAT,
12208             CUR_STREAM (str)->caps);
12209         /* retrieve bitrate, prefer avg then max */
12210         bitrate = 0;
12211         if (str->stream_tags) {
12212           if (gst_tag_list_get_uint (str->stream_tags,
12213                   GST_TAG_MAXIMUM_BITRATE, &bitrate))
12214             GST_DEBUG_OBJECT (qtdemux, "max-bitrate: %u", bitrate);
12215           if (gst_tag_list_get_uint (str->stream_tags,
12216                   GST_TAG_NOMINAL_BITRATE, &bitrate))
12217             GST_DEBUG_OBJECT (qtdemux, "nominal-bitrate: %u", bitrate);
12218           if (gst_tag_list_get_uint (str->stream_tags,
12219                   GST_TAG_BITRATE, &bitrate))
12220             GST_DEBUG_OBJECT (qtdemux, "bitrate: %u", bitrate);
12221         }
12222         if (bitrate)
12223           sum_bitrate += bitrate;
12224         else {
12225           if (stream) {
12226             GST_DEBUG_OBJECT (qtdemux,
12227                 ">1 stream with unknown bitrate - bailing");
12228             return;
12229           } else
12230             stream = str;
12231         }
12232
12233       default:
12234         /* For other subtypes, we assume no significant impact on bitrate */
12235         break;
12236     }
12237   }
12238
12239   if (!stream) {
12240     GST_DEBUG_OBJECT (qtdemux, "All stream bitrates are known");
12241     return;
12242   }
12243
12244   sys_bitrate = gst_util_uint64_scale (size, GST_SECOND * 8, duration);
12245
12246   if (sys_bitrate < sum_bitrate) {
12247     /* This can happen, since sum_bitrate might be derived from maximum
12248      * bitrates and not average bitrates */
12249     GST_DEBUG_OBJECT (qtdemux,
12250         "System bitrate less than sum bitrate - bailing");
12251     return;
12252   }
12253
12254   bitrate = sys_bitrate - sum_bitrate;
12255   GST_DEBUG_OBJECT (qtdemux, "System bitrate = %" G_GINT64_FORMAT
12256       ", Stream bitrate = %u", sys_bitrate, bitrate);
12257
12258   if (!stream->stream_tags)
12259     stream->stream_tags = gst_tag_list_new_empty ();
12260   else
12261     stream->stream_tags = gst_tag_list_make_writable (stream->stream_tags);
12262
12263   gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
12264       GST_TAG_BITRATE, bitrate, NULL);
12265 }
12266
12267 static GstFlowReturn
12268 qtdemux_prepare_streams (GstQTDemux * qtdemux)
12269 {
12270   GstFlowReturn ret = GST_FLOW_OK;
12271   GList *iter, *next;
12272
12273   GST_DEBUG_OBJECT (qtdemux, "prepare streams");
12274
12275   for (iter = qtdemux->active_streams; ret == GST_FLOW_OK && iter; iter = next) {
12276     QtDemuxStream *stream = QTDEMUX_STREAM (iter->data);
12277     guint32 sample_num = 0;
12278
12279     next = iter->next;
12280
12281     GST_DEBUG_OBJECT (qtdemux, "track-id %u, fourcc %" GST_FOURCC_FORMAT,
12282         stream->track_id, GST_FOURCC_ARGS (CUR_STREAM (stream)->fourcc));
12283
12284     if (qtdemux->fragmented) {
12285       /* need all moov samples first */
12286       GST_OBJECT_LOCK (qtdemux);
12287       while (stream->n_samples == 0)
12288         if ((ret = qtdemux_add_fragmented_samples (qtdemux)) != GST_FLOW_OK)
12289           break;
12290       GST_OBJECT_UNLOCK (qtdemux);
12291     } else {
12292       /* discard any stray moof */
12293       qtdemux->moof_offset = 0;
12294     }
12295
12296     /* prepare braking */
12297     if (ret != GST_FLOW_ERROR)
12298       ret = GST_FLOW_OK;
12299
12300     /* in pull mode, we should have parsed some sample info by now;
12301      * and quite some code will not handle no samples.
12302      * in push mode, we'll just have to deal with it */
12303     if (G_UNLIKELY (qtdemux->pullbased && !stream->n_samples)) {
12304       GST_DEBUG_OBJECT (qtdemux, "no samples for stream; discarding");
12305       gst_qtdemux_remove_stream (qtdemux, stream);
12306       continue;
12307     } else if (stream->track_id == qtdemux->chapters_track_id &&
12308         (stream->subtype == FOURCC_text || stream->subtype == FOURCC_sbtl)) {
12309       /* TODO - parse chapters track and expose it as GstToc; For now just ignore it
12310          so that it doesn't look like a subtitle track */
12311       gst_qtdemux_remove_stream (qtdemux, stream);
12312       continue;
12313     }
12314
12315     /* parse the initial sample for use in setting the frame rate cap */
12316     while (sample_num == 0 && sample_num < stream->n_samples) {
12317       if (!qtdemux_parse_samples (qtdemux, stream, sample_num))
12318         break;
12319       ++sample_num;
12320     }
12321   }
12322
12323   return ret;
12324 }
12325
12326 static GList *
12327 _stream_in_list (GList * list, QtDemuxStream * stream)
12328 {
12329   GList *iter;
12330
12331   for (iter = list; iter; iter = g_list_next (iter)) {
12332     QtDemuxStream *tmp = QTDEMUX_STREAM (iter->data);
12333     if (!g_strcmp0 (tmp->stream_id, stream->stream_id))
12334       return iter;
12335   }
12336
12337   return NULL;
12338 }
12339
12340 static gboolean
12341 qtdemux_is_streams_update (GstQTDemux * qtdemux)
12342 {
12343   GList *new, *old;
12344
12345   g_return_val_if_fail (qtdemux->active_streams != NULL, FALSE);
12346
12347   /* streams in list are sorted in track-id order */
12348   for (new = qtdemux->active_streams, old = qtdemux->old_streams; new && old;
12349       new = g_list_next (new), old = g_list_next (old)) {
12350
12351     /* Different stream-id, updated */
12352     if (g_strcmp0 (QTDEMUX_STREAM (new->data)->stream_id,
12353             QTDEMUX_STREAM (old->data)->stream_id))
12354       return TRUE;
12355   }
12356
12357   /* Different length, updated */
12358   if (new != NULL || old != NULL)
12359     return TRUE;
12360
12361   return FALSE;
12362 }
12363
12364 static gboolean
12365 qtdemux_reuse_and_configure_stream (GstQTDemux * qtdemux,
12366     QtDemuxStream * oldstream, QtDemuxStream * newstream)
12367 {
12368   /* Connect old stream's srcpad to new stream */
12369   newstream->pad = oldstream->pad;
12370   oldstream->pad = NULL;
12371
12372   /* unset new_stream to prevent stream-start event */
12373   newstream->new_stream = FALSE;
12374
12375   return gst_qtdemux_configure_stream (qtdemux, newstream);
12376 }
12377
12378 static gboolean
12379 qtdemux_update_streams (GstQTDemux * qtdemux)
12380 {
12381   GList *iter, *next;
12382
12383   /* At below, figure out which stream in active_streams has identical stream-id
12384    * with that of in old_streams. If there is matching stream-id,
12385    * corresponding newstream will not be exposed again,
12386    * but demux will reuse srcpad of matched old stream
12387    *
12388    * active_streams : newly created streams from the latest moov
12389    * old_streams : existing streams (belong to previous moov)
12390    */
12391
12392   /* Count n_streams again */
12393   qtdemux->n_streams = 0;
12394
12395   for (iter = qtdemux->active_streams; iter; iter = next) {
12396     GList *tmp;
12397     QtDemuxStream *stream = QTDEMUX_STREAM (iter->data);
12398
12399     next = iter->next;
12400
12401     GST_DEBUG_OBJECT (qtdemux, "track-id %u, fourcc %" GST_FOURCC_FORMAT,
12402         stream->track_id, GST_FOURCC_ARGS (CUR_STREAM (stream)->fourcc));
12403
12404     qtdemux->n_streams++;
12405
12406     if (qtdemux->streams_aware
12407         && (tmp = _stream_in_list (qtdemux->old_streams, stream)) != NULL
12408         && QTDEMUX_STREAM (tmp->data)->pad) {
12409       QtDemuxStream *oldstream = QTDEMUX_STREAM (tmp->data);
12410
12411       GST_DEBUG_OBJECT (qtdemux, "Reuse track-id %d", oldstream->track_id);
12412
12413       if (!qtdemux_reuse_and_configure_stream (qtdemux, oldstream, stream))
12414         return FALSE;
12415
12416       qtdemux->old_streams = g_list_remove (qtdemux->old_streams, oldstream);
12417       gst_qtdemux_stream_free (oldstream);
12418     } else {
12419       GstTagList *list;
12420
12421       /* now we have all info and can expose */
12422       list = stream->stream_tags;
12423       stream->stream_tags = NULL;
12424       if (!gst_qtdemux_add_stream (qtdemux, stream, list))
12425         return FALSE;
12426     }
12427   }
12428
12429   return TRUE;
12430 }
12431
12432 /* Must be called with expose lock */
12433 static GstFlowReturn
12434 qtdemux_expose_streams (GstQTDemux * qtdemux)
12435 {
12436   GList *iter, *next;
12437
12438   GST_DEBUG_OBJECT (qtdemux, "exposing streams");
12439
12440   if (!qtdemux_is_streams_update (qtdemux)) {
12441     GList *new, *old;
12442
12443     GST_DEBUG_OBJECT (qtdemux, "Reuse all streams");
12444     for (new = qtdemux->active_streams, old = qtdemux->old_streams; new && old;
12445         new = g_list_next (new), old = g_list_next (old)) {
12446       if (!qtdemux_reuse_and_configure_stream (qtdemux,
12447               QTDEMUX_STREAM (old->data), QTDEMUX_STREAM (new->data)))
12448         return GST_FLOW_ERROR;
12449     }
12450
12451     g_list_free_full (qtdemux->old_streams,
12452         (GDestroyNotify) gst_qtdemux_stream_free);
12453     qtdemux->old_streams = NULL;
12454
12455     return GST_FLOW_OK;
12456   }
12457
12458   if (qtdemux->streams_aware) {
12459     if (!qtdemux_update_streams (qtdemux))
12460       return GST_FLOW_ERROR;
12461   } else {
12462     for (iter = qtdemux->active_streams; iter; iter = g_list_next (iter)) {
12463       QtDemuxStream *stream = QTDEMUX_STREAM (iter->data);
12464       GstTagList *list;
12465
12466       /* now we have all info and can expose */
12467       list = stream->stream_tags;
12468       stream->stream_tags = NULL;
12469       if (!gst_qtdemux_add_stream (qtdemux, stream, list))
12470         return GST_FLOW_ERROR;
12471
12472     }
12473   }
12474
12475   gst_qtdemux_guess_bitrate (qtdemux);
12476
12477   gst_element_no_more_pads (GST_ELEMENT_CAST (qtdemux));
12478
12479   /* If we have still old_streams, it's no more used stream */
12480   for (iter = qtdemux->old_streams; iter; iter = next) {
12481     QtDemuxStream *stream = QTDEMUX_STREAM (iter->data);
12482     next = g_list_next (iter);
12483
12484     if (stream->pad) {
12485       GstEvent *event;
12486
12487       event = gst_event_new_eos ();
12488       if (qtdemux->segment_seqnum)
12489         gst_event_set_seqnum (event, qtdemux->segment_seqnum);
12490
12491       gst_pad_push_event (stream->pad, event);
12492     }
12493
12494     qtdemux->old_streams = g_list_remove (qtdemux->old_streams, stream);
12495     gst_qtdemux_stream_free (stream);
12496   }
12497
12498   /* check if we should post a redirect in case there is a single trak
12499    * and it is a redirecting trak */
12500   if (qtdemux->n_streams == 1 &&
12501       QTDEMUX_FIRST_STREAM (qtdemux)->redirect_uri != NULL) {
12502     GstMessage *m;
12503
12504     GST_INFO_OBJECT (qtdemux, "Issuing a redirect due to a single track with "
12505         "an external content");
12506     m = gst_message_new_element (GST_OBJECT_CAST (qtdemux),
12507         gst_structure_new ("redirect",
12508             "new-location", G_TYPE_STRING,
12509             QTDEMUX_FIRST_STREAM (qtdemux)->redirect_uri, NULL));
12510     gst_element_post_message (GST_ELEMENT_CAST (qtdemux), m);
12511     qtdemux->posted_redirect = TRUE;
12512   }
12513
12514   for (iter = qtdemux->active_streams; iter; iter = g_list_next (iter)) {
12515     qtdemux_do_allocation (qtdemux, QTDEMUX_STREAM (iter->data));
12516   }
12517
12518   qtdemux->exposed = TRUE;
12519   return GST_FLOW_OK;
12520 }
12521
12522 /* check if major or compatible brand is 3GP */
12523 static inline gboolean
12524 qtdemux_is_brand_3gp (GstQTDemux * qtdemux, gboolean major)
12525 {
12526   if (major) {
12527     return ((qtdemux->major_brand & GST_MAKE_FOURCC (255, 255, 0, 0)) ==
12528         FOURCC_3g__);
12529   } else if (qtdemux->comp_brands != NULL) {
12530     GstMapInfo map;
12531     guint8 *data;
12532     gsize size;
12533     gboolean res = FALSE;
12534
12535     gst_buffer_map (qtdemux->comp_brands, &map, GST_MAP_READ);
12536     data = map.data;
12537     size = map.size;
12538     while (size >= 4) {
12539       res = res || ((QT_FOURCC (data) & GST_MAKE_FOURCC (255, 255, 0, 0)) ==
12540           FOURCC_3g__);
12541       data += 4;
12542       size -= 4;
12543     }
12544     gst_buffer_unmap (qtdemux->comp_brands, &map);
12545     return res;
12546   } else {
12547     return FALSE;
12548   }
12549 }
12550
12551 /* check if tag is a spec'ed 3GP tag keyword storing a string */
12552 static inline gboolean
12553 qtdemux_is_string_tag_3gp (GstQTDemux * qtdemux, guint32 fourcc)
12554 {
12555   return fourcc == FOURCC_cprt || fourcc == FOURCC_gnre || fourcc == FOURCC_titl
12556       || fourcc == FOURCC_dscp || fourcc == FOURCC_perf || fourcc == FOURCC_auth
12557       || fourcc == FOURCC_albm;
12558 }
12559
12560 static void
12561 qtdemux_tag_add_location (GstQTDemux * qtdemux, GstTagList * taglist,
12562     const char *tag, const char *dummy, GNode * node)
12563 {
12564   const gchar *env_vars[] = { "GST_QT_TAG_ENCODING", "GST_TAG_ENCODING", NULL };
12565   int offset;
12566   char *name;
12567   gchar *data;
12568   gdouble longitude, latitude, altitude;
12569   gint len;
12570
12571   len = QT_UINT32 (node->data);
12572   if (len <= 14)
12573     goto short_read;
12574
12575   data = node->data;
12576   offset = 14;
12577
12578   /* TODO: language code skipped */
12579
12580   name = gst_tag_freeform_string_to_utf8 (data + offset, -1, env_vars);
12581
12582   if (!name) {
12583     /* do not alarm in trivial case, but bail out otherwise */
12584     if (*(data + offset) != 0) {
12585       GST_DEBUG_OBJECT (qtdemux, "failed to convert %s tag to UTF-8, "
12586           "giving up", tag);
12587     }
12588   } else {
12589     gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE,
12590         GST_TAG_GEO_LOCATION_NAME, name, NULL);
12591     offset += strlen (name);
12592     g_free (name);
12593   }
12594
12595   if (len < offset + 2 + 4 + 4 + 4)
12596     goto short_read;
12597
12598   /* +1 +1 = skip null-terminator and location role byte */
12599   offset += 1 + 1;
12600   /* table in spec says unsigned, semantics say negative has meaning ... */
12601   longitude = QT_SFP32 (data + offset);
12602
12603   offset += 4;
12604   latitude = QT_SFP32 (data + offset);
12605
12606   offset += 4;
12607   altitude = QT_SFP32 (data + offset);
12608
12609   /* one invalid means all are invalid */
12610   if (longitude >= -180.0 && longitude <= 180.0 &&
12611       latitude >= -90.0 && latitude <= 90.0) {
12612     gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE,
12613         GST_TAG_GEO_LOCATION_LATITUDE, latitude,
12614         GST_TAG_GEO_LOCATION_LONGITUDE, longitude,
12615         GST_TAG_GEO_LOCATION_ELEVATION, altitude, NULL);
12616   }
12617
12618   /* TODO: no GST_TAG_, so astronomical body and additional notes skipped */
12619
12620   return;
12621
12622   /* ERRORS */
12623 short_read:
12624   {
12625     GST_DEBUG_OBJECT (qtdemux, "short read parsing 3GP location");
12626     return;
12627   }
12628 }
12629
12630
12631 static void
12632 qtdemux_tag_add_year (GstQTDemux * qtdemux, GstTagList * taglist,
12633     const char *tag, const char *dummy, GNode * node)
12634 {
12635   guint16 y;
12636   GDate *date;
12637   gint len;
12638
12639   len = QT_UINT32 (node->data);
12640   if (len < 14)
12641     return;
12642
12643   y = QT_UINT16 ((guint8 *) node->data + 12);
12644   if (y == 0) {
12645     GST_DEBUG_OBJECT (qtdemux, "year: %u is not a valid year", y);
12646     return;
12647   }
12648   GST_DEBUG_OBJECT (qtdemux, "year: %u", y);
12649
12650   date = g_date_new_dmy (1, 1, y);
12651   gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag, date, NULL);
12652   g_date_free (date);
12653 }
12654
12655 static void
12656 qtdemux_tag_add_classification (GstQTDemux * qtdemux, GstTagList * taglist,
12657     const char *tag, const char *dummy, GNode * node)
12658 {
12659   int offset;
12660   char *tag_str = NULL;
12661   guint8 *entity;
12662   guint16 table;
12663   gint len;
12664
12665   len = QT_UINT32 (node->data);
12666   if (len <= 20)
12667     goto short_read;
12668
12669   offset = 12;
12670   entity = (guint8 *) node->data + offset;
12671   if (entity[0] == 0 || entity[1] == 0 || entity[2] == 0 || entity[3] == 0) {
12672     GST_DEBUG_OBJECT (qtdemux,
12673         "classification info: %c%c%c%c invalid classification entity",
12674         entity[0], entity[1], entity[2], entity[3]);
12675     return;
12676   }
12677
12678   offset += 4;
12679   table = QT_UINT16 ((guint8 *) node->data + offset);
12680
12681   /* Language code skipped */
12682
12683   offset += 4;
12684
12685   /* Tag format: "XXXX://Y[YYYY]/classification info string"
12686    * XXXX: classification entity, fixed length 4 chars.
12687    * Y[YYYY]: classification table, max 5 chars.
12688    */
12689   tag_str = g_strdup_printf ("----://%u/%s",
12690       table, (char *) node->data + offset);
12691
12692   /* memcpy To be sure we're preserving byte order */
12693   memcpy (tag_str, entity, 4);
12694   GST_DEBUG_OBJECT (qtdemux, "classification info: %s", tag_str);
12695
12696   gst_tag_list_add (taglist, GST_TAG_MERGE_APPEND, tag, tag_str, NULL);
12697
12698   g_free (tag_str);
12699
12700   return;
12701
12702   /* ERRORS */
12703 short_read:
12704   {
12705     GST_DEBUG_OBJECT (qtdemux, "short read parsing 3GP classification");
12706     return;
12707   }
12708 }
12709
12710 static gboolean
12711 qtdemux_tag_add_str_full (GstQTDemux * qtdemux, GstTagList * taglist,
12712     const char *tag, const char *dummy, GNode * node)
12713 {
12714   const gchar *env_vars[] = { "GST_QT_TAG_ENCODING", "GST_TAG_ENCODING", NULL };
12715   GNode *data;
12716   char *s;
12717   int len;
12718   guint32 type;
12719   int offset;
12720   gboolean ret = TRUE;
12721   const gchar *charset = NULL;
12722
12723   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
12724   if (data) {
12725     len = QT_UINT32 (data->data);
12726     type = QT_UINT32 ((guint8 *) data->data + 8);
12727     if (type == 0x00000001 && len > 16) {
12728       s = gst_tag_freeform_string_to_utf8 ((char *) data->data + 16, len - 16,
12729           env_vars);
12730       if (s) {
12731         GST_DEBUG_OBJECT (qtdemux, "adding tag %s", GST_STR_NULL (s));
12732         gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag, s, NULL);
12733         g_free (s);
12734       } else {
12735         GST_DEBUG_OBJECT (qtdemux, "failed to convert %s tag to UTF-8", tag);
12736       }
12737     }
12738   } else {
12739     len = QT_UINT32 (node->data);
12740     type = QT_UINT32 ((guint8 *) node->data + 4);
12741     if ((type >> 24) == 0xa9 && len > 8 + 4) {
12742       gint str_len;
12743       gint lang_code;
12744
12745       /* Type starts with the (C) symbol, so the next data is a list
12746        * of (string size(16), language code(16), string) */
12747
12748       str_len = QT_UINT16 ((guint8 *) node->data + 8);
12749       lang_code = QT_UINT16 ((guint8 *) node->data + 10);
12750
12751       /* the string + fourcc + size + 2 16bit fields,
12752        * means that there are more tags in this atom */
12753       if (len > str_len + 8 + 4) {
12754         /* TODO how to represent the same tag in different languages? */
12755         GST_WARNING_OBJECT (qtdemux, "Ignoring metadata entry with multiple "
12756             "text alternatives, reading only first one");
12757       }
12758
12759       offset = 12;
12760       len = MIN (len, str_len + 8 + 4); /* remove trailing strings that we don't use */
12761       GST_DEBUG_OBJECT (qtdemux, "found international text tag");
12762
12763       if (lang_code < 0x800) {  /* MAC encoded string */
12764         charset = "mac";
12765       }
12766     } else if (len > 14 && qtdemux_is_string_tag_3gp (qtdemux,
12767             QT_FOURCC ((guint8 *) node->data + 4))) {
12768       guint32 type = QT_UINT32 ((guint8 *) node->data + 8);
12769
12770       /* we go for 3GP style encoding if major brands claims so,
12771        * or if no hope for data be ok UTF-8, and compatible 3GP brand present */
12772       if (qtdemux_is_brand_3gp (qtdemux, TRUE) ||
12773           (qtdemux_is_brand_3gp (qtdemux, FALSE) &&
12774               ((type & 0x00FFFFFF) == 0x0) && (type >> 24 <= 0xF))) {
12775         offset = 14;
12776         /* 16-bit Language code is ignored here as well */
12777         GST_DEBUG_OBJECT (qtdemux, "found 3gpp text tag");
12778       } else {
12779         goto normal;
12780       }
12781     } else {
12782     normal:
12783       offset = 8;
12784       GST_DEBUG_OBJECT (qtdemux, "found normal text tag");
12785       ret = FALSE;              /* may have to fallback */
12786     }
12787     if (charset) {
12788       GError *err = NULL;
12789
12790       s = g_convert ((gchar *) node->data + offset, len - offset, "utf8",
12791           charset, NULL, NULL, &err);
12792       if (err) {
12793         GST_DEBUG_OBJECT (qtdemux, "Failed to convert string from charset %s:"
12794             " %s(%d): %s", charset, g_quark_to_string (err->domain), err->code,
12795             err->message);
12796         g_error_free (err);
12797       }
12798     } else {
12799       s = gst_tag_freeform_string_to_utf8 ((char *) node->data + offset,
12800           len - offset, env_vars);
12801     }
12802     if (s) {
12803       GST_DEBUG_OBJECT (qtdemux, "adding tag %s", GST_STR_NULL (s));
12804       gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag, s, NULL);
12805       g_free (s);
12806       ret = TRUE;
12807     } else {
12808       GST_DEBUG_OBJECT (qtdemux, "failed to convert %s tag to UTF-8", tag);
12809     }
12810   }
12811   return ret;
12812 }
12813
12814 static void
12815 qtdemux_tag_add_str (GstQTDemux * qtdemux, GstTagList * taglist,
12816     const char *tag, const char *dummy, GNode * node)
12817 {
12818   qtdemux_tag_add_str_full (qtdemux, taglist, tag, dummy, node);
12819 }
12820
12821 static void
12822 qtdemux_tag_add_keywords (GstQTDemux * qtdemux, GstTagList * taglist,
12823     const char *tag, const char *dummy, GNode * node)
12824 {
12825   const gchar *env_vars[] = { "GST_QT_TAG_ENCODING", "GST_TAG_ENCODING", NULL };
12826   guint8 *data;
12827   char *s, *t, *k = NULL;
12828   int len;
12829   int offset;
12830   int count;
12831
12832   /* first try normal string tag if major brand not 3GP */
12833   if (!qtdemux_is_brand_3gp (qtdemux, TRUE)) {
12834     if (!qtdemux_tag_add_str_full (qtdemux, taglist, tag, dummy, node)) {
12835       /* hm, that did not work, maybe 3gpp storage in non-3gpp major brand;
12836        * let's try it 3gpp way after minor safety check */
12837       data = node->data;
12838       if (QT_UINT32 (data) < 15 || !qtdemux_is_brand_3gp (qtdemux, FALSE))
12839         return;
12840     } else
12841       return;
12842   }
12843
12844   GST_DEBUG_OBJECT (qtdemux, "found 3gpp keyword tag");
12845
12846   data = node->data;
12847
12848   len = QT_UINT32 (data);
12849   if (len < 15)
12850     goto short_read;
12851
12852   count = QT_UINT8 (data + 14);
12853   offset = 15;
12854   for (; count; count--) {
12855     gint slen;
12856
12857     if (offset + 1 > len)
12858       goto short_read;
12859     slen = QT_UINT8 (data + offset);
12860     offset += 1;
12861     if (offset + slen > len)
12862       goto short_read;
12863     s = gst_tag_freeform_string_to_utf8 ((char *) node->data + offset,
12864         slen, env_vars);
12865     if (s) {
12866       GST_DEBUG_OBJECT (qtdemux, "adding keyword %s", GST_STR_NULL (s));
12867       if (k) {
12868         t = g_strjoin (",", k, s, NULL);
12869         g_free (s);
12870         g_free (k);
12871         k = t;
12872       } else {
12873         k = s;
12874       }
12875     } else {
12876       GST_DEBUG_OBJECT (qtdemux, "failed to convert keyword to UTF-8");
12877     }
12878     offset += slen;
12879   }
12880
12881 done:
12882   if (k) {
12883     GST_DEBUG_OBJECT (qtdemux, "adding tag %s", GST_STR_NULL (k));
12884     gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag, k, NULL);
12885   }
12886   g_free (k);
12887
12888   return;
12889
12890   /* ERRORS */
12891 short_read:
12892   {
12893     GST_DEBUG_OBJECT (qtdemux, "short read parsing 3GP keywords");
12894     goto done;
12895   }
12896 }
12897
12898 static void
12899 qtdemux_tag_add_num (GstQTDemux * qtdemux, GstTagList * taglist,
12900     const char *tag1, const char *tag2, GNode * node)
12901 {
12902   GNode *data;
12903   int len;
12904   int type;
12905   int n1, n2;
12906
12907   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
12908   if (data) {
12909     len = QT_UINT32 (data->data);
12910     type = QT_UINT32 ((guint8 *) data->data + 8);
12911     if (type == 0x00000000 && len >= 22) {
12912       n1 = QT_UINT16 ((guint8 *) data->data + 18);
12913       n2 = QT_UINT16 ((guint8 *) data->data + 20);
12914       if (n1 > 0) {
12915         GST_DEBUG_OBJECT (qtdemux, "adding tag %s=%d", tag1, n1);
12916         gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag1, n1, NULL);
12917       }
12918       if (n2 > 0) {
12919         GST_DEBUG_OBJECT (qtdemux, "adding tag %s=%d", tag2, n2);
12920         gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag2, n2, NULL);
12921       }
12922     }
12923   }
12924 }
12925
12926 static void
12927 qtdemux_tag_add_tmpo (GstQTDemux * qtdemux, GstTagList * taglist,
12928     const char *tag1, const char *dummy, GNode * node)
12929 {
12930   GNode *data;
12931   int len;
12932   int type;
12933   int n1;
12934
12935   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
12936   if (data) {
12937     len = QT_UINT32 (data->data);
12938     type = QT_UINT32 ((guint8 *) data->data + 8);
12939     GST_DEBUG_OBJECT (qtdemux, "have tempo tag, type=%d,len=%d", type, len);
12940     /* some files wrongly have a type 0x0f=15, but it should be 0x15 */
12941     if ((type == 0x00000015 || type == 0x0000000f) && len >= 18) {
12942       n1 = QT_UINT16 ((guint8 *) data->data + 16);
12943       if (n1) {
12944         /* do not add bpm=0 */
12945         GST_DEBUG_OBJECT (qtdemux, "adding tag %d", n1);
12946         gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag1, (gdouble) n1,
12947             NULL);
12948       }
12949     }
12950   }
12951 }
12952
12953 static void
12954 qtdemux_tag_add_uint32 (GstQTDemux * qtdemux, GstTagList * taglist,
12955     const char *tag1, const char *dummy, GNode * node)
12956 {
12957   GNode *data;
12958   int len;
12959   int type;
12960   guint32 num;
12961
12962   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
12963   if (data) {
12964     len = QT_UINT32 (data->data);
12965     type = QT_UINT32 ((guint8 *) data->data + 8);
12966     GST_DEBUG_OBJECT (qtdemux, "have %s tag, type=%d,len=%d", tag1, type, len);
12967     /* some files wrongly have a type 0x0f=15, but it should be 0x15 */
12968     if ((type == 0x00000015 || type == 0x0000000f) && len >= 20) {
12969       num = QT_UINT32 ((guint8 *) data->data + 16);
12970       if (num) {
12971         /* do not add num=0 */
12972         GST_DEBUG_OBJECT (qtdemux, "adding tag %d", num);
12973         gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag1, num, NULL);
12974       }
12975     }
12976   }
12977 }
12978
12979 static void
12980 qtdemux_tag_add_covr (GstQTDemux * qtdemux, GstTagList * taglist,
12981     const char *tag1, const char *dummy, GNode * node)
12982 {
12983   GNode *data;
12984   int len;
12985   int type;
12986   GstSample *sample;
12987
12988   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
12989   if (data) {
12990     len = QT_UINT32 (data->data);
12991     type = QT_UINT32 ((guint8 *) data->data + 8);
12992     GST_DEBUG_OBJECT (qtdemux, "have covr tag, type=%d,len=%d", type, len);
12993     if ((type == 0x0000000d || type == 0x0000000e) && len > 16) {
12994       GstTagImageType image_type;
12995
12996       if (gst_tag_list_get_tag_size (taglist, GST_TAG_IMAGE) == 0)
12997         image_type = GST_TAG_IMAGE_TYPE_FRONT_COVER;
12998       else
12999         image_type = GST_TAG_IMAGE_TYPE_NONE;
13000
13001       if ((sample =
13002               gst_tag_image_data_to_image_sample ((guint8 *) data->data + 16,
13003                   len - 16, image_type))) {
13004         GST_DEBUG_OBJECT (qtdemux, "adding tag size %d", len - 16);
13005         gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag1, sample, NULL);
13006         gst_sample_unref (sample);
13007       }
13008     }
13009   }
13010 }
13011
13012 static void
13013 qtdemux_tag_add_date (GstQTDemux * qtdemux, GstTagList * taglist,
13014     const char *tag, const char *dummy, GNode * node)
13015 {
13016   GNode *data;
13017   GstDateTime *datetime = NULL;
13018   char *s;
13019   int len;
13020   int type;
13021
13022   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
13023   if (data) {
13024     len = QT_UINT32 (data->data);
13025     type = QT_UINT32 ((guint8 *) data->data + 8);
13026     if (type == 0x00000001 && len > 16) {
13027       guint y, m = 1, d = 1;
13028       gint ret;
13029
13030       s = g_strndup ((char *) data->data + 16, len - 16);
13031       GST_DEBUG_OBJECT (qtdemux, "adding date '%s'", s);
13032       datetime = gst_date_time_new_from_iso8601_string (s);
13033       if (datetime != NULL) {
13034         gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, GST_TAG_DATE_TIME,
13035             datetime, NULL);
13036         gst_date_time_unref (datetime);
13037       }
13038
13039       ret = sscanf (s, "%u-%u-%u", &y, &m, &d);
13040       if (ret >= 1 && y > 1500 && y < 3000) {
13041         GDate *date;
13042
13043         date = g_date_new_dmy (d, m, y);
13044         gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag, date, NULL);
13045         g_date_free (date);
13046       } else {
13047         GST_DEBUG_OBJECT (qtdemux, "could not parse date string '%s'", s);
13048       }
13049       g_free (s);
13050     }
13051   }
13052 }
13053
13054 static void
13055 qtdemux_tag_add_gnre (GstQTDemux * qtdemux, GstTagList * taglist,
13056     const char *tag, const char *dummy, GNode * node)
13057 {
13058   GNode *data;
13059
13060   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
13061
13062   /* re-route to normal string tag if major brand says so
13063    * or no data atom and compatible brand suggests so */
13064   if (qtdemux_is_brand_3gp (qtdemux, TRUE) ||
13065       (qtdemux_is_brand_3gp (qtdemux, FALSE) && !data)) {
13066     qtdemux_tag_add_str (qtdemux, taglist, tag, dummy, node);
13067     return;
13068   }
13069
13070   if (data) {
13071     guint len, type, n;
13072
13073     len = QT_UINT32 (data->data);
13074     type = QT_UINT32 ((guint8 *) data->data + 8);
13075     if (type == 0x00000000 && len >= 18) {
13076       n = QT_UINT16 ((guint8 *) data->data + 16);
13077       if (n > 0) {
13078         const gchar *genre;
13079
13080         genre = gst_tag_id3_genre_get (n - 1);
13081         if (genre != NULL) {
13082           GST_DEBUG_OBJECT (qtdemux, "adding %d [%s]", n, genre);
13083           gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag, genre, NULL);
13084         }
13085       }
13086     }
13087   }
13088 }
13089
13090 static void
13091 qtdemux_add_double_tag_from_str (GstQTDemux * demux, GstTagList * taglist,
13092     const gchar * tag, guint8 * data, guint32 datasize)
13093 {
13094   gdouble value;
13095   gchar *datacopy;
13096
13097   /* make a copy to have \0 at the end */
13098   datacopy = g_strndup ((gchar *) data, datasize);
13099
13100   /* convert the str to double */
13101   if (sscanf (datacopy, "%lf", &value) == 1) {
13102     GST_DEBUG_OBJECT (demux, "adding tag: %s [%s]", tag, datacopy);
13103     gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag, value, NULL);
13104   } else {
13105     GST_WARNING_OBJECT (demux, "Failed to parse double from string: %s",
13106         datacopy);
13107   }
13108   g_free (datacopy);
13109 }
13110
13111
13112 static void
13113 qtdemux_tag_add_revdns (GstQTDemux * demux, GstTagList * taglist,
13114     const char *tag, const char *tag_bis, GNode * node)
13115 {
13116   GNode *mean;
13117   GNode *name;
13118   GNode *data;
13119   guint32 meansize;
13120   guint32 namesize;
13121   guint32 datatype;
13122   guint32 datasize;
13123   const gchar *meanstr;
13124   const gchar *namestr;
13125
13126   /* checking the whole ---- atom size for consistency */
13127   if (QT_UINT32 (node->data) <= 4 + 12 + 12 + 16) {
13128     GST_WARNING_OBJECT (demux, "Tag ---- atom is too small, ignoring");
13129     return;
13130   }
13131
13132   mean = qtdemux_tree_get_child_by_type (node, FOURCC_mean);
13133   if (!mean) {
13134     GST_WARNING_OBJECT (demux, "No 'mean' atom found");
13135     return;
13136   }
13137
13138   meansize = QT_UINT32 (mean->data);
13139   if (meansize <= 12) {
13140     GST_WARNING_OBJECT (demux, "Small mean atom, ignoring the whole tag");
13141     return;
13142   }
13143   meanstr = ((gchar *) mean->data) + 12;
13144   meansize -= 12;
13145
13146   name = qtdemux_tree_get_child_by_type (node, FOURCC_name);
13147   if (!name) {
13148     GST_WARNING_OBJECT (demux, "'name' atom not found, ignoring tag");
13149     return;
13150   }
13151
13152   namesize = QT_UINT32 (name->data);
13153   if (namesize <= 12) {
13154     GST_WARNING_OBJECT (demux, "'name' atom is too small, ignoring tag");
13155     return;
13156   }
13157   namestr = ((gchar *) name->data) + 12;
13158   namesize -= 12;
13159
13160   /*
13161    * Data atom is:
13162    * uint32 - size
13163    * uint32 - name
13164    * uint8  - version
13165    * uint24 - data type
13166    * uint32 - all 0
13167    * rest   - the data
13168    */
13169   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
13170   if (!data) {
13171     GST_WARNING_OBJECT (demux, "No data atom in this tag");
13172     return;
13173   }
13174   datasize = QT_UINT32 (data->data);
13175   if (datasize <= 16) {
13176     GST_WARNING_OBJECT (demux, "Data atom too small");
13177     return;
13178   }
13179   datatype = QT_UINT32 (((gchar *) data->data) + 8) & 0xFFFFFF;
13180
13181   if ((strncmp (meanstr, "com.apple.iTunes", meansize) == 0) ||
13182       (strncmp (meanstr, "org.hydrogenaudio.replaygain", meansize) == 0)) {
13183     static const struct
13184     {
13185       const gchar name[28];
13186       const gchar tag[28];
13187     } tags[] = {
13188       {
13189       "replaygain_track_gain", GST_TAG_TRACK_GAIN}, {
13190       "replaygain_track_peak", GST_TAG_TRACK_PEAK}, {
13191       "replaygain_album_gain", GST_TAG_ALBUM_GAIN}, {
13192       "replaygain_album_peak", GST_TAG_ALBUM_PEAK}, {
13193       "MusicBrainz Track Id", GST_TAG_MUSICBRAINZ_TRACKID}, {
13194       "MusicBrainz Artist Id", GST_TAG_MUSICBRAINZ_ARTISTID}, {
13195       "MusicBrainz Album Id", GST_TAG_MUSICBRAINZ_ALBUMID}, {
13196       "MusicBrainz Album Artist Id", GST_TAG_MUSICBRAINZ_ALBUMARTISTID}
13197     };
13198     int i;
13199
13200     for (i = 0; i < G_N_ELEMENTS (tags); ++i) {
13201       if (!g_ascii_strncasecmp (tags[i].name, namestr, namesize)) {
13202         switch (gst_tag_get_type (tags[i].tag)) {
13203           case G_TYPE_DOUBLE:
13204             qtdemux_add_double_tag_from_str (demux, taglist, tags[i].tag,
13205                 ((guint8 *) data->data) + 16, datasize - 16);
13206             break;
13207           case G_TYPE_STRING:
13208             qtdemux_tag_add_str (demux, taglist, tags[i].tag, NULL, node);
13209             break;
13210           default:
13211             /* not reached */
13212             break;
13213         }
13214         break;
13215       }
13216     }
13217     if (i == G_N_ELEMENTS (tags))
13218       goto unknown_tag;
13219   } else {
13220     goto unknown_tag;
13221   }
13222
13223   return;
13224
13225 /* errors */
13226 unknown_tag:
13227 #ifndef GST_DISABLE_GST_DEBUG
13228   {
13229     gchar *namestr_dbg;
13230     gchar *meanstr_dbg;
13231
13232     meanstr_dbg = g_strndup (meanstr, meansize);
13233     namestr_dbg = g_strndup (namestr, namesize);
13234
13235     GST_WARNING_OBJECT (demux, "This tag %s:%s type:%u is not mapped, "
13236         "file a bug at bugzilla.gnome.org", meanstr_dbg, namestr_dbg, datatype);
13237
13238     g_free (namestr_dbg);
13239     g_free (meanstr_dbg);
13240   }
13241 #endif
13242   return;
13243 }
13244
13245 static void
13246 qtdemux_tag_add_id32 (GstQTDemux * demux, GstTagList * taglist, const char *tag,
13247     const char *tag_bis, GNode * node)
13248 {
13249   guint8 *data;
13250   GstBuffer *buf;
13251   guint len;
13252   GstTagList *id32_taglist = NULL;
13253
13254   GST_LOG_OBJECT (demux, "parsing ID32");
13255
13256   data = node->data;
13257   len = GST_READ_UINT32_BE (data);
13258
13259   /* need at least full box and language tag */
13260   if (len < 12 + 2)
13261     return;
13262
13263   buf = gst_buffer_new_allocate (NULL, len - 14, NULL);
13264   gst_buffer_fill (buf, 0, data + 14, len - 14);
13265
13266   id32_taglist = gst_tag_list_from_id3v2_tag (buf);
13267   if (id32_taglist) {
13268     GST_LOG_OBJECT (demux, "parsing ok");
13269     gst_tag_list_insert (taglist, id32_taglist, GST_TAG_MERGE_KEEP);
13270     gst_tag_list_unref (id32_taglist);
13271   } else {
13272     GST_LOG_OBJECT (demux, "parsing failed");
13273   }
13274
13275   gst_buffer_unref (buf);
13276 }
13277
13278 typedef void (*GstQTDemuxAddTagFunc) (GstQTDemux * demux, GstTagList * taglist,
13279     const char *tag, const char *tag_bis, GNode * node);
13280
13281 /* unmapped tags
13282 FOURCC_pcst -> if media is a podcast -> bool
13283 FOURCC_cpil -> if media is part of a compilation -> bool
13284 FOURCC_pgap -> if media is part of a gapless context -> bool
13285 FOURCC_tven -> the tv episode id e.g. S01E23 -> str
13286 */
13287
13288 static const struct
13289 {
13290   guint32 fourcc;
13291   const gchar *gst_tag;
13292   const gchar *gst_tag_bis;
13293   const GstQTDemuxAddTagFunc func;
13294 } add_funcs[] = {
13295   {
13296   FOURCC__nam, GST_TAG_TITLE, NULL, qtdemux_tag_add_str}, {
13297   FOURCC_titl, GST_TAG_TITLE, NULL, qtdemux_tag_add_str}, {
13298   FOURCC__grp, GST_TAG_GROUPING, NULL, qtdemux_tag_add_str}, {
13299   FOURCC__wrt, GST_TAG_COMPOSER, NULL, qtdemux_tag_add_str}, {
13300   FOURCC__ART, GST_TAG_ARTIST, NULL, qtdemux_tag_add_str}, {
13301   FOURCC_aART, GST_TAG_ALBUM_ARTIST, NULL, qtdemux_tag_add_str}, {
13302   FOURCC_perf, GST_TAG_ARTIST, NULL, qtdemux_tag_add_str}, {
13303   FOURCC_auth, GST_TAG_COMPOSER, NULL, qtdemux_tag_add_str}, {
13304   FOURCC__alb, GST_TAG_ALBUM, NULL, qtdemux_tag_add_str}, {
13305   FOURCC_albm, GST_TAG_ALBUM, NULL, qtdemux_tag_add_str}, {
13306   FOURCC_cprt, GST_TAG_COPYRIGHT, NULL, qtdemux_tag_add_str}, {
13307   FOURCC__cpy, GST_TAG_COPYRIGHT, NULL, qtdemux_tag_add_str}, {
13308   FOURCC__cmt, GST_TAG_COMMENT, NULL, qtdemux_tag_add_str}, {
13309   FOURCC__des, GST_TAG_DESCRIPTION, NULL, qtdemux_tag_add_str}, {
13310   FOURCC_desc, GST_TAG_DESCRIPTION, NULL, qtdemux_tag_add_str}, {
13311   FOURCC_dscp, GST_TAG_DESCRIPTION, NULL, qtdemux_tag_add_str}, {
13312   FOURCC__lyr, GST_TAG_LYRICS, NULL, qtdemux_tag_add_str}, {
13313   FOURCC__day, GST_TAG_DATE, NULL, qtdemux_tag_add_date}, {
13314   FOURCC_yrrc, GST_TAG_DATE, NULL, qtdemux_tag_add_year}, {
13315   FOURCC__too, GST_TAG_ENCODER, NULL, qtdemux_tag_add_str}, {
13316   FOURCC__inf, GST_TAG_COMMENT, NULL, qtdemux_tag_add_str}, {
13317   FOURCC_trkn, GST_TAG_TRACK_NUMBER, GST_TAG_TRACK_COUNT, qtdemux_tag_add_num}, {
13318   FOURCC_disk, GST_TAG_ALBUM_VOLUME_NUMBER, GST_TAG_ALBUM_VOLUME_COUNT,
13319         qtdemux_tag_add_num}, {
13320   FOURCC_disc, GST_TAG_ALBUM_VOLUME_NUMBER, GST_TAG_ALBUM_VOLUME_COUNT,
13321         qtdemux_tag_add_num}, {
13322   FOURCC__gen, GST_TAG_GENRE, NULL, qtdemux_tag_add_str}, {
13323   FOURCC_gnre, GST_TAG_GENRE, NULL, qtdemux_tag_add_gnre}, {
13324   FOURCC_tmpo, GST_TAG_BEATS_PER_MINUTE, NULL, qtdemux_tag_add_tmpo}, {
13325   FOURCC_covr, GST_TAG_IMAGE, NULL, qtdemux_tag_add_covr}, {
13326   FOURCC_sonm, GST_TAG_TITLE_SORTNAME, NULL, qtdemux_tag_add_str}, {
13327   FOURCC_soal, GST_TAG_ALBUM_SORTNAME, NULL, qtdemux_tag_add_str}, {
13328   FOURCC_soar, GST_TAG_ARTIST_SORTNAME, NULL, qtdemux_tag_add_str}, {
13329   FOURCC_soaa, GST_TAG_ALBUM_ARTIST_SORTNAME, NULL, qtdemux_tag_add_str}, {
13330   FOURCC_soco, GST_TAG_COMPOSER_SORTNAME, NULL, qtdemux_tag_add_str}, {
13331   FOURCC_sosn, GST_TAG_SHOW_SORTNAME, NULL, qtdemux_tag_add_str}, {
13332   FOURCC_tvsh, GST_TAG_SHOW_NAME, NULL, qtdemux_tag_add_str}, {
13333   FOURCC_tvsn, GST_TAG_SHOW_SEASON_NUMBER, NULL, qtdemux_tag_add_uint32}, {
13334   FOURCC_tves, GST_TAG_SHOW_EPISODE_NUMBER, NULL, qtdemux_tag_add_uint32}, {
13335   FOURCC_kywd, GST_TAG_KEYWORDS, NULL, qtdemux_tag_add_keywords}, {
13336   FOURCC_keyw, GST_TAG_KEYWORDS, NULL, qtdemux_tag_add_str}, {
13337   FOURCC__enc, GST_TAG_ENCODER, NULL, qtdemux_tag_add_str}, {
13338   FOURCC_loci, GST_TAG_GEO_LOCATION_NAME, NULL, qtdemux_tag_add_location}, {
13339   FOURCC_clsf, GST_QT_DEMUX_CLASSIFICATION_TAG, NULL,
13340         qtdemux_tag_add_classification}, {
13341   FOURCC__mak, GST_TAG_DEVICE_MANUFACTURER, NULL, qtdemux_tag_add_str}, {
13342   FOURCC__mod, GST_TAG_DEVICE_MODEL, NULL, qtdemux_tag_add_str}, {
13343   FOURCC__swr, GST_TAG_APPLICATION_NAME, NULL, qtdemux_tag_add_str}, {
13344
13345     /* This is a special case, some tags are stored in this
13346      * 'reverse dns naming', according to:
13347      * http://atomicparsley.sourceforge.net/mpeg-4files.html and
13348      * bug #614471
13349      */
13350   FOURCC_____, "", NULL, qtdemux_tag_add_revdns}, {
13351     /* see http://www.mp4ra.org/specs.html for ID32 in meta box */
13352   FOURCC_ID32, "", NULL, qtdemux_tag_add_id32}
13353 };
13354
13355 struct _GstQtDemuxTagList
13356 {
13357   GstQTDemux *demux;
13358   GstTagList *taglist;
13359 };
13360 typedef struct _GstQtDemuxTagList GstQtDemuxTagList;
13361
13362 static void
13363 qtdemux_tag_add_blob (GNode * node, GstQtDemuxTagList * qtdemuxtaglist)
13364 {
13365   gint len;
13366   guint8 *data;
13367   GstBuffer *buf;
13368   gchar *media_type;
13369   const gchar *style;
13370   GstSample *sample;
13371   GstStructure *s;
13372   guint i;
13373   guint8 ndata[4];
13374   GstQTDemux *demux = qtdemuxtaglist->demux;
13375   GstTagList *taglist = qtdemuxtaglist->taglist;
13376
13377   data = node->data;
13378   len = QT_UINT32 (data);
13379   buf = gst_buffer_new_and_alloc (len);
13380   gst_buffer_fill (buf, 0, data, len);
13381
13382   /* heuristic to determine style of tag */
13383   if (QT_FOURCC (data + 4) == FOURCC_____ ||
13384       (len > 8 + 12 && QT_FOURCC (data + 12) == FOURCC_data))
13385     style = "itunes";
13386   else if (demux->major_brand == FOURCC_qt__)
13387     style = "quicktime";
13388   /* fall back to assuming iso/3gp tag style */
13389   else
13390     style = "iso";
13391
13392   /* santize the name for the caps. */
13393   for (i = 0; i < 4; i++) {
13394     guint8 d = data[4 + i];
13395     if (g_ascii_isalnum (d))
13396       ndata[i] = g_ascii_tolower (d);
13397     else
13398       ndata[i] = '_';
13399   }
13400
13401   media_type = g_strdup_printf ("application/x-gst-qt-%c%c%c%c-tag",
13402       ndata[0], ndata[1], ndata[2], ndata[3]);
13403   GST_DEBUG_OBJECT (demux, "media type %s", media_type);
13404
13405   s = gst_structure_new (media_type, "style", G_TYPE_STRING, style, NULL);
13406   sample = gst_sample_new (buf, NULL, NULL, s);
13407   gst_buffer_unref (buf);
13408   g_free (media_type);
13409
13410   GST_DEBUG_OBJECT (demux, "adding private tag; size %d, info %" GST_PTR_FORMAT,
13411       len, s);
13412
13413   gst_tag_list_add (taglist, GST_TAG_MERGE_APPEND,
13414       GST_QT_DEMUX_PRIVATE_TAG, sample, NULL);
13415
13416   gst_sample_unref (sample);
13417 }
13418
13419 static void
13420 qtdemux_parse_udta (GstQTDemux * qtdemux, GstTagList * taglist, GNode * udta)
13421 {
13422   GNode *meta;
13423   GNode *ilst;
13424   GNode *xmp_;
13425   GNode *node;
13426   gint i;
13427   GstQtDemuxTagList demuxtaglist;
13428
13429   demuxtaglist.demux = qtdemux;
13430   demuxtaglist.taglist = taglist;
13431
13432   meta = qtdemux_tree_get_child_by_type (udta, FOURCC_meta);
13433   if (meta != NULL) {
13434     ilst = qtdemux_tree_get_child_by_type (meta, FOURCC_ilst);
13435     if (ilst == NULL) {
13436       GST_LOG_OBJECT (qtdemux, "no ilst");
13437       return;
13438     }
13439   } else {
13440     ilst = udta;
13441     GST_LOG_OBJECT (qtdemux, "no meta so using udta itself");
13442   }
13443
13444   i = 0;
13445   while (i < G_N_ELEMENTS (add_funcs)) {
13446     node = qtdemux_tree_get_child_by_type (ilst, add_funcs[i].fourcc);
13447     if (node) {
13448       gint len;
13449
13450       len = QT_UINT32 (node->data);
13451       if (len < 12) {
13452         GST_DEBUG_OBJECT (qtdemux, "too small tag atom %" GST_FOURCC_FORMAT,
13453             GST_FOURCC_ARGS (add_funcs[i].fourcc));
13454       } else {
13455         add_funcs[i].func (qtdemux, taglist, add_funcs[i].gst_tag,
13456             add_funcs[i].gst_tag_bis, node);
13457       }
13458       g_node_destroy (node);
13459     } else {
13460       i++;
13461     }
13462   }
13463
13464   /* parsed nodes have been removed, pass along remainder as blob */
13465   g_node_children_foreach (ilst, G_TRAVERSE_ALL,
13466       (GNodeForeachFunc) qtdemux_tag_add_blob, &demuxtaglist);
13467
13468   /* parse up XMP_ node if existing */
13469   xmp_ = qtdemux_tree_get_child_by_type (udta, FOURCC_XMP_);
13470   if (xmp_ != NULL) {
13471     GstBuffer *buf;
13472     GstTagList *xmptaglist;
13473
13474     buf = _gst_buffer_new_wrapped (((guint8 *) xmp_->data) + 8,
13475         QT_UINT32 ((guint8 *) xmp_->data) - 8, NULL);
13476     xmptaglist = gst_tag_list_from_xmp_buffer (buf);
13477     gst_buffer_unref (buf);
13478
13479     qtdemux_handle_xmp_taglist (qtdemux, taglist, xmptaglist);
13480   } else {
13481     GST_DEBUG_OBJECT (qtdemux, "No XMP_ node found");
13482   }
13483 }
13484
13485 typedef struct
13486 {
13487   GstStructure *structure;      /* helper for sort function */
13488   gchar *location;
13489   guint min_req_bitrate;
13490   guint min_req_qt_version;
13491 } GstQtReference;
13492
13493 static gint
13494 qtdemux_redirects_sort_func (gconstpointer a, gconstpointer b)
13495 {
13496   GstQtReference *ref_a = (GstQtReference *) a;
13497   GstQtReference *ref_b = (GstQtReference *) b;
13498
13499   if (ref_b->min_req_qt_version != ref_a->min_req_qt_version)
13500     return ref_b->min_req_qt_version - ref_a->min_req_qt_version;
13501
13502   /* known bitrates go before unknown; higher bitrates go first */
13503   return ref_b->min_req_bitrate - ref_a->min_req_bitrate;
13504 }
13505
13506 /* sort the redirects and post a message for the application.
13507  */
13508 static void
13509 qtdemux_process_redirects (GstQTDemux * qtdemux, GList * references)
13510 {
13511   GstQtReference *best;
13512   GstStructure *s;
13513   GstMessage *msg;
13514   GValue list_val = { 0, };
13515   GList *l;
13516
13517   g_assert (references != NULL);
13518
13519   references = g_list_sort (references, qtdemux_redirects_sort_func);
13520
13521   best = (GstQtReference *) references->data;
13522
13523   g_value_init (&list_val, GST_TYPE_LIST);
13524
13525   for (l = references; l != NULL; l = l->next) {
13526     GstQtReference *ref = (GstQtReference *) l->data;
13527     GValue struct_val = { 0, };
13528
13529     ref->structure = gst_structure_new ("redirect",
13530         "new-location", G_TYPE_STRING, ref->location, NULL);
13531
13532     if (ref->min_req_bitrate > 0) {
13533       gst_structure_set (ref->structure, "minimum-bitrate", G_TYPE_INT,
13534           ref->min_req_bitrate, NULL);
13535     }
13536
13537     g_value_init (&struct_val, GST_TYPE_STRUCTURE);
13538     g_value_set_boxed (&struct_val, ref->structure);
13539     gst_value_list_append_value (&list_val, &struct_val);
13540     g_value_unset (&struct_val);
13541     /* don't free anything here yet, since we need best->structure below */
13542   }
13543
13544   g_assert (best != NULL);
13545   s = gst_structure_copy (best->structure);
13546
13547   if (g_list_length (references) > 1) {
13548     gst_structure_set_value (s, "locations", &list_val);
13549   }
13550
13551   g_value_unset (&list_val);
13552
13553   for (l = references; l != NULL; l = l->next) {
13554     GstQtReference *ref = (GstQtReference *) l->data;
13555
13556     gst_structure_free (ref->structure);
13557     g_free (ref->location);
13558     g_free (ref);
13559   }
13560   g_list_free (references);
13561
13562   GST_INFO_OBJECT (qtdemux, "posting redirect message: %" GST_PTR_FORMAT, s);
13563   msg = gst_message_new_element (GST_OBJECT_CAST (qtdemux), s);
13564   gst_element_post_message (GST_ELEMENT_CAST (qtdemux), msg);
13565   qtdemux->posted_redirect = TRUE;
13566 }
13567
13568 /* look for redirect nodes, collect all redirect information and
13569  * process it.
13570  */
13571 static gboolean
13572 qtdemux_parse_redirects (GstQTDemux * qtdemux)
13573 {
13574   GNode *rmra, *rmda, *rdrf;
13575
13576   rmra = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_rmra);
13577   if (rmra) {
13578     GList *redirects = NULL;
13579
13580     rmda = qtdemux_tree_get_child_by_type (rmra, FOURCC_rmda);
13581     while (rmda) {
13582       GstQtReference ref = { NULL, NULL, 0, 0 };
13583       GNode *rmdr, *rmvc;
13584
13585       if ((rmdr = qtdemux_tree_get_child_by_type (rmda, FOURCC_rmdr))) {
13586         ref.min_req_bitrate = QT_UINT32 ((guint8 *) rmdr->data + 12);
13587         GST_LOG_OBJECT (qtdemux, "data rate atom, required bitrate = %u",
13588             ref.min_req_bitrate);
13589       }
13590
13591       if ((rmvc = qtdemux_tree_get_child_by_type (rmda, FOURCC_rmvc))) {
13592         guint32 package = QT_FOURCC ((guint8 *) rmvc->data + 12);
13593         guint version = QT_UINT32 ((guint8 *) rmvc->data + 16);
13594
13595 #ifndef GST_DISABLE_GST_DEBUG
13596         guint bitmask = QT_UINT32 ((guint8 *) rmvc->data + 20);
13597 #endif
13598         guint check_type = QT_UINT16 ((guint8 *) rmvc->data + 24);
13599
13600         GST_LOG_OBJECT (qtdemux,
13601             "version check atom [%" GST_FOURCC_FORMAT "], version=0x%08x"
13602             ", mask=%08x, check_type=%u", GST_FOURCC_ARGS (package), version,
13603             bitmask, check_type);
13604         if (package == FOURCC_qtim && check_type == 0) {
13605           ref.min_req_qt_version = version;
13606         }
13607       }
13608
13609       rdrf = qtdemux_tree_get_child_by_type (rmda, FOURCC_rdrf);
13610       if (rdrf) {
13611         guint32 ref_type;
13612         guint8 *ref_data;
13613         guint ref_len;
13614
13615         ref_len = QT_UINT32 ((guint8 *) rdrf->data);
13616         if (ref_len > 20) {
13617           ref_type = QT_FOURCC ((guint8 *) rdrf->data + 12);
13618           ref_data = (guint8 *) rdrf->data + 20;
13619           if (ref_type == FOURCC_alis) {
13620             guint record_len, record_version, fn_len;
13621
13622             if (ref_len > 70) {
13623               /* MacOSX alias record, google for alias-layout.txt */
13624               record_len = QT_UINT16 (ref_data + 4);
13625               record_version = QT_UINT16 (ref_data + 4 + 2);
13626               fn_len = QT_UINT8 (ref_data + 50);
13627               if (record_len > 50 && record_version == 2 && fn_len > 0) {
13628                 ref.location = g_strndup ((gchar *) ref_data + 51, fn_len);
13629               }
13630             } else {
13631               GST_WARNING_OBJECT (qtdemux, "Invalid rdrf/alis size (%u < 70)",
13632                   ref_len);
13633             }
13634           } else if (ref_type == FOURCC_url_) {
13635             ref.location = g_strndup ((gchar *) ref_data, ref_len - 8);
13636           } else {
13637             GST_DEBUG_OBJECT (qtdemux,
13638                 "unknown rdrf reference type %" GST_FOURCC_FORMAT,
13639                 GST_FOURCC_ARGS (ref_type));
13640           }
13641           if (ref.location != NULL) {
13642             GST_INFO_OBJECT (qtdemux, "New location: %s", ref.location);
13643             redirects =
13644                 g_list_prepend (redirects, g_memdup (&ref, sizeof (ref)));
13645           } else {
13646             GST_WARNING_OBJECT (qtdemux,
13647                 "Failed to extract redirect location from rdrf atom");
13648           }
13649         } else {
13650           GST_WARNING_OBJECT (qtdemux, "Invalid rdrf size (%u < 20)", ref_len);
13651         }
13652       }
13653
13654       /* look for others */
13655       rmda = qtdemux_tree_get_sibling_by_type (rmda, FOURCC_rmda);
13656     }
13657
13658     if (redirects != NULL) {
13659       qtdemux_process_redirects (qtdemux, redirects);
13660     }
13661   }
13662   return TRUE;
13663 }
13664
13665 static GstTagList *
13666 qtdemux_add_container_format (GstQTDemux * qtdemux, GstTagList * tags)
13667 {
13668   const gchar *fmt;
13669
13670   if (tags == NULL) {
13671     tags = gst_tag_list_new_empty ();
13672     gst_tag_list_set_scope (tags, GST_TAG_SCOPE_GLOBAL);
13673   }
13674
13675   if (qtdemux->major_brand == FOURCC_mjp2)
13676     fmt = "Motion JPEG 2000";
13677   else if ((qtdemux->major_brand & 0xffff) == FOURCC_3g__)
13678     fmt = "3GP";
13679   else if (qtdemux->major_brand == FOURCC_qt__)
13680     fmt = "Quicktime";
13681   else if (qtdemux->fragmented)
13682     fmt = "ISO fMP4";
13683   else
13684     fmt = "ISO MP4/M4A";
13685
13686   GST_LOG_OBJECT (qtdemux, "mapped %" GST_FOURCC_FORMAT " to '%s'",
13687       GST_FOURCC_ARGS (qtdemux->major_brand), fmt);
13688
13689   gst_tag_list_add (tags, GST_TAG_MERGE_REPLACE, GST_TAG_CONTAINER_FORMAT,
13690       fmt, NULL);
13691
13692   return tags;
13693 }
13694
13695 /* we have read the complete moov node now.
13696  * This function parses all of the relevant info, creates the traks and
13697  * prepares all data structures for playback
13698  */
13699 static gboolean
13700 qtdemux_parse_tree (GstQTDemux * qtdemux)
13701 {
13702   GNode *mvhd;
13703   GNode *trak;
13704   GNode *udta;
13705   GNode *mvex;
13706   GstClockTime duration;
13707   GNode *pssh;
13708   guint64 creation_time;
13709   GstDateTime *datetime = NULL;
13710   gint version;
13711
13712   /* make sure we have a usable taglist */
13713   qtdemux->tag_list = gst_tag_list_make_writable (qtdemux->tag_list);
13714
13715   mvhd = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_mvhd);
13716   if (mvhd == NULL) {
13717     GST_LOG_OBJECT (qtdemux, "No mvhd node found, looking for redirects.");
13718     return qtdemux_parse_redirects (qtdemux);
13719   }
13720
13721   version = QT_UINT8 ((guint8 *) mvhd->data + 8);
13722   if (version == 1) {
13723     creation_time = QT_UINT64 ((guint8 *) mvhd->data + 12);
13724     qtdemux->timescale = QT_UINT32 ((guint8 *) mvhd->data + 28);
13725     qtdemux->duration = QT_UINT64 ((guint8 *) mvhd->data + 32);
13726   } else if (version == 0) {
13727     creation_time = QT_UINT32 ((guint8 *) mvhd->data + 12);
13728     qtdemux->timescale = QT_UINT32 ((guint8 *) mvhd->data + 20);
13729     qtdemux->duration = QT_UINT32 ((guint8 *) mvhd->data + 24);
13730   } else {
13731     GST_WARNING_OBJECT (qtdemux, "Unhandled mvhd version %d", version);
13732     return FALSE;
13733   }
13734
13735   /* Moving qt creation time (secs since 1904) to unix time */
13736   if (creation_time != 0) {
13737     /* Try to use epoch first as it should be faster and more commonly found */
13738     if (creation_time >= QTDEMUX_SECONDS_FROM_1904_TO_1970) {
13739       GTimeVal now;
13740
13741       creation_time -= QTDEMUX_SECONDS_FROM_1904_TO_1970;
13742       /* some data cleansing sanity */
13743       g_get_current_time (&now);
13744       if (now.tv_sec + 24 * 3600 < creation_time) {
13745         GST_DEBUG_OBJECT (qtdemux, "discarding bogus future creation time");
13746       } else {
13747         datetime = gst_date_time_new_from_unix_epoch_utc (creation_time);
13748       }
13749     } else {
13750       GDateTime *base_dt = g_date_time_new_utc (1904, 1, 1, 0, 0, 0);
13751       GDateTime *dt, *dt_local;
13752
13753       dt = g_date_time_add_seconds (base_dt, creation_time);
13754       dt_local = g_date_time_to_local (dt);
13755       datetime = gst_date_time_new_from_g_date_time (dt_local);
13756
13757       g_date_time_unref (base_dt);
13758       g_date_time_unref (dt);
13759     }
13760   }
13761   if (datetime) {
13762     /* Use KEEP as explicit tags should have a higher priority than mvhd tag */
13763     gst_tag_list_add (qtdemux->tag_list, GST_TAG_MERGE_KEEP, GST_TAG_DATE_TIME,
13764         datetime, NULL);
13765     gst_date_time_unref (datetime);
13766   }
13767
13768   GST_INFO_OBJECT (qtdemux, "timescale: %u", qtdemux->timescale);
13769   GST_INFO_OBJECT (qtdemux, "duration: %" G_GUINT64_FORMAT, qtdemux->duration);
13770
13771   /* check for fragmented file and get some (default) data */
13772   mvex = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_mvex);
13773   if (mvex) {
13774     GNode *mehd;
13775     GstByteReader mehd_data;
13776
13777     /* let track parsing or anyone know weird stuff might happen ... */
13778     qtdemux->fragmented = TRUE;
13779
13780     /* compensate for total duration */
13781     mehd = qtdemux_tree_get_child_by_type_full (mvex, FOURCC_mehd, &mehd_data);
13782     if (mehd)
13783       qtdemux_parse_mehd (qtdemux, &mehd_data);
13784   }
13785
13786   /* set duration in the segment info */
13787   gst_qtdemux_get_duration (qtdemux, &duration);
13788   if (duration) {
13789     qtdemux->segment.duration = duration;
13790     /* also do not exceed duration; stop is set that way post seek anyway,
13791      * and segment activation falls back to duration,
13792      * whereas loop only checks stop, so let's align this here as well */
13793     qtdemux->segment.stop = duration;
13794   }
13795
13796   /* parse all traks */
13797   trak = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_trak);
13798   while (trak) {
13799     qtdemux_parse_trak (qtdemux, trak);
13800     /* iterate all siblings */
13801     trak = qtdemux_tree_get_sibling_by_type (trak, FOURCC_trak);
13802   }
13803
13804   qtdemux->tag_list = gst_tag_list_make_writable (qtdemux->tag_list);
13805
13806   /* find tags */
13807   udta = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_udta);
13808   if (udta) {
13809     qtdemux_parse_udta (qtdemux, qtdemux->tag_list, udta);
13810   } else {
13811     GST_LOG_OBJECT (qtdemux, "No udta node found.");
13812   }
13813
13814   /* maybe also some tags in meta box */
13815   udta = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_meta);
13816   if (udta) {
13817     GST_DEBUG_OBJECT (qtdemux, "Parsing meta box for tags.");
13818     qtdemux_parse_udta (qtdemux, qtdemux->tag_list, udta);
13819   } else {
13820     GST_LOG_OBJECT (qtdemux, "No meta node found.");
13821   }
13822
13823   /* parse any protection system info */
13824   pssh = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_pssh);
13825   while (pssh) {
13826     GST_LOG_OBJECT (qtdemux, "Parsing pssh box.");
13827     qtdemux_parse_pssh (qtdemux, pssh);
13828     pssh = qtdemux_tree_get_sibling_by_type (pssh, FOURCC_pssh);
13829   }
13830
13831   qtdemux->tag_list = qtdemux_add_container_format (qtdemux, qtdemux->tag_list);
13832
13833   return TRUE;
13834 }
13835
13836 /* taken from ffmpeg */
13837 static int
13838 read_descr_size (guint8 * ptr, guint8 * end, guint8 ** end_out)
13839 {
13840   int count = 4;
13841   int len = 0;
13842
13843   while (count--) {
13844     int c;
13845
13846     if (ptr >= end)
13847       return -1;
13848
13849     c = *ptr++;
13850     len = (len << 7) | (c & 0x7f);
13851     if (!(c & 0x80))
13852       break;
13853   }
13854   *end_out = ptr;
13855   return len;
13856 }
13857
13858 static GList *
13859 parse_xiph_stream_headers (GstQTDemux * qtdemux, gpointer codec_data,
13860     gsize codec_data_size)
13861 {
13862   GList *list = NULL;
13863   guint8 *p = codec_data;
13864   gint i, offset, num_packets;
13865   guint *length, last;
13866
13867   GST_MEMDUMP_OBJECT (qtdemux, "xiph codec data", codec_data, codec_data_size);
13868
13869   if (codec_data == NULL || codec_data_size == 0)
13870     goto error;
13871
13872   /* start of the stream and vorbis audio or theora video, need to
13873    * send the codec_priv data as first three packets */
13874   num_packets = p[0] + 1;
13875   GST_DEBUG_OBJECT (qtdemux,
13876       "%u stream headers, total length=%" G_GSIZE_FORMAT " bytes",
13877       (guint) num_packets, codec_data_size);
13878
13879   /* Let's put some limits, Don't think there even is a xiph codec
13880    * with more than 3-4 headers */
13881   if (G_UNLIKELY (num_packets > 16)) {
13882     GST_WARNING_OBJECT (qtdemux,
13883         "Unlikely number of xiph headers, most likely not valid");
13884     goto error;
13885   }
13886
13887   length = g_alloca (num_packets * sizeof (guint));
13888   last = 0;
13889   offset = 1;
13890
13891   /* first packets, read length values */
13892   for (i = 0; i < num_packets - 1; i++) {
13893     length[i] = 0;
13894     while (offset < codec_data_size) {
13895       length[i] += p[offset];
13896       if (p[offset++] != 0xff)
13897         break;
13898     }
13899     last += length[i];
13900   }
13901   if (offset + last > codec_data_size)
13902     goto error;
13903
13904   /* last packet is the remaining size */
13905   length[i] = codec_data_size - offset - last;
13906
13907   for (i = 0; i < num_packets; i++) {
13908     GstBuffer *hdr;
13909
13910     GST_DEBUG_OBJECT (qtdemux, "buffer %d: %u bytes", i, (guint) length[i]);
13911
13912     if (offset + length[i] > codec_data_size)
13913       goto error;
13914
13915     hdr = gst_buffer_new_wrapped (g_memdup (p + offset, length[i]), length[i]);
13916     list = g_list_append (list, hdr);
13917
13918     offset += length[i];
13919   }
13920
13921   return list;
13922
13923   /* ERRORS */
13924 error:
13925   {
13926     if (list != NULL)
13927       g_list_free_full (list, (GDestroyNotify) gst_buffer_unref);
13928     return NULL;
13929   }
13930
13931 }
13932
13933 /* this can change the codec originally present in @list */
13934 static void
13935 gst_qtdemux_handle_esds (GstQTDemux * qtdemux, QtDemuxStream * stream,
13936     QtDemuxStreamStsdEntry * entry, GNode * esds, GstTagList * list)
13937 {
13938   int len = QT_UINT32 (esds->data);
13939   guint8 *ptr = esds->data;
13940   guint8 *end = ptr + len;
13941   int tag;
13942   guint8 *data_ptr = NULL;
13943   int data_len = 0;
13944   guint8 object_type_id = 0;
13945   guint8 stream_type = 0;
13946   const char *codec_name = NULL;
13947   GstCaps *caps = NULL;
13948
13949   GST_MEMDUMP_OBJECT (qtdemux, "esds", ptr, len);
13950   ptr += 8;
13951   GST_DEBUG_OBJECT (qtdemux, "version/flags = %08x", QT_UINT32 (ptr));
13952   ptr += 4;
13953   while (ptr + 1 < end) {
13954     tag = QT_UINT8 (ptr);
13955     GST_DEBUG_OBJECT (qtdemux, "tag = %02x", tag);
13956     ptr++;
13957     len = read_descr_size (ptr, end, &ptr);
13958     GST_DEBUG_OBJECT (qtdemux, "len = %d", len);
13959
13960     /* Check the stated amount of data is available for reading */
13961     if (len < 0 || ptr + len > end)
13962       break;
13963
13964     switch (tag) {
13965       case ES_DESCRIPTOR_TAG:
13966         GST_DEBUG_OBJECT (qtdemux, "ID 0x%04x", QT_UINT16 (ptr));
13967         GST_DEBUG_OBJECT (qtdemux, "priority 0x%04x", QT_UINT8 (ptr + 2));
13968         ptr += 3;
13969         break;
13970       case DECODER_CONFIG_DESC_TAG:{
13971         guint max_bitrate, avg_bitrate;
13972
13973         object_type_id = QT_UINT8 (ptr);
13974         stream_type = QT_UINT8 (ptr + 1) >> 2;
13975         max_bitrate = QT_UINT32 (ptr + 5);
13976         avg_bitrate = QT_UINT32 (ptr + 9);
13977         GST_DEBUG_OBJECT (qtdemux, "object_type_id %02x", object_type_id);
13978         GST_DEBUG_OBJECT (qtdemux, "stream_type %02x", stream_type);
13979         GST_DEBUG_OBJECT (qtdemux, "buffer_size_db %02x", QT_UINT24 (ptr + 2));
13980         GST_DEBUG_OBJECT (qtdemux, "max bitrate %u", max_bitrate);
13981         GST_DEBUG_OBJECT (qtdemux, "avg bitrate %u", avg_bitrate);
13982         if (max_bitrate > 0 && max_bitrate < G_MAXUINT32) {
13983           gst_tag_list_add (list, GST_TAG_MERGE_REPLACE,
13984               GST_TAG_MAXIMUM_BITRATE, max_bitrate, NULL);
13985         }
13986         if (avg_bitrate > 0 && avg_bitrate < G_MAXUINT32) {
13987           gst_tag_list_add (list, GST_TAG_MERGE_REPLACE, GST_TAG_BITRATE,
13988               avg_bitrate, NULL);
13989         }
13990         ptr += 13;
13991         break;
13992       }
13993       case DECODER_SPECIFIC_INFO_TAG:
13994         GST_MEMDUMP_OBJECT (qtdemux, "data", ptr, len);
13995         if (object_type_id == 0xe0 && len == 0x40) {
13996           guint8 *data;
13997           GstStructure *s;
13998           guint32 clut[16];
13999           gint i;
14000
14001           GST_DEBUG_OBJECT (qtdemux,
14002               "Have VOBSUB palette. Creating palette event");
14003           /* move to decConfigDescr data and read palette */
14004           data = ptr;
14005           for (i = 0; i < 16; i++) {
14006             clut[i] = QT_UINT32 (data);
14007             data += 4;
14008           }
14009
14010           s = gst_structure_new ("application/x-gst-dvd", "event",
14011               G_TYPE_STRING, "dvd-spu-clut-change",
14012               "clut00", G_TYPE_INT, clut[0], "clut01", G_TYPE_INT, clut[1],
14013               "clut02", G_TYPE_INT, clut[2], "clut03", G_TYPE_INT, clut[3],
14014               "clut04", G_TYPE_INT, clut[4], "clut05", G_TYPE_INT, clut[5],
14015               "clut06", G_TYPE_INT, clut[6], "clut07", G_TYPE_INT, clut[7],
14016               "clut08", G_TYPE_INT, clut[8], "clut09", G_TYPE_INT, clut[9],
14017               "clut10", G_TYPE_INT, clut[10], "clut11", G_TYPE_INT, clut[11],
14018               "clut12", G_TYPE_INT, clut[12], "clut13", G_TYPE_INT, clut[13],
14019               "clut14", G_TYPE_INT, clut[14], "clut15", G_TYPE_INT, clut[15],
14020               NULL);
14021
14022           /* store event and trigger custom processing */
14023           stream->pending_event =
14024               gst_event_new_custom (GST_EVENT_CUSTOM_DOWNSTREAM, s);
14025         } else {
14026           /* Generic codec_data handler puts it on the caps */
14027           data_ptr = ptr;
14028           data_len = len;
14029         }
14030
14031         ptr += len;
14032         break;
14033       case SL_CONFIG_DESC_TAG:
14034         GST_DEBUG_OBJECT (qtdemux, "data %02x", QT_UINT8 (ptr));
14035         ptr += 1;
14036         break;
14037       default:
14038         GST_DEBUG_OBJECT (qtdemux, "Unknown/unhandled descriptor tag %02x",
14039             tag);
14040         GST_MEMDUMP_OBJECT (qtdemux, "descriptor data", ptr, len);
14041         ptr += len;
14042         break;
14043     }
14044   }
14045
14046   /* object_type_id in the esds atom in mp4a and mp4v tells us which codec is
14047    * in use, and should also be used to override some other parameters for some
14048    * codecs. */
14049   switch (object_type_id) {
14050     case 0x20:                 /* MPEG-4 */
14051       /* 4 bytes for the visual_object_sequence_start_code and 1 byte for the
14052        * profile_and_level_indication */
14053       if (data_ptr != NULL && data_len >= 5 &&
14054           GST_READ_UINT32_BE (data_ptr) == 0x000001b0) {
14055         gst_codec_utils_mpeg4video_caps_set_level_and_profile (entry->caps,
14056             data_ptr + 4, data_len - 4);
14057       }
14058       break;                    /* Nothing special needed here */
14059     case 0x21:                 /* H.264 */
14060       codec_name = "H.264 / AVC";
14061       caps = gst_caps_new_simple ("video/x-h264",
14062           "stream-format", G_TYPE_STRING, "avc",
14063           "alignment", G_TYPE_STRING, "au", NULL);
14064       break;
14065     case 0x40:                 /* AAC (any) */
14066     case 0x66:                 /* AAC Main */
14067     case 0x67:                 /* AAC LC */
14068     case 0x68:                 /* AAC SSR */
14069       /* Override channels and rate based on the codec_data, as it's often
14070        * wrong. */
14071       /* Only do so for basic setup without HE-AAC extension */
14072       if (data_ptr && data_len == 2) {
14073         guint channels, rate;
14074
14075         channels = gst_codec_utils_aac_get_channels (data_ptr, data_len);
14076         if (channels > 0)
14077           entry->n_channels = channels;
14078
14079         rate = gst_codec_utils_aac_get_sample_rate (data_ptr, data_len);
14080         if (rate > 0)
14081           entry->rate = rate;
14082       }
14083
14084       /* Set level and profile if possible */
14085       if (data_ptr != NULL && data_len >= 2) {
14086         gst_codec_utils_aac_caps_set_level_and_profile (entry->caps,
14087             data_ptr, data_len);
14088       } else {
14089         const gchar *profile_str = NULL;
14090         GstBuffer *buffer;
14091         GstMapInfo map;
14092         guint8 *codec_data;
14093         gint rate_idx, profile;
14094
14095         /* No codec_data, let's invent something.
14096          * FIXME: This is wrong for SBR! */
14097
14098         GST_WARNING_OBJECT (qtdemux, "No codec_data for AAC available");
14099
14100         buffer = gst_buffer_new_and_alloc (2);
14101         gst_buffer_map (buffer, &map, GST_MAP_WRITE);
14102         codec_data = map.data;
14103
14104         rate_idx =
14105             gst_codec_utils_aac_get_index_from_sample_rate (CUR_STREAM
14106             (stream)->rate);
14107
14108         switch (object_type_id) {
14109           case 0x66:
14110             profile_str = "main";
14111             profile = 0;
14112             break;
14113           case 0x67:
14114             profile_str = "lc";
14115             profile = 1;
14116             break;
14117           case 0x68:
14118             profile_str = "ssr";
14119             profile = 2;
14120             break;
14121           default:
14122             profile = 3;
14123             break;
14124         }
14125
14126         codec_data[0] = ((profile + 1) << 3) | ((rate_idx & 0xE) >> 1);
14127         codec_data[1] =
14128             ((rate_idx & 0x1) << 7) | (CUR_STREAM (stream)->n_channels << 3);
14129
14130         gst_buffer_unmap (buffer, &map);
14131         gst_caps_set_simple (CUR_STREAM (stream)->caps, "codec_data",
14132             GST_TYPE_BUFFER, buffer, NULL);
14133         gst_buffer_unref (buffer);
14134
14135         if (profile_str) {
14136           gst_caps_set_simple (CUR_STREAM (stream)->caps, "profile",
14137               G_TYPE_STRING, profile_str, NULL);
14138         }
14139       }
14140       break;
14141     case 0x60:                 /* MPEG-2, various profiles */
14142     case 0x61:
14143     case 0x62:
14144     case 0x63:
14145     case 0x64:
14146     case 0x65:
14147       codec_name = "MPEG-2 video";
14148       caps = gst_caps_new_simple ("video/mpeg",
14149           "mpegversion", G_TYPE_INT, 2,
14150           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
14151       break;
14152     case 0x69:                 /* MPEG-2 BC audio */
14153     case 0x6B:                 /* MPEG-1 audio */
14154       caps = gst_caps_new_simple ("audio/mpeg",
14155           "mpegversion", G_TYPE_INT, 1, NULL);
14156       codec_name = "MPEG-1 audio";
14157       break;
14158     case 0x6A:                 /* MPEG-1 */
14159       codec_name = "MPEG-1 video";
14160       caps = gst_caps_new_simple ("video/mpeg",
14161           "mpegversion", G_TYPE_INT, 1,
14162           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
14163       break;
14164     case 0x6C:                 /* MJPEG */
14165       caps =
14166           gst_caps_new_simple ("image/jpeg", "parsed", G_TYPE_BOOLEAN, TRUE,
14167           NULL);
14168       codec_name = "Motion-JPEG";
14169       break;
14170     case 0x6D:                 /* PNG */
14171       caps =
14172           gst_caps_new_simple ("image/png", "parsed", G_TYPE_BOOLEAN, TRUE,
14173           NULL);
14174       codec_name = "PNG still images";
14175       break;
14176     case 0x6E:                 /* JPEG2000 */
14177       codec_name = "JPEG-2000";
14178       caps = gst_caps_new_simple ("image/x-j2c", "fields", G_TYPE_INT, 1, NULL);
14179       break;
14180     case 0xA4:                 /* Dirac */
14181       codec_name = "Dirac";
14182       caps = gst_caps_new_empty_simple ("video/x-dirac");
14183       break;
14184     case 0xA5:                 /* AC3 */
14185       codec_name = "AC-3 audio";
14186       caps = gst_caps_new_simple ("audio/x-ac3",
14187           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
14188       break;
14189     case 0xA9:                 /* AC3 */
14190       codec_name = "DTS audio";
14191       caps = gst_caps_new_simple ("audio/x-dts",
14192           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
14193       break;
14194     case 0xDD:
14195       if (stream_type == 0x05 && data_ptr) {
14196         GList *headers =
14197             parse_xiph_stream_headers (qtdemux, data_ptr, data_len);
14198         if (headers) {
14199           GList *tmp;
14200           GValue arr_val = G_VALUE_INIT;
14201           GValue buf_val = G_VALUE_INIT;
14202           GstStructure *s;
14203
14204           /* Let's assume it's vorbis if it's an audio stream of type 0xdd and we have codec data that extracts properly */
14205           codec_name = "Vorbis";
14206           caps = gst_caps_new_empty_simple ("audio/x-vorbis");
14207           g_value_init (&arr_val, GST_TYPE_ARRAY);
14208           g_value_init (&buf_val, GST_TYPE_BUFFER);
14209           for (tmp = headers; tmp; tmp = tmp->next) {
14210             g_value_set_boxed (&buf_val, (GstBuffer *) tmp->data);
14211             gst_value_array_append_value (&arr_val, &buf_val);
14212           }
14213           s = gst_caps_get_structure (caps, 0);
14214           gst_structure_take_value (s, "streamheader", &arr_val);
14215           g_value_unset (&buf_val);
14216           g_list_free (headers);
14217
14218           data_ptr = NULL;
14219           data_len = 0;
14220         }
14221       }
14222       break;
14223     case 0xE1:                 /* QCELP */
14224       /* QCELP, the codec_data is a riff tag (little endian) with
14225        * 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). */
14226       caps = gst_caps_new_empty_simple ("audio/qcelp");
14227       codec_name = "QCELP";
14228       break;
14229     default:
14230       break;
14231   }
14232
14233   /* If we have a replacement caps, then change our caps for this stream */
14234   if (caps) {
14235     gst_caps_unref (entry->caps);
14236     entry->caps = caps;
14237   }
14238
14239   if (codec_name && list)
14240     gst_tag_list_add (list, GST_TAG_MERGE_REPLACE,
14241         GST_TAG_AUDIO_CODEC, codec_name, NULL);
14242
14243   /* Add the codec_data attribute to caps, if we have it */
14244   if (data_ptr) {
14245     GstBuffer *buffer;
14246
14247     buffer = gst_buffer_new_and_alloc (data_len);
14248     gst_buffer_fill (buffer, 0, data_ptr, data_len);
14249
14250     GST_DEBUG_OBJECT (qtdemux, "setting codec_data from esds");
14251     GST_MEMDUMP_OBJECT (qtdemux, "codec_data from esds", data_ptr, data_len);
14252
14253     gst_caps_set_simple (entry->caps, "codec_data", GST_TYPE_BUFFER,
14254         buffer, NULL);
14255     gst_buffer_unref (buffer);
14256   }
14257
14258 }
14259
14260 static inline GstCaps *
14261 _get_unknown_codec_name (const gchar * type, guint32 fourcc)
14262 {
14263   GstCaps *caps;
14264   guint i;
14265   char *s, fourstr[5];
14266
14267   g_snprintf (fourstr, 5, "%" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (fourcc));
14268   for (i = 0; i < 4; i++) {
14269     if (!g_ascii_isalnum (fourstr[i]))
14270       fourstr[i] = '_';
14271   }
14272   s = g_strdup_printf ("%s/x-gst-fourcc-%s", type, g_strstrip (fourstr));
14273   caps = gst_caps_new_empty_simple (s);
14274   g_free (s);
14275   return caps;
14276 }
14277
14278 #define _codec(name) \
14279   do { \
14280     if (codec_name) { \
14281       *codec_name = g_strdup (name); \
14282     } \
14283   } while (0)
14284
14285 static GstCaps *
14286 qtdemux_video_caps (GstQTDemux * qtdemux, QtDemuxStream * stream,
14287     QtDemuxStreamStsdEntry * entry, guint32 fourcc,
14288     const guint8 * stsd_entry_data, gchar ** codec_name)
14289 {
14290   GstCaps *caps = NULL;
14291   GstVideoFormat format = GST_VIDEO_FORMAT_UNKNOWN;
14292
14293   switch (fourcc) {
14294     case FOURCC_png:
14295       _codec ("PNG still images");
14296       caps = gst_caps_new_empty_simple ("image/png");
14297       break;
14298     case FOURCC_jpeg:
14299       _codec ("JPEG still images");
14300       caps =
14301           gst_caps_new_simple ("image/jpeg", "parsed", G_TYPE_BOOLEAN, TRUE,
14302           NULL);
14303       break;
14304     case GST_MAKE_FOURCC ('m', 'j', 'p', 'a'):
14305     case GST_MAKE_FOURCC ('A', 'V', 'D', 'J'):
14306     case GST_MAKE_FOURCC ('M', 'J', 'P', 'G'):
14307     case GST_MAKE_FOURCC ('d', 'm', 'b', '1'):
14308       _codec ("Motion-JPEG");
14309       caps =
14310           gst_caps_new_simple ("image/jpeg", "parsed", G_TYPE_BOOLEAN, TRUE,
14311           NULL);
14312       break;
14313     case GST_MAKE_FOURCC ('m', 'j', 'p', 'b'):
14314       _codec ("Motion-JPEG format B");
14315       caps = gst_caps_new_empty_simple ("video/x-mjpeg-b");
14316       break;
14317     case FOURCC_mjp2:
14318       _codec ("JPEG-2000");
14319       /* override to what it should be according to spec, avoid palette_data */
14320       entry->bits_per_sample = 24;
14321       caps = gst_caps_new_simple ("image/x-j2c", "fields", G_TYPE_INT, 1, NULL);
14322       break;
14323     case FOURCC_SVQ3:
14324       _codec ("Sorensen video v.3");
14325       caps = gst_caps_new_simple ("video/x-svq",
14326           "svqversion", G_TYPE_INT, 3, NULL);
14327       break;
14328     case GST_MAKE_FOURCC ('s', 'v', 'q', 'i'):
14329     case GST_MAKE_FOURCC ('S', 'V', 'Q', '1'):
14330       _codec ("Sorensen video v.1");
14331       caps = gst_caps_new_simple ("video/x-svq",
14332           "svqversion", G_TYPE_INT, 1, NULL);
14333       break;
14334     case GST_MAKE_FOURCC ('W', 'R', 'A', 'W'):
14335       caps = gst_caps_new_empty_simple ("video/x-raw");
14336       gst_caps_set_simple (caps, "format", G_TYPE_STRING, "RGB8P", NULL);
14337       _codec ("Windows Raw RGB");
14338       stream->alignment = 32;
14339       break;
14340     case FOURCC_raw_:
14341     {
14342       guint16 bps;
14343
14344       bps = QT_UINT16 (stsd_entry_data + 82);
14345       switch (bps) {
14346         case 15:
14347           format = GST_VIDEO_FORMAT_RGB15;
14348           break;
14349         case 16:
14350           format = GST_VIDEO_FORMAT_RGB16;
14351           break;
14352         case 24:
14353           format = GST_VIDEO_FORMAT_RGB;
14354           break;
14355         case 32:
14356           format = GST_VIDEO_FORMAT_ARGB;
14357           break;
14358         default:
14359           /* unknown */
14360           break;
14361       }
14362       break;
14363     }
14364     case GST_MAKE_FOURCC ('y', 'v', '1', '2'):
14365       format = GST_VIDEO_FORMAT_I420;
14366       break;
14367     case GST_MAKE_FOURCC ('y', 'u', 'v', '2'):
14368     case GST_MAKE_FOURCC ('Y', 'u', 'v', '2'):
14369       format = GST_VIDEO_FORMAT_I420;
14370       break;
14371     case FOURCC_2vuy:
14372     case GST_MAKE_FOURCC ('2', 'V', 'u', 'y'):
14373       format = GST_VIDEO_FORMAT_UYVY;
14374       break;
14375     case GST_MAKE_FOURCC ('v', '3', '0', '8'):
14376       format = GST_VIDEO_FORMAT_v308;
14377       break;
14378     case GST_MAKE_FOURCC ('v', '2', '1', '6'):
14379       format = GST_VIDEO_FORMAT_v216;
14380       break;
14381     case FOURCC_v210:
14382       format = GST_VIDEO_FORMAT_v210;
14383       break;
14384     case GST_MAKE_FOURCC ('r', '2', '1', '0'):
14385       format = GST_VIDEO_FORMAT_r210;
14386       break;
14387       /* Packed YUV 4:4:4 10 bit in 32 bits, complex
14388          case GST_MAKE_FOURCC ('v', '4', '1', '0'):
14389          format = GST_VIDEO_FORMAT_v410;
14390          break;
14391        */
14392       /* Packed YUV 4:4:4:4 8 bit in 32 bits
14393        * but different order than AYUV
14394        case GST_MAKE_FOURCC ('v', '4', '0', '8'):
14395        format = GST_VIDEO_FORMAT_v408;
14396        break;
14397        */
14398     case GST_MAKE_FOURCC ('m', 'p', 'e', 'g'):
14399     case GST_MAKE_FOURCC ('m', 'p', 'g', '1'):
14400       _codec ("MPEG-1 video");
14401       caps = gst_caps_new_simple ("video/mpeg", "mpegversion", G_TYPE_INT, 1,
14402           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
14403       break;
14404     case GST_MAKE_FOURCC ('h', 'd', 'v', '1'): /* HDV 720p30 */
14405     case GST_MAKE_FOURCC ('h', 'd', 'v', '2'): /* HDV 1080i60 */
14406     case GST_MAKE_FOURCC ('h', 'd', 'v', '3'): /* HDV 1080i50 */
14407     case GST_MAKE_FOURCC ('h', 'd', 'v', '4'): /* HDV 720p24 */
14408     case GST_MAKE_FOURCC ('h', 'd', 'v', '5'): /* HDV 720p25 */
14409     case GST_MAKE_FOURCC ('h', 'd', 'v', '6'): /* HDV 1080p24 */
14410     case GST_MAKE_FOURCC ('h', 'd', 'v', '7'): /* HDV 1080p25 */
14411     case GST_MAKE_FOURCC ('h', 'd', 'v', '8'): /* HDV 1080p30 */
14412     case GST_MAKE_FOURCC ('h', 'd', 'v', '9'): /* HDV 720p60 */
14413     case GST_MAKE_FOURCC ('h', 'd', 'v', 'a'): /* HDV 720p50 */
14414     case GST_MAKE_FOURCC ('m', 'x', '5', 'n'): /* MPEG2 IMX NTSC 525/60 50mb/s produced by FCP */
14415     case GST_MAKE_FOURCC ('m', 'x', '5', 'p'): /* MPEG2 IMX PAL 625/60 50mb/s produced by FCP */
14416     case GST_MAKE_FOURCC ('m', 'x', '4', 'n'): /* MPEG2 IMX NTSC 525/60 40mb/s produced by FCP */
14417     case GST_MAKE_FOURCC ('m', 'x', '4', 'p'): /* MPEG2 IMX PAL 625/60 40mb/s produced by FCP */
14418     case GST_MAKE_FOURCC ('m', 'x', '3', 'n'): /* MPEG2 IMX NTSC 525/60 30mb/s produced by FCP */
14419     case GST_MAKE_FOURCC ('m', 'x', '3', 'p'): /* MPEG2 IMX PAL 625/50 30mb/s produced by FCP */
14420     case GST_MAKE_FOURCC ('x', 'd', 'v', '1'): /* XDCAM HD 720p30 35Mb/s */
14421     case GST_MAKE_FOURCC ('x', 'd', 'v', '2'): /* XDCAM HD 1080i60 35Mb/s */
14422     case GST_MAKE_FOURCC ('x', 'd', 'v', '3'): /* XDCAM HD 1080i50 35Mb/s */
14423     case GST_MAKE_FOURCC ('x', 'd', 'v', '4'): /* XDCAM HD 720p24 35Mb/s */
14424     case GST_MAKE_FOURCC ('x', 'd', 'v', '5'): /* XDCAM HD 720p25 35Mb/s */
14425     case GST_MAKE_FOURCC ('x', 'd', 'v', '6'): /* XDCAM HD 1080p24 35Mb/s */
14426     case GST_MAKE_FOURCC ('x', 'd', 'v', '7'): /* XDCAM HD 1080p25 35Mb/s */
14427     case GST_MAKE_FOURCC ('x', 'd', 'v', '8'): /* XDCAM HD 1080p30 35Mb/s */
14428     case GST_MAKE_FOURCC ('x', 'd', 'v', '9'): /* XDCAM HD 720p60 35Mb/s */
14429     case GST_MAKE_FOURCC ('x', 'd', 'v', 'a'): /* XDCAM HD 720p50 35Mb/s */
14430     case GST_MAKE_FOURCC ('x', 'd', 'v', 'b'): /* XDCAM EX 1080i60 50Mb/s CBR */
14431     case GST_MAKE_FOURCC ('x', 'd', 'v', 'c'): /* XDCAM EX 1080i50 50Mb/s CBR */
14432     case GST_MAKE_FOURCC ('x', 'd', 'v', 'd'): /* XDCAM HD 1080p24 50Mb/s CBR */
14433     case GST_MAKE_FOURCC ('x', 'd', 'v', 'e'): /* XDCAM HD 1080p25 50Mb/s CBR */
14434     case GST_MAKE_FOURCC ('x', 'd', 'v', 'f'): /* XDCAM HD 1080p30 50Mb/s CBR */
14435     case GST_MAKE_FOURCC ('x', 'd', '5', '1'): /* XDCAM HD422 720p30 50Mb/s CBR */
14436     case GST_MAKE_FOURCC ('x', 'd', '5', '4'): /* XDCAM HD422 720p24 50Mb/s CBR */
14437     case GST_MAKE_FOURCC ('x', 'd', '5', '5'): /* XDCAM HD422 720p25 50Mb/s CBR */
14438     case GST_MAKE_FOURCC ('x', 'd', '5', '9'): /* XDCAM HD422 720p60 50Mb/s CBR */
14439     case GST_MAKE_FOURCC ('x', 'd', '5', 'a'): /* XDCAM HD422 720p50 50Mb/s CBR */
14440     case GST_MAKE_FOURCC ('x', 'd', '5', 'b'): /* XDCAM HD422 1080i50 50Mb/s CBR */
14441     case GST_MAKE_FOURCC ('x', 'd', '5', 'c'): /* XDCAM HD422 1080i50 50Mb/s CBR */
14442     case GST_MAKE_FOURCC ('x', 'd', '5', 'd'): /* XDCAM HD422 1080p24 50Mb/s CBR */
14443     case GST_MAKE_FOURCC ('x', 'd', '5', 'e'): /* XDCAM HD422 1080p25 50Mb/s CBR */
14444     case GST_MAKE_FOURCC ('x', 'd', '5', 'f'): /* XDCAM HD422 1080p30 50Mb/s CBR */
14445     case GST_MAKE_FOURCC ('x', 'd', 'h', 'd'): /* XDCAM HD 540p */
14446     case GST_MAKE_FOURCC ('x', 'd', 'h', '2'): /* XDCAM HD422 540p */
14447     case GST_MAKE_FOURCC ('A', 'V', 'm', 'p'): /* AVID IMX PAL */
14448     case GST_MAKE_FOURCC ('m', 'p', 'g', '2'): /* AVID IMX PAL */
14449     case GST_MAKE_FOURCC ('m', 'p', '2', 'v'): /* AVID IMX PAL */
14450     case GST_MAKE_FOURCC ('m', '2', 'v', '1'):
14451       _codec ("MPEG-2 video");
14452       caps = gst_caps_new_simple ("video/mpeg", "mpegversion", G_TYPE_INT, 2,
14453           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
14454       break;
14455     case GST_MAKE_FOURCC ('g', 'i', 'f', ' '):
14456       _codec ("GIF still images");
14457       caps = gst_caps_new_empty_simple ("image/gif");
14458       break;
14459     case FOURCC_h263:
14460     case GST_MAKE_FOURCC ('H', '2', '6', '3'):
14461     case FOURCC_s263:
14462     case GST_MAKE_FOURCC ('U', '2', '6', '3'):
14463       _codec ("H.263");
14464       /* ffmpeg uses the height/width props, don't know why */
14465       caps = gst_caps_new_simple ("video/x-h263",
14466           "variant", G_TYPE_STRING, "itu", NULL);
14467       break;
14468     case FOURCC_mp4v:
14469     case FOURCC_MP4V:
14470       _codec ("MPEG-4 video");
14471       caps = gst_caps_new_simple ("video/mpeg", "mpegversion", G_TYPE_INT, 4,
14472           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
14473       break;
14474     case GST_MAKE_FOURCC ('3', 'i', 'v', 'd'):
14475     case GST_MAKE_FOURCC ('3', 'I', 'V', 'D'):
14476       _codec ("Microsoft MPEG-4 4.3");  /* FIXME? */
14477       caps = gst_caps_new_simple ("video/x-msmpeg",
14478           "msmpegversion", G_TYPE_INT, 43, NULL);
14479       break;
14480     case GST_MAKE_FOURCC ('D', 'I', 'V', '3'):
14481       _codec ("DivX 3");
14482       caps = gst_caps_new_simple ("video/x-divx",
14483           "divxversion", G_TYPE_INT, 3, NULL);
14484       break;
14485     case GST_MAKE_FOURCC ('D', 'I', 'V', 'X'):
14486     case GST_MAKE_FOURCC ('d', 'i', 'v', 'x'):
14487       _codec ("DivX 4");
14488       caps = gst_caps_new_simple ("video/x-divx",
14489           "divxversion", G_TYPE_INT, 4, NULL);
14490       break;
14491     case GST_MAKE_FOURCC ('D', 'X', '5', '0'):
14492       _codec ("DivX 5");
14493       caps = gst_caps_new_simple ("video/x-divx",
14494           "divxversion", G_TYPE_INT, 5, NULL);
14495       break;
14496
14497     case GST_MAKE_FOURCC ('F', 'F', 'V', '1'):
14498       _codec ("FFV1");
14499       caps = gst_caps_new_simple ("video/x-ffv",
14500           "ffvversion", G_TYPE_INT, 1, NULL);
14501       break;
14502
14503     case GST_MAKE_FOURCC ('3', 'I', 'V', '1'):
14504     case GST_MAKE_FOURCC ('3', 'I', 'V', '2'):
14505     case FOURCC_XVID:
14506     case FOURCC_xvid:
14507     case FOURCC_FMP4:
14508     case FOURCC_fmp4:
14509     case GST_MAKE_FOURCC ('U', 'M', 'P', '4'):
14510       caps = gst_caps_new_simple ("video/mpeg", "mpegversion", G_TYPE_INT, 4,
14511           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
14512       _codec ("MPEG-4");
14513       break;
14514
14515     case GST_MAKE_FOURCC ('c', 'v', 'i', 'd'):
14516       _codec ("Cinepak");
14517       caps = gst_caps_new_empty_simple ("video/x-cinepak");
14518       break;
14519     case GST_MAKE_FOURCC ('q', 'd', 'r', 'w'):
14520       _codec ("Apple QuickDraw");
14521       caps = gst_caps_new_empty_simple ("video/x-qdrw");
14522       break;
14523     case GST_MAKE_FOURCC ('r', 'p', 'z', 'a'):
14524       _codec ("Apple video");
14525       caps = gst_caps_new_empty_simple ("video/x-apple-video");
14526       break;
14527     case FOURCC_H264:
14528     case FOURCC_avc1:
14529       _codec ("H.264 / AVC");
14530       caps = gst_caps_new_simple ("video/x-h264",
14531           "stream-format", G_TYPE_STRING, "avc",
14532           "alignment", G_TYPE_STRING, "au", NULL);
14533       break;
14534     case FOURCC_avc3:
14535       _codec ("H.264 / AVC");
14536       caps = gst_caps_new_simple ("video/x-h264",
14537           "stream-format", G_TYPE_STRING, "avc3",
14538           "alignment", G_TYPE_STRING, "au", NULL);
14539       break;
14540     case FOURCC_H265:
14541     case FOURCC_hvc1:
14542       _codec ("H.265 / HEVC");
14543       caps = gst_caps_new_simple ("video/x-h265",
14544           "stream-format", G_TYPE_STRING, "hvc1",
14545           "alignment", G_TYPE_STRING, "au", NULL);
14546       break;
14547     case FOURCC_hev1:
14548       _codec ("H.265 / HEVC");
14549       caps = gst_caps_new_simple ("video/x-h265",
14550           "stream-format", G_TYPE_STRING, "hev1",
14551           "alignment", G_TYPE_STRING, "au", NULL);
14552       break;
14553     case FOURCC_rle_:
14554       _codec ("Run-length encoding");
14555       caps = gst_caps_new_simple ("video/x-rle",
14556           "layout", G_TYPE_STRING, "quicktime", NULL);
14557       break;
14558     case FOURCC_WRLE:
14559       _codec ("Run-length encoding");
14560       caps = gst_caps_new_simple ("video/x-rle",
14561           "layout", G_TYPE_STRING, "microsoft", NULL);
14562       break;
14563     case GST_MAKE_FOURCC ('I', 'V', '3', '2'):
14564     case GST_MAKE_FOURCC ('i', 'v', '3', '2'):
14565       _codec ("Indeo Video 3");
14566       caps = gst_caps_new_simple ("video/x-indeo",
14567           "indeoversion", G_TYPE_INT, 3, NULL);
14568       break;
14569     case GST_MAKE_FOURCC ('I', 'V', '4', '1'):
14570     case GST_MAKE_FOURCC ('i', 'v', '4', '1'):
14571       _codec ("Intel Video 4");
14572       caps = gst_caps_new_simple ("video/x-indeo",
14573           "indeoversion", G_TYPE_INT, 4, NULL);
14574       break;
14575     case FOURCC_dvcp:
14576     case FOURCC_dvc_:
14577     case GST_MAKE_FOURCC ('d', 'v', 's', 'd'):
14578     case GST_MAKE_FOURCC ('D', 'V', 'S', 'D'):
14579     case GST_MAKE_FOURCC ('d', 'v', 'c', 's'):
14580     case GST_MAKE_FOURCC ('D', 'V', 'C', 'S'):
14581     case GST_MAKE_FOURCC ('d', 'v', '2', '5'):
14582     case GST_MAKE_FOURCC ('d', 'v', 'p', 'p'):
14583       _codec ("DV Video");
14584       caps = gst_caps_new_simple ("video/x-dv", "dvversion", G_TYPE_INT, 25,
14585           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
14586       break;
14587     case FOURCC_dv5n:          /* DVCPRO50 NTSC */
14588     case FOURCC_dv5p:          /* DVCPRO50 PAL */
14589       _codec ("DVCPro50 Video");
14590       caps = gst_caps_new_simple ("video/x-dv", "dvversion", G_TYPE_INT, 50,
14591           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
14592       break;
14593     case GST_MAKE_FOURCC ('d', 'v', 'h', '5'): /* DVCPRO HD 50i produced by FCP */
14594     case GST_MAKE_FOURCC ('d', 'v', 'h', '6'): /* DVCPRO HD 60i produced by FCP */
14595       _codec ("DVCProHD Video");
14596       caps = gst_caps_new_simple ("video/x-dv", "dvversion", G_TYPE_INT, 100,
14597           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
14598       break;
14599     case GST_MAKE_FOURCC ('s', 'm', 'c', ' '):
14600       _codec ("Apple Graphics (SMC)");
14601       caps = gst_caps_new_empty_simple ("video/x-smc");
14602       break;
14603     case GST_MAKE_FOURCC ('V', 'P', '3', '1'):
14604       _codec ("VP3");
14605       caps = gst_caps_new_empty_simple ("video/x-vp3");
14606       break;
14607     case GST_MAKE_FOURCC ('V', 'P', '6', 'F'):
14608       _codec ("VP6 Flash");
14609       caps = gst_caps_new_empty_simple ("video/x-vp6-flash");
14610       break;
14611     case FOURCC_XiTh:
14612       _codec ("Theora");
14613       caps = gst_caps_new_empty_simple ("video/x-theora");
14614       /* theora uses one byte of padding in the data stream because it does not
14615        * allow 0 sized packets while theora does */
14616       entry->padding = 1;
14617       break;
14618     case FOURCC_drac:
14619       _codec ("Dirac");
14620       caps = gst_caps_new_empty_simple ("video/x-dirac");
14621       break;
14622     case GST_MAKE_FOURCC ('t', 'i', 'f', 'f'):
14623       _codec ("TIFF still images");
14624       caps = gst_caps_new_empty_simple ("image/tiff");
14625       break;
14626     case GST_MAKE_FOURCC ('i', 'c', 'o', 'd'):
14627       _codec ("Apple Intermediate Codec");
14628       caps = gst_caps_from_string ("video/x-apple-intermediate-codec");
14629       break;
14630     case GST_MAKE_FOURCC ('A', 'V', 'd', 'n'):
14631       _codec ("AVID DNxHD");
14632       caps = gst_caps_from_string ("video/x-dnxhd");
14633       break;
14634     case FOURCC_VP80:
14635     case FOURCC_vp08:
14636       _codec ("On2 VP8");
14637       caps = gst_caps_from_string ("video/x-vp8");
14638       break;
14639     case FOURCC_vp09:
14640       _codec ("Google VP9");
14641       caps = gst_caps_from_string ("video/x-vp9");
14642       break;
14643     case FOURCC_apcs:
14644       _codec ("Apple ProRes LT");
14645       caps =
14646           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING, "lt",
14647           NULL);
14648       break;
14649     case FOURCC_apch:
14650       _codec ("Apple ProRes HQ");
14651       caps =
14652           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING, "hq",
14653           NULL);
14654       break;
14655     case FOURCC_apcn:
14656       _codec ("Apple ProRes");
14657       caps =
14658           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING,
14659           "standard", NULL);
14660       break;
14661     case FOURCC_apco:
14662       _codec ("Apple ProRes Proxy");
14663       caps =
14664           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING,
14665           "proxy", NULL);
14666       break;
14667     case FOURCC_ap4h:
14668       _codec ("Apple ProRes 4444");
14669       caps =
14670           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING,
14671           "4444", NULL);
14672       break;
14673     case FOURCC_ap4x:
14674       _codec ("Apple ProRes 4444 XQ");
14675       caps =
14676           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING,
14677           "4444xq", NULL);
14678       break;
14679     case FOURCC_cfhd:
14680       _codec ("GoPro CineForm");
14681       caps = gst_caps_from_string ("video/x-cineform");
14682       break;
14683     case FOURCC_vc_1:
14684     case FOURCC_ovc1:
14685       _codec ("VC-1");
14686       caps = gst_caps_new_simple ("video/x-wmv",
14687           "wmvversion", G_TYPE_INT, 3, "format", G_TYPE_STRING, "WVC1", NULL);
14688       break;
14689     case GST_MAKE_FOURCC ('k', 'p', 'c', 'd'):
14690     default:
14691     {
14692       caps = _get_unknown_codec_name ("video", fourcc);
14693       break;
14694     }
14695   }
14696
14697   if (format != GST_VIDEO_FORMAT_UNKNOWN) {
14698     GstVideoInfo info;
14699
14700     gst_video_info_init (&info);
14701     gst_video_info_set_format (&info, format, entry->width, entry->height);
14702
14703     caps = gst_video_info_to_caps (&info);
14704     *codec_name = gst_pb_utils_get_codec_description (caps);
14705
14706     /* enable clipping for raw video streams */
14707     stream->need_clip = TRUE;
14708     stream->alignment = 32;
14709   }
14710
14711   return caps;
14712 }
14713
14714 static guint
14715 round_up_pow2 (guint n)
14716 {
14717   n = n - 1;
14718   n = n | (n >> 1);
14719   n = n | (n >> 2);
14720   n = n | (n >> 4);
14721   n = n | (n >> 8);
14722   n = n | (n >> 16);
14723   return n + 1;
14724 }
14725
14726 static GstCaps *
14727 qtdemux_audio_caps (GstQTDemux * qtdemux, QtDemuxStream * stream,
14728     QtDemuxStreamStsdEntry * entry, guint32 fourcc, const guint8 * data,
14729     int len, gchar ** codec_name)
14730 {
14731   GstCaps *caps;
14732   const GstStructure *s;
14733   const gchar *name;
14734   gint endian = 0;
14735   GstAudioFormat format = 0;
14736   gint depth;
14737
14738   GST_DEBUG_OBJECT (qtdemux, "resolve fourcc 0x%08x", GUINT32_TO_BE (fourcc));
14739
14740   depth = entry->bytes_per_packet * 8;
14741
14742   switch (fourcc) {
14743     case GST_MAKE_FOURCC ('N', 'O', 'N', 'E'):
14744     case FOURCC_raw_:
14745       /* 8-bit audio is unsigned */
14746       if (depth == 8)
14747         format = GST_AUDIO_FORMAT_U8;
14748       /* otherwise it's signed and big-endian just like 'twos' */
14749     case FOURCC_twos:
14750       endian = G_BIG_ENDIAN;
14751       /* fall-through */
14752     case FOURCC_sowt:
14753     {
14754       gchar *str;
14755
14756       if (!endian)
14757         endian = G_LITTLE_ENDIAN;
14758
14759       if (!format)
14760         format = gst_audio_format_build_integer (TRUE, endian, depth, depth);
14761
14762       str = g_strdup_printf ("Raw %d-bit PCM audio", depth);
14763       _codec (str);
14764       g_free (str);
14765
14766       caps = gst_caps_new_simple ("audio/x-raw",
14767           "format", G_TYPE_STRING, gst_audio_format_to_string (format),
14768           "layout", G_TYPE_STRING, "interleaved", NULL);
14769       stream->alignment = GST_ROUND_UP_8 (depth);
14770       stream->alignment = round_up_pow2 (stream->alignment);
14771       break;
14772     }
14773     case GST_MAKE_FOURCC ('f', 'l', '6', '4'):
14774       _codec ("Raw 64-bit floating-point audio");
14775       caps = gst_caps_new_simple ("audio/x-raw",
14776           "format", G_TYPE_STRING, "F64BE",
14777           "layout", G_TYPE_STRING, "interleaved", NULL);
14778       stream->alignment = 8;
14779       break;
14780     case GST_MAKE_FOURCC ('f', 'l', '3', '2'):
14781       _codec ("Raw 32-bit floating-point audio");
14782       caps = gst_caps_new_simple ("audio/x-raw",
14783           "format", G_TYPE_STRING, "F32BE",
14784           "layout", G_TYPE_STRING, "interleaved", NULL);
14785       stream->alignment = 4;
14786       break;
14787     case FOURCC_in24:
14788       _codec ("Raw 24-bit PCM audio");
14789       /* we assume BIG ENDIAN, an enda box will tell us to change this to little
14790        * endian later */
14791       caps = gst_caps_new_simple ("audio/x-raw",
14792           "format", G_TYPE_STRING, "S24BE",
14793           "layout", G_TYPE_STRING, "interleaved", NULL);
14794       stream->alignment = 4;
14795       break;
14796     case GST_MAKE_FOURCC ('i', 'n', '3', '2'):
14797       _codec ("Raw 32-bit PCM audio");
14798       caps = gst_caps_new_simple ("audio/x-raw",
14799           "format", G_TYPE_STRING, "S32BE",
14800           "layout", G_TYPE_STRING, "interleaved", NULL);
14801       stream->alignment = 4;
14802       break;
14803     case GST_MAKE_FOURCC ('s', '1', '6', 'l'):
14804       _codec ("Raw 16-bit PCM audio");
14805       caps = gst_caps_new_simple ("audio/x-raw",
14806           "format", G_TYPE_STRING, "S16LE",
14807           "layout", G_TYPE_STRING, "interleaved", NULL);
14808       stream->alignment = 2;
14809       break;
14810     case FOURCC_ulaw:
14811       _codec ("Mu-law audio");
14812       caps = gst_caps_new_empty_simple ("audio/x-mulaw");
14813       break;
14814     case FOURCC_alaw:
14815       _codec ("A-law audio");
14816       caps = gst_caps_new_empty_simple ("audio/x-alaw");
14817       break;
14818     case 0x0200736d:
14819     case 0x6d730002:
14820       _codec ("Microsoft ADPCM");
14821       /* Microsoft ADPCM-ACM code 2 */
14822       caps = gst_caps_new_simple ("audio/x-adpcm",
14823           "layout", G_TYPE_STRING, "microsoft", NULL);
14824       break;
14825     case 0x1100736d:
14826     case 0x6d730011:
14827       _codec ("DVI/IMA ADPCM");
14828       caps = gst_caps_new_simple ("audio/x-adpcm",
14829           "layout", G_TYPE_STRING, "dvi", NULL);
14830       break;
14831     case 0x1700736d:
14832     case 0x6d730017:
14833       _codec ("DVI/Intel IMA ADPCM");
14834       /* FIXME DVI/Intel IMA ADPCM/ACM code 17 */
14835       caps = gst_caps_new_simple ("audio/x-adpcm",
14836           "layout", G_TYPE_STRING, "quicktime", NULL);
14837       break;
14838     case 0x5500736d:
14839     case 0x6d730055:
14840       /* MPEG layer 3, CBR only (pre QT4.1) */
14841     case FOURCC__mp3:
14842       _codec ("MPEG-1 layer 3");
14843       /* MPEG layer 3, CBR & VBR (QT4.1 and later) */
14844       caps = gst_caps_new_simple ("audio/mpeg", "layer", G_TYPE_INT, 3,
14845           "mpegversion", G_TYPE_INT, 1, NULL);
14846       break;
14847     case GST_MAKE_FOURCC ('.', 'm', 'p', '2'):
14848       _codec ("MPEG-1 layer 2");
14849       /* MPEG layer 2 */
14850       caps = gst_caps_new_simple ("audio/mpeg", "layer", G_TYPE_INT, 2,
14851           "mpegversion", G_TYPE_INT, 1, NULL);
14852       break;
14853     case 0x20736d:
14854     case GST_MAKE_FOURCC ('e', 'c', '-', '3'):
14855       _codec ("EAC-3 audio");
14856       caps = gst_caps_new_simple ("audio/x-eac3",
14857           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
14858       entry->sampled = TRUE;
14859       break;
14860     case GST_MAKE_FOURCC ('s', 'a', 'c', '3'): // Nero Recode
14861     case FOURCC_ac_3:
14862       _codec ("AC-3 audio");
14863       caps = gst_caps_new_simple ("audio/x-ac3",
14864           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
14865       entry->sampled = TRUE;
14866       break;
14867     case GST_MAKE_FOURCC ('d', 't', 's', 'c'):
14868     case GST_MAKE_FOURCC ('D', 'T', 'S', ' '):
14869       _codec ("DTS audio");
14870       caps = gst_caps_new_simple ("audio/x-dts",
14871           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
14872       entry->sampled = TRUE;
14873       break;
14874     case GST_MAKE_FOURCC ('d', 't', 's', 'h'): // DTS-HD
14875     case GST_MAKE_FOURCC ('d', 't', 's', 'l'): // DTS-HD Lossless
14876       _codec ("DTS-HD audio");
14877       caps = gst_caps_new_simple ("audio/x-dts",
14878           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
14879       entry->sampled = TRUE;
14880       break;
14881     case FOURCC_MAC3:
14882       _codec ("MACE-3");
14883       caps = gst_caps_new_simple ("audio/x-mace",
14884           "maceversion", G_TYPE_INT, 3, NULL);
14885       break;
14886     case FOURCC_MAC6:
14887       _codec ("MACE-6");
14888       caps = gst_caps_new_simple ("audio/x-mace",
14889           "maceversion", G_TYPE_INT, 6, NULL);
14890       break;
14891     case GST_MAKE_FOURCC ('O', 'g', 'g', 'V'):
14892       /* ogg/vorbis */
14893       caps = gst_caps_new_empty_simple ("application/ogg");
14894       break;
14895     case GST_MAKE_FOURCC ('d', 'v', 'c', 'a'):
14896       _codec ("DV audio");
14897       caps = gst_caps_new_empty_simple ("audio/x-dv");
14898       break;
14899     case FOURCC_mp4a:
14900       _codec ("MPEG-4 AAC audio");
14901       caps = gst_caps_new_simple ("audio/mpeg",
14902           "mpegversion", G_TYPE_INT, 4, "framed", G_TYPE_BOOLEAN, TRUE,
14903           "stream-format", G_TYPE_STRING, "raw", NULL);
14904       break;
14905     case GST_MAKE_FOURCC ('Q', 'D', 'M', 'C'):
14906       _codec ("QDesign Music");
14907       caps = gst_caps_new_empty_simple ("audio/x-qdm");
14908       break;
14909     case FOURCC_QDM2:
14910       _codec ("QDesign Music v.2");
14911       /* FIXME: QDesign music version 2 (no constant) */
14912       if (FALSE && data) {
14913         caps = gst_caps_new_simple ("audio/x-qdm2",
14914             "framesize", G_TYPE_INT, QT_UINT32 (data + 52),
14915             "bitrate", G_TYPE_INT, QT_UINT32 (data + 40),
14916             "blocksize", G_TYPE_INT, QT_UINT32 (data + 44), NULL);
14917       } else {
14918         caps = gst_caps_new_empty_simple ("audio/x-qdm2");
14919       }
14920       break;
14921     case FOURCC_agsm:
14922       _codec ("GSM audio");
14923       caps = gst_caps_new_empty_simple ("audio/x-gsm");
14924       break;
14925     case FOURCC_samr:
14926       _codec ("AMR audio");
14927       caps = gst_caps_new_empty_simple ("audio/AMR");
14928       break;
14929     case FOURCC_sawb:
14930       _codec ("AMR-WB audio");
14931       caps = gst_caps_new_empty_simple ("audio/AMR-WB");
14932       break;
14933     case FOURCC_ima4:
14934       _codec ("Quicktime IMA ADPCM");
14935       caps = gst_caps_new_simple ("audio/x-adpcm",
14936           "layout", G_TYPE_STRING, "quicktime", NULL);
14937       break;
14938     case FOURCC_alac:
14939       _codec ("Apple lossless audio");
14940       caps = gst_caps_new_empty_simple ("audio/x-alac");
14941       break;
14942     case FOURCC_fLaC:
14943       _codec ("Free Lossless Audio Codec");
14944       caps = gst_caps_new_simple ("audio/x-flac",
14945           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
14946       break;
14947     case GST_MAKE_FOURCC ('Q', 'c', 'l', 'p'):
14948       _codec ("QualComm PureVoice");
14949       caps = gst_caps_from_string ("audio/qcelp");
14950       break;
14951     case FOURCC_wma_:
14952     case FOURCC_owma:
14953       _codec ("WMA");
14954       caps = gst_caps_new_empty_simple ("audio/x-wma");
14955       break;
14956     case FOURCC_opus:
14957       _codec ("Opus");
14958       caps = gst_caps_new_empty_simple ("audio/x-opus");
14959       break;
14960     case FOURCC_lpcm:
14961     {
14962       guint32 flags = 0;
14963       guint32 depth = 0;
14964       guint32 width = 0;
14965       GstAudioFormat format;
14966       enum
14967       {
14968         FLAG_IS_FLOAT = 0x1,
14969         FLAG_IS_BIG_ENDIAN = 0x2,
14970         FLAG_IS_SIGNED = 0x4,
14971         FLAG_IS_PACKED = 0x8,
14972         FLAG_IS_ALIGNED_HIGH = 0x10,
14973         FLAG_IS_NON_INTERLEAVED = 0x20
14974       };
14975       _codec ("Raw LPCM audio");
14976
14977       if (data && len >= 36) {
14978         depth = QT_UINT32 (data + 24);
14979         flags = QT_UINT32 (data + 28);
14980         width = QT_UINT32 (data + 32) * 8 / entry->n_channels;
14981       }
14982       if ((flags & FLAG_IS_FLOAT) == 0) {
14983         if (depth == 0)
14984           depth = 16;
14985         if (width == 0)
14986           width = 16;
14987         if ((flags & FLAG_IS_ALIGNED_HIGH))
14988           depth = width;
14989
14990         format = gst_audio_format_build_integer ((flags & FLAG_IS_SIGNED) ?
14991             TRUE : FALSE, (flags & FLAG_IS_BIG_ENDIAN) ?
14992             G_BIG_ENDIAN : G_LITTLE_ENDIAN, width, depth);
14993         caps = gst_caps_new_simple ("audio/x-raw",
14994             "format", G_TYPE_STRING,
14995             format !=
14996             GST_AUDIO_FORMAT_UNKNOWN ? gst_audio_format_to_string (format) :
14997             "UNKNOWN", "layout", G_TYPE_STRING,
14998             (flags & FLAG_IS_NON_INTERLEAVED) ? "non-interleaved" :
14999             "interleaved", NULL);
15000         stream->alignment = GST_ROUND_UP_8 (depth);
15001         stream->alignment = round_up_pow2 (stream->alignment);
15002       } else {
15003         if (width == 0)
15004           width = 32;
15005         if (width == 64) {
15006           if (flags & FLAG_IS_BIG_ENDIAN)
15007             format = GST_AUDIO_FORMAT_F64BE;
15008           else
15009             format = GST_AUDIO_FORMAT_F64LE;
15010         } else {
15011           if (flags & FLAG_IS_BIG_ENDIAN)
15012             format = GST_AUDIO_FORMAT_F32BE;
15013           else
15014             format = GST_AUDIO_FORMAT_F32LE;
15015         }
15016         caps = gst_caps_new_simple ("audio/x-raw",
15017             "format", G_TYPE_STRING, gst_audio_format_to_string (format),
15018             "layout", G_TYPE_STRING, (flags & FLAG_IS_NON_INTERLEAVED) ?
15019             "non-interleaved" : "interleaved", NULL);
15020         stream->alignment = width / 8;
15021       }
15022       break;
15023     }
15024     case GST_MAKE_FOURCC ('q', 't', 'v', 'r'):
15025       /* ? */
15026     default:
15027     {
15028       caps = _get_unknown_codec_name ("audio", fourcc);
15029       break;
15030     }
15031   }
15032
15033   if (caps) {
15034     GstCaps *templ_caps =
15035         gst_static_pad_template_get_caps (&gst_qtdemux_audiosrc_template);
15036     GstCaps *intersection = gst_caps_intersect (caps, templ_caps);
15037     gst_caps_unref (caps);
15038     gst_caps_unref (templ_caps);
15039     caps = intersection;
15040   }
15041
15042   /* enable clipping for raw audio streams */
15043   s = gst_caps_get_structure (caps, 0);
15044   name = gst_structure_get_name (s);
15045   if (g_str_has_prefix (name, "audio/x-raw")) {
15046     stream->need_clip = TRUE;
15047     stream->max_buffer_size = 4096 * entry->bytes_per_frame;
15048     GST_DEBUG ("setting max buffer size to %d", stream->max_buffer_size);
15049   }
15050   return caps;
15051 }
15052
15053 static GstCaps *
15054 qtdemux_sub_caps (GstQTDemux * qtdemux, QtDemuxStream * stream,
15055     QtDemuxStreamStsdEntry * entry, guint32 fourcc,
15056     const guint8 * stsd_entry_data, gchar ** codec_name)
15057 {
15058   GstCaps *caps;
15059
15060   GST_DEBUG_OBJECT (qtdemux, "resolve fourcc 0x%08x", GUINT32_TO_BE (fourcc));
15061
15062   switch (fourcc) {
15063     case FOURCC_mp4s:
15064       _codec ("DVD subtitle");
15065       caps = gst_caps_new_empty_simple ("subpicture/x-dvd");
15066       stream->need_process = TRUE;
15067       break;
15068     case FOURCC_text:
15069       _codec ("Quicktime timed text");
15070       goto text;
15071     case FOURCC_tx3g:
15072       _codec ("3GPP timed text");
15073     text:
15074       caps = gst_caps_new_simple ("text/x-raw", "format", G_TYPE_STRING,
15075           "utf8", NULL);
15076       /* actual text piece needs to be extracted */
15077       stream->need_process = TRUE;
15078       break;
15079     case FOURCC_stpp:
15080       _codec ("XML subtitles");
15081       caps = gst_caps_new_empty_simple ("application/ttml+xml");
15082       break;
15083     case FOURCC_c608:
15084       _codec ("CEA 608 Closed Caption");
15085       caps =
15086           gst_caps_new_simple ("closedcaption/x-cea-608", "format",
15087           G_TYPE_STRING, "cc_data", NULL);
15088       stream->need_process = TRUE;
15089       break;
15090     case FOURCC_c708:
15091       _codec ("CEA 708 Closed Caption");
15092       caps =
15093           gst_caps_new_simple ("closedcaption/x-cea-708", "format",
15094           G_TYPE_STRING, "cdp", NULL);
15095       stream->need_process = TRUE;
15096       break;
15097
15098     default:
15099     {
15100       caps = _get_unknown_codec_name ("text", fourcc);
15101       break;
15102     }
15103   }
15104   return caps;
15105 }
15106
15107 static GstCaps *
15108 qtdemux_generic_caps (GstQTDemux * qtdemux, QtDemuxStream * stream,
15109     QtDemuxStreamStsdEntry * entry, guint32 fourcc,
15110     const guint8 * stsd_entry_data, gchar ** codec_name)
15111 {
15112   GstCaps *caps;
15113
15114   switch (fourcc) {
15115     case FOURCC_m1v:
15116       _codec ("MPEG 1 video");
15117       caps = gst_caps_new_simple ("video/mpeg", "mpegversion", G_TYPE_INT, 1,
15118           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
15119       break;
15120     default:
15121       caps = NULL;
15122       break;
15123   }
15124   return caps;
15125 }
15126
15127 static void
15128 gst_qtdemux_append_protection_system_id (GstQTDemux * qtdemux,
15129     const gchar * system_id)
15130 {
15131   gint i;
15132
15133   if (!qtdemux->protection_system_ids)
15134     qtdemux->protection_system_ids =
15135         g_ptr_array_new_with_free_func ((GDestroyNotify) g_free);
15136   /* Check whether we already have an entry for this system ID. */
15137   for (i = 0; i < qtdemux->protection_system_ids->len; ++i) {
15138     const gchar *id = g_ptr_array_index (qtdemux->protection_system_ids, i);
15139     if (g_ascii_strcasecmp (system_id, id) == 0) {
15140       return;
15141     }
15142   }
15143   GST_DEBUG_OBJECT (qtdemux, "Adding cenc protection system ID %s", system_id);
15144   g_ptr_array_add (qtdemux->protection_system_ids, g_ascii_strdown (system_id,
15145           -1));
15146 }