d953ca039b4c08640b01448212b362a2038b65ca
[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_STREAM(s) ((QtDemuxStream *)(s))
101 #define QTDEMUX_N_STREAMS(demux) ((demux)->active_streams->len)
102 #define QTDEMUX_NTH_STREAM(demux,idx) \
103    QTDEMUX_STREAM(g_ptr_array_index((demux)->active_streams,idx))
104 #define QTDEMUX_NTH_OLD_STREAM(demux,idx) \
105    QTDEMUX_STREAM(g_ptr_array_index((demux)->old_streams,idx))
106
107 GST_DEBUG_CATEGORY (qtdemux_debug);
108 #define GST_CAT_DEFAULT qtdemux_debug
109
110 typedef struct _QtDemuxSegment QtDemuxSegment;
111 typedef struct _QtDemuxSample QtDemuxSample;
112
113 typedef struct _QtDemuxCencSampleSetInfo QtDemuxCencSampleSetInfo;
114
115 struct _QtDemuxSample
116 {
117   guint32 size;
118   gint32 pts_offset;            /* Add this value to timestamp to get the pts */
119   guint64 offset;
120   guint64 timestamp;            /* DTS In mov time */
121   guint32 duration;             /* In mov time */
122   gboolean keyframe;            /* TRUE when this packet is a keyframe */
123 };
124
125 /* Macros for converting to/from timescale */
126 #define QTSTREAMTIME_TO_GSTTIME(stream, value) (gst_util_uint64_scale((value), GST_SECOND, (stream)->timescale))
127 #define GSTTIME_TO_QTSTREAMTIME(stream, value) (gst_util_uint64_scale((value), (stream)->timescale, GST_SECOND))
128
129 #define QTTIME_TO_GSTTIME(qtdemux, value) (gst_util_uint64_scale((value), GST_SECOND, (qtdemux)->timescale))
130 #define GSTTIME_TO_QTTIME(qtdemux, value) (gst_util_uint64_scale((value), (qtdemux)->timescale, GST_SECOND))
131
132 /* timestamp is the DTS */
133 #define QTSAMPLE_DTS(stream,sample) (QTSTREAMTIME_TO_GSTTIME((stream), (sample)->timestamp))
134 /* timestamp + offset + cslg_shift is the outgoing PTS */
135 #define QTSAMPLE_PTS(stream,sample) (QTSTREAMTIME_TO_GSTTIME((stream), (sample)->timestamp + (stream)->cslg_shift + (sample)->pts_offset))
136 /* timestamp + offset is the PTS used for internal seek calcuations */
137 #define QTSAMPLE_PTS_NO_CSLG(stream,sample) (QTSTREAMTIME_TO_GSTTIME((stream), (sample)->timestamp + (sample)->pts_offset))
138 /* timestamp + duration - dts is the duration */
139 #define QTSAMPLE_DUR_DTS(stream, sample, dts) (QTSTREAMTIME_TO_GSTTIME ((stream), (sample)->timestamp + (sample)->duration) - (dts))
140
141 #define QTSAMPLE_KEYFRAME(stream,sample) ((stream)->all_keyframe || (sample)->keyframe)
142
143 #define QTDEMUX_EXPOSE_GET_LOCK(demux) (&((demux)->expose_lock))
144 #define QTDEMUX_EXPOSE_LOCK(demux) G_STMT_START { \
145     GST_TRACE("Locking from thread %p", g_thread_self()); \
146     g_mutex_lock (QTDEMUX_EXPOSE_GET_LOCK (demux)); \
147     GST_TRACE("Locked from thread %p", g_thread_self()); \
148  } G_STMT_END
149
150 #define QTDEMUX_EXPOSE_UNLOCK(demux) G_STMT_START { \
151     GST_TRACE("Unlocking from thread %p", g_thread_self()); \
152     g_mutex_unlock (QTDEMUX_EXPOSE_GET_LOCK (demux)); \
153  } G_STMT_END
154
155 /*
156  * Quicktime has tracks and segments. A track is a continuous piece of
157  * multimedia content. The track is not always played from start to finish but
158  * instead, pieces of the track are 'cut out' and played in sequence. This is
159  * what the segments do.
160  *
161  * Inside the track we have keyframes (K) and delta frames. The track has its
162  * own timing, which starts from 0 and extends to end. The position in the track
163  * is called the media_time.
164  *
165  * The segments now describe the pieces that should be played from this track
166  * and are basically tuples of media_time/duration/rate entries. We can have
167  * multiple segments and they are all played after one another. An example:
168  *
169  * segment 1: media_time: 1 second, duration: 1 second, rate 1
170  * segment 2: media_time: 3 second, duration: 2 second, rate 2
171  *
172  * To correctly play back this track, one must play: 1 second of media starting
173  * from media_time 1 followed by 2 seconds of media starting from media_time 3
174  * at a rate of 2.
175  *
176  * Each of the segments will be played at a specific time, the first segment at
177  * time 0, the second one after the duration of the first one, etc.. Note that
178  * the time in resulting playback is not identical to the media_time of the
179  * track anymore.
180  *
181  * Visually, assuming the track has 4 second of media_time:
182  *
183  *                (a)                   (b)          (c)              (d)
184  *         .-----------------------------------------------------------.
185  * track:  | K.....K.........K........K.......K.......K...........K... |
186  *         '-----------------------------------------------------------'
187  *         0              1              2              3              4
188  *           .------------^              ^   .----------^              ^
189  *          /              .-------------'  /       .------------------'
190  *         /              /          .-----'       /
191  *         .--------------.         .--------------.
192  *         | segment 1    |         | segment 2    |
193  *         '--------------'         '--------------'
194  *
195  * The challenge here is to cut out the right pieces of the track for each of
196  * the playback segments. This fortunately can easily be done with the SEGMENT
197  * events of GStreamer.
198  *
199  * For playback of segment 1, we need to provide the decoder with the keyframe
200  * (a), in the above figure, but we must instruct it only to output the decoded
201  * data between second 1 and 2. We do this with a SEGMENT event for 1 to 2, time
202  * position set to the time of the segment: 0.
203  *
204  * We then proceed to push data from keyframe (a) to frame (b). The decoder
205  * decodes but clips all before media_time 1.
206  *
207  * After finishing a segment, we push out a new SEGMENT event with the clipping
208  * boundaries of the new data.
209  *
210  * This is a good usecase for the GStreamer accumulated SEGMENT events.
211  */
212
213 struct _QtDemuxSegment
214 {
215   /* global time and duration, all gst time */
216   GstClockTime time;
217   GstClockTime stop_time;
218   GstClockTime duration;
219   /* media time of trak, all gst time */
220   GstClockTime media_start;
221   GstClockTime media_stop;
222   gdouble rate;
223   /* Media start time in trak timescale units */
224   guint32 trak_media_start;
225 };
226
227 #define QTSEGMENT_IS_EMPTY(s) ((s)->media_start == GST_CLOCK_TIME_NONE)
228
229 /* Used with fragmented MP4 files (mfra atom) */
230 typedef struct
231 {
232   GstClockTime ts;
233   guint64 moof_offset;
234 } QtDemuxRandomAccessEntry;
235
236 typedef struct _QtDemuxStreamStsdEntry
237 {
238   GstCaps *caps;
239   guint32 fourcc;
240   gboolean sparse;
241
242   /* video info */
243   gint width;
244   gint height;
245   gint par_w;
246   gint par_h;
247   /* Numerator/denominator framerate */
248   gint fps_n;
249   gint fps_d;
250   GstVideoColorimetry colorimetry;
251   guint16 bits_per_sample;
252   guint16 color_table_id;
253   GstMemory *rgb8_palette;
254   guint interlace_mode;
255   guint field_order;
256
257   /* audio info */
258   gdouble rate;
259   gint n_channels;
260   guint samples_per_packet;
261   guint samples_per_frame;
262   guint bytes_per_packet;
263   guint bytes_per_sample;
264   guint bytes_per_frame;
265   guint compression;
266
267   /* if we use chunks or samples */
268   gboolean sampled;
269   guint padding;
270
271 } QtDemuxStreamStsdEntry;
272
273 #define CUR_STREAM(s) (&((s)->stsd_entries[(s)->cur_stsd_entry_index]))
274
275 struct _QtDemuxStream
276 {
277   GstPad *pad;
278
279   GstQTDemux *demux;
280   gchar *stream_id;
281
282   QtDemuxStreamStsdEntry *stsd_entries;
283   guint stsd_entries_length;
284   guint cur_stsd_entry_index;
285
286   /* stream type */
287   guint32 subtype;
288
289   gboolean new_caps;            /* If TRUE, caps need to be generated (by
290                                  * calling _configure_stream()) This happens
291                                  * for MSS and fragmented streams */
292
293   gboolean new_stream;          /* signals that a stream_start is required */
294   gboolean on_keyframe;         /* if this stream last pushed buffer was a
295                                  * keyframe. This is important to identify
296                                  * where to stop pushing buffers after a
297                                  * segment stop time */
298
299   /* if the stream has a redirect URI in its headers, we store it here */
300   gchar *redirect_uri;
301
302   /* track id */
303   guint track_id;
304
305   /* duration/scale */
306   guint64 duration;             /* in timescale units */
307   guint32 timescale;
308
309   /* language */
310   gchar lang_id[4];             /* ISO 639-2T language code */
311
312   /* our samples */
313   guint32 n_samples;
314   QtDemuxSample *samples;
315   gboolean all_keyframe;        /* TRUE when all samples are keyframes (no stss) */
316   guint32 n_samples_moof;       /* sample count in a moof */
317   guint64 duration_moof;        /* duration in timescale of a moof, used for figure out
318                                  * the framerate of fragmented format stream */
319   guint64 duration_last_moof;
320
321   guint32 offset_in_sample;     /* Offset in the current sample, used for
322                                  * streams which have got exceedingly big
323                                  * sample size (such as 24s of raw audio).
324                                  * Only used when max_buffer_size is non-NULL */
325   guint32 max_buffer_size;      /* Maximum allowed size for output buffers.
326                                  * Currently only set for raw audio streams*/
327
328   /* video info */
329   /* aspect ratio */
330   gint display_width;
331   gint display_height;
332
333   /* allocation */
334   gboolean use_allocator;
335   GstAllocator *allocator;
336   GstAllocationParams params;
337
338   gsize alignment;
339
340   /* when a discontinuity is pending */
341   gboolean discont;
342
343   /* list of buffers to push first */
344   GSList *buffers;
345
346   /* if we need to clip this buffer. This is only needed for uncompressed
347    * data */
348   gboolean need_clip;
349
350   /* buffer needs some custom processing, e.g. subtitles */
351   gboolean need_process;
352
353   /* current position */
354   guint32 segment_index;
355   guint32 sample_index;
356   GstClockTime time_position;   /* in gst time */
357   guint64 accumulated_base;
358
359   /* the Gst segment we are processing out, used for clipping */
360   GstSegment segment;
361
362   /* quicktime segments */
363   guint32 n_segments;
364   QtDemuxSegment *segments;
365   gboolean dummy_segment;
366   guint32 from_sample;
367   guint32 to_sample;
368
369   gboolean sent_eos;
370   GstTagList *stream_tags;
371   gboolean send_global_tags;
372
373   GstEvent *pending_event;
374
375   GstByteReader stco;
376   GstByteReader stsz;
377   GstByteReader stsc;
378   GstByteReader stts;
379   GstByteReader stss;
380   GstByteReader stps;
381   GstByteReader ctts;
382
383   gboolean chunks_are_samples;  /* TRUE means treat chunks as samples */
384   gint64 stbl_index;
385   /* stco */
386   guint co_size;
387   GstByteReader co_chunk;
388   guint32 first_chunk;
389   guint32 current_chunk;
390   guint32 last_chunk;
391   guint32 samples_per_chunk;
392   guint32 stsd_sample_description_id;
393   guint32 stco_sample_index;
394   /* stsz */
395   guint32 sample_size;          /* 0 means variable sizes are stored in stsz */
396   /* stsc */
397   guint32 stsc_index;
398   guint32 n_samples_per_chunk;
399   guint32 stsc_chunk_index;
400   guint32 stsc_sample_index;
401   guint64 chunk_offset;
402   /* stts */
403   guint32 stts_index;
404   guint32 stts_samples;
405   guint32 n_sample_times;
406   guint32 stts_sample_index;
407   guint64 stts_time;
408   guint32 stts_duration;
409   /* stss */
410   gboolean stss_present;
411   guint32 n_sample_syncs;
412   guint32 stss_index;
413   /* stps */
414   gboolean stps_present;
415   guint32 n_sample_partial_syncs;
416   guint32 stps_index;
417   QtDemuxRandomAccessEntry *ra_entries;
418   guint n_ra_entries;
419
420   const QtDemuxRandomAccessEntry *pending_seek;
421
422   /* ctts */
423   gboolean ctts_present;
424   guint32 n_composition_times;
425   guint32 ctts_index;
426   guint32 ctts_sample_index;
427   guint32 ctts_count;
428   gint32 ctts_soffset;
429
430   /* cslg */
431   guint32 cslg_shift;
432
433   /* fragmented */
434   gboolean parsed_trex;
435   guint32 def_sample_description_index; /* index is 1-based */
436   guint32 def_sample_duration;
437   guint32 def_sample_size;
438   guint32 def_sample_flags;
439
440   gboolean disabled;
441
442   /* stereoscopic video streams */
443   GstVideoMultiviewMode multiview_mode;
444   GstVideoMultiviewFlags multiview_flags;
445
446   /* protected streams */
447   gboolean protected;
448   guint32 protection_scheme_type;
449   guint32 protection_scheme_version;
450   gpointer protection_scheme_info;      /* specific to the protection scheme */
451   GQueue protection_scheme_event_queue;
452
453   gint ref_count;               /* atomic */
454 };
455
456 /* Contains properties and cryptographic info for a set of samples from a
457  * track protected using Common Encryption (cenc) */
458 struct _QtDemuxCencSampleSetInfo
459 {
460   GstStructure *default_properties;
461
462   /* @crypto_info holds one GstStructure per sample */
463   GPtrArray *crypto_info;
464 };
465
466 static const gchar *
467 qt_demux_state_string (enum QtDemuxState state)
468 {
469   switch (state) {
470     case QTDEMUX_STATE_INITIAL:
471       return "<INITIAL>";
472     case QTDEMUX_STATE_HEADER:
473       return "<HEADER>";
474     case QTDEMUX_STATE_MOVIE:
475       return "<MOVIE>";
476     case QTDEMUX_STATE_BUFFER_MDAT:
477       return "<BUFFER_MDAT>";
478     default:
479       return "<UNKNOWN>";
480   }
481 }
482
483 static GNode *qtdemux_tree_get_child_by_type (GNode * node, guint32 fourcc);
484 static GNode *qtdemux_tree_get_child_by_type_full (GNode * node,
485     guint32 fourcc, GstByteReader * parser);
486 static GNode *qtdemux_tree_get_sibling_by_type (GNode * node, guint32 fourcc);
487 static GNode *qtdemux_tree_get_sibling_by_type_full (GNode * node,
488     guint32 fourcc, GstByteReader * parser);
489
490 static GstFlowReturn qtdemux_add_fragmented_samples (GstQTDemux * qtdemux);
491
492 static void gst_qtdemux_check_send_pending_segment (GstQTDemux * demux);
493
494 static GstStaticPadTemplate gst_qtdemux_sink_template =
495     GST_STATIC_PAD_TEMPLATE ("sink",
496     GST_PAD_SINK,
497     GST_PAD_ALWAYS,
498     GST_STATIC_CAPS ("video/quicktime; video/mj2; audio/x-m4a; "
499         "application/x-3gp")
500     );
501
502 static GstStaticPadTemplate gst_qtdemux_videosrc_template =
503 GST_STATIC_PAD_TEMPLATE ("video_%u",
504     GST_PAD_SRC,
505     GST_PAD_SOMETIMES,
506     GST_STATIC_CAPS_ANY);
507
508 static GstStaticPadTemplate gst_qtdemux_audiosrc_template =
509 GST_STATIC_PAD_TEMPLATE ("audio_%u",
510     GST_PAD_SRC,
511     GST_PAD_SOMETIMES,
512     GST_STATIC_CAPS_ANY);
513
514 static GstStaticPadTemplate gst_qtdemux_subsrc_template =
515 GST_STATIC_PAD_TEMPLATE ("subtitle_%u",
516     GST_PAD_SRC,
517     GST_PAD_SOMETIMES,
518     GST_STATIC_CAPS_ANY);
519
520 #define gst_qtdemux_parent_class parent_class
521 G_DEFINE_TYPE (GstQTDemux, gst_qtdemux, GST_TYPE_ELEMENT);
522
523 static void gst_qtdemux_dispose (GObject * object);
524
525 static guint32
526 gst_qtdemux_find_index_linear (GstQTDemux * qtdemux, QtDemuxStream * str,
527     GstClockTime media_time);
528 static guint32
529 gst_qtdemux_find_index_for_given_media_offset_linear (GstQTDemux * qtdemux,
530     QtDemuxStream * str, gint64 media_offset);
531
532 #if 0
533 static void gst_qtdemux_set_index (GstElement * element, GstIndex * index);
534 static GstIndex *gst_qtdemux_get_index (GstElement * element);
535 #endif
536 static GstStateChangeReturn gst_qtdemux_change_state (GstElement * element,
537     GstStateChange transition);
538 static void gst_qtdemux_set_context (GstElement * element,
539     GstContext * context);
540 static gboolean qtdemux_sink_activate (GstPad * sinkpad, GstObject * parent);
541 static gboolean qtdemux_sink_activate_mode (GstPad * sinkpad,
542     GstObject * parent, GstPadMode mode, gboolean active);
543
544 static void gst_qtdemux_loop (GstPad * pad);
545 static GstFlowReturn gst_qtdemux_chain (GstPad * sinkpad, GstObject * parent,
546     GstBuffer * inbuf);
547 static gboolean gst_qtdemux_handle_sink_event (GstPad * pad, GstObject * parent,
548     GstEvent * event);
549 static gboolean gst_qtdemux_setcaps (GstQTDemux * qtdemux, GstCaps * caps);
550 static gboolean gst_qtdemux_configure_stream (GstQTDemux * qtdemux,
551     QtDemuxStream * stream);
552 static void gst_qtdemux_stream_check_and_change_stsd_index (GstQTDemux * demux,
553     QtDemuxStream * stream);
554 static GstFlowReturn gst_qtdemux_process_adapter (GstQTDemux * demux,
555     gboolean force);
556
557 static gboolean qtdemux_parse_moov (GstQTDemux * qtdemux,
558     const guint8 * buffer, guint length);
559 static gboolean qtdemux_parse_node (GstQTDemux * qtdemux, GNode * node,
560     const guint8 * buffer, guint length);
561 static gboolean qtdemux_parse_tree (GstQTDemux * qtdemux);
562 static void qtdemux_parse_udta (GstQTDemux * qtdemux, GstTagList * taglist,
563     GNode * udta);
564
565 static void gst_qtdemux_handle_esds (GstQTDemux * qtdemux,
566     QtDemuxStream * stream, QtDemuxStreamStsdEntry * entry, GNode * esds,
567     GstTagList * list);
568 static GstCaps *qtdemux_video_caps (GstQTDemux * qtdemux,
569     QtDemuxStream * stream, QtDemuxStreamStsdEntry * entry, guint32 fourcc,
570     const guint8 * stsd_entry_data, gchar ** codec_name);
571 static GstCaps *qtdemux_audio_caps (GstQTDemux * qtdemux,
572     QtDemuxStream * stream, QtDemuxStreamStsdEntry * entry, guint32 fourcc,
573     const guint8 * data, int len, gchar ** codec_name);
574 static GstCaps *qtdemux_sub_caps (GstQTDemux * qtdemux, QtDemuxStream * stream,
575     QtDemuxStreamStsdEntry * entry, guint32 fourcc, const guint8 * data,
576     gchar ** codec_name);
577 static GstCaps *qtdemux_generic_caps (GstQTDemux * qtdemux,
578     QtDemuxStream * stream, QtDemuxStreamStsdEntry * entry, guint32 fourcc,
579     const guint8 * stsd_entry_data, gchar ** codec_name);
580
581 static gboolean qtdemux_parse_samples (GstQTDemux * qtdemux,
582     QtDemuxStream * stream, guint32 n);
583 static GstFlowReturn qtdemux_expose_streams (GstQTDemux * qtdemux);
584 static QtDemuxStream *gst_qtdemux_stream_ref (QtDemuxStream * stream);
585 static void gst_qtdemux_stream_unref (QtDemuxStream * stream);
586 static void gst_qtdemux_stream_clear (QtDemuxStream * stream);
587 static GstFlowReturn qtdemux_prepare_streams (GstQTDemux * qtdemux);
588 static void qtdemux_do_allocation (QtDemuxStream * stream,
589     GstQTDemux * qtdemux);
590 static gboolean gst_qtdemux_activate_segment (GstQTDemux * qtdemux,
591     QtDemuxStream * stream, guint32 seg_idx, GstClockTime offset);
592 static gboolean gst_qtdemux_stream_update_segment (GstQTDemux * qtdemux,
593     QtDemuxStream * stream, gint seg_idx, GstClockTime offset,
594     GstClockTime * _start, GstClockTime * _stop);
595 static void gst_qtdemux_send_gap_for_segment (GstQTDemux * demux,
596     QtDemuxStream * stream, gint segment_index, GstClockTime pos);
597
598 static gboolean qtdemux_pull_mfro_mfra (GstQTDemux * qtdemux);
599 static void check_update_duration (GstQTDemux * qtdemux, GstClockTime duration);
600
601 static gchar *qtdemux_uuid_bytes_to_string (gconstpointer uuid_bytes);
602
603 static GstStructure *qtdemux_get_cenc_sample_properties (GstQTDemux * qtdemux,
604     QtDemuxStream * stream, guint sample_index);
605 static void gst_qtdemux_append_protection_system_id (GstQTDemux * qtdemux,
606     const gchar * id);
607 static void qtdemux_gst_structure_free (GstStructure * gststructure);
608 static void gst_qtdemux_reset (GstQTDemux * qtdemux, gboolean hard);
609
610 static void
611 gst_qtdemux_class_init (GstQTDemuxClass * klass)
612 {
613   GObjectClass *gobject_class;
614   GstElementClass *gstelement_class;
615
616   gobject_class = (GObjectClass *) klass;
617   gstelement_class = (GstElementClass *) klass;
618
619   parent_class = g_type_class_peek_parent (klass);
620
621   gobject_class->dispose = gst_qtdemux_dispose;
622
623   gstelement_class->change_state = GST_DEBUG_FUNCPTR (gst_qtdemux_change_state);
624 #if 0
625   gstelement_class->set_index = GST_DEBUG_FUNCPTR (gst_qtdemux_set_index);
626   gstelement_class->get_index = GST_DEBUG_FUNCPTR (gst_qtdemux_get_index);
627 #endif
628   gstelement_class->set_context = GST_DEBUG_FUNCPTR (gst_qtdemux_set_context);
629
630   gst_tag_register_musicbrainz_tags ();
631
632   gst_element_class_add_static_pad_template (gstelement_class,
633       &gst_qtdemux_sink_template);
634   gst_element_class_add_static_pad_template (gstelement_class,
635       &gst_qtdemux_videosrc_template);
636   gst_element_class_add_static_pad_template (gstelement_class,
637       &gst_qtdemux_audiosrc_template);
638   gst_element_class_add_static_pad_template (gstelement_class,
639       &gst_qtdemux_subsrc_template);
640   gst_element_class_set_static_metadata (gstelement_class, "QuickTime demuxer",
641       "Codec/Demuxer",
642       "Demultiplex a QuickTime file into audio and video streams",
643       "David Schleef <ds@schleef.org>, Wim Taymans <wim@fluendo.com>");
644
645   GST_DEBUG_CATEGORY_INIT (qtdemux_debug, "qtdemux", 0, "qtdemux plugin");
646   gst_riff_init ();
647 }
648
649 static void
650 gst_qtdemux_init (GstQTDemux * qtdemux)
651 {
652   qtdemux->sinkpad =
653       gst_pad_new_from_static_template (&gst_qtdemux_sink_template, "sink");
654   gst_pad_set_activate_function (qtdemux->sinkpad, qtdemux_sink_activate);
655   gst_pad_set_activatemode_function (qtdemux->sinkpad,
656       qtdemux_sink_activate_mode);
657   gst_pad_set_chain_function (qtdemux->sinkpad, gst_qtdemux_chain);
658   gst_pad_set_event_function (qtdemux->sinkpad, gst_qtdemux_handle_sink_event);
659   gst_element_add_pad (GST_ELEMENT_CAST (qtdemux), qtdemux->sinkpad);
660
661   qtdemux->adapter = gst_adapter_new ();
662   g_queue_init (&qtdemux->protection_event_queue);
663   qtdemux->flowcombiner = gst_flow_combiner_new ();
664   g_mutex_init (&qtdemux->expose_lock);
665
666   qtdemux->active_streams = g_ptr_array_new_with_free_func
667       ((GDestroyNotify) gst_qtdemux_stream_unref);
668   qtdemux->old_streams = g_ptr_array_new_with_free_func
669       ((GDestroyNotify) gst_qtdemux_stream_unref);
670
671   GST_OBJECT_FLAG_SET (qtdemux, GST_ELEMENT_FLAG_INDEXABLE);
672
673   gst_qtdemux_reset (qtdemux, TRUE);
674 }
675
676 static void
677 gst_qtdemux_dispose (GObject * object)
678 {
679   GstQTDemux *qtdemux = GST_QTDEMUX (object);
680
681   if (qtdemux->adapter) {
682     g_object_unref (G_OBJECT (qtdemux->adapter));
683     qtdemux->adapter = NULL;
684   }
685   gst_tag_list_unref (qtdemux->tag_list);
686   gst_flow_combiner_free (qtdemux->flowcombiner);
687   g_queue_foreach (&qtdemux->protection_event_queue, (GFunc) gst_event_unref,
688       NULL);
689   g_queue_clear (&qtdemux->protection_event_queue);
690
691   g_free (qtdemux->cenc_aux_info_sizes);
692   qtdemux->cenc_aux_info_sizes = NULL;
693   g_mutex_clear (&qtdemux->expose_lock);
694
695   g_ptr_array_free (qtdemux->active_streams, TRUE);
696   g_ptr_array_free (qtdemux->old_streams, TRUE);
697
698   G_OBJECT_CLASS (parent_class)->dispose (object);
699 }
700
701 static void
702 gst_qtdemux_post_no_playable_stream_error (GstQTDemux * qtdemux)
703 {
704   if (qtdemux->posted_redirect) {
705     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
706         (_("This file contains no playable streams.")),
707         ("no known streams found, a redirect message has been posted"));
708   } else {
709     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
710         (_("This file contains no playable streams.")),
711         ("no known streams found"));
712   }
713 }
714
715 static GstBuffer *
716 _gst_buffer_new_wrapped (gpointer mem, gsize size, GFreeFunc free_func)
717 {
718   return gst_buffer_new_wrapped_full (free_func ? 0 : GST_MEMORY_FLAG_READONLY,
719       mem, size, 0, size, mem, free_func);
720 }
721
722 static GstFlowReturn
723 gst_qtdemux_pull_atom (GstQTDemux * qtdemux, guint64 offset, guint64 size,
724     GstBuffer ** buf)
725 {
726   GstFlowReturn flow;
727   GstMapInfo map;
728   gsize bsize;
729
730   if (G_UNLIKELY (size == 0)) {
731     GstFlowReturn ret;
732     GstBuffer *tmp = NULL;
733
734     ret = gst_qtdemux_pull_atom (qtdemux, offset, sizeof (guint32), &tmp);
735     if (ret != GST_FLOW_OK)
736       return ret;
737
738     gst_buffer_map (tmp, &map, GST_MAP_READ);
739     size = QT_UINT32 (map.data);
740     GST_DEBUG_OBJECT (qtdemux, "size 0x%08" G_GINT64_MODIFIER "x", size);
741
742     gst_buffer_unmap (tmp, &map);
743     gst_buffer_unref (tmp);
744   }
745
746   /* Sanity check: catch bogus sizes (fuzzed/broken files) */
747   if (G_UNLIKELY (size > QTDEMUX_MAX_ATOM_SIZE)) {
748     if (qtdemux->state != QTDEMUX_STATE_MOVIE && qtdemux->got_moov) {
749       /* we're pulling header but already got most interesting bits,
750        * so never mind the rest (e.g. tags) (that much) */
751       GST_WARNING_OBJECT (qtdemux, "atom has bogus size %" G_GUINT64_FORMAT,
752           size);
753       return GST_FLOW_EOS;
754     } else {
755       GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
756           (_("This file is invalid and cannot be played.")),
757           ("atom has bogus size %" G_GUINT64_FORMAT, size));
758       return GST_FLOW_ERROR;
759     }
760   }
761
762   flow = gst_pad_pull_range (qtdemux->sinkpad, offset, size, buf);
763
764   if (G_UNLIKELY (flow != GST_FLOW_OK))
765     return flow;
766
767   bsize = gst_buffer_get_size (*buf);
768   /* Catch short reads - we don't want any partial atoms */
769   if (G_UNLIKELY (bsize < size)) {
770     GST_WARNING_OBJECT (qtdemux,
771         "short read: %" G_GSIZE_FORMAT " < %" G_GUINT64_FORMAT, bsize, size);
772     gst_buffer_unref (*buf);
773     *buf = NULL;
774     return GST_FLOW_EOS;
775   }
776
777   return flow;
778 }
779
780 #if 1
781 static gboolean
782 gst_qtdemux_src_convert (GstQTDemux * qtdemux, GstPad * pad,
783     GstFormat src_format, gint64 src_value, GstFormat dest_format,
784     gint64 * dest_value)
785 {
786   gboolean res = TRUE;
787   QtDemuxStream *stream = gst_pad_get_element_private (pad);
788   gint32 index;
789
790   if (stream->subtype != FOURCC_vide) {
791     res = FALSE;
792     goto done;
793   }
794
795   switch (src_format) {
796     case GST_FORMAT_TIME:
797       switch (dest_format) {
798         case GST_FORMAT_BYTES:{
799           index = gst_qtdemux_find_index_linear (qtdemux, stream, src_value);
800           if (-1 == index) {
801             res = FALSE;
802             goto done;
803           }
804
805           *dest_value = stream->samples[index].offset;
806
807           GST_DEBUG_OBJECT (qtdemux, "Format Conversion Time->Offset :%"
808               GST_TIME_FORMAT "->%" G_GUINT64_FORMAT,
809               GST_TIME_ARGS (src_value), *dest_value);
810           break;
811         }
812         default:
813           res = FALSE;
814           break;
815       }
816       break;
817     case GST_FORMAT_BYTES:
818       switch (dest_format) {
819         case GST_FORMAT_TIME:{
820           index =
821               gst_qtdemux_find_index_for_given_media_offset_linear (qtdemux,
822               stream, src_value);
823
824           if (-1 == index) {
825             res = FALSE;
826             goto done;
827           }
828
829           *dest_value =
830               QTSTREAMTIME_TO_GSTTIME (stream,
831               stream->samples[index].timestamp);
832           GST_DEBUG_OBJECT (qtdemux,
833               "Format Conversion Offset->Time :%" G_GUINT64_FORMAT "->%"
834               GST_TIME_FORMAT, src_value, GST_TIME_ARGS (*dest_value));
835           break;
836         }
837         default:
838           res = FALSE;
839           break;
840       }
841       break;
842     default:
843       res = FALSE;
844       break;
845   }
846
847 done:
848   return res;
849 }
850 #endif
851
852 static gboolean
853 gst_qtdemux_get_duration (GstQTDemux * qtdemux, GstClockTime * duration)
854 {
855   gboolean res = FALSE;
856
857   *duration = GST_CLOCK_TIME_NONE;
858
859   if (qtdemux->duration != 0 &&
860       qtdemux->duration != G_MAXINT64 && qtdemux->timescale != 0) {
861     *duration = QTTIME_TO_GSTTIME (qtdemux, qtdemux->duration);
862     res = TRUE;
863   } else {
864     *duration = GST_CLOCK_TIME_NONE;
865   }
866
867   return res;
868 }
869
870 static gboolean
871 gst_qtdemux_handle_src_query (GstPad * pad, GstObject * parent,
872     GstQuery * query)
873 {
874   gboolean res = FALSE;
875   GstQTDemux *qtdemux = GST_QTDEMUX (parent);
876
877   GST_LOG_OBJECT (pad, "%s query", GST_QUERY_TYPE_NAME (query));
878
879   switch (GST_QUERY_TYPE (query)) {
880     case GST_QUERY_POSITION:{
881       GstFormat fmt;
882
883       gst_query_parse_position (query, &fmt, NULL);
884       if (fmt == GST_FORMAT_TIME
885           && GST_CLOCK_TIME_IS_VALID (qtdemux->segment.position)) {
886         gst_query_set_position (query, GST_FORMAT_TIME,
887             qtdemux->segment.position);
888         res = TRUE;
889       }
890     }
891       break;
892     case GST_QUERY_DURATION:{
893       GstFormat fmt;
894
895       gst_query_parse_duration (query, &fmt, NULL);
896       if (fmt == GST_FORMAT_TIME) {
897         /* First try to query upstream */
898         res = gst_pad_query_default (pad, parent, query);
899         if (!res) {
900           GstClockTime duration;
901           if (gst_qtdemux_get_duration (qtdemux, &duration) && duration > 0) {
902             gst_query_set_duration (query, GST_FORMAT_TIME, duration);
903             res = TRUE;
904           }
905         }
906       }
907       break;
908     }
909     case GST_QUERY_CONVERT:{
910       GstFormat src_fmt, dest_fmt;
911       gint64 src_value, dest_value = 0;
912
913       gst_query_parse_convert (query, &src_fmt, &src_value, &dest_fmt, NULL);
914
915       res = gst_qtdemux_src_convert (qtdemux, pad,
916           src_fmt, src_value, dest_fmt, &dest_value);
917       if (res)
918         gst_query_set_convert (query, src_fmt, src_value, dest_fmt, dest_value);
919
920       break;
921     }
922     case GST_QUERY_FORMATS:
923       gst_query_set_formats (query, 2, GST_FORMAT_TIME, GST_FORMAT_BYTES);
924       res = TRUE;
925       break;
926     case GST_QUERY_SEEKING:{
927       GstFormat fmt;
928       gboolean seekable;
929
930       /* try upstream first */
931       res = gst_pad_query_default (pad, parent, query);
932
933       if (!res) {
934         gst_query_parse_seeking (query, &fmt, NULL, NULL, NULL);
935         if (fmt == GST_FORMAT_TIME) {
936           GstClockTime duration;
937
938           gst_qtdemux_get_duration (qtdemux, &duration);
939           seekable = TRUE;
940           if (!qtdemux->pullbased) {
941             GstQuery *q;
942
943             /* we might be able with help from upstream */
944             seekable = FALSE;
945             q = gst_query_new_seeking (GST_FORMAT_BYTES);
946             if (gst_pad_peer_query (qtdemux->sinkpad, q)) {
947               gst_query_parse_seeking (q, &fmt, &seekable, NULL, NULL);
948               GST_LOG_OBJECT (qtdemux, "upstream BYTE seekable %d", seekable);
949             }
950             gst_query_unref (q);
951           }
952           gst_query_set_seeking (query, GST_FORMAT_TIME, seekable, 0, duration);
953           res = TRUE;
954         }
955       }
956       break;
957     }
958     case GST_QUERY_SEGMENT:
959     {
960       GstFormat format;
961       gint64 start, stop;
962
963       format = qtdemux->segment.format;
964
965       start =
966           gst_segment_to_stream_time (&qtdemux->segment, format,
967           qtdemux->segment.start);
968       if ((stop = qtdemux->segment.stop) == -1)
969         stop = qtdemux->segment.duration;
970       else
971         stop = gst_segment_to_stream_time (&qtdemux->segment, format, stop);
972
973       gst_query_set_segment (query, qtdemux->segment.rate, format, start, stop);
974       res = TRUE;
975       break;
976     }
977     default:
978       res = gst_pad_query_default (pad, parent, query);
979       break;
980   }
981
982   return res;
983 }
984
985 static void
986 gst_qtdemux_push_tags (GstQTDemux * qtdemux, QtDemuxStream * stream)
987 {
988   if (G_LIKELY (stream->pad)) {
989     GST_DEBUG_OBJECT (qtdemux, "Checking pad %s:%s for tags",
990         GST_DEBUG_PAD_NAME (stream->pad));
991
992     if (!gst_tag_list_is_empty (stream->stream_tags)) {
993       GST_DEBUG_OBJECT (qtdemux, "Sending tags %" GST_PTR_FORMAT,
994           stream->stream_tags);
995       gst_pad_push_event (stream->pad,
996           gst_event_new_tag (gst_tag_list_ref (stream->stream_tags)));
997     }
998
999     if (G_UNLIKELY (stream->send_global_tags)) {
1000       GST_DEBUG_OBJECT (qtdemux, "Sending global tags %" GST_PTR_FORMAT,
1001           qtdemux->tag_list);
1002       gst_pad_push_event (stream->pad,
1003           gst_event_new_tag (gst_tag_list_ref (qtdemux->tag_list)));
1004       stream->send_global_tags = FALSE;
1005     }
1006   }
1007 }
1008
1009 /* push event on all source pads; takes ownership of the event */
1010 static void
1011 gst_qtdemux_push_event (GstQTDemux * qtdemux, GstEvent * event)
1012 {
1013   gboolean has_valid_stream = FALSE;
1014   GstEventType etype = GST_EVENT_TYPE (event);
1015   guint i;
1016
1017   GST_DEBUG_OBJECT (qtdemux, "pushing %s event on all source pads",
1018       GST_EVENT_TYPE_NAME (event));
1019
1020   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
1021     GstPad *pad;
1022     QtDemuxStream *stream = QTDEMUX_NTH_STREAM (qtdemux, i);
1023     GST_DEBUG_OBJECT (qtdemux, "pushing on track-id %u", stream->track_id);
1024
1025     if ((pad = stream->pad)) {
1026       has_valid_stream = TRUE;
1027
1028       if (etype == GST_EVENT_EOS) {
1029         /* let's not send twice */
1030         if (stream->sent_eos)
1031           continue;
1032         stream->sent_eos = TRUE;
1033       }
1034
1035       gst_pad_push_event (pad, gst_event_ref (event));
1036     }
1037   }
1038
1039   gst_event_unref (event);
1040
1041   /* if it is EOS and there are no pads, post an error */
1042   if (!has_valid_stream && etype == GST_EVENT_EOS) {
1043     gst_qtdemux_post_no_playable_stream_error (qtdemux);
1044   }
1045 }
1046
1047 typedef struct
1048 {
1049   guint64 media_time;
1050 } FindData;
1051
1052 static gint
1053 find_func (QtDemuxSample * s1, gint64 * media_time, gpointer user_data)
1054 {
1055   if ((gint64) s1->timestamp > *media_time)
1056     return 1;
1057   if ((gint64) s1->timestamp == *media_time)
1058     return 0;
1059
1060   return -1;
1061 }
1062
1063 /* find the index of the sample that includes the data for @media_time using a
1064  * binary search.  Only to be called in optimized cases of linear search below.
1065  *
1066  * Returns the index of the sample with the corresponding *DTS*.
1067  */
1068 static guint32
1069 gst_qtdemux_find_index (GstQTDemux * qtdemux, QtDemuxStream * str,
1070     guint64 media_time)
1071 {
1072   QtDemuxSample *result;
1073   guint32 index;
1074
1075   /* convert media_time to mov format */
1076   media_time =
1077       gst_util_uint64_scale_ceil (media_time, str->timescale, GST_SECOND);
1078
1079   result = gst_util_array_binary_search (str->samples, str->stbl_index + 1,
1080       sizeof (QtDemuxSample), (GCompareDataFunc) find_func,
1081       GST_SEARCH_MODE_BEFORE, &media_time, NULL);
1082
1083   if (G_LIKELY (result))
1084     index = result - str->samples;
1085   else
1086     index = 0;
1087
1088   return index;
1089 }
1090
1091
1092
1093 /* find the index of the sample that includes the data for @media_offset using a
1094  * linear search
1095  *
1096  * Returns the index of the sample.
1097  */
1098 static guint32
1099 gst_qtdemux_find_index_for_given_media_offset_linear (GstQTDemux * qtdemux,
1100     QtDemuxStream * str, gint64 media_offset)
1101 {
1102   QtDemuxSample *result = str->samples;
1103   guint32 index = 0;
1104
1105   if (result == NULL || str->n_samples == 0)
1106     return -1;
1107
1108   if (media_offset == result->offset)
1109     return index;
1110
1111   result++;
1112   while (index < str->n_samples - 1) {
1113     if (!qtdemux_parse_samples (qtdemux, str, index + 1))
1114       goto parse_failed;
1115
1116     if (media_offset < result->offset)
1117       break;
1118
1119     index++;
1120     result++;
1121   }
1122   return index;
1123
1124   /* ERRORS */
1125 parse_failed:
1126   {
1127     GST_LOG_OBJECT (qtdemux, "Parsing of index %u failed!", index + 1);
1128     return -1;
1129   }
1130 }
1131
1132 /* find the index of the sample that includes the data for @media_time using a
1133  * linear search, and keeping in mind that not all samples may have been parsed
1134  * yet.  If possible, it will delegate to binary search.
1135  *
1136  * Returns the index of the sample.
1137  */
1138 static guint32
1139 gst_qtdemux_find_index_linear (GstQTDemux * qtdemux, QtDemuxStream * str,
1140     GstClockTime media_time)
1141 {
1142   guint32 index = 0;
1143   guint64 mov_time;
1144   QtDemuxSample *sample;
1145
1146   /* convert media_time to mov format */
1147   mov_time =
1148       gst_util_uint64_scale_ceil (media_time, str->timescale, GST_SECOND);
1149
1150   sample = str->samples;
1151   if (mov_time == sample->timestamp + sample->pts_offset)
1152     return index;
1153
1154   /* use faster search if requested time in already parsed range */
1155   sample = str->samples + str->stbl_index;
1156   if (str->stbl_index >= 0 && mov_time <= sample->timestamp) {
1157     index = gst_qtdemux_find_index (qtdemux, str, media_time);
1158     sample = str->samples + index;
1159   } else {
1160     while (index < str->n_samples - 1) {
1161       if (!qtdemux_parse_samples (qtdemux, str, index + 1))
1162         goto parse_failed;
1163
1164       sample = str->samples + index + 1;
1165       if (mov_time < sample->timestamp) {
1166         sample = str->samples + index;
1167         break;
1168       }
1169
1170       index++;
1171     }
1172   }
1173
1174   /* sample->timestamp is now <= media_time, need to find the corresponding
1175    * PTS now by looking backwards */
1176   while (index > 0 && sample->timestamp + sample->pts_offset > mov_time) {
1177     index--;
1178     sample = str->samples + index;
1179   }
1180
1181   return index;
1182
1183   /* ERRORS */
1184 parse_failed:
1185   {
1186     GST_LOG_OBJECT (qtdemux, "Parsing of index %u failed!", index + 1);
1187     return -1;
1188   }
1189 }
1190
1191 /* find the index of the keyframe needed to decode the sample at @index
1192  * of stream @str, or of a subsequent keyframe (depending on @next)
1193  *
1194  * Returns the index of the keyframe.
1195  */
1196 static guint32
1197 gst_qtdemux_find_keyframe (GstQTDemux * qtdemux, QtDemuxStream * str,
1198     guint32 index, gboolean next)
1199 {
1200   guint32 new_index = index;
1201
1202   if (index >= str->n_samples) {
1203     new_index = str->n_samples;
1204     goto beach;
1205   }
1206
1207   /* all keyframes, return index */
1208   if (str->all_keyframe) {
1209     new_index = index;
1210     goto beach;
1211   }
1212
1213   /* else search until we have a keyframe */
1214   while (new_index < str->n_samples) {
1215     if (next && !qtdemux_parse_samples (qtdemux, str, new_index))
1216       goto parse_failed;
1217
1218     if (str->samples[new_index].keyframe)
1219       break;
1220
1221     if (new_index == 0)
1222       break;
1223
1224     if (next)
1225       new_index++;
1226     else
1227       new_index--;
1228   }
1229
1230   if (new_index == str->n_samples) {
1231     GST_DEBUG_OBJECT (qtdemux, "no next keyframe");
1232     new_index = -1;
1233   }
1234
1235 beach:
1236   GST_DEBUG_OBJECT (qtdemux, "searching for keyframe index %s index %u "
1237       "gave %u", next ? "after" : "before", index, new_index);
1238
1239   return new_index;
1240
1241   /* ERRORS */
1242 parse_failed:
1243   {
1244     GST_LOG_OBJECT (qtdemux, "Parsing of index %u failed!", new_index);
1245     return -1;
1246   }
1247 }
1248
1249 /* find the segment for @time_position for @stream
1250  *
1251  * Returns the index of the segment containing @time_position.
1252  * Returns the last segment and sets the @eos variable to TRUE
1253  * if the time is beyond the end. @eos may be NULL
1254  */
1255 static guint32
1256 gst_qtdemux_find_segment (GstQTDemux * qtdemux, QtDemuxStream * stream,
1257     GstClockTime time_position)
1258 {
1259   gint i;
1260   guint32 seg_idx;
1261
1262   GST_LOG_OBJECT (stream->pad, "finding segment for %" GST_TIME_FORMAT,
1263       GST_TIME_ARGS (time_position));
1264
1265   seg_idx = -1;
1266   for (i = 0; i < stream->n_segments; i++) {
1267     QtDemuxSegment *segment = &stream->segments[i];
1268
1269     GST_LOG_OBJECT (stream->pad,
1270         "looking at segment %" GST_TIME_FORMAT "-%" GST_TIME_FORMAT,
1271         GST_TIME_ARGS (segment->time), GST_TIME_ARGS (segment->stop_time));
1272
1273     /* For the last segment we include stop_time in the last segment */
1274     if (i < stream->n_segments - 1) {
1275       if (segment->time <= time_position && time_position < segment->stop_time) {
1276         GST_LOG_OBJECT (stream->pad, "segment %d matches", i);
1277         seg_idx = i;
1278         break;
1279       }
1280     } else {
1281       /* Last segment always matches */
1282       seg_idx = i;
1283       break;
1284     }
1285   }
1286   return seg_idx;
1287 }
1288
1289 /* move the stream @str to the sample position @index.
1290  *
1291  * Updates @str->sample_index and marks discontinuity if needed.
1292  */
1293 static void
1294 gst_qtdemux_move_stream (GstQTDemux * qtdemux, QtDemuxStream * str,
1295     guint32 index)
1296 {
1297   /* no change needed */
1298   if (index == str->sample_index)
1299     return;
1300
1301   GST_DEBUG_OBJECT (qtdemux, "moving to sample %u of %u", index,
1302       str->n_samples);
1303
1304   /* position changed, we have a discont */
1305   str->sample_index = index;
1306   str->offset_in_sample = 0;
1307   /* Each time we move in the stream we store the position where we are
1308    * starting from */
1309   str->from_sample = index;
1310   str->discont = TRUE;
1311 }
1312
1313 static void
1314 gst_qtdemux_adjust_seek (GstQTDemux * qtdemux, gint64 desired_time,
1315     gboolean use_sparse, gboolean next, gint64 * key_time, gint64 * key_offset)
1316 {
1317   guint64 min_offset;
1318   gint64 min_byte_offset = -1;
1319   guint i;
1320
1321   min_offset = desired_time;
1322
1323   /* for each stream, find the index of the sample in the segment
1324    * and move back to the previous keyframe. */
1325   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
1326     QtDemuxStream *str;
1327     guint32 index, kindex;
1328     guint32 seg_idx;
1329     GstClockTime media_start;
1330     GstClockTime media_time;
1331     GstClockTime seg_time;
1332     QtDemuxSegment *seg;
1333     gboolean empty_segment = FALSE;
1334
1335     str = QTDEMUX_NTH_STREAM (qtdemux, i);
1336
1337     if (CUR_STREAM (str)->sparse && !use_sparse)
1338       continue;
1339
1340     seg_idx = gst_qtdemux_find_segment (qtdemux, str, desired_time);
1341     GST_DEBUG_OBJECT (qtdemux, "align segment %d", seg_idx);
1342
1343     /* get segment and time in the segment */
1344     seg = &str->segments[seg_idx];
1345     seg_time = (desired_time - seg->time) * seg->rate;
1346
1347     while (QTSEGMENT_IS_EMPTY (seg)) {
1348       seg_time = 0;
1349       empty_segment = TRUE;
1350       GST_DEBUG_OBJECT (str->pad, "Segment %d is empty, moving to next one",
1351           seg_idx);
1352       seg_idx++;
1353       if (seg_idx == str->n_segments)
1354         break;
1355       seg = &str->segments[seg_idx];
1356     }
1357
1358     if (seg_idx == str->n_segments) {
1359       /* FIXME track shouldn't have the last segment as empty, but if it
1360        * happens we better handle it */
1361       continue;
1362     }
1363
1364     /* get the media time in the segment */
1365     media_start = seg->media_start + seg_time;
1366
1367     /* get the index of the sample with media time */
1368     index = gst_qtdemux_find_index_linear (qtdemux, str, media_start);
1369     GST_DEBUG_OBJECT (qtdemux, "sample for %" GST_TIME_FORMAT " at %u"
1370         " at offset %" G_GUINT64_FORMAT " (empty segment: %d)",
1371         GST_TIME_ARGS (media_start), index, str->samples[index].offset,
1372         empty_segment);
1373
1374     /* shift to next frame if we are looking for next keyframe */
1375     if (next && QTSAMPLE_PTS_NO_CSLG (str, &str->samples[index]) < media_start
1376         && index < str->stbl_index)
1377       index++;
1378
1379     if (!empty_segment) {
1380       /* find previous keyframe */
1381       kindex = gst_qtdemux_find_keyframe (qtdemux, str, index, next);
1382
1383       /* we will settle for one before if none found after */
1384       if (next && kindex == -1)
1385         kindex = gst_qtdemux_find_keyframe (qtdemux, str, index, FALSE);
1386
1387       /* if the keyframe is at a different position, we need to update the
1388        * requested seek time */
1389       if (index != kindex) {
1390         index = kindex;
1391
1392         /* get timestamp of keyframe */
1393         media_time = QTSAMPLE_PTS_NO_CSLG (str, &str->samples[kindex]);
1394         GST_DEBUG_OBJECT (qtdemux,
1395             "keyframe at %u with time %" GST_TIME_FORMAT " at offset %"
1396             G_GUINT64_FORMAT, kindex, GST_TIME_ARGS (media_time),
1397             str->samples[kindex].offset);
1398
1399         /* keyframes in the segment get a chance to change the
1400          * desired_offset. keyframes out of the segment are
1401          * ignored. */
1402         if (media_time >= seg->media_start) {
1403           GstClockTime seg_time;
1404
1405           /* this keyframe is inside the segment, convert back to
1406            * segment time */
1407           seg_time = (media_time - seg->media_start) + seg->time;
1408           if ((!next && (seg_time < min_offset)) ||
1409               (next && (seg_time > min_offset)))
1410             min_offset = seg_time;
1411         }
1412       }
1413     }
1414
1415     if (min_byte_offset < 0 || str->samples[index].offset < min_byte_offset)
1416       min_byte_offset = str->samples[index].offset;
1417   }
1418
1419   if (key_time)
1420     *key_time = min_offset;
1421   if (key_offset)
1422     *key_offset = min_byte_offset;
1423 }
1424
1425 static gboolean
1426 gst_qtdemux_convert_seek (GstPad * pad, GstFormat * format,
1427     GstSeekType cur_type, gint64 * cur, GstSeekType stop_type, gint64 * stop)
1428 {
1429   gboolean res;
1430
1431   g_return_val_if_fail (format != NULL, FALSE);
1432   g_return_val_if_fail (cur != NULL, FALSE);
1433   g_return_val_if_fail (stop != NULL, FALSE);
1434
1435   if (*format == GST_FORMAT_TIME)
1436     return TRUE;
1437
1438   res = TRUE;
1439   if (cur_type != GST_SEEK_TYPE_NONE)
1440     res = gst_pad_query_convert (pad, *format, *cur, GST_FORMAT_TIME, cur);
1441   if (res && stop_type != GST_SEEK_TYPE_NONE)
1442     res = gst_pad_query_convert (pad, *format, *stop, GST_FORMAT_TIME, stop);
1443
1444   if (res)
1445     *format = GST_FORMAT_TIME;
1446
1447   return res;
1448 }
1449
1450 /* perform seek in push based mode:
1451    find BYTE position to move to based on time and delegate to upstream
1452 */
1453 static gboolean
1454 gst_qtdemux_do_push_seek (GstQTDemux * qtdemux, GstPad * pad, GstEvent * event)
1455 {
1456   gdouble rate;
1457   GstFormat format;
1458   GstSeekFlags flags;
1459   GstSeekType cur_type, stop_type;
1460   gint64 cur, stop, key_cur;
1461   gboolean res;
1462   gint64 byte_cur;
1463   gint64 original_stop;
1464   guint32 seqnum;
1465
1466   GST_DEBUG_OBJECT (qtdemux, "doing push-based seek");
1467
1468   gst_event_parse_seek (event, &rate, &format, &flags,
1469       &cur_type, &cur, &stop_type, &stop);
1470   seqnum = gst_event_get_seqnum (event);
1471
1472   /* only forward streaming and seeking is possible */
1473   if (rate <= 0)
1474     goto unsupported_seek;
1475
1476   /* convert to TIME if needed and possible */
1477   if (!gst_qtdemux_convert_seek (pad, &format, cur_type, &cur,
1478           stop_type, &stop))
1479     goto no_format;
1480
1481   /* Upstream seek in bytes will have undefined stop, but qtdemux stores
1482    * the original stop position to use when upstream pushes the new segment
1483    * for this seek */
1484   original_stop = stop;
1485   stop = -1;
1486
1487   /* find reasonable corresponding BYTE position,
1488    * also try to mind about keyframes, since we can not go back a bit for them
1489    * later on */
1490   /* determining @next here based on SNAP_BEFORE/SNAP_AFTER should
1491    * mostly just work, but let's not yet boldly go there  ... */
1492   gst_qtdemux_adjust_seek (qtdemux, cur, FALSE, FALSE, &key_cur, &byte_cur);
1493
1494   if (byte_cur == -1)
1495     goto abort_seek;
1496
1497   GST_DEBUG_OBJECT (qtdemux, "Pushing BYTE seek rate %g, "
1498       "start %" G_GINT64_FORMAT ", stop %" G_GINT64_FORMAT, rate, byte_cur,
1499       stop);
1500
1501   GST_OBJECT_LOCK (qtdemux);
1502   qtdemux->seek_offset = byte_cur;
1503   if (!(flags & GST_SEEK_FLAG_KEY_UNIT)) {
1504     qtdemux->push_seek_start = cur;
1505   } else {
1506     qtdemux->push_seek_start = key_cur;
1507   }
1508
1509   if (stop_type == GST_SEEK_TYPE_NONE) {
1510     qtdemux->push_seek_stop = qtdemux->segment.stop;
1511   } else {
1512     qtdemux->push_seek_stop = original_stop;
1513   }
1514   GST_OBJECT_UNLOCK (qtdemux);
1515
1516   qtdemux->segment_seqnum = seqnum;
1517   /* BYTE seek event */
1518   event = gst_event_new_seek (rate, GST_FORMAT_BYTES, flags, cur_type, byte_cur,
1519       stop_type, stop);
1520   gst_event_set_seqnum (event, seqnum);
1521   res = gst_pad_push_event (qtdemux->sinkpad, event);
1522
1523   return res;
1524
1525   /* ERRORS */
1526 abort_seek:
1527   {
1528     GST_DEBUG_OBJECT (qtdemux, "could not determine byte position to seek to, "
1529         "seek aborted.");
1530     return FALSE;
1531   }
1532 unsupported_seek:
1533   {
1534     GST_DEBUG_OBJECT (qtdemux, "unsupported seek, seek aborted.");
1535     return FALSE;
1536   }
1537 no_format:
1538   {
1539     GST_DEBUG_OBJECT (qtdemux, "unsupported format given, seek aborted.");
1540     return FALSE;
1541   }
1542 }
1543
1544 /* perform the seek.
1545  *
1546  * We set all segment_indexes in the streams to unknown and
1547  * adjust the time_position to the desired position. this is enough
1548  * to trigger a segment switch in the streaming thread to start
1549  * streaming from the desired position.
1550  *
1551  * Keyframe seeking is a little more complicated when dealing with
1552  * segments. Ideally we want to move to the previous keyframe in
1553  * the segment but there might not be a keyframe in the segment. In
1554  * fact, none of the segments could contain a keyframe. We take a
1555  * practical approach: seek to the previous keyframe in the segment,
1556  * if there is none, seek to the beginning of the segment.
1557  *
1558  * Called with STREAM_LOCK
1559  */
1560 static gboolean
1561 gst_qtdemux_perform_seek (GstQTDemux * qtdemux, GstSegment * segment,
1562     guint32 seqnum, GstSeekFlags flags)
1563 {
1564   gint64 desired_offset;
1565   guint i;
1566
1567   desired_offset = segment->position;
1568
1569   GST_DEBUG_OBJECT (qtdemux, "seeking to %" GST_TIME_FORMAT,
1570       GST_TIME_ARGS (desired_offset));
1571
1572   /* may not have enough fragmented info to do this adjustment,
1573    * and we can't scan (and probably should not) at this time with
1574    * possibly flushing upstream */
1575   if ((flags & GST_SEEK_FLAG_KEY_UNIT) && !qtdemux->fragmented) {
1576     gint64 min_offset;
1577     gboolean next, before, after;
1578
1579     before = ! !(flags & GST_SEEK_FLAG_SNAP_BEFORE);
1580     after = ! !(flags & GST_SEEK_FLAG_SNAP_AFTER);
1581     next = after && !before;
1582     if (segment->rate < 0)
1583       next = !next;
1584
1585     gst_qtdemux_adjust_seek (qtdemux, desired_offset, TRUE, next, &min_offset,
1586         NULL);
1587     GST_DEBUG_OBJECT (qtdemux, "keyframe seek, align to %"
1588         GST_TIME_FORMAT, GST_TIME_ARGS (min_offset));
1589     desired_offset = min_offset;
1590   }
1591
1592   /* and set all streams to the final position */
1593   gst_flow_combiner_reset (qtdemux->flowcombiner);
1594   qtdemux->segment_seqnum = seqnum;
1595   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
1596     QtDemuxStream *stream = QTDEMUX_NTH_STREAM (qtdemux, i);
1597
1598     stream->time_position = desired_offset;
1599     stream->accumulated_base = 0;
1600     stream->sample_index = -1;
1601     stream->offset_in_sample = 0;
1602     stream->segment_index = -1;
1603     stream->sent_eos = FALSE;
1604
1605     if (segment->flags & GST_SEEK_FLAG_FLUSH)
1606       gst_segment_init (&stream->segment, GST_FORMAT_TIME);
1607   }
1608   segment->position = desired_offset;
1609   segment->time = desired_offset;
1610   if (segment->rate >= 0) {
1611     segment->start = desired_offset;
1612
1613     /* we stop at the end */
1614     if (segment->stop == -1)
1615       segment->stop = segment->duration;
1616   } else {
1617     segment->stop = desired_offset;
1618   }
1619
1620   if (qtdemux->fragmented)
1621     qtdemux->fragmented_seek_pending = TRUE;
1622
1623   return TRUE;
1624 }
1625
1626 /* do a seek in pull based mode */
1627 static gboolean
1628 gst_qtdemux_do_seek (GstQTDemux * qtdemux, GstPad * pad, GstEvent * event)
1629 {
1630   gdouble rate;
1631   GstFormat format;
1632   GstSeekFlags flags;
1633   GstSeekType cur_type, stop_type;
1634   gint64 cur, stop;
1635   gboolean flush;
1636   gboolean update;
1637   GstSegment seeksegment;
1638   guint32 seqnum = GST_SEQNUM_INVALID;
1639   GstEvent *flush_event;
1640   gboolean ret;
1641
1642   if (event) {
1643     GST_DEBUG_OBJECT (qtdemux, "doing seek with event");
1644
1645     gst_event_parse_seek (event, &rate, &format, &flags,
1646         &cur_type, &cur, &stop_type, &stop);
1647     seqnum = gst_event_get_seqnum (event);
1648
1649     /* we have to have a format as the segment format. Try to convert
1650      * if not. */
1651     if (!gst_qtdemux_convert_seek (pad, &format, cur_type, &cur,
1652             stop_type, &stop))
1653       goto no_format;
1654
1655     GST_DEBUG_OBJECT (qtdemux, "seek format %s", gst_format_get_name (format));
1656   } else {
1657     GST_DEBUG_OBJECT (qtdemux, "doing seek without event");
1658     flags = 0;
1659   }
1660
1661   flush = flags & GST_SEEK_FLAG_FLUSH;
1662
1663   /* stop streaming, either by flushing or by pausing the task */
1664   if (flush) {
1665     flush_event = gst_event_new_flush_start ();
1666     if (seqnum != GST_SEQNUM_INVALID)
1667       gst_event_set_seqnum (flush_event, seqnum);
1668     /* unlock upstream pull_range */
1669     gst_pad_push_event (qtdemux->sinkpad, gst_event_ref (flush_event));
1670     /* make sure out loop function exits */
1671     gst_qtdemux_push_event (qtdemux, flush_event);
1672   } else {
1673     /* non flushing seek, pause the task */
1674     gst_pad_pause_task (qtdemux->sinkpad);
1675   }
1676
1677   /* wait for streaming to finish */
1678   GST_PAD_STREAM_LOCK (qtdemux->sinkpad);
1679
1680   /* copy segment, we need this because we still need the old
1681    * segment when we close the current segment. */
1682   memcpy (&seeksegment, &qtdemux->segment, sizeof (GstSegment));
1683
1684   if (event) {
1685     /* configure the segment with the seek variables */
1686     GST_DEBUG_OBJECT (qtdemux, "configuring seek");
1687     if (!gst_segment_do_seek (&seeksegment, rate, format, flags,
1688             cur_type, cur, stop_type, stop, &update)) {
1689       ret = FALSE;
1690       GST_ERROR_OBJECT (qtdemux, "inconsistent seek values, doing nothing");
1691     } else {
1692       /* now do the seek */
1693       ret = gst_qtdemux_perform_seek (qtdemux, &seeksegment, seqnum, flags);
1694     }
1695   } else {
1696     /* now do the seek */
1697     ret = gst_qtdemux_perform_seek (qtdemux, &seeksegment, seqnum, flags);
1698   }
1699
1700   /* prepare for streaming again */
1701   if (flush) {
1702     flush_event = gst_event_new_flush_stop (TRUE);
1703     if (seqnum != GST_SEQNUM_INVALID)
1704       gst_event_set_seqnum (flush_event, seqnum);
1705
1706     gst_pad_push_event (qtdemux->sinkpad, gst_event_ref (flush_event));
1707     gst_qtdemux_push_event (qtdemux, flush_event);
1708   }
1709
1710   /* commit the new segment */
1711   memcpy (&qtdemux->segment, &seeksegment, sizeof (GstSegment));
1712
1713   if (qtdemux->segment.flags & GST_SEEK_FLAG_SEGMENT) {
1714     GstMessage *msg = gst_message_new_segment_start (GST_OBJECT_CAST (qtdemux),
1715         qtdemux->segment.format, qtdemux->segment.position);
1716     if (seqnum != GST_SEQNUM_INVALID)
1717       gst_message_set_seqnum (msg, seqnum);
1718     gst_element_post_message (GST_ELEMENT_CAST (qtdemux), msg);
1719   }
1720
1721   /* restart streaming, NEWSEGMENT will be sent from the streaming thread. */
1722   gst_pad_start_task (qtdemux->sinkpad, (GstTaskFunction) gst_qtdemux_loop,
1723       qtdemux->sinkpad, NULL);
1724
1725   GST_PAD_STREAM_UNLOCK (qtdemux->sinkpad);
1726
1727   return ret;
1728
1729   /* ERRORS */
1730 no_format:
1731   {
1732     GST_DEBUG_OBJECT (qtdemux, "unsupported format given, seek aborted.");
1733     return FALSE;
1734   }
1735 }
1736
1737 static gboolean
1738 qtdemux_ensure_index (GstQTDemux * qtdemux)
1739 {
1740   guint i;
1741
1742   GST_DEBUG_OBJECT (qtdemux, "collecting all metadata for all streams");
1743
1744   /* Build complete index */
1745   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
1746     QtDemuxStream *stream = QTDEMUX_NTH_STREAM (qtdemux, i);
1747
1748     if (!qtdemux_parse_samples (qtdemux, stream, stream->n_samples - 1)) {
1749       GST_LOG_OBJECT (qtdemux,
1750           "Building complete index of track-id %u for seeking failed!",
1751           stream->track_id);
1752       return FALSE;
1753     }
1754   }
1755
1756   return TRUE;
1757 }
1758
1759 static gboolean
1760 gst_qtdemux_handle_src_event (GstPad * pad, GstObject * parent,
1761     GstEvent * event)
1762 {
1763   gboolean res = TRUE;
1764   GstQTDemux *qtdemux = GST_QTDEMUX (parent);
1765
1766   switch (GST_EVENT_TYPE (event)) {
1767     case GST_EVENT_SEEK:
1768     {
1769 #ifndef GST_DISABLE_GST_DEBUG
1770       GstClockTime ts = gst_util_get_timestamp ();
1771 #endif
1772       guint32 seqnum = gst_event_get_seqnum (event);
1773
1774       qtdemux->received_seek = TRUE;
1775
1776       if (seqnum == qtdemux->segment_seqnum) {
1777         GST_LOG_OBJECT (pad,
1778             "Drop duplicated SEEK event seqnum %" G_GUINT32_FORMAT, seqnum);
1779         gst_event_unref (event);
1780         return TRUE;
1781       }
1782
1783       if (qtdemux->upstream_format_is_time && qtdemux->fragmented) {
1784         /* seek should be handled by upstream, we might need to re-download fragments */
1785         GST_DEBUG_OBJECT (qtdemux,
1786             "let upstream handle seek for fragmented playback");
1787         goto upstream;
1788       }
1789
1790       /* Build complete index for seeking;
1791        * if not a fragmented file at least */
1792       if (!qtdemux->fragmented)
1793         if (!qtdemux_ensure_index (qtdemux))
1794           goto index_failed;
1795 #ifndef GST_DISABLE_GST_DEBUG
1796       ts = gst_util_get_timestamp () - ts;
1797       GST_INFO_OBJECT (qtdemux,
1798           "Time taken to parse index %" GST_TIME_FORMAT, GST_TIME_ARGS (ts));
1799 #endif
1800     }
1801       if (qtdemux->pullbased) {
1802         res = gst_qtdemux_do_seek (qtdemux, pad, event);
1803       } else if (gst_pad_push_event (qtdemux->sinkpad, gst_event_ref (event))) {
1804         GST_DEBUG_OBJECT (qtdemux, "Upstream successfully seeked");
1805         res = TRUE;
1806       } else if (qtdemux->state == QTDEMUX_STATE_MOVIE
1807           && QTDEMUX_N_STREAMS (qtdemux)
1808           && !qtdemux->fragmented) {
1809         res = gst_qtdemux_do_push_seek (qtdemux, pad, event);
1810       } else {
1811         GST_DEBUG_OBJECT (qtdemux,
1812             "ignoring seek in push mode in current state");
1813         res = FALSE;
1814       }
1815       gst_event_unref (event);
1816       break;
1817     default:
1818     upstream:
1819       res = gst_pad_event_default (pad, parent, event);
1820       break;
1821   }
1822
1823 done:
1824   return res;
1825
1826   /* ERRORS */
1827 index_failed:
1828   {
1829     GST_ERROR_OBJECT (qtdemux, "Index failed");
1830     gst_event_unref (event);
1831     res = FALSE;
1832     goto done;
1833   }
1834 }
1835
1836 /* Find, for each track, the first sample in coding order that has a file offset >= @byte_pos.
1837  *
1838  * If @fw is false, the coding order is explored backwards.
1839  *
1840  * If @set is true, each stream will be moved to its matched sample, or EOS if no matching
1841  * sample is found for that track.
1842  *
1843  * The stream and sample index of the sample with the minimum offset in the direction explored
1844  * (see @fw) is returned in the output parameters @_stream and @_index respectively.
1845  *
1846  * @_time is set to the QTSAMPLE_PTS of the matched sample with the minimum QTSAMPLE_PTS in the
1847  * direction explored, which may not always match the QTSAMPLE_PTS of the sample returned in
1848  * @_stream and @_index. */
1849 static void
1850 gst_qtdemux_find_sample (GstQTDemux * qtdemux, gint64 byte_pos, gboolean fw,
1851     gboolean set, QtDemuxStream ** _stream, gint * _index, gint64 * _time)
1852 {
1853   gint i, index;
1854   gint64 time, min_time;
1855   QtDemuxStream *stream;
1856   gint iter;
1857
1858   min_time = -1;
1859   stream = NULL;
1860   index = -1;
1861
1862   for (iter = 0; iter < QTDEMUX_N_STREAMS (qtdemux); iter++) {
1863     QtDemuxStream *str;
1864     gint inc;
1865     gboolean set_sample;
1866
1867     str = QTDEMUX_NTH_STREAM (qtdemux, iter);
1868     set_sample = !set;
1869
1870     if (fw) {
1871       i = 0;
1872       inc = 1;
1873     } else {
1874       i = str->n_samples - 1;
1875       inc = -1;
1876     }
1877
1878     for (; (i >= 0) && (i < str->n_samples); i += inc) {
1879       if (str->samples[i].size == 0)
1880         continue;
1881
1882       if (fw && (str->samples[i].offset < byte_pos))
1883         continue;
1884
1885       if (!fw && (str->samples[i].offset + str->samples[i].size > byte_pos))
1886         continue;
1887
1888       /* move stream to first available sample */
1889       if (set) {
1890         gst_qtdemux_move_stream (qtdemux, str, i);
1891         set_sample = TRUE;
1892       }
1893
1894       /* avoid index from sparse streams since they might be far away */
1895       if (!CUR_STREAM (str)->sparse) {
1896         /* determine min/max time */
1897         time = QTSAMPLE_PTS (str, &str->samples[i]);
1898         if (min_time == -1 || (!fw && time > min_time) ||
1899             (fw && time < min_time)) {
1900           min_time = time;
1901         }
1902
1903         /* determine stream with leading sample, to get its position */
1904         if (!stream ||
1905             (fw && (str->samples[i].offset < stream->samples[index].offset)) ||
1906             (!fw && (str->samples[i].offset > stream->samples[index].offset))) {
1907           stream = str;
1908           index = i;
1909         }
1910       }
1911       break;
1912     }
1913
1914     /* no sample for this stream, mark eos */
1915     if (!set_sample)
1916       gst_qtdemux_move_stream (qtdemux, str, str->n_samples);
1917   }
1918
1919   if (_time)
1920     *_time = min_time;
1921   if (_stream)
1922     *_stream = stream;
1923   if (_index)
1924     *_index = index;
1925 }
1926
1927 /* Copied from mpegtsbase code */
1928 /* FIXME: replace this function when we add new util function for stream-id creation */
1929 static gchar *
1930 _get_upstream_id (GstQTDemux * demux)
1931 {
1932   gchar *upstream_id = gst_pad_get_stream_id (demux->sinkpad);
1933
1934   if (!upstream_id) {
1935     /* Try to create one from the upstream URI, else use a randome number */
1936     GstQuery *query;
1937     gchar *uri = NULL;
1938
1939     /* Try to generate one from the URI query and
1940      * if it fails take a random number instead */
1941     query = gst_query_new_uri ();
1942     if (gst_element_query (GST_ELEMENT_CAST (demux), query)) {
1943       gst_query_parse_uri (query, &uri);
1944     }
1945
1946     if (uri) {
1947       GChecksum *cs;
1948
1949       /* And then generate an SHA256 sum of the URI */
1950       cs = g_checksum_new (G_CHECKSUM_SHA256);
1951       g_checksum_update (cs, (const guchar *) uri, strlen (uri));
1952       g_free (uri);
1953       upstream_id = g_strdup (g_checksum_get_string (cs));
1954       g_checksum_free (cs);
1955     } else {
1956       /* Just get some random number if the URI query fails */
1957       GST_FIXME_OBJECT (demux, "Creating random stream-id, consider "
1958           "implementing a deterministic way of creating a stream-id");
1959       upstream_id =
1960           g_strdup_printf ("%08x%08x%08x%08x", g_random_int (), g_random_int (),
1961           g_random_int (), g_random_int ());
1962     }
1963
1964     gst_query_unref (query);
1965   }
1966   return upstream_id;
1967 }
1968
1969 static QtDemuxStream *
1970 _create_stream (GstQTDemux * demux, guint32 track_id)
1971 {
1972   QtDemuxStream *stream;
1973   gchar *upstream_id;
1974
1975   stream = g_new0 (QtDemuxStream, 1);
1976   stream->demux = demux;
1977   stream->track_id = track_id;
1978   upstream_id = _get_upstream_id (demux);
1979   stream->stream_id = g_strdup_printf ("%s/%03u", upstream_id, track_id);
1980   g_free (upstream_id);
1981   /* new streams always need a discont */
1982   stream->discont = TRUE;
1983   /* we enable clipping for raw audio/video streams */
1984   stream->need_clip = FALSE;
1985   stream->need_process = FALSE;
1986   stream->segment_index = -1;
1987   stream->time_position = 0;
1988   stream->sample_index = -1;
1989   stream->offset_in_sample = 0;
1990   stream->new_stream = TRUE;
1991   stream->multiview_mode = GST_VIDEO_MULTIVIEW_MODE_NONE;
1992   stream->multiview_flags = GST_VIDEO_MULTIVIEW_FLAGS_NONE;
1993   stream->protected = FALSE;
1994   stream->protection_scheme_type = 0;
1995   stream->protection_scheme_version = 0;
1996   stream->protection_scheme_info = NULL;
1997   stream->n_samples_moof = 0;
1998   stream->duration_moof = 0;
1999   stream->duration_last_moof = 0;
2000   stream->alignment = 1;
2001   stream->stream_tags = gst_tag_list_new_empty ();
2002   gst_tag_list_set_scope (stream->stream_tags, GST_TAG_SCOPE_STREAM);
2003   g_queue_init (&stream->protection_scheme_event_queue);
2004   stream->ref_count = 1;
2005   return stream;
2006 }
2007
2008 static gboolean
2009 gst_qtdemux_setcaps (GstQTDemux * demux, GstCaps * caps)
2010 {
2011   GstStructure *structure;
2012   const gchar *variant;
2013   const GstCaps *mediacaps = NULL;
2014
2015   GST_DEBUG_OBJECT (demux, "Sink set caps: %" GST_PTR_FORMAT, caps);
2016
2017   structure = gst_caps_get_structure (caps, 0);
2018   variant = gst_structure_get_string (structure, "variant");
2019
2020   if (variant && strcmp (variant, "mss-fragmented") == 0) {
2021     QtDemuxStream *stream;
2022     const GValue *value;
2023
2024     demux->fragmented = TRUE;
2025     demux->mss_mode = TRUE;
2026
2027     if (QTDEMUX_N_STREAMS (demux) > 1) {
2028       /* can't do this, we can only renegotiate for another mss format */
2029       return FALSE;
2030     }
2031
2032     value = gst_structure_get_value (structure, "media-caps");
2033     /* create stream */
2034     if (value) {
2035       const GValue *timescale_v;
2036
2037       /* TODO update when stream changes during playback */
2038
2039       if (QTDEMUX_N_STREAMS (demux) == 0) {
2040         stream = _create_stream (demux, 1);
2041         g_ptr_array_add (demux->active_streams, stream);
2042         /* mss has no stsd/stsd entry, use id 0 as default */
2043         stream->stsd_entries_length = 1;
2044         stream->stsd_sample_description_id = stream->cur_stsd_entry_index = 0;
2045         stream->stsd_entries = g_new0 (QtDemuxStreamStsdEntry, 1);
2046       } else {
2047         stream = QTDEMUX_NTH_STREAM (demux, 0);
2048       }
2049
2050       timescale_v = gst_structure_get_value (structure, "timescale");
2051       if (timescale_v) {
2052         stream->timescale = g_value_get_uint64 (timescale_v);
2053       } else {
2054         /* default mss timescale */
2055         stream->timescale = 10000000;
2056       }
2057       demux->timescale = stream->timescale;
2058
2059       mediacaps = gst_value_get_caps (value);
2060       if (!CUR_STREAM (stream)->caps
2061           || !gst_caps_is_equal_fixed (mediacaps, CUR_STREAM (stream)->caps)) {
2062         GST_DEBUG_OBJECT (demux, "We have a new caps %" GST_PTR_FORMAT,
2063             mediacaps);
2064         stream->new_caps = TRUE;
2065       }
2066       gst_caps_replace (&CUR_STREAM (stream)->caps, (GstCaps *) mediacaps);
2067       structure = gst_caps_get_structure (mediacaps, 0);
2068       if (g_str_has_prefix (gst_structure_get_name (structure), "video")) {
2069         stream->subtype = FOURCC_vide;
2070
2071         gst_structure_get_int (structure, "width", &CUR_STREAM (stream)->width);
2072         gst_structure_get_int (structure, "height",
2073             &CUR_STREAM (stream)->height);
2074         gst_structure_get_fraction (structure, "framerate",
2075             &CUR_STREAM (stream)->fps_n, &CUR_STREAM (stream)->fps_d);
2076       } else if (g_str_has_prefix (gst_structure_get_name (structure), "audio")) {
2077         gint rate = 0;
2078         stream->subtype = FOURCC_soun;
2079         gst_structure_get_int (structure, "channels",
2080             &CUR_STREAM (stream)->n_channels);
2081         gst_structure_get_int (structure, "rate", &rate);
2082         CUR_STREAM (stream)->rate = rate;
2083       }
2084     }
2085     gst_caps_replace (&demux->media_caps, (GstCaps *) mediacaps);
2086   } else {
2087     demux->mss_mode = FALSE;
2088   }
2089
2090   return TRUE;
2091 }
2092
2093 static void
2094 gst_qtdemux_reset (GstQTDemux * qtdemux, gboolean hard)
2095 {
2096   gint i;
2097
2098   GST_DEBUG_OBJECT (qtdemux, "Resetting demux");
2099   gst_pad_stop_task (qtdemux->sinkpad);
2100
2101   if (hard || qtdemux->upstream_format_is_time) {
2102     qtdemux->state = QTDEMUX_STATE_INITIAL;
2103     qtdemux->neededbytes = 16;
2104     qtdemux->todrop = 0;
2105     qtdemux->pullbased = FALSE;
2106     qtdemux->posted_redirect = FALSE;
2107     qtdemux->first_mdat = -1;
2108     qtdemux->header_size = 0;
2109     qtdemux->mdatoffset = -1;
2110     qtdemux->restoredata_offset = -1;
2111     if (qtdemux->mdatbuffer)
2112       gst_buffer_unref (qtdemux->mdatbuffer);
2113     if (qtdemux->restoredata_buffer)
2114       gst_buffer_unref (qtdemux->restoredata_buffer);
2115     qtdemux->mdatbuffer = NULL;
2116     qtdemux->restoredata_buffer = NULL;
2117     qtdemux->mdatleft = 0;
2118     qtdemux->mdatsize = 0;
2119     if (qtdemux->comp_brands)
2120       gst_buffer_unref (qtdemux->comp_brands);
2121     qtdemux->comp_brands = NULL;
2122     qtdemux->last_moov_offset = -1;
2123     if (qtdemux->moov_node_compressed) {
2124       g_node_destroy (qtdemux->moov_node_compressed);
2125       if (qtdemux->moov_node)
2126         g_free (qtdemux->moov_node->data);
2127     }
2128     qtdemux->moov_node_compressed = NULL;
2129     if (qtdemux->moov_node)
2130       g_node_destroy (qtdemux->moov_node);
2131     qtdemux->moov_node = NULL;
2132     if (qtdemux->tag_list)
2133       gst_mini_object_unref (GST_MINI_OBJECT_CAST (qtdemux->tag_list));
2134     qtdemux->tag_list = gst_tag_list_new_empty ();
2135     gst_tag_list_set_scope (qtdemux->tag_list, GST_TAG_SCOPE_GLOBAL);
2136 #if 0
2137     if (qtdemux->element_index)
2138       gst_object_unref (qtdemux->element_index);
2139     qtdemux->element_index = NULL;
2140 #endif
2141     qtdemux->major_brand = 0;
2142     qtdemux->upstream_format_is_time = FALSE;
2143     qtdemux->upstream_seekable = FALSE;
2144     qtdemux->upstream_size = 0;
2145
2146     qtdemux->fragment_start = -1;
2147     qtdemux->fragment_start_offset = -1;
2148     qtdemux->duration = 0;
2149     qtdemux->moof_offset = 0;
2150     qtdemux->chapters_track_id = 0;
2151     qtdemux->have_group_id = FALSE;
2152     qtdemux->group_id = G_MAXUINT;
2153
2154     g_queue_foreach (&qtdemux->protection_event_queue, (GFunc) gst_event_unref,
2155         NULL);
2156     g_queue_clear (&qtdemux->protection_event_queue);
2157
2158     qtdemux->received_seek = FALSE;
2159     qtdemux->first_moof_already_parsed = FALSE;
2160   }
2161   qtdemux->offset = 0;
2162   gst_adapter_clear (qtdemux->adapter);
2163   gst_segment_init (&qtdemux->segment, GST_FORMAT_TIME);
2164   qtdemux->need_segment = TRUE;
2165
2166   if (hard) {
2167     qtdemux->segment_seqnum = GST_SEQNUM_INVALID;
2168     g_ptr_array_remove_range (qtdemux->active_streams,
2169         0, qtdemux->active_streams->len);
2170     g_ptr_array_remove_range (qtdemux->old_streams,
2171         0, qtdemux->old_streams->len);
2172     qtdemux->n_video_streams = 0;
2173     qtdemux->n_audio_streams = 0;
2174     qtdemux->n_sub_streams = 0;
2175     qtdemux->exposed = FALSE;
2176     qtdemux->fragmented = FALSE;
2177     qtdemux->mss_mode = FALSE;
2178     gst_caps_replace (&qtdemux->media_caps, NULL);
2179     qtdemux->timescale = 0;
2180     qtdemux->got_moov = FALSE;
2181     qtdemux->cenc_aux_info_offset = 0;
2182     qtdemux->cenc_aux_info_sizes = NULL;
2183     qtdemux->cenc_aux_sample_count = 0;
2184     if (qtdemux->protection_system_ids) {
2185       g_ptr_array_free (qtdemux->protection_system_ids, TRUE);
2186       qtdemux->protection_system_ids = NULL;
2187     }
2188     qtdemux->streams_aware = GST_OBJECT_PARENT (qtdemux)
2189         && GST_OBJECT_FLAG_IS_SET (GST_OBJECT_PARENT (qtdemux),
2190         GST_BIN_FLAG_STREAMS_AWARE);
2191
2192     if (qtdemux->preferred_protection_system_id) {
2193       g_free (qtdemux->preferred_protection_system_id);
2194       qtdemux->preferred_protection_system_id = NULL;
2195     }
2196   } else if (qtdemux->mss_mode) {
2197     gst_flow_combiner_reset (qtdemux->flowcombiner);
2198     g_ptr_array_foreach (qtdemux->active_streams,
2199         (GFunc) gst_qtdemux_stream_clear, NULL);
2200   } else {
2201     gst_flow_combiner_reset (qtdemux->flowcombiner);
2202     for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
2203       QtDemuxStream *stream = QTDEMUX_NTH_STREAM (qtdemux, i);
2204       stream->sent_eos = FALSE;
2205       stream->time_position = 0;
2206       stream->accumulated_base = 0;
2207     }
2208   }
2209 }
2210
2211
2212 /* Maps the @segment to the qt edts internal segments and pushes
2213  * the correspnding segment event.
2214  *
2215  * If it ends up being at a empty segment, a gap will be pushed and the next
2216  * edts segment will be activated in sequence.
2217  *
2218  * To be used in push-mode only */
2219 static void
2220 gst_qtdemux_map_and_push_segments (GstQTDemux * qtdemux, GstSegment * segment)
2221 {
2222   gint i, iter;
2223
2224   for (iter = 0; iter < QTDEMUX_N_STREAMS (qtdemux); iter++) {
2225     QtDemuxStream *stream = QTDEMUX_NTH_STREAM (qtdemux, iter);
2226
2227     stream->time_position = segment->start;
2228
2229     /* in push mode we should be guaranteed that we will have empty segments
2230      * at the beginning and then one segment after, other scenarios are not
2231      * supported and are discarded when parsing the edts */
2232     for (i = 0; i < stream->n_segments; i++) {
2233       if (stream->segments[i].stop_time > segment->start) {
2234         /* push the empty segment and move to the next one */
2235         gst_qtdemux_activate_segment (qtdemux, stream, i,
2236             stream->time_position);
2237         if (QTSEGMENT_IS_EMPTY (&stream->segments[i])) {
2238           gst_qtdemux_send_gap_for_segment (qtdemux, stream, i,
2239               stream->time_position);
2240
2241           /* accumulate previous segments */
2242           if (GST_CLOCK_TIME_IS_VALID (stream->segment.stop))
2243             stream->accumulated_base +=
2244                 (stream->segment.stop -
2245                 stream->segment.start) / ABS (stream->segment.rate);
2246           continue;
2247         }
2248
2249         g_assert (i == stream->n_segments - 1);
2250       }
2251     }
2252   }
2253 }
2254
2255 static void
2256 gst_qtdemux_stream_concat (GstQTDemux * qtdemux, GPtrArray * dest,
2257     GPtrArray * src)
2258 {
2259   guint i;
2260   guint len;
2261
2262   len = src->len;
2263
2264   if (len == 0)
2265     return;
2266
2267   for (i = 0; i < len; i++) {
2268     QtDemuxStream *stream = g_ptr_array_index (src, i);
2269
2270 #ifndef GST_DISABLE_GST_DEBUG
2271     GST_DEBUG_OBJECT (qtdemux, "Move stream %p (stream-id %s) to %p",
2272         stream, GST_STR_NULL (stream->stream_id), dest);
2273 #endif
2274     g_ptr_array_add (dest, gst_qtdemux_stream_ref (stream));
2275   }
2276
2277   g_ptr_array_remove_range (src, 0, len);
2278 }
2279
2280 static gboolean
2281 gst_qtdemux_handle_sink_event (GstPad * sinkpad, GstObject * parent,
2282     GstEvent * event)
2283 {
2284   GstQTDemux *demux = GST_QTDEMUX (parent);
2285   gboolean res = TRUE;
2286
2287   GST_LOG_OBJECT (demux, "handling %s event", GST_EVENT_TYPE_NAME (event));
2288
2289   switch (GST_EVENT_TYPE (event)) {
2290     case GST_EVENT_SEGMENT:
2291     {
2292       gint64 offset = 0;
2293       QtDemuxStream *stream;
2294       gint idx;
2295       GstSegment segment;
2296
2297       /* some debug output */
2298       gst_event_copy_segment (event, &segment);
2299       GST_DEBUG_OBJECT (demux, "received newsegment %" GST_SEGMENT_FORMAT,
2300           &segment);
2301
2302       if (segment.format == GST_FORMAT_TIME) {
2303         demux->upstream_format_is_time = TRUE;
2304         demux->segment_seqnum = gst_event_get_seqnum (event);
2305       } else {
2306         GST_DEBUG_OBJECT (demux, "Not storing upstream newsegment, "
2307             "not in time format");
2308
2309         /* chain will send initial newsegment after pads have been added */
2310         if (demux->state != QTDEMUX_STATE_MOVIE || !QTDEMUX_N_STREAMS (demux)) {
2311           GST_DEBUG_OBJECT (demux, "still starting, eating event");
2312           goto exit;
2313         }
2314       }
2315
2316       /* check if this matches a time seek we received previously
2317        * FIXME for backwards compatibility reasons we use the
2318        * seek_offset here to compare. In the future we might want to
2319        * change this to use the seqnum as it uniquely should identify
2320        * the segment that corresponds to the seek. */
2321       GST_DEBUG_OBJECT (demux, "Stored seek offset: %" G_GINT64_FORMAT
2322           ", received segment offset %" G_GINT64_FORMAT,
2323           demux->seek_offset, segment.start);
2324       if (segment.format == GST_FORMAT_BYTES
2325           && demux->seek_offset == segment.start) {
2326         GST_OBJECT_LOCK (demux);
2327         offset = segment.start;
2328
2329         segment.format = GST_FORMAT_TIME;
2330         segment.start = demux->push_seek_start;
2331         segment.stop = demux->push_seek_stop;
2332         GST_DEBUG_OBJECT (demux, "Replaced segment with stored seek "
2333             "segment %" GST_TIME_FORMAT " - %" GST_TIME_FORMAT,
2334             GST_TIME_ARGS (segment.start), GST_TIME_ARGS (segment.stop));
2335         GST_OBJECT_UNLOCK (demux);
2336       }
2337
2338       /* we only expect a BYTE segment, e.g. following a seek */
2339       if (segment.format == GST_FORMAT_BYTES) {
2340         if (GST_CLOCK_TIME_IS_VALID (segment.start)) {
2341           offset = segment.start;
2342
2343           gst_qtdemux_find_sample (demux, segment.start, TRUE, FALSE, NULL,
2344               NULL, (gint64 *) & segment.start);
2345           if ((gint64) segment.start < 0)
2346             segment.start = 0;
2347         }
2348         if (GST_CLOCK_TIME_IS_VALID (segment.stop)) {
2349           gst_qtdemux_find_sample (demux, segment.stop, FALSE, FALSE, NULL,
2350               NULL, (gint64 *) & segment.stop);
2351           /* keyframe seeking should already arrange for start >= stop,
2352            * but make sure in other rare cases */
2353           segment.stop = MAX (segment.stop, segment.start);
2354         }
2355       } else if (segment.format == GST_FORMAT_TIME) {
2356         /* push all data on the adapter before starting this
2357          * new segment */
2358         gst_qtdemux_process_adapter (demux, TRUE);
2359       } else {
2360         GST_DEBUG_OBJECT (demux, "unsupported segment format, ignoring");
2361         goto exit;
2362       }
2363
2364       /* We shouldn't modify upstream driven TIME FORMAT segment */
2365       if (!demux->upstream_format_is_time) {
2366         /* accept upstream's notion of segment and distribute along */
2367         segment.format = GST_FORMAT_TIME;
2368         segment.position = segment.time = segment.start;
2369         segment.duration = demux->segment.duration;
2370         segment.base = gst_segment_to_running_time (&demux->segment,
2371             GST_FORMAT_TIME, demux->segment.position);
2372       }
2373
2374       gst_segment_copy_into (&segment, &demux->segment);
2375       GST_DEBUG_OBJECT (demux, "Pushing newseg %" GST_SEGMENT_FORMAT, &segment);
2376
2377       /* map segment to internal qt segments and push on each stream */
2378       if (QTDEMUX_N_STREAMS (demux)) {
2379         demux->need_segment = TRUE;
2380         gst_qtdemux_check_send_pending_segment (demux);
2381       }
2382
2383       /* clear leftover in current segment, if any */
2384       gst_adapter_clear (demux->adapter);
2385
2386       /* set up streaming thread */
2387       demux->offset = offset;
2388       if (demux->upstream_format_is_time) {
2389         GST_DEBUG_OBJECT (demux, "Upstream is driving in time format, "
2390             "set values to restart reading from a new atom");
2391         demux->neededbytes = 16;
2392         demux->todrop = 0;
2393       } else {
2394         gst_qtdemux_find_sample (demux, offset, TRUE, TRUE, &stream, &idx,
2395             NULL);
2396         if (stream) {
2397           demux->todrop = stream->samples[idx].offset - offset;
2398           demux->neededbytes = demux->todrop + stream->samples[idx].size;
2399         } else {
2400           /* set up for EOS */
2401           demux->neededbytes = -1;
2402           demux->todrop = 0;
2403         }
2404       }
2405     exit:
2406       gst_event_unref (event);
2407       res = TRUE;
2408       goto drop;
2409     }
2410     case GST_EVENT_FLUSH_START:
2411     {
2412       if (gst_event_get_seqnum (event) == demux->offset_seek_seqnum) {
2413         gst_event_unref (event);
2414         goto drop;
2415       }
2416       QTDEMUX_EXPOSE_LOCK (demux);
2417       res = gst_pad_event_default (demux->sinkpad, parent, event);
2418       QTDEMUX_EXPOSE_UNLOCK (demux);
2419       goto drop;
2420     }
2421     case GST_EVENT_FLUSH_STOP:
2422     {
2423       guint64 dur;
2424
2425       dur = demux->segment.duration;
2426       gst_qtdemux_reset (demux, FALSE);
2427       demux->segment.duration = dur;
2428
2429       if (gst_event_get_seqnum (event) == demux->offset_seek_seqnum) {
2430         gst_event_unref (event);
2431         goto drop;
2432       }
2433       break;
2434     }
2435     case GST_EVENT_EOS:
2436       /* If we are in push mode, and get an EOS before we've seen any streams,
2437        * then error out - we have nowhere to send the EOS */
2438       if (!demux->pullbased) {
2439         gint i;
2440         gboolean has_valid_stream = FALSE;
2441         for (i = 0; i < QTDEMUX_N_STREAMS (demux); i++) {
2442           if (QTDEMUX_NTH_STREAM (demux, i)->pad != NULL) {
2443             has_valid_stream = TRUE;
2444             break;
2445           }
2446         }
2447         if (!has_valid_stream)
2448           gst_qtdemux_post_no_playable_stream_error (demux);
2449         else {
2450           GST_DEBUG_OBJECT (demux, "Data still available after EOS: %u",
2451               (guint) gst_adapter_available (demux->adapter));
2452           if (gst_qtdemux_process_adapter (demux, TRUE) != GST_FLOW_OK) {
2453             res = FALSE;
2454           }
2455         }
2456       }
2457       break;
2458     case GST_EVENT_CAPS:{
2459       GstCaps *caps = NULL;
2460
2461       gst_event_parse_caps (event, &caps);
2462       gst_qtdemux_setcaps (demux, caps);
2463       res = TRUE;
2464       gst_event_unref (event);
2465       goto drop;
2466     }
2467     case GST_EVENT_PROTECTION:
2468     {
2469       const gchar *system_id = NULL;
2470
2471       gst_event_parse_protection (event, &system_id, NULL, NULL);
2472       GST_DEBUG_OBJECT (demux, "Received protection event for system ID %s",
2473           system_id);
2474       gst_qtdemux_append_protection_system_id (demux, system_id);
2475       /* save the event for later, for source pads that have not been created */
2476       g_queue_push_tail (&demux->protection_event_queue, gst_event_ref (event));
2477       /* send it to all pads that already exist */
2478       gst_qtdemux_push_event (demux, event);
2479       res = TRUE;
2480       goto drop;
2481     }
2482     case GST_EVENT_STREAM_START:
2483     {
2484       res = TRUE;
2485       gst_event_unref (event);
2486
2487       /* Drain all the buffers */
2488       gst_qtdemux_process_adapter (demux, TRUE);
2489       gst_qtdemux_reset (demux, FALSE);
2490       /* We expect new moov box after new stream-start event */
2491       if (demux->exposed) {
2492         gst_qtdemux_stream_concat (demux,
2493             demux->old_streams, demux->active_streams);
2494       }
2495
2496       goto drop;
2497     }
2498     default:
2499       break;
2500   }
2501
2502   res = gst_pad_event_default (demux->sinkpad, parent, event) & res;
2503
2504 drop:
2505   return res;
2506 }
2507
2508 #if 0
2509 static void
2510 gst_qtdemux_set_index (GstElement * element, GstIndex * index)
2511 {
2512   GstQTDemux *demux = GST_QTDEMUX (element);
2513
2514   GST_OBJECT_LOCK (demux);
2515   if (demux->element_index)
2516     gst_object_unref (demux->element_index);
2517   if (index) {
2518     demux->element_index = gst_object_ref (index);
2519   } else {
2520     demux->element_index = NULL;
2521   }
2522   GST_OBJECT_UNLOCK (demux);
2523   /* object lock might be taken again */
2524   if (index)
2525     gst_index_get_writer_id (index, GST_OBJECT (element), &demux->index_id);
2526   GST_DEBUG_OBJECT (demux, "Set index %" GST_PTR_FORMAT "for writer id %d",
2527       demux->element_index, demux->index_id);
2528 }
2529
2530 static GstIndex *
2531 gst_qtdemux_get_index (GstElement * element)
2532 {
2533   GstIndex *result = NULL;
2534   GstQTDemux *demux = GST_QTDEMUX (element);
2535
2536   GST_OBJECT_LOCK (demux);
2537   if (demux->element_index)
2538     result = gst_object_ref (demux->element_index);
2539   GST_OBJECT_UNLOCK (demux);
2540
2541   GST_DEBUG_OBJECT (demux, "Returning index %" GST_PTR_FORMAT, result);
2542
2543   return result;
2544 }
2545 #endif
2546
2547 static void
2548 gst_qtdemux_stbl_free (QtDemuxStream * stream)
2549 {
2550   g_free ((gpointer) stream->stco.data);
2551   stream->stco.data = NULL;
2552   g_free ((gpointer) stream->stsz.data);
2553   stream->stsz.data = NULL;
2554   g_free ((gpointer) stream->stsc.data);
2555   stream->stsc.data = NULL;
2556   g_free ((gpointer) stream->stts.data);
2557   stream->stts.data = NULL;
2558   g_free ((gpointer) stream->stss.data);
2559   stream->stss.data = NULL;
2560   g_free ((gpointer) stream->stps.data);
2561   stream->stps.data = NULL;
2562   g_free ((gpointer) stream->ctts.data);
2563   stream->ctts.data = NULL;
2564 }
2565
2566 static void
2567 gst_qtdemux_stream_flush_segments_data (QtDemuxStream * stream)
2568 {
2569   g_free (stream->segments);
2570   stream->segments = NULL;
2571   stream->segment_index = -1;
2572   stream->accumulated_base = 0;
2573 }
2574
2575 static void
2576 gst_qtdemux_stream_flush_samples_data (QtDemuxStream * stream)
2577 {
2578   g_free (stream->samples);
2579   stream->samples = NULL;
2580   gst_qtdemux_stbl_free (stream);
2581
2582   /* fragments */
2583   g_free (stream->ra_entries);
2584   stream->ra_entries = NULL;
2585   stream->n_ra_entries = 0;
2586
2587   stream->sample_index = -1;
2588   stream->stbl_index = -1;
2589   stream->n_samples = 0;
2590   stream->time_position = 0;
2591
2592   stream->n_samples_moof = 0;
2593   stream->duration_moof = 0;
2594   stream->duration_last_moof = 0;
2595 }
2596
2597 static void
2598 gst_qtdemux_stream_clear (QtDemuxStream * stream)
2599 {
2600   gint i;
2601   if (stream->allocator)
2602     gst_object_unref (stream->allocator);
2603   while (stream->buffers) {
2604     gst_buffer_unref (GST_BUFFER_CAST (stream->buffers->data));
2605     stream->buffers = g_slist_delete_link (stream->buffers, stream->buffers);
2606   }
2607   for (i = 0; i < stream->stsd_entries_length; i++) {
2608     QtDemuxStreamStsdEntry *entry = &stream->stsd_entries[i];
2609     if (entry->rgb8_palette) {
2610       gst_memory_unref (entry->rgb8_palette);
2611       entry->rgb8_palette = NULL;
2612     }
2613     entry->sparse = FALSE;
2614   }
2615
2616   if (stream->stream_tags)
2617     gst_tag_list_unref (stream->stream_tags);
2618
2619   stream->stream_tags = gst_tag_list_new_empty ();
2620   gst_tag_list_set_scope (stream->stream_tags, GST_TAG_SCOPE_STREAM);
2621   g_free (stream->redirect_uri);
2622   stream->redirect_uri = NULL;
2623   stream->sent_eos = FALSE;
2624   stream->protected = FALSE;
2625   if (stream->protection_scheme_info) {
2626     if (stream->protection_scheme_type == FOURCC_cenc) {
2627       QtDemuxCencSampleSetInfo *info =
2628           (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
2629       if (info->default_properties)
2630         gst_structure_free (info->default_properties);
2631       if (info->crypto_info)
2632         g_ptr_array_free (info->crypto_info, TRUE);
2633     }
2634     g_free (stream->protection_scheme_info);
2635     stream->protection_scheme_info = NULL;
2636   }
2637   stream->protection_scheme_type = 0;
2638   stream->protection_scheme_version = 0;
2639   g_queue_foreach (&stream->protection_scheme_event_queue,
2640       (GFunc) gst_event_unref, NULL);
2641   g_queue_clear (&stream->protection_scheme_event_queue);
2642   gst_qtdemux_stream_flush_segments_data (stream);
2643   gst_qtdemux_stream_flush_samples_data (stream);
2644 }
2645
2646 static void
2647 gst_qtdemux_stream_reset (QtDemuxStream * stream)
2648 {
2649   gint i;
2650   gst_qtdemux_stream_clear (stream);
2651   for (i = 0; i < stream->stsd_entries_length; i++) {
2652     QtDemuxStreamStsdEntry *entry = &stream->stsd_entries[i];
2653     if (entry->caps) {
2654       gst_caps_unref (entry->caps);
2655       entry->caps = NULL;
2656     }
2657   }
2658   g_free (stream->stsd_entries);
2659   stream->stsd_entries = NULL;
2660   stream->stsd_entries_length = 0;
2661 }
2662
2663 static QtDemuxStream *
2664 gst_qtdemux_stream_ref (QtDemuxStream * stream)
2665 {
2666   g_atomic_int_add (&stream->ref_count, 1);
2667
2668   return stream;
2669 }
2670
2671 static void
2672 gst_qtdemux_stream_unref (QtDemuxStream * stream)
2673 {
2674   if (g_atomic_int_dec_and_test (&stream->ref_count)) {
2675     gst_qtdemux_stream_reset (stream);
2676     gst_tag_list_unref (stream->stream_tags);
2677     if (stream->pad) {
2678       GstQTDemux *demux = stream->demux;
2679       gst_element_remove_pad (GST_ELEMENT_CAST (demux), stream->pad);
2680       gst_flow_combiner_remove_pad (demux->flowcombiner, stream->pad);
2681     }
2682     g_free (stream->stream_id);
2683     g_free (stream);
2684   }
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_update_default_sample_encryption_settings (GstQTDemux * qtdemux,
2780     QtDemuxCencSampleSetInfo * info, guint32 is_encrypted, guint8 iv_size,
2781     const guint8 * kid)
2782 {
2783   GstBuffer *kid_buf = gst_buffer_new_allocate (NULL, 16, NULL);
2784   gst_buffer_fill (kid_buf, 0, kid, 16);
2785   if (info->default_properties)
2786     gst_structure_free (info->default_properties);
2787   info->default_properties =
2788       gst_structure_new ("application/x-cenc",
2789       "iv_size", G_TYPE_UINT, iv_size,
2790       "encrypted", G_TYPE_BOOLEAN, (is_encrypted == 1),
2791       "kid", GST_TYPE_BUFFER, kid_buf, NULL);
2792   GST_DEBUG_OBJECT (qtdemux, "default sample properties: "
2793       "is_encrypted=%u, iv_size=%u", is_encrypted, iv_size);
2794   gst_buffer_unref (kid_buf);
2795 }
2796
2797 static gboolean
2798 qtdemux_update_default_piff_encryption_settings (GstQTDemux * qtdemux,
2799     QtDemuxCencSampleSetInfo * info, GstByteReader * br)
2800 {
2801   guint32 algorithm_id = 0;
2802   const guint8 *kid;
2803   gboolean is_encrypted = TRUE;
2804   guint8 iv_size = 8;
2805
2806   if (!gst_byte_reader_get_uint24_le (br, &algorithm_id)) {
2807     GST_ERROR_OBJECT (qtdemux, "Error getting box's algorithm ID field");
2808     return FALSE;
2809   }
2810
2811   algorithm_id >>= 8;
2812   if (algorithm_id == 0) {
2813     is_encrypted = FALSE;
2814   } else if (algorithm_id == 1) {
2815     GST_DEBUG_OBJECT (qtdemux, "AES 128-bits CTR encrypted stream");
2816   } else if (algorithm_id == 2) {
2817     GST_DEBUG_OBJECT (qtdemux, "AES 128-bits CBC encrypted stream");
2818   }
2819
2820   if (!gst_byte_reader_get_uint8 (br, &iv_size))
2821     return FALSE;
2822
2823   if (!gst_byte_reader_get_data (br, 16, &kid))
2824     return FALSE;
2825
2826   qtdemux_update_default_sample_encryption_settings (qtdemux, info,
2827       is_encrypted, iv_size, kid);
2828   gst_structure_set (info->default_properties, "piff_algorithm_id",
2829       G_TYPE_UINT, algorithm_id, NULL);
2830   return TRUE;
2831 }
2832
2833
2834 static void
2835 qtdemux_parse_piff (GstQTDemux * qtdemux, const guint8 * buffer, gint length,
2836     guint offset)
2837 {
2838   GstByteReader br;
2839   guint8 version;
2840   guint32 flags = 0;
2841   guint i;
2842   guint iv_size = 8;
2843   QtDemuxStream *stream;
2844   GstStructure *structure;
2845   QtDemuxCencSampleSetInfo *ss_info = NULL;
2846   const gchar *system_id;
2847   gboolean uses_sub_sample_encryption = FALSE;
2848   guint32 sample_count;
2849
2850   if (QTDEMUX_N_STREAMS (qtdemux) == 0)
2851     return;
2852
2853   stream = QTDEMUX_NTH_STREAM (qtdemux, 0);
2854
2855   structure = gst_caps_get_structure (CUR_STREAM (stream)->caps, 0);
2856   if (!gst_structure_has_name (structure, "application/x-cenc")) {
2857     GST_WARNING_OBJECT (qtdemux,
2858         "Attempting PIFF box parsing on an unencrypted stream.");
2859     return;
2860   }
2861
2862   gst_structure_get (structure, GST_PROTECTION_SYSTEM_ID_CAPS_FIELD,
2863       G_TYPE_STRING, &system_id, NULL);
2864   gst_qtdemux_append_protection_system_id (qtdemux, system_id);
2865
2866   stream->protected = TRUE;
2867   stream->protection_scheme_type = FOURCC_cenc;
2868
2869   if (!stream->protection_scheme_info)
2870     stream->protection_scheme_info = g_new0 (QtDemuxCencSampleSetInfo, 1);
2871
2872   ss_info = (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
2873   if (!ss_info->default_properties) {
2874     ss_info->default_properties =
2875         gst_structure_new ("application/x-cenc",
2876         "iv_size", G_TYPE_UINT, iv_size, "encrypted", G_TYPE_BOOLEAN, TRUE,
2877         NULL);
2878
2879   }
2880
2881   if (ss_info->crypto_info) {
2882     GST_LOG_OBJECT (qtdemux, "unreffing existing crypto_info");
2883     g_ptr_array_free (ss_info->crypto_info, TRUE);
2884     ss_info->crypto_info = NULL;
2885   }
2886
2887   /* skip UUID */
2888   gst_byte_reader_init (&br, buffer + offset + 16, length - offset - 16);
2889
2890   if (!gst_byte_reader_get_uint8 (&br, &version)) {
2891     GST_ERROR_OBJECT (qtdemux, "Error getting box's version field");
2892     return;
2893   }
2894
2895   if (!gst_byte_reader_get_uint24_be (&br, &flags)) {
2896     GST_ERROR_OBJECT (qtdemux, "Error getting box's flags field");
2897     return;
2898   }
2899
2900   if ((flags & 0x000001)) {
2901     if (!qtdemux_update_default_piff_encryption_settings (qtdemux, ss_info,
2902             &br))
2903       return;
2904   } else if ((flags & 0x000002)) {
2905     uses_sub_sample_encryption = TRUE;
2906   }
2907
2908   if (!gst_structure_get_uint (ss_info->default_properties, "iv_size",
2909           &iv_size)) {
2910     GST_ERROR_OBJECT (qtdemux, "Error getting encryption IV size field");
2911     return;
2912   }
2913
2914   if (!gst_byte_reader_get_uint32_be (&br, &sample_count)) {
2915     GST_ERROR_OBJECT (qtdemux, "Error getting box's sample count field");
2916     return;
2917   }
2918
2919   ss_info->crypto_info =
2920       g_ptr_array_new_full (sample_count,
2921       (GDestroyNotify) qtdemux_gst_structure_free);
2922
2923   for (i = 0; i < sample_count; ++i) {
2924     GstStructure *properties;
2925     guint8 *data;
2926     GstBuffer *buf;
2927
2928     properties = qtdemux_get_cenc_sample_properties (qtdemux, stream, i);
2929     if (properties == NULL) {
2930       GST_ERROR_OBJECT (qtdemux, "failed to get properties for sample %u", i);
2931       qtdemux->cenc_aux_sample_count = i;
2932       return;
2933     }
2934
2935     if (!gst_byte_reader_dup_data (&br, iv_size, &data)) {
2936       GST_ERROR_OBJECT (qtdemux, "IV data not present for sample %u", i);
2937       gst_structure_free (properties);
2938       qtdemux->cenc_aux_sample_count = i;
2939       return;
2940     }
2941     buf = gst_buffer_new_wrapped (data, iv_size);
2942     gst_structure_set (properties, "iv", GST_TYPE_BUFFER, buf, NULL);
2943     gst_buffer_unref (buf);
2944
2945     if (uses_sub_sample_encryption) {
2946       guint16 n_subsamples;
2947       const GValue *kid_buf_value;
2948
2949       if (!gst_byte_reader_get_uint16_be (&br, &n_subsamples)
2950           || n_subsamples == 0) {
2951         GST_ERROR_OBJECT (qtdemux,
2952             "failed to get subsample count for sample %u", i);
2953         gst_structure_free (properties);
2954         qtdemux->cenc_aux_sample_count = i;
2955         return;
2956       }
2957       GST_LOG_OBJECT (qtdemux, "subsample count: %u", n_subsamples);
2958       if (!gst_byte_reader_dup_data (&br, n_subsamples * 6, &data)) {
2959         GST_ERROR_OBJECT (qtdemux, "failed to get subsample data for sample %u",
2960             i);
2961         gst_structure_free (properties);
2962         qtdemux->cenc_aux_sample_count = i;
2963         return;
2964       }
2965       buf = gst_buffer_new_wrapped (data, n_subsamples * 6);
2966
2967       kid_buf_value =
2968           gst_structure_get_value (ss_info->default_properties, "kid");
2969
2970       gst_structure_set (properties,
2971           "subsample_count", G_TYPE_UINT, n_subsamples,
2972           "subsamples", GST_TYPE_BUFFER, buf, NULL);
2973       gst_structure_set_value (properties, "kid", kid_buf_value);
2974       gst_buffer_unref (buf);
2975     } else {
2976       gst_structure_set (properties, "subsample_count", G_TYPE_UINT, 0, NULL);
2977     }
2978
2979     g_ptr_array_add (ss_info->crypto_info, properties);
2980   }
2981
2982   qtdemux->cenc_aux_sample_count = sample_count;
2983 }
2984
2985 static void
2986 qtdemux_parse_uuid (GstQTDemux * qtdemux, const guint8 * buffer, gint length)
2987 {
2988   static const guint8 xmp_uuid[] = { 0xBE, 0x7A, 0xCF, 0xCB,
2989     0x97, 0xA9, 0x42, 0xE8,
2990     0x9C, 0x71, 0x99, 0x94,
2991     0x91, 0xE3, 0xAF, 0xAC
2992   };
2993   static const guint8 playready_uuid[] = {
2994     0xd0, 0x8a, 0x4f, 0x18, 0x10, 0xf3, 0x4a, 0x82,
2995     0xb6, 0xc8, 0x32, 0xd8, 0xab, 0xa1, 0x83, 0xd3
2996   };
2997
2998   static const guint8 piff_sample_encryption_uuid[] = {
2999     0xa2, 0x39, 0x4f, 0x52, 0x5a, 0x9b, 0x4f, 0x14,
3000     0xa2, 0x44, 0x6c, 0x42, 0x7c, 0x64, 0x8d, 0xf4
3001   };
3002
3003   guint offset;
3004
3005   /* counts as header data */
3006   qtdemux->header_size += length;
3007
3008   offset = (QT_UINT32 (buffer) == 0) ? 16 : 8;
3009
3010   if (length <= offset + 16) {
3011     GST_DEBUG_OBJECT (qtdemux, "uuid atom is too short, skipping");
3012     return;
3013   }
3014
3015   if (memcmp (buffer + offset, xmp_uuid, 16) == 0) {
3016     GstBuffer *buf;
3017     GstTagList *taglist;
3018
3019     buf = _gst_buffer_new_wrapped ((guint8 *) buffer + offset + 16,
3020         length - offset - 16, NULL);
3021     taglist = gst_tag_list_from_xmp_buffer (buf);
3022     gst_buffer_unref (buf);
3023
3024     /* make sure we have a usable taglist */
3025     qtdemux->tag_list = gst_tag_list_make_writable (qtdemux->tag_list);
3026
3027     qtdemux_handle_xmp_taglist (qtdemux, qtdemux->tag_list, taglist);
3028
3029   } else if (memcmp (buffer + offset, playready_uuid, 16) == 0) {
3030     int len;
3031     const gunichar2 *s_utf16;
3032     char *contents;
3033
3034     len = GST_READ_UINT16_LE (buffer + offset + 0x30);
3035     s_utf16 = (const gunichar2 *) (buffer + offset + 0x32);
3036     contents = g_utf16_to_utf8 (s_utf16, len / 2, NULL, NULL, NULL);
3037     GST_ERROR_OBJECT (qtdemux, "contents: %s", contents);
3038
3039     g_free (contents);
3040
3041     GST_ELEMENT_ERROR (qtdemux, STREAM, DECRYPT,
3042         (_("Cannot play stream because it is encrypted with PlayReady DRM.")),
3043         (NULL));
3044   } else if (memcmp (buffer + offset, piff_sample_encryption_uuid, 16) == 0) {
3045     qtdemux_parse_piff (qtdemux, buffer, length, offset);
3046   } else {
3047     GST_DEBUG_OBJECT (qtdemux, "Ignoring unknown uuid: %08x-%08x-%08x-%08x",
3048         GST_READ_UINT32_LE (buffer + offset),
3049         GST_READ_UINT32_LE (buffer + offset + 4),
3050         GST_READ_UINT32_LE (buffer + offset + 8),
3051         GST_READ_UINT32_LE (buffer + offset + 12));
3052   }
3053 }
3054
3055 static void
3056 qtdemux_parse_sidx (GstQTDemux * qtdemux, const guint8 * buffer, gint length)
3057 {
3058   GstSidxParser sidx_parser;
3059   GstIsoffParserResult res;
3060   guint consumed;
3061
3062   gst_isoff_qt_sidx_parser_init (&sidx_parser);
3063
3064   res =
3065       gst_isoff_qt_sidx_parser_add_data (&sidx_parser, buffer, length,
3066       &consumed);
3067   GST_DEBUG_OBJECT (qtdemux, "sidx parse result: %d", res);
3068   if (res == GST_ISOFF_QT_PARSER_DONE) {
3069     check_update_duration (qtdemux, sidx_parser.cumulative_pts);
3070   }
3071   gst_isoff_qt_sidx_parser_clear (&sidx_parser);
3072 }
3073
3074 /* caller verifies at least 8 bytes in buf */
3075 static void
3076 extract_initial_length_and_fourcc (const guint8 * data, guint size,
3077     guint64 * plength, guint32 * pfourcc)
3078 {
3079   guint64 length;
3080   guint32 fourcc;
3081
3082   length = QT_UINT32 (data);
3083   GST_DEBUG ("length 0x%08" G_GINT64_MODIFIER "x", length);
3084   fourcc = QT_FOURCC (data + 4);
3085   GST_DEBUG ("atom type %" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (fourcc));
3086
3087   if (length == 0) {
3088     length = G_MAXUINT64;
3089   } else if (length == 1 && size >= 16) {
3090     /* this means we have an extended size, which is the 64 bit value of
3091      * the next 8 bytes */
3092     length = QT_UINT64 (data + 8);
3093     GST_DEBUG ("length 0x%08" G_GINT64_MODIFIER "x", length);
3094   }
3095
3096   if (plength)
3097     *plength = length;
3098   if (pfourcc)
3099     *pfourcc = fourcc;
3100 }
3101
3102 static gboolean
3103 qtdemux_parse_mehd (GstQTDemux * qtdemux, GstByteReader * br)
3104 {
3105   guint32 version = 0;
3106   GstClockTime duration = 0;
3107
3108   if (!gst_byte_reader_get_uint32_be (br, &version))
3109     goto failed;
3110
3111   version >>= 24;
3112   if (version == 1) {
3113     if (!gst_byte_reader_get_uint64_be (br, &duration))
3114       goto failed;
3115   } else {
3116     guint32 dur = 0;
3117
3118     if (!gst_byte_reader_get_uint32_be (br, &dur))
3119       goto failed;
3120     duration = dur;
3121   }
3122
3123   GST_INFO_OBJECT (qtdemux, "mehd duration: %" G_GUINT64_FORMAT, duration);
3124   qtdemux->duration = duration;
3125
3126   return TRUE;
3127
3128 failed:
3129   {
3130     GST_DEBUG_OBJECT (qtdemux, "parsing mehd failed");
3131     return FALSE;
3132   }
3133 }
3134
3135 static gboolean
3136 qtdemux_parse_trex (GstQTDemux * qtdemux, QtDemuxStream * stream,
3137     guint32 * ds_duration, guint32 * ds_size, guint32 * ds_flags)
3138 {
3139   if (!stream->parsed_trex && qtdemux->moov_node) {
3140     GNode *mvex, *trex;
3141     GstByteReader trex_data;
3142
3143     mvex = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_mvex);
3144     if (mvex) {
3145       trex = qtdemux_tree_get_child_by_type_full (mvex, FOURCC_trex,
3146           &trex_data);
3147       while (trex) {
3148         guint32 id = 0, sdi = 0, dur = 0, size = 0, flags = 0;
3149
3150         /* skip version/flags */
3151         if (!gst_byte_reader_skip (&trex_data, 4))
3152           goto next;
3153         if (!gst_byte_reader_get_uint32_be (&trex_data, &id))
3154           goto next;
3155         if (id != stream->track_id)
3156           goto next;
3157         if (!gst_byte_reader_get_uint32_be (&trex_data, &sdi))
3158           goto next;
3159         if (!gst_byte_reader_get_uint32_be (&trex_data, &dur))
3160           goto next;
3161         if (!gst_byte_reader_get_uint32_be (&trex_data, &size))
3162           goto next;
3163         if (!gst_byte_reader_get_uint32_be (&trex_data, &flags))
3164           goto next;
3165
3166         GST_DEBUG_OBJECT (qtdemux, "fragment defaults for stream %d; "
3167             "duration %d,  size %d, flags 0x%x", stream->track_id,
3168             dur, size, flags);
3169
3170         stream->parsed_trex = TRUE;
3171         stream->def_sample_description_index = sdi;
3172         stream->def_sample_duration = dur;
3173         stream->def_sample_size = size;
3174         stream->def_sample_flags = flags;
3175
3176       next:
3177         /* iterate all siblings */
3178         trex = qtdemux_tree_get_sibling_by_type_full (trex, FOURCC_trex,
3179             &trex_data);
3180       }
3181     }
3182   }
3183
3184   *ds_duration = stream->def_sample_duration;
3185   *ds_size = stream->def_sample_size;
3186   *ds_flags = stream->def_sample_flags;
3187
3188   /* even then, above values are better than random ... */
3189   if (G_UNLIKELY (!stream->parsed_trex)) {
3190     GST_WARNING_OBJECT (qtdemux,
3191         "failed to find fragment defaults for stream %d", stream->track_id);
3192     return FALSE;
3193   }
3194
3195   return TRUE;
3196 }
3197
3198 /* This method should be called whenever a more accurate duration might
3199  * have been found. It will update all relevant variables if/where needed
3200  */
3201 static void
3202 check_update_duration (GstQTDemux * qtdemux, GstClockTime duration)
3203 {
3204   guint i;
3205   guint64 movdur;
3206   GstClockTime prevdur;
3207
3208   movdur = GSTTIME_TO_QTTIME (qtdemux, duration);
3209
3210   if (movdur > qtdemux->duration) {
3211     prevdur = QTTIME_TO_GSTTIME (qtdemux, qtdemux->duration);
3212     GST_DEBUG_OBJECT (qtdemux,
3213         "Updating total duration to %" GST_TIME_FORMAT " was %" GST_TIME_FORMAT,
3214         GST_TIME_ARGS (duration), GST_TIME_ARGS (prevdur));
3215     qtdemux->duration = movdur;
3216     GST_DEBUG_OBJECT (qtdemux,
3217         "qtdemux->segment.duration: %" GST_TIME_FORMAT " .stop: %"
3218         GST_TIME_FORMAT, GST_TIME_ARGS (qtdemux->segment.duration),
3219         GST_TIME_ARGS (qtdemux->segment.stop));
3220     if (qtdemux->segment.duration == prevdur) {
3221       /* If the current segment has duration/stop identical to previous duration
3222        * update them also (because they were set at that point in time with
3223        * the wrong duration */
3224       /* We convert the value *from* the timescale version to avoid rounding errors */
3225       GstClockTime fixeddur = QTTIME_TO_GSTTIME (qtdemux, movdur);
3226       GST_DEBUG_OBJECT (qtdemux, "Updated segment.duration and segment.stop");
3227       qtdemux->segment.duration = fixeddur;
3228       qtdemux->segment.stop = fixeddur;
3229     }
3230   }
3231
3232   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
3233     QtDemuxStream *stream = QTDEMUX_NTH_STREAM (qtdemux, i);
3234
3235     movdur = GSTTIME_TO_QTSTREAMTIME (stream, duration);
3236     if (movdur > stream->duration) {
3237       GST_DEBUG_OBJECT (qtdemux,
3238           "Updating stream #%d duration to %" GST_TIME_FORMAT, i,
3239           GST_TIME_ARGS (duration));
3240       stream->duration = movdur;
3241       /* internal duration tracking state has been updated above, so */
3242       /* preserve an open-ended dummy segment rather than repeatedly updating
3243        * it and spamming downstream accordingly with segment events */
3244       if (stream->dummy_segment &&
3245           GST_CLOCK_TIME_IS_VALID (stream->segments[0].duration)) {
3246         /* Update all dummy values to new duration */
3247         stream->segments[0].stop_time = duration;
3248         stream->segments[0].duration = duration;
3249         stream->segments[0].media_stop = duration;
3250
3251         /* let downstream know we possibly have a new stop time */
3252         if (stream->segment_index != -1) {
3253           GstClockTime pos;
3254
3255           if (qtdemux->segment.rate >= 0) {
3256             pos = stream->segment.start;
3257           } else {
3258             pos = stream->segment.stop;
3259           }
3260
3261           gst_qtdemux_stream_update_segment (qtdemux, stream,
3262               stream->segment_index, pos, NULL, NULL);
3263         }
3264       }
3265     }
3266   }
3267 }
3268
3269 static gboolean
3270 qtdemux_parse_trun (GstQTDemux * qtdemux, GstByteReader * trun,
3271     QtDemuxStream * stream, guint32 d_sample_duration, guint32 d_sample_size,
3272     guint32 d_sample_flags, gint64 moof_offset, gint64 moof_length,
3273     gint64 * base_offset, gint64 * running_offset, gint64 decode_ts,
3274     gboolean has_tfdt)
3275 {
3276   GstClockTime gst_ts = GST_CLOCK_TIME_NONE;
3277   guint64 timestamp;
3278   gint32 data_offset = 0;
3279   guint32 flags = 0, first_flags = 0, samples_count = 0;
3280   gint i;
3281   guint8 *data;
3282   guint entry_size, dur_offset, size_offset, flags_offset = 0, ct_offset = 0;
3283   QtDemuxSample *sample;
3284   gboolean ismv = FALSE;
3285   gint64 initial_offset;
3286
3287   GST_LOG_OBJECT (qtdemux, "parsing trun track-id %d; "
3288       "default dur %d, size %d, flags 0x%x, base offset %" G_GINT64_FORMAT ", "
3289       "decode ts %" G_GINT64_FORMAT, stream->track_id, d_sample_duration,
3290       d_sample_size, d_sample_flags, *base_offset, decode_ts);
3291
3292   if (stream->pending_seek && moof_offset < stream->pending_seek->moof_offset) {
3293     GST_INFO_OBJECT (stream->pad, "skipping trun before seek target fragment");
3294     return TRUE;
3295   }
3296
3297   /* presence of stss or not can't really tell us much,
3298    * and flags and so on tend to be marginally reliable in these files */
3299   if (stream->subtype == FOURCC_soun) {
3300     GST_DEBUG_OBJECT (qtdemux,
3301         "sound track in fragmented file; marking all keyframes");
3302     stream->all_keyframe = TRUE;
3303   }
3304
3305   if (!gst_byte_reader_skip (trun, 1) ||
3306       !gst_byte_reader_get_uint24_be (trun, &flags))
3307     goto fail;
3308
3309   if (!gst_byte_reader_get_uint32_be (trun, &samples_count))
3310     goto fail;
3311
3312   if (flags & TR_DATA_OFFSET) {
3313     /* note this is really signed */
3314     if (!gst_byte_reader_get_int32_be (trun, &data_offset))
3315       goto fail;
3316     GST_LOG_OBJECT (qtdemux, "trun data offset %d", data_offset);
3317     /* default base offset = first byte of moof */
3318     if (*base_offset == -1) {
3319       GST_LOG_OBJECT (qtdemux, "base_offset at moof");
3320       *base_offset = moof_offset;
3321     }
3322     *running_offset = *base_offset + data_offset;
3323   } else {
3324     /* if no offset at all, that would mean data starts at moof start,
3325      * which is a bit wrong and is ismv crappy way, so compensate
3326      * assuming data is in mdat following moof */
3327     if (*base_offset == -1) {
3328       *base_offset = moof_offset + moof_length + 8;
3329       GST_LOG_OBJECT (qtdemux, "base_offset assumed in mdat after moof");
3330       ismv = TRUE;
3331     }
3332     if (*running_offset == -1)
3333       *running_offset = *base_offset;
3334   }
3335
3336   GST_LOG_OBJECT (qtdemux, "running offset now %" G_GINT64_FORMAT,
3337       *running_offset);
3338   GST_LOG_OBJECT (qtdemux, "trun offset %d, flags 0x%x, entries %d",
3339       data_offset, flags, samples_count);
3340
3341   if (flags & TR_FIRST_SAMPLE_FLAGS) {
3342     if (G_UNLIKELY (flags & TR_SAMPLE_FLAGS)) {
3343       GST_DEBUG_OBJECT (qtdemux,
3344           "invalid flags; SAMPLE and FIRST_SAMPLE present, discarding latter");
3345       flags ^= TR_FIRST_SAMPLE_FLAGS;
3346     } else {
3347       if (!gst_byte_reader_get_uint32_be (trun, &first_flags))
3348         goto fail;
3349       GST_LOG_OBJECT (qtdemux, "first flags: 0x%x", first_flags);
3350     }
3351   }
3352
3353   /* FIXME ? spec says other bits should also be checked to determine
3354    * entry size (and prefix size for that matter) */
3355   entry_size = 0;
3356   dur_offset = size_offset = 0;
3357   if (flags & TR_SAMPLE_DURATION) {
3358     GST_LOG_OBJECT (qtdemux, "entry duration present");
3359     dur_offset = entry_size;
3360     entry_size += 4;
3361   }
3362   if (flags & TR_SAMPLE_SIZE) {
3363     GST_LOG_OBJECT (qtdemux, "entry size present");
3364     size_offset = entry_size;
3365     entry_size += 4;
3366   }
3367   if (flags & TR_SAMPLE_FLAGS) {
3368     GST_LOG_OBJECT (qtdemux, "entry flags present");
3369     flags_offset = entry_size;
3370     entry_size += 4;
3371   }
3372   if (flags & TR_COMPOSITION_TIME_OFFSETS) {
3373     GST_LOG_OBJECT (qtdemux, "entry ct offset present");
3374     ct_offset = entry_size;
3375     entry_size += 4;
3376   }
3377
3378   if (!qt_atom_parser_has_chunks (trun, samples_count, entry_size))
3379     goto fail;
3380   data = (guint8 *) gst_byte_reader_peek_data_unchecked (trun);
3381
3382   if (stream->n_samples + samples_count >=
3383       QTDEMUX_MAX_SAMPLE_INDEX_SIZE / sizeof (QtDemuxSample))
3384     goto index_too_big;
3385
3386   GST_DEBUG_OBJECT (qtdemux, "allocating n_samples %u * %u (%.2f MB)",
3387       stream->n_samples + samples_count, (guint) sizeof (QtDemuxSample),
3388       (stream->n_samples + samples_count) *
3389       sizeof (QtDemuxSample) / (1024.0 * 1024.0));
3390
3391   /* create a new array of samples if it's the first sample parsed */
3392   if (stream->n_samples == 0) {
3393     g_assert (stream->samples == NULL);
3394     stream->samples = g_try_new0 (QtDemuxSample, samples_count);
3395     /* or try to reallocate it with space enough to insert the new samples */
3396   } else
3397     stream->samples = g_try_renew (QtDemuxSample, stream->samples,
3398         stream->n_samples + samples_count);
3399   if (stream->samples == NULL)
3400     goto out_of_memory;
3401
3402   if (qtdemux->fragment_start != -1) {
3403     timestamp = GSTTIME_TO_QTSTREAMTIME (stream, qtdemux->fragment_start);
3404     qtdemux->fragment_start = -1;
3405   } else {
3406     if (stream->n_samples == 0) {
3407       if (decode_ts > 0) {
3408         timestamp = decode_ts;
3409       } else if (stream->pending_seek != NULL) {
3410         /* if we don't have a timestamp from a tfdt box, we'll use the one
3411          * from the mfra seek table */
3412         GST_INFO_OBJECT (stream->pad, "pending seek ts = %" GST_TIME_FORMAT,
3413             GST_TIME_ARGS (stream->pending_seek->ts));
3414
3415         /* FIXME: this is not fully correct, the timestamp refers to the random
3416          * access sample refered to in the tfra entry, which may not necessarily
3417          * be the first sample in the tfrag/trun (but hopefully/usually is) */
3418         timestamp = GSTTIME_TO_QTSTREAMTIME (stream, stream->pending_seek->ts);
3419       } else {
3420         timestamp = 0;
3421       }
3422
3423       gst_ts = QTSTREAMTIME_TO_GSTTIME (stream, timestamp);
3424       GST_INFO_OBJECT (stream->pad, "first sample ts %" GST_TIME_FORMAT,
3425           GST_TIME_ARGS (gst_ts));
3426     } else {
3427       /* subsequent fragments extend stream */
3428       timestamp =
3429           stream->samples[stream->n_samples - 1].timestamp +
3430           stream->samples[stream->n_samples - 1].duration;
3431
3432       /* If this is a GST_FORMAT_BYTES stream and there's a significant
3433        * difference (1 sec.) between decode_ts and timestamp, prefer the
3434        * former */
3435       if (has_tfdt && !qtdemux->upstream_format_is_time
3436           && ABSDIFF (decode_ts, timestamp) >
3437           MAX (stream->duration_last_moof / 2,
3438               GSTTIME_TO_QTSTREAMTIME (stream, GST_SECOND))) {
3439         GST_INFO_OBJECT (qtdemux,
3440             "decode_ts (%" GST_TIME_FORMAT ") and timestamp (%" GST_TIME_FORMAT
3441             ") are significantly different (more than %" GST_TIME_FORMAT
3442             "), using decode_ts",
3443             GST_TIME_ARGS (QTSTREAMTIME_TO_GSTTIME (stream, decode_ts)),
3444             GST_TIME_ARGS (QTSTREAMTIME_TO_GSTTIME (stream, timestamp)),
3445             GST_TIME_ARGS (QTSTREAMTIME_TO_GSTTIME (stream,
3446                     MAX (stream->duration_last_moof / 2,
3447                         GSTTIME_TO_QTSTREAMTIME (stream, GST_SECOND)))));
3448         timestamp = decode_ts;
3449       }
3450
3451       gst_ts = QTSTREAMTIME_TO_GSTTIME (stream, timestamp);
3452       GST_INFO_OBJECT (qtdemux, "first sample ts %" GST_TIME_FORMAT
3453           " (extends previous samples)", GST_TIME_ARGS (gst_ts));
3454     }
3455   }
3456
3457   initial_offset = *running_offset;
3458
3459   sample = stream->samples + stream->n_samples;
3460   for (i = 0; i < samples_count; i++) {
3461     guint32 dur, size, sflags, ct;
3462
3463     /* first read sample data */
3464     if (flags & TR_SAMPLE_DURATION) {
3465       dur = QT_UINT32 (data + dur_offset);
3466     } else {
3467       dur = d_sample_duration;
3468     }
3469     if (flags & TR_SAMPLE_SIZE) {
3470       size = QT_UINT32 (data + size_offset);
3471     } else {
3472       size = d_sample_size;
3473     }
3474     if (flags & TR_FIRST_SAMPLE_FLAGS) {
3475       if (i == 0) {
3476         sflags = first_flags;
3477       } else {
3478         sflags = d_sample_flags;
3479       }
3480     } else if (flags & TR_SAMPLE_FLAGS) {
3481       sflags = QT_UINT32 (data + flags_offset);
3482     } else {
3483       sflags = d_sample_flags;
3484     }
3485     if (flags & TR_COMPOSITION_TIME_OFFSETS) {
3486       ct = QT_UINT32 (data + ct_offset);
3487     } else {
3488       ct = 0;
3489     }
3490     data += entry_size;
3491
3492     /* fill the sample information */
3493     sample->offset = *running_offset;
3494     sample->pts_offset = ct;
3495     sample->size = size;
3496     sample->timestamp = timestamp;
3497     sample->duration = dur;
3498     /* sample-is-difference-sample */
3499     /* ismv seems to use 0x40 for keyframe, 0xc0 for non-keyframe,
3500      * now idea how it relates to bitfield other than massive LE/BE confusion */
3501     sample->keyframe = ismv ? ((sflags & 0xff) == 0x40) : !(sflags & 0x10000);
3502     *running_offset += size;
3503     timestamp += dur;
3504     stream->duration_moof += dur;
3505     sample++;
3506   }
3507
3508   /* Update total duration if needed */
3509   check_update_duration (qtdemux, QTSTREAMTIME_TO_GSTTIME (stream, timestamp));
3510
3511   /* Pre-emptively figure out size of mdat based on trun information.
3512    * If the [mdat] atom is effectivelly read, it will be replaced by the actual
3513    * size, else we will still be able to use this when dealing with gap'ed
3514    * input */
3515   qtdemux->mdatleft = *running_offset - initial_offset;
3516   qtdemux->mdatoffset = initial_offset;
3517   qtdemux->mdatsize = qtdemux->mdatleft;
3518
3519   stream->n_samples += samples_count;
3520   stream->n_samples_moof += samples_count;
3521
3522   if (stream->pending_seek != NULL)
3523     stream->pending_seek = NULL;
3524
3525   return TRUE;
3526
3527 fail:
3528   {
3529     GST_WARNING_OBJECT (qtdemux, "failed to parse trun");
3530     return FALSE;
3531   }
3532 out_of_memory:
3533   {
3534     GST_WARNING_OBJECT (qtdemux, "failed to allocate %d samples",
3535         stream->n_samples);
3536     return FALSE;
3537   }
3538 index_too_big:
3539   {
3540     GST_WARNING_OBJECT (qtdemux, "not allocating index of %d samples, would "
3541         "be larger than %uMB (broken file?)", stream->n_samples,
3542         QTDEMUX_MAX_SAMPLE_INDEX_SIZE >> 20);
3543     return FALSE;
3544   }
3545 }
3546
3547 /* find stream with @id */
3548 static inline QtDemuxStream *
3549 qtdemux_find_stream (GstQTDemux * qtdemux, guint32 id)
3550 {
3551   QtDemuxStream *stream;
3552   gint i;
3553
3554   /* check */
3555   if (G_UNLIKELY (!id)) {
3556     GST_DEBUG_OBJECT (qtdemux, "invalid track id 0");
3557     return NULL;
3558   }
3559
3560   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
3561     stream = QTDEMUX_NTH_STREAM (qtdemux, i);
3562     if (stream->track_id == id)
3563       return stream;
3564   }
3565   if (qtdemux->mss_mode) {
3566     /* mss should have only 1 stream anyway */
3567     return QTDEMUX_NTH_STREAM (qtdemux, 0);
3568   }
3569
3570   return NULL;
3571 }
3572
3573 static gboolean
3574 qtdemux_parse_mfhd (GstQTDemux * qtdemux, GstByteReader * mfhd,
3575     guint32 * fragment_number)
3576 {
3577   if (!gst_byte_reader_skip (mfhd, 4))
3578     goto fail;
3579   if (!gst_byte_reader_get_uint32_be (mfhd, fragment_number))
3580     goto fail;
3581   return TRUE;
3582 fail:
3583   {
3584     GST_WARNING_OBJECT (qtdemux, "Failed to parse mfhd atom");
3585     return FALSE;
3586   }
3587 }
3588
3589 static gboolean
3590 qtdemux_parse_tfhd (GstQTDemux * qtdemux, GstByteReader * tfhd,
3591     QtDemuxStream ** stream, guint32 * default_sample_duration,
3592     guint32 * default_sample_size, guint32 * default_sample_flags,
3593     gint64 * base_offset)
3594 {
3595   guint32 flags = 0;
3596   guint32 track_id = 0;
3597
3598   if (!gst_byte_reader_skip (tfhd, 1) ||
3599       !gst_byte_reader_get_uint24_be (tfhd, &flags))
3600     goto invalid_track;
3601
3602   if (!gst_byte_reader_get_uint32_be (tfhd, &track_id))
3603     goto invalid_track;
3604
3605   *stream = qtdemux_find_stream (qtdemux, track_id);
3606   if (G_UNLIKELY (!*stream))
3607     goto unknown_stream;
3608
3609   if (flags & TF_DEFAULT_BASE_IS_MOOF)
3610     *base_offset = qtdemux->moof_offset;
3611
3612   if (flags & TF_BASE_DATA_OFFSET)
3613     if (!gst_byte_reader_get_uint64_be (tfhd, (guint64 *) base_offset))
3614       goto invalid_track;
3615
3616   /* obtain stream defaults */
3617   qtdemux_parse_trex (qtdemux, *stream,
3618       default_sample_duration, default_sample_size, default_sample_flags);
3619
3620   (*stream)->stsd_sample_description_id =
3621       (*stream)->def_sample_description_index - 1;
3622
3623   if (flags & TF_SAMPLE_DESCRIPTION_INDEX) {
3624     guint32 sample_description_index;
3625     if (!gst_byte_reader_get_uint32_be (tfhd, &sample_description_index))
3626       goto invalid_track;
3627     (*stream)->stsd_sample_description_id = sample_description_index - 1;
3628   }
3629
3630   if (qtdemux->mss_mode) {
3631     /* mss has no stsd entry */
3632     (*stream)->stsd_sample_description_id = 0;
3633   }
3634
3635   if (flags & TF_DEFAULT_SAMPLE_DURATION)
3636     if (!gst_byte_reader_get_uint32_be (tfhd, default_sample_duration))
3637       goto invalid_track;
3638
3639   if (flags & TF_DEFAULT_SAMPLE_SIZE)
3640     if (!gst_byte_reader_get_uint32_be (tfhd, default_sample_size))
3641       goto invalid_track;
3642
3643   if (flags & TF_DEFAULT_SAMPLE_FLAGS)
3644     if (!gst_byte_reader_get_uint32_be (tfhd, default_sample_flags))
3645       goto invalid_track;
3646
3647   return TRUE;
3648
3649 invalid_track:
3650   {
3651     GST_WARNING_OBJECT (qtdemux, "invalid track fragment header");
3652     return FALSE;
3653   }
3654 unknown_stream:
3655   {
3656     GST_DEBUG_OBJECT (qtdemux, "unknown stream in tfhd");
3657     return TRUE;
3658   }
3659 }
3660
3661 static gboolean
3662 qtdemux_parse_tfdt (GstQTDemux * qtdemux, GstByteReader * br,
3663     guint64 * decode_time)
3664 {
3665   guint32 version = 0;
3666
3667   if (!gst_byte_reader_get_uint32_be (br, &version))
3668     return FALSE;
3669
3670   version >>= 24;
3671   if (version == 1) {
3672     if (!gst_byte_reader_get_uint64_be (br, decode_time))
3673       goto failed;
3674   } else {
3675     guint32 dec_time = 0;
3676     if (!gst_byte_reader_get_uint32_be (br, &dec_time))
3677       goto failed;
3678     *decode_time = dec_time;
3679   }
3680
3681   GST_INFO_OBJECT (qtdemux, "Track fragment decode time: %" G_GUINT64_FORMAT,
3682       *decode_time);
3683
3684   return TRUE;
3685
3686 failed:
3687   {
3688     GST_DEBUG_OBJECT (qtdemux, "parsing tfdt failed");
3689     return FALSE;
3690   }
3691 }
3692
3693 /* Returns a pointer to a GstStructure containing the properties of
3694  * the stream sample identified by @sample_index. The caller must unref
3695  * the returned object after use. Returns NULL if unsuccessful. */
3696 static GstStructure *
3697 qtdemux_get_cenc_sample_properties (GstQTDemux * qtdemux,
3698     QtDemuxStream * stream, guint sample_index)
3699 {
3700   QtDemuxCencSampleSetInfo *info = NULL;
3701
3702   g_return_val_if_fail (stream != NULL, NULL);
3703   g_return_val_if_fail (stream->protected, NULL);
3704   g_return_val_if_fail (stream->protection_scheme_info != NULL, NULL);
3705
3706   info = (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
3707
3708   /* Currently, cenc properties for groups of samples are not supported, so
3709    * simply return a copy of the default sample properties */
3710   return gst_structure_copy (info->default_properties);
3711 }
3712
3713 /* Parses the sizes of sample auxiliary information contained within a stream,
3714  * as given in a saiz box. Returns array of sample_count guint8 size values,
3715  * or NULL on failure */
3716 static guint8 *
3717 qtdemux_parse_saiz (GstQTDemux * qtdemux, QtDemuxStream * stream,
3718     GstByteReader * br, guint32 * sample_count)
3719 {
3720   guint32 flags = 0;
3721   guint8 *info_sizes;
3722   guint8 default_info_size;
3723
3724   g_return_val_if_fail (qtdemux != NULL, NULL);
3725   g_return_val_if_fail (stream != NULL, NULL);
3726   g_return_val_if_fail (br != NULL, NULL);
3727   g_return_val_if_fail (sample_count != NULL, NULL);
3728
3729   if (!gst_byte_reader_get_uint32_be (br, &flags))
3730     return NULL;
3731
3732   if (flags & 0x1) {
3733     /* aux_info_type and aux_info_type_parameter are ignored */
3734     if (!gst_byte_reader_skip (br, 8))
3735       return NULL;
3736   }
3737
3738   if (!gst_byte_reader_get_uint8 (br, &default_info_size))
3739     return NULL;
3740   GST_DEBUG_OBJECT (qtdemux, "default_info_size: %u", default_info_size);
3741
3742   if (!gst_byte_reader_get_uint32_be (br, sample_count))
3743     return NULL;
3744   GST_DEBUG_OBJECT (qtdemux, "sample_count: %u", *sample_count);
3745
3746
3747   if (default_info_size == 0) {
3748     if (!gst_byte_reader_dup_data (br, *sample_count, &info_sizes)) {
3749       return NULL;
3750     }
3751   } else {
3752     info_sizes = g_new (guint8, *sample_count);
3753     memset (info_sizes, default_info_size, *sample_count);
3754   }
3755
3756   return info_sizes;
3757 }
3758
3759 /* Parses the offset of sample auxiliary information contained within a stream,
3760  * as given in a saio box. Returns TRUE if successful; FALSE otherwise. */
3761 static gboolean
3762 qtdemux_parse_saio (GstQTDemux * qtdemux, QtDemuxStream * stream,
3763     GstByteReader * br, guint32 * info_type, guint32 * info_type_parameter,
3764     guint64 * offset)
3765 {
3766   guint8 version = 0;
3767   guint32 flags = 0;
3768   guint32 aux_info_type = 0;
3769   guint32 aux_info_type_parameter = 0;
3770   guint32 entry_count;
3771   guint32 off_32;
3772   guint64 off_64;
3773   const guint8 *aux_info_type_data = NULL;
3774
3775   g_return_val_if_fail (qtdemux != NULL, FALSE);
3776   g_return_val_if_fail (stream != NULL, FALSE);
3777   g_return_val_if_fail (br != NULL, FALSE);
3778   g_return_val_if_fail (offset != NULL, FALSE);
3779
3780   if (!gst_byte_reader_get_uint8 (br, &version))
3781     return FALSE;
3782
3783   if (!gst_byte_reader_get_uint24_be (br, &flags))
3784     return FALSE;
3785
3786   if (flags & 0x1) {
3787
3788     if (!gst_byte_reader_get_data (br, 4, &aux_info_type_data))
3789       return FALSE;
3790     aux_info_type = QT_FOURCC (aux_info_type_data);
3791
3792     if (!gst_byte_reader_get_uint32_be (br, &aux_info_type_parameter))
3793       return FALSE;
3794   } else if (stream->protected) {
3795     aux_info_type = stream->protection_scheme_type;
3796   } else {
3797     aux_info_type = CUR_STREAM (stream)->fourcc;
3798   }
3799
3800   if (info_type)
3801     *info_type = aux_info_type;
3802   if (info_type_parameter)
3803     *info_type_parameter = aux_info_type_parameter;
3804
3805   GST_DEBUG_OBJECT (qtdemux, "aux_info_type: '%" GST_FOURCC_FORMAT "', "
3806       "aux_info_type_parameter:  %#06x",
3807       GST_FOURCC_ARGS (aux_info_type), aux_info_type_parameter);
3808
3809   if (!gst_byte_reader_get_uint32_be (br, &entry_count))
3810     return FALSE;
3811
3812   if (entry_count != 1) {
3813     GST_ERROR_OBJECT (qtdemux, "multiple offsets are not supported");
3814     return FALSE;
3815   }
3816
3817   if (version == 0) {
3818     if (!gst_byte_reader_get_uint32_be (br, &off_32))
3819       return FALSE;
3820     *offset = (guint64) off_32;
3821   } else {
3822     if (!gst_byte_reader_get_uint64_be (br, &off_64))
3823       return FALSE;
3824     *offset = off_64;
3825   }
3826
3827   GST_DEBUG_OBJECT (qtdemux, "offset: %" G_GUINT64_FORMAT, *offset);
3828   return TRUE;
3829 }
3830
3831 static void
3832 qtdemux_gst_structure_free (GstStructure * gststructure)
3833 {
3834   if (gststructure) {
3835     gst_structure_free (gststructure);
3836   }
3837 }
3838
3839 /* Parses auxiliary information relating to samples protected using Common
3840  * Encryption (cenc); the format of this information is defined in
3841  * ISO/IEC 23001-7. Returns TRUE if successful; FALSE otherwise. */
3842 static gboolean
3843 qtdemux_parse_cenc_aux_info (GstQTDemux * qtdemux, QtDemuxStream * stream,
3844     GstByteReader * br, guint8 * info_sizes, guint32 sample_count)
3845 {
3846   QtDemuxCencSampleSetInfo *ss_info = NULL;
3847   guint8 size;
3848   gint i;
3849   GPtrArray *old_crypto_info = NULL;
3850   guint old_entries = 0;
3851
3852   g_return_val_if_fail (qtdemux != NULL, FALSE);
3853   g_return_val_if_fail (stream != NULL, FALSE);
3854   g_return_val_if_fail (br != NULL, FALSE);
3855   g_return_val_if_fail (stream->protected, FALSE);
3856   g_return_val_if_fail (stream->protection_scheme_info != NULL, FALSE);
3857
3858   ss_info = (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
3859
3860   if (ss_info->crypto_info) {
3861     old_crypto_info = ss_info->crypto_info;
3862     /* Count number of non-null entries remaining at the tail end */
3863     for (i = old_crypto_info->len - 1; i >= 0; i--) {
3864       if (g_ptr_array_index (old_crypto_info, i) == NULL)
3865         break;
3866       old_entries++;
3867     }
3868   }
3869
3870   ss_info->crypto_info =
3871       g_ptr_array_new_full (sample_count + old_entries,
3872       (GDestroyNotify) qtdemux_gst_structure_free);
3873
3874   /* We preserve old entries because we parse the next moof in advance
3875    * of consuming all samples from the previous moof, and otherwise
3876    * we'd discard the corresponding crypto info for the samples
3877    * from the previous fragment. */
3878   if (old_entries) {
3879     GST_DEBUG_OBJECT (qtdemux, "Preserving %d old crypto info entries",
3880         old_entries);
3881     for (i = old_crypto_info->len - old_entries; i < old_crypto_info->len; i++) {
3882       g_ptr_array_add (ss_info->crypto_info, g_ptr_array_index (old_crypto_info,
3883               i));
3884       g_ptr_array_index (old_crypto_info, i) = NULL;
3885     }
3886   }
3887
3888   if (old_crypto_info) {
3889     /* Everything now belongs to the new array */
3890     g_ptr_array_free (old_crypto_info, TRUE);
3891   }
3892
3893   for (i = 0; i < sample_count; ++i) {
3894     GstStructure *properties;
3895     guint16 n_subsamples = 0;
3896     guint8 *data;
3897     guint iv_size;
3898     GstBuffer *buf;
3899
3900     properties = qtdemux_get_cenc_sample_properties (qtdemux, stream, i);
3901     if (properties == NULL) {
3902       GST_ERROR_OBJECT (qtdemux, "failed to get properties for sample %u", i);
3903       return FALSE;
3904     }
3905     if (!gst_structure_get_uint (properties, "iv_size", &iv_size)) {
3906       GST_ERROR_OBJECT (qtdemux, "failed to get iv_size for sample %u", i);
3907       gst_structure_free (properties);
3908       return FALSE;
3909     }
3910     if (!gst_byte_reader_dup_data (br, iv_size, &data)) {
3911       GST_ERROR_OBJECT (qtdemux, "failed to get IV for sample %u", i);
3912       gst_structure_free (properties);
3913       return FALSE;
3914     }
3915     buf = gst_buffer_new_wrapped (data, iv_size);
3916     gst_structure_set (properties, "iv", GST_TYPE_BUFFER, buf, NULL);
3917     gst_buffer_unref (buf);
3918     size = info_sizes[i];
3919     if (size > iv_size) {
3920       if (!gst_byte_reader_get_uint16_be (br, &n_subsamples)
3921           || !(n_subsamples > 0)) {
3922         gst_structure_free (properties);
3923         GST_ERROR_OBJECT (qtdemux,
3924             "failed to get subsample count for sample %u", i);
3925         return FALSE;
3926       }
3927       GST_LOG_OBJECT (qtdemux, "subsample count: %u", n_subsamples);
3928       if (!gst_byte_reader_dup_data (br, n_subsamples * 6, &data)) {
3929         GST_ERROR_OBJECT (qtdemux, "failed to get subsample data for sample %u",
3930             i);
3931         gst_structure_free (properties);
3932         return FALSE;
3933       }
3934       buf = gst_buffer_new_wrapped (data, n_subsamples * 6);
3935       if (!buf) {
3936         gst_structure_free (properties);
3937         return FALSE;
3938       }
3939       gst_structure_set (properties,
3940           "subsample_count", G_TYPE_UINT, n_subsamples,
3941           "subsamples", GST_TYPE_BUFFER, buf, NULL);
3942       gst_buffer_unref (buf);
3943     } else {
3944       gst_structure_set (properties, "subsample_count", G_TYPE_UINT, 0, NULL);
3945     }
3946     g_ptr_array_add (ss_info->crypto_info, properties);
3947   }
3948   return TRUE;
3949 }
3950
3951 /* Converts a UUID in raw byte form to a string representation, as defined in
3952  * RFC 4122. The caller takes ownership of the returned string and is
3953  * responsible for freeing it after use. */
3954 static gchar *
3955 qtdemux_uuid_bytes_to_string (gconstpointer uuid_bytes)
3956 {
3957   const guint8 *uuid = (const guint8 *) uuid_bytes;
3958
3959   return g_strdup_printf ("%02x%02x%02x%02x-%02x%02x-%02x%02x-"
3960       "%02x%02x-%02x%02x%02x%02x%02x%02x",
3961       uuid[0], uuid[1], uuid[2], uuid[3],
3962       uuid[4], uuid[5], uuid[6], uuid[7],
3963       uuid[8], uuid[9], uuid[10], uuid[11],
3964       uuid[12], uuid[13], uuid[14], uuid[15]);
3965 }
3966
3967 /* Parses a Protection System Specific Header box (pssh), as defined in the
3968  * Common Encryption (cenc) standard (ISO/IEC 23001-7), which contains
3969  * information needed by a specific content protection system in order to
3970  * decrypt cenc-protected tracks. Returns TRUE if successful; FALSE
3971  * otherwise. */
3972 static gboolean
3973 qtdemux_parse_pssh (GstQTDemux * qtdemux, GNode * node)
3974 {
3975   gchar *sysid_string;
3976   guint32 pssh_size = QT_UINT32 (node->data);
3977   GstBuffer *pssh = NULL;
3978   GstEvent *event = NULL;
3979   guint32 parent_box_type;
3980   gint i;
3981
3982   if (G_UNLIKELY (pssh_size < 32U)) {
3983     GST_ERROR_OBJECT (qtdemux, "invalid box size");
3984     return FALSE;
3985   }
3986
3987   sysid_string =
3988       qtdemux_uuid_bytes_to_string ((const guint8 *) node->data + 12);
3989
3990   gst_qtdemux_append_protection_system_id (qtdemux, sysid_string);
3991
3992   pssh = gst_buffer_new_wrapped (g_memdup (node->data, pssh_size), pssh_size);
3993   GST_LOG_OBJECT (qtdemux, "cenc pssh size: %" G_GSIZE_FORMAT,
3994       gst_buffer_get_size (pssh));
3995
3996   parent_box_type = QT_FOURCC ((const guint8 *) node->parent->data + 4);
3997
3998   /* Push an event containing the pssh box onto the queues of all streams. */
3999   event = gst_event_new_protection (sysid_string, pssh,
4000       (parent_box_type == FOURCC_moov) ? "isobmff/moov" : "isobmff/moof");
4001   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
4002     QtDemuxStream *stream = QTDEMUX_NTH_STREAM (qtdemux, i);
4003     GST_TRACE_OBJECT (qtdemux,
4004         "adding protection event for stream %s and system %s",
4005         stream->stream_id, sysid_string);
4006     g_queue_push_tail (&stream->protection_scheme_event_queue,
4007         gst_event_ref (event));
4008   }
4009   g_free (sysid_string);
4010   gst_event_unref (event);
4011   gst_buffer_unref (pssh);
4012   return TRUE;
4013 }
4014
4015 static gboolean
4016 qtdemux_parse_moof (GstQTDemux * qtdemux, const guint8 * buffer, guint length,
4017     guint64 moof_offset, QtDemuxStream * stream)
4018 {
4019   GNode *moof_node, *traf_node, *tfhd_node, *trun_node, *tfdt_node, *mfhd_node;
4020   GNode *uuid_node;
4021   GstByteReader mfhd_data, trun_data, tfhd_data, tfdt_data;
4022   GNode *saiz_node, *saio_node, *pssh_node;
4023   GstByteReader saiz_data, saio_data;
4024   guint32 ds_size = 0, ds_duration = 0, ds_flags = 0;
4025   gint64 base_offset, running_offset;
4026   guint32 frag_num;
4027   GstClockTime min_dts = GST_CLOCK_TIME_NONE;
4028
4029   /* NOTE @stream ignored */
4030
4031   moof_node = g_node_new ((guint8 *) buffer);
4032   qtdemux_parse_node (qtdemux, moof_node, buffer, length);
4033   qtdemux_node_dump (qtdemux, moof_node);
4034
4035   /* Get fragment number from mfhd and check it's valid */
4036   mfhd_node =
4037       qtdemux_tree_get_child_by_type_full (moof_node, FOURCC_mfhd, &mfhd_data);
4038   if (mfhd_node == NULL)
4039     goto missing_mfhd;
4040   if (!qtdemux_parse_mfhd (qtdemux, &mfhd_data, &frag_num))
4041     goto fail;
4042   GST_DEBUG_OBJECT (qtdemux, "Fragment #%d", frag_num);
4043
4044   /* unknown base_offset to start with */
4045   base_offset = running_offset = -1;
4046   traf_node = qtdemux_tree_get_child_by_type (moof_node, FOURCC_traf);
4047   while (traf_node) {
4048     guint64 decode_time = 0;
4049
4050     /* Fragment Header node */
4051     tfhd_node =
4052         qtdemux_tree_get_child_by_type_full (traf_node, FOURCC_tfhd,
4053         &tfhd_data);
4054     if (!tfhd_node)
4055       goto missing_tfhd;
4056     if (!qtdemux_parse_tfhd (qtdemux, &tfhd_data, &stream, &ds_duration,
4057             &ds_size, &ds_flags, &base_offset))
4058       goto missing_tfhd;
4059
4060     /* The following code assumes at most a single set of sample auxiliary
4061      * data in the fragment (consisting of a saiz box and a corresponding saio
4062      * box); in theory, however, there could be multiple sets of sample
4063      * auxiliary data in a fragment. */
4064     saiz_node =
4065         qtdemux_tree_get_child_by_type_full (traf_node, FOURCC_saiz,
4066         &saiz_data);
4067     if (saiz_node) {
4068       guint32 info_type = 0;
4069       guint64 offset = 0;
4070       guint32 info_type_parameter = 0;
4071
4072       g_free (qtdemux->cenc_aux_info_sizes);
4073
4074       qtdemux->cenc_aux_info_sizes =
4075           qtdemux_parse_saiz (qtdemux, stream, &saiz_data,
4076           &qtdemux->cenc_aux_sample_count);
4077       if (qtdemux->cenc_aux_info_sizes == NULL) {
4078         GST_ERROR_OBJECT (qtdemux, "failed to parse saiz box");
4079         goto fail;
4080       }
4081       saio_node =
4082           qtdemux_tree_get_child_by_type_full (traf_node, FOURCC_saio,
4083           &saio_data);
4084       if (!saio_node) {
4085         GST_ERROR_OBJECT (qtdemux, "saiz box without a corresponding saio box");
4086         g_free (qtdemux->cenc_aux_info_sizes);
4087         qtdemux->cenc_aux_info_sizes = NULL;
4088         goto fail;
4089       }
4090
4091       if (G_UNLIKELY (!qtdemux_parse_saio (qtdemux, stream, &saio_data,
4092                   &info_type, &info_type_parameter, &offset))) {
4093         GST_ERROR_OBJECT (qtdemux, "failed to parse saio box");
4094         g_free (qtdemux->cenc_aux_info_sizes);
4095         qtdemux->cenc_aux_info_sizes = NULL;
4096         goto fail;
4097       }
4098       if (base_offset > -1 && base_offset > qtdemux->moof_offset)
4099         offset += (guint64) (base_offset - qtdemux->moof_offset);
4100       if (info_type == FOURCC_cenc && info_type_parameter == 0U) {
4101         GstByteReader br;
4102         if (offset > length) {
4103           GST_DEBUG_OBJECT (qtdemux, "cenc auxiliary info stored out of moof");
4104           qtdemux->cenc_aux_info_offset = offset;
4105         } else {
4106           gst_byte_reader_init (&br, buffer + offset, length - offset);
4107           if (!qtdemux_parse_cenc_aux_info (qtdemux, stream, &br,
4108                   qtdemux->cenc_aux_info_sizes,
4109                   qtdemux->cenc_aux_sample_count)) {
4110             GST_ERROR_OBJECT (qtdemux, "failed to parse cenc auxiliary info");
4111             g_free (qtdemux->cenc_aux_info_sizes);
4112             qtdemux->cenc_aux_info_sizes = NULL;
4113             goto fail;
4114           }
4115         }
4116       }
4117     }
4118
4119     tfdt_node =
4120         qtdemux_tree_get_child_by_type_full (traf_node, FOURCC_tfdt,
4121         &tfdt_data);
4122     if (tfdt_node) {
4123       /* We'll use decode_time to interpolate timestamps
4124        * in case the input timestamps are missing */
4125       qtdemux_parse_tfdt (qtdemux, &tfdt_data, &decode_time);
4126
4127       GST_DEBUG_OBJECT (qtdemux, "decode time %" G_GINT64_FORMAT
4128           " (%" GST_TIME_FORMAT ")", decode_time,
4129           GST_TIME_ARGS (stream ? QTSTREAMTIME_TO_GSTTIME (stream,
4130                   decode_time) : GST_CLOCK_TIME_NONE));
4131
4132       /* Discard the fragment buffer timestamp info to avoid using it.
4133        * Rely on tfdt instead as it is more accurate than the timestamp
4134        * that is fetched from a manifest/playlist and is usually
4135        * less accurate. */
4136       qtdemux->fragment_start = -1;
4137     }
4138
4139     if (G_UNLIKELY (!stream)) {
4140       /* we lost track of offset, we'll need to regain it,
4141        * but can delay complaining until later or avoid doing so altogether */
4142       base_offset = -2;
4143       goto next;
4144     }
4145     if (G_UNLIKELY (base_offset < -1))
4146       goto lost_offset;
4147
4148     min_dts = MIN (min_dts, QTSTREAMTIME_TO_GSTTIME (stream, decode_time));
4149
4150     if (!qtdemux->pullbased) {
4151       /* Sample tables can grow enough to be problematic if the system memory
4152        * is very low (e.g. embedded devices) and the videos very long
4153        * (~8 MiB/hour for 25-30 fps video + typical AAC audio frames).
4154        * Fortunately, we can easily discard them for each new fragment when
4155        * we know qtdemux will not receive seeks outside of the current fragment.
4156        * adaptivedemux honors this assumption.
4157        * This optimization is also useful for applications that use qtdemux as
4158        * a push-based simple demuxer, like Media Source Extensions. */
4159       gst_qtdemux_stream_flush_samples_data (stream);
4160     }
4161
4162     /* initialise moof sample data */
4163     stream->n_samples_moof = 0;
4164     stream->duration_last_moof = stream->duration_moof;
4165     stream->duration_moof = 0;
4166
4167     /* Track Run node */
4168     trun_node =
4169         qtdemux_tree_get_child_by_type_full (traf_node, FOURCC_trun,
4170         &trun_data);
4171     while (trun_node) {
4172       qtdemux_parse_trun (qtdemux, &trun_data, stream,
4173           ds_duration, ds_size, ds_flags, moof_offset, length, &base_offset,
4174           &running_offset, decode_time, (tfdt_node != NULL));
4175       /* iterate all siblings */
4176       trun_node = qtdemux_tree_get_sibling_by_type_full (trun_node, FOURCC_trun,
4177           &trun_data);
4178     }
4179
4180     uuid_node = qtdemux_tree_get_child_by_type (traf_node, FOURCC_uuid);
4181     if (uuid_node) {
4182       guint8 *uuid_buffer = (guint8 *) uuid_node->data;
4183       guint32 box_length = QT_UINT32 (uuid_buffer);
4184
4185       qtdemux_parse_uuid (qtdemux, uuid_buffer, box_length);
4186     }
4187
4188     /* if no new base_offset provided for next traf,
4189      * base is end of current traf */
4190     base_offset = running_offset;
4191     running_offset = -1;
4192
4193     if (stream->n_samples_moof && stream->duration_moof)
4194       stream->new_caps = TRUE;
4195
4196   next:
4197     /* iterate all siblings */
4198     traf_node = qtdemux_tree_get_sibling_by_type (traf_node, FOURCC_traf);
4199   }
4200
4201   /* parse any protection system info */
4202   pssh_node = qtdemux_tree_get_child_by_type (moof_node, FOURCC_pssh);
4203   while (pssh_node) {
4204     GST_LOG_OBJECT (qtdemux, "Parsing pssh box.");
4205     qtdemux_parse_pssh (qtdemux, pssh_node);
4206     pssh_node = qtdemux_tree_get_sibling_by_type (pssh_node, FOURCC_pssh);
4207   }
4208
4209   if (!qtdemux->upstream_format_is_time && !qtdemux->first_moof_already_parsed
4210       && !qtdemux->received_seek && GST_CLOCK_TIME_IS_VALID (min_dts)
4211       && min_dts != 0) {
4212     /* Unless the user has explictly requested another seek, perform an
4213      * internal seek to the time specified in the tfdt.
4214      *
4215      * This way if the user opens a file where the first tfdt is 1 hour
4216      * into the presentation, they will not have to wait 1 hour for run
4217      * time to catch up and actual playback to start. */
4218     gint i;
4219
4220     GST_DEBUG_OBJECT (qtdemux, "First fragment has a non-zero tfdt, "
4221         "performing an internal seek to %" GST_TIME_FORMAT,
4222         GST_TIME_ARGS (min_dts));
4223
4224     qtdemux->segment.start = min_dts;
4225     qtdemux->segment.time = qtdemux->segment.position = min_dts;
4226
4227     for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
4228       QtDemuxStream *stream = QTDEMUX_NTH_STREAM (qtdemux, i);
4229       stream->time_position = min_dts;
4230     }
4231
4232     /* Before this code was run a segment was already sent when the moov was
4233      * parsed... which is OK -- some apps (mostly tests) expect a segment to
4234      * be emitted after a moov, and we can emit a second segment anyway for
4235      * special cases like this. */
4236     qtdemux->need_segment = TRUE;
4237   }
4238
4239   qtdemux->first_moof_already_parsed = TRUE;
4240
4241   g_node_destroy (moof_node);
4242   return TRUE;
4243
4244 missing_tfhd:
4245   {
4246     GST_DEBUG_OBJECT (qtdemux, "missing tfhd box");
4247     goto fail;
4248   }
4249 missing_mfhd:
4250   {
4251     GST_DEBUG_OBJECT (qtdemux, "Missing mfhd box");
4252     goto fail;
4253   }
4254 lost_offset:
4255   {
4256     GST_DEBUG_OBJECT (qtdemux, "lost offset");
4257     goto fail;
4258   }
4259 fail:
4260   {
4261     g_node_destroy (moof_node);
4262     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
4263         (_("This file is corrupt and cannot be played.")), (NULL));
4264     return FALSE;
4265   }
4266 }
4267
4268 #if 0
4269 /* might be used if some day we actually use mfra & co
4270  * for random access to fragments,
4271  * but that will require quite some modifications and much less relying
4272  * on a sample array */
4273 #endif
4274
4275 static gboolean
4276 qtdemux_parse_tfra (GstQTDemux * qtdemux, GNode * tfra_node)
4277 {
4278   QtDemuxStream *stream;
4279   guint32 ver_flags, track_id, len, num_entries, i;
4280   guint value_size, traf_size, trun_size, sample_size;
4281   guint64 time = 0, moof_offset = 0;
4282 #if 0
4283   GstBuffer *buf = NULL;
4284   GstFlowReturn ret;
4285 #endif
4286   GstByteReader tfra;
4287
4288   gst_byte_reader_init (&tfra, tfra_node->data, QT_UINT32 (tfra_node->data));
4289
4290   if (!gst_byte_reader_skip (&tfra, 8))
4291     return FALSE;
4292
4293   if (!gst_byte_reader_get_uint32_be (&tfra, &ver_flags))
4294     return FALSE;
4295
4296   if (!gst_byte_reader_get_uint32_be (&tfra, &track_id)
4297       || !gst_byte_reader_get_uint32_be (&tfra, &len)
4298       || !gst_byte_reader_get_uint32_be (&tfra, &num_entries))
4299     return FALSE;
4300
4301   GST_DEBUG_OBJECT (qtdemux, "parsing tfra box for track id %u", track_id);
4302
4303   stream = qtdemux_find_stream (qtdemux, track_id);
4304   if (stream == NULL)
4305     goto unknown_trackid;
4306
4307   value_size = ((ver_flags >> 24) == 1) ? sizeof (guint64) : sizeof (guint32);
4308   sample_size = (len & 3) + 1;
4309   trun_size = ((len & 12) >> 2) + 1;
4310   traf_size = ((len & 48) >> 4) + 1;
4311
4312   GST_DEBUG_OBJECT (qtdemux, "%u entries, sizes: value %u, traf %u, trun %u, "
4313       "sample %u", num_entries, value_size, traf_size, trun_size, sample_size);
4314
4315   if (num_entries == 0)
4316     goto no_samples;
4317
4318   if (!qt_atom_parser_has_chunks (&tfra, num_entries,
4319           value_size + value_size + traf_size + trun_size + sample_size))
4320     goto corrupt_file;
4321
4322   g_free (stream->ra_entries);
4323   stream->ra_entries = g_new (QtDemuxRandomAccessEntry, num_entries);
4324   stream->n_ra_entries = num_entries;
4325
4326   for (i = 0; i < num_entries; i++) {
4327     qt_atom_parser_get_offset (&tfra, value_size, &time);
4328     qt_atom_parser_get_offset (&tfra, value_size, &moof_offset);
4329     qt_atom_parser_get_uint_with_size_unchecked (&tfra, traf_size);
4330     qt_atom_parser_get_uint_with_size_unchecked (&tfra, trun_size);
4331     qt_atom_parser_get_uint_with_size_unchecked (&tfra, sample_size);
4332
4333     time = QTSTREAMTIME_TO_GSTTIME (stream, time);
4334
4335     GST_LOG_OBJECT (qtdemux, "fragment time: %" GST_TIME_FORMAT ", "
4336         " moof_offset: %" G_GUINT64_FORMAT, GST_TIME_ARGS (time), moof_offset);
4337
4338     stream->ra_entries[i].ts = time;
4339     stream->ra_entries[i].moof_offset = moof_offset;
4340
4341     /* don't want to go through the entire file and read all moofs at startup */
4342 #if 0
4343     ret = gst_qtdemux_pull_atom (qtdemux, moof_offset, 0, &buf);
4344     if (ret != GST_FLOW_OK)
4345       goto corrupt_file;
4346     qtdemux_parse_moof (qtdemux, GST_BUFFER_DATA (buf), GST_BUFFER_SIZE (buf),
4347         moof_offset, stream);
4348     gst_buffer_unref (buf);
4349 #endif
4350   }
4351
4352   check_update_duration (qtdemux, time);
4353
4354   return TRUE;
4355
4356 /* ERRORS */
4357 unknown_trackid:
4358   {
4359     GST_WARNING_OBJECT (qtdemux, "Couldn't find stream for track %u", track_id);
4360     return FALSE;
4361   }
4362 corrupt_file:
4363   {
4364     GST_WARNING_OBJECT (qtdemux, "broken traf box, ignoring");
4365     return FALSE;
4366   }
4367 no_samples:
4368   {
4369     GST_WARNING_OBJECT (qtdemux, "stream has no samples");
4370     return FALSE;
4371   }
4372 }
4373
4374 static gboolean
4375 qtdemux_pull_mfro_mfra (GstQTDemux * qtdemux)
4376 {
4377   GstMapInfo mfro_map = GST_MAP_INFO_INIT;
4378   GstMapInfo mfra_map = GST_MAP_INFO_INIT;
4379   GstBuffer *mfro = NULL, *mfra = NULL;
4380   GstFlowReturn flow;
4381   gboolean ret = FALSE;
4382   GNode *mfra_node, *tfra_node;
4383   guint64 mfra_offset = 0;
4384   guint32 fourcc, mfra_size;
4385   gint64 len;
4386
4387   /* query upstream size in bytes */
4388   if (!gst_pad_peer_query_duration (qtdemux->sinkpad, GST_FORMAT_BYTES, &len))
4389     goto size_query_failed;
4390
4391   /* mfro box should be at the very end of the file */
4392   flow = gst_qtdemux_pull_atom (qtdemux, len - 16, 16, &mfro);
4393   if (flow != GST_FLOW_OK)
4394     goto exit;
4395
4396   gst_buffer_map (mfro, &mfro_map, GST_MAP_READ);
4397
4398   fourcc = QT_FOURCC (mfro_map.data + 4);
4399   if (fourcc != FOURCC_mfro)
4400     goto exit;
4401
4402   GST_INFO_OBJECT (qtdemux, "Found mfro box");
4403   if (mfro_map.size < 16)
4404     goto invalid_mfro_size;
4405
4406   mfra_size = QT_UINT32 (mfro_map.data + 12);
4407   if (mfra_size >= len)
4408     goto invalid_mfra_size;
4409
4410   mfra_offset = len - mfra_size;
4411
4412   GST_INFO_OBJECT (qtdemux, "mfra offset: %" G_GUINT64_FORMAT ", size %u",
4413       mfra_offset, mfra_size);
4414
4415   /* now get and parse mfra box */
4416   flow = gst_qtdemux_pull_atom (qtdemux, mfra_offset, mfra_size, &mfra);
4417   if (flow != GST_FLOW_OK)
4418     goto broken_file;
4419
4420   gst_buffer_map (mfra, &mfra_map, GST_MAP_READ);
4421
4422   mfra_node = g_node_new ((guint8 *) mfra_map.data);
4423   qtdemux_parse_node (qtdemux, mfra_node, mfra_map.data, mfra_map.size);
4424
4425   tfra_node = qtdemux_tree_get_child_by_type (mfra_node, FOURCC_tfra);
4426
4427   while (tfra_node) {
4428     qtdemux_parse_tfra (qtdemux, tfra_node);
4429     /* iterate all siblings */
4430     tfra_node = qtdemux_tree_get_sibling_by_type (tfra_node, FOURCC_tfra);
4431   }
4432   g_node_destroy (mfra_node);
4433
4434   GST_INFO_OBJECT (qtdemux, "parsed movie fragment random access box (mfra)");
4435   ret = TRUE;
4436
4437 exit:
4438
4439   if (mfro) {
4440     if (mfro_map.memory != NULL)
4441       gst_buffer_unmap (mfro, &mfro_map);
4442     gst_buffer_unref (mfro);
4443   }
4444   if (mfra) {
4445     if (mfra_map.memory != NULL)
4446       gst_buffer_unmap (mfra, &mfra_map);
4447     gst_buffer_unref (mfra);
4448   }
4449   return ret;
4450
4451 /* ERRORS */
4452 size_query_failed:
4453   {
4454     GST_WARNING_OBJECT (qtdemux, "could not query upstream size");
4455     goto exit;
4456   }
4457 invalid_mfro_size:
4458   {
4459     GST_WARNING_OBJECT (qtdemux, "mfro size is too small");
4460     goto exit;
4461   }
4462 invalid_mfra_size:
4463   {
4464     GST_WARNING_OBJECT (qtdemux, "mfra_size in mfro box is invalid");
4465     goto exit;
4466   }
4467 broken_file:
4468   {
4469     GST_WARNING_OBJECT (qtdemux, "bogus mfra offset or size, broken file");
4470     goto exit;
4471   }
4472 }
4473
4474 static guint64
4475 add_offset (guint64 offset, guint64 advance)
4476 {
4477   /* Avoid 64-bit overflow by clamping */
4478   if (offset > G_MAXUINT64 - advance)
4479     return G_MAXUINT64;
4480   return offset + advance;
4481 }
4482
4483 static GstFlowReturn
4484 gst_qtdemux_loop_state_header (GstQTDemux * qtdemux)
4485 {
4486   guint64 length = 0;
4487   guint32 fourcc = 0;
4488   GstBuffer *buf = NULL;
4489   GstFlowReturn ret = GST_FLOW_OK;
4490   guint64 cur_offset = qtdemux->offset;
4491   GstMapInfo map;
4492
4493   ret = gst_pad_pull_range (qtdemux->sinkpad, cur_offset, 16, &buf);
4494   if (G_UNLIKELY (ret != GST_FLOW_OK))
4495     goto beach;
4496   gst_buffer_map (buf, &map, GST_MAP_READ);
4497   if (G_LIKELY (map.size >= 8))
4498     extract_initial_length_and_fourcc (map.data, map.size, &length, &fourcc);
4499   gst_buffer_unmap (buf, &map);
4500   gst_buffer_unref (buf);
4501
4502   /* maybe we already got most we needed, so only consider this eof */
4503   if (G_UNLIKELY (length == 0)) {
4504     GST_ELEMENT_WARNING (qtdemux, STREAM, DEMUX,
4505         (_("Invalid atom size.")),
4506         ("Header atom '%" GST_FOURCC_FORMAT "' has empty length",
4507             GST_FOURCC_ARGS (fourcc)));
4508     ret = GST_FLOW_EOS;
4509     goto beach;
4510   }
4511
4512   switch (fourcc) {
4513     case FOURCC_moof:
4514       /* record for later parsing when needed */
4515       if (!qtdemux->moof_offset) {
4516         qtdemux->moof_offset = qtdemux->offset;
4517       }
4518       if (qtdemux_pull_mfro_mfra (qtdemux)) {
4519         /* FIXME */
4520       } else {
4521         qtdemux->offset += length;      /* skip moof and keep going */
4522       }
4523       if (qtdemux->got_moov) {
4524         GST_INFO_OBJECT (qtdemux, "moof header, got moov, done with headers");
4525         ret = GST_FLOW_EOS;
4526         goto beach;
4527       }
4528       break;
4529     case FOURCC_mdat:
4530     case FOURCC_free:
4531     case FOURCC_skip:
4532     case FOURCC_wide:
4533     case FOURCC_PICT:
4534     case FOURCC_pnot:
4535     {
4536       GST_LOG_OBJECT (qtdemux,
4537           "skipping atom '%" GST_FOURCC_FORMAT "' at %" G_GUINT64_FORMAT,
4538           GST_FOURCC_ARGS (fourcc), cur_offset);
4539       qtdemux->offset = add_offset (qtdemux->offset, length);
4540       break;
4541     }
4542     case FOURCC_moov:
4543     {
4544       GstBuffer *moov = NULL;
4545
4546       if (qtdemux->got_moov) {
4547         GST_DEBUG_OBJECT (qtdemux, "Skipping moov atom as we have one already");
4548         qtdemux->offset = add_offset (qtdemux->offset, length);
4549         goto beach;
4550       }
4551
4552       ret = gst_pad_pull_range (qtdemux->sinkpad, cur_offset, length, &moov);
4553       if (ret != GST_FLOW_OK)
4554         goto beach;
4555       gst_buffer_map (moov, &map, GST_MAP_READ);
4556
4557       if (length != map.size) {
4558         /* Some files have a 'moov' atom at the end of the file which contains
4559          * a terminal 'free' atom where the body of the atom is missing.
4560          * Check for, and permit, this special case.
4561          */
4562         if (map.size >= 8) {
4563           guint8 *final_data = map.data + (map.size - 8);
4564           guint32 final_length = QT_UINT32 (final_data);
4565           guint32 final_fourcc = QT_FOURCC (final_data + 4);
4566
4567           if (final_fourcc == FOURCC_free
4568               && map.size + final_length - 8 == length) {
4569             /* Ok, we've found that special case. Allocate a new buffer with
4570              * that free atom actually present. */
4571             GstBuffer *newmoov = gst_buffer_new_and_alloc (length);
4572             gst_buffer_fill (newmoov, 0, map.data, map.size);
4573             gst_buffer_memset (newmoov, map.size, 0, final_length - 8);
4574             gst_buffer_unmap (moov, &map);
4575             gst_buffer_unref (moov);
4576             moov = newmoov;
4577             gst_buffer_map (moov, &map, GST_MAP_READ);
4578           }
4579         }
4580       }
4581
4582       if (length != map.size) {
4583         GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
4584             (_("This file is incomplete and cannot be played.")),
4585             ("We got less than expected (received %" G_GSIZE_FORMAT
4586                 ", wanted %u, offset %" G_GUINT64_FORMAT ")", map.size,
4587                 (guint) length, cur_offset));
4588         gst_buffer_unmap (moov, &map);
4589         gst_buffer_unref (moov);
4590         ret = GST_FLOW_ERROR;
4591         goto beach;
4592       }
4593       qtdemux->offset += length;
4594
4595       qtdemux_parse_moov (qtdemux, map.data, length);
4596       qtdemux_node_dump (qtdemux, qtdemux->moov_node);
4597
4598       qtdemux_parse_tree (qtdemux);
4599       if (qtdemux->moov_node_compressed) {
4600         g_node_destroy (qtdemux->moov_node_compressed);
4601         g_free (qtdemux->moov_node->data);
4602       }
4603       qtdemux->moov_node_compressed = NULL;
4604       g_node_destroy (qtdemux->moov_node);
4605       qtdemux->moov_node = NULL;
4606       gst_buffer_unmap (moov, &map);
4607       gst_buffer_unref (moov);
4608       qtdemux->got_moov = TRUE;
4609
4610       break;
4611     }
4612     case FOURCC_ftyp:
4613     {
4614       GstBuffer *ftyp = NULL;
4615
4616       /* extract major brand; might come in handy for ISO vs QT issues */
4617       ret = gst_qtdemux_pull_atom (qtdemux, cur_offset, length, &ftyp);
4618       if (ret != GST_FLOW_OK)
4619         goto beach;
4620       qtdemux->offset += length;
4621       gst_buffer_map (ftyp, &map, GST_MAP_READ);
4622       qtdemux_parse_ftyp (qtdemux, map.data, map.size);
4623       gst_buffer_unmap (ftyp, &map);
4624       gst_buffer_unref (ftyp);
4625       break;
4626     }
4627     case FOURCC_uuid:
4628     {
4629       GstBuffer *uuid = NULL;
4630
4631       /* uuid are extension atoms */
4632       ret = gst_qtdemux_pull_atom (qtdemux, cur_offset, length, &uuid);
4633       if (ret != GST_FLOW_OK)
4634         goto beach;
4635       qtdemux->offset += length;
4636       gst_buffer_map (uuid, &map, GST_MAP_READ);
4637       qtdemux_parse_uuid (qtdemux, map.data, map.size);
4638       gst_buffer_unmap (uuid, &map);
4639       gst_buffer_unref (uuid);
4640       break;
4641     }
4642     case FOURCC_sidx:
4643     {
4644       GstBuffer *sidx = NULL;
4645       ret = gst_qtdemux_pull_atom (qtdemux, cur_offset, length, &sidx);
4646       if (ret != GST_FLOW_OK)
4647         goto beach;
4648       qtdemux->offset += length;
4649       gst_buffer_map (sidx, &map, GST_MAP_READ);
4650       qtdemux_parse_sidx (qtdemux, map.data, map.size);
4651       gst_buffer_unmap (sidx, &map);
4652       gst_buffer_unref (sidx);
4653       break;
4654     }
4655     default:
4656     {
4657       GstBuffer *unknown = NULL;
4658
4659       GST_LOG_OBJECT (qtdemux,
4660           "unknown %08x '%" GST_FOURCC_FORMAT "' of size %" G_GUINT64_FORMAT
4661           " at %" G_GUINT64_FORMAT, fourcc, GST_FOURCC_ARGS (fourcc), length,
4662           cur_offset);
4663       ret = gst_qtdemux_pull_atom (qtdemux, cur_offset, length, &unknown);
4664       if (ret != GST_FLOW_OK)
4665         goto beach;
4666       gst_buffer_map (unknown, &map, GST_MAP_READ);
4667       GST_MEMDUMP ("Unknown tag", map.data, map.size);
4668       gst_buffer_unmap (unknown, &map);
4669       gst_buffer_unref (unknown);
4670       qtdemux->offset += length;
4671       break;
4672     }
4673   }
4674
4675 beach:
4676   if (ret == GST_FLOW_EOS && (qtdemux->got_moov || qtdemux->media_caps)) {
4677     /* digested all data, show what we have */
4678     qtdemux_prepare_streams (qtdemux);
4679     QTDEMUX_EXPOSE_LOCK (qtdemux);
4680     ret = qtdemux_expose_streams (qtdemux);
4681     QTDEMUX_EXPOSE_UNLOCK (qtdemux);
4682
4683     qtdemux->state = QTDEMUX_STATE_MOVIE;
4684     GST_DEBUG_OBJECT (qtdemux, "switching state to STATE_MOVIE (%d)",
4685         qtdemux->state);
4686     return ret;
4687   }
4688   return ret;
4689 }
4690
4691 /* Seeks to the previous keyframe of the indexed stream and
4692  * aligns other streams with respect to the keyframe timestamp
4693  * of indexed stream. Only called in case of Reverse Playback
4694  */
4695 static GstFlowReturn
4696 gst_qtdemux_seek_to_previous_keyframe (GstQTDemux * qtdemux)
4697 {
4698   guint32 seg_idx = 0, k_index = 0;
4699   guint32 ref_seg_idx, ref_k_index;
4700   GstClockTime k_pos = 0, last_stop = 0;
4701   QtDemuxSegment *seg = NULL;
4702   QtDemuxStream *ref_str = NULL;
4703   guint64 seg_media_start_mov;  /* segment media start time in mov format */
4704   guint64 target_ts;
4705   gint i;
4706
4707   /* Now we choose an arbitrary stream, get the previous keyframe timestamp
4708    * and finally align all the other streams on that timestamp with their
4709    * respective keyframes */
4710   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
4711     QtDemuxStream *str = QTDEMUX_NTH_STREAM (qtdemux, i);
4712
4713     /* No candidate yet, take the first stream */
4714     if (!ref_str) {
4715       ref_str = str;
4716       continue;
4717     }
4718
4719     /* So that stream has a segment, we prefer video streams */
4720     if (str->subtype == FOURCC_vide) {
4721       ref_str = str;
4722       break;
4723     }
4724   }
4725
4726   if (G_UNLIKELY (!ref_str)) {
4727     GST_DEBUG_OBJECT (qtdemux, "couldn't find any stream");
4728     goto eos;
4729   }
4730
4731   if (G_UNLIKELY (!ref_str->from_sample)) {
4732     GST_DEBUG_OBJECT (qtdemux, "reached the beginning of the file");
4733     goto eos;
4734   }
4735
4736   /* So that stream has been playing from from_sample to to_sample. We will
4737    * get the timestamp of the previous sample and search for a keyframe before
4738    * that. For audio streams we do an arbitrary jump in the past (10 samples) */
4739   if (ref_str->subtype == FOURCC_vide) {
4740     k_index = gst_qtdemux_find_keyframe (qtdemux, ref_str,
4741         ref_str->from_sample - 1, FALSE);
4742   } else {
4743     if (ref_str->from_sample >= 10)
4744       k_index = ref_str->from_sample - 10;
4745     else
4746       k_index = 0;
4747   }
4748
4749   target_ts =
4750       ref_str->samples[k_index].timestamp +
4751       ref_str->samples[k_index].pts_offset;
4752
4753   /* get current segment for that stream */
4754   seg = &ref_str->segments[ref_str->segment_index];
4755   /* Use segment start in original timescale for comparisons */
4756   seg_media_start_mov = seg->trak_media_start;
4757
4758   GST_LOG_OBJECT (qtdemux, "keyframe index %u ts %" G_GUINT64_FORMAT
4759       " seg start %" G_GUINT64_FORMAT " %" GST_TIME_FORMAT "\n",
4760       k_index, target_ts, seg_media_start_mov,
4761       GST_TIME_ARGS (seg->media_start));
4762
4763   /* Crawl back through segments to find the one containing this I frame */
4764   while (target_ts < seg_media_start_mov) {
4765     GST_DEBUG_OBJECT (qtdemux,
4766         "keyframe position (sample %u) is out of segment %u " " target %"
4767         G_GUINT64_FORMAT " seg start %" G_GUINT64_FORMAT, k_index,
4768         ref_str->segment_index, target_ts, seg_media_start_mov);
4769
4770     if (G_UNLIKELY (!ref_str->segment_index)) {
4771       /* Reached first segment, let's consider it's EOS */
4772       goto eos;
4773     }
4774     ref_str->segment_index--;
4775     seg = &ref_str->segments[ref_str->segment_index];
4776     /* Use segment start in original timescale for comparisons */
4777     seg_media_start_mov = seg->trak_media_start;
4778   }
4779   /* Calculate time position of the keyframe and where we should stop */
4780   k_pos =
4781       QTSTREAMTIME_TO_GSTTIME (ref_str,
4782       target_ts - seg->trak_media_start) + seg->time;
4783   last_stop =
4784       QTSTREAMTIME_TO_GSTTIME (ref_str,
4785       ref_str->samples[ref_str->from_sample].timestamp -
4786       seg->trak_media_start) + seg->time;
4787
4788   GST_DEBUG_OBJECT (qtdemux, "preferred stream played from sample %u, "
4789       "now going to sample %u (pts %" GST_TIME_FORMAT ")", ref_str->from_sample,
4790       k_index, GST_TIME_ARGS (k_pos));
4791
4792   /* Set last_stop with the keyframe timestamp we pushed of that stream */
4793   qtdemux->segment.position = last_stop;
4794   GST_DEBUG_OBJECT (qtdemux, "last_stop now is %" GST_TIME_FORMAT,
4795       GST_TIME_ARGS (last_stop));
4796
4797   if (G_UNLIKELY (last_stop < qtdemux->segment.start)) {
4798     GST_DEBUG_OBJECT (qtdemux, "reached the beginning of segment");
4799     goto eos;
4800   }
4801
4802   ref_seg_idx = ref_str->segment_index;
4803   ref_k_index = k_index;
4804
4805   /* Align them all on this */
4806   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
4807     guint32 index = 0;
4808     GstClockTime seg_time = 0;
4809     QtDemuxStream *str = QTDEMUX_NTH_STREAM (qtdemux, i);
4810
4811     /* aligning reference stream again might lead to backing up to yet another
4812      * keyframe (due to timestamp rounding issues),
4813      * potentially putting more load on downstream; so let's try to avoid */
4814     if (str == ref_str) {
4815       seg_idx = ref_seg_idx;
4816       seg = &str->segments[seg_idx];
4817       k_index = ref_k_index;
4818       GST_DEBUG_OBJECT (qtdemux, "reference track-id %u segment %d, "
4819           "sample at index %d", str->track_id, ref_str->segment_index, k_index);
4820     } else {
4821       seg_idx = gst_qtdemux_find_segment (qtdemux, str, k_pos);
4822       GST_DEBUG_OBJECT (qtdemux,
4823           "track-id %u align segment %d for keyframe pos %" GST_TIME_FORMAT,
4824           str->track_id, seg_idx, GST_TIME_ARGS (k_pos));
4825
4826       /* get segment and time in the segment */
4827       seg = &str->segments[seg_idx];
4828       seg_time = k_pos - seg->time;
4829
4830       /* get the media time in the segment.
4831        * No adjustment for empty "filler" segments */
4832       if (seg->media_start != GST_CLOCK_TIME_NONE)
4833         seg_time += seg->media_start;
4834
4835       /* get the index of the sample with media time */
4836       index = gst_qtdemux_find_index_linear (qtdemux, str, seg_time);
4837       GST_DEBUG_OBJECT (qtdemux,
4838           "track-id %u sample for %" GST_TIME_FORMAT " at %u", str->track_id,
4839           GST_TIME_ARGS (seg_time), index);
4840
4841       /* find previous keyframe */
4842       k_index = gst_qtdemux_find_keyframe (qtdemux, str, index, FALSE);
4843     }
4844
4845     /* Remember until where we want to go */
4846     str->to_sample = str->from_sample - 1;
4847     /* Define our time position */
4848     target_ts =
4849         str->samples[k_index].timestamp + str->samples[k_index].pts_offset;
4850     str->time_position = QTSTREAMTIME_TO_GSTTIME (str, target_ts) + seg->time;
4851     if (seg->media_start != GST_CLOCK_TIME_NONE)
4852       str->time_position -= seg->media_start;
4853
4854     /* Now seek back in time */
4855     gst_qtdemux_move_stream (qtdemux, str, k_index);
4856     GST_DEBUG_OBJECT (qtdemux, "track-id %u keyframe at %u, time position %"
4857         GST_TIME_FORMAT " playing from sample %u to %u", str->track_id, k_index,
4858         GST_TIME_ARGS (str->time_position), str->from_sample, str->to_sample);
4859   }
4860
4861   return GST_FLOW_OK;
4862
4863 eos:
4864   return GST_FLOW_EOS;
4865 }
4866
4867 /*
4868  * Gets the current qt segment start, stop and position for the
4869  * given time offset. This is used in update_segment()
4870  */
4871 static void
4872 gst_qtdemux_stream_segment_get_boundaries (GstQTDemux * qtdemux,
4873     QtDemuxStream * stream, GstClockTime offset,
4874     GstClockTime * _start, GstClockTime * _stop, GstClockTime * _time)
4875 {
4876   GstClockTime seg_time;
4877   GstClockTime start, stop, time;
4878   QtDemuxSegment *segment;
4879
4880   segment = &stream->segments[stream->segment_index];
4881
4882   /* get time in this segment */
4883   seg_time = (offset - segment->time) * segment->rate;
4884
4885   GST_LOG_OBJECT (stream->pad, "seg_time %" GST_TIME_FORMAT,
4886       GST_TIME_ARGS (seg_time));
4887
4888   if (G_UNLIKELY (seg_time > segment->duration)) {
4889     GST_LOG_OBJECT (stream->pad,
4890         "seg_time > segment->duration %" GST_TIME_FORMAT,
4891         GST_TIME_ARGS (segment->duration));
4892     seg_time = segment->duration;
4893   }
4894
4895   /* qtdemux->segment.stop is in outside-time-realm, whereas
4896    * segment->media_stop is in track-time-realm.
4897    *
4898    * In order to compare the two, we need to bring segment.stop
4899    * into the track-time-realm
4900    *
4901    * FIXME - does this comment still hold? Don't see any conversion here */
4902
4903   stop = qtdemux->segment.stop;
4904   if (stop == GST_CLOCK_TIME_NONE)
4905     stop = qtdemux->segment.duration;
4906   if (stop == GST_CLOCK_TIME_NONE)
4907     stop = segment->media_stop;
4908   else
4909     stop =
4910         MIN (segment->media_stop, stop - segment->time + segment->media_start);
4911
4912   if (G_UNLIKELY (QTSEGMENT_IS_EMPTY (segment))) {
4913     start = segment->time + seg_time;
4914     time = offset;
4915     stop = start - seg_time + segment->duration;
4916   } else if (qtdemux->segment.rate >= 0) {
4917     start = MIN (segment->media_start + seg_time, stop);
4918     time = offset;
4919   } else {
4920     if (segment->media_start >= qtdemux->segment.start) {
4921       time = segment->time;
4922     } else {
4923       time = segment->time + (qtdemux->segment.start - segment->media_start);
4924     }
4925
4926     start = MAX (segment->media_start, qtdemux->segment.start);
4927     stop = MIN (segment->media_start + seg_time, stop);
4928   }
4929
4930   *_start = start;
4931   *_stop = stop;
4932   *_time = time;
4933 }
4934
4935 /*
4936  * Updates the qt segment used for the stream and pushes a new segment event
4937  * downstream on this stream's pad.
4938  */
4939 static gboolean
4940 gst_qtdemux_stream_update_segment (GstQTDemux * qtdemux, QtDemuxStream * stream,
4941     gint seg_idx, GstClockTime offset, GstClockTime * _start,
4942     GstClockTime * _stop)
4943 {
4944   QtDemuxSegment *segment;
4945   GstClockTime start = 0, stop = GST_CLOCK_TIME_NONE, time = 0;
4946   gdouble rate;
4947   GstEvent *event;
4948
4949   /* update the current segment */
4950   stream->segment_index = seg_idx;
4951
4952   /* get the segment */
4953   segment = &stream->segments[seg_idx];
4954
4955   if (G_UNLIKELY (offset < segment->time)) {
4956     GST_WARNING_OBJECT (stream->pad, "offset < segment->time %" GST_TIME_FORMAT,
4957         GST_TIME_ARGS (segment->time));
4958     return FALSE;
4959   }
4960
4961   /* segment lies beyond total indicated duration */
4962   if (G_UNLIKELY (qtdemux->segment.duration != GST_CLOCK_TIME_NONE &&
4963           segment->time > qtdemux->segment.duration)) {
4964     GST_WARNING_OBJECT (stream->pad, "file duration %" GST_TIME_FORMAT
4965         " < segment->time %" GST_TIME_FORMAT,
4966         GST_TIME_ARGS (qtdemux->segment.duration),
4967         GST_TIME_ARGS (segment->time));
4968     return FALSE;
4969   }
4970
4971   gst_qtdemux_stream_segment_get_boundaries (qtdemux, stream, offset,
4972       &start, &stop, &time);
4973
4974   GST_DEBUG_OBJECT (stream->pad, "new segment %d from %" GST_TIME_FORMAT
4975       " to %" GST_TIME_FORMAT ", time %" GST_TIME_FORMAT, seg_idx,
4976       GST_TIME_ARGS (start), GST_TIME_ARGS (stop), GST_TIME_ARGS (time));
4977
4978   /* combine global rate with that of the segment */
4979   rate = segment->rate * qtdemux->segment.rate;
4980
4981   /* Copy flags from main segment */
4982   stream->segment.flags = qtdemux->segment.flags;
4983
4984   /* update the segment values used for clipping */
4985   stream->segment.offset = qtdemux->segment.offset;
4986   stream->segment.base = qtdemux->segment.base + stream->accumulated_base;
4987   stream->segment.applied_rate = qtdemux->segment.applied_rate;
4988   stream->segment.rate = rate;
4989   stream->segment.start = start + QTSTREAMTIME_TO_GSTTIME (stream,
4990       stream->cslg_shift);
4991   stream->segment.stop = stop + QTSTREAMTIME_TO_GSTTIME (stream,
4992       stream->cslg_shift);
4993   stream->segment.time = time;
4994   stream->segment.position = stream->segment.start;
4995
4996   GST_DEBUG_OBJECT (stream->pad, "New segment: %" GST_SEGMENT_FORMAT,
4997       &stream->segment);
4998
4999   /* now prepare and send the segment */
5000   if (stream->pad) {
5001     event = gst_event_new_segment (&stream->segment);
5002     if (qtdemux->segment_seqnum != GST_SEQNUM_INVALID) {
5003       gst_event_set_seqnum (event, qtdemux->segment_seqnum);
5004     }
5005     gst_pad_push_event (stream->pad, event);
5006     /* assume we can send more data now */
5007     GST_PAD_LAST_FLOW_RETURN (stream->pad) = GST_FLOW_OK;
5008     /* clear to send tags on this pad now */
5009     gst_qtdemux_push_tags (qtdemux, stream);
5010   }
5011
5012   if (_start)
5013     *_start = start;
5014   if (_stop)
5015     *_stop = stop;
5016
5017   return TRUE;
5018 }
5019
5020 /* activate the given segment number @seg_idx of @stream at time @offset.
5021  * @offset is an absolute global position over all the segments.
5022  *
5023  * This will push out a NEWSEGMENT event with the right values and
5024  * position the stream index to the first decodable sample before
5025  * @offset.
5026  */
5027 static gboolean
5028 gst_qtdemux_activate_segment (GstQTDemux * qtdemux, QtDemuxStream * stream,
5029     guint32 seg_idx, GstClockTime offset)
5030 {
5031   QtDemuxSegment *segment;
5032   guint32 index, kf_index;
5033   GstClockTime start = 0, stop = GST_CLOCK_TIME_NONE;
5034
5035   GST_LOG_OBJECT (stream->pad, "activate segment %d, offset %" GST_TIME_FORMAT,
5036       seg_idx, GST_TIME_ARGS (offset));
5037
5038   if (!gst_qtdemux_stream_update_segment (qtdemux, stream, seg_idx, offset,
5039           &start, &stop))
5040     return FALSE;
5041
5042   segment = &stream->segments[stream->segment_index];
5043
5044   /* in the fragmented case, we pick a fragment that starts before our
5045    * desired position and rely on downstream to wait for a keyframe
5046    * (FIXME: doesn't seem to work so well with ismv and wmv, as no parser; the
5047    * tfra entries tells us which trun/sample the key unit is in, but we don't
5048    * make use of this additional information at the moment) */
5049   if (qtdemux->fragmented && !qtdemux->fragmented_seek_pending) {
5050     stream->to_sample = G_MAXUINT32;
5051     return TRUE;
5052   } else {
5053     /* well, it will be taken care of below */
5054     qtdemux->fragmented_seek_pending = FALSE;
5055     /* FIXME ideally the do_fragmented_seek can be done right here,
5056      * rather than at loop level
5057      * (which might even allow handling edit lists in a fragmented file) */
5058   }
5059
5060   /* We don't need to look for a sample in push-based */
5061   if (!qtdemux->pullbased)
5062     return TRUE;
5063
5064   /* and move to the keyframe before the indicated media time of the
5065    * segment */
5066   if (G_LIKELY (!QTSEGMENT_IS_EMPTY (segment))) {
5067     if (qtdemux->segment.rate >= 0) {
5068       index = gst_qtdemux_find_index_linear (qtdemux, stream, start);
5069       stream->to_sample = G_MAXUINT32;
5070       GST_DEBUG_OBJECT (stream->pad,
5071           "moving data pointer to %" GST_TIME_FORMAT ", index: %u, pts %"
5072           GST_TIME_FORMAT, GST_TIME_ARGS (start), index,
5073           GST_TIME_ARGS (QTSAMPLE_PTS (stream, &stream->samples[index])));
5074     } else {
5075       index = gst_qtdemux_find_index_linear (qtdemux, stream, stop);
5076       stream->to_sample = index;
5077       GST_DEBUG_OBJECT (stream->pad,
5078           "moving data pointer to %" GST_TIME_FORMAT ", index: %u, pts %"
5079           GST_TIME_FORMAT, GST_TIME_ARGS (stop), index,
5080           GST_TIME_ARGS (QTSAMPLE_PTS (stream, &stream->samples[index])));
5081     }
5082   } else {
5083     GST_DEBUG_OBJECT (stream->pad, "No need to look for keyframe, "
5084         "this is an empty segment");
5085     return TRUE;
5086   }
5087
5088   /* gst_qtdemux_parse_sample () called from gst_qtdemux_find_index_linear ()
5089    * encountered an error and printed a message so we return appropriately */
5090   if (index == -1)
5091     return FALSE;
5092
5093   /* we're at the right spot */
5094   if (index == stream->sample_index) {
5095     GST_DEBUG_OBJECT (stream->pad, "we are at the right index");
5096     return TRUE;
5097   }
5098
5099   /* find keyframe of the target index */
5100   kf_index = gst_qtdemux_find_keyframe (qtdemux, stream, index, FALSE);
5101
5102 /* *INDENT-OFF* */
5103 /* indent does stupid stuff with stream->samples[].timestamp */
5104
5105   /* if we move forwards, we don't have to go back to the previous
5106    * keyframe since we already sent that. We can also just jump to
5107    * the keyframe right before the target index if there is one. */
5108   if (index > stream->sample_index) {
5109     /* moving forwards check if we move past a keyframe */
5110     if (kf_index > stream->sample_index) {
5111       GST_DEBUG_OBJECT (stream->pad,
5112            "moving forwards to keyframe at %u (pts %" GST_TIME_FORMAT " dts %"GST_TIME_FORMAT" )", kf_index,
5113            GST_TIME_ARGS (QTSAMPLE_PTS(stream, &stream->samples[kf_index])),
5114            GST_TIME_ARGS (QTSAMPLE_DTS(stream, &stream->samples[kf_index])));
5115       gst_qtdemux_move_stream (qtdemux, stream, kf_index);
5116     } else {
5117       GST_DEBUG_OBJECT (stream->pad,
5118           "moving forwards, keyframe at %u (pts %" GST_TIME_FORMAT " dts %"GST_TIME_FORMAT" ) already sent", kf_index,
5119           GST_TIME_ARGS (QTSAMPLE_PTS (stream, &stream->samples[kf_index])),
5120           GST_TIME_ARGS (QTSAMPLE_DTS (stream, &stream->samples[kf_index])));
5121     }
5122   } else {
5123     GST_DEBUG_OBJECT (stream->pad,
5124         "moving backwards to keyframe at %u (pts %" GST_TIME_FORMAT " dts %"GST_TIME_FORMAT" )", kf_index,
5125         GST_TIME_ARGS (QTSAMPLE_PTS(stream, &stream->samples[kf_index])),
5126         GST_TIME_ARGS (QTSAMPLE_DTS(stream, &stream->samples[kf_index])));
5127     gst_qtdemux_move_stream (qtdemux, stream, kf_index);
5128   }
5129
5130 /* *INDENT-ON* */
5131
5132   return TRUE;
5133 }
5134
5135 /* prepare to get the current sample of @stream, getting essential values.
5136  *
5137  * This function will also prepare and send the segment when needed.
5138  *
5139  * Return FALSE if the stream is EOS.
5140  *
5141  * PULL-BASED
5142  */
5143 static gboolean
5144 gst_qtdemux_prepare_current_sample (GstQTDemux * qtdemux,
5145     QtDemuxStream * stream, gboolean * empty, guint64 * offset, guint * size,
5146     GstClockTime * dts, GstClockTime * pts, GstClockTime * duration,
5147     gboolean * keyframe)
5148 {
5149   QtDemuxSample *sample;
5150   GstClockTime time_position;
5151   guint32 seg_idx;
5152
5153   g_return_val_if_fail (stream != NULL, FALSE);
5154
5155   time_position = stream->time_position;
5156   if (G_UNLIKELY (time_position == GST_CLOCK_TIME_NONE))
5157     goto eos;
5158
5159   seg_idx = stream->segment_index;
5160   if (G_UNLIKELY (seg_idx == -1)) {
5161     /* find segment corresponding to time_position if we are looking
5162      * for a segment. */
5163     seg_idx = gst_qtdemux_find_segment (qtdemux, stream, time_position);
5164   }
5165
5166   /* different segment, activate it, sample_index will be set. */
5167   if (G_UNLIKELY (stream->segment_index != seg_idx))
5168     gst_qtdemux_activate_segment (qtdemux, stream, seg_idx, time_position);
5169
5170   if (G_UNLIKELY (QTSEGMENT_IS_EMPTY (&stream->segments[stream->
5171                   segment_index]))) {
5172     QtDemuxSegment *seg = &stream->segments[stream->segment_index];
5173
5174     GST_LOG_OBJECT (qtdemux, "Empty segment activated,"
5175         " prepare empty sample");
5176
5177     *empty = TRUE;
5178     *pts = *dts = time_position;
5179     *duration = seg->duration - (time_position - seg->time);
5180
5181     return TRUE;
5182   }
5183
5184   *empty = FALSE;
5185
5186   if (stream->sample_index == -1)
5187     stream->sample_index = 0;
5188
5189   GST_LOG_OBJECT (qtdemux, "segment active, index = %u of %u",
5190       stream->sample_index, stream->n_samples);
5191
5192   if (G_UNLIKELY (stream->sample_index >= stream->n_samples)) {
5193     if (!qtdemux->fragmented)
5194       goto eos;
5195
5196     GST_INFO_OBJECT (qtdemux, "out of samples, trying to add more");
5197     do {
5198       GstFlowReturn flow;
5199
5200       GST_OBJECT_LOCK (qtdemux);
5201       flow = qtdemux_add_fragmented_samples (qtdemux);
5202       GST_OBJECT_UNLOCK (qtdemux);
5203
5204       if (flow != GST_FLOW_OK)
5205         goto eos;
5206     }
5207     while (stream->sample_index >= stream->n_samples);
5208   }
5209
5210   if (!qtdemux_parse_samples (qtdemux, stream, stream->sample_index)) {
5211     GST_LOG_OBJECT (qtdemux, "Parsing of index %u failed!",
5212         stream->sample_index);
5213     return FALSE;
5214   }
5215
5216   /* now get the info for the sample we're at */
5217   sample = &stream->samples[stream->sample_index];
5218
5219   *dts = QTSAMPLE_DTS (stream, sample);
5220   *pts = QTSAMPLE_PTS (stream, sample);
5221   *offset = sample->offset;
5222   *size = sample->size;
5223   *duration = QTSAMPLE_DUR_DTS (stream, sample, *dts);
5224   *keyframe = QTSAMPLE_KEYFRAME (stream, sample);
5225
5226   return TRUE;
5227
5228   /* special cases */
5229 eos:
5230   {
5231     stream->time_position = GST_CLOCK_TIME_NONE;
5232     return FALSE;
5233   }
5234 }
5235
5236 /* move to the next sample in @stream.
5237  *
5238  * Moves to the next segment when needed.
5239  */
5240 static void
5241 gst_qtdemux_advance_sample (GstQTDemux * qtdemux, QtDemuxStream * stream)
5242 {
5243   QtDemuxSample *sample;
5244   QtDemuxSegment *segment;
5245
5246   /* get current segment */
5247   segment = &stream->segments[stream->segment_index];
5248
5249   if (G_UNLIKELY (QTSEGMENT_IS_EMPTY (segment))) {
5250     GST_DEBUG_OBJECT (qtdemux, "Empty segment, no samples to advance");
5251     goto next_segment;
5252   }
5253
5254   if (G_UNLIKELY (stream->sample_index >= stream->to_sample)) {
5255     /* Mark the stream as EOS */
5256     GST_DEBUG_OBJECT (qtdemux,
5257         "reached max allowed sample %u, mark EOS", stream->to_sample);
5258     stream->time_position = GST_CLOCK_TIME_NONE;
5259     return;
5260   }
5261
5262   /* move to next sample */
5263   stream->sample_index++;
5264   stream->offset_in_sample = 0;
5265
5266   /* reached the last sample, we need the next segment */
5267   if (G_UNLIKELY (stream->sample_index >= stream->n_samples))
5268     goto next_segment;
5269
5270   if (!qtdemux_parse_samples (qtdemux, stream, stream->sample_index)) {
5271     GST_LOG_OBJECT (qtdemux, "Parsing of index %u failed!",
5272         stream->sample_index);
5273     return;
5274   }
5275
5276   /* get next sample */
5277   sample = &stream->samples[stream->sample_index];
5278
5279   /* see if we are past the segment */
5280   if (G_UNLIKELY (QTSAMPLE_DTS (stream, sample) >= segment->media_stop))
5281     goto next_segment;
5282
5283   if (QTSAMPLE_DTS (stream, sample) >= segment->media_start) {
5284     /* inside the segment, update time_position, looks very familiar to
5285      * GStreamer segments, doesn't it? */
5286     stream->time_position =
5287         QTSAMPLE_DTS (stream, sample) - segment->media_start + segment->time;
5288   } else {
5289     /* not yet in segment, time does not yet increment. This means
5290      * that we are still prerolling keyframes to the decoder so it can
5291      * decode the first sample of the segment. */
5292     stream->time_position = segment->time;
5293   }
5294   return;
5295
5296   /* move to the next segment */
5297 next_segment:
5298   {
5299     GST_DEBUG_OBJECT (qtdemux, "segment %d ended ", stream->segment_index);
5300
5301     if (stream->segment_index == stream->n_segments - 1) {
5302       /* are we at the end of the last segment, we're EOS */
5303       stream->time_position = GST_CLOCK_TIME_NONE;
5304     } else {
5305       /* else we're only at the end of the current segment */
5306       stream->time_position = segment->stop_time;
5307     }
5308     /* make sure we select a new segment */
5309
5310     /* accumulate previous segments */
5311     if (GST_CLOCK_TIME_IS_VALID (stream->segment.stop))
5312       stream->accumulated_base +=
5313           (stream->segment.stop -
5314           stream->segment.start) / ABS (stream->segment.rate);
5315
5316     stream->segment_index = -1;
5317   }
5318 }
5319
5320 static void
5321 gst_qtdemux_sync_streams (GstQTDemux * demux)
5322 {
5323   gint i;
5324
5325   if (QTDEMUX_N_STREAMS (demux) <= 1)
5326     return;
5327
5328   for (i = 0; i < QTDEMUX_N_STREAMS (demux); i++) {
5329     QtDemuxStream *stream;
5330     GstClockTime end_time;
5331
5332     stream = QTDEMUX_NTH_STREAM (demux, i);
5333
5334     if (!stream->pad)
5335       continue;
5336
5337     /* TODO advance time on subtitle streams here, if any some day */
5338
5339     /* some clips/trailers may have unbalanced streams at the end,
5340      * so send EOS on shorter stream to prevent stalling others */
5341
5342     /* do not mess with EOS if SEGMENT seeking */
5343     if (demux->segment.flags & GST_SEEK_FLAG_SEGMENT)
5344       continue;
5345
5346     if (demux->pullbased) {
5347       /* loop mode is sample time based */
5348       if (!STREAM_IS_EOS (stream))
5349         continue;
5350     } else {
5351       /* push mode is byte position based */
5352       if (stream->n_samples &&
5353           stream->samples[stream->n_samples - 1].offset >= demux->offset)
5354         continue;
5355     }
5356
5357     if (stream->sent_eos)
5358       continue;
5359
5360     /* only act if some gap */
5361     end_time = stream->segments[stream->n_segments - 1].stop_time;
5362     GST_LOG_OBJECT (demux, "current position: %" GST_TIME_FORMAT
5363         ", stream end: %" GST_TIME_FORMAT,
5364         GST_TIME_ARGS (demux->segment.position), GST_TIME_ARGS (end_time));
5365     if (GST_CLOCK_TIME_IS_VALID (end_time)
5366         && (end_time + 2 * GST_SECOND < demux->segment.position)) {
5367       GstEvent *event;
5368
5369       GST_DEBUG_OBJECT (demux, "sending EOS for stream %s",
5370           GST_PAD_NAME (stream->pad));
5371       stream->sent_eos = TRUE;
5372       event = gst_event_new_eos ();
5373       if (demux->segment_seqnum != GST_SEQNUM_INVALID)
5374         gst_event_set_seqnum (event, demux->segment_seqnum);
5375       gst_pad_push_event (stream->pad, event);
5376     }
5377   }
5378 }
5379
5380 /* EOS and NOT_LINKED need to be combined. This means that we return:
5381  *
5382  *  GST_FLOW_NOT_LINKED: when all pads NOT_LINKED.
5383  *  GST_FLOW_EOS: when all pads EOS or NOT_LINKED.
5384  */
5385 static GstFlowReturn
5386 gst_qtdemux_combine_flows (GstQTDemux * demux, QtDemuxStream * stream,
5387     GstFlowReturn ret)
5388 {
5389   GST_LOG_OBJECT (demux, "flow return: %s", gst_flow_get_name (ret));
5390
5391   if (stream->pad)
5392     ret = gst_flow_combiner_update_pad_flow (demux->flowcombiner, stream->pad,
5393         ret);
5394   else
5395     ret = gst_flow_combiner_update_flow (demux->flowcombiner, ret);
5396
5397   GST_LOG_OBJECT (demux, "combined flow return: %s", gst_flow_get_name (ret));
5398   return ret;
5399 }
5400
5401 /* the input buffer metadata must be writable. Returns NULL when the buffer is
5402  * completely clipped
5403  *
5404  * Should be used only with raw buffers */
5405 static GstBuffer *
5406 gst_qtdemux_clip_buffer (GstQTDemux * qtdemux, QtDemuxStream * stream,
5407     GstBuffer * buf)
5408 {
5409   guint64 start, stop, cstart, cstop, diff;
5410   GstClockTime pts, duration;
5411   gsize size, osize;
5412   gint num_rate, denom_rate;
5413   gint frame_size;
5414   gboolean clip_data;
5415   guint offset;
5416
5417   osize = size = gst_buffer_get_size (buf);
5418   offset = 0;
5419
5420   /* depending on the type, setup the clip parameters */
5421   if (stream->subtype == FOURCC_soun) {
5422     frame_size = CUR_STREAM (stream)->bytes_per_frame;
5423     num_rate = GST_SECOND;
5424     denom_rate = (gint) CUR_STREAM (stream)->rate;
5425     clip_data = TRUE;
5426   } else if (stream->subtype == FOURCC_vide) {
5427     frame_size = size;
5428     num_rate = CUR_STREAM (stream)->fps_n;
5429     denom_rate = CUR_STREAM (stream)->fps_d;
5430     clip_data = FALSE;
5431   } else
5432     goto wrong_type;
5433
5434   if (frame_size <= 0)
5435     goto bad_frame_size;
5436
5437   /* we can only clip if we have a valid pts */
5438   pts = GST_BUFFER_PTS (buf);
5439   if (G_UNLIKELY (!GST_CLOCK_TIME_IS_VALID (pts)))
5440     goto no_pts;
5441
5442   duration = GST_BUFFER_DURATION (buf);
5443
5444   if (G_UNLIKELY (!GST_CLOCK_TIME_IS_VALID (duration))) {
5445     duration =
5446         gst_util_uint64_scale_int (size / frame_size, num_rate, denom_rate);
5447   }
5448
5449   start = pts;
5450   stop = start + duration;
5451
5452   if (G_UNLIKELY (!gst_segment_clip (&stream->segment,
5453               GST_FORMAT_TIME, start, stop, &cstart, &cstop)))
5454     goto clipped;
5455
5456   /* see if some clipping happened */
5457   diff = cstart - start;
5458   if (diff > 0) {
5459     pts += diff;
5460     duration -= diff;
5461
5462     if (clip_data) {
5463       /* bring clipped time to samples and to bytes */
5464       diff = gst_util_uint64_scale_int (diff, denom_rate, num_rate);
5465       diff *= frame_size;
5466
5467       GST_DEBUG_OBJECT (qtdemux,
5468           "clipping start to %" GST_TIME_FORMAT " %"
5469           G_GUINT64_FORMAT " bytes", GST_TIME_ARGS (cstart), diff);
5470
5471       offset = diff;
5472       size -= diff;
5473     }
5474   }
5475   diff = stop - cstop;
5476   if (diff > 0) {
5477     duration -= diff;
5478
5479     if (clip_data) {
5480       /* bring clipped time to samples and then to bytes */
5481       diff = gst_util_uint64_scale_int (diff, denom_rate, num_rate);
5482       diff *= frame_size;
5483       GST_DEBUG_OBJECT (qtdemux,
5484           "clipping stop to %" GST_TIME_FORMAT " %" G_GUINT64_FORMAT
5485           " bytes", GST_TIME_ARGS (cstop), diff);
5486       size -= diff;
5487     }
5488   }
5489
5490   if (offset != 0 || size != osize)
5491     gst_buffer_resize (buf, offset, size);
5492
5493   GST_BUFFER_DTS (buf) = GST_CLOCK_TIME_NONE;
5494   GST_BUFFER_PTS (buf) = pts;
5495   GST_BUFFER_DURATION (buf) = duration;
5496
5497   return buf;
5498
5499   /* dropped buffer */
5500 wrong_type:
5501   {
5502     GST_DEBUG_OBJECT (qtdemux, "unknown stream type");
5503     return buf;
5504   }
5505 bad_frame_size:
5506   {
5507     GST_DEBUG_OBJECT (qtdemux, "bad frame size");
5508     return buf;
5509   }
5510 no_pts:
5511   {
5512     GST_DEBUG_OBJECT (qtdemux, "no pts on buffer");
5513     return buf;
5514   }
5515 clipped:
5516   {
5517     GST_DEBUG_OBJECT (qtdemux, "clipped buffer");
5518     gst_buffer_unref (buf);
5519     return NULL;
5520   }
5521 }
5522
5523 static GstBuffer *
5524 gst_qtdemux_align_buffer (GstQTDemux * demux,
5525     GstBuffer * buffer, gsize alignment)
5526 {
5527   GstMapInfo map;
5528
5529   gst_buffer_map (buffer, &map, GST_MAP_READ);
5530
5531   if (map.size < sizeof (guintptr)) {
5532     gst_buffer_unmap (buffer, &map);
5533     return buffer;
5534   }
5535
5536   if (((guintptr) map.data) & (alignment - 1)) {
5537     GstBuffer *new_buffer;
5538     GstAllocationParams params = { 0, alignment - 1, 0, 0, };
5539
5540     new_buffer = gst_buffer_new_allocate (NULL,
5541         gst_buffer_get_size (buffer), &params);
5542
5543     /* Copy data "by hand", so ensure alignment is kept: */
5544     gst_buffer_fill (new_buffer, 0, map.data, map.size);
5545
5546     gst_buffer_copy_into (new_buffer, buffer, GST_BUFFER_COPY_METADATA, 0, -1);
5547     GST_DEBUG_OBJECT (demux,
5548         "We want output aligned on %" G_GSIZE_FORMAT ", reallocated",
5549         alignment);
5550
5551     gst_buffer_unmap (buffer, &map);
5552     gst_buffer_unref (buffer);
5553
5554     return new_buffer;
5555   }
5556
5557   gst_buffer_unmap (buffer, &map);
5558   return buffer;
5559 }
5560
5561 static guint8 *
5562 convert_to_ccdata (const guint8 * ccpair, guint8 ccpair_size, guint field,
5563     gsize * res)
5564 {
5565   guint8 *storage;
5566   gsize i;
5567
5568   /* We are converting from pairs to triplets */
5569   *res = ccpair_size / 2 * 3;
5570   storage = g_malloc (*res);
5571   for (i = 0; i * 2 < ccpair_size; i += 1) {
5572     if (field == 1)
5573       storage[i * 3] = 0xfc;
5574     else
5575       storage[i * 3] = 0xfd;
5576     storage[i * 3 + 1] = ccpair[i * 2];
5577     storage[i * 3 + 2] = ccpair[i * 2 + 1];
5578   }
5579
5580   return storage;
5581 }
5582
5583 static guint8 *
5584 extract_cc_from_data (QtDemuxStream * stream, const guint8 * data, gsize size,
5585     gsize * cclen)
5586 {
5587   guint8 *res = NULL;
5588   guint32 atom_length, fourcc;
5589   QtDemuxStreamStsdEntry *stsd_entry;
5590
5591   GST_MEMDUMP ("caption atom", data, size);
5592
5593   /* There might be multiple atoms */
5594
5595   *cclen = 0;
5596   if (size < 8)
5597     goto invalid_cdat;
5598   atom_length = QT_UINT32 (data);
5599   fourcc = QT_FOURCC (data + 4);
5600   if (G_UNLIKELY (atom_length > size || atom_length == 8))
5601     goto invalid_cdat;
5602
5603   GST_DEBUG_OBJECT (stream->pad, "here");
5604
5605   /* Check if we have somethig compatible */
5606   stsd_entry = CUR_STREAM (stream);
5607   switch (stsd_entry->fourcc) {
5608     case FOURCC_c608:{
5609       guint8 *cdat = NULL, *cdt2 = NULL;
5610       gsize cdat_size = 0, cdt2_size = 0;
5611       /* Should be cdat or cdt2 */
5612       if (fourcc != FOURCC_cdat && fourcc != FOURCC_cdt2) {
5613         GST_WARNING_OBJECT (stream->pad,
5614             "Unknown data atom (%" GST_FOURCC_FORMAT ") for CEA608",
5615             GST_FOURCC_ARGS (fourcc));
5616         goto invalid_cdat;
5617       }
5618
5619       /* Convert to cc_data triplet */
5620       if (fourcc == FOURCC_cdat)
5621         cdat = convert_to_ccdata (data + 8, atom_length - 8, 1, &cdat_size);
5622       else
5623         cdt2 = convert_to_ccdata (data + 8, atom_length - 8, 2, &cdt2_size);
5624       GST_DEBUG_OBJECT (stream->pad, "size:%" G_GSIZE_FORMAT " atom_length:%u",
5625           size, atom_length);
5626
5627       /* Check for another atom ? */
5628       if (size > atom_length + 8) {
5629         guint32 new_atom_length = QT_UINT32 (data + atom_length);
5630         if (size >= atom_length + new_atom_length) {
5631           fourcc = QT_FOURCC (data + atom_length + 4);
5632           if (fourcc == FOURCC_cdat) {
5633             if (cdat == NULL)
5634               cdat =
5635                   convert_to_ccdata (data + atom_length + 8,
5636                   new_atom_length - 8, 1, &cdat_size);
5637             else
5638               GST_WARNING_OBJECT (stream->pad,
5639                   "Got multiple [cdat] atoms in a c608 sample. This is unsupported for now. Please file a bug");
5640           } else {
5641             if (cdt2 == NULL)
5642               cdt2 =
5643                   convert_to_ccdata (data + atom_length + 8,
5644                   new_atom_length - 8, 2, &cdt2_size);
5645             else
5646               GST_WARNING_OBJECT (stream->pad,
5647                   "Got multiple [cdt2] atoms in a c608 sample. This is unsupported for now. Please file a bug");
5648           }
5649         }
5650       }
5651
5652       *cclen = cdat_size + cdt2_size;
5653       res = g_malloc (*cclen);
5654       if (cdat_size)
5655         memcpy (res, cdat, cdat_size);
5656       if (cdt2_size)
5657         memcpy (res + cdat_size, cdt2, cdt2_size);
5658       g_free (cdat);
5659       g_free (cdt2);
5660     }
5661       break;
5662     case FOURCC_c708:
5663       if (fourcc != FOURCC_ccdp) {
5664         GST_WARNING_OBJECT (stream->pad,
5665             "Unknown data atom (%" GST_FOURCC_FORMAT ") for CEA708",
5666             GST_FOURCC_ARGS (fourcc));
5667         goto invalid_cdat;
5668       }
5669       *cclen = atom_length - 8;
5670       res = g_memdup (data + 8, *cclen);
5671       break;
5672     default:
5673       /* Keep this here in case other closed caption formats are added */
5674       g_assert_not_reached ();
5675       break;
5676   }
5677
5678   GST_MEMDUMP ("Output", res, *cclen);
5679   return res;
5680
5681   /* Errors */
5682 invalid_cdat:
5683   GST_WARNING ("[cdat] atom is too small or invalid");
5684   return NULL;
5685 }
5686
5687 /* the input buffer metadata must be writable,
5688  * but time/duration etc not yet set and need not be preserved */
5689 static GstBuffer *
5690 gst_qtdemux_process_buffer (GstQTDemux * qtdemux, QtDemuxStream * stream,
5691     GstBuffer * buf)
5692 {
5693   GstMapInfo map;
5694   guint nsize = 0;
5695   gchar *str;
5696
5697   /* not many cases for now */
5698   if (G_UNLIKELY (CUR_STREAM (stream)->fourcc == FOURCC_mp4s)) {
5699     /* send a one time dvd clut event */
5700     if (stream->pending_event && stream->pad)
5701       gst_pad_push_event (stream->pad, stream->pending_event);
5702     stream->pending_event = NULL;
5703   }
5704
5705   if (G_UNLIKELY (stream->subtype != FOURCC_text
5706           && stream->subtype != FOURCC_sbtl &&
5707           stream->subtype != FOURCC_subp && stream->subtype != FOURCC_clcp)) {
5708     return buf;
5709   }
5710
5711   gst_buffer_map (buf, &map, GST_MAP_READ);
5712
5713   /* empty buffer is sent to terminate previous subtitle */
5714   if (map.size <= 2) {
5715     gst_buffer_unmap (buf, &map);
5716     gst_buffer_unref (buf);
5717     return NULL;
5718   }
5719   if (stream->subtype == FOURCC_subp) {
5720     /* That's all the processing needed for subpictures */
5721     gst_buffer_unmap (buf, &map);
5722     return buf;
5723   }
5724
5725   if (stream->subtype == FOURCC_clcp) {
5726     guint8 *cc;
5727     gsize cclen = 0;
5728     /* For closed caption, we need to extract the information from the
5729      * [cdat],[cdt2] or [ccdp] atom */
5730     cc = extract_cc_from_data (stream, map.data, map.size, &cclen);
5731     gst_buffer_unmap (buf, &map);
5732     gst_buffer_unref (buf);
5733     if (cc) {
5734       buf = _gst_buffer_new_wrapped (cc, cclen, g_free);
5735     } else {
5736       /* Conversion failed or there's nothing */
5737       buf = NULL;
5738     }
5739     return buf;
5740   }
5741
5742   nsize = GST_READ_UINT16_BE (map.data);
5743   nsize = MIN (nsize, map.size - 2);
5744
5745   GST_LOG_OBJECT (qtdemux, "3GPP timed text subtitle: %d/%" G_GSIZE_FORMAT "",
5746       nsize, map.size);
5747
5748   /* takes care of UTF-8 validation or UTF-16 recognition,
5749    * no other encoding expected */
5750   str = gst_tag_freeform_string_to_utf8 ((gchar *) map.data + 2, nsize, NULL);
5751   gst_buffer_unmap (buf, &map);
5752   if (str) {
5753     gst_buffer_unref (buf);
5754     buf = _gst_buffer_new_wrapped (str, strlen (str), g_free);
5755   } else {
5756     /* this should not really happen unless the subtitle is corrupted */
5757     gst_buffer_unref (buf);
5758     buf = NULL;
5759   }
5760
5761   /* FIXME ? convert optional subsequent style info to markup */
5762
5763   return buf;
5764 }
5765
5766 /* Sets a buffer's attributes properly and pushes it downstream.
5767  * Also checks for additional actions and custom processing that may
5768  * need to be done first.
5769  */
5770 static GstFlowReturn
5771 gst_qtdemux_decorate_and_push_buffer (GstQTDemux * qtdemux,
5772     QtDemuxStream * stream, GstBuffer * buf,
5773     GstClockTime dts, GstClockTime pts, GstClockTime duration,
5774     gboolean keyframe, GstClockTime position, guint64 byte_position)
5775 {
5776   GstFlowReturn ret = GST_FLOW_OK;
5777
5778   /* offset the timestamps according to the edit list */
5779
5780   if (G_UNLIKELY (CUR_STREAM (stream)->fourcc == FOURCC_rtsp)) {
5781     gchar *url;
5782     GstMapInfo map;
5783
5784     gst_buffer_map (buf, &map, GST_MAP_READ);
5785     url = g_strndup ((gchar *) map.data, map.size);
5786     gst_buffer_unmap (buf, &map);
5787     if (url != NULL && strlen (url) != 0) {
5788       /* we have RTSP redirect now */
5789       gst_element_post_message (GST_ELEMENT_CAST (qtdemux),
5790           gst_message_new_element (GST_OBJECT_CAST (qtdemux),
5791               gst_structure_new ("redirect",
5792                   "new-location", G_TYPE_STRING, url, NULL)));
5793       qtdemux->posted_redirect = TRUE;
5794     } else {
5795       GST_WARNING_OBJECT (qtdemux, "Redirect URI of stream is empty, not "
5796           "posting");
5797     }
5798     g_free (url);
5799   }
5800
5801   /* position reporting */
5802   if (qtdemux->segment.rate >= 0) {
5803     qtdemux->segment.position = position;
5804     gst_qtdemux_sync_streams (qtdemux);
5805   }
5806
5807   if (G_UNLIKELY (!stream->pad)) {
5808     GST_DEBUG_OBJECT (qtdemux, "No output pad for stream, ignoring");
5809     gst_buffer_unref (buf);
5810     goto exit;
5811   }
5812
5813   /* send out pending buffers */
5814   while (stream->buffers) {
5815     GstBuffer *buffer = (GstBuffer *) stream->buffers->data;
5816
5817     if (G_UNLIKELY (stream->discont)) {
5818       GST_LOG_OBJECT (qtdemux, "marking discont buffer");
5819       GST_BUFFER_FLAG_SET (buffer, GST_BUFFER_FLAG_DISCONT);
5820       stream->discont = FALSE;
5821     } else {
5822       GST_BUFFER_FLAG_UNSET (buf, GST_BUFFER_FLAG_DISCONT);
5823     }
5824
5825     if (stream->alignment > 1)
5826       buffer = gst_qtdemux_align_buffer (qtdemux, buffer, stream->alignment);
5827     gst_pad_push (stream->pad, buffer);
5828
5829     stream->buffers = g_slist_delete_link (stream->buffers, stream->buffers);
5830   }
5831
5832   /* we're going to modify the metadata */
5833   buf = gst_buffer_make_writable (buf);
5834
5835   if (G_UNLIKELY (stream->need_process))
5836     buf = gst_qtdemux_process_buffer (qtdemux, stream, buf);
5837
5838   if (!buf) {
5839     goto exit;
5840   }
5841
5842   GST_BUFFER_DTS (buf) = dts;
5843   GST_BUFFER_PTS (buf) = pts;
5844   GST_BUFFER_DURATION (buf) = duration;
5845   GST_BUFFER_OFFSET (buf) = -1;
5846   GST_BUFFER_OFFSET_END (buf) = -1;
5847
5848   if (G_UNLIKELY (CUR_STREAM (stream)->rgb8_palette))
5849     gst_buffer_append_memory (buf,
5850         gst_memory_ref (CUR_STREAM (stream)->rgb8_palette));
5851
5852   if (G_UNLIKELY (CUR_STREAM (stream)->padding)) {
5853     gst_buffer_resize (buf, CUR_STREAM (stream)->padding, -1);
5854   }
5855 #if 0
5856   if (G_UNLIKELY (qtdemux->element_index)) {
5857     GstClockTime stream_time;
5858
5859     stream_time =
5860         gst_segment_to_stream_time (&stream->segment, GST_FORMAT_TIME,
5861         timestamp);
5862     if (GST_CLOCK_TIME_IS_VALID (stream_time)) {
5863       GST_LOG_OBJECT (qtdemux,
5864           "adding association %" GST_TIME_FORMAT "-> %"
5865           G_GUINT64_FORMAT, GST_TIME_ARGS (stream_time), byte_position);
5866       gst_index_add_association (qtdemux->element_index,
5867           qtdemux->index_id,
5868           keyframe ? GST_ASSOCIATION_FLAG_KEY_UNIT :
5869           GST_ASSOCIATION_FLAG_DELTA_UNIT, GST_FORMAT_TIME, stream_time,
5870           GST_FORMAT_BYTES, byte_position, NULL);
5871     }
5872   }
5873 #endif
5874
5875   if (stream->need_clip)
5876     buf = gst_qtdemux_clip_buffer (qtdemux, stream, buf);
5877
5878   if (G_UNLIKELY (buf == NULL))
5879     goto exit;
5880
5881   if (G_UNLIKELY (stream->discont)) {
5882     GST_LOG_OBJECT (qtdemux, "marking discont buffer");
5883     GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_DISCONT);
5884     stream->discont = FALSE;
5885   } else {
5886     GST_BUFFER_FLAG_UNSET (buf, GST_BUFFER_FLAG_DISCONT);
5887   }
5888
5889   if (!keyframe) {
5890     GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_DELTA_UNIT);
5891     stream->on_keyframe = FALSE;
5892   } else {
5893     stream->on_keyframe = TRUE;
5894   }
5895
5896
5897   GST_LOG_OBJECT (qtdemux,
5898       "Pushing buffer with dts %" GST_TIME_FORMAT ", pts %" GST_TIME_FORMAT
5899       ", duration %" GST_TIME_FORMAT " on pad %s", GST_TIME_ARGS (dts),
5900       GST_TIME_ARGS (pts), GST_TIME_ARGS (duration),
5901       GST_PAD_NAME (stream->pad));
5902
5903   if (stream->protected && stream->protection_scheme_type == FOURCC_cenc) {
5904     GstStructure *crypto_info;
5905     QtDemuxCencSampleSetInfo *info =
5906         (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
5907     gint index;
5908     GstEvent *event;
5909
5910     while ((event = g_queue_pop_head (&stream->protection_scheme_event_queue))) {
5911       GST_TRACE_OBJECT (stream->pad, "pushing protection event: %"
5912           GST_PTR_FORMAT, event);
5913       gst_pad_push_event (stream->pad, event);
5914     }
5915
5916     if (info->crypto_info == NULL) {
5917       GST_DEBUG_OBJECT (qtdemux,
5918           "cenc metadata hasn't been parsed yet, pushing buffer as if it wasn't encrypted");
5919     } else {
5920       /* The end of the crypto_info array matches our n_samples position,
5921        * so count backward from there */
5922       index = stream->sample_index - stream->n_samples + info->crypto_info->len;
5923       if (G_LIKELY (index >= 0 && index < info->crypto_info->len)) {
5924         /* steal structure from array */
5925         crypto_info = g_ptr_array_index (info->crypto_info, index);
5926         g_ptr_array_index (info->crypto_info, index) = NULL;
5927         GST_LOG_OBJECT (qtdemux, "attaching cenc metadata [%u/%u]", index,
5928             info->crypto_info->len);
5929         if (!crypto_info || !gst_buffer_add_protection_meta (buf, crypto_info))
5930           GST_ERROR_OBJECT (qtdemux,
5931               "failed to attach cenc metadata to buffer");
5932       } else {
5933         GST_INFO_OBJECT (qtdemux, "No crypto info with index %d and sample %d",
5934             index, stream->sample_index);
5935       }
5936     }
5937   }
5938
5939   if (stream->alignment > 1)
5940     buf = gst_qtdemux_align_buffer (qtdemux, buf, stream->alignment);
5941
5942   ret = gst_pad_push (stream->pad, buf);
5943
5944   if (GST_CLOCK_TIME_IS_VALID (pts) && GST_CLOCK_TIME_IS_VALID (duration)) {
5945     /* mark position in stream, we'll need this to know when to send GAP event */
5946     stream->segment.position = pts + duration;
5947   }
5948
5949 exit:
5950   return ret;
5951 }
5952
5953 static const QtDemuxRandomAccessEntry *
5954 gst_qtdemux_stream_seek_fragment (GstQTDemux * qtdemux, QtDemuxStream * stream,
5955     GstClockTime pos, gboolean after)
5956 {
5957   QtDemuxRandomAccessEntry *entries = stream->ra_entries;
5958   guint n_entries = stream->n_ra_entries;
5959   guint i;
5960
5961   /* we assume the table is sorted */
5962   for (i = 0; i < n_entries; ++i) {
5963     if (entries[i].ts > pos)
5964       break;
5965   }
5966
5967   /* FIXME: maybe save first moof_offset somewhere instead, but for now it's
5968    * probably okay to assume that the index lists the very first fragment */
5969   if (i == 0)
5970     return &entries[0];
5971
5972   if (after)
5973     return &entries[i];
5974   else
5975     return &entries[i - 1];
5976 }
5977
5978 static gboolean
5979 gst_qtdemux_do_fragmented_seek (GstQTDemux * qtdemux)
5980 {
5981   const QtDemuxRandomAccessEntry *best_entry = NULL;
5982   gint i;
5983
5984   GST_OBJECT_LOCK (qtdemux);
5985
5986   g_assert (QTDEMUX_N_STREAMS (qtdemux) > 0);
5987
5988   /* first see if we can determine where to go to using mfra,
5989    * before we start clearing things */
5990   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
5991     const QtDemuxRandomAccessEntry *entry;
5992     QtDemuxStream *stream;
5993     gboolean is_audio_or_video;
5994
5995     stream = QTDEMUX_NTH_STREAM (qtdemux, i);
5996
5997     if (stream->ra_entries == NULL)
5998       continue;
5999
6000     if (stream->subtype == FOURCC_vide || stream->subtype == FOURCC_soun)
6001       is_audio_or_video = TRUE;
6002     else
6003       is_audio_or_video = FALSE;
6004
6005     entry =
6006         gst_qtdemux_stream_seek_fragment (qtdemux, stream,
6007         stream->time_position, !is_audio_or_video);
6008
6009     GST_INFO_OBJECT (stream->pad, "%" GST_TIME_FORMAT " at offset "
6010         "%" G_GUINT64_FORMAT, GST_TIME_ARGS (entry->ts), entry->moof_offset);
6011
6012     stream->pending_seek = entry;
6013
6014     /* decide position to jump to just based on audio/video tracks, not subs */
6015     if (!is_audio_or_video)
6016       continue;
6017
6018     if (best_entry == NULL || entry->moof_offset < best_entry->moof_offset)
6019       best_entry = entry;
6020   }
6021
6022   /* no luck, will handle seek otherwise */
6023   if (best_entry == NULL) {
6024     GST_OBJECT_UNLOCK (qtdemux);
6025     return FALSE;
6026   }
6027
6028   /* ok, now we can prepare for processing as of located moof */
6029   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
6030     QtDemuxStream *stream;
6031
6032     stream = QTDEMUX_NTH_STREAM (qtdemux, i);
6033
6034     g_free (stream->samples);
6035     stream->samples = NULL;
6036     stream->n_samples = 0;
6037     stream->stbl_index = -1;    /* no samples have yet been parsed */
6038     stream->sample_index = -1;
6039
6040     if (stream->protection_scheme_info) {
6041       /* Clear out any old cenc crypto info entries as we'll move to a new moof */
6042       if (stream->protection_scheme_type == FOURCC_cenc) {
6043         QtDemuxCencSampleSetInfo *info =
6044             (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
6045         if (info->crypto_info) {
6046           g_ptr_array_free (info->crypto_info, TRUE);
6047           info->crypto_info = NULL;
6048         }
6049       }
6050     }
6051   }
6052
6053   GST_INFO_OBJECT (qtdemux, "seek to %" GST_TIME_FORMAT ", best fragment "
6054       "moof offset: %" G_GUINT64_FORMAT ", ts %" GST_TIME_FORMAT,
6055       GST_TIME_ARGS (QTDEMUX_NTH_STREAM (qtdemux, 0)->time_position),
6056       best_entry->moof_offset, GST_TIME_ARGS (best_entry->ts));
6057
6058   qtdemux->moof_offset = best_entry->moof_offset;
6059
6060   qtdemux_add_fragmented_samples (qtdemux);
6061
6062   GST_OBJECT_UNLOCK (qtdemux);
6063   return TRUE;
6064 }
6065
6066 static GstFlowReturn
6067 gst_qtdemux_loop_state_movie (GstQTDemux * qtdemux)
6068 {
6069   GstFlowReturn ret = GST_FLOW_OK;
6070   GstBuffer *buf = NULL;
6071   QtDemuxStream *stream, *target_stream = NULL;
6072   GstClockTime min_time;
6073   guint64 offset = 0;
6074   GstClockTime dts = GST_CLOCK_TIME_NONE;
6075   GstClockTime pts = GST_CLOCK_TIME_NONE;
6076   GstClockTime duration = 0;
6077   gboolean keyframe = FALSE;
6078   guint sample_size = 0;
6079   gboolean empty = 0;
6080   guint size;
6081   gint i;
6082
6083   if (qtdemux->fragmented_seek_pending) {
6084     GST_INFO_OBJECT (qtdemux, "pending fragmented seek");
6085     if (gst_qtdemux_do_fragmented_seek (qtdemux)) {
6086       GST_INFO_OBJECT (qtdemux, "fragmented seek done!");
6087       qtdemux->fragmented_seek_pending = FALSE;
6088     } else {
6089       GST_INFO_OBJECT (qtdemux, "fragmented seek still pending");
6090     }
6091   }
6092
6093   /* Figure out the next stream sample to output, min_time is expressed in
6094    * global time and runs over the edit list segments. */
6095   min_time = G_MAXUINT64;
6096   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
6097     GstClockTime position;
6098
6099     stream = QTDEMUX_NTH_STREAM (qtdemux, i);
6100     position = stream->time_position;
6101
6102     /* position of -1 is EOS */
6103     if (position != GST_CLOCK_TIME_NONE && position < min_time) {
6104       min_time = position;
6105       target_stream = stream;
6106     }
6107   }
6108   /* all are EOS */
6109   if (G_UNLIKELY (target_stream == NULL)) {
6110     GST_DEBUG_OBJECT (qtdemux, "all streams are EOS");
6111     goto eos;
6112   }
6113
6114   /* check for segment end */
6115   if (G_UNLIKELY (qtdemux->segment.stop != -1
6116           && ((qtdemux->segment.rate >= 0 && qtdemux->segment.stop <= min_time)
6117               || (qtdemux->segment.rate < 0
6118                   && qtdemux->segment.start > min_time))
6119           && target_stream->on_keyframe)) {
6120     GST_DEBUG_OBJECT (qtdemux, "we reached the end of our segment.");
6121     target_stream->time_position = GST_CLOCK_TIME_NONE;
6122     goto eos_stream;
6123   }
6124
6125   /* gap events for subtitle streams */
6126   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
6127     stream = QTDEMUX_NTH_STREAM (qtdemux, i);
6128     if (stream->pad && (stream->subtype == FOURCC_subp
6129             || stream->subtype == FOURCC_text
6130             || stream->subtype == FOURCC_sbtl)) {
6131       /* send one second gap events until the stream catches up */
6132       /* gaps can only be sent after segment is activated (segment.stop is no longer -1) */
6133       while (GST_CLOCK_TIME_IS_VALID (stream->segment.stop) &&
6134           GST_CLOCK_TIME_IS_VALID (stream->segment.position) &&
6135           stream->segment.position + GST_SECOND < min_time) {
6136         GstEvent *gap =
6137             gst_event_new_gap (stream->segment.position, GST_SECOND);
6138         gst_pad_push_event (stream->pad, gap);
6139         stream->segment.position += GST_SECOND;
6140       }
6141     }
6142   }
6143
6144   stream = target_stream;
6145   /* fetch info for the current sample of this stream */
6146   if (G_UNLIKELY (!gst_qtdemux_prepare_current_sample (qtdemux, stream, &empty,
6147               &offset, &sample_size, &dts, &pts, &duration, &keyframe)))
6148     goto eos_stream;
6149
6150   gst_qtdemux_stream_check_and_change_stsd_index (qtdemux, stream);
6151   if (stream->new_caps) {
6152     gst_qtdemux_configure_stream (qtdemux, stream);
6153     qtdemux_do_allocation (stream, qtdemux);
6154   }
6155
6156   /* If we're doing a keyframe-only trickmode, only push keyframes on video streams */
6157   if (G_UNLIKELY (qtdemux->
6158           segment.flags & GST_SEGMENT_FLAG_TRICKMODE_KEY_UNITS)) {
6159     if (stream->subtype == FOURCC_vide && !keyframe) {
6160       GST_LOG_OBJECT (qtdemux, "Skipping non-keyframe on track-id %u",
6161           stream->track_id);
6162       goto next;
6163     }
6164   }
6165
6166   GST_DEBUG_OBJECT (qtdemux,
6167       "pushing from track-id %u, empty %d offset %" G_GUINT64_FORMAT
6168       ", size %d, dts=%" GST_TIME_FORMAT ", pts=%" GST_TIME_FORMAT
6169       ", duration %" GST_TIME_FORMAT, stream->track_id, empty, offset,
6170       sample_size, GST_TIME_ARGS (dts), GST_TIME_ARGS (pts),
6171       GST_TIME_ARGS (duration));
6172
6173   if (G_UNLIKELY (empty)) {
6174     /* empty segment, push a gap if there's a second or more
6175      * difference and move to the next one */
6176     if ((pts + duration - stream->segment.position) >= GST_SECOND)
6177       gst_pad_push_event (stream->pad, gst_event_new_gap (pts, duration));
6178     stream->segment.position = pts + duration;
6179     goto next;
6180   }
6181
6182   /* hmm, empty sample, skip and move to next sample */
6183   if (G_UNLIKELY (sample_size <= 0))
6184     goto next;
6185
6186   /* last pushed sample was out of boundary, goto next sample */
6187   if (G_UNLIKELY (GST_PAD_LAST_FLOW_RETURN (stream->pad) == GST_FLOW_EOS))
6188     goto next;
6189
6190   if (stream->max_buffer_size == 0 || sample_size <= stream->max_buffer_size) {
6191     size = sample_size;
6192   } else {
6193     GST_DEBUG_OBJECT (qtdemux,
6194         "size %d larger than stream max_buffer_size %d, trimming",
6195         sample_size, stream->max_buffer_size);
6196     size =
6197         MIN (sample_size - stream->offset_in_sample, stream->max_buffer_size);
6198   }
6199
6200   if (qtdemux->cenc_aux_info_offset > 0) {
6201     GstMapInfo map;
6202     GstByteReader br;
6203     GstBuffer *aux_info = NULL;
6204
6205     /* pull the data stored before the sample */
6206     ret =
6207         gst_qtdemux_pull_atom (qtdemux, qtdemux->offset,
6208         offset + stream->offset_in_sample - qtdemux->offset, &aux_info);
6209     if (G_UNLIKELY (ret != GST_FLOW_OK))
6210       goto beach;
6211     gst_buffer_map (aux_info, &map, GST_MAP_READ);
6212     GST_DEBUG_OBJECT (qtdemux, "parsing cenc auxiliary info");
6213     gst_byte_reader_init (&br, map.data + 8, map.size);
6214     if (!qtdemux_parse_cenc_aux_info (qtdemux, stream, &br,
6215             qtdemux->cenc_aux_info_sizes, qtdemux->cenc_aux_sample_count)) {
6216       GST_ERROR_OBJECT (qtdemux, "failed to parse cenc auxiliary info");
6217       gst_buffer_unmap (aux_info, &map);
6218       gst_buffer_unref (aux_info);
6219       ret = GST_FLOW_ERROR;
6220       goto beach;
6221     }
6222     gst_buffer_unmap (aux_info, &map);
6223     gst_buffer_unref (aux_info);
6224   }
6225
6226   GST_LOG_OBJECT (qtdemux, "reading %d bytes @ %" G_GUINT64_FORMAT, size,
6227       offset);
6228
6229   if (stream->use_allocator) {
6230     /* if we have a per-stream allocator, use it */
6231     buf = gst_buffer_new_allocate (stream->allocator, size, &stream->params);
6232   }
6233
6234   ret = gst_qtdemux_pull_atom (qtdemux, offset + stream->offset_in_sample,
6235       size, &buf);
6236   if (G_UNLIKELY (ret != GST_FLOW_OK))
6237     goto beach;
6238
6239   if (size != sample_size) {
6240     pts += gst_util_uint64_scale_int (GST_SECOND,
6241         stream->offset_in_sample / CUR_STREAM (stream)->bytes_per_frame,
6242         stream->timescale);
6243     dts +=
6244         gst_util_uint64_scale_int (GST_SECOND,
6245         stream->offset_in_sample / CUR_STREAM (stream)->bytes_per_frame,
6246         stream->timescale);
6247     duration =
6248         gst_util_uint64_scale_int (GST_SECOND,
6249         size / CUR_STREAM (stream)->bytes_per_frame, stream->timescale);
6250   }
6251
6252   ret = gst_qtdemux_decorate_and_push_buffer (qtdemux, stream, buf,
6253       dts, pts, duration, keyframe, min_time, offset);
6254
6255   if (size != sample_size) {
6256     QtDemuxSample *sample = &stream->samples[stream->sample_index];
6257     QtDemuxSegment *segment = &stream->segments[stream->segment_index];
6258
6259     GstClockTime time_position = QTSTREAMTIME_TO_GSTTIME (stream,
6260         sample->timestamp +
6261         stream->offset_in_sample / CUR_STREAM (stream)->bytes_per_frame);
6262     if (time_position >= segment->media_start) {
6263       /* inside the segment, update time_position, looks very familiar to
6264        * GStreamer segments, doesn't it? */
6265       stream->time_position = (time_position - segment->media_start) +
6266           segment->time;
6267     } else {
6268       /* not yet in segment, time does not yet increment. This means
6269        * that we are still prerolling keyframes to the decoder so it can
6270        * decode the first sample of the segment. */
6271       stream->time_position = segment->time;
6272     }
6273   }
6274
6275   /* combine flows */
6276   ret = gst_qtdemux_combine_flows (qtdemux, stream, ret);
6277   /* ignore unlinked, we will not push on the pad anymore and we will EOS when
6278    * we have no more data for the pad to push */
6279   if (ret == GST_FLOW_EOS)
6280     ret = GST_FLOW_OK;
6281
6282   stream->offset_in_sample += size;
6283   if (stream->offset_in_sample >= sample_size) {
6284     gst_qtdemux_advance_sample (qtdemux, stream);
6285   }
6286   goto beach;
6287
6288 next:
6289   gst_qtdemux_advance_sample (qtdemux, stream);
6290
6291 beach:
6292   return ret;
6293
6294   /* special cases */
6295 eos:
6296   {
6297     GST_DEBUG_OBJECT (qtdemux, "No samples left for any streams - EOS");
6298     ret = GST_FLOW_EOS;
6299     goto beach;
6300   }
6301 eos_stream:
6302   {
6303     GST_DEBUG_OBJECT (qtdemux, "No samples left for stream");
6304     /* EOS will be raised if all are EOS */
6305     ret = GST_FLOW_OK;
6306     goto beach;
6307   }
6308 }
6309
6310 static void
6311 gst_qtdemux_loop (GstPad * pad)
6312 {
6313   GstQTDemux *qtdemux;
6314   guint64 cur_offset;
6315   GstFlowReturn ret;
6316
6317   qtdemux = GST_QTDEMUX (gst_pad_get_parent (pad));
6318
6319   cur_offset = qtdemux->offset;
6320   GST_LOG_OBJECT (qtdemux, "loop at position %" G_GUINT64_FORMAT ", state %s",
6321       cur_offset, qt_demux_state_string (qtdemux->state));
6322
6323   switch (qtdemux->state) {
6324     case QTDEMUX_STATE_INITIAL:
6325     case QTDEMUX_STATE_HEADER:
6326       ret = gst_qtdemux_loop_state_header (qtdemux);
6327       break;
6328     case QTDEMUX_STATE_MOVIE:
6329       ret = gst_qtdemux_loop_state_movie (qtdemux);
6330       if (qtdemux->segment.rate < 0 && ret == GST_FLOW_EOS) {
6331         ret = gst_qtdemux_seek_to_previous_keyframe (qtdemux);
6332       }
6333       break;
6334     default:
6335       /* ouch */
6336       goto invalid_state;
6337   }
6338
6339   /* if something went wrong, pause */
6340   if (ret != GST_FLOW_OK)
6341     goto pause;
6342
6343 done:
6344   gst_object_unref (qtdemux);
6345   return;
6346
6347   /* ERRORS */
6348 invalid_state:
6349   {
6350     GST_ELEMENT_ERROR (qtdemux, STREAM, FAILED,
6351         (NULL), ("streaming stopped, invalid state"));
6352     gst_pad_pause_task (pad);
6353     gst_qtdemux_push_event (qtdemux, gst_event_new_eos ());
6354     goto done;
6355   }
6356 pause:
6357   {
6358     const gchar *reason = gst_flow_get_name (ret);
6359
6360     GST_LOG_OBJECT (qtdemux, "pausing task, reason %s", reason);
6361
6362     gst_pad_pause_task (pad);
6363
6364     /* fatal errors need special actions */
6365     /* check EOS */
6366     if (ret == GST_FLOW_EOS) {
6367       if (QTDEMUX_N_STREAMS (qtdemux) == 0) {
6368         /* we have no streams, post an error */
6369         gst_qtdemux_post_no_playable_stream_error (qtdemux);
6370       }
6371       if (qtdemux->segment.flags & GST_SEEK_FLAG_SEGMENT) {
6372         gint64 stop;
6373
6374         if ((stop = qtdemux->segment.stop) == -1)
6375           stop = qtdemux->segment.duration;
6376
6377         if (qtdemux->segment.rate >= 0) {
6378           GstMessage *message;
6379           GstEvent *event;
6380
6381           GST_LOG_OBJECT (qtdemux, "Sending segment done, at end of segment");
6382           message = gst_message_new_segment_done (GST_OBJECT_CAST (qtdemux),
6383               GST_FORMAT_TIME, stop);
6384           event = gst_event_new_segment_done (GST_FORMAT_TIME, stop);
6385           if (qtdemux->segment_seqnum != GST_SEQNUM_INVALID) {
6386             gst_message_set_seqnum (message, qtdemux->segment_seqnum);
6387             gst_event_set_seqnum (event, qtdemux->segment_seqnum);
6388           }
6389           gst_element_post_message (GST_ELEMENT_CAST (qtdemux), message);
6390           gst_qtdemux_push_event (qtdemux, event);
6391         } else {
6392           GstMessage *message;
6393           GstEvent *event;
6394
6395           /*  For Reverse Playback */
6396           GST_LOG_OBJECT (qtdemux, "Sending segment done, at start of segment");
6397           message = gst_message_new_segment_done (GST_OBJECT_CAST (qtdemux),
6398               GST_FORMAT_TIME, qtdemux->segment.start);
6399           event = gst_event_new_segment_done (GST_FORMAT_TIME,
6400               qtdemux->segment.start);
6401           if (qtdemux->segment_seqnum != GST_SEQNUM_INVALID) {
6402             gst_message_set_seqnum (message, qtdemux->segment_seqnum);
6403             gst_event_set_seqnum (event, qtdemux->segment_seqnum);
6404           }
6405           gst_element_post_message (GST_ELEMENT_CAST (qtdemux), message);
6406           gst_qtdemux_push_event (qtdemux, event);
6407         }
6408       } else {
6409         GstEvent *event;
6410
6411         GST_LOG_OBJECT (qtdemux, "Sending EOS at end of segment");
6412         event = gst_event_new_eos ();
6413         if (qtdemux->segment_seqnum != GST_SEQNUM_INVALID)
6414           gst_event_set_seqnum (event, qtdemux->segment_seqnum);
6415         gst_qtdemux_push_event (qtdemux, event);
6416       }
6417     } else if (ret == GST_FLOW_NOT_LINKED || ret < GST_FLOW_EOS) {
6418       GST_ELEMENT_FLOW_ERROR (qtdemux, ret);
6419       gst_qtdemux_push_event (qtdemux, gst_event_new_eos ());
6420     }
6421     goto done;
6422   }
6423 }
6424
6425 /*
6426  * has_next_entry
6427  *
6428  * Returns if there are samples to be played.
6429  */
6430 static gboolean
6431 has_next_entry (GstQTDemux * demux)
6432 {
6433   QtDemuxStream *stream;
6434   gint i;
6435
6436   GST_DEBUG_OBJECT (demux, "Checking if there are samples not played yet");
6437
6438   for (i = 0; i < QTDEMUX_N_STREAMS (demux); i++) {
6439     stream = QTDEMUX_NTH_STREAM (demux, i);
6440
6441     if (stream->sample_index == -1) {
6442       stream->sample_index = 0;
6443       stream->offset_in_sample = 0;
6444     }
6445
6446     if (stream->sample_index >= stream->n_samples) {
6447       GST_LOG_OBJECT (demux, "track-id %u samples exhausted", stream->track_id);
6448       continue;
6449     }
6450     GST_DEBUG_OBJECT (demux, "Found a sample");
6451     return TRUE;
6452   }
6453
6454   GST_DEBUG_OBJECT (demux, "There wasn't any next sample");
6455   return FALSE;
6456 }
6457
6458 /*
6459  * next_entry_size
6460  *
6461  * Returns the size of the first entry at the current offset.
6462  * If -1, there are none (which means EOS or empty file).
6463  */
6464 static guint64
6465 next_entry_size (GstQTDemux * demux)
6466 {
6467   QtDemuxStream *stream, *target_stream = NULL;
6468   guint64 smalloffs = (guint64) - 1;
6469   QtDemuxSample *sample;
6470   gint i;
6471
6472   GST_LOG_OBJECT (demux, "Finding entry at offset %" G_GUINT64_FORMAT,
6473       demux->offset);
6474
6475   for (i = 0; i < QTDEMUX_N_STREAMS (demux); i++) {
6476     stream = QTDEMUX_NTH_STREAM (demux, i);
6477
6478     if (stream->sample_index == -1) {
6479       stream->sample_index = 0;
6480       stream->offset_in_sample = 0;
6481     }
6482
6483     if (stream->sample_index >= stream->n_samples) {
6484       GST_LOG_OBJECT (demux, "track-id %u samples exhausted", stream->track_id);
6485       continue;
6486     }
6487
6488     if (!qtdemux_parse_samples (demux, stream, stream->sample_index)) {
6489       GST_LOG_OBJECT (demux, "Parsing of index %u from stbl atom failed!",
6490           stream->sample_index);
6491       return -1;
6492     }
6493
6494     sample = &stream->samples[stream->sample_index];
6495
6496     GST_LOG_OBJECT (demux,
6497         "Checking track-id %u (sample_index:%d / offset:%" G_GUINT64_FORMAT
6498         " / size:%" G_GUINT32_FORMAT ")", stream->track_id,
6499         stream->sample_index, sample->offset, sample->size);
6500
6501     if (((smalloffs == -1)
6502             || (sample->offset < smalloffs)) && (sample->size)) {
6503       smalloffs = sample->offset;
6504       target_stream = stream;
6505     }
6506   }
6507
6508   if (!target_stream)
6509     return -1;
6510
6511   GST_LOG_OBJECT (demux,
6512       "track-id %u offset %" G_GUINT64_FORMAT " demux->offset :%"
6513       G_GUINT64_FORMAT, target_stream->track_id, smalloffs, demux->offset);
6514
6515   stream = target_stream;
6516   sample = &stream->samples[stream->sample_index];
6517
6518   if (sample->offset >= demux->offset) {
6519     demux->todrop = sample->offset - demux->offset;
6520     return sample->size + demux->todrop;
6521   }
6522
6523   GST_DEBUG_OBJECT (demux,
6524       "There wasn't any entry at offset %" G_GUINT64_FORMAT, demux->offset);
6525   return -1;
6526 }
6527
6528 static void
6529 gst_qtdemux_post_progress (GstQTDemux * demux, gint num, gint denom)
6530 {
6531   gint perc = (gint) ((gdouble) num * 100.0 / (gdouble) denom);
6532
6533   gst_element_post_message (GST_ELEMENT_CAST (demux),
6534       gst_message_new_element (GST_OBJECT_CAST (demux),
6535           gst_structure_new ("progress", "percent", G_TYPE_INT, perc, NULL)));
6536 }
6537
6538 static gboolean
6539 qtdemux_seek_offset (GstQTDemux * demux, guint64 offset)
6540 {
6541   GstEvent *event;
6542   gboolean res = 0;
6543
6544   GST_DEBUG_OBJECT (demux, "Seeking to %" G_GUINT64_FORMAT, offset);
6545
6546   event =
6547       gst_event_new_seek (1.0, GST_FORMAT_BYTES,
6548       GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_ACCURATE, GST_SEEK_TYPE_SET, offset,
6549       GST_SEEK_TYPE_NONE, -1);
6550
6551   /* store seqnum to drop flush events, they don't need to reach downstream */
6552   demux->offset_seek_seqnum = gst_event_get_seqnum (event);
6553   res = gst_pad_push_event (demux->sinkpad, event);
6554   demux->offset_seek_seqnum = GST_SEQNUM_INVALID;
6555
6556   return res;
6557 }
6558
6559 /* check for seekable upstream, above and beyond a mere query */
6560 static void
6561 gst_qtdemux_check_seekability (GstQTDemux * demux)
6562 {
6563   GstQuery *query;
6564   gboolean seekable = FALSE;
6565   gint64 start = -1, stop = -1;
6566
6567   if (demux->upstream_size)
6568     return;
6569
6570   if (demux->upstream_format_is_time)
6571     return;
6572
6573   query = gst_query_new_seeking (GST_FORMAT_BYTES);
6574   if (!gst_pad_peer_query (demux->sinkpad, query)) {
6575     GST_DEBUG_OBJECT (demux, "seeking query failed");
6576     goto done;
6577   }
6578
6579   gst_query_parse_seeking (query, NULL, &seekable, &start, &stop);
6580
6581   /* try harder to query upstream size if we didn't get it the first time */
6582   if (seekable && stop == -1) {
6583     GST_DEBUG_OBJECT (demux, "doing duration query to fix up unset stop");
6584     gst_pad_peer_query_duration (demux->sinkpad, GST_FORMAT_BYTES, &stop);
6585   }
6586
6587   /* if upstream doesn't know the size, it's likely that it's not seekable in
6588    * practice even if it technically may be seekable */
6589   if (seekable && (start != 0 || stop <= start)) {
6590     GST_DEBUG_OBJECT (demux, "seekable but unknown start/stop -> disable");
6591     seekable = FALSE;
6592   }
6593
6594 done:
6595   gst_query_unref (query);
6596
6597   GST_DEBUG_OBJECT (demux, "seekable: %d (%" G_GUINT64_FORMAT " - %"
6598       G_GUINT64_FORMAT ")", seekable, start, stop);
6599   demux->upstream_seekable = seekable;
6600   demux->upstream_size = seekable ? stop : -1;
6601 }
6602
6603 static void
6604 gst_qtdemux_drop_data (GstQTDemux * demux, gint bytes)
6605 {
6606   g_return_if_fail (bytes <= demux->todrop);
6607
6608   GST_LOG_OBJECT (demux, "Dropping %d bytes", bytes);
6609   gst_adapter_flush (demux->adapter, bytes);
6610   demux->neededbytes -= bytes;
6611   demux->offset += bytes;
6612   demux->todrop -= bytes;
6613 }
6614
6615 /* PUSH-MODE only: Send a segment, if not done already. */
6616 static void
6617 gst_qtdemux_check_send_pending_segment (GstQTDemux * demux)
6618 {
6619   if (G_UNLIKELY (demux->need_segment)) {
6620     gint i;
6621
6622     if (!demux->upstream_format_is_time) {
6623       gst_qtdemux_map_and_push_segments (demux, &demux->segment);
6624     } else {
6625       GstEvent *segment_event;
6626       segment_event = gst_event_new_segment (&demux->segment);
6627       if (demux->segment_seqnum != GST_SEQNUM_INVALID)
6628         gst_event_set_seqnum (segment_event, demux->segment_seqnum);
6629       gst_qtdemux_push_event (demux, segment_event);
6630     }
6631
6632     demux->need_segment = FALSE;
6633
6634     /* clear to send tags on all streams */
6635     for (i = 0; i < QTDEMUX_N_STREAMS (demux); i++) {
6636       QtDemuxStream *stream = QTDEMUX_NTH_STREAM (demux, i);
6637       gst_qtdemux_push_tags (demux, stream);
6638       if (CUR_STREAM (stream)->sparse) {
6639         GST_INFO_OBJECT (demux, "Sending gap event on stream %d", i);
6640         gst_pad_push_event (stream->pad,
6641             gst_event_new_gap (stream->segment.position, GST_CLOCK_TIME_NONE));
6642       }
6643     }
6644   }
6645 }
6646
6647 /* Used for push mode only. */
6648 static void
6649 gst_qtdemux_send_gap_for_segment (GstQTDemux * demux,
6650     QtDemuxStream * stream, gint segment_index, GstClockTime pos)
6651 {
6652   GstClockTime ts, dur;
6653
6654   ts = pos;
6655   dur =
6656       stream->segments[segment_index].duration - (pos -
6657       stream->segments[segment_index].time);
6658   stream->time_position += dur;
6659
6660   /* Only gaps with a duration of at least one second are propagated.
6661    * Same workaround as in pull mode.
6662    * (See 2e45926a96ec5298c6ef29bf912e5e6a06dc3e0e) */
6663   if (dur >= GST_SECOND) {
6664     GstEvent *gap;
6665     gap = gst_event_new_gap (ts, dur);
6666
6667     GST_DEBUG_OBJECT (stream->pad, "Pushing gap for empty "
6668         "segment: %" GST_PTR_FORMAT, gap);
6669     gst_pad_push_event (stream->pad, gap);
6670   }
6671 }
6672
6673 static GstFlowReturn
6674 gst_qtdemux_chain (GstPad * sinkpad, GstObject * parent, GstBuffer * inbuf)
6675 {
6676   GstQTDemux *demux;
6677
6678   demux = GST_QTDEMUX (parent);
6679
6680   GST_DEBUG_OBJECT (demux,
6681       "Received buffer pts:%" GST_TIME_FORMAT " dts:%" GST_TIME_FORMAT
6682       " offset:%" G_GUINT64_FORMAT " size:%" G_GSIZE_FORMAT " demux offset:%"
6683       G_GUINT64_FORMAT, GST_TIME_ARGS (GST_BUFFER_PTS (inbuf)),
6684       GST_TIME_ARGS (GST_BUFFER_DTS (inbuf)), GST_BUFFER_OFFSET (inbuf),
6685       gst_buffer_get_size (inbuf), demux->offset);
6686
6687   if (GST_BUFFER_FLAG_IS_SET (inbuf, GST_BUFFER_FLAG_DISCONT)) {
6688     gboolean is_gap_input = FALSE;
6689     gint i;
6690
6691     GST_DEBUG_OBJECT (demux, "Got DISCONT, marking all streams as DISCONT");
6692
6693     for (i = 0; i < QTDEMUX_N_STREAMS (demux); i++) {
6694       QTDEMUX_NTH_STREAM (demux, i)->discont = TRUE;
6695     }
6696
6697     /* Check if we can land back on our feet in the case where upstream is
6698      * handling the seeking/pushing of samples with gaps in between (like
6699      * in the case of trick-mode DASH for example) */
6700     if (demux->upstream_format_is_time
6701         && GST_BUFFER_OFFSET (inbuf) != GST_BUFFER_OFFSET_NONE) {
6702       for (i = 0; i < QTDEMUX_N_STREAMS (demux); i++) {
6703         guint32 res;
6704         QtDemuxStream *stream = QTDEMUX_NTH_STREAM (demux, i);
6705         GST_LOG_OBJECT (demux,
6706             "track-id #%u , checking if offset %" G_GUINT64_FORMAT
6707             " is a sample start", stream->track_id, GST_BUFFER_OFFSET (inbuf));
6708         res =
6709             gst_qtdemux_find_index_for_given_media_offset_linear (demux,
6710             stream, GST_BUFFER_OFFSET (inbuf));
6711         if (res != -1) {
6712           QtDemuxSample *sample = &stream->samples[res];
6713           GST_LOG_OBJECT (demux,
6714               "Checking if sample %d from track-id %u is valid (offset:%"
6715               G_GUINT64_FORMAT " size:%" G_GUINT32_FORMAT ")", res,
6716               stream->track_id, sample->offset, sample->size);
6717           if (sample->offset == GST_BUFFER_OFFSET (inbuf)) {
6718             GST_LOG_OBJECT (demux,
6719                 "new buffer corresponds to a valid sample : %" G_GUINT32_FORMAT,
6720                 res);
6721             is_gap_input = TRUE;
6722             /* We can go back to standard playback mode */
6723             demux->state = QTDEMUX_STATE_MOVIE;
6724             /* Remember which sample this stream is at */
6725             stream->sample_index = res;
6726             /* Finally update all push-based values to the expected values */
6727             demux->neededbytes = stream->samples[res].size;
6728             demux->offset = GST_BUFFER_OFFSET (inbuf);
6729             demux->mdatleft =
6730                 demux->mdatsize - demux->offset + demux->mdatoffset;
6731             demux->todrop = 0;
6732           }
6733         }
6734       }
6735       if (!is_gap_input) {
6736         GST_DEBUG_OBJECT (demux, "Resetting, actual DISCONT");
6737         /* Reset state if it's a real discont */
6738         demux->neededbytes = 16;
6739         demux->state = QTDEMUX_STATE_INITIAL;
6740         demux->offset = GST_BUFFER_OFFSET (inbuf);
6741         gst_adapter_clear (demux->adapter);
6742       }
6743     }
6744     /* Reverse fragmented playback, need to flush all we have before
6745      * consuming a new fragment.
6746      * The samples array have the timestamps calculated by accumulating the
6747      * durations but this won't work for reverse playback of fragments as
6748      * the timestamps of a subsequent fragment should be smaller than the
6749      * previously received one. */
6750     if (!is_gap_input && demux->fragmented && demux->segment.rate < 0) {
6751       gst_qtdemux_process_adapter (demux, TRUE);
6752       g_ptr_array_foreach (demux->active_streams,
6753           (GFunc) gst_qtdemux_stream_flush_samples_data, NULL);
6754     }
6755   }
6756
6757   gst_adapter_push (demux->adapter, inbuf);
6758
6759   GST_DEBUG_OBJECT (demux,
6760       "pushing in inbuf %p, neededbytes:%u, available:%" G_GSIZE_FORMAT, inbuf,
6761       demux->neededbytes, gst_adapter_available (demux->adapter));
6762
6763   return gst_qtdemux_process_adapter (demux, FALSE);
6764 }
6765
6766 static GstFlowReturn
6767 gst_qtdemux_process_adapter (GstQTDemux * demux, gboolean force)
6768 {
6769   GstFlowReturn ret = GST_FLOW_OK;
6770
6771   /* we never really mean to buffer that much */
6772   if (demux->neededbytes == -1) {
6773     goto eos;
6774   }
6775
6776   while (((gst_adapter_available (demux->adapter)) >= demux->neededbytes) &&
6777       (ret == GST_FLOW_OK || (ret == GST_FLOW_NOT_LINKED && force))) {
6778
6779 #ifndef GST_DISABLE_GST_DEBUG
6780     {
6781       guint64 discont_offset, distance_from_discont;
6782
6783       discont_offset = gst_adapter_offset_at_discont (demux->adapter);
6784       distance_from_discont =
6785           gst_adapter_distance_from_discont (demux->adapter);
6786
6787       GST_DEBUG_OBJECT (demux,
6788           "state:%s , demux->neededbytes:%d, demux->offset:%" G_GUINT64_FORMAT
6789           " adapter offset :%" G_GUINT64_FORMAT " (+ %" G_GUINT64_FORMAT
6790           " bytes)", qt_demux_state_string (demux->state), demux->neededbytes,
6791           demux->offset, discont_offset, distance_from_discont);
6792     }
6793 #endif
6794
6795     switch (demux->state) {
6796       case QTDEMUX_STATE_INITIAL:{
6797         const guint8 *data;
6798         guint32 fourcc;
6799         guint64 size;
6800
6801         gst_qtdemux_check_seekability (demux);
6802
6803         data = gst_adapter_map (demux->adapter, demux->neededbytes);
6804
6805         /* get fourcc/length, set neededbytes */
6806         extract_initial_length_and_fourcc ((guint8 *) data, demux->neededbytes,
6807             &size, &fourcc);
6808         gst_adapter_unmap (demux->adapter);
6809         data = NULL;
6810         GST_DEBUG_OBJECT (demux, "Peeking found [%" GST_FOURCC_FORMAT "] "
6811             "size: %" G_GUINT64_FORMAT, GST_FOURCC_ARGS (fourcc), size);
6812         if (size == 0) {
6813           GST_ELEMENT_ERROR (demux, STREAM, DEMUX,
6814               (_("This file is invalid and cannot be played.")),
6815               ("initial atom '%" GST_FOURCC_FORMAT "' has empty length",
6816                   GST_FOURCC_ARGS (fourcc)));
6817           ret = GST_FLOW_ERROR;
6818           break;
6819         }
6820         if (fourcc == FOURCC_mdat) {
6821           gint next_entry = next_entry_size (demux);
6822           if (QTDEMUX_N_STREAMS (demux) > 0 && (next_entry != -1
6823                   || !demux->fragmented)) {
6824             /* we have the headers, start playback */
6825             demux->state = QTDEMUX_STATE_MOVIE;
6826             demux->neededbytes = next_entry;
6827             demux->mdatleft = size;
6828             demux->mdatsize = demux->mdatleft;
6829           } else {
6830             /* no headers yet, try to get them */
6831             guint bs;
6832             gboolean res;
6833             guint64 old, target;
6834
6835           buffer_data:
6836             old = demux->offset;
6837             target = old + size;
6838
6839             /* try to jump over the atom with a seek */
6840             /* only bother if it seems worth doing so,
6841              * and avoids possible upstream/server problems */
6842             if (demux->upstream_seekable &&
6843                 demux->upstream_size > 4 * (1 << 20)) {
6844               res = qtdemux_seek_offset (demux, target);
6845             } else {
6846               GST_DEBUG_OBJECT (demux, "skipping seek");
6847               res = FALSE;
6848             }
6849
6850             if (res) {
6851               GST_DEBUG_OBJECT (demux, "seek success");
6852               /* remember the offset fo the first mdat so we can seek back to it
6853                * after we have the headers */
6854               if (fourcc == FOURCC_mdat && demux->first_mdat == -1) {
6855                 demux->first_mdat = old;
6856                 GST_DEBUG_OBJECT (demux, "first mdat at %" G_GUINT64_FORMAT,
6857                     demux->first_mdat);
6858               }
6859               /* seek worked, continue reading */
6860               demux->offset = target;
6861               demux->neededbytes = 16;
6862               demux->state = QTDEMUX_STATE_INITIAL;
6863             } else {
6864               /* seek failed, need to buffer */
6865               demux->offset = old;
6866               GST_DEBUG_OBJECT (demux, "seek failed/skipped");
6867               /* there may be multiple mdat (or alike) buffers */
6868               /* sanity check */
6869               if (demux->mdatbuffer)
6870                 bs = gst_buffer_get_size (demux->mdatbuffer);
6871               else
6872                 bs = 0;
6873               if (size + bs > 10 * (1 << 20))
6874                 goto no_moov;
6875               demux->state = QTDEMUX_STATE_BUFFER_MDAT;
6876               demux->neededbytes = size;
6877               if (!demux->mdatbuffer)
6878                 demux->mdatoffset = demux->offset;
6879             }
6880           }
6881         } else if (G_UNLIKELY (size > QTDEMUX_MAX_ATOM_SIZE)) {
6882           GST_ELEMENT_ERROR (demux, STREAM, DEMUX,
6883               (_("This file is invalid and cannot be played.")),
6884               ("atom %" GST_FOURCC_FORMAT " has bogus size %" G_GUINT64_FORMAT,
6885                   GST_FOURCC_ARGS (fourcc), size));
6886           ret = GST_FLOW_ERROR;
6887           break;
6888         } else {
6889           /* this means we already started buffering and still no moov header,
6890            * let's continue buffering everything till we get moov */
6891           if (demux->mdatbuffer && !(fourcc == FOURCC_moov
6892                   || fourcc == FOURCC_moof))
6893             goto buffer_data;
6894           demux->neededbytes = size;
6895           demux->state = QTDEMUX_STATE_HEADER;
6896         }
6897         break;
6898       }
6899       case QTDEMUX_STATE_HEADER:{
6900         const guint8 *data;
6901         guint32 fourcc;
6902
6903         GST_DEBUG_OBJECT (demux, "In header");
6904
6905         data = gst_adapter_map (demux->adapter, demux->neededbytes);
6906
6907         /* parse the header */
6908         extract_initial_length_and_fourcc (data, demux->neededbytes, NULL,
6909             &fourcc);
6910         if (fourcc == FOURCC_moov) {
6911           /* in usual fragmented setup we could try to scan for more
6912            * and end up at the the moov (after mdat) again */
6913           if (demux->got_moov && QTDEMUX_N_STREAMS (demux) > 0 &&
6914               (!demux->fragmented
6915                   || demux->last_moov_offset == demux->offset)) {
6916             GST_DEBUG_OBJECT (demux,
6917                 "Skipping moov atom as we have (this) one already");
6918           } else {
6919             GST_DEBUG_OBJECT (demux, "Parsing [moov]");
6920
6921             if (demux->got_moov && demux->fragmented) {
6922               GST_DEBUG_OBJECT (demux,
6923                   "Got a second moov, clean up data from old one");
6924               if (demux->moov_node_compressed) {
6925                 g_node_destroy (demux->moov_node_compressed);
6926                 if (demux->moov_node)
6927                   g_free (demux->moov_node->data);
6928               }
6929               demux->moov_node_compressed = NULL;
6930               if (demux->moov_node)
6931                 g_node_destroy (demux->moov_node);
6932               demux->moov_node = NULL;
6933             }
6934
6935             demux->last_moov_offset = demux->offset;
6936
6937             /* Update streams with new moov */
6938             gst_qtdemux_stream_concat (demux,
6939                 demux->old_streams, demux->active_streams);
6940
6941             qtdemux_parse_moov (demux, data, demux->neededbytes);
6942             qtdemux_node_dump (demux, demux->moov_node);
6943             qtdemux_parse_tree (demux);
6944             qtdemux_prepare_streams (demux);
6945             QTDEMUX_EXPOSE_LOCK (demux);
6946             qtdemux_expose_streams (demux);
6947             QTDEMUX_EXPOSE_UNLOCK (demux);
6948
6949             demux->got_moov = TRUE;
6950
6951             gst_qtdemux_check_send_pending_segment (demux);
6952
6953             if (demux->moov_node_compressed) {
6954               g_node_destroy (demux->moov_node_compressed);
6955               g_free (demux->moov_node->data);
6956             }
6957             demux->moov_node_compressed = NULL;
6958             g_node_destroy (demux->moov_node);
6959             demux->moov_node = NULL;
6960             GST_DEBUG_OBJECT (demux, "Finished parsing the header");
6961           }
6962         } else if (fourcc == FOURCC_moof) {
6963           if ((demux->got_moov || demux->media_caps) && demux->fragmented) {
6964             guint64 dist = 0;
6965             GstClockTime prev_pts;
6966             guint64 prev_offset;
6967             guint64 adapter_discont_offset, adapter_discont_dist;
6968
6969             GST_DEBUG_OBJECT (demux, "Parsing [moof]");
6970
6971             /*
6972              * The timestamp of the moof buffer is relevant as some scenarios
6973              * won't have the initial timestamp in the atoms. Whenever a new
6974              * buffer has started, we get that buffer's PTS and use it as a base
6975              * timestamp for the trun entries.
6976              *
6977              * To keep track of the current buffer timestamp and starting point
6978              * we use gst_adapter_prev_pts that gives us the PTS and the distance
6979              * from the beggining of the buffer, with the distance and demux->offset
6980              * we know if it is still the same buffer or not.
6981              */
6982             prev_pts = gst_adapter_prev_pts (demux->adapter, &dist);
6983             prev_offset = demux->offset - dist;
6984             if (demux->fragment_start_offset == -1
6985                 || prev_offset > demux->fragment_start_offset) {
6986               demux->fragment_start_offset = prev_offset;
6987               demux->fragment_start = prev_pts;
6988               GST_DEBUG_OBJECT (demux,
6989                   "New fragment start found at: %" G_GUINT64_FORMAT " : %"
6990                   GST_TIME_FORMAT, demux->fragment_start_offset,
6991                   GST_TIME_ARGS (demux->fragment_start));
6992             }
6993
6994             /* We can't use prev_offset() here because this would require
6995              * upstream to set consistent and correct offsets on all buffers
6996              * since the discont. Nothing ever did that in the past and we
6997              * would break backwards compatibility here then.
6998              * Instead take the offset we had at the last discont and count
6999              * the bytes from there. This works with old code as there would
7000              * be no discont between moov and moof, and also works with
7001              * adaptivedemux which correctly sets offset and will set the
7002              * DISCONT flag accordingly when needed.
7003              *
7004              * We also only do this for upstream TIME segments as otherwise
7005              * there are potential backwards compatibility problems with
7006              * seeking in PUSH mode and upstream providing inconsistent
7007              * timestamps. */
7008             adapter_discont_offset =
7009                 gst_adapter_offset_at_discont (demux->adapter);
7010             adapter_discont_dist =
7011                 gst_adapter_distance_from_discont (demux->adapter);
7012
7013             GST_DEBUG_OBJECT (demux,
7014                 "demux offset %" G_GUINT64_FORMAT " adapter offset %"
7015                 G_GUINT64_FORMAT " (+ %" G_GUINT64_FORMAT " bytes)",
7016                 demux->offset, adapter_discont_offset, adapter_discont_dist);
7017
7018             if (demux->upstream_format_is_time) {
7019               demux->moof_offset = adapter_discont_offset;
7020               if (demux->moof_offset != GST_BUFFER_OFFSET_NONE)
7021                 demux->moof_offset += adapter_discont_dist;
7022               if (demux->moof_offset == GST_BUFFER_OFFSET_NONE)
7023                 demux->moof_offset = demux->offset;
7024             } else {
7025               demux->moof_offset = demux->offset;
7026             }
7027
7028             if (!qtdemux_parse_moof (demux, data, demux->neededbytes,
7029                     demux->moof_offset, NULL)) {
7030               gst_adapter_unmap (demux->adapter);
7031               ret = GST_FLOW_ERROR;
7032               goto done;
7033             }
7034
7035             /* in MSS we need to expose the pads after the first moof as we won't get a moov */
7036             if (demux->mss_mode && !demux->exposed) {
7037               QTDEMUX_EXPOSE_LOCK (demux);
7038               qtdemux_expose_streams (demux);
7039               QTDEMUX_EXPOSE_UNLOCK (demux);
7040             }
7041
7042             gst_qtdemux_check_send_pending_segment (demux);
7043           } else {
7044             GST_DEBUG_OBJECT (demux, "Discarding [moof]");
7045           }
7046         } else if (fourcc == FOURCC_ftyp) {
7047           GST_DEBUG_OBJECT (demux, "Parsing [ftyp]");
7048           qtdemux_parse_ftyp (demux, data, demux->neededbytes);
7049         } else if (fourcc == FOURCC_uuid) {
7050           GST_DEBUG_OBJECT (demux, "Parsing [uuid]");
7051           qtdemux_parse_uuid (demux, data, demux->neededbytes);
7052         } else if (fourcc == FOURCC_sidx) {
7053           GST_DEBUG_OBJECT (demux, "Parsing [sidx]");
7054           qtdemux_parse_sidx (demux, data, demux->neededbytes);
7055         } else {
7056           switch (fourcc) {
7057             case FOURCC_styp:
7058               /* [styp] is like a [ftyp], but in fragment header. We ignore it for now
7059                * FALLTHROUGH */
7060             case FOURCC_skip:
7061             case FOURCC_free:
7062               /* [free] and [skip] are padding atoms */
7063               GST_DEBUG_OBJECT (demux,
7064                   "Skipping fourcc while parsing header : %" GST_FOURCC_FORMAT,
7065                   GST_FOURCC_ARGS (fourcc));
7066               break;
7067             default:
7068               GST_WARNING_OBJECT (demux,
7069                   "Unknown fourcc while parsing header : %" GST_FOURCC_FORMAT,
7070                   GST_FOURCC_ARGS (fourcc));
7071               /* Let's jump that one and go back to initial state */
7072               break;
7073           }
7074         }
7075         gst_adapter_unmap (demux->adapter);
7076         data = NULL;
7077
7078         if (demux->mdatbuffer && QTDEMUX_N_STREAMS (demux)) {
7079           gsize remaining_data_size = 0;
7080
7081           /* the mdat was before the header */
7082           GST_DEBUG_OBJECT (demux, "We have n_streams:%d and mdatbuffer:%p",
7083               QTDEMUX_N_STREAMS (demux), demux->mdatbuffer);
7084           /* restore our adapter/offset view of things with upstream;
7085            * put preceding buffered data ahead of current moov data.
7086            * This should also handle evil mdat, moov, mdat cases and alike */
7087           gst_adapter_flush (demux->adapter, demux->neededbytes);
7088
7089           /* Store any remaining data after the mdat for later usage */
7090           remaining_data_size = gst_adapter_available (demux->adapter);
7091           if (remaining_data_size > 0) {
7092             g_assert (demux->restoredata_buffer == NULL);
7093             demux->restoredata_buffer =
7094                 gst_adapter_take_buffer (demux->adapter, remaining_data_size);
7095             demux->restoredata_offset = demux->offset + demux->neededbytes;
7096             GST_DEBUG_OBJECT (demux,
7097                 "Stored %" G_GSIZE_FORMAT " post mdat bytes at offset %"
7098                 G_GUINT64_FORMAT, remaining_data_size,
7099                 demux->restoredata_offset);
7100           }
7101
7102           gst_adapter_push (demux->adapter, demux->mdatbuffer);
7103           demux->mdatbuffer = NULL;
7104           demux->offset = demux->mdatoffset;
7105           demux->neededbytes = next_entry_size (demux);
7106           demux->state = QTDEMUX_STATE_MOVIE;
7107           demux->mdatleft = gst_adapter_available (demux->adapter);
7108           demux->mdatsize = demux->mdatleft;
7109         } else {
7110           GST_DEBUG_OBJECT (demux, "Carrying on normally");
7111           gst_adapter_flush (demux->adapter, demux->neededbytes);
7112
7113           /* only go back to the mdat if there are samples to play */
7114           if (demux->got_moov && demux->first_mdat != -1
7115               && has_next_entry (demux)) {
7116             gboolean res;
7117
7118             /* we need to seek back */
7119             res = qtdemux_seek_offset (demux, demux->first_mdat);
7120             if (res) {
7121               demux->offset = demux->first_mdat;
7122             } else {
7123               GST_DEBUG_OBJECT (demux, "Seek back failed");
7124             }
7125           } else {
7126             demux->offset += demux->neededbytes;
7127           }
7128           demux->neededbytes = 16;
7129           demux->state = QTDEMUX_STATE_INITIAL;
7130         }
7131
7132         break;
7133       }
7134       case QTDEMUX_STATE_BUFFER_MDAT:{
7135         GstBuffer *buf;
7136         guint8 fourcc[4];
7137
7138         GST_DEBUG_OBJECT (demux, "Got our buffer at offset %" G_GUINT64_FORMAT,
7139             demux->offset);
7140         buf = gst_adapter_take_buffer (demux->adapter, demux->neededbytes);
7141         gst_buffer_extract (buf, 0, fourcc, 4);
7142         GST_DEBUG_OBJECT (demux, "mdatbuffer starts with %" GST_FOURCC_FORMAT,
7143             GST_FOURCC_ARGS (QT_FOURCC (fourcc)));
7144         if (demux->mdatbuffer)
7145           demux->mdatbuffer = gst_buffer_append (demux->mdatbuffer, buf);
7146         else
7147           demux->mdatbuffer = buf;
7148         demux->offset += demux->neededbytes;
7149         demux->neededbytes = 16;
7150         demux->state = QTDEMUX_STATE_INITIAL;
7151         gst_qtdemux_post_progress (demux, 1, 1);
7152
7153         break;
7154       }
7155       case QTDEMUX_STATE_MOVIE:{
7156         QtDemuxStream *stream = NULL;
7157         QtDemuxSample *sample;
7158         GstClockTime dts, pts, duration;
7159         gboolean keyframe;
7160         gint i;
7161
7162         GST_DEBUG_OBJECT (demux,
7163             "BEGIN // in MOVIE for offset %" G_GUINT64_FORMAT, demux->offset);
7164
7165         if (demux->fragmented) {
7166           GST_DEBUG_OBJECT (demux, "mdat remaining %" G_GUINT64_FORMAT,
7167               demux->mdatleft);
7168           if (G_LIKELY (demux->todrop < demux->mdatleft)) {
7169             /* if needed data starts within this atom,
7170              * then it should not exceed this atom */
7171             if (G_UNLIKELY (demux->neededbytes > demux->mdatleft)) {
7172               GST_ELEMENT_ERROR (demux, STREAM, DEMUX,
7173                   (_("This file is invalid and cannot be played.")),
7174                   ("sample data crosses atom boundary"));
7175               ret = GST_FLOW_ERROR;
7176               break;
7177             }
7178             demux->mdatleft -= demux->neededbytes;
7179           } else {
7180             GST_DEBUG_OBJECT (demux, "data atom emptied; resuming atom scan");
7181             /* so we are dropping more than left in this atom */
7182             gst_qtdemux_drop_data (demux, demux->mdatleft);
7183             demux->mdatleft = 0;
7184
7185             /* need to resume atom parsing so we do not miss any other pieces */
7186             demux->state = QTDEMUX_STATE_INITIAL;
7187             demux->neededbytes = 16;
7188
7189             /* check if there was any stored post mdat data from previous buffers */
7190             if (demux->restoredata_buffer) {
7191               g_assert (gst_adapter_available (demux->adapter) == 0);
7192
7193               gst_adapter_push (demux->adapter, demux->restoredata_buffer);
7194               demux->restoredata_buffer = NULL;
7195               demux->offset = demux->restoredata_offset;
7196             }
7197
7198             break;
7199           }
7200         }
7201
7202         if (demux->todrop) {
7203           if (demux->cenc_aux_info_offset > 0) {
7204             GstByteReader br;
7205             const guint8 *data;
7206
7207             GST_DEBUG_OBJECT (demux, "parsing cenc auxiliary info");
7208             data = gst_adapter_map (demux->adapter, demux->todrop);
7209             gst_byte_reader_init (&br, data + 8, demux->todrop);
7210             if (!qtdemux_parse_cenc_aux_info (demux,
7211                     QTDEMUX_NTH_STREAM (demux, 0), &br,
7212                     demux->cenc_aux_info_sizes, demux->cenc_aux_sample_count)) {
7213               GST_ERROR_OBJECT (demux, "failed to parse cenc auxiliary info");
7214               ret = GST_FLOW_ERROR;
7215               gst_adapter_unmap (demux->adapter);
7216               g_free (demux->cenc_aux_info_sizes);
7217               demux->cenc_aux_info_sizes = NULL;
7218               goto done;
7219             }
7220             demux->cenc_aux_info_offset = 0;
7221             g_free (demux->cenc_aux_info_sizes);
7222             demux->cenc_aux_info_sizes = NULL;
7223             gst_adapter_unmap (demux->adapter);
7224           }
7225           gst_qtdemux_drop_data (demux, demux->todrop);
7226         }
7227
7228         /* first buffer? */
7229         /* initial newsegment sent here after having added pads,
7230          * possible others in sink_event */
7231         gst_qtdemux_check_send_pending_segment (demux);
7232
7233         /* Figure out which stream this packet belongs to */
7234         for (i = 0; i < QTDEMUX_N_STREAMS (demux); i++) {
7235           stream = QTDEMUX_NTH_STREAM (demux, i);
7236           if (stream->sample_index >= stream->n_samples) {
7237             /* reset to be checked below G_UNLIKELY (stream == NULL) */
7238             stream = NULL;
7239             continue;
7240           }
7241           GST_LOG_OBJECT (demux,
7242               "Checking track-id %u (sample_index:%d / offset:%"
7243               G_GUINT64_FORMAT " / size:%d)", stream->track_id,
7244               stream->sample_index,
7245               stream->samples[stream->sample_index].offset,
7246               stream->samples[stream->sample_index].size);
7247
7248           if (stream->samples[stream->sample_index].offset == demux->offset)
7249             break;
7250         }
7251
7252         if (G_UNLIKELY (stream == NULL))
7253           goto unknown_stream;
7254
7255         gst_qtdemux_stream_check_and_change_stsd_index (demux, stream);
7256
7257         if (stream->new_caps) {
7258           gst_qtdemux_configure_stream (demux, stream);
7259         }
7260
7261         /* Put data in a buffer, set timestamps, caps, ... */
7262         sample = &stream->samples[stream->sample_index];
7263
7264         if (G_LIKELY (!(STREAM_IS_EOS (stream)))) {
7265           GST_DEBUG_OBJECT (demux, "stream : %" GST_FOURCC_FORMAT,
7266               GST_FOURCC_ARGS (CUR_STREAM (stream)->fourcc));
7267
7268           dts = QTSAMPLE_DTS (stream, sample);
7269           pts = QTSAMPLE_PTS (stream, sample);
7270           duration = QTSAMPLE_DUR_DTS (stream, sample, dts);
7271           keyframe = QTSAMPLE_KEYFRAME (stream, sample);
7272
7273           /* check for segment end */
7274           if (G_UNLIKELY (demux->segment.stop != -1
7275                   && demux->segment.stop <= pts && stream->on_keyframe)
7276               && !(demux->upstream_format_is_time && demux->segment.rate < 0)) {
7277             GST_DEBUG_OBJECT (demux, "we reached the end of our segment.");
7278             stream->time_position = GST_CLOCK_TIME_NONE;        /* this means EOS */
7279
7280             /* skip this data, stream is EOS */
7281             gst_adapter_flush (demux->adapter, demux->neededbytes);
7282             demux->offset += demux->neededbytes;
7283
7284             /* check if all streams are eos */
7285             ret = GST_FLOW_EOS;
7286             for (i = 0; i < QTDEMUX_N_STREAMS (demux); i++) {
7287               if (!STREAM_IS_EOS (QTDEMUX_NTH_STREAM (demux, i))) {
7288                 ret = GST_FLOW_OK;
7289                 break;
7290               }
7291             }
7292           } else {
7293             GstBuffer *outbuf;
7294
7295             outbuf =
7296                 gst_adapter_take_buffer (demux->adapter, demux->neededbytes);
7297
7298             /* FIXME: should either be an assert or a plain check */
7299             g_return_val_if_fail (outbuf != NULL, GST_FLOW_ERROR);
7300
7301             ret = gst_qtdemux_decorate_and_push_buffer (demux, stream, outbuf,
7302                 dts, pts, duration, keyframe, dts, demux->offset);
7303           }
7304
7305           /* combine flows */
7306           ret = gst_qtdemux_combine_flows (demux, stream, ret);
7307         } else {
7308           /* skip this data, stream is EOS */
7309           gst_adapter_flush (demux->adapter, demux->neededbytes);
7310         }
7311
7312         stream->sample_index++;
7313         stream->offset_in_sample = 0;
7314
7315         /* update current offset and figure out size of next buffer */
7316         GST_LOG_OBJECT (demux, "increasing offset %" G_GUINT64_FORMAT " by %u",
7317             demux->offset, demux->neededbytes);
7318         demux->offset += demux->neededbytes;
7319         GST_LOG_OBJECT (demux, "offset is now %" G_GUINT64_FORMAT,
7320             demux->offset);
7321
7322
7323         if (ret == GST_FLOW_EOS) {
7324           GST_DEBUG_OBJECT (demux, "All streams are EOS, signal upstream");
7325           demux->neededbytes = -1;
7326           goto eos;
7327         }
7328
7329         if ((demux->neededbytes = next_entry_size (demux)) == -1) {
7330           if (demux->fragmented) {
7331             GST_DEBUG_OBJECT (demux, "(temporarily) out of fragmented samples");
7332             /* there may be more to follow, only finish this atom */
7333             demux->todrop = demux->mdatleft;
7334             demux->neededbytes = demux->todrop;
7335             break;
7336           }
7337           goto eos;
7338         }
7339         if (ret != GST_FLOW_OK && ret != GST_FLOW_NOT_LINKED) {
7340           goto non_ok_unlinked_flow;
7341         }
7342         break;
7343       }
7344       default:
7345         goto invalid_state;
7346     }
7347   }
7348
7349   /* when buffering movie data, at least show user something is happening */
7350   if (ret == GST_FLOW_OK && demux->state == QTDEMUX_STATE_BUFFER_MDAT &&
7351       gst_adapter_available (demux->adapter) <= demux->neededbytes) {
7352     gst_qtdemux_post_progress (demux, gst_adapter_available (demux->adapter),
7353         demux->neededbytes);
7354   }
7355 done:
7356
7357   return ret;
7358
7359   /* ERRORS */
7360 non_ok_unlinked_flow:
7361   {
7362     GST_DEBUG_OBJECT (demux, "Stopping, combined return flow %s",
7363         gst_flow_get_name (ret));
7364     return ret;
7365   }
7366 unknown_stream:
7367   {
7368     GST_ELEMENT_ERROR (demux, STREAM, FAILED, (NULL), ("unknown stream found"));
7369     ret = GST_FLOW_ERROR;
7370     goto done;
7371   }
7372 eos:
7373   {
7374     GST_DEBUG_OBJECT (demux, "no next entry, EOS");
7375     ret = GST_FLOW_EOS;
7376     goto done;
7377   }
7378 invalid_state:
7379   {
7380     GST_ELEMENT_ERROR (demux, STREAM, FAILED,
7381         (NULL), ("qtdemuxer invalid state %d", demux->state));
7382     ret = GST_FLOW_ERROR;
7383     goto done;
7384   }
7385 no_moov:
7386   {
7387     GST_ELEMENT_ERROR (demux, STREAM, FAILED,
7388         (NULL), ("no 'moov' atom within the first 10 MB"));
7389     ret = GST_FLOW_ERROR;
7390     goto done;
7391   }
7392 }
7393
7394 static gboolean
7395 qtdemux_sink_activate (GstPad * sinkpad, GstObject * parent)
7396 {
7397   GstQuery *query;
7398   gboolean pull_mode;
7399
7400   query = gst_query_new_scheduling ();
7401
7402   if (!gst_pad_peer_query (sinkpad, query)) {
7403     gst_query_unref (query);
7404     goto activate_push;
7405   }
7406
7407   pull_mode = gst_query_has_scheduling_mode_with_flags (query,
7408       GST_PAD_MODE_PULL, GST_SCHEDULING_FLAG_SEEKABLE);
7409   gst_query_unref (query);
7410
7411   if (!pull_mode)
7412     goto activate_push;
7413
7414   GST_DEBUG_OBJECT (sinkpad, "activating pull");
7415   return gst_pad_activate_mode (sinkpad, GST_PAD_MODE_PULL, TRUE);
7416
7417 activate_push:
7418   {
7419     GST_DEBUG_OBJECT (sinkpad, "activating push");
7420     return gst_pad_activate_mode (sinkpad, GST_PAD_MODE_PUSH, TRUE);
7421   }
7422 }
7423
7424 static gboolean
7425 qtdemux_sink_activate_mode (GstPad * sinkpad, GstObject * parent,
7426     GstPadMode mode, gboolean active)
7427 {
7428   gboolean res;
7429   GstQTDemux *demux = GST_QTDEMUX (parent);
7430
7431   switch (mode) {
7432     case GST_PAD_MODE_PUSH:
7433       demux->pullbased = FALSE;
7434       res = TRUE;
7435       break;
7436     case GST_PAD_MODE_PULL:
7437       if (active) {
7438         demux->pullbased = TRUE;
7439         res = gst_pad_start_task (sinkpad, (GstTaskFunction) gst_qtdemux_loop,
7440             sinkpad, NULL);
7441       } else {
7442         res = gst_pad_stop_task (sinkpad);
7443       }
7444       break;
7445     default:
7446       res = FALSE;
7447       break;
7448   }
7449   return res;
7450 }
7451
7452 #ifdef HAVE_ZLIB
7453 static void *
7454 qtdemux_inflate (void *z_buffer, guint z_length, guint * length)
7455 {
7456   guint8 *buffer;
7457   z_stream z;
7458   int ret;
7459
7460   memset (&z, 0, sizeof (z));
7461   z.zalloc = NULL;
7462   z.zfree = NULL;
7463   z.opaque = NULL;
7464
7465   if ((ret = inflateInit (&z)) != Z_OK) {
7466     GST_ERROR ("inflateInit() returned %d", ret);
7467     return NULL;
7468   }
7469
7470   z.next_in = z_buffer;
7471   z.avail_in = z_length;
7472
7473   buffer = (guint8 *) g_malloc (*length);
7474   z.avail_out = *length;
7475   z.next_out = (Bytef *) buffer;
7476   do {
7477     ret = inflate (&z, Z_NO_FLUSH);
7478     if (ret == Z_STREAM_END) {
7479       break;
7480     } else if (ret != Z_OK) {
7481       GST_WARNING ("inflate() returned %d", ret);
7482       break;
7483     }
7484
7485     *length += 4096;
7486     buffer = (guint8 *) g_realloc (buffer, *length);
7487     z.next_out = (Bytef *) (buffer + z.total_out);
7488     z.avail_out += 4096;
7489   } while (z.avail_in > 0);
7490
7491   if (ret != Z_STREAM_END) {
7492     g_free (buffer);
7493     buffer = NULL;
7494     *length = 0;
7495   } else {
7496     *length = z.total_out;
7497   }
7498
7499   inflateEnd (&z);
7500
7501   return buffer;
7502 }
7503 #endif /* HAVE_ZLIB */
7504
7505 static gboolean
7506 qtdemux_parse_moov (GstQTDemux * qtdemux, const guint8 * buffer, guint length)
7507 {
7508   GNode *cmov;
7509
7510   qtdemux->moov_node = g_node_new ((guint8 *) buffer);
7511
7512   /* counts as header data */
7513   qtdemux->header_size += length;
7514
7515   GST_DEBUG_OBJECT (qtdemux, "parsing 'moov' atom");
7516   qtdemux_parse_node (qtdemux, qtdemux->moov_node, buffer, length);
7517
7518   cmov = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_cmov);
7519   if (cmov) {
7520     guint32 method;
7521     GNode *dcom;
7522     GNode *cmvd;
7523     guint32 dcom_len;
7524
7525     dcom = qtdemux_tree_get_child_by_type (cmov, FOURCC_dcom);
7526     cmvd = qtdemux_tree_get_child_by_type (cmov, FOURCC_cmvd);
7527     if (dcom == NULL || cmvd == NULL)
7528       goto invalid_compression;
7529
7530     dcom_len = QT_UINT32 (dcom->data);
7531     if (dcom_len < 12)
7532       goto invalid_compression;
7533
7534     method = QT_FOURCC ((guint8 *) dcom->data + 8);
7535     switch (method) {
7536 #ifdef HAVE_ZLIB
7537       case FOURCC_zlib:{
7538         guint uncompressed_length;
7539         guint compressed_length;
7540         guint8 *buf;
7541         guint32 cmvd_len;
7542
7543         cmvd_len = QT_UINT32 ((guint8 *) cmvd->data);
7544         if (cmvd_len < 12)
7545           goto invalid_compression;
7546
7547         uncompressed_length = QT_UINT32 ((guint8 *) cmvd->data + 8);
7548         compressed_length = cmvd_len - 12;
7549         GST_LOG ("length = %u", uncompressed_length);
7550
7551         buf =
7552             (guint8 *) qtdemux_inflate ((guint8 *) cmvd->data + 12,
7553             compressed_length, &uncompressed_length);
7554
7555         if (buf) {
7556           qtdemux->moov_node_compressed = qtdemux->moov_node;
7557           qtdemux->moov_node = g_node_new (buf);
7558
7559           qtdemux_parse_node (qtdemux, qtdemux->moov_node, buf,
7560               uncompressed_length);
7561         }
7562         break;
7563       }
7564 #endif /* HAVE_ZLIB */
7565       default:
7566         GST_WARNING_OBJECT (qtdemux, "unknown or unhandled header compression "
7567             "type %" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (method));
7568         break;
7569     }
7570   }
7571   return TRUE;
7572
7573   /* ERRORS */
7574 invalid_compression:
7575   {
7576     GST_ERROR_OBJECT (qtdemux, "invalid compressed header");
7577     return FALSE;
7578   }
7579 }
7580
7581 static gboolean
7582 qtdemux_parse_container (GstQTDemux * qtdemux, GNode * node, const guint8 * buf,
7583     const guint8 * end)
7584 {
7585   while (G_UNLIKELY (buf < end)) {
7586     GNode *child;
7587     guint32 len;
7588
7589     if (G_UNLIKELY (buf + 4 > end)) {
7590       GST_LOG_OBJECT (qtdemux, "buffer overrun");
7591       break;
7592     }
7593     len = QT_UINT32 (buf);
7594     if (G_UNLIKELY (len == 0)) {
7595       GST_LOG_OBJECT (qtdemux, "empty container");
7596       break;
7597     }
7598     if (G_UNLIKELY (len < 8)) {
7599       GST_WARNING_OBJECT (qtdemux, "length too short (%d < 8)", len);
7600       break;
7601     }
7602     if (G_UNLIKELY (len > (end - buf))) {
7603       GST_WARNING_OBJECT (qtdemux, "length too long (%d > %d)", len,
7604           (gint) (end - buf));
7605       break;
7606     }
7607
7608     child = g_node_new ((guint8 *) buf);
7609     g_node_append (node, child);
7610     GST_LOG_OBJECT (qtdemux, "adding new node of len %d", len);
7611     qtdemux_parse_node (qtdemux, child, buf, len);
7612
7613     buf += len;
7614   }
7615   return TRUE;
7616 }
7617
7618 static gboolean
7619 qtdemux_parse_theora_extension (GstQTDemux * qtdemux, QtDemuxStream * stream,
7620     GNode * xdxt)
7621 {
7622   int len = QT_UINT32 (xdxt->data);
7623   guint8 *buf = xdxt->data;
7624   guint8 *end = buf + len;
7625   GstBuffer *buffer;
7626
7627   /* skip size and type */
7628   buf += 8;
7629   end -= 8;
7630
7631   while (buf < end) {
7632     gint size;
7633     guint32 type;
7634
7635     size = QT_UINT32 (buf);
7636     type = QT_FOURCC (buf + 4);
7637
7638     GST_LOG_OBJECT (qtdemux, "%p %p", buf, end);
7639
7640     if (buf + size > end || size <= 0)
7641       break;
7642
7643     buf += 8;
7644     size -= 8;
7645
7646     GST_WARNING_OBJECT (qtdemux, "have cookie %" GST_FOURCC_FORMAT,
7647         GST_FOURCC_ARGS (type));
7648
7649     switch (type) {
7650       case FOURCC_tCtH:
7651         buffer = gst_buffer_new_and_alloc (size);
7652         gst_buffer_fill (buffer, 0, buf, size);
7653         stream->buffers = g_slist_append (stream->buffers, buffer);
7654         GST_LOG_OBJECT (qtdemux, "parsing theora header");
7655         break;
7656       case FOURCC_tCt_:
7657         buffer = gst_buffer_new_and_alloc (size);
7658         gst_buffer_fill (buffer, 0, buf, size);
7659         stream->buffers = g_slist_append (stream->buffers, buffer);
7660         GST_LOG_OBJECT (qtdemux, "parsing theora comment");
7661         break;
7662       case FOURCC_tCtC:
7663         buffer = gst_buffer_new_and_alloc (size);
7664         gst_buffer_fill (buffer, 0, buf, size);
7665         stream->buffers = g_slist_append (stream->buffers, buffer);
7666         GST_LOG_OBJECT (qtdemux, "parsing theora codebook");
7667         break;
7668       default:
7669         GST_WARNING_OBJECT (qtdemux,
7670             "unknown theora cookie %" GST_FOURCC_FORMAT,
7671             GST_FOURCC_ARGS (type));
7672         break;
7673     }
7674     buf += size;
7675   }
7676   return TRUE;
7677 }
7678
7679 static gboolean
7680 qtdemux_parse_node (GstQTDemux * qtdemux, GNode * node, const guint8 * buffer,
7681     guint length)
7682 {
7683   guint32 fourcc = 0;
7684   guint32 node_length = 0;
7685   const QtNodeType *type;
7686   const guint8 *end;
7687
7688   GST_LOG_OBJECT (qtdemux, "qtdemux_parse buffer %p length %u", buffer, length);
7689
7690   if (G_UNLIKELY (length < 8))
7691     goto not_enough_data;
7692
7693   node_length = QT_UINT32 (buffer);
7694   fourcc = QT_FOURCC (buffer + 4);
7695
7696   /* ignore empty nodes */
7697   if (G_UNLIKELY (fourcc == 0 || node_length == 8))
7698     return TRUE;
7699
7700   type = qtdemux_type_get (fourcc);
7701
7702   end = buffer + length;
7703
7704   GST_LOG_OBJECT (qtdemux,
7705       "parsing '%" GST_FOURCC_FORMAT "', length=%u, name '%s'",
7706       GST_FOURCC_ARGS (fourcc), node_length, type->name);
7707
7708   if (node_length > length)
7709     goto broken_atom_size;
7710
7711   if (type->flags & QT_FLAG_CONTAINER) {
7712     qtdemux_parse_container (qtdemux, node, buffer + 8, end);
7713   } else {
7714     switch (fourcc) {
7715       case FOURCC_stsd:
7716       {
7717         if (node_length < 20) {
7718           GST_LOG_OBJECT (qtdemux, "skipping small stsd box");
7719           break;
7720         }
7721         GST_DEBUG_OBJECT (qtdemux,
7722             "parsing stsd (sample table, sample description) atom");
7723         /* Skip over 8 byte atom hdr + 1 byte version, 3 bytes flags, 4 byte num_entries */
7724         qtdemux_parse_container (qtdemux, node, buffer + 16, end);
7725         break;
7726       }
7727       case FOURCC_mp4a:
7728       case FOURCC_alac:
7729       case FOURCC_fLaC:
7730       {
7731         guint32 version;
7732         guint32 offset;
7733         guint min_size;
7734
7735         /* also read alac (or whatever) in stead of mp4a in the following,
7736          * since a similar layout is used in other cases as well */
7737         if (fourcc == FOURCC_mp4a)
7738           min_size = 20;
7739         else if (fourcc == FOURCC_fLaC)
7740           min_size = 86;
7741         else
7742           min_size = 40;
7743
7744         /* There are two things we might encounter here: a true mp4a atom, and
7745            an mp4a entry in an stsd atom. The latter is what we're interested
7746            in, and it looks like an atom, but isn't really one. The true mp4a
7747            atom is short, so we detect it based on length here. */
7748         if (length < min_size) {
7749           GST_LOG_OBJECT (qtdemux, "skipping small %" GST_FOURCC_FORMAT " box",
7750               GST_FOURCC_ARGS (fourcc));
7751           break;
7752         }
7753
7754         /* 'version' here is the sound sample description version. Types 0 and
7755            1 are documented in the QTFF reference, but type 2 is not: it's
7756            described in Apple header files instead (struct SoundDescriptionV2
7757            in Movies.h) */
7758         version = QT_UINT16 (buffer + 16);
7759
7760         GST_DEBUG_OBJECT (qtdemux, "%" GST_FOURCC_FORMAT " version 0x%08x",
7761             GST_FOURCC_ARGS (fourcc), version);
7762
7763         /* parse any esds descriptors */
7764         switch (version) {
7765           case 0:
7766             offset = 0x24;
7767             break;
7768           case 1:
7769             offset = 0x34;
7770             break;
7771           case 2:
7772             offset = 0x48;
7773             break;
7774           default:
7775             GST_WARNING_OBJECT (qtdemux,
7776                 "unhandled %" GST_FOURCC_FORMAT " version 0x%08x",
7777                 GST_FOURCC_ARGS (fourcc), version);
7778             offset = 0;
7779             break;
7780         }
7781         if (offset)
7782           qtdemux_parse_container (qtdemux, node, buffer + offset, end);
7783         break;
7784       }
7785       case FOURCC_mp4v:
7786       case FOURCC_MP4V:
7787       case FOURCC_fmp4:
7788       case FOURCC_FMP4:
7789       case FOURCC_apcs:
7790       case FOURCC_apch:
7791       case FOURCC_apcn:
7792       case FOURCC_apco:
7793       case FOURCC_ap4h:
7794       case FOURCC_xvid:
7795       case FOURCC_XVID:
7796       case FOURCC_H264:
7797       case FOURCC_avc1:
7798       case FOURCC_avc3:
7799       case FOURCC_H265:
7800       case FOURCC_hvc1:
7801       case FOURCC_hev1:
7802       case FOURCC_mjp2:
7803       case FOURCC_encv:
7804       {
7805         guint32 version;
7806         guint32 str_len;
7807
7808         /* codec_data is contained inside these atoms, which all have
7809          * the same format. */
7810         /* video sample description size is 86 bytes without extension.
7811          * node_length have to be bigger than 86 bytes because video sample
7812          * description can include extenstions such as esds, fiel, glbl, etc. */
7813         if (node_length < 86) {
7814           GST_WARNING_OBJECT (qtdemux, "%" GST_FOURCC_FORMAT
7815               " sample description length too short (%u < 86)",
7816               GST_FOURCC_ARGS (fourcc), node_length);
7817           break;
7818         }
7819
7820         GST_DEBUG_OBJECT (qtdemux, "parsing in %" GST_FOURCC_FORMAT,
7821             GST_FOURCC_ARGS (fourcc));
7822
7823         /* version (2 bytes) : this is set to 0, unless a compressor has changed
7824          *              its data format.
7825          * revision level (2 bytes) : must be set to 0. */
7826         version = QT_UINT32 (buffer + 16);
7827         GST_DEBUG_OBJECT (qtdemux, "version %08x", version);
7828
7829         /* compressor name : PASCAL string and informative purposes
7830          * first byte : the number of bytes to be displayed.
7831          *              it has to be less than 32 because it is reserved
7832          *              space of 32 bytes total including itself. */
7833         str_len = QT_UINT8 (buffer + 50);
7834         if (str_len < 32)
7835           GST_DEBUG_OBJECT (qtdemux, "compressorname = %.*s", str_len,
7836               (char *) buffer + 51);
7837         else
7838           GST_WARNING_OBJECT (qtdemux,
7839               "compressorname length too big (%u > 31)", str_len);
7840
7841         GST_MEMDUMP_OBJECT (qtdemux, "video sample description", buffer,
7842             end - buffer);
7843         qtdemux_parse_container (qtdemux, node, buffer + 86, end);
7844         break;
7845       }
7846       case FOURCC_meta:
7847       {
7848         GST_DEBUG_OBJECT (qtdemux, "parsing meta atom");
7849
7850         /* You are reading this correctly. QTFF specifies that the
7851          * metadata atom is a short atom, whereas ISO BMFF specifies
7852          * it's a full atom. But since so many people are doing things
7853          * differently, we actually peek into the atom to see which
7854          * variant it is */
7855         if (length < 16) {
7856           GST_LOG_OBJECT (qtdemux, "skipping small %" GST_FOURCC_FORMAT " box",
7857               GST_FOURCC_ARGS (fourcc));
7858           break;
7859         }
7860         if (QT_FOURCC (buffer + 12) == FOURCC_hdlr) {
7861           /* Variant 1: What QTFF specifies. 'meta' is a short header which
7862            * starts with a 'hdlr' atom */
7863           qtdemux_parse_container (qtdemux, node, buffer + 8, end);
7864         } else if (QT_UINT32 (buffer + 8) == 0x00000000) {
7865           /* Variant 2: What ISO BMFF specifies. 'meta' is a _full_ atom
7866            * with version/flags both set to zero */
7867           qtdemux_parse_container (qtdemux, node, buffer + 12, end);
7868         } else
7869           GST_WARNING_OBJECT (qtdemux, "Unknown 'meta' atom format");
7870         break;
7871       }
7872       case FOURCC_mp4s:
7873       {
7874         GST_MEMDUMP_OBJECT (qtdemux, "mp4s", buffer, end - buffer);
7875         /* Skip 8 byte header, plus 8 byte version + flags + entry_count */
7876         qtdemux_parse_container (qtdemux, node, buffer + 16, end);
7877         break;
7878       }
7879       case FOURCC_XiTh:
7880       {
7881         guint32 version;
7882         guint32 offset;
7883
7884         if (length < 16) {
7885           GST_LOG_OBJECT (qtdemux, "skipping small %" GST_FOURCC_FORMAT " box",
7886               GST_FOURCC_ARGS (fourcc));
7887           break;
7888         }
7889
7890         version = QT_UINT32 (buffer + 12);
7891         GST_DEBUG_OBJECT (qtdemux, "parsing XiTh atom version 0x%08x", version);
7892
7893         switch (version) {
7894           case 0x00000001:
7895             offset = 0x62;
7896             break;
7897           default:
7898             GST_DEBUG_OBJECT (qtdemux, "unknown version 0x%08x", version);
7899             offset = 0;
7900             break;
7901         }
7902         if (offset) {
7903           if (length < offset) {
7904             GST_WARNING_OBJECT (qtdemux,
7905                 "skipping too small %" GST_FOURCC_FORMAT " box",
7906                 GST_FOURCC_ARGS (fourcc));
7907             break;
7908           }
7909           qtdemux_parse_container (qtdemux, node, buffer + offset, end);
7910         }
7911         break;
7912       }
7913       case FOURCC_in24:
7914       {
7915         qtdemux_parse_container (qtdemux, node, buffer + 0x34, end);
7916         break;
7917       }
7918       case FOURCC_uuid:
7919       {
7920         qtdemux_parse_uuid (qtdemux, buffer, end - buffer);
7921         break;
7922       }
7923       case FOURCC_enca:
7924       {
7925         qtdemux_parse_container (qtdemux, node, buffer + 36, end);
7926         break;
7927       }
7928       default:
7929         if (!strcmp (type->name, "unknown"))
7930           GST_MEMDUMP ("Unknown tag", buffer + 4, end - buffer - 4);
7931         break;
7932     }
7933   }
7934   GST_LOG_OBJECT (qtdemux, "parsed '%" GST_FOURCC_FORMAT "'",
7935       GST_FOURCC_ARGS (fourcc));
7936   return TRUE;
7937
7938 /* ERRORS */
7939 not_enough_data:
7940   {
7941     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
7942         (_("This file is corrupt and cannot be played.")),
7943         ("Not enough data for an atom header, got only %u bytes", length));
7944     return FALSE;
7945   }
7946 broken_atom_size:
7947   {
7948     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
7949         (_("This file is corrupt and cannot be played.")),
7950         ("Atom '%" GST_FOURCC_FORMAT "' has size of %u bytes, but we have only "
7951             "%u bytes available.", GST_FOURCC_ARGS (fourcc), node_length,
7952             length));
7953     return FALSE;
7954   }
7955 }
7956
7957 static GNode *
7958 qtdemux_tree_get_child_by_type (GNode * node, guint32 fourcc)
7959 {
7960   GNode *child;
7961   guint8 *buffer;
7962   guint32 child_fourcc;
7963
7964   for (child = g_node_first_child (node); child;
7965       child = g_node_next_sibling (child)) {
7966     buffer = (guint8 *) child->data;
7967
7968     child_fourcc = QT_FOURCC (buffer + 4);
7969
7970     if (G_UNLIKELY (child_fourcc == fourcc)) {
7971       return child;
7972     }
7973   }
7974   return NULL;
7975 }
7976
7977 static GNode *
7978 qtdemux_tree_get_child_by_type_full (GNode * node, guint32 fourcc,
7979     GstByteReader * parser)
7980 {
7981   GNode *child;
7982   guint8 *buffer;
7983   guint32 child_fourcc, child_len;
7984
7985   for (child = g_node_first_child (node); child;
7986       child = g_node_next_sibling (child)) {
7987     buffer = (guint8 *) child->data;
7988
7989     child_len = QT_UINT32 (buffer);
7990     child_fourcc = QT_FOURCC (buffer + 4);
7991
7992     if (G_UNLIKELY (child_fourcc == fourcc)) {
7993       if (G_UNLIKELY (child_len < (4 + 4)))
7994         return NULL;
7995       /* FIXME: must verify if atom length < parent atom length */
7996       gst_byte_reader_init (parser, buffer + (4 + 4), child_len - (4 + 4));
7997       return child;
7998     }
7999   }
8000   return NULL;
8001 }
8002
8003 static GNode *
8004 qtdemux_tree_get_child_by_index (GNode * node, guint index)
8005 {
8006   return g_node_nth_child (node, index);
8007 }
8008
8009 static GNode *
8010 qtdemux_tree_get_sibling_by_type_full (GNode * node, guint32 fourcc,
8011     GstByteReader * parser)
8012 {
8013   GNode *child;
8014   guint8 *buffer;
8015   guint32 child_fourcc, child_len;
8016
8017   for (child = g_node_next_sibling (node); child;
8018       child = g_node_next_sibling (child)) {
8019     buffer = (guint8 *) child->data;
8020
8021     child_fourcc = QT_FOURCC (buffer + 4);
8022
8023     if (child_fourcc == fourcc) {
8024       if (parser) {
8025         child_len = QT_UINT32 (buffer);
8026         if (G_UNLIKELY (child_len < (4 + 4)))
8027           return NULL;
8028         /* FIXME: must verify if atom length < parent atom length */
8029         gst_byte_reader_init (parser, buffer + (4 + 4), child_len - (4 + 4));
8030       }
8031       return child;
8032     }
8033   }
8034   return NULL;
8035 }
8036
8037 static GNode *
8038 qtdemux_tree_get_sibling_by_type (GNode * node, guint32 fourcc)
8039 {
8040   return qtdemux_tree_get_sibling_by_type_full (node, fourcc, NULL);
8041 }
8042
8043 static void
8044 qtdemux_do_allocation (QtDemuxStream * stream, GstQTDemux * qtdemux)
8045 {
8046 /* FIXME: This can only reliably work if demuxers have a
8047  * separate streaming thread per srcpad. This should be
8048  * done in a demuxer base class, which integrates parts
8049  * of multiqueue
8050  *
8051  * https://bugzilla.gnome.org/show_bug.cgi?id=701856
8052  */
8053 #if 0
8054   GstQuery *query;
8055
8056   query = gst_query_new_allocation (stream->caps, FALSE);
8057
8058   if (!gst_pad_peer_query (stream->pad, query)) {
8059     /* not a problem, just debug a little */
8060     GST_DEBUG_OBJECT (qtdemux, "peer ALLOCATION query failed");
8061   }
8062
8063   if (stream->allocator)
8064     gst_object_unref (stream->allocator);
8065
8066   if (gst_query_get_n_allocation_params (query) > 0) {
8067     /* try the allocator */
8068     gst_query_parse_nth_allocation_param (query, 0, &stream->allocator,
8069         &stream->params);
8070     stream->use_allocator = TRUE;
8071   } else {
8072     stream->allocator = NULL;
8073     gst_allocation_params_init (&stream->params);
8074     stream->use_allocator = FALSE;
8075   }
8076   gst_query_unref (query);
8077 #endif
8078 }
8079
8080 static gboolean
8081 pad_query (const GValue * item, GValue * value, gpointer user_data)
8082 {
8083   GstPad *pad = g_value_get_object (item);
8084   GstQuery *query = user_data;
8085   gboolean res;
8086
8087   res = gst_pad_peer_query (pad, query);
8088
8089   if (res) {
8090     g_value_set_boolean (value, TRUE);
8091     return FALSE;
8092   }
8093
8094   GST_INFO_OBJECT (pad, "pad peer query failed");
8095   return TRUE;
8096 }
8097
8098 static gboolean
8099 gst_qtdemux_run_query (GstElement * element, GstQuery * query,
8100     GstPadDirection direction)
8101 {
8102   GstIterator *it;
8103   GstIteratorFoldFunction func = pad_query;
8104   GValue res = { 0, };
8105
8106   g_value_init (&res, G_TYPE_BOOLEAN);
8107   g_value_set_boolean (&res, FALSE);
8108
8109   /* Ask neighbor */
8110   if (direction == GST_PAD_SRC)
8111     it = gst_element_iterate_src_pads (element);
8112   else
8113     it = gst_element_iterate_sink_pads (element);
8114
8115   while (gst_iterator_fold (it, func, &res, query) == GST_ITERATOR_RESYNC)
8116     gst_iterator_resync (it);
8117
8118   gst_iterator_free (it);
8119
8120   return g_value_get_boolean (&res);
8121 }
8122
8123 static void
8124 gst_qtdemux_request_protection_context (GstQTDemux * qtdemux,
8125     QtDemuxStream * stream)
8126 {
8127   GstQuery *query;
8128   GstContext *ctxt;
8129   GstElement *element = GST_ELEMENT (qtdemux);
8130   GstStructure *st;
8131   gchar **filtered_sys_ids;
8132   GValue event_list = G_VALUE_INIT;
8133   GList *walk;
8134
8135   /* 1. Check if we already have the context. */
8136   if (qtdemux->preferred_protection_system_id != NULL) {
8137     GST_LOG_OBJECT (element,
8138         "already have the protection context, no need to request it again");
8139     return;
8140   }
8141
8142   g_ptr_array_add (qtdemux->protection_system_ids, NULL);
8143   filtered_sys_ids = gst_protection_filter_systems_by_available_decryptors (
8144       (const gchar **) qtdemux->protection_system_ids->pdata);
8145
8146   g_ptr_array_remove_index (qtdemux->protection_system_ids,
8147       qtdemux->protection_system_ids->len - 1);
8148   GST_TRACE_OBJECT (qtdemux, "detected %u protection systems, we have "
8149       "decryptors for %u of them, running context request",
8150       qtdemux->protection_system_ids->len,
8151       filtered_sys_ids ? g_strv_length (filtered_sys_ids) : 0);
8152
8153
8154   if (stream->protection_scheme_event_queue.length) {
8155     GST_TRACE_OBJECT (qtdemux, "using stream event queue, length %u",
8156         stream->protection_scheme_event_queue.length);
8157     walk = stream->protection_scheme_event_queue.tail;
8158   } else {
8159     GST_TRACE_OBJECT (qtdemux, "using demuxer event queue, length %u",
8160         qtdemux->protection_event_queue.length);
8161     walk = qtdemux->protection_event_queue.tail;
8162   }
8163
8164   g_value_init (&event_list, GST_TYPE_LIST);
8165   for (; walk; walk = g_list_previous (walk)) {
8166     GValue *event_value = g_new0 (GValue, 1);
8167     g_value_init (event_value, GST_TYPE_EVENT);
8168     g_value_set_boxed (event_value, walk->data);
8169     gst_value_list_append_and_take_value (&event_list, event_value);
8170   }
8171
8172   /*  2a) Query downstream with GST_QUERY_CONTEXT for the context and
8173    *      check if downstream already has a context of the specific type
8174    *  2b) Query upstream as above.
8175    */
8176   query = gst_query_new_context ("drm-preferred-decryption-system-id");
8177   st = gst_query_writable_structure (query);
8178   gst_structure_set (st, "track-id", G_TYPE_UINT, stream->track_id,
8179       "available-stream-encryption-systems", G_TYPE_STRV, filtered_sys_ids,
8180       NULL);
8181   gst_structure_set_value (st, "stream-encryption-events", &event_list);
8182   if (gst_qtdemux_run_query (element, query, GST_PAD_SRC)) {
8183     gst_query_parse_context (query, &ctxt);
8184     GST_INFO_OBJECT (element, "found context (%p) in downstream query", ctxt);
8185     gst_element_set_context (element, ctxt);
8186   } else if (gst_qtdemux_run_query (element, query, GST_PAD_SINK)) {
8187     gst_query_parse_context (query, &ctxt);
8188     GST_INFO_OBJECT (element, "found context (%p) in upstream query", ctxt);
8189     gst_element_set_context (element, ctxt);
8190   } else {
8191     /* 3) Post a GST_MESSAGE_NEED_CONTEXT message on the bus with
8192      *    the required context type and afterwards check if a
8193      *    usable context was set now as in 1). The message could
8194      *    be handled by the parent bins of the element and the
8195      *    application.
8196      */
8197     GstMessage *msg;
8198
8199     GST_INFO_OBJECT (element, "posting need context message");
8200     msg = gst_message_new_need_context (GST_OBJECT_CAST (element),
8201         "drm-preferred-decryption-system-id");
8202     st = (GstStructure *) gst_message_get_structure (msg);
8203     gst_structure_set (st, "track-id", G_TYPE_UINT, stream->track_id,
8204         "available-stream-encryption-systems", G_TYPE_STRV, filtered_sys_ids,
8205         NULL);
8206
8207     gst_structure_set_value (st, "stream-encryption-events", &event_list);
8208     gst_element_post_message (element, msg);
8209   }
8210
8211   g_strfreev (filtered_sys_ids);
8212   g_value_unset (&event_list);
8213   gst_query_unref (query);
8214 }
8215
8216 static gboolean
8217 gst_qtdemux_configure_protected_caps (GstQTDemux * qtdemux,
8218     QtDemuxStream * stream)
8219 {
8220   GstStructure *s;
8221   const gchar *selected_system = NULL;
8222
8223   g_return_val_if_fail (qtdemux != NULL, FALSE);
8224   g_return_val_if_fail (stream != NULL, FALSE);
8225   g_return_val_if_fail (gst_caps_get_size (CUR_STREAM (stream)->caps) == 1,
8226       FALSE);
8227
8228   if (stream->protection_scheme_type != FOURCC_cenc) {
8229     GST_ERROR_OBJECT (qtdemux,
8230         "unsupported protection scheme: %" GST_FOURCC_FORMAT,
8231         GST_FOURCC_ARGS (stream->protection_scheme_type));
8232     return FALSE;
8233   }
8234   if (qtdemux->protection_system_ids == NULL) {
8235     GST_ERROR_OBJECT (qtdemux, "stream is protected using cenc, but no "
8236         "cenc protection system information has been found");
8237     return FALSE;
8238   }
8239
8240   gst_qtdemux_request_protection_context (qtdemux, stream);
8241   if (qtdemux->preferred_protection_system_id != NULL) {
8242     const gchar *preferred_system_array[] =
8243         { qtdemux->preferred_protection_system_id, NULL };
8244
8245     selected_system = gst_protection_select_system (preferred_system_array);
8246
8247     if (selected_system) {
8248       GST_TRACE_OBJECT (qtdemux, "selected preferred system %s",
8249           qtdemux->preferred_protection_system_id);
8250     } else {
8251       GST_WARNING_OBJECT (qtdemux, "could not select preferred system %s "
8252           "because there is no available decryptor",
8253           qtdemux->preferred_protection_system_id);
8254     }
8255   }
8256
8257   if (!selected_system) {
8258     g_ptr_array_add (qtdemux->protection_system_ids, NULL);
8259     selected_system = gst_protection_select_system ((const gchar **)
8260         qtdemux->protection_system_ids->pdata);
8261     g_ptr_array_remove_index (qtdemux->protection_system_ids,
8262         qtdemux->protection_system_ids->len - 1);
8263   }
8264
8265   if (!selected_system) {
8266     GST_ERROR_OBJECT (qtdemux, "stream is protected, but no "
8267         "suitable decryptor element has been found");
8268     return FALSE;
8269   }
8270
8271   GST_DEBUG_OBJECT (qtdemux, "selected protection system is %s",
8272       selected_system);
8273
8274   s = gst_caps_get_structure (CUR_STREAM (stream)->caps, 0);
8275   if (!gst_structure_has_name (s, "application/x-cenc")) {
8276     gst_structure_set (s,
8277         "original-media-type", G_TYPE_STRING, gst_structure_get_name (s),
8278         GST_PROTECTION_SYSTEM_ID_CAPS_FIELD, G_TYPE_STRING, selected_system,
8279         NULL);
8280     gst_structure_set_name (s, "application/x-cenc");
8281   }
8282   return TRUE;
8283 }
8284
8285 static gboolean
8286 gst_qtdemux_configure_stream (GstQTDemux * qtdemux, QtDemuxStream * stream)
8287 {
8288   if (stream->subtype == FOURCC_vide) {
8289     /* fps is calculated base on the duration of the average framerate since
8290      * qt does not have a fixed framerate. */
8291     gboolean fps_available = TRUE;
8292     guint32 first_duration = 0;
8293
8294     if (stream->n_samples > 0)
8295       first_duration = stream->samples[0].duration;
8296
8297     if ((stream->n_samples == 1 && first_duration == 0)
8298         || (qtdemux->fragmented && stream->n_samples_moof == 1)) {
8299       /* still frame */
8300       CUR_STREAM (stream)->fps_n = 0;
8301       CUR_STREAM (stream)->fps_d = 1;
8302     } else {
8303       if (stream->duration == 0 || stream->n_samples < 2) {
8304         CUR_STREAM (stream)->fps_n = stream->timescale;
8305         CUR_STREAM (stream)->fps_d = 1;
8306         fps_available = FALSE;
8307       } else {
8308         GstClockTime avg_duration;
8309         guint64 duration;
8310         guint32 n_samples;
8311
8312         /* duration and n_samples can be updated for fragmented format
8313          * so, framerate of fragmented format is calculated using data in a moof */
8314         if (qtdemux->fragmented && stream->n_samples_moof > 0
8315             && stream->duration_moof > 0) {
8316           n_samples = stream->n_samples_moof;
8317           duration = stream->duration_moof;
8318         } else {
8319           n_samples = stream->n_samples;
8320           duration = stream->duration;
8321         }
8322
8323         /* Calculate a framerate, ignoring the first sample which is sometimes truncated */
8324         /* stream->duration is guint64, timescale, n_samples are guint32 */
8325         avg_duration =
8326             gst_util_uint64_scale_round (duration -
8327             first_duration, GST_SECOND,
8328             (guint64) (stream->timescale) * (n_samples - 1));
8329
8330         GST_LOG_OBJECT (qtdemux,
8331             "Calculating avg sample duration based on stream (or moof) duration %"
8332             G_GUINT64_FORMAT
8333             " minus first sample %u, leaving %d samples gives %"
8334             GST_TIME_FORMAT, duration, first_duration,
8335             n_samples - 1, GST_TIME_ARGS (avg_duration));
8336
8337         gst_video_guess_framerate (avg_duration, &CUR_STREAM (stream)->fps_n,
8338             &CUR_STREAM (stream)->fps_d);
8339
8340         GST_DEBUG_OBJECT (qtdemux,
8341             "Calculating framerate, timescale %u gave fps_n %d fps_d %d",
8342             stream->timescale, CUR_STREAM (stream)->fps_n,
8343             CUR_STREAM (stream)->fps_d);
8344       }
8345     }
8346
8347     if (CUR_STREAM (stream)->caps) {
8348       CUR_STREAM (stream)->caps =
8349           gst_caps_make_writable (CUR_STREAM (stream)->caps);
8350
8351       if (CUR_STREAM (stream)->width && CUR_STREAM (stream)->height)
8352         gst_caps_set_simple (CUR_STREAM (stream)->caps,
8353             "width", G_TYPE_INT, CUR_STREAM (stream)->width,
8354             "height", G_TYPE_INT, CUR_STREAM (stream)->height, NULL);
8355
8356       /* set framerate if calculated framerate is reliable */
8357       if (fps_available) {
8358         gst_caps_set_simple (CUR_STREAM (stream)->caps,
8359             "framerate", GST_TYPE_FRACTION, CUR_STREAM (stream)->fps_n,
8360             CUR_STREAM (stream)->fps_d, NULL);
8361       }
8362
8363       /* calculate pixel-aspect-ratio using display width and height */
8364       GST_DEBUG_OBJECT (qtdemux,
8365           "video size %dx%d, target display size %dx%d",
8366           CUR_STREAM (stream)->width, CUR_STREAM (stream)->height,
8367           stream->display_width, stream->display_height);
8368       /* qt file might have pasp atom */
8369       if (CUR_STREAM (stream)->par_w > 0 && CUR_STREAM (stream)->par_h > 0) {
8370         GST_DEBUG_OBJECT (qtdemux, "par %d:%d", CUR_STREAM (stream)->par_w,
8371             CUR_STREAM (stream)->par_h);
8372         gst_caps_set_simple (CUR_STREAM (stream)->caps, "pixel-aspect-ratio",
8373             GST_TYPE_FRACTION, CUR_STREAM (stream)->par_w,
8374             CUR_STREAM (stream)->par_h, NULL);
8375       } else if (stream->display_width > 0 && stream->display_height > 0
8376           && CUR_STREAM (stream)->width > 0
8377           && CUR_STREAM (stream)->height > 0) {
8378         gint n, d;
8379
8380         /* calculate the pixel aspect ratio using the display and pixel w/h */
8381         n = stream->display_width * CUR_STREAM (stream)->height;
8382         d = stream->display_height * CUR_STREAM (stream)->width;
8383         if (n == d)
8384           n = d = 1;
8385         GST_DEBUG_OBJECT (qtdemux, "setting PAR to %d/%d", n, d);
8386         CUR_STREAM (stream)->par_w = n;
8387         CUR_STREAM (stream)->par_h = d;
8388         gst_caps_set_simple (CUR_STREAM (stream)->caps, "pixel-aspect-ratio",
8389             GST_TYPE_FRACTION, CUR_STREAM (stream)->par_w,
8390             CUR_STREAM (stream)->par_h, NULL);
8391       }
8392
8393       if (CUR_STREAM (stream)->interlace_mode > 0) {
8394         if (CUR_STREAM (stream)->interlace_mode == 1) {
8395           gst_caps_set_simple (CUR_STREAM (stream)->caps, "interlace-mode",
8396               G_TYPE_STRING, "progressive", NULL);
8397         } else if (CUR_STREAM (stream)->interlace_mode == 2) {
8398           gst_caps_set_simple (CUR_STREAM (stream)->caps, "interlace-mode",
8399               G_TYPE_STRING, "interleaved", NULL);
8400           if (CUR_STREAM (stream)->field_order == 9) {
8401             gst_caps_set_simple (CUR_STREAM (stream)->caps, "field-order",
8402                 G_TYPE_STRING, "top-field-first", NULL);
8403           } else if (CUR_STREAM (stream)->field_order == 14) {
8404             gst_caps_set_simple (CUR_STREAM (stream)->caps, "field-order",
8405                 G_TYPE_STRING, "bottom-field-first", NULL);
8406           }
8407         }
8408       }
8409
8410       /* Create incomplete colorimetry here if needed */
8411       if (CUR_STREAM (stream)->colorimetry.range ||
8412           CUR_STREAM (stream)->colorimetry.matrix ||
8413           CUR_STREAM (stream)->colorimetry.transfer
8414           || CUR_STREAM (stream)->colorimetry.primaries) {
8415         gchar *colorimetry =
8416             gst_video_colorimetry_to_string (&CUR_STREAM (stream)->colorimetry);
8417         gst_caps_set_simple (CUR_STREAM (stream)->caps, "colorimetry",
8418             G_TYPE_STRING, colorimetry, NULL);
8419         g_free (colorimetry);
8420       }
8421
8422       if (stream->multiview_mode != GST_VIDEO_MULTIVIEW_MODE_NONE) {
8423         guint par_w = 1, par_h = 1;
8424
8425         if (CUR_STREAM (stream)->par_w > 0 && CUR_STREAM (stream)->par_h > 0) {
8426           par_w = CUR_STREAM (stream)->par_w;
8427           par_h = CUR_STREAM (stream)->par_h;
8428         }
8429
8430         if (gst_video_multiview_guess_half_aspect (stream->multiview_mode,
8431                 CUR_STREAM (stream)->width, CUR_STREAM (stream)->height, par_w,
8432                 par_h)) {
8433           stream->multiview_flags |= GST_VIDEO_MULTIVIEW_FLAGS_HALF_ASPECT;
8434         }
8435
8436         gst_caps_set_simple (CUR_STREAM (stream)->caps,
8437             "multiview-mode", G_TYPE_STRING,
8438             gst_video_multiview_mode_to_caps_string (stream->multiview_mode),
8439             "multiview-flags", GST_TYPE_VIDEO_MULTIVIEW_FLAGSET,
8440             stream->multiview_flags, GST_FLAG_SET_MASK_EXACT, NULL);
8441       }
8442     }
8443   }
8444
8445   else if (stream->subtype == FOURCC_soun) {
8446     if (CUR_STREAM (stream)->caps) {
8447       CUR_STREAM (stream)->caps =
8448           gst_caps_make_writable (CUR_STREAM (stream)->caps);
8449       if (CUR_STREAM (stream)->rate > 0)
8450         gst_caps_set_simple (CUR_STREAM (stream)->caps,
8451             "rate", G_TYPE_INT, (int) CUR_STREAM (stream)->rate, NULL);
8452       if (CUR_STREAM (stream)->n_channels > 0)
8453         gst_caps_set_simple (CUR_STREAM (stream)->caps,
8454             "channels", G_TYPE_INT, CUR_STREAM (stream)->n_channels, NULL);
8455       if (CUR_STREAM (stream)->n_channels > 2) {
8456         /* FIXME: Need to parse the 'chan' atom to get channel layouts
8457          * correctly; this is just the minimum we can do - assume
8458          * we don't actually have any channel positions. */
8459         gst_caps_set_simple (CUR_STREAM (stream)->caps,
8460             "channel-mask", GST_TYPE_BITMASK, G_GUINT64_CONSTANT (0), NULL);
8461       }
8462     }
8463   }
8464
8465   if (stream->pad) {
8466     GstCaps *prev_caps = NULL;
8467
8468     GST_PAD_ELEMENT_PRIVATE (stream->pad) = stream;
8469     gst_pad_set_event_function (stream->pad, gst_qtdemux_handle_src_event);
8470     gst_pad_set_query_function (stream->pad, gst_qtdemux_handle_src_query);
8471     gst_pad_set_active (stream->pad, TRUE);
8472
8473     gst_pad_use_fixed_caps (stream->pad);
8474
8475     if (stream->protected) {
8476       if (!gst_qtdemux_configure_protected_caps (qtdemux, stream)) {
8477         GST_ERROR_OBJECT (qtdemux,
8478             "Failed to configure protected stream caps.");
8479         return FALSE;
8480       }
8481     }
8482
8483     GST_DEBUG_OBJECT (qtdemux, "setting caps %" GST_PTR_FORMAT,
8484         CUR_STREAM (stream)->caps);
8485     if (stream->new_stream) {
8486       GstEvent *event;
8487       GstStreamFlags stream_flags = GST_STREAM_FLAG_NONE;
8488
8489       event =
8490           gst_pad_get_sticky_event (qtdemux->sinkpad, GST_EVENT_STREAM_START,
8491           0);
8492       if (event) {
8493         gst_event_parse_stream_flags (event, &stream_flags);
8494         if (gst_event_parse_group_id (event, &qtdemux->group_id))
8495           qtdemux->have_group_id = TRUE;
8496         else
8497           qtdemux->have_group_id = FALSE;
8498         gst_event_unref (event);
8499       } else if (!qtdemux->have_group_id) {
8500         qtdemux->have_group_id = TRUE;
8501         qtdemux->group_id = gst_util_group_id_next ();
8502       }
8503
8504       stream->new_stream = FALSE;
8505       event = gst_event_new_stream_start (stream->stream_id);
8506       if (qtdemux->have_group_id)
8507         gst_event_set_group_id (event, qtdemux->group_id);
8508       if (stream->disabled)
8509         stream_flags |= GST_STREAM_FLAG_UNSELECT;
8510       if (CUR_STREAM (stream)->sparse) {
8511         stream_flags |= GST_STREAM_FLAG_SPARSE;
8512       } else {
8513         stream_flags &= ~GST_STREAM_FLAG_SPARSE;
8514       }
8515       gst_event_set_stream_flags (event, stream_flags);
8516       gst_pad_push_event (stream->pad, event);
8517     }
8518
8519     prev_caps = gst_pad_get_current_caps (stream->pad);
8520
8521     if (CUR_STREAM (stream)->caps) {
8522       if (!prev_caps
8523           || !gst_caps_is_equal_fixed (prev_caps, CUR_STREAM (stream)->caps)) {
8524         GST_DEBUG_OBJECT (qtdemux, "setting caps %" GST_PTR_FORMAT,
8525             CUR_STREAM (stream)->caps);
8526         gst_pad_set_caps (stream->pad, CUR_STREAM (stream)->caps);
8527       } else {
8528         GST_DEBUG_OBJECT (qtdemux, "ignore duplicated caps");
8529       }
8530     } else {
8531       GST_WARNING_OBJECT (qtdemux, "stream without caps");
8532     }
8533
8534     if (prev_caps)
8535       gst_caps_unref (prev_caps);
8536     stream->new_caps = FALSE;
8537   }
8538   return TRUE;
8539 }
8540
8541 static void
8542 gst_qtdemux_stream_check_and_change_stsd_index (GstQTDemux * demux,
8543     QtDemuxStream * stream)
8544 {
8545   if (stream->cur_stsd_entry_index == stream->stsd_sample_description_id)
8546     return;
8547
8548   GST_DEBUG_OBJECT (stream->pad, "Changing stsd index from '%u' to '%u'",
8549       stream->cur_stsd_entry_index, stream->stsd_sample_description_id);
8550   if (G_UNLIKELY (stream->stsd_sample_description_id >=
8551           stream->stsd_entries_length)) {
8552     GST_ELEMENT_ERROR (demux, STREAM, DEMUX,
8553         (_("This file is invalid and cannot be played.")),
8554         ("New sample description id is out of bounds (%d >= %d)",
8555             stream->stsd_sample_description_id, stream->stsd_entries_length));
8556   } else {
8557     stream->cur_stsd_entry_index = stream->stsd_sample_description_id;
8558     stream->new_caps = TRUE;
8559   }
8560 }
8561
8562 static gboolean
8563 gst_qtdemux_add_stream (GstQTDemux * qtdemux,
8564     QtDemuxStream * stream, GstTagList * list)
8565 {
8566   gboolean ret = TRUE;
8567   /* consistent default for push based mode */
8568   gst_segment_init (&stream->segment, GST_FORMAT_TIME);
8569
8570   if (stream->subtype == FOURCC_vide) {
8571     gchar *name = g_strdup_printf ("video_%u", qtdemux->n_video_streams);
8572
8573     stream->pad =
8574         gst_pad_new_from_static_template (&gst_qtdemux_videosrc_template, name);
8575     g_free (name);
8576
8577     if (!gst_qtdemux_configure_stream (qtdemux, stream)) {
8578       gst_object_unref (stream->pad);
8579       stream->pad = NULL;
8580       ret = FALSE;
8581       goto done;
8582     }
8583
8584     qtdemux->n_video_streams++;
8585   } else if (stream->subtype == FOURCC_soun) {
8586     gchar *name = g_strdup_printf ("audio_%u", qtdemux->n_audio_streams);
8587
8588     stream->pad =
8589         gst_pad_new_from_static_template (&gst_qtdemux_audiosrc_template, name);
8590     g_free (name);
8591     if (!gst_qtdemux_configure_stream (qtdemux, stream)) {
8592       gst_object_unref (stream->pad);
8593       stream->pad = NULL;
8594       ret = FALSE;
8595       goto done;
8596     }
8597     qtdemux->n_audio_streams++;
8598   } else if (stream->subtype == FOURCC_strm) {
8599     GST_DEBUG_OBJECT (qtdemux, "stream type, not creating pad");
8600   } else if (stream->subtype == FOURCC_subp || stream->subtype == FOURCC_text
8601       || stream->subtype == FOURCC_sbtl || stream->subtype == FOURCC_subt
8602       || stream->subtype == FOURCC_clcp) {
8603     gchar *name = g_strdup_printf ("subtitle_%u", qtdemux->n_sub_streams);
8604
8605     stream->pad =
8606         gst_pad_new_from_static_template (&gst_qtdemux_subsrc_template, name);
8607     g_free (name);
8608     if (!gst_qtdemux_configure_stream (qtdemux, stream)) {
8609       gst_object_unref (stream->pad);
8610       stream->pad = NULL;
8611       ret = FALSE;
8612       goto done;
8613     }
8614     qtdemux->n_sub_streams++;
8615   } else if (CUR_STREAM (stream)->caps) {
8616     gchar *name = g_strdup_printf ("video_%u", qtdemux->n_video_streams);
8617
8618     stream->pad =
8619         gst_pad_new_from_static_template (&gst_qtdemux_videosrc_template, name);
8620     g_free (name);
8621     if (!gst_qtdemux_configure_stream (qtdemux, stream)) {
8622       gst_object_unref (stream->pad);
8623       stream->pad = NULL;
8624       ret = FALSE;
8625       goto done;
8626     }
8627     qtdemux->n_video_streams++;
8628   } else {
8629     GST_DEBUG_OBJECT (qtdemux, "unknown stream type");
8630     goto done;
8631   }
8632
8633   if (stream->pad) {
8634     GList *l;
8635
8636     GST_DEBUG_OBJECT (qtdemux, "adding pad %s %p to qtdemux %p",
8637         GST_OBJECT_NAME (stream->pad), stream->pad, qtdemux);
8638     gst_element_add_pad (GST_ELEMENT_CAST (qtdemux), stream->pad);
8639     gst_flow_combiner_add_pad (qtdemux->flowcombiner, stream->pad);
8640
8641     if (stream->stream_tags)
8642       gst_tag_list_unref (stream->stream_tags);
8643     stream->stream_tags = list;
8644     list = NULL;
8645     /* global tags go on each pad anyway */
8646     stream->send_global_tags = TRUE;
8647     /* send upstream GST_EVENT_PROTECTION events that were received before
8648        this source pad was created */
8649     for (l = qtdemux->protection_event_queue.head; l != NULL; l = l->next)
8650       gst_pad_push_event (stream->pad, gst_event_ref (l->data));
8651   }
8652 done:
8653   if (list)
8654     gst_tag_list_unref (list);
8655   return ret;
8656 }
8657
8658 /* find next atom with @fourcc starting at @offset */
8659 static GstFlowReturn
8660 qtdemux_find_atom (GstQTDemux * qtdemux, guint64 * offset,
8661     guint64 * length, guint32 fourcc)
8662 {
8663   GstFlowReturn ret;
8664   guint32 lfourcc;
8665   GstBuffer *buf;
8666
8667   GST_LOG_OBJECT (qtdemux, "finding fourcc %" GST_FOURCC_FORMAT " at offset %"
8668       G_GUINT64_FORMAT, GST_FOURCC_ARGS (fourcc), *offset);
8669
8670   while (TRUE) {
8671     GstMapInfo map;
8672
8673     buf = NULL;
8674     ret = gst_pad_pull_range (qtdemux->sinkpad, *offset, 16, &buf);
8675     if (G_UNLIKELY (ret != GST_FLOW_OK))
8676       goto locate_failed;
8677     if (G_UNLIKELY (gst_buffer_get_size (buf) != 16)) {
8678       /* likely EOF */
8679       ret = GST_FLOW_EOS;
8680       gst_buffer_unref (buf);
8681       goto locate_failed;
8682     }
8683     gst_buffer_map (buf, &map, GST_MAP_READ);
8684     extract_initial_length_and_fourcc (map.data, 16, length, &lfourcc);
8685     gst_buffer_unmap (buf, &map);
8686     gst_buffer_unref (buf);
8687
8688     if (G_UNLIKELY (*length == 0)) {
8689       GST_DEBUG_OBJECT (qtdemux, "invalid length 0");
8690       ret = GST_FLOW_ERROR;
8691       goto locate_failed;
8692     }
8693
8694     if (lfourcc == fourcc) {
8695       GST_DEBUG_OBJECT (qtdemux, "found fourcc at offset %" G_GUINT64_FORMAT,
8696           *offset);
8697       break;
8698     } else {
8699       GST_LOG_OBJECT (qtdemux,
8700           "skipping atom '%" GST_FOURCC_FORMAT "' at %" G_GUINT64_FORMAT,
8701           GST_FOURCC_ARGS (fourcc), *offset);
8702       *offset += *length;
8703     }
8704   }
8705
8706   return GST_FLOW_OK;
8707
8708 locate_failed:
8709   {
8710     /* might simply have had last one */
8711     GST_DEBUG_OBJECT (qtdemux, "fourcc not found");
8712     return ret;
8713   }
8714 }
8715
8716 /* should only do something in pull mode */
8717 /* call with OBJECT lock */
8718 static GstFlowReturn
8719 qtdemux_add_fragmented_samples (GstQTDemux * qtdemux)
8720 {
8721   guint64 length, offset;
8722   GstBuffer *buf = NULL;
8723   GstFlowReturn ret = GST_FLOW_OK;
8724   GstFlowReturn res = GST_FLOW_OK;
8725   GstMapInfo map;
8726
8727   offset = qtdemux->moof_offset;
8728   GST_DEBUG_OBJECT (qtdemux, "next moof at offset %" G_GUINT64_FORMAT, offset);
8729
8730   if (!offset) {
8731     GST_DEBUG_OBJECT (qtdemux, "no next moof");
8732     return GST_FLOW_EOS;
8733   }
8734
8735   /* best not do pull etc with lock held */
8736   GST_OBJECT_UNLOCK (qtdemux);
8737
8738   ret = qtdemux_find_atom (qtdemux, &offset, &length, FOURCC_moof);
8739   if (ret != GST_FLOW_OK)
8740     goto flow_failed;
8741
8742   ret = gst_qtdemux_pull_atom (qtdemux, offset, length, &buf);
8743   if (G_UNLIKELY (ret != GST_FLOW_OK))
8744     goto flow_failed;
8745   gst_buffer_map (buf, &map, GST_MAP_READ);
8746   if (!qtdemux_parse_moof (qtdemux, map.data, map.size, offset, NULL)) {
8747     gst_buffer_unmap (buf, &map);
8748     gst_buffer_unref (buf);
8749     buf = NULL;
8750     goto parse_failed;
8751   }
8752
8753   gst_buffer_unmap (buf, &map);
8754   gst_buffer_unref (buf);
8755   buf = NULL;
8756
8757   offset += length;
8758   /* look for next moof */
8759   ret = qtdemux_find_atom (qtdemux, &offset, &length, FOURCC_moof);
8760   if (G_UNLIKELY (ret != GST_FLOW_OK))
8761     goto flow_failed;
8762
8763 exit:
8764   GST_OBJECT_LOCK (qtdemux);
8765
8766   qtdemux->moof_offset = offset;
8767
8768   return res;
8769
8770 parse_failed:
8771   {
8772     GST_DEBUG_OBJECT (qtdemux, "failed to parse moof");
8773     offset = 0;
8774     res = GST_FLOW_ERROR;
8775     goto exit;
8776   }
8777 flow_failed:
8778   {
8779     /* maybe upstream temporarily flushing */
8780     if (ret != GST_FLOW_FLUSHING) {
8781       GST_DEBUG_OBJECT (qtdemux, "no next moof");
8782       offset = 0;
8783     } else {
8784       GST_DEBUG_OBJECT (qtdemux, "upstream WRONG_STATE");
8785       /* resume at current position next time */
8786     }
8787     res = ret;
8788     goto exit;
8789   }
8790 }
8791
8792 /* initialise bytereaders for stbl sub-atoms */
8793 static gboolean
8794 qtdemux_stbl_init (GstQTDemux * qtdemux, QtDemuxStream * stream, GNode * stbl)
8795 {
8796   stream->stbl_index = -1;      /* no samples have yet been parsed */
8797   stream->sample_index = -1;
8798
8799   /* time-to-sample atom */
8800   if (!qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stts, &stream->stts))
8801     goto corrupt_file;
8802
8803   /* copy atom data into a new buffer for later use */
8804   stream->stts.data = g_memdup (stream->stts.data, stream->stts.size);
8805
8806   /* skip version + flags */
8807   if (!gst_byte_reader_skip (&stream->stts, 1 + 3) ||
8808       !gst_byte_reader_get_uint32_be (&stream->stts, &stream->n_sample_times))
8809     goto corrupt_file;
8810   GST_LOG_OBJECT (qtdemux, "%u timestamp blocks", stream->n_sample_times);
8811
8812   /* make sure there's enough data */
8813   if (!qt_atom_parser_has_chunks (&stream->stts, stream->n_sample_times, 8)) {
8814     stream->n_sample_times = gst_byte_reader_get_remaining (&stream->stts) / 8;
8815     GST_LOG_OBJECT (qtdemux, "overriding to %u timestamp blocks",
8816         stream->n_sample_times);
8817     if (!stream->n_sample_times)
8818       goto corrupt_file;
8819   }
8820
8821   /* sync sample atom */
8822   stream->stps_present = FALSE;
8823   if ((stream->stss_present =
8824           ! !qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stss,
8825               &stream->stss) ? TRUE : FALSE) == TRUE) {
8826     /* copy atom data into a new buffer for later use */
8827     stream->stss.data = g_memdup (stream->stss.data, stream->stss.size);
8828
8829     /* skip version + flags */
8830     if (!gst_byte_reader_skip (&stream->stss, 1 + 3) ||
8831         !gst_byte_reader_get_uint32_be (&stream->stss, &stream->n_sample_syncs))
8832       goto corrupt_file;
8833
8834     if (stream->n_sample_syncs) {
8835       /* make sure there's enough data */
8836       if (!qt_atom_parser_has_chunks (&stream->stss, stream->n_sample_syncs, 4))
8837         goto corrupt_file;
8838     }
8839
8840     /* partial sync sample atom */
8841     if ((stream->stps_present =
8842             ! !qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stps,
8843                 &stream->stps) ? TRUE : FALSE) == TRUE) {
8844       /* copy atom data into a new buffer for later use */
8845       stream->stps.data = g_memdup (stream->stps.data, stream->stps.size);
8846
8847       /* skip version + flags */
8848       if (!gst_byte_reader_skip (&stream->stps, 1 + 3) ||
8849           !gst_byte_reader_get_uint32_be (&stream->stps,
8850               &stream->n_sample_partial_syncs))
8851         goto corrupt_file;
8852
8853       /* if there are no entries, the stss table contains the real
8854        * sync samples */
8855       if (stream->n_sample_partial_syncs) {
8856         /* make sure there's enough data */
8857         if (!qt_atom_parser_has_chunks (&stream->stps,
8858                 stream->n_sample_partial_syncs, 4))
8859           goto corrupt_file;
8860       }
8861     }
8862   }
8863
8864   /* sample size */
8865   if (!qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stsz, &stream->stsz))
8866     goto no_samples;
8867
8868   /* copy atom data into a new buffer for later use */
8869   stream->stsz.data = g_memdup (stream->stsz.data, stream->stsz.size);
8870
8871   /* skip version + flags */
8872   if (!gst_byte_reader_skip (&stream->stsz, 1 + 3) ||
8873       !gst_byte_reader_get_uint32_be (&stream->stsz, &stream->sample_size))
8874     goto corrupt_file;
8875
8876   if (!gst_byte_reader_get_uint32_be (&stream->stsz, &stream->n_samples))
8877     goto corrupt_file;
8878
8879   if (!stream->n_samples)
8880     goto no_samples;
8881
8882   /* sample-to-chunk atom */
8883   if (!qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stsc, &stream->stsc))
8884     goto corrupt_file;
8885
8886   /* copy atom data into a new buffer for later use */
8887   stream->stsc.data = g_memdup (stream->stsc.data, stream->stsc.size);
8888
8889   /* skip version + flags */
8890   if (!gst_byte_reader_skip (&stream->stsc, 1 + 3) ||
8891       !gst_byte_reader_get_uint32_be (&stream->stsc,
8892           &stream->n_samples_per_chunk))
8893     goto corrupt_file;
8894
8895   GST_DEBUG_OBJECT (qtdemux, "n_samples_per_chunk %u",
8896       stream->n_samples_per_chunk);
8897
8898   /* make sure there's enough data */
8899   if (!qt_atom_parser_has_chunks (&stream->stsc, stream->n_samples_per_chunk,
8900           12))
8901     goto corrupt_file;
8902
8903
8904   /* chunk offset */
8905   if (qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stco, &stream->stco))
8906     stream->co_size = sizeof (guint32);
8907   else if (qtdemux_tree_get_child_by_type_full (stbl, FOURCC_co64,
8908           &stream->stco))
8909     stream->co_size = sizeof (guint64);
8910   else
8911     goto corrupt_file;
8912
8913   /* copy atom data into a new buffer for later use */
8914   stream->stco.data = g_memdup (stream->stco.data, stream->stco.size);
8915
8916   /* skip version + flags */
8917   if (!gst_byte_reader_skip (&stream->stco, 1 + 3))
8918     goto corrupt_file;
8919
8920   /* chunks_are_samples == TRUE means treat chunks as samples */
8921   stream->chunks_are_samples = stream->sample_size
8922       && !CUR_STREAM (stream)->sampled;
8923   if (stream->chunks_are_samples) {
8924     /* treat chunks as samples */
8925     if (!gst_byte_reader_get_uint32_be (&stream->stco, &stream->n_samples))
8926       goto corrupt_file;
8927   } else {
8928     /* skip number of entries */
8929     if (!gst_byte_reader_skip (&stream->stco, 4))
8930       goto corrupt_file;
8931
8932     /* make sure there are enough data in the stsz atom */
8933     if (!stream->sample_size) {
8934       /* different sizes for each sample */
8935       if (!qt_atom_parser_has_chunks (&stream->stsz, stream->n_samples, 4))
8936         goto corrupt_file;
8937     }
8938   }
8939
8940   GST_DEBUG_OBJECT (qtdemux, "allocating n_samples %u * %u (%.2f MB)",
8941       stream->n_samples, (guint) sizeof (QtDemuxSample),
8942       stream->n_samples * sizeof (QtDemuxSample) / (1024.0 * 1024.0));
8943
8944   if (stream->n_samples >=
8945       QTDEMUX_MAX_SAMPLE_INDEX_SIZE / sizeof (QtDemuxSample)) {
8946     GST_WARNING_OBJECT (qtdemux, "not allocating index of %d samples, would "
8947         "be larger than %uMB (broken file?)", stream->n_samples,
8948         QTDEMUX_MAX_SAMPLE_INDEX_SIZE >> 20);
8949     return FALSE;
8950   }
8951
8952   g_assert (stream->samples == NULL);
8953   stream->samples = g_try_new0 (QtDemuxSample, stream->n_samples);
8954   if (!stream->samples) {
8955     GST_WARNING_OBJECT (qtdemux, "failed to allocate %d samples",
8956         stream->n_samples);
8957     return FALSE;
8958   }
8959
8960   /* composition time-to-sample */
8961   if ((stream->ctts_present =
8962           ! !qtdemux_tree_get_child_by_type_full (stbl, FOURCC_ctts,
8963               &stream->ctts) ? TRUE : FALSE) == TRUE) {
8964     GstByteReader cslg = GST_BYTE_READER_INIT (NULL, 0);
8965
8966     /* copy atom data into a new buffer for later use */
8967     stream->ctts.data = g_memdup (stream->ctts.data, stream->ctts.size);
8968
8969     /* skip version + flags */
8970     if (!gst_byte_reader_skip (&stream->ctts, 1 + 3)
8971         || !gst_byte_reader_get_uint32_be (&stream->ctts,
8972             &stream->n_composition_times))
8973       goto corrupt_file;
8974
8975     /* make sure there's enough data */
8976     if (!qt_atom_parser_has_chunks (&stream->ctts, stream->n_composition_times,
8977             4 + 4))
8978       goto corrupt_file;
8979
8980     /* This is optional, if missing we iterate the ctts */
8981     if (qtdemux_tree_get_child_by_type_full (stbl, FOURCC_cslg, &cslg)) {
8982       if (!gst_byte_reader_skip (&cslg, 1 + 3)
8983           || !gst_byte_reader_get_uint32_be (&cslg, &stream->cslg_shift)) {
8984         g_free ((gpointer) cslg.data);
8985         goto corrupt_file;
8986       }
8987     } else {
8988       gint32 cslg_least = 0;
8989       guint num_entries, pos;
8990       gint i;
8991
8992       pos = gst_byte_reader_get_pos (&stream->ctts);
8993       num_entries = stream->n_composition_times;
8994
8995       stream->cslg_shift = 0;
8996
8997       for (i = 0; i < num_entries; i++) {
8998         gint32 offset;
8999
9000         gst_byte_reader_skip_unchecked (&stream->ctts, 4);
9001         offset = gst_byte_reader_get_int32_be_unchecked (&stream->ctts);
9002         /* HACK: if sample_offset is larger than 2 * duration, ignore the box.
9003          * slightly inaccurate PTS could be more usable than corrupted one */
9004         if (G_UNLIKELY ((ABS (offset) / 2) > stream->duration)) {
9005           GST_WARNING_OBJECT (qtdemux,
9006               "Ignore corrupted ctts, sample_offset %" G_GINT32_FORMAT
9007               " larger than duration %" G_GUINT64_FORMAT,
9008               offset, stream->duration);
9009
9010           stream->cslg_shift = 0;
9011           stream->ctts_present = FALSE;
9012           return TRUE;
9013         }
9014
9015         if (offset < cslg_least)
9016           cslg_least = offset;
9017       }
9018
9019       if (cslg_least < 0)
9020         stream->cslg_shift = ABS (cslg_least);
9021       else
9022         stream->cslg_shift = 0;
9023
9024       /* reset the reader so we can generate sample table */
9025       gst_byte_reader_set_pos (&stream->ctts, pos);
9026     }
9027   } else {
9028     /* Ensure the cslg_shift value is consistent so we can use it
9029      * unconditionnally to produce TS and Segment */
9030     stream->cslg_shift = 0;
9031   }
9032
9033   return TRUE;
9034
9035 corrupt_file:
9036   {
9037     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
9038         (_("This file is corrupt and cannot be played.")), (NULL));
9039     return FALSE;
9040   }
9041 no_samples:
9042   {
9043     gst_qtdemux_stbl_free (stream);
9044     if (!qtdemux->fragmented) {
9045       /* not quite good */
9046       GST_WARNING_OBJECT (qtdemux, "stream has no samples");
9047       return FALSE;
9048     } else {
9049       /* may pick up samples elsewhere */
9050       return TRUE;
9051     }
9052   }
9053 }
9054
9055 /* collect samples from the next sample to be parsed up to sample @n for @stream
9056  * by reading the info from @stbl
9057  *
9058  * This code can be executed from both the streaming thread and the seeking
9059  * thread so it takes the object lock to protect itself
9060  */
9061 static gboolean
9062 qtdemux_parse_samples (GstQTDemux * qtdemux, QtDemuxStream * stream, guint32 n)
9063 {
9064   gint i, j, k;
9065   QtDemuxSample *samples, *first, *cur, *last;
9066   guint32 n_samples_per_chunk;
9067   guint32 n_samples;
9068
9069   GST_LOG_OBJECT (qtdemux, "parsing samples for stream fourcc %"
9070       GST_FOURCC_FORMAT ", pad %s",
9071       GST_FOURCC_ARGS (CUR_STREAM (stream)->fourcc),
9072       stream->pad ? GST_PAD_NAME (stream->pad) : "(NULL)");
9073
9074   n_samples = stream->n_samples;
9075
9076   if (n >= n_samples)
9077     goto out_of_samples;
9078
9079   GST_OBJECT_LOCK (qtdemux);
9080   if (n <= stream->stbl_index)
9081     goto already_parsed;
9082
9083   GST_DEBUG_OBJECT (qtdemux, "parsing up to sample %u", n);
9084
9085   if (!stream->stsz.data) {
9086     /* so we already parsed and passed all the moov samples;
9087      * onto fragmented ones */
9088     g_assert (qtdemux->fragmented);
9089     goto done;
9090   }
9091
9092   /* pointer to the sample table */
9093   samples = stream->samples;
9094
9095   /* starts from -1, moves to the next sample index to parse */
9096   stream->stbl_index++;
9097
9098   /* keep track of the first and last sample to fill */
9099   first = &samples[stream->stbl_index];
9100   last = &samples[n];
9101
9102   if (!stream->chunks_are_samples) {
9103     /* set the sample sizes */
9104     if (stream->sample_size == 0) {
9105       /* different sizes for each sample */
9106       for (cur = first; cur <= last; cur++) {
9107         cur->size = gst_byte_reader_get_uint32_be_unchecked (&stream->stsz);
9108         GST_LOG_OBJECT (qtdemux, "sample %d has size %u",
9109             (guint) (cur - samples), cur->size);
9110       }
9111     } else {
9112       /* samples have the same size */
9113       GST_LOG_OBJECT (qtdemux, "all samples have size %u", stream->sample_size);
9114       for (cur = first; cur <= last; cur++)
9115         cur->size = stream->sample_size;
9116     }
9117   }
9118
9119   n_samples_per_chunk = stream->n_samples_per_chunk;
9120   cur = first;
9121
9122   for (i = stream->stsc_index; i < n_samples_per_chunk; i++) {
9123     guint32 last_chunk;
9124
9125     if (stream->stsc_chunk_index >= stream->last_chunk
9126         || stream->stsc_chunk_index < stream->first_chunk) {
9127       stream->first_chunk =
9128           gst_byte_reader_get_uint32_be_unchecked (&stream->stsc);
9129       stream->samples_per_chunk =
9130           gst_byte_reader_get_uint32_be_unchecked (&stream->stsc);
9131       /* starts from 1 */
9132       stream->stsd_sample_description_id =
9133           gst_byte_reader_get_uint32_be_unchecked (&stream->stsc) - 1;
9134
9135       /* chunk numbers are counted from 1 it seems */
9136       if (G_UNLIKELY (stream->first_chunk == 0))
9137         goto corrupt_file;
9138
9139       --stream->first_chunk;
9140
9141       /* the last chunk of each entry is calculated by taking the first chunk
9142        * of the next entry; except if there is no next, where we fake it with
9143        * INT_MAX */
9144       if (G_UNLIKELY (i == (stream->n_samples_per_chunk - 1))) {
9145         stream->last_chunk = G_MAXUINT32;
9146       } else {
9147         stream->last_chunk =
9148             gst_byte_reader_peek_uint32_be_unchecked (&stream->stsc);
9149         if (G_UNLIKELY (stream->last_chunk == 0))
9150           goto corrupt_file;
9151
9152         --stream->last_chunk;
9153       }
9154
9155       GST_LOG_OBJECT (qtdemux,
9156           "entry %d has first_chunk %d, last_chunk %d, samples_per_chunk %d"
9157           "sample desc ID: %d", i, stream->first_chunk, stream->last_chunk,
9158           stream->samples_per_chunk, stream->stsd_sample_description_id);
9159
9160       if (G_UNLIKELY (stream->last_chunk < stream->first_chunk))
9161         goto corrupt_file;
9162
9163       if (stream->last_chunk != G_MAXUINT32) {
9164         if (!qt_atom_parser_peek_sub (&stream->stco,
9165                 stream->first_chunk * stream->co_size,
9166                 (stream->last_chunk - stream->first_chunk) * stream->co_size,
9167                 &stream->co_chunk))
9168           goto corrupt_file;
9169
9170       } else {
9171         stream->co_chunk = stream->stco;
9172         if (!gst_byte_reader_skip (&stream->co_chunk,
9173                 stream->first_chunk * stream->co_size))
9174           goto corrupt_file;
9175       }
9176
9177       stream->stsc_chunk_index = stream->first_chunk;
9178     }
9179
9180     last_chunk = stream->last_chunk;
9181
9182     if (stream->chunks_are_samples) {
9183       cur = &samples[stream->stsc_chunk_index];
9184
9185       for (j = stream->stsc_chunk_index; j < last_chunk; j++) {
9186         if (j > n) {
9187           /* save state */
9188           stream->stsc_chunk_index = j;
9189           goto done;
9190         }
9191
9192         cur->offset =
9193             qt_atom_parser_get_offset_unchecked (&stream->co_chunk,
9194             stream->co_size);
9195
9196         GST_LOG_OBJECT (qtdemux, "Created entry %d with offset "
9197             "%" G_GUINT64_FORMAT, j, cur->offset);
9198
9199         if (CUR_STREAM (stream)->samples_per_frame > 0 &&
9200             CUR_STREAM (stream)->bytes_per_frame > 0) {
9201           cur->size =
9202               (stream->samples_per_chunk * CUR_STREAM (stream)->n_channels) /
9203               CUR_STREAM (stream)->samples_per_frame *
9204               CUR_STREAM (stream)->bytes_per_frame;
9205         } else {
9206           cur->size = stream->samples_per_chunk;
9207         }
9208
9209         GST_DEBUG_OBJECT (qtdemux,
9210             "keyframe sample %d: timestamp %" GST_TIME_FORMAT ", size %u",
9211             j, GST_TIME_ARGS (QTSTREAMTIME_TO_GSTTIME (stream,
9212                     stream->stco_sample_index)), cur->size);
9213
9214         cur->timestamp = stream->stco_sample_index;
9215         cur->duration = stream->samples_per_chunk;
9216         cur->keyframe = TRUE;
9217         cur++;
9218
9219         stream->stco_sample_index += stream->samples_per_chunk;
9220       }
9221       stream->stsc_chunk_index = j;
9222     } else {
9223       for (j = stream->stsc_chunk_index; j < last_chunk; j++) {
9224         guint32 samples_per_chunk;
9225         guint64 chunk_offset;
9226
9227         if (!stream->stsc_sample_index
9228             && !qt_atom_parser_get_offset (&stream->co_chunk, stream->co_size,
9229                 &stream->chunk_offset))
9230           goto corrupt_file;
9231
9232         samples_per_chunk = stream->samples_per_chunk;
9233         chunk_offset = stream->chunk_offset;
9234
9235         for (k = stream->stsc_sample_index; k < samples_per_chunk; k++) {
9236           GST_LOG_OBJECT (qtdemux, "creating entry %d with offset %"
9237               G_GUINT64_FORMAT " and size %d",
9238               (guint) (cur - samples), chunk_offset, cur->size);
9239
9240           cur->offset = chunk_offset;
9241           chunk_offset += cur->size;
9242           cur++;
9243
9244           if (G_UNLIKELY (cur > last)) {
9245             /* save state */
9246             stream->stsc_sample_index = k + 1;
9247             stream->chunk_offset = chunk_offset;
9248             stream->stsc_chunk_index = j;
9249             goto done2;
9250           }
9251         }
9252         stream->stsc_sample_index = 0;
9253       }
9254       stream->stsc_chunk_index = j;
9255     }
9256     stream->stsc_index++;
9257   }
9258
9259   if (stream->chunks_are_samples)
9260     goto ctts;
9261 done2:
9262   {
9263     guint32 n_sample_times;
9264
9265     n_sample_times = stream->n_sample_times;
9266     cur = first;
9267
9268     for (i = stream->stts_index; i < n_sample_times; i++) {
9269       guint32 stts_samples;
9270       gint32 stts_duration;
9271       gint64 stts_time;
9272
9273       if (stream->stts_sample_index >= stream->stts_samples
9274           || !stream->stts_sample_index) {
9275
9276         stream->stts_samples =
9277             gst_byte_reader_get_uint32_be_unchecked (&stream->stts);
9278         stream->stts_duration =
9279             gst_byte_reader_get_uint32_be_unchecked (&stream->stts);
9280
9281         GST_LOG_OBJECT (qtdemux, "block %d, %u timestamps, duration %u",
9282             i, stream->stts_samples, stream->stts_duration);
9283
9284         stream->stts_sample_index = 0;
9285       }
9286
9287       stts_samples = stream->stts_samples;
9288       stts_duration = stream->stts_duration;
9289       stts_time = stream->stts_time;
9290
9291       for (j = stream->stts_sample_index; j < stts_samples; j++) {
9292         GST_DEBUG_OBJECT (qtdemux,
9293             "sample %d: index %d, timestamp %" GST_TIME_FORMAT,
9294             (guint) (cur - samples), j,
9295             GST_TIME_ARGS (QTSTREAMTIME_TO_GSTTIME (stream, stts_time)));
9296
9297         cur->timestamp = stts_time;
9298         cur->duration = stts_duration;
9299
9300         /* avoid 32-bit wrap-around,
9301          * but still mind possible 'negative' duration */
9302         stts_time += (gint64) stts_duration;
9303         cur++;
9304
9305         if (G_UNLIKELY (cur > last)) {
9306           /* save values */
9307           stream->stts_time = stts_time;
9308           stream->stts_sample_index = j + 1;
9309           if (stream->stts_sample_index >= stream->stts_samples)
9310             stream->stts_index++;
9311           goto done3;
9312         }
9313       }
9314       stream->stts_sample_index = 0;
9315       stream->stts_time = stts_time;
9316       stream->stts_index++;
9317     }
9318     /* fill up empty timestamps with the last timestamp, this can happen when
9319      * the last samples do not decode and so we don't have timestamps for them.
9320      * We however look at the last timestamp to estimate the track length so we
9321      * need something in here. */
9322     for (; cur < last; cur++) {
9323       GST_DEBUG_OBJECT (qtdemux,
9324           "fill sample %d: timestamp %" GST_TIME_FORMAT,
9325           (guint) (cur - samples),
9326           GST_TIME_ARGS (QTSTREAMTIME_TO_GSTTIME (stream, stream->stts_time)));
9327       cur->timestamp = stream->stts_time;
9328       cur->duration = -1;
9329     }
9330   }
9331 done3:
9332   {
9333     /* sample sync, can be NULL */
9334     if (stream->stss_present == TRUE) {
9335       guint32 n_sample_syncs;
9336
9337       n_sample_syncs = stream->n_sample_syncs;
9338
9339       if (!n_sample_syncs) {
9340         GST_DEBUG_OBJECT (qtdemux, "all samples are keyframes");
9341         stream->all_keyframe = TRUE;
9342       } else {
9343         for (i = stream->stss_index; i < n_sample_syncs; i++) {
9344           /* note that the first sample is index 1, not 0 */
9345           guint32 index;
9346
9347           index = gst_byte_reader_get_uint32_be_unchecked (&stream->stss);
9348
9349           if (G_LIKELY (index > 0 && index <= n_samples)) {
9350             index -= 1;
9351             samples[index].keyframe = TRUE;
9352             GST_DEBUG_OBJECT (qtdemux, "samples at %u is keyframe", index);
9353             /* and exit if we have enough samples */
9354             if (G_UNLIKELY (index >= n)) {
9355               i++;
9356               break;
9357             }
9358           }
9359         }
9360         /* save state */
9361         stream->stss_index = i;
9362       }
9363
9364       /* stps marks partial sync frames like open GOP I-Frames */
9365       if (stream->stps_present == TRUE) {
9366         guint32 n_sample_partial_syncs;
9367
9368         n_sample_partial_syncs = stream->n_sample_partial_syncs;
9369
9370         /* if there are no entries, the stss table contains the real
9371          * sync samples */
9372         if (n_sample_partial_syncs) {
9373           for (i = stream->stps_index; i < n_sample_partial_syncs; i++) {
9374             /* note that the first sample is index 1, not 0 */
9375             guint32 index;
9376
9377             index = gst_byte_reader_get_uint32_be_unchecked (&stream->stps);
9378
9379             if (G_LIKELY (index > 0 && index <= n_samples)) {
9380               index -= 1;
9381               samples[index].keyframe = TRUE;
9382               GST_DEBUG_OBJECT (qtdemux, "samples at %u is keyframe", index);
9383               /* and exit if we have enough samples */
9384               if (G_UNLIKELY (index >= n)) {
9385                 i++;
9386                 break;
9387               }
9388             }
9389           }
9390           /* save state */
9391           stream->stps_index = i;
9392         }
9393       }
9394     } else {
9395       /* no stss, all samples are keyframes */
9396       stream->all_keyframe = TRUE;
9397       GST_DEBUG_OBJECT (qtdemux, "setting all keyframes");
9398     }
9399   }
9400
9401 ctts:
9402   /* composition time to sample */
9403   if (stream->ctts_present == TRUE) {
9404     guint32 n_composition_times;
9405     guint32 ctts_count;
9406     gint32 ctts_soffset;
9407
9408     /* Fill in the pts_offsets */
9409     cur = first;
9410     n_composition_times = stream->n_composition_times;
9411
9412     for (i = stream->ctts_index; i < n_composition_times; i++) {
9413       if (stream->ctts_sample_index >= stream->ctts_count
9414           || !stream->ctts_sample_index) {
9415         stream->ctts_count =
9416             gst_byte_reader_get_uint32_be_unchecked (&stream->ctts);
9417         stream->ctts_soffset =
9418             gst_byte_reader_get_int32_be_unchecked (&stream->ctts);
9419         stream->ctts_sample_index = 0;
9420       }
9421
9422       ctts_count = stream->ctts_count;
9423       ctts_soffset = stream->ctts_soffset;
9424
9425       for (j = stream->ctts_sample_index; j < ctts_count; j++) {
9426         cur->pts_offset = ctts_soffset;
9427         cur++;
9428
9429         if (G_UNLIKELY (cur > last)) {
9430           /* save state */
9431           stream->ctts_sample_index = j + 1;
9432           goto done;
9433         }
9434       }
9435       stream->ctts_sample_index = 0;
9436       stream->ctts_index++;
9437     }
9438   }
9439 done:
9440   stream->stbl_index = n;
9441   /* if index has been completely parsed, free data that is no-longer needed */
9442   if (n + 1 == stream->n_samples) {
9443     gst_qtdemux_stbl_free (stream);
9444     GST_DEBUG_OBJECT (qtdemux, "parsed all available samples;");
9445     if (qtdemux->pullbased) {
9446       GST_DEBUG_OBJECT (qtdemux, "checking for more samples");
9447       while (n + 1 == stream->n_samples)
9448         if (qtdemux_add_fragmented_samples (qtdemux) != GST_FLOW_OK)
9449           break;
9450     }
9451   }
9452   GST_OBJECT_UNLOCK (qtdemux);
9453
9454   return TRUE;
9455
9456   /* SUCCESS */
9457 already_parsed:
9458   {
9459     GST_LOG_OBJECT (qtdemux,
9460         "Tried to parse up to sample %u but this sample has already been parsed",
9461         n);
9462     /* if fragmented, there may be more */
9463     if (qtdemux->fragmented && n == stream->stbl_index)
9464       goto done;
9465     GST_OBJECT_UNLOCK (qtdemux);
9466     return TRUE;
9467   }
9468   /* ERRORS */
9469 out_of_samples:
9470   {
9471     GST_LOG_OBJECT (qtdemux,
9472         "Tried to parse up to sample %u but there are only %u samples", n + 1,
9473         stream->n_samples);
9474     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
9475         (_("This file is corrupt and cannot be played.")), (NULL));
9476     return FALSE;
9477   }
9478 corrupt_file:
9479   {
9480     GST_OBJECT_UNLOCK (qtdemux);
9481     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
9482         (_("This file is corrupt and cannot be played.")), (NULL));
9483     return FALSE;
9484   }
9485 }
9486
9487 /* collect all segment info for @stream.
9488  */
9489 static gboolean
9490 qtdemux_parse_segments (GstQTDemux * qtdemux, QtDemuxStream * stream,
9491     GNode * trak)
9492 {
9493   GNode *edts;
9494   /* accept edts if they contain gaps at start and there is only
9495    * one media segment */
9496   gboolean allow_pushbased_edts = TRUE;
9497   gint media_segments_count = 0;
9498
9499   /* parse and prepare segment info from the edit list */
9500   GST_DEBUG_OBJECT (qtdemux, "looking for edit list container");
9501   stream->n_segments = 0;
9502   stream->segments = NULL;
9503   if ((edts = qtdemux_tree_get_child_by_type (trak, FOURCC_edts))) {
9504     GNode *elst;
9505     gint n_segments;
9506     gint segment_number, entry_size;
9507     guint64 time;
9508     GstClockTime stime;
9509     const guint8 *buffer;
9510     guint8 version;
9511     guint32 size;
9512
9513     GST_DEBUG_OBJECT (qtdemux, "looking for edit list");
9514     if (!(elst = qtdemux_tree_get_child_by_type (edts, FOURCC_elst)))
9515       goto done;
9516
9517     buffer = elst->data;
9518
9519     size = QT_UINT32 (buffer);
9520     /* version, flags, n_segments */
9521     if (size < 16) {
9522       GST_WARNING_OBJECT (qtdemux, "Invalid edit list");
9523       goto done;
9524     }
9525     version = QT_UINT8 (buffer + 8);
9526     entry_size = (version == 1) ? 20 : 12;
9527
9528     n_segments = QT_UINT32 (buffer + 12);
9529
9530     if (n_segments > 100000 || size < 16 + n_segments * entry_size) {
9531       GST_WARNING_OBJECT (qtdemux, "Invalid edit list");
9532       goto done;
9533     }
9534
9535     /* we might allocate a bit too much, at least allocate 1 segment */
9536     stream->segments = g_new (QtDemuxSegment, MAX (n_segments, 1));
9537
9538     /* segments always start from 0 */
9539     time = 0;
9540     stime = 0;
9541     buffer += 16;
9542     for (segment_number = 0; segment_number < n_segments; segment_number++) {
9543       guint64 duration;
9544       guint64 media_time;
9545       gboolean empty_edit = FALSE;
9546       QtDemuxSegment *segment;
9547       guint32 rate_int;
9548       GstClockTime media_start = GST_CLOCK_TIME_NONE;
9549
9550       if (version == 1) {
9551         media_time = QT_UINT64 (buffer + 8);
9552         duration = QT_UINT64 (buffer);
9553         if (media_time == G_MAXUINT64)
9554           empty_edit = TRUE;
9555       } else {
9556         media_time = QT_UINT32 (buffer + 4);
9557         duration = QT_UINT32 (buffer);
9558         if (media_time == G_MAXUINT32)
9559           empty_edit = TRUE;
9560       }
9561
9562       if (!empty_edit)
9563         media_start = QTSTREAMTIME_TO_GSTTIME (stream, media_time);
9564
9565       segment = &stream->segments[segment_number];
9566
9567       /* time and duration expressed in global timescale */
9568       segment->time = stime;
9569       if (duration != 0 || empty_edit) {
9570         /* edge case: empty edits with duration=zero are treated here.
9571          * (files should not have these anyway). */
9572
9573         /* add non scaled values so we don't cause roundoff errors */
9574         time += duration;
9575         stime = QTTIME_TO_GSTTIME (qtdemux, time);
9576         segment->duration = stime - segment->time;
9577       } else {
9578         /* zero duration does not imply media_start == media_stop
9579          * but, only specify media_start. The edit ends with the track. */
9580         stime = segment->duration = GST_CLOCK_TIME_NONE;
9581         /* Don't allow more edits after this one. */
9582         n_segments = segment_number + 1;
9583       }
9584       segment->stop_time = stime;
9585
9586       segment->trak_media_start = media_time;
9587       /* media_time expressed in stream timescale */
9588       if (!empty_edit) {
9589         segment->media_start = media_start;
9590         segment->media_stop = GST_CLOCK_TIME_IS_VALID (segment->duration)
9591             ? segment->media_start + segment->duration : GST_CLOCK_TIME_NONE;
9592         media_segments_count++;
9593       } else {
9594         segment->media_start = GST_CLOCK_TIME_NONE;
9595         segment->media_stop = GST_CLOCK_TIME_NONE;
9596       }
9597       rate_int = QT_UINT32 (buffer + ((version == 1) ? 16 : 8));
9598
9599       if (rate_int <= 1) {
9600         /* 0 is not allowed, some programs write 1 instead of the floating point
9601          * value */
9602         GST_WARNING_OBJECT (qtdemux, "found suspicious rate %" G_GUINT32_FORMAT,
9603             rate_int);
9604         segment->rate = 1;
9605       } else {
9606         segment->rate = rate_int / 65536.0;
9607       }
9608
9609       GST_DEBUG_OBJECT (qtdemux, "created segment %d time %" GST_TIME_FORMAT
9610           ", duration %" GST_TIME_FORMAT ", media_start %" GST_TIME_FORMAT
9611           " (%" G_GUINT64_FORMAT ") , media_stop %" GST_TIME_FORMAT
9612           " stop_time %" GST_TIME_FORMAT " rate %g, (%d) timescale %u",
9613           segment_number, GST_TIME_ARGS (segment->time),
9614           GST_TIME_ARGS (segment->duration),
9615           GST_TIME_ARGS (segment->media_start), media_time,
9616           GST_TIME_ARGS (segment->media_stop),
9617           GST_TIME_ARGS (segment->stop_time), segment->rate, rate_int,
9618           stream->timescale);
9619       if (segment->stop_time > qtdemux->segment.stop &&
9620           !qtdemux->upstream_format_is_time) {
9621         GST_WARNING_OBJECT (qtdemux, "Segment %d "
9622             " extends to %" GST_TIME_FORMAT
9623             " past the end of the declared movie duration %" GST_TIME_FORMAT
9624             " movie segment will be extended", segment_number,
9625             GST_TIME_ARGS (segment->stop_time),
9626             GST_TIME_ARGS (qtdemux->segment.stop));
9627         qtdemux->segment.stop = qtdemux->segment.duration = segment->stop_time;
9628       }
9629
9630       buffer += entry_size;
9631     }
9632     GST_DEBUG_OBJECT (qtdemux, "found %d segments", n_segments);
9633     stream->n_segments = n_segments;
9634     if (media_segments_count != 1)
9635       allow_pushbased_edts = FALSE;
9636   }
9637 done:
9638
9639   /* push based does not handle segments, so act accordingly here,
9640    * and warn if applicable */
9641   if (!qtdemux->pullbased && !allow_pushbased_edts) {
9642     GST_WARNING_OBJECT (qtdemux, "streaming; discarding edit list segments");
9643     /* remove and use default one below, we stream like it anyway */
9644     g_free (stream->segments);
9645     stream->segments = NULL;
9646     stream->n_segments = 0;
9647   }
9648
9649   /* no segments, create one to play the complete trak */
9650   if (stream->n_segments == 0) {
9651     GstClockTime stream_duration =
9652         QTSTREAMTIME_TO_GSTTIME (stream, stream->duration);
9653
9654     if (stream->segments == NULL)
9655       stream->segments = g_new (QtDemuxSegment, 1);
9656
9657     /* represent unknown our way */
9658     if (stream_duration == 0)
9659       stream_duration = GST_CLOCK_TIME_NONE;
9660
9661     stream->segments[0].time = 0;
9662     stream->segments[0].stop_time = stream_duration;
9663     stream->segments[0].duration = stream_duration;
9664     stream->segments[0].media_start = 0;
9665     stream->segments[0].media_stop = stream_duration;
9666     stream->segments[0].rate = 1.0;
9667     stream->segments[0].trak_media_start = 0;
9668
9669     GST_DEBUG_OBJECT (qtdemux, "created dummy segment %" GST_TIME_FORMAT,
9670         GST_TIME_ARGS (stream_duration));
9671     stream->n_segments = 1;
9672     stream->dummy_segment = TRUE;
9673   }
9674   GST_DEBUG_OBJECT (qtdemux, "using %d segments", stream->n_segments);
9675
9676   return TRUE;
9677 }
9678
9679 /*
9680  * Parses the stsd atom of a svq3 trak looking for
9681  * the SMI and gama atoms.
9682  */
9683 static void
9684 qtdemux_parse_svq3_stsd_data (GstQTDemux * qtdemux,
9685     const guint8 * stsd_entry_data, const guint8 ** gamma, GstBuffer ** seqh)
9686 {
9687   const guint8 *_gamma = NULL;
9688   GstBuffer *_seqh = NULL;
9689   const guint8 *stsd_data = stsd_entry_data;
9690   guint32 length = QT_UINT32 (stsd_data);
9691   guint16 version;
9692
9693   if (length < 32) {
9694     GST_WARNING_OBJECT (qtdemux, "stsd too short");
9695     goto end;
9696   }
9697
9698   stsd_data += 16;
9699   length -= 16;
9700   version = QT_UINT16 (stsd_data);
9701   if (version == 3) {
9702     if (length >= 70) {
9703       length -= 70;
9704       stsd_data += 70;
9705       while (length > 8) {
9706         guint32 fourcc, size;
9707         const guint8 *data;
9708         size = QT_UINT32 (stsd_data);
9709         fourcc = QT_FOURCC (stsd_data + 4);
9710         data = stsd_data + 8;
9711
9712         if (size == 0) {
9713           GST_WARNING_OBJECT (qtdemux, "Atom of size 0 found, aborting "
9714               "svq3 atom parsing");
9715           goto end;
9716         }
9717
9718         switch (fourcc) {
9719           case FOURCC_gama:{
9720             if (size == 12) {
9721               _gamma = data;
9722             } else {
9723               GST_WARNING_OBJECT (qtdemux, "Unexpected size %" G_GUINT32_FORMAT
9724                   " for gama atom, expected 12", size);
9725             }
9726             break;
9727           }
9728           case FOURCC_SMI_:{
9729             if (size > 16 && QT_FOURCC (data) == FOURCC_SEQH) {
9730               guint32 seqh_size;
9731               if (_seqh != NULL) {
9732                 GST_WARNING_OBJECT (qtdemux, "Unexpected second SEQH SMI atom "
9733                     " found, ignoring");
9734               } else {
9735                 seqh_size = QT_UINT32 (data + 4);
9736                 if (seqh_size > 0) {
9737                   _seqh = gst_buffer_new_and_alloc (seqh_size);
9738                   gst_buffer_fill (_seqh, 0, data + 8, seqh_size);
9739                 }
9740               }
9741             }
9742             break;
9743           }
9744           default:{
9745             GST_WARNING_OBJECT (qtdemux, "Unhandled atom %" GST_FOURCC_FORMAT
9746                 " in SVQ3 entry in stsd atom", GST_FOURCC_ARGS (fourcc));
9747           }
9748         }
9749
9750         if (size <= length) {
9751           length -= size;
9752           stsd_data += size;
9753         }
9754       }
9755     } else {
9756       GST_WARNING_OBJECT (qtdemux, "SVQ3 entry too short in stsd atom");
9757     }
9758   } else {
9759     GST_WARNING_OBJECT (qtdemux, "Unexpected version for SVQ3 entry %"
9760         G_GUINT16_FORMAT, version);
9761     goto end;
9762   }
9763
9764 end:
9765   if (gamma) {
9766     *gamma = _gamma;
9767   }
9768   if (seqh) {
9769     *seqh = _seqh;
9770   } else if (_seqh) {
9771     gst_buffer_unref (_seqh);
9772   }
9773 }
9774
9775 static gchar *
9776 qtdemux_get_rtsp_uri_from_hndl (GstQTDemux * qtdemux, GNode * minf)
9777 {
9778   GNode *dinf;
9779   GstByteReader dref;
9780   gchar *uri = NULL;
9781
9782   /*
9783    * Get 'dinf', to get its child 'dref', that might contain a 'hndl'
9784    * atom that might contain a 'data' atom with the rtsp uri.
9785    * This case was reported in bug #597497, some info about
9786    * the hndl atom can be found in TN1195
9787    */
9788   dinf = qtdemux_tree_get_child_by_type (minf, FOURCC_dinf);
9789   GST_DEBUG_OBJECT (qtdemux, "Trying to obtain rtsp URI for stream trak");
9790
9791   if (dinf) {
9792     guint32 dref_num_entries = 0;
9793     if (qtdemux_tree_get_child_by_type_full (dinf, FOURCC_dref, &dref) &&
9794         gst_byte_reader_skip (&dref, 4) &&
9795         gst_byte_reader_get_uint32_be (&dref, &dref_num_entries)) {
9796       gint i;
9797
9798       /* search dref entries for hndl atom */
9799       for (i = 0; i < dref_num_entries; i++) {
9800         guint32 size = 0, type;
9801         guint8 string_len = 0;
9802         if (gst_byte_reader_get_uint32_be (&dref, &size) &&
9803             qt_atom_parser_get_fourcc (&dref, &type)) {
9804           if (type == FOURCC_hndl) {
9805             GST_DEBUG_OBJECT (qtdemux, "Found hndl atom");
9806
9807             /* skip data reference handle bytes and the
9808              * following pascal string and some extra 4
9809              * bytes I have no idea what are */
9810             if (!gst_byte_reader_skip (&dref, 4) ||
9811                 !gst_byte_reader_get_uint8 (&dref, &string_len) ||
9812                 !gst_byte_reader_skip (&dref, string_len + 4)) {
9813               GST_WARNING_OBJECT (qtdemux, "Failed to parse hndl atom");
9814               break;
9815             }
9816
9817             /* iterate over the atoms to find the data atom */
9818             while (gst_byte_reader_get_remaining (&dref) >= 8) {
9819               guint32 atom_size;
9820               guint32 atom_type;
9821
9822               if (gst_byte_reader_get_uint32_be (&dref, &atom_size) &&
9823                   qt_atom_parser_get_fourcc (&dref, &atom_type)) {
9824                 if (atom_type == FOURCC_data) {
9825                   const guint8 *uri_aux = NULL;
9826
9827                   /* found the data atom that might contain the rtsp uri */
9828                   GST_DEBUG_OBJECT (qtdemux, "Found data atom inside "
9829                       "hndl atom, interpreting it as an URI");
9830                   if (gst_byte_reader_peek_data (&dref, atom_size - 8,
9831                           &uri_aux)) {
9832                     if (g_strstr_len ((gchar *) uri_aux, 7, "rtsp://") != NULL)
9833                       uri = g_strndup ((gchar *) uri_aux, atom_size - 8);
9834                     else
9835                       GST_WARNING_OBJECT (qtdemux, "Data atom in hndl atom "
9836                           "didn't contain a rtsp address");
9837                   } else {
9838                     GST_WARNING_OBJECT (qtdemux, "Failed to get the data "
9839                         "atom contents");
9840                   }
9841                   break;
9842                 }
9843                 /* skipping to the next entry */
9844                 if (!gst_byte_reader_skip (&dref, atom_size - 8))
9845                   break;
9846               } else {
9847                 GST_WARNING_OBJECT (qtdemux, "Failed to parse hndl child "
9848                     "atom header");
9849                 break;
9850               }
9851             }
9852             break;
9853           }
9854           /* skip to the next entry */
9855           if (!gst_byte_reader_skip (&dref, size - 8))
9856             break;
9857         } else {
9858           GST_WARNING_OBJECT (qtdemux, "Error parsing dref atom");
9859         }
9860       }
9861       GST_DEBUG_OBJECT (qtdemux, "Finished parsing dref atom");
9862     }
9863   }
9864   return uri;
9865 }
9866
9867 #define AMR_NB_ALL_MODES        0x81ff
9868 #define AMR_WB_ALL_MODES        0x83ff
9869 static guint
9870 qtdemux_parse_amr_bitrate (GstBuffer * buf, gboolean wb)
9871 {
9872   /* The 'damr' atom is of the form:
9873    *
9874    * | vendor | decoder_ver | mode_set | mode_change_period | frames/sample |
9875    *    32 b       8 b          16 b           8 b                 8 b
9876    *
9877    * The highest set bit of the first 7 (AMR-NB) or 8 (AMR-WB) bits of mode_set
9878    * represents the highest mode used in the stream (and thus the maximum
9879    * bitrate), with a couple of special cases as seen below.
9880    */
9881
9882   /* Map of frame type ID -> bitrate */
9883   static const guint nb_bitrates[] = {
9884     4750, 5150, 5900, 6700, 7400, 7950, 10200, 12200
9885   };
9886   static const guint wb_bitrates[] = {
9887     6600, 8850, 12650, 14250, 15850, 18250, 19850, 23050, 23850
9888   };
9889   GstMapInfo map;
9890   gsize max_mode;
9891   guint16 mode_set;
9892
9893   gst_buffer_map (buf, &map, GST_MAP_READ);
9894
9895   if (map.size != 0x11) {
9896     GST_DEBUG ("Atom should have size 0x11, not %" G_GSIZE_FORMAT, map.size);
9897     goto bad_data;
9898   }
9899
9900   if (QT_FOURCC (map.data + 4) != FOURCC_damr) {
9901     GST_DEBUG ("Unknown atom in %" GST_FOURCC_FORMAT,
9902         GST_FOURCC_ARGS (QT_UINT32 (map.data + 4)));
9903     goto bad_data;
9904   }
9905
9906   mode_set = QT_UINT16 (map.data + 13);
9907
9908   if (mode_set == (wb ? AMR_WB_ALL_MODES : AMR_NB_ALL_MODES))
9909     max_mode = 7 + (wb ? 1 : 0);
9910   else
9911     /* AMR-NB modes fo from 0-7, and AMR-WB modes go from 0-8 */
9912     max_mode = g_bit_nth_msf ((gulong) mode_set & (wb ? 0x1ff : 0xff), -1);
9913
9914   if (max_mode == -1) {
9915     GST_DEBUG ("No mode indication was found (mode set) = %x",
9916         (guint) mode_set);
9917     goto bad_data;
9918   }
9919
9920   gst_buffer_unmap (buf, &map);
9921   return wb ? wb_bitrates[max_mode] : nb_bitrates[max_mode];
9922
9923 bad_data:
9924   gst_buffer_unmap (buf, &map);
9925   return 0;
9926 }
9927
9928 static gboolean
9929 qtdemux_parse_transformation_matrix (GstQTDemux * qtdemux,
9930     GstByteReader * reader, guint32 * matrix, const gchar * atom)
9931 {
9932   /*
9933    * 9 values of 32 bits (fixed point 16.16, except 2 5 and 8 that are 2.30)
9934    * [0 1 2]
9935    * [3 4 5]
9936    * [6 7 8]
9937    */
9938
9939   if (gst_byte_reader_get_remaining (reader) < 36)
9940     return FALSE;
9941
9942   matrix[0] = gst_byte_reader_get_uint32_be_unchecked (reader);
9943   matrix[1] = gst_byte_reader_get_uint32_be_unchecked (reader);
9944   matrix[2] = gst_byte_reader_get_uint32_be_unchecked (reader);
9945   matrix[3] = gst_byte_reader_get_uint32_be_unchecked (reader);
9946   matrix[4] = gst_byte_reader_get_uint32_be_unchecked (reader);
9947   matrix[5] = gst_byte_reader_get_uint32_be_unchecked (reader);
9948   matrix[6] = gst_byte_reader_get_uint32_be_unchecked (reader);
9949   matrix[7] = gst_byte_reader_get_uint32_be_unchecked (reader);
9950   matrix[8] = gst_byte_reader_get_uint32_be_unchecked (reader);
9951
9952   GST_DEBUG_OBJECT (qtdemux, "Transformation matrix from atom %s", atom);
9953   GST_DEBUG_OBJECT (qtdemux, "%u.%u %u.%u %u.%u", matrix[0] >> 16,
9954       matrix[0] & 0xFFFF, matrix[1] >> 16, matrix[1] & 0xFF, matrix[2] >> 16,
9955       matrix[2] & 0xFF);
9956   GST_DEBUG_OBJECT (qtdemux, "%u.%u %u.%u %u.%u", matrix[3] >> 16,
9957       matrix[3] & 0xFFFF, matrix[4] >> 16, matrix[4] & 0xFF, matrix[5] >> 16,
9958       matrix[5] & 0xFF);
9959   GST_DEBUG_OBJECT (qtdemux, "%u.%u %u.%u %u.%u", matrix[6] >> 16,
9960       matrix[6] & 0xFFFF, matrix[7] >> 16, matrix[7] & 0xFF, matrix[8] >> 16,
9961       matrix[8] & 0xFF);
9962
9963   return TRUE;
9964 }
9965
9966 static void
9967 qtdemux_inspect_transformation_matrix (GstQTDemux * qtdemux,
9968     QtDemuxStream * stream, guint32 * matrix, GstTagList ** taglist)
9969 {
9970
9971 /* [a b c]
9972  * [d e f]
9973  * [g h i]
9974  *
9975  * This macro will only compare value abdegh, it expects cfi to have already
9976  * been checked
9977  */
9978 #define QTCHECK_MATRIX(m,a,b,d,e) ((m)[0] == (a << 16) && (m)[1] == (b << 16) && \
9979                                    (m)[3] == (d << 16) && (m)[4] == (e << 16))
9980
9981   /* only handle the cases where the last column has standard values */
9982   if (matrix[2] == 0 && matrix[5] == 0 && matrix[8] == 1 << 30) {
9983     const gchar *rotation_tag = NULL;
9984
9985     /* no rotation needed */
9986     if (QTCHECK_MATRIX (matrix, 1, 0, 0, 1)) {
9987       /* NOP */
9988     } else if (QTCHECK_MATRIX (matrix, 0, 1, G_MAXUINT16, 0)) {
9989       rotation_tag = "rotate-90";
9990     } else if (QTCHECK_MATRIX (matrix, G_MAXUINT16, 0, 0, G_MAXUINT16)) {
9991       rotation_tag = "rotate-180";
9992     } else if (QTCHECK_MATRIX (matrix, 0, G_MAXUINT16, 1, 0)) {
9993       rotation_tag = "rotate-270";
9994     } else {
9995       GST_FIXME_OBJECT (qtdemux, "Unhandled transformation matrix values");
9996     }
9997
9998     GST_DEBUG_OBJECT (qtdemux, "Transformation matrix rotation %s",
9999         rotation_tag);
10000     if (rotation_tag != NULL) {
10001       if (*taglist == NULL)
10002         *taglist = gst_tag_list_new_empty ();
10003       gst_tag_list_add (*taglist, GST_TAG_MERGE_REPLACE,
10004           GST_TAG_IMAGE_ORIENTATION, rotation_tag, NULL);
10005     }
10006   } else {
10007     GST_FIXME_OBJECT (qtdemux, "Unhandled transformation matrix values");
10008   }
10009 }
10010
10011 /* Parses the boxes defined in ISO/IEC 14496-12 that enable support for
10012  * protected streams (sinf, frma, schm and schi); if the protection scheme is
10013  * Common Encryption (cenc), the function will also parse the tenc box (defined
10014  * in ISO/IEC 23001-7). @container points to the node that contains these boxes
10015  * (typically an enc[v|a|t|s] sample entry); the function will set
10016  * @original_fmt to the fourcc of the original unencrypted stream format.
10017  * Returns TRUE if successful; FALSE otherwise. */
10018 static gboolean
10019 qtdemux_parse_protection_scheme_info (GstQTDemux * qtdemux,
10020     QtDemuxStream * stream, GNode * container, guint32 * original_fmt)
10021 {
10022   GNode *sinf;
10023   GNode *frma;
10024   GNode *schm;
10025   GNode *schi;
10026   QtDemuxCencSampleSetInfo *info;
10027   GNode *tenc;
10028   const guint8 *tenc_data;
10029
10030   g_return_val_if_fail (qtdemux != NULL, FALSE);
10031   g_return_val_if_fail (stream != NULL, FALSE);
10032   g_return_val_if_fail (container != NULL, FALSE);
10033   g_return_val_if_fail (original_fmt != NULL, FALSE);
10034
10035   sinf = qtdemux_tree_get_child_by_type (container, FOURCC_sinf);
10036   if (G_UNLIKELY (!sinf)) {
10037     if (stream->protection_scheme_type == FOURCC_cenc) {
10038       GST_ERROR_OBJECT (qtdemux, "sinf box does not contain schi box, which is "
10039           "mandatory for Common Encryption");
10040       return FALSE;
10041     }
10042     return TRUE;
10043   }
10044
10045   frma = qtdemux_tree_get_child_by_type (sinf, FOURCC_frma);
10046   if (G_UNLIKELY (!frma)) {
10047     GST_ERROR_OBJECT (qtdemux, "sinf box does not contain mandatory frma box");
10048     return FALSE;
10049   }
10050
10051   *original_fmt = QT_FOURCC ((const guint8 *) frma->data + 8);
10052   GST_DEBUG_OBJECT (qtdemux, "original stream format: '%" GST_FOURCC_FORMAT "'",
10053       GST_FOURCC_ARGS (*original_fmt));
10054
10055   schm = qtdemux_tree_get_child_by_type (sinf, FOURCC_schm);
10056   if (!schm) {
10057     GST_DEBUG_OBJECT (qtdemux, "sinf box does not contain schm box");
10058     return FALSE;
10059   }
10060   stream->protection_scheme_type = QT_FOURCC ((const guint8 *) schm->data + 12);
10061   stream->protection_scheme_version =
10062       QT_UINT32 ((const guint8 *) schm->data + 16);
10063
10064   GST_DEBUG_OBJECT (qtdemux,
10065       "protection_scheme_type: %" GST_FOURCC_FORMAT ", "
10066       "protection_scheme_version: %#010x",
10067       GST_FOURCC_ARGS (stream->protection_scheme_type),
10068       stream->protection_scheme_version);
10069
10070   schi = qtdemux_tree_get_child_by_type (sinf, FOURCC_schi);
10071   if (!schi) {
10072     GST_DEBUG_OBJECT (qtdemux, "sinf box does not contain schi box");
10073     return FALSE;
10074   }
10075   if (stream->protection_scheme_type != FOURCC_cenc &&
10076       stream->protection_scheme_type != FOURCC_piff) {
10077     GST_ERROR_OBJECT (qtdemux,
10078         "Invalid protection_scheme_type: %" GST_FOURCC_FORMAT,
10079         GST_FOURCC_ARGS (stream->protection_scheme_type));
10080     return FALSE;
10081   }
10082
10083   if (G_UNLIKELY (!stream->protection_scheme_info))
10084     stream->protection_scheme_info =
10085         g_malloc0 (sizeof (QtDemuxCencSampleSetInfo));
10086
10087   info = (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
10088
10089   if (stream->protection_scheme_type == FOURCC_cenc) {
10090     guint32 is_encrypted;
10091     guint8 iv_size;
10092     const guint8 *default_kid;
10093
10094     tenc = qtdemux_tree_get_child_by_type (schi, FOURCC_tenc);
10095     if (!tenc) {
10096       GST_ERROR_OBJECT (qtdemux, "schi box does not contain tenc box, "
10097           "which is mandatory for Common Encryption");
10098       return FALSE;
10099     }
10100     tenc_data = (const guint8 *) tenc->data + 12;
10101     is_encrypted = QT_UINT24 (tenc_data);
10102     iv_size = QT_UINT8 (tenc_data + 3);
10103     default_kid = (tenc_data + 4);
10104     qtdemux_update_default_sample_encryption_settings (qtdemux, info,
10105         is_encrypted, iv_size, default_kid);
10106   } else if (stream->protection_scheme_type == FOURCC_piff) {
10107     GstByteReader br;
10108     static const guint8 piff_track_encryption_uuid[] = {
10109       0x89, 0x74, 0xdb, 0xce, 0x7b, 0xe7, 0x4c, 0x51,
10110       0x84, 0xf9, 0x71, 0x48, 0xf9, 0x88, 0x25, 0x54
10111     };
10112
10113     tenc = qtdemux_tree_get_child_by_type (schi, FOURCC_uuid);
10114     if (!tenc) {
10115       GST_ERROR_OBJECT (qtdemux, "schi box does not contain tenc box, "
10116           "which is mandatory for Common Encryption");
10117       return FALSE;
10118     }
10119
10120     tenc_data = (const guint8 *) tenc->data + 8;
10121     if (memcmp (tenc_data, piff_track_encryption_uuid, 16) != 0) {
10122       gchar *box_uuid = qtdemux_uuid_bytes_to_string (tenc_data);
10123       GST_ERROR_OBJECT (qtdemux,
10124           "Unsupported track encryption box with uuid: %s", box_uuid);
10125       g_free (box_uuid);
10126       return FALSE;
10127     }
10128     tenc_data = (const guint8 *) tenc->data + 16 + 12;
10129     gst_byte_reader_init (&br, tenc_data, 20);
10130     if (!qtdemux_update_default_piff_encryption_settings (qtdemux, info, &br)) {
10131       GST_ERROR_OBJECT (qtdemux, "PIFF track box parsing error");
10132       return FALSE;
10133     }
10134     stream->protection_scheme_type = FOURCC_cenc;
10135   }
10136
10137   return TRUE;
10138 }
10139
10140 static gint
10141 qtdemux_track_id_compare_func (QtDemuxStream ** stream1,
10142     QtDemuxStream ** stream2)
10143 {
10144   return (gint) (*stream1)->track_id - (gint) (*stream2)->track_id;
10145 }
10146
10147 /* parse the traks.
10148  * With each track we associate a new QtDemuxStream that contains all the info
10149  * about the trak.
10150  * traks that do not decode to something (like strm traks) will not have a pad.
10151  */
10152 static gboolean
10153 qtdemux_parse_trak (GstQTDemux * qtdemux, GNode * trak)
10154 {
10155   GstByteReader tkhd;
10156   int offset;
10157   GNode *mdia;
10158   GNode *mdhd;
10159   GNode *hdlr;
10160   GNode *minf;
10161   GNode *stbl;
10162   GNode *stsd;
10163   GNode *mp4a;
10164   GNode *mp4v;
10165   GNode *esds;
10166   GNode *tref;
10167   GNode *udta;
10168   GNode *svmi;
10169
10170   QtDemuxStream *stream = NULL;
10171   const guint8 *stsd_data;
10172   const guint8 *stsd_entry_data;
10173   guint remaining_stsd_len;
10174   guint stsd_entry_count;
10175   guint stsd_index;
10176   guint16 lang_code;            /* quicktime lang code or packed iso code */
10177   guint32 version;
10178   guint32 tkhd_flags = 0;
10179   guint8 tkhd_version = 0;
10180   guint32 w = 0, h = 0;
10181   guint value_size, stsd_len, len;
10182   guint32 track_id;
10183   guint32 dummy;
10184
10185   GST_DEBUG_OBJECT (qtdemux, "parse_trak");
10186
10187   if (!qtdemux_tree_get_child_by_type_full (trak, FOURCC_tkhd, &tkhd)
10188       || !gst_byte_reader_get_uint8 (&tkhd, &tkhd_version)
10189       || !gst_byte_reader_get_uint24_be (&tkhd, &tkhd_flags))
10190     goto corrupt_file;
10191
10192   /* pick between 64 or 32 bits */
10193   value_size = tkhd_version == 1 ? 8 : 4;
10194   if (!gst_byte_reader_skip (&tkhd, value_size * 2) ||
10195       !gst_byte_reader_get_uint32_be (&tkhd, &track_id))
10196     goto corrupt_file;
10197
10198   /* Check if current moov has duplicated track_id */
10199   if (qtdemux_find_stream (qtdemux, track_id))
10200     goto existing_stream;
10201
10202   stream = _create_stream (qtdemux, track_id);
10203   stream->stream_tags = gst_tag_list_make_writable (stream->stream_tags);
10204
10205   /* need defaults for fragments */
10206   qtdemux_parse_trex (qtdemux, stream, &dummy, &dummy, &dummy);
10207
10208   if ((tkhd_flags & 1) == 0)
10209     stream->disabled = TRUE;
10210
10211   GST_LOG_OBJECT (qtdemux, "track[tkhd] version/flags/id: 0x%02x/%06x/%u",
10212       tkhd_version, tkhd_flags, stream->track_id);
10213
10214   if (!(mdia = qtdemux_tree_get_child_by_type (trak, FOURCC_mdia)))
10215     goto corrupt_file;
10216
10217   if (!(mdhd = qtdemux_tree_get_child_by_type (mdia, FOURCC_mdhd))) {
10218     /* be nice for some crooked mjp2 files that use mhdr for mdhd */
10219     if (qtdemux->major_brand != FOURCC_mjp2 ||
10220         !(mdhd = qtdemux_tree_get_child_by_type (mdia, FOURCC_mhdr)))
10221       goto corrupt_file;
10222   }
10223
10224   len = QT_UINT32 ((guint8 *) mdhd->data);
10225   version = QT_UINT32 ((guint8 *) mdhd->data + 8);
10226   GST_LOG_OBJECT (qtdemux, "track version/flags: %08x", version);
10227   if (version == 0x01000000) {
10228     if (len < 38)
10229       goto corrupt_file;
10230     stream->timescale = QT_UINT32 ((guint8 *) mdhd->data + 28);
10231     stream->duration = QT_UINT64 ((guint8 *) mdhd->data + 32);
10232     lang_code = QT_UINT16 ((guint8 *) mdhd->data + 36);
10233   } else {
10234     if (len < 30)
10235       goto corrupt_file;
10236     stream->timescale = QT_UINT32 ((guint8 *) mdhd->data + 20);
10237     stream->duration = QT_UINT32 ((guint8 *) mdhd->data + 24);
10238     lang_code = QT_UINT16 ((guint8 *) mdhd->data + 28);
10239   }
10240
10241   if (lang_code < 0x400) {
10242     qtdemux_lang_map_qt_code_to_iso (stream->lang_id, lang_code);
10243   } else if (lang_code == 0x7fff) {
10244     stream->lang_id[0] = 0;     /* unspecified */
10245   } else {
10246     stream->lang_id[0] = 0x60 + ((lang_code >> 10) & 0x1F);
10247     stream->lang_id[1] = 0x60 + ((lang_code >> 5) & 0x1F);
10248     stream->lang_id[2] = 0x60 + (lang_code & 0x1F);
10249     stream->lang_id[3] = 0;
10250   }
10251
10252   GST_LOG_OBJECT (qtdemux, "track timescale: %" G_GUINT32_FORMAT,
10253       stream->timescale);
10254   GST_LOG_OBJECT (qtdemux, "track duration: %" G_GUINT64_FORMAT,
10255       stream->duration);
10256   GST_LOG_OBJECT (qtdemux, "track language code/id: 0x%04x/%s",
10257       lang_code, stream->lang_id);
10258
10259   if (G_UNLIKELY (stream->timescale == 0 || qtdemux->timescale == 0))
10260     goto corrupt_file;
10261
10262   if ((tref = qtdemux_tree_get_child_by_type (trak, FOURCC_tref))) {
10263     /* chapters track reference */
10264     GNode *chap = qtdemux_tree_get_child_by_type (tref, FOURCC_chap);
10265     if (chap) {
10266       gsize length = GST_READ_UINT32_BE (chap->data);
10267       if (qtdemux->chapters_track_id)
10268         GST_FIXME_OBJECT (qtdemux, "Multiple CHAP tracks");
10269
10270       if (length >= 12) {
10271         qtdemux->chapters_track_id =
10272             GST_READ_UINT32_BE ((gint8 *) chap->data + 8);
10273       }
10274     }
10275   }
10276
10277   /* fragmented files may have bogus duration in moov */
10278   if (!qtdemux->fragmented &&
10279       qtdemux->duration != G_MAXINT64 && stream->duration != G_MAXINT32) {
10280     guint64 tdur1, tdur2;
10281
10282     /* don't overflow */
10283     tdur1 = stream->timescale * (guint64) qtdemux->duration;
10284     tdur2 = qtdemux->timescale * (guint64) stream->duration;
10285
10286     /* HACK:
10287      * some of those trailers, nowadays, have prologue images that are
10288      * themselves video tracks as well. I haven't really found a way to
10289      * identify those yet, except for just looking at their duration. */
10290     if (tdur1 != 0 && (tdur2 * 10 / tdur1) < 2) {
10291       GST_WARNING_OBJECT (qtdemux,
10292           "Track shorter than 20%% (%" G_GUINT64_FORMAT "/%" G_GUINT32_FORMAT
10293           " vs. %" G_GUINT64_FORMAT "/%" G_GUINT32_FORMAT ") of the stream "
10294           "found, assuming preview image or something; skipping track",
10295           stream->duration, stream->timescale, qtdemux->duration,
10296           qtdemux->timescale);
10297       gst_qtdemux_stream_unref (stream);
10298       return TRUE;
10299     }
10300   }
10301
10302   if (!(hdlr = qtdemux_tree_get_child_by_type (mdia, FOURCC_hdlr)))
10303     goto corrupt_file;
10304
10305   GST_LOG_OBJECT (qtdemux, "track type: %" GST_FOURCC_FORMAT,
10306       GST_FOURCC_ARGS (QT_FOURCC ((guint8 *) hdlr->data + 12)));
10307
10308   len = QT_UINT32 ((guint8 *) hdlr->data);
10309   if (len >= 20)
10310     stream->subtype = QT_FOURCC ((guint8 *) hdlr->data + 16);
10311   GST_LOG_OBJECT (qtdemux, "track subtype: %" GST_FOURCC_FORMAT,
10312       GST_FOURCC_ARGS (stream->subtype));
10313
10314   if (!(minf = qtdemux_tree_get_child_by_type (mdia, FOURCC_minf)))
10315     goto corrupt_file;
10316
10317   if (!(stbl = qtdemux_tree_get_child_by_type (minf, FOURCC_stbl)))
10318     goto corrupt_file;
10319
10320   /*parse svmi header if existing */
10321   svmi = qtdemux_tree_get_child_by_type (stbl, FOURCC_svmi);
10322   if (svmi) {
10323     len = QT_UINT32 ((guint8 *) svmi->data);
10324     version = QT_UINT32 ((guint8 *) svmi->data + 8);
10325     if (!version) {
10326       GstVideoMultiviewMode mode = GST_VIDEO_MULTIVIEW_MODE_NONE;
10327       GstVideoMultiviewFlags flags = GST_VIDEO_MULTIVIEW_FLAGS_NONE;
10328       guint8 frame_type, frame_layout;
10329
10330       /* MPEG-A stereo video */
10331       if (qtdemux->major_brand == FOURCC_ss02)
10332         flags |= GST_VIDEO_MULTIVIEW_FLAGS_MIXED_MONO;
10333
10334       frame_type = QT_UINT8 ((guint8 *) svmi->data + 12);
10335       frame_layout = QT_UINT8 ((guint8 *) svmi->data + 13) & 0x01;
10336       switch (frame_type) {
10337         case 0:
10338           mode = GST_VIDEO_MULTIVIEW_MODE_SIDE_BY_SIDE;
10339           break;
10340         case 1:
10341           mode = GST_VIDEO_MULTIVIEW_MODE_ROW_INTERLEAVED;
10342           break;
10343         case 2:
10344           mode = GST_VIDEO_MULTIVIEW_MODE_FRAME_BY_FRAME;
10345           break;
10346         case 3:
10347           /* mode 3 is primary/secondary view sequence, ie
10348            * left/right views in separate tracks. See section 7.2
10349            * of ISO/IEC 23000-11:2009 */
10350           GST_FIXME_OBJECT (qtdemux,
10351               "Implement stereo video in separate streams");
10352       }
10353
10354       if ((frame_layout & 0x1) == 0)
10355         flags |= GST_VIDEO_MULTIVIEW_FLAGS_RIGHT_VIEW_FIRST;
10356
10357       GST_LOG_OBJECT (qtdemux,
10358           "StereoVideo: composition type: %u, is_left_first: %u",
10359           frame_type, frame_layout);
10360       stream->multiview_mode = mode;
10361       stream->multiview_flags = flags;
10362     }
10363   }
10364
10365   /* parse rest of tkhd */
10366   if (stream->subtype == FOURCC_vide) {
10367     guint32 matrix[9];
10368
10369     /* version 1 uses some 64-bit ints */
10370     if (!gst_byte_reader_skip (&tkhd, 20 + value_size))
10371       goto corrupt_file;
10372
10373     if (!qtdemux_parse_transformation_matrix (qtdemux, &tkhd, matrix, "tkhd"))
10374       goto corrupt_file;
10375
10376     if (!gst_byte_reader_get_uint32_be (&tkhd, &w)
10377         || !gst_byte_reader_get_uint32_be (&tkhd, &h))
10378       goto corrupt_file;
10379
10380     qtdemux_inspect_transformation_matrix (qtdemux, stream, matrix,
10381         &stream->stream_tags);
10382   }
10383
10384   /* parse stsd */
10385   if (!(stsd = qtdemux_tree_get_child_by_type (stbl, FOURCC_stsd)))
10386     goto corrupt_file;
10387   stsd_data = (const guint8 *) stsd->data;
10388
10389   /* stsd should at least have one entry */
10390   stsd_len = QT_UINT32 (stsd_data);
10391   if (stsd_len < 24) {
10392     /* .. but skip stream with empty stsd produced by some Vivotek cameras */
10393     if (stream->subtype == FOURCC_vivo) {
10394       gst_qtdemux_stream_unref (stream);
10395       return TRUE;
10396     } else {
10397       goto corrupt_file;
10398     }
10399   }
10400
10401   stream->stsd_entries_length = stsd_entry_count = QT_UINT32 (stsd_data + 12);
10402   stream->stsd_entries = g_new0 (QtDemuxStreamStsdEntry, stsd_entry_count);
10403   GST_LOG_OBJECT (qtdemux, "stsd len:           %d", stsd_len);
10404   GST_LOG_OBJECT (qtdemux, "stsd entry count:   %u", stsd_entry_count);
10405
10406   stsd_entry_data = stsd_data + 16;
10407   remaining_stsd_len = stsd_len - 16;
10408   for (stsd_index = 0; stsd_index < stsd_entry_count; stsd_index++) {
10409     guint32 fourcc;
10410     gchar *codec = NULL;
10411     QtDemuxStreamStsdEntry *entry = &stream->stsd_entries[stsd_index];
10412
10413     /* and that entry should fit within stsd */
10414     len = QT_UINT32 (stsd_entry_data);
10415     if (len > remaining_stsd_len)
10416       goto corrupt_file;
10417
10418     entry->fourcc = fourcc = QT_FOURCC (stsd_entry_data + 4);
10419     GST_LOG_OBJECT (qtdemux, "stsd type:          %" GST_FOURCC_FORMAT,
10420         GST_FOURCC_ARGS (entry->fourcc));
10421     GST_LOG_OBJECT (qtdemux, "stsd type len:      %d", len);
10422
10423     if ((fourcc == FOURCC_drms) || (fourcc == FOURCC_drmi))
10424       goto error_encrypted;
10425
10426     if (fourcc == FOURCC_encv || fourcc == FOURCC_enca) {
10427       /* FIXME this looks wrong, there might be multiple children
10428        * with the same type */
10429       GNode *enc = qtdemux_tree_get_child_by_type (stsd, fourcc);
10430       stream->protected = TRUE;
10431       if (!qtdemux_parse_protection_scheme_info (qtdemux, stream, enc, &fourcc))
10432         GST_ERROR_OBJECT (qtdemux, "Failed to parse protection scheme info");
10433     }
10434
10435     if (stream->subtype == FOURCC_vide) {
10436       GNode *colr;
10437       GNode *fiel;
10438       GNode *pasp;
10439       gboolean gray;
10440       gint depth, palette_size, palette_count;
10441       guint32 *palette_data = NULL;
10442
10443       entry->sampled = TRUE;
10444
10445       stream->display_width = w >> 16;
10446       stream->display_height = h >> 16;
10447
10448       offset = 16;
10449       if (len < 86)             /* TODO verify */
10450         goto corrupt_file;
10451
10452       entry->width = QT_UINT16 (stsd_entry_data + offset + 16);
10453       entry->height = QT_UINT16 (stsd_entry_data + offset + 18);
10454       entry->fps_n = 0;         /* this is filled in later */
10455       entry->fps_d = 0;         /* this is filled in later */
10456       entry->bits_per_sample = QT_UINT16 (stsd_entry_data + offset + 66);
10457       entry->color_table_id = QT_UINT16 (stsd_entry_data + offset + 68);
10458
10459       /* if color_table_id is 0, ctab atom must follow; however some files
10460        * produced by TMPEGEnc have color_table_id = 0 and no ctab atom, so
10461        * if color table is not present we'll correct the value */
10462       if (entry->color_table_id == 0 &&
10463           (len < 90
10464               || QT_FOURCC (stsd_entry_data + offset + 70) != FOURCC_ctab)) {
10465         entry->color_table_id = -1;
10466       }
10467
10468       GST_LOG_OBJECT (qtdemux, "width %d, height %d, bps %d, color table id %d",
10469           entry->width, entry->height, entry->bits_per_sample,
10470           entry->color_table_id);
10471
10472       depth = entry->bits_per_sample;
10473
10474       /* more than 32 bits means grayscale */
10475       gray = (depth > 32);
10476       /* low 32 bits specify the depth  */
10477       depth &= 0x1F;
10478
10479       /* different number of palette entries is determined by depth. */
10480       palette_count = 0;
10481       if ((depth == 1) || (depth == 2) || (depth == 4) || (depth == 8))
10482         palette_count = (1 << depth);
10483       palette_size = palette_count * 4;
10484
10485       if (entry->color_table_id) {
10486         switch (palette_count) {
10487           case 0:
10488             break;
10489           case 2:
10490             palette_data = g_memdup (ff_qt_default_palette_2, palette_size);
10491             break;
10492           case 4:
10493             palette_data = g_memdup (ff_qt_default_palette_4, palette_size);
10494             break;
10495           case 16:
10496             if (gray)
10497               palette_data =
10498                   g_memdup (ff_qt_grayscale_palette_16, palette_size);
10499             else
10500               palette_data = g_memdup (ff_qt_default_palette_16, palette_size);
10501             break;
10502           case 256:
10503             if (gray)
10504               palette_data =
10505                   g_memdup (ff_qt_grayscale_palette_256, palette_size);
10506             else
10507               palette_data = g_memdup (ff_qt_default_palette_256, palette_size);
10508             break;
10509           default:
10510             GST_ELEMENT_WARNING (qtdemux, STREAM, DEMUX,
10511                 (_("The video in this file might not play correctly.")),
10512                 ("unsupported palette depth %d", depth));
10513             break;
10514         }
10515       } else {
10516         gint i, j, start, end;
10517
10518         if (len < 94)
10519           goto corrupt_file;
10520
10521         /* read table */
10522         start = QT_UINT32 (stsd_entry_data + offset + 70);
10523         palette_count = QT_UINT16 (stsd_entry_data + offset + 74);
10524         end = QT_UINT16 (stsd_entry_data + offset + 76);
10525
10526         GST_LOG_OBJECT (qtdemux, "start %d, end %d, palette_count %d",
10527             start, end, palette_count);
10528
10529         if (end > 255)
10530           end = 255;
10531         if (start > end)
10532           start = end;
10533
10534         if (len < 94 + (end - start) * 8)
10535           goto corrupt_file;
10536
10537         /* palette is always the same size */
10538         palette_data = g_malloc0 (256 * 4);
10539         palette_size = 256 * 4;
10540
10541         for (j = 0, i = start; i <= end; j++, i++) {
10542           guint32 a, r, g, b;
10543
10544           a = QT_UINT16 (stsd_entry_data + offset + 78 + (j * 8));
10545           r = QT_UINT16 (stsd_entry_data + offset + 80 + (j * 8));
10546           g = QT_UINT16 (stsd_entry_data + offset + 82 + (j * 8));
10547           b = QT_UINT16 (stsd_entry_data + offset + 84 + (j * 8));
10548
10549           palette_data[i] = ((a & 0xff00) << 16) | ((r & 0xff00) << 8) |
10550               (g & 0xff00) | (b >> 8);
10551         }
10552       }
10553
10554       if (entry->caps)
10555         gst_caps_unref (entry->caps);
10556
10557       entry->caps =
10558           qtdemux_video_caps (qtdemux, stream, entry, fourcc, stsd_entry_data,
10559           &codec);
10560       if (G_UNLIKELY (!entry->caps)) {
10561         g_free (palette_data);
10562         goto unknown_stream;
10563       }
10564
10565       if (codec) {
10566         gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
10567             GST_TAG_VIDEO_CODEC, codec, NULL);
10568         g_free (codec);
10569         codec = NULL;
10570       }
10571
10572       if (palette_data) {
10573         GstStructure *s;
10574
10575         if (entry->rgb8_palette)
10576           gst_memory_unref (entry->rgb8_palette);
10577         entry->rgb8_palette = gst_memory_new_wrapped (GST_MEMORY_FLAG_READONLY,
10578             palette_data, palette_size, 0, palette_size, palette_data, g_free);
10579
10580         s = gst_caps_get_structure (entry->caps, 0);
10581
10582         /* non-raw video has a palette_data property. raw video has the palette as
10583          * an extra plane that we append to the output buffers before we push
10584          * them*/
10585         if (!gst_structure_has_name (s, "video/x-raw")) {
10586           GstBuffer *palette;
10587
10588           palette = gst_buffer_new ();
10589           gst_buffer_append_memory (palette, entry->rgb8_palette);
10590           entry->rgb8_palette = NULL;
10591
10592           gst_caps_set_simple (entry->caps, "palette_data",
10593               GST_TYPE_BUFFER, palette, NULL);
10594           gst_buffer_unref (palette);
10595         }
10596       } else if (palette_count != 0) {
10597         GST_ELEMENT_WARNING (qtdemux, STREAM, NOT_IMPLEMENTED,
10598             (NULL), ("Unsupported palette depth %d", depth));
10599       }
10600
10601       GST_LOG_OBJECT (qtdemux, "frame count:   %u",
10602           QT_UINT16 (stsd_entry_data + offset + 32));
10603
10604       esds = NULL;
10605       pasp = NULL;
10606       colr = NULL;
10607       fiel = NULL;
10608       /* pick 'the' stsd child */
10609       mp4v = qtdemux_tree_get_child_by_index (stsd, stsd_index);
10610       if (!stream->protected) {
10611         if (QTDEMUX_TREE_NODE_FOURCC (mp4v) != fourcc) {
10612           mp4v = NULL;
10613         }
10614       } else {
10615         if (QTDEMUX_TREE_NODE_FOURCC (mp4v) != FOURCC_encv) {
10616           mp4v = NULL;
10617         }
10618       }
10619
10620       if (mp4v) {
10621         esds = qtdemux_tree_get_child_by_type (mp4v, FOURCC_esds);
10622         pasp = qtdemux_tree_get_child_by_type (mp4v, FOURCC_pasp);
10623         colr = qtdemux_tree_get_child_by_type (mp4v, FOURCC_colr);
10624         fiel = qtdemux_tree_get_child_by_type (mp4v, FOURCC_fiel);
10625       }
10626
10627       if (pasp) {
10628         const guint8 *pasp_data = (const guint8 *) pasp->data;
10629         gint len = QT_UINT32 (pasp_data);
10630
10631         if (len == 16) {
10632           CUR_STREAM (stream)->par_w = QT_UINT32 (pasp_data + 8);
10633           CUR_STREAM (stream)->par_h = QT_UINT32 (pasp_data + 12);
10634         } else {
10635           CUR_STREAM (stream)->par_w = 0;
10636           CUR_STREAM (stream)->par_h = 0;
10637         }
10638       } else {
10639         CUR_STREAM (stream)->par_w = 0;
10640         CUR_STREAM (stream)->par_h = 0;
10641       }
10642
10643       if (fiel) {
10644         const guint8 *fiel_data = (const guint8 *) fiel->data;
10645         gint len = QT_UINT32 (fiel_data);
10646
10647         if (len == 10) {
10648           CUR_STREAM (stream)->interlace_mode = GST_READ_UINT8 (fiel_data + 8);
10649           CUR_STREAM (stream)->field_order = GST_READ_UINT8 (fiel_data + 9);
10650         }
10651       }
10652
10653       if (colr) {
10654         const guint8 *colr_data = (const guint8 *) colr->data;
10655         gint len = QT_UINT32 (colr_data);
10656
10657         if (len == 19 || len == 18) {
10658           guint32 color_type = GST_READ_UINT32_LE (colr_data + 8);
10659
10660           if (color_type == FOURCC_nclx || color_type == FOURCC_nclc) {
10661             guint16 primaries = GST_READ_UINT16_BE (colr_data + 12);
10662             guint16 transfer_function = GST_READ_UINT16_BE (colr_data + 14);
10663             guint16 matrix = GST_READ_UINT16_BE (colr_data + 16);
10664             gboolean full_range = len == 19 ? colr_data[17] >> 7 : FALSE;
10665
10666             switch (primaries) {
10667               case 1:
10668                 CUR_STREAM (stream)->colorimetry.primaries =
10669                     GST_VIDEO_COLOR_PRIMARIES_BT709;
10670                 break;
10671               case 5:
10672                 CUR_STREAM (stream)->colorimetry.primaries =
10673                     GST_VIDEO_COLOR_PRIMARIES_BT470BG;
10674                 break;
10675               case 6:
10676                 CUR_STREAM (stream)->colorimetry.primaries =
10677                     GST_VIDEO_COLOR_PRIMARIES_SMPTE170M;
10678                 break;
10679               case 9:
10680                 CUR_STREAM (stream)->colorimetry.primaries =
10681                     GST_VIDEO_COLOR_PRIMARIES_BT2020;
10682                 break;
10683               default:
10684                 break;
10685             }
10686
10687             switch (transfer_function) {
10688               case 1:
10689                 CUR_STREAM (stream)->colorimetry.transfer =
10690                     GST_VIDEO_TRANSFER_BT709;
10691                 break;
10692               case 7:
10693                 CUR_STREAM (stream)->colorimetry.transfer =
10694                     GST_VIDEO_TRANSFER_SMPTE240M;
10695                 break;
10696               default:
10697                 break;
10698             }
10699
10700             switch (matrix) {
10701               case 1:
10702                 CUR_STREAM (stream)->colorimetry.matrix =
10703                     GST_VIDEO_COLOR_MATRIX_BT709;
10704                 break;
10705               case 6:
10706                 CUR_STREAM (stream)->colorimetry.matrix =
10707                     GST_VIDEO_COLOR_MATRIX_BT601;
10708                 break;
10709               case 7:
10710                 CUR_STREAM (stream)->colorimetry.matrix =
10711                     GST_VIDEO_COLOR_MATRIX_SMPTE240M;
10712                 break;
10713               case 9:
10714                 CUR_STREAM (stream)->colorimetry.matrix =
10715                     GST_VIDEO_COLOR_MATRIX_BT2020;
10716                 break;
10717               default:
10718                 break;
10719             }
10720
10721             CUR_STREAM (stream)->colorimetry.range =
10722                 full_range ? GST_VIDEO_COLOR_RANGE_0_255 :
10723                 GST_VIDEO_COLOR_RANGE_16_235;
10724           } else {
10725             GST_DEBUG_OBJECT (qtdemux, "Unsupported color type");
10726           }
10727         } else {
10728           GST_WARNING_OBJECT (qtdemux, "Invalid colr atom size");
10729         }
10730       }
10731
10732       if (esds) {
10733         gst_qtdemux_handle_esds (qtdemux, stream, entry, esds,
10734             stream->stream_tags);
10735       } else {
10736         switch (fourcc) {
10737           case FOURCC_H264:
10738           case FOURCC_avc1:
10739           case FOURCC_avc3:
10740           {
10741             gint len = QT_UINT32 (stsd_entry_data) - 0x56;
10742             const guint8 *avc_data = stsd_entry_data + 0x56;
10743
10744             /* find avcC */
10745             while (len >= 0x8) {
10746               gint size;
10747
10748               if (QT_UINT32 (avc_data) <= len)
10749                 size = QT_UINT32 (avc_data) - 0x8;
10750               else
10751                 size = len - 0x8;
10752
10753               if (size < 1)
10754                 /* No real data, so break out */
10755                 break;
10756
10757               switch (QT_FOURCC (avc_data + 0x4)) {
10758                 case FOURCC_avcC:
10759                 {
10760                   /* parse, if found */
10761                   GstBuffer *buf;
10762
10763                   GST_DEBUG_OBJECT (qtdemux, "found avcC codec_data in stsd");
10764
10765                   /* First 4 bytes are the length of the atom, the next 4 bytes
10766                    * are the fourcc, the next 1 byte is the version, and the
10767                    * subsequent bytes are profile_tier_level structure like data. */
10768                   gst_codec_utils_h264_caps_set_level_and_profile (entry->caps,
10769                       avc_data + 8 + 1, size - 1);
10770                   buf = gst_buffer_new_and_alloc (size);
10771                   gst_buffer_fill (buf, 0, avc_data + 0x8, size);
10772                   gst_caps_set_simple (entry->caps,
10773                       "codec_data", GST_TYPE_BUFFER, buf, NULL);
10774                   gst_buffer_unref (buf);
10775
10776                   break;
10777                 }
10778                 case FOURCC_strf:
10779                 {
10780                   GstBuffer *buf;
10781
10782                   GST_DEBUG_OBJECT (qtdemux, "found strf codec_data in stsd");
10783
10784                   /* First 4 bytes are the length of the atom, the next 4 bytes
10785                    * are the fourcc, next 40 bytes are BITMAPINFOHEADER,
10786                    * next 1 byte is the version, and the
10787                    * subsequent bytes are sequence parameter set like data. */
10788
10789                   size -= 40;   /* we'll be skipping BITMAPINFOHEADER */
10790                   if (size > 1) {
10791                     gst_codec_utils_h264_caps_set_level_and_profile
10792                         (entry->caps, avc_data + 8 + 40 + 1, size - 1);
10793
10794                     buf = gst_buffer_new_and_alloc (size);
10795                     gst_buffer_fill (buf, 0, avc_data + 8 + 40, size);
10796                     gst_caps_set_simple (entry->caps,
10797                         "codec_data", GST_TYPE_BUFFER, buf, NULL);
10798                     gst_buffer_unref (buf);
10799                   }
10800                   break;
10801                 }
10802                 case FOURCC_btrt:
10803                 {
10804                   guint avg_bitrate, max_bitrate;
10805
10806                   /* bufferSizeDB, maxBitrate and avgBitrate - 4 bytes each */
10807                   if (size < 12)
10808                     break;
10809
10810                   max_bitrate = QT_UINT32 (avc_data + 0xc);
10811                   avg_bitrate = QT_UINT32 (avc_data + 0x10);
10812
10813                   if (!max_bitrate && !avg_bitrate)
10814                     break;
10815
10816                   /* Some muxers seem to swap the average and maximum bitrates
10817                    * (I'm looking at you, YouTube), so we swap for sanity. */
10818                   if (max_bitrate > 0 && max_bitrate < avg_bitrate) {
10819                     guint temp = avg_bitrate;
10820
10821                     avg_bitrate = max_bitrate;
10822                     max_bitrate = temp;
10823                   }
10824
10825                   if (max_bitrate > 0 && max_bitrate < G_MAXUINT32) {
10826                     gst_tag_list_add (stream->stream_tags,
10827                         GST_TAG_MERGE_REPLACE, GST_TAG_MAXIMUM_BITRATE,
10828                         max_bitrate, NULL);
10829                   }
10830                   if (avg_bitrate > 0 && avg_bitrate < G_MAXUINT32) {
10831                     gst_tag_list_add (stream->stream_tags,
10832                         GST_TAG_MERGE_REPLACE, GST_TAG_BITRATE, avg_bitrate,
10833                         NULL);
10834                   }
10835
10836                   break;
10837                 }
10838
10839                 default:
10840                   break;
10841               }
10842
10843               len -= size + 8;
10844               avc_data += size + 8;
10845             }
10846
10847             break;
10848           }
10849           case FOURCC_H265:
10850           case FOURCC_hvc1:
10851           case FOURCC_hev1:
10852           {
10853             gint len = QT_UINT32 (stsd_entry_data) - 0x56;
10854             const guint8 *hevc_data = stsd_entry_data + 0x56;
10855
10856             /* find hevc */
10857             while (len >= 0x8) {
10858               gint size;
10859
10860               if (QT_UINT32 (hevc_data) <= len)
10861                 size = QT_UINT32 (hevc_data) - 0x8;
10862               else
10863                 size = len - 0x8;
10864
10865               if (size < 1)
10866                 /* No real data, so break out */
10867                 break;
10868
10869               switch (QT_FOURCC (hevc_data + 0x4)) {
10870                 case FOURCC_hvcC:
10871                 {
10872                   /* parse, if found */
10873                   GstBuffer *buf;
10874
10875                   GST_DEBUG_OBJECT (qtdemux, "found hvcC codec_data in stsd");
10876
10877                   /* First 4 bytes are the length of the atom, the next 4 bytes
10878                    * are the fourcc, the next 1 byte is the version, and the
10879                    * subsequent bytes are sequence parameter set like data. */
10880                   gst_codec_utils_h265_caps_set_level_tier_and_profile
10881                       (entry->caps, hevc_data + 8 + 1, size - 1);
10882
10883                   buf = gst_buffer_new_and_alloc (size);
10884                   gst_buffer_fill (buf, 0, hevc_data + 0x8, size);
10885                   gst_caps_set_simple (entry->caps,
10886                       "codec_data", GST_TYPE_BUFFER, buf, NULL);
10887                   gst_buffer_unref (buf);
10888                   break;
10889                 }
10890                 default:
10891                   break;
10892               }
10893               len -= size + 8;
10894               hevc_data += size + 8;
10895             }
10896             break;
10897           }
10898           case FOURCC_mp4v:
10899           case FOURCC_MP4V:
10900           case FOURCC_fmp4:
10901           case FOURCC_FMP4:
10902           case FOURCC_xvid:
10903           case FOURCC_XVID:
10904           {
10905             GNode *glbl;
10906
10907             GST_DEBUG_OBJECT (qtdemux, "found %" GST_FOURCC_FORMAT,
10908                 GST_FOURCC_ARGS (fourcc));
10909
10910             /* codec data might be in glbl extension atom */
10911             glbl = mp4v ?
10912                 qtdemux_tree_get_child_by_type (mp4v, FOURCC_glbl) : NULL;
10913             if (glbl) {
10914               guint8 *data;
10915               GstBuffer *buf;
10916               gint len;
10917
10918               GST_DEBUG_OBJECT (qtdemux, "found glbl data in stsd");
10919               data = glbl->data;
10920               len = QT_UINT32 (data);
10921               if (len > 0x8) {
10922                 len -= 0x8;
10923                 buf = gst_buffer_new_and_alloc (len);
10924                 gst_buffer_fill (buf, 0, data + 8, len);
10925                 gst_caps_set_simple (entry->caps,
10926                     "codec_data", GST_TYPE_BUFFER, buf, NULL);
10927                 gst_buffer_unref (buf);
10928               }
10929             }
10930             break;
10931           }
10932           case FOURCC_mjp2:
10933           {
10934             /* see annex I of the jpeg2000 spec */
10935             GNode *jp2h, *ihdr, *colr, *mjp2, *field, *prefix, *cmap, *cdef;
10936             const guint8 *data;
10937             const gchar *colorspace = NULL;
10938             gint ncomp = 0;
10939             guint32 ncomp_map = 0;
10940             gint32 *comp_map = NULL;
10941             guint32 nchan_def = 0;
10942             gint32 *chan_def = NULL;
10943
10944             GST_DEBUG_OBJECT (qtdemux, "found mjp2");
10945             /* some required atoms */
10946             mjp2 = qtdemux_tree_get_child_by_index (stsd, stsd_index);
10947             if (!mjp2)
10948               break;
10949             jp2h = qtdemux_tree_get_child_by_type (mjp2, FOURCC_jp2h);
10950             if (!jp2h)
10951               break;
10952
10953             /* number of components; redundant with info in codestream, but useful
10954                to a muxer */
10955             ihdr = qtdemux_tree_get_child_by_type (jp2h, FOURCC_ihdr);
10956             if (!ihdr || QT_UINT32 (ihdr->data) != 22)
10957               break;
10958             ncomp = QT_UINT16 (((guint8 *) ihdr->data) + 16);
10959
10960             colr = qtdemux_tree_get_child_by_type (jp2h, FOURCC_colr);
10961             if (!colr)
10962               break;
10963             GST_DEBUG_OBJECT (qtdemux, "found colr");
10964             /* extract colour space info */
10965             if (QT_UINT8 ((guint8 *) colr->data + 8) == 1) {
10966               switch (QT_UINT32 ((guint8 *) colr->data + 11)) {
10967                 case 16:
10968                   colorspace = "sRGB";
10969                   break;
10970                 case 17:
10971                   colorspace = "GRAY";
10972                   break;
10973                 case 18:
10974                   colorspace = "sYUV";
10975                   break;
10976                 default:
10977                   colorspace = NULL;
10978                   break;
10979               }
10980             }
10981             if (!colorspace)
10982               /* colr is required, and only values 16, 17, and 18 are specified,
10983                  so error if we have no colorspace */
10984               break;
10985
10986             /* extract component mapping */
10987             cmap = qtdemux_tree_get_child_by_type (jp2h, FOURCC_cmap);
10988             if (cmap) {
10989               guint32 cmap_len = 0;
10990               int i;
10991               cmap_len = QT_UINT32 (cmap->data);
10992               if (cmap_len >= 8) {
10993                 /* normal box, subtract off header */
10994                 cmap_len -= 8;
10995                 /* cmap: { u16 cmp; u8 mtyp; u8 pcol; }* */
10996                 if (cmap_len % 4 == 0) {
10997                   ncomp_map = (cmap_len / 4);
10998                   comp_map = g_new0 (gint32, ncomp_map);
10999                   for (i = 0; i < ncomp_map; i++) {
11000                     guint16 cmp;
11001                     guint8 mtyp, pcol;
11002                     cmp = QT_UINT16 (((guint8 *) cmap->data) + 8 + i * 4);
11003                     mtyp = QT_UINT8 (((guint8 *) cmap->data) + 8 + i * 4 + 2);
11004                     pcol = QT_UINT8 (((guint8 *) cmap->data) + 8 + i * 4 + 3);
11005                     comp_map[i] = (mtyp << 24) | (pcol << 16) | cmp;
11006                   }
11007                 }
11008               }
11009             }
11010             /* extract channel definitions */
11011             cdef = qtdemux_tree_get_child_by_type (jp2h, FOURCC_cdef);
11012             if (cdef) {
11013               guint32 cdef_len = 0;
11014               int i;
11015               cdef_len = QT_UINT32 (cdef->data);
11016               if (cdef_len >= 10) {
11017                 /* normal box, subtract off header and len */
11018                 cdef_len -= 10;
11019                 /* cdef: u16 n; { u16 cn; u16 typ; u16 asoc; }* */
11020                 if (cdef_len % 6 == 0) {
11021                   nchan_def = (cdef_len / 6);
11022                   chan_def = g_new0 (gint32, nchan_def);
11023                   for (i = 0; i < nchan_def; i++)
11024                     chan_def[i] = -1;
11025                   for (i = 0; i < nchan_def; i++) {
11026                     guint16 cn, typ, asoc;
11027                     cn = QT_UINT16 (((guint8 *) cdef->data) + 10 + i * 6);
11028                     typ = QT_UINT16 (((guint8 *) cdef->data) + 10 + i * 6 + 2);
11029                     asoc = QT_UINT16 (((guint8 *) cdef->data) + 10 + i * 6 + 4);
11030                     if (cn < nchan_def) {
11031                       switch (typ) {
11032                         case 0:
11033                           chan_def[cn] = asoc;
11034                           break;
11035                         case 1:
11036                           chan_def[cn] = 0;     /* alpha */
11037                           break;
11038                         default:
11039                           chan_def[cn] = -typ;
11040                       }
11041                     }
11042                   }
11043                 }
11044               }
11045             }
11046
11047             gst_caps_set_simple (entry->caps,
11048                 "num-components", G_TYPE_INT, ncomp, NULL);
11049             gst_caps_set_simple (entry->caps,
11050                 "colorspace", G_TYPE_STRING, colorspace, NULL);
11051
11052             if (comp_map) {
11053               GValue arr = { 0, };
11054               GValue elt = { 0, };
11055               int i;
11056               g_value_init (&arr, GST_TYPE_ARRAY);
11057               g_value_init (&elt, G_TYPE_INT);
11058               for (i = 0; i < ncomp_map; i++) {
11059                 g_value_set_int (&elt, comp_map[i]);
11060                 gst_value_array_append_value (&arr, &elt);
11061               }
11062               gst_structure_set_value (gst_caps_get_structure (entry->caps, 0),
11063                   "component-map", &arr);
11064               g_value_unset (&elt);
11065               g_value_unset (&arr);
11066               g_free (comp_map);
11067             }
11068
11069             if (chan_def) {
11070               GValue arr = { 0, };
11071               GValue elt = { 0, };
11072               int i;
11073               g_value_init (&arr, GST_TYPE_ARRAY);
11074               g_value_init (&elt, G_TYPE_INT);
11075               for (i = 0; i < nchan_def; i++) {
11076                 g_value_set_int (&elt, chan_def[i]);
11077                 gst_value_array_append_value (&arr, &elt);
11078               }
11079               gst_structure_set_value (gst_caps_get_structure (entry->caps, 0),
11080                   "channel-definitions", &arr);
11081               g_value_unset (&elt);
11082               g_value_unset (&arr);
11083               g_free (chan_def);
11084             }
11085
11086             /* some optional atoms */
11087             field = qtdemux_tree_get_child_by_type (mjp2, FOURCC_fiel);
11088             prefix = qtdemux_tree_get_child_by_type (mjp2, FOURCC_jp2x);
11089
11090             /* indicate possible fields in caps */
11091             if (field) {
11092               data = (guint8 *) field->data + 8;
11093               if (*data != 1)
11094                 gst_caps_set_simple (entry->caps, "fields", G_TYPE_INT,
11095                     (gint) * data, NULL);
11096             }
11097             /* add codec_data if provided */
11098             if (prefix) {
11099               GstBuffer *buf;
11100               gint len;
11101
11102               GST_DEBUG_OBJECT (qtdemux, "found prefix data in stsd");
11103               data = prefix->data;
11104               len = QT_UINT32 (data);
11105               if (len > 0x8) {
11106                 len -= 0x8;
11107                 buf = gst_buffer_new_and_alloc (len);
11108                 gst_buffer_fill (buf, 0, data + 8, len);
11109                 gst_caps_set_simple (entry->caps,
11110                     "codec_data", GST_TYPE_BUFFER, buf, NULL);
11111                 gst_buffer_unref (buf);
11112               }
11113             }
11114             break;
11115           }
11116           case FOURCC_SVQ3:
11117           case FOURCC_VP31:
11118           {
11119             GstBuffer *buf;
11120             GstBuffer *seqh = NULL;
11121             const guint8 *gamma_data = NULL;
11122             gint len = QT_UINT32 (stsd_data);   /* FIXME review - why put the whole stsd in codec data? */
11123
11124             qtdemux_parse_svq3_stsd_data (qtdemux, stsd_entry_data, &gamma_data,
11125                 &seqh);
11126             if (gamma_data) {
11127               gst_caps_set_simple (entry->caps, "applied-gamma", G_TYPE_DOUBLE,
11128                   QT_FP32 (gamma_data), NULL);
11129             }
11130             if (seqh) {
11131               /* sorry for the bad name, but we don't know what this is, other
11132                * than its own fourcc */
11133               gst_caps_set_simple (entry->caps, "seqh", GST_TYPE_BUFFER, seqh,
11134                   NULL);
11135               gst_buffer_unref (seqh);
11136             }
11137
11138             GST_DEBUG_OBJECT (qtdemux, "found codec_data in stsd");
11139             buf = gst_buffer_new_and_alloc (len);
11140             gst_buffer_fill (buf, 0, stsd_data, len);
11141             gst_caps_set_simple (entry->caps,
11142                 "codec_data", GST_TYPE_BUFFER, buf, NULL);
11143             gst_buffer_unref (buf);
11144             break;
11145           }
11146           case FOURCC_jpeg:
11147           {
11148             /* https://developer.apple.com/standards/qtff-2001.pdf,
11149              * page 92, "Video Sample Description", under table 3.1 */
11150             GstByteReader br;
11151
11152             const gint compressor_offset =
11153                 16 + 4 + 4 * 3 + 2 * 2 + 2 * 4 + 4 + 2;
11154             const gint min_size = compressor_offset + 32 + 2 + 2;
11155             GNode *jpeg;
11156             guint32 len;
11157             guint16 color_table_id = 0;
11158             gboolean ok;
11159
11160             GST_DEBUG_OBJECT (qtdemux, "found jpeg");
11161
11162             /* recover information on interlaced/progressive */
11163             jpeg = qtdemux_tree_get_child_by_type (stsd, FOURCC_jpeg);
11164             if (!jpeg)
11165               break;
11166
11167             len = QT_UINT32 (jpeg->data);
11168             GST_DEBUG_OBJECT (qtdemux, "Found jpeg: len %u, need %d", len,
11169                 min_size);
11170             if (len >= min_size) {
11171               gst_byte_reader_init (&br, jpeg->data, len);
11172
11173               gst_byte_reader_skip (&br, compressor_offset + 32 + 2);
11174               gst_byte_reader_get_uint16_le (&br, &color_table_id);
11175               if (color_table_id != 0) {
11176                 /* the spec says there can be concatenated chunks in the data, and we want
11177                  * to find one called field. Walk through them. */
11178                 gint offset = min_size;
11179                 while (offset + 8 < len) {
11180                   guint32 size = 0, tag;
11181                   ok = gst_byte_reader_get_uint32_le (&br, &size);
11182                   ok &= gst_byte_reader_get_uint32_le (&br, &tag);
11183                   if (!ok || size < 8) {
11184                     GST_WARNING_OBJECT (qtdemux,
11185                         "Failed to walk optional chunk list");
11186                     break;
11187                   }
11188                   GST_DEBUG_OBJECT (qtdemux,
11189                       "Found optional %4.4s chunk, size %u",
11190                       (const char *) &tag, size);
11191                   if (tag == FOURCC_fiel) {
11192                     guint8 n_fields = 0, ordering = 0;
11193                     gst_byte_reader_get_uint8 (&br, &n_fields);
11194                     gst_byte_reader_get_uint8 (&br, &ordering);
11195                     if (n_fields == 1 || n_fields == 2) {
11196                       GST_DEBUG_OBJECT (qtdemux,
11197                           "Found fiel tag with %u fields, ordering %u",
11198                           n_fields, ordering);
11199                       if (n_fields == 2)
11200                         gst_caps_set_simple (CUR_STREAM (stream)->caps,
11201                             "interlace-mode", G_TYPE_STRING, "interleaved",
11202                             NULL);
11203                     } else {
11204                       GST_WARNING_OBJECT (qtdemux,
11205                           "Found fiel tag with invalid fields (%u)", n_fields);
11206                     }
11207                   }
11208                   offset += size;
11209                 }
11210               } else {
11211                 GST_DEBUG_OBJECT (qtdemux,
11212                     "Color table ID is 0, not trying to get interlacedness");
11213               }
11214             } else {
11215               GST_WARNING_OBJECT (qtdemux,
11216                   "Length of jpeg chunk is too small, not trying to get interlacedness");
11217             }
11218
11219             break;
11220           }
11221           case FOURCC_rle_:
11222           case FOURCC_WRLE:
11223           {
11224             gst_caps_set_simple (entry->caps,
11225                 "depth", G_TYPE_INT, QT_UINT16 (stsd_entry_data + offset + 66),
11226                 NULL);
11227             break;
11228           }
11229           case FOURCC_XiTh:
11230           {
11231             GNode *xith, *xdxt;
11232
11233             GST_DEBUG_OBJECT (qtdemux, "found XiTh");
11234             xith = qtdemux_tree_get_child_by_index (stsd, stsd_index);
11235             if (!xith)
11236               break;
11237
11238             xdxt = qtdemux_tree_get_child_by_type (xith, FOURCC_XdxT);
11239             if (!xdxt)
11240               break;
11241
11242             GST_DEBUG_OBJECT (qtdemux, "found XdxT node");
11243             /* collect the headers and store them in a stream list so that we can
11244              * send them out first */
11245             qtdemux_parse_theora_extension (qtdemux, stream, xdxt);
11246             break;
11247           }
11248           case FOURCC_ovc1:
11249           {
11250             GNode *ovc1;
11251             guint8 *ovc1_data;
11252             guint ovc1_len;
11253             GstBuffer *buf;
11254
11255             GST_DEBUG_OBJECT (qtdemux, "parse ovc1 header");
11256             ovc1 = qtdemux_tree_get_child_by_index (stsd, stsd_index);
11257             if (!ovc1)
11258               break;
11259             ovc1_data = ovc1->data;
11260             ovc1_len = QT_UINT32 (ovc1_data);
11261             if (ovc1_len <= 198) {
11262               GST_WARNING_OBJECT (qtdemux, "Too small ovc1 header, skipping");
11263               break;
11264             }
11265             buf = gst_buffer_new_and_alloc (ovc1_len - 198);
11266             gst_buffer_fill (buf, 0, ovc1_data + 198, ovc1_len - 198);
11267             gst_caps_set_simple (entry->caps,
11268                 "codec_data", GST_TYPE_BUFFER, buf, NULL);
11269             gst_buffer_unref (buf);
11270             break;
11271           }
11272           case FOURCC_vc_1:
11273           {
11274             gint len = QT_UINT32 (stsd_entry_data) - 0x56;
11275             const guint8 *vc1_data = stsd_entry_data + 0x56;
11276
11277             /* find dvc1 */
11278             while (len >= 8) {
11279               gint size;
11280
11281               if (QT_UINT32 (vc1_data) <= len)
11282                 size = QT_UINT32 (vc1_data) - 8;
11283               else
11284                 size = len - 8;
11285
11286               if (size < 1)
11287                 /* No real data, so break out */
11288                 break;
11289
11290               switch (QT_FOURCC (vc1_data + 0x4)) {
11291                 case GST_MAKE_FOURCC ('d', 'v', 'c', '1'):
11292                 {
11293                   GstBuffer *buf;
11294
11295                   GST_DEBUG_OBJECT (qtdemux, "found dvc1 codec_data in stsd");
11296                   buf = gst_buffer_new_and_alloc (size);
11297                   gst_buffer_fill (buf, 0, vc1_data + 8, size);
11298                   gst_caps_set_simple (entry->caps,
11299                       "codec_data", GST_TYPE_BUFFER, buf, NULL);
11300                   gst_buffer_unref (buf);
11301                   break;
11302                 }
11303                 default:
11304                   break;
11305               }
11306               len -= size + 8;
11307               vc1_data += size + 8;
11308             }
11309             break;
11310           }
11311           case FOURCC_av01:
11312           {
11313             gint len = QT_UINT32 (stsd_entry_data) - 0x56;
11314             const guint8 *av1_data = stsd_entry_data + 0x56;
11315
11316             /* find av1C */
11317             while (len >= 0x8) {
11318               gint size;
11319
11320               if (QT_UINT32 (av1_data) <= len)
11321                 size = QT_UINT32 (av1_data) - 0x8;
11322               else
11323                 size = len - 0x8;
11324
11325               if (size < 1)
11326                 /* No real data, so break out */
11327                 break;
11328
11329               switch (QT_FOURCC (av1_data + 0x4)) {
11330                 case FOURCC_av1C:
11331                 {
11332                   /* parse, if found */
11333                   GstBuffer *buf;
11334                   guint8 pres_delay_field;
11335
11336                   GST_DEBUG_OBJECT (qtdemux,
11337                       "found av1C codec_data in stsd of size %d", size);
11338
11339                   /* not enough data, just ignore and hope for the best */
11340                   if (size < 5)
11341                     break;
11342
11343                   /* Content is:
11344                    * 4 bytes: atom length
11345                    * 4 bytes: fourcc
11346                    * 1 byte: version
11347                    * 3 bytes: flags
11348                    * 3 bits: reserved
11349                    * 1 bits:  initial_presentation_delay_present
11350                    * 4 bits: initial_presentation_delay (if present else reserved
11351                    * rest: OBUs.
11352                    */
11353
11354                   if (av1_data[9] != 0) {
11355                     GST_WARNING ("Unknown version %d of av1C box", av1_data[9]);
11356                     break;
11357                   }
11358
11359                   /* We skip initial_presentation_delay* for now */
11360                   pres_delay_field = *(av1_data + 12);
11361                   if (pres_delay_field & (1 << 5)) {
11362                     gst_caps_set_simple (entry->caps,
11363                         "presentation-delay", G_TYPE_INT,
11364                         (gint) (pres_delay_field & 0x0F) + 1, NULL);
11365                   }
11366                   if (size > 5) {
11367                     buf = gst_buffer_new_and_alloc (size - 5);
11368                     GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_HEADER);
11369                     gst_buffer_fill (buf, 0, av1_data + 13, size - 5);
11370                     gst_caps_set_simple (entry->caps,
11371                         "codec_data", GST_TYPE_BUFFER, buf, NULL);
11372                     gst_buffer_unref (buf);
11373                   }
11374                   break;
11375                 }
11376                 default:
11377                   break;
11378               }
11379
11380               len -= size + 8;
11381               av1_data += size + 8;
11382             }
11383
11384             break;
11385           }
11386           default:
11387             break;
11388         }
11389       }
11390
11391       GST_INFO_OBJECT (qtdemux,
11392           "type %" GST_FOURCC_FORMAT " caps %" GST_PTR_FORMAT,
11393           GST_FOURCC_ARGS (fourcc), entry->caps);
11394
11395     } else if (stream->subtype == FOURCC_soun) {
11396       GNode *wave;
11397       int version, samplesize;
11398       guint16 compression_id;
11399       gboolean amrwb = FALSE;
11400
11401       offset = 16;
11402       /* sample description entry (16) + sound sample description v0 (20) */
11403       if (len < 36)
11404         goto corrupt_file;
11405
11406       version = QT_UINT32 (stsd_entry_data + offset);
11407       entry->n_channels = QT_UINT16 (stsd_entry_data + offset + 8);
11408       samplesize = QT_UINT16 (stsd_entry_data + offset + 10);
11409       compression_id = QT_UINT16 (stsd_entry_data + offset + 12);
11410       entry->rate = QT_FP32 (stsd_entry_data + offset + 16);
11411
11412       GST_LOG_OBJECT (qtdemux, "version/rev:      %08x", version);
11413       GST_LOG_OBJECT (qtdemux, "vendor:           %08x",
11414           QT_UINT32 (stsd_entry_data + offset + 4));
11415       GST_LOG_OBJECT (qtdemux, "n_channels:       %d", entry->n_channels);
11416       GST_LOG_OBJECT (qtdemux, "sample_size:      %d", samplesize);
11417       GST_LOG_OBJECT (qtdemux, "compression_id:   %d", compression_id);
11418       GST_LOG_OBJECT (qtdemux, "packet size:      %d",
11419           QT_UINT16 (stsd_entry_data + offset + 14));
11420       GST_LOG_OBJECT (qtdemux, "sample rate:      %g", entry->rate);
11421
11422       if (compression_id == 0xfffe)
11423         entry->sampled = TRUE;
11424
11425       /* first assume uncompressed audio */
11426       entry->bytes_per_sample = samplesize / 8;
11427       entry->samples_per_frame = entry->n_channels;
11428       entry->bytes_per_frame = entry->n_channels * entry->bytes_per_sample;
11429       entry->samples_per_packet = entry->samples_per_frame;
11430       entry->bytes_per_packet = entry->bytes_per_sample;
11431
11432       offset = 36;
11433       switch (fourcc) {
11434           /* Yes, these have to be hard-coded */
11435         case FOURCC_MAC6:
11436         {
11437           entry->samples_per_packet = 6;
11438           entry->bytes_per_packet = 1;
11439           entry->bytes_per_frame = 1 * entry->n_channels;
11440           entry->bytes_per_sample = 1;
11441           entry->samples_per_frame = 6 * entry->n_channels;
11442           break;
11443         }
11444         case FOURCC_MAC3:
11445         {
11446           entry->samples_per_packet = 3;
11447           entry->bytes_per_packet = 1;
11448           entry->bytes_per_frame = 1 * entry->n_channels;
11449           entry->bytes_per_sample = 1;
11450           entry->samples_per_frame = 3 * entry->n_channels;
11451           break;
11452         }
11453         case FOURCC_ima4:
11454         {
11455           entry->samples_per_packet = 64;
11456           entry->bytes_per_packet = 34;
11457           entry->bytes_per_frame = 34 * entry->n_channels;
11458           entry->bytes_per_sample = 2;
11459           entry->samples_per_frame = 64 * entry->n_channels;
11460           break;
11461         }
11462         case FOURCC_ulaw:
11463         case FOURCC_alaw:
11464         {
11465           entry->samples_per_packet = 1;
11466           entry->bytes_per_packet = 1;
11467           entry->bytes_per_frame = 1 * entry->n_channels;
11468           entry->bytes_per_sample = 1;
11469           entry->samples_per_frame = 1 * entry->n_channels;
11470           break;
11471         }
11472         case FOURCC_agsm:
11473         {
11474           entry->samples_per_packet = 160;
11475           entry->bytes_per_packet = 33;
11476           entry->bytes_per_frame = 33 * entry->n_channels;
11477           entry->bytes_per_sample = 2;
11478           entry->samples_per_frame = 160 * entry->n_channels;
11479           break;
11480         }
11481         default:
11482           break;
11483       }
11484
11485       if (version == 0x00010000) {
11486         /* sample description entry (16) + sound sample description v1 (20+16) */
11487         if (len < 52)
11488           goto corrupt_file;
11489
11490         switch (fourcc) {
11491           case FOURCC_twos:
11492           case FOURCC_sowt:
11493           case FOURCC_raw_:
11494           case FOURCC_lpcm:
11495             break;
11496           default:
11497           {
11498             /* only parse extra decoding config for non-pcm audio */
11499             entry->samples_per_packet = QT_UINT32 (stsd_entry_data + offset);
11500             entry->bytes_per_packet = QT_UINT32 (stsd_entry_data + offset + 4);
11501             entry->bytes_per_frame = QT_UINT32 (stsd_entry_data + offset + 8);
11502             entry->bytes_per_sample = QT_UINT32 (stsd_entry_data + offset + 12);
11503
11504             GST_LOG_OBJECT (qtdemux, "samples/packet:   %d",
11505                 entry->samples_per_packet);
11506             GST_LOG_OBJECT (qtdemux, "bytes/packet:     %d",
11507                 entry->bytes_per_packet);
11508             GST_LOG_OBJECT (qtdemux, "bytes/frame:      %d",
11509                 entry->bytes_per_frame);
11510             GST_LOG_OBJECT (qtdemux, "bytes/sample:     %d",
11511                 entry->bytes_per_sample);
11512
11513             if (!entry->sampled && entry->bytes_per_packet) {
11514               entry->samples_per_frame = (entry->bytes_per_frame /
11515                   entry->bytes_per_packet) * entry->samples_per_packet;
11516               GST_LOG_OBJECT (qtdemux, "samples/frame:    %d",
11517                   entry->samples_per_frame);
11518             }
11519             break;
11520           }
11521         }
11522       } else if (version == 0x00020000) {
11523         union
11524         {
11525           gdouble fp;
11526           guint64 val;
11527         } qtfp;
11528
11529         /* sample description entry (16) + sound sample description v2 (56) */
11530         if (len < 72)
11531           goto corrupt_file;
11532
11533         qtfp.val = QT_UINT64 (stsd_entry_data + offset + 4);
11534         entry->rate = qtfp.fp;
11535         entry->n_channels = QT_UINT32 (stsd_entry_data + offset + 12);
11536
11537         GST_LOG_OBJECT (qtdemux, "Sound sample description Version 2");
11538         GST_LOG_OBJECT (qtdemux, "sample rate:        %g", entry->rate);
11539         GST_LOG_OBJECT (qtdemux, "n_channels:         %d", entry->n_channels);
11540         GST_LOG_OBJECT (qtdemux, "bits/channel:       %d",
11541             QT_UINT32 (stsd_entry_data + offset + 20));
11542         GST_LOG_OBJECT (qtdemux, "format flags:       %X",
11543             QT_UINT32 (stsd_entry_data + offset + 24));
11544         GST_LOG_OBJECT (qtdemux, "bytes/packet:       %d",
11545             QT_UINT32 (stsd_entry_data + offset + 28));
11546         GST_LOG_OBJECT (qtdemux, "LPCM frames/packet: %d",
11547             QT_UINT32 (stsd_entry_data + offset + 32));
11548       } else if (version != 0x00000) {
11549         GST_WARNING_OBJECT (qtdemux, "unknown audio STSD version %08x",
11550             version);
11551       }
11552
11553       if (entry->caps)
11554         gst_caps_unref (entry->caps);
11555
11556       entry->caps = qtdemux_audio_caps (qtdemux, stream, entry, fourcc,
11557           stsd_entry_data + 32, len - 16, &codec);
11558
11559       switch (fourcc) {
11560         case FOURCC_in24:
11561         {
11562           GNode *enda;
11563           GNode *in24;
11564
11565           in24 = qtdemux_tree_get_child_by_type (stsd, FOURCC_in24);
11566
11567           enda = qtdemux_tree_get_child_by_type (in24, FOURCC_enda);
11568           if (!enda) {
11569             wave = qtdemux_tree_get_child_by_type (in24, FOURCC_wave);
11570             if (wave)
11571               enda = qtdemux_tree_get_child_by_type (wave, FOURCC_enda);
11572           }
11573           if (enda) {
11574             int enda_value = QT_UINT16 ((guint8 *) enda->data + 8);
11575             gst_caps_set_simple (entry->caps,
11576                 "format", G_TYPE_STRING, (enda_value) ? "S24LE" : "S24BE",
11577                 NULL);
11578           }
11579           break;
11580         }
11581         case FOURCC_owma:
11582         {
11583           const guint8 *owma_data;
11584           const gchar *codec_name = NULL;
11585           guint owma_len;
11586           GstBuffer *buf;
11587           gint version = 1;
11588           /* from http://msdn.microsoft.com/en-us/library/dd757720(VS.85).aspx */
11589           /* FIXME this should also be gst_riff_strf_auds,
11590            * but the latter one is actually missing bits-per-sample :( */
11591           typedef struct
11592           {
11593             gint16 wFormatTag;
11594             gint16 nChannels;
11595             gint32 nSamplesPerSec;
11596             gint32 nAvgBytesPerSec;
11597             gint16 nBlockAlign;
11598             gint16 wBitsPerSample;
11599             gint16 cbSize;
11600           } WAVEFORMATEX;
11601           WAVEFORMATEX *wfex;
11602
11603           GST_DEBUG_OBJECT (qtdemux, "parse owma");
11604           owma_data = stsd_entry_data;
11605           owma_len = QT_UINT32 (owma_data);
11606           if (owma_len <= 54) {
11607             GST_WARNING_OBJECT (qtdemux, "Too small owma header, skipping");
11608             break;
11609           }
11610           wfex = (WAVEFORMATEX *) (owma_data + 36);
11611           buf = gst_buffer_new_and_alloc (owma_len - 54);
11612           gst_buffer_fill (buf, 0, owma_data + 54, owma_len - 54);
11613           if (wfex->wFormatTag == 0x0161) {
11614             codec_name = "Windows Media Audio";
11615             version = 2;
11616           } else if (wfex->wFormatTag == 0x0162) {
11617             codec_name = "Windows Media Audio 9 Pro";
11618             version = 3;
11619           } else if (wfex->wFormatTag == 0x0163) {
11620             codec_name = "Windows Media Audio 9 Lossless";
11621             /* is that correct? gstffmpegcodecmap.c is missing it, but
11622              * fluendo codec seems to support it */
11623             version = 4;
11624           }
11625
11626           gst_caps_set_simple (entry->caps,
11627               "codec_data", GST_TYPE_BUFFER, buf,
11628               "wmaversion", G_TYPE_INT, version,
11629               "block_align", G_TYPE_INT,
11630               GST_READ_UINT16_LE (&wfex->nBlockAlign), "bitrate", G_TYPE_INT,
11631               GST_READ_UINT32_LE (&wfex->nAvgBytesPerSec), "width", G_TYPE_INT,
11632               GST_READ_UINT16_LE (&wfex->wBitsPerSample), "depth", G_TYPE_INT,
11633               GST_READ_UINT16_LE (&wfex->wBitsPerSample), NULL);
11634           gst_buffer_unref (buf);
11635
11636           if (codec_name) {
11637             g_free (codec);
11638             codec = g_strdup (codec_name);
11639           }
11640           break;
11641         }
11642         case FOURCC_wma_:
11643         {
11644           gint len = QT_UINT32 (stsd_entry_data) - offset;
11645           const guint8 *wfex_data = stsd_entry_data + offset;
11646           const gchar *codec_name = NULL;
11647           gint version = 1;
11648           /* from http://msdn.microsoft.com/en-us/library/dd757720(VS.85).aspx */
11649           /* FIXME this should also be gst_riff_strf_auds,
11650            * but the latter one is actually missing bits-per-sample :( */
11651           typedef struct
11652           {
11653             gint16 wFormatTag;
11654             gint16 nChannels;
11655             gint32 nSamplesPerSec;
11656             gint32 nAvgBytesPerSec;
11657             gint16 nBlockAlign;
11658             gint16 wBitsPerSample;
11659             gint16 cbSize;
11660           } WAVEFORMATEX;
11661           WAVEFORMATEX wfex;
11662
11663           /* FIXME: unify with similar wavformatex parsing code above */
11664           GST_DEBUG_OBJECT (qtdemux, "parse wma, looking for wfex");
11665
11666           /* find wfex */
11667           while (len >= 8) {
11668             gint size;
11669
11670             if (QT_UINT32 (wfex_data) <= len)
11671               size = QT_UINT32 (wfex_data) - 8;
11672             else
11673               size = len - 8;
11674
11675             if (size < 1)
11676               /* No real data, so break out */
11677               break;
11678
11679             switch (QT_FOURCC (wfex_data + 4)) {
11680               case GST_MAKE_FOURCC ('w', 'f', 'e', 'x'):
11681               {
11682                 GST_DEBUG_OBJECT (qtdemux, "found wfex in stsd");
11683
11684                 if (size < 8 + 18)
11685                   break;
11686
11687                 wfex.wFormatTag = GST_READ_UINT16_LE (wfex_data + 8 + 0);
11688                 wfex.nChannels = GST_READ_UINT16_LE (wfex_data + 8 + 2);
11689                 wfex.nSamplesPerSec = GST_READ_UINT32_LE (wfex_data + 8 + 4);
11690                 wfex.nAvgBytesPerSec = GST_READ_UINT32_LE (wfex_data + 8 + 8);
11691                 wfex.nBlockAlign = GST_READ_UINT16_LE (wfex_data + 8 + 12);
11692                 wfex.wBitsPerSample = GST_READ_UINT16_LE (wfex_data + 8 + 14);
11693                 wfex.cbSize = GST_READ_UINT16_LE (wfex_data + 8 + 16);
11694
11695                 GST_LOG_OBJECT (qtdemux, "Found wfex box in stsd:");
11696                 GST_LOG_OBJECT (qtdemux, "FormatTag = 0x%04x, Channels = %u, "
11697                     "SamplesPerSec = %u, AvgBytesPerSec = %u, BlockAlign = %u, "
11698                     "BitsPerSample = %u, Size = %u", wfex.wFormatTag,
11699                     wfex.nChannels, wfex.nSamplesPerSec, wfex.nAvgBytesPerSec,
11700                     wfex.nBlockAlign, wfex.wBitsPerSample, wfex.cbSize);
11701
11702                 if (wfex.wFormatTag == 0x0161) {
11703                   codec_name = "Windows Media Audio";
11704                   version = 2;
11705                 } else if (wfex.wFormatTag == 0x0162) {
11706                   codec_name = "Windows Media Audio 9 Pro";
11707                   version = 3;
11708                 } else if (wfex.wFormatTag == 0x0163) {
11709                   codec_name = "Windows Media Audio 9 Lossless";
11710                   /* is that correct? gstffmpegcodecmap.c is missing it, but
11711                    * fluendo codec seems to support it */
11712                   version = 4;
11713                 }
11714
11715                 gst_caps_set_simple (entry->caps,
11716                     "wmaversion", G_TYPE_INT, version,
11717                     "block_align", G_TYPE_INT, wfex.nBlockAlign,
11718                     "bitrate", G_TYPE_INT, wfex.nAvgBytesPerSec,
11719                     "width", G_TYPE_INT, wfex.wBitsPerSample,
11720                     "depth", G_TYPE_INT, wfex.wBitsPerSample, NULL);
11721
11722                 if (size > wfex.cbSize) {
11723                   GstBuffer *buf;
11724
11725                   buf = gst_buffer_new_and_alloc (size - wfex.cbSize);
11726                   gst_buffer_fill (buf, 0, wfex_data + 8 + wfex.cbSize,
11727                       size - wfex.cbSize);
11728                   gst_caps_set_simple (entry->caps,
11729                       "codec_data", GST_TYPE_BUFFER, buf, NULL);
11730                   gst_buffer_unref (buf);
11731                 } else {
11732                   GST_WARNING_OBJECT (qtdemux, "no codec data");
11733                 }
11734
11735                 if (codec_name) {
11736                   g_free (codec);
11737                   codec = g_strdup (codec_name);
11738                 }
11739                 break;
11740               }
11741               default:
11742                 break;
11743             }
11744             len -= size + 8;
11745             wfex_data += size + 8;
11746           }
11747           break;
11748         }
11749         case FOURCC_opus:
11750         {
11751           const guint8 *opus_data;
11752           guint8 *channel_mapping = NULL;
11753           guint32 rate;
11754           guint8 channels;
11755           guint8 channel_mapping_family;
11756           guint8 stream_count;
11757           guint8 coupled_count;
11758           guint8 i;
11759
11760           opus_data = stsd_entry_data;
11761
11762           channels = GST_READ_UINT8 (opus_data + 45);
11763           rate = GST_READ_UINT32_LE (opus_data + 48);
11764           channel_mapping_family = GST_READ_UINT8 (opus_data + 54);
11765           stream_count = GST_READ_UINT8 (opus_data + 55);
11766           coupled_count = GST_READ_UINT8 (opus_data + 56);
11767
11768           if (channels > 0) {
11769             channel_mapping = g_malloc (channels * sizeof (guint8));
11770             for (i = 0; i < channels; i++)
11771               channel_mapping[i] = GST_READ_UINT8 (opus_data + i + 57);
11772           }
11773
11774           entry->caps = gst_codec_utils_opus_create_caps (rate, channels,
11775               channel_mapping_family, stream_count, coupled_count,
11776               channel_mapping);
11777           break;
11778         }
11779         default:
11780           break;
11781       }
11782
11783       if (codec) {
11784         GstStructure *s;
11785         gint bitrate = 0;
11786
11787         gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
11788             GST_TAG_AUDIO_CODEC, codec, NULL);
11789         g_free (codec);
11790         codec = NULL;
11791
11792         /* some bitrate info may have ended up in caps */
11793         s = gst_caps_get_structure (entry->caps, 0);
11794         gst_structure_get_int (s, "bitrate", &bitrate);
11795         if (bitrate > 0)
11796           gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
11797               GST_TAG_BITRATE, bitrate, NULL);
11798       }
11799
11800       mp4a = qtdemux_tree_get_child_by_index (stsd, stsd_index);
11801       if (!stream->protected) {
11802       } else {
11803         if (QTDEMUX_TREE_NODE_FOURCC (mp4v) != FOURCC_encv) {
11804           mp4v = NULL;
11805         }
11806       }
11807       if (stream->protected && fourcc == FOURCC_mp4a) {
11808         if (QTDEMUX_TREE_NODE_FOURCC (mp4a) != FOURCC_enca) {
11809           mp4a = NULL;
11810         }
11811       } else {
11812         if (QTDEMUX_TREE_NODE_FOURCC (mp4a) != FOURCC_mp4a) {
11813           mp4a = NULL;
11814         }
11815       }
11816
11817       wave = NULL;
11818       esds = NULL;
11819       if (mp4a) {
11820         wave = qtdemux_tree_get_child_by_type (mp4a, FOURCC_wave);
11821         if (wave)
11822           esds = qtdemux_tree_get_child_by_type (wave, FOURCC_esds);
11823         if (!esds)
11824           esds = qtdemux_tree_get_child_by_type (mp4a, FOURCC_esds);
11825       }
11826
11827
11828       /* If the fourcc's bottom 16 bits gives 'sm', then the top
11829          16 bits is a byte-swapped wave-style codec identifier,
11830          and we can find a WAVE header internally to a 'wave' atom here.
11831          This can more clearly be thought of as 'ms' as the top 16 bits, and a
11832          codec id as the bottom 16 bits - but byte-swapped to store in QT (which
11833          is big-endian).
11834        */
11835       if ((fourcc & 0xffff) == (('s' << 8) | 'm')) {
11836         if (len < offset + 20) {
11837           GST_WARNING_OBJECT (qtdemux, "No wave atom in MS-style audio");
11838         } else {
11839           guint32 datalen = QT_UINT32 (stsd_entry_data + offset + 16);
11840           const guint8 *data = stsd_entry_data + offset + 16;
11841           GNode *wavenode;
11842           GNode *waveheadernode;
11843
11844           wavenode = g_node_new ((guint8 *) data);
11845           if (qtdemux_parse_node (qtdemux, wavenode, data, datalen)) {
11846             const guint8 *waveheader;
11847             guint32 headerlen;
11848
11849             waveheadernode = qtdemux_tree_get_child_by_type (wavenode, fourcc);
11850             if (waveheadernode) {
11851               waveheader = (const guint8 *) waveheadernode->data;
11852               headerlen = QT_UINT32 (waveheader);
11853
11854               if (headerlen > 8) {
11855                 gst_riff_strf_auds *header = NULL;
11856                 GstBuffer *headerbuf;
11857                 GstBuffer *extra;
11858
11859                 waveheader += 8;
11860                 headerlen -= 8;
11861
11862                 headerbuf = gst_buffer_new_and_alloc (headerlen);
11863                 gst_buffer_fill (headerbuf, 0, waveheader, headerlen);
11864
11865                 if (gst_riff_parse_strf_auds (GST_ELEMENT_CAST (qtdemux),
11866                         headerbuf, &header, &extra)) {
11867                   gst_caps_unref (entry->caps);
11868                   /* FIXME: Need to do something with the channel reorder map */
11869                   entry->caps =
11870                       gst_riff_create_audio_caps (header->format, NULL, header,
11871                       extra, NULL, NULL, NULL);
11872
11873                   if (extra)
11874                     gst_buffer_unref (extra);
11875                   g_free (header);
11876                 }
11877               }
11878             } else
11879               GST_DEBUG ("Didn't find waveheadernode for this codec");
11880           }
11881           g_node_destroy (wavenode);
11882         }
11883       } else if (esds) {
11884         gst_qtdemux_handle_esds (qtdemux, stream, entry, esds,
11885             stream->stream_tags);
11886       } else {
11887         switch (fourcc) {
11888 #if 0
11889             /* FIXME: what is in the chunk? */
11890           case FOURCC_QDMC:
11891           {
11892             gint len = QT_UINT32 (stsd_data);
11893
11894             /* seems to be always = 116 = 0x74 */
11895             break;
11896           }
11897 #endif
11898           case FOURCC_QDM2:
11899           {
11900             gint len = QT_UINT32 (stsd_entry_data);
11901
11902             if (len > 0x3C) {
11903               GstBuffer *buf = gst_buffer_new_and_alloc (len - 0x3C);
11904
11905               gst_buffer_fill (buf, 0, stsd_entry_data + 0x3C, len - 0x3C);
11906               gst_caps_set_simple (entry->caps,
11907                   "codec_data", GST_TYPE_BUFFER, buf, NULL);
11908               gst_buffer_unref (buf);
11909             }
11910             gst_caps_set_simple (entry->caps,
11911                 "samplesize", G_TYPE_INT, samplesize, NULL);
11912             break;
11913           }
11914           case FOURCC_alac:
11915           {
11916             GNode *alac, *wave = NULL;
11917
11918             /* apparently, m4a has this atom appended directly in the stsd entry,
11919              * while mov has it in a wave atom */
11920             alac = qtdemux_tree_get_child_by_type (stsd, FOURCC_alac);
11921             if (alac) {
11922               /* alac now refers to stsd entry atom */
11923               wave = qtdemux_tree_get_child_by_type (alac, FOURCC_wave);
11924               if (wave)
11925                 alac = qtdemux_tree_get_child_by_type (wave, FOURCC_alac);
11926               else
11927                 alac = qtdemux_tree_get_child_by_type (alac, FOURCC_alac);
11928             }
11929             if (alac) {
11930               const guint8 *alac_data = alac->data;
11931               gint len = QT_UINT32 (alac->data);
11932               GstBuffer *buf;
11933
11934               if (len < 36) {
11935                 GST_DEBUG_OBJECT (qtdemux,
11936                     "discarding alac atom with unexpected len %d", len);
11937               } else {
11938                 /* codec-data contains alac atom size and prefix,
11939                  * ffmpeg likes it that way, not quite gst-ish though ...*/
11940                 buf = gst_buffer_new_and_alloc (len);
11941                 gst_buffer_fill (buf, 0, alac->data, len);
11942                 gst_caps_set_simple (entry->caps,
11943                     "codec_data", GST_TYPE_BUFFER, buf, NULL);
11944                 gst_buffer_unref (buf);
11945
11946                 entry->bytes_per_frame = QT_UINT32 (alac_data + 12);
11947                 entry->n_channels = QT_UINT8 (alac_data + 21);
11948                 entry->rate = QT_UINT32 (alac_data + 32);
11949               }
11950             }
11951             gst_caps_set_simple (entry->caps,
11952                 "samplesize", G_TYPE_INT, samplesize, NULL);
11953             break;
11954           }
11955           case FOURCC_fLaC:
11956           {
11957             /* The codingname of the sample entry is 'fLaC' */
11958             GNode *flac = qtdemux_tree_get_child_by_type (stsd, FOURCC_fLaC);
11959
11960             if (flac) {
11961               /* The 'dfLa' box is added to the sample entry to convey
11962                  initializing information for the decoder. */
11963               const GNode *dfla =
11964                   qtdemux_tree_get_child_by_type (flac, FOURCC_dfLa);
11965
11966               if (dfla) {
11967                 const guint32 len = QT_UINT32 (dfla->data);
11968
11969                 /* Must contain at least dfLa box header (12),
11970                  * METADATA_BLOCK_HEADER (4), METADATA_BLOCK_STREAMINFO (34) */
11971                 if (len < 50) {
11972                   GST_DEBUG_OBJECT (qtdemux,
11973                       "discarding dfla atom with unexpected len %d", len);
11974                 } else {
11975                   /* skip dfLa header to get the METADATA_BLOCKs */
11976                   const guint8 *metadata_blocks = (guint8 *) dfla->data + 12;
11977                   const guint32 metadata_blocks_len = len - 12;
11978
11979                   gchar *stream_marker = g_strdup ("fLaC");
11980                   GstBuffer *block = gst_buffer_new_wrapped (stream_marker,
11981                       strlen (stream_marker));
11982
11983                   guint32 index = 0;
11984                   guint32 remainder = 0;
11985                   guint32 block_size = 0;
11986                   gboolean is_last = FALSE;
11987
11988                   GValue array = G_VALUE_INIT;
11989                   GValue value = G_VALUE_INIT;
11990
11991                   g_value_init (&array, GST_TYPE_ARRAY);
11992                   g_value_init (&value, GST_TYPE_BUFFER);
11993
11994                   gst_value_set_buffer (&value, block);
11995                   gst_value_array_append_value (&array, &value);
11996                   g_value_reset (&value);
11997
11998                   gst_buffer_unref (block);
11999
12000                   /* check there's at least one METADATA_BLOCK_HEADER's worth
12001                    * of data, and we haven't already finished parsing */
12002                   while (!is_last && ((index + 3) < metadata_blocks_len)) {
12003                     remainder = metadata_blocks_len - index;
12004
12005                     /* add the METADATA_BLOCK_HEADER size to the signalled size */
12006                     block_size = 4 +
12007                         (metadata_blocks[index + 1] << 16) +
12008                         (metadata_blocks[index + 2] << 8) +
12009                         metadata_blocks[index + 3];
12010
12011                     /* be careful not to read off end of box */
12012                     if (block_size > remainder) {
12013                       break;
12014                     }
12015
12016                     is_last = metadata_blocks[index] >> 7;
12017
12018                     block = gst_buffer_new_and_alloc (block_size);
12019
12020                     gst_buffer_fill (block, 0, &metadata_blocks[index],
12021                         block_size);
12022
12023                     gst_value_set_buffer (&value, block);
12024                     gst_value_array_append_value (&array, &value);
12025                     g_value_reset (&value);
12026
12027                     gst_buffer_unref (block);
12028
12029                     index += block_size;
12030                   }
12031
12032                   /* only append the metadata if we successfully read all of it */
12033                   if (is_last) {
12034                     gst_structure_set_value (gst_caps_get_structure (CUR_STREAM
12035                             (stream)->caps, 0), "streamheader", &array);
12036                   } else {
12037                     GST_WARNING_OBJECT (qtdemux,
12038                         "discarding all METADATA_BLOCKs due to invalid "
12039                         "block_size %d at idx %d, rem %d", block_size, index,
12040                         remainder);
12041                   }
12042
12043                   g_value_unset (&value);
12044                   g_value_unset (&array);
12045
12046                   /* The sample rate obtained from the stsd may not be accurate
12047                    * since it cannot represent rates greater than 65535Hz, so
12048                    * override that value with the sample rate from the
12049                    * METADATA_BLOCK_STREAMINFO block */
12050                   CUR_STREAM (stream)->rate =
12051                       (QT_UINT32 (metadata_blocks + 14) >> 12) & 0xFFFFF;
12052                 }
12053               }
12054             }
12055             break;
12056           }
12057           case FOURCC_sawb:
12058             /* Fallthrough! */
12059             amrwb = TRUE;
12060           case FOURCC_samr:
12061           {
12062             gint len = QT_UINT32 (stsd_entry_data);
12063
12064             if (len > 0x24) {
12065               GstBuffer *buf = gst_buffer_new_and_alloc (len - 0x24);
12066               guint bitrate;
12067
12068               gst_buffer_fill (buf, 0, stsd_entry_data + 0x24, len - 0x24);
12069
12070               /* If we have enough data, let's try to get the 'damr' atom. See
12071                * the 3GPP container spec (26.244) for more details. */
12072               if ((len - 0x34) > 8 &&
12073                   (bitrate = qtdemux_parse_amr_bitrate (buf, amrwb))) {
12074                 gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
12075                     GST_TAG_MAXIMUM_BITRATE, bitrate, NULL);
12076               }
12077
12078               gst_caps_set_simple (entry->caps,
12079                   "codec_data", GST_TYPE_BUFFER, buf, NULL);
12080               gst_buffer_unref (buf);
12081             }
12082             break;
12083           }
12084           case FOURCC_mp4a:
12085           {
12086             /* mp4a atom withtout ESDS; Attempt to build codec data from atom */
12087             gint len = QT_UINT32 (stsd_entry_data);
12088
12089             if (len >= 34) {
12090               guint16 sound_version = QT_UINT16 (stsd_entry_data + 16);
12091
12092               if (sound_version == 1) {
12093                 guint16 channels = QT_UINT16 (stsd_entry_data + 24);
12094                 guint32 time_scale = QT_UINT32 (stsd_entry_data + 30);
12095                 guint8 codec_data[2];
12096                 GstBuffer *buf;
12097                 gint profile = 2;       /* FIXME: Can this be determined somehow? There doesn't seem to be anything in mp4a atom that specifis compression */
12098
12099                 gint sample_rate_index =
12100                     gst_codec_utils_aac_get_index_from_sample_rate (time_scale);
12101
12102                 /* build AAC codec data */
12103                 codec_data[0] = profile << 3;
12104                 codec_data[0] |= ((sample_rate_index >> 1) & 0x7);
12105                 codec_data[1] = (sample_rate_index & 0x01) << 7;
12106                 codec_data[1] |= (channels & 0xF) << 3;
12107
12108                 buf = gst_buffer_new_and_alloc (2);
12109                 gst_buffer_fill (buf, 0, codec_data, 2);
12110                 gst_caps_set_simple (entry->caps,
12111                     "codec_data", GST_TYPE_BUFFER, buf, NULL);
12112                 gst_buffer_unref (buf);
12113               }
12114             }
12115             break;
12116           }
12117           case FOURCC_lpcm:
12118             /* Fully handled elsewhere */
12119             break;
12120           default:
12121             GST_INFO_OBJECT (qtdemux,
12122                 "unhandled type %" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (fourcc));
12123             break;
12124         }
12125       }
12126       GST_INFO_OBJECT (qtdemux,
12127           "type %" GST_FOURCC_FORMAT " caps %" GST_PTR_FORMAT,
12128           GST_FOURCC_ARGS (fourcc), entry->caps);
12129
12130     } else if (stream->subtype == FOURCC_strm) {
12131       if (fourcc == FOURCC_rtsp) {
12132         stream->redirect_uri = qtdemux_get_rtsp_uri_from_hndl (qtdemux, minf);
12133       } else {
12134         GST_INFO_OBJECT (qtdemux, "unhandled stream type %" GST_FOURCC_FORMAT,
12135             GST_FOURCC_ARGS (fourcc));
12136         goto unknown_stream;
12137       }
12138       entry->sampled = TRUE;
12139     } else if (stream->subtype == FOURCC_subp || stream->subtype == FOURCC_text
12140         || stream->subtype == FOURCC_sbtl || stream->subtype == FOURCC_subt
12141         || stream->subtype == FOURCC_clcp) {
12142
12143       entry->sampled = TRUE;
12144       entry->sparse = TRUE;
12145
12146       entry->caps =
12147           qtdemux_sub_caps (qtdemux, stream, entry, fourcc, stsd_entry_data,
12148           &codec);
12149       if (codec) {
12150         gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
12151             GST_TAG_SUBTITLE_CODEC, codec, NULL);
12152         g_free (codec);
12153         codec = NULL;
12154       }
12155
12156       /* hunt for sort-of codec data */
12157       switch (fourcc) {
12158         case FOURCC_mp4s:
12159         {
12160           GNode *mp4s = NULL;
12161           GNode *esds = NULL;
12162
12163           /* look for palette in a stsd->mp4s->esds sub-atom */
12164           mp4s = qtdemux_tree_get_child_by_type (stsd, FOURCC_mp4s);
12165           if (mp4s)
12166             esds = qtdemux_tree_get_child_by_type (mp4s, FOURCC_esds);
12167           if (esds == NULL) {
12168             /* Invalid STSD */
12169             GST_LOG_OBJECT (qtdemux, "Skipping invalid stsd: no esds child");
12170             break;
12171           }
12172
12173           gst_qtdemux_handle_esds (qtdemux, stream, entry, esds,
12174               stream->stream_tags);
12175           break;
12176         }
12177         default:
12178           GST_INFO_OBJECT (qtdemux,
12179               "unhandled type %" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (fourcc));
12180           break;
12181       }
12182       GST_INFO_OBJECT (qtdemux,
12183           "type %" GST_FOURCC_FORMAT " caps %" GST_PTR_FORMAT,
12184           GST_FOURCC_ARGS (fourcc), entry->caps);
12185     } else {
12186       /* everything in 1 sample */
12187       entry->sampled = TRUE;
12188
12189       entry->caps =
12190           qtdemux_generic_caps (qtdemux, stream, entry, fourcc, stsd_entry_data,
12191           &codec);
12192
12193       if (entry->caps == NULL)
12194         goto unknown_stream;
12195
12196       if (codec) {
12197         gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
12198             GST_TAG_SUBTITLE_CODEC, codec, NULL);
12199         g_free (codec);
12200         codec = NULL;
12201       }
12202     }
12203
12204     /* promote to sampled format */
12205     if (entry->fourcc == FOURCC_samr) {
12206       /* force mono 8000 Hz for AMR */
12207       entry->sampled = TRUE;
12208       entry->n_channels = 1;
12209       entry->rate = 8000;
12210     } else if (entry->fourcc == FOURCC_sawb) {
12211       /* force mono 16000 Hz for AMR-WB */
12212       entry->sampled = TRUE;
12213       entry->n_channels = 1;
12214       entry->rate = 16000;
12215     } else if (entry->fourcc == FOURCC_mp4a) {
12216       entry->sampled = TRUE;
12217     }
12218
12219
12220     stsd_entry_data += len;
12221     remaining_stsd_len -= len;
12222
12223   }
12224
12225   /* collect sample information */
12226   if (!qtdemux_stbl_init (qtdemux, stream, stbl))
12227     goto samples_failed;
12228
12229   if (qtdemux->fragmented) {
12230     guint64 offset;
12231
12232     /* need all moov samples as basis; probably not many if any at all */
12233     /* prevent moof parsing taking of at this time */
12234     offset = qtdemux->moof_offset;
12235     qtdemux->moof_offset = 0;
12236     if (stream->n_samples &&
12237         !qtdemux_parse_samples (qtdemux, stream, stream->n_samples - 1)) {
12238       qtdemux->moof_offset = offset;
12239       goto samples_failed;
12240     }
12241     qtdemux->moof_offset = 0;
12242     /* movie duration more reliable in this case (e.g. mehd) */
12243     if (qtdemux->segment.duration &&
12244         GST_CLOCK_TIME_IS_VALID (qtdemux->segment.duration))
12245       stream->duration =
12246           GSTTIME_TO_QTSTREAMTIME (stream, qtdemux->segment.duration);
12247   }
12248
12249   /* configure segments */
12250   if (!qtdemux_parse_segments (qtdemux, stream, trak))
12251     goto segments_failed;
12252
12253   /* add some language tag, if useful */
12254   if (stream->lang_id[0] != '\0' && strcmp (stream->lang_id, "unk") &&
12255       strcmp (stream->lang_id, "und")) {
12256     const gchar *lang_code;
12257
12258     /* convert ISO 639-2 code to ISO 639-1 */
12259     lang_code = gst_tag_get_language_code (stream->lang_id);
12260     gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
12261         GST_TAG_LANGUAGE_CODE, (lang_code) ? lang_code : stream->lang_id, NULL);
12262   }
12263
12264   /* Check for UDTA tags */
12265   if ((udta = qtdemux_tree_get_child_by_type (trak, FOURCC_udta))) {
12266     qtdemux_parse_udta (qtdemux, stream->stream_tags, udta);
12267   }
12268
12269   /* Insert and sort new stream in track-id order.
12270    * This will help in comparing old/new streams during stream update check */
12271   g_ptr_array_add (qtdemux->active_streams, stream);
12272   g_ptr_array_sort (qtdemux->active_streams,
12273       (GCompareFunc) qtdemux_track_id_compare_func);
12274   GST_DEBUG_OBJECT (qtdemux, "n_streams is now %d",
12275       QTDEMUX_N_STREAMS (qtdemux));
12276
12277   return TRUE;
12278
12279 /* ERRORS */
12280 corrupt_file:
12281   {
12282     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
12283         (_("This file is corrupt and cannot be played.")), (NULL));
12284     if (stream)
12285       gst_qtdemux_stream_unref (stream);
12286     return FALSE;
12287   }
12288 error_encrypted:
12289   {
12290     GST_ELEMENT_ERROR (qtdemux, STREAM, DECRYPT, (NULL), (NULL));
12291     gst_qtdemux_stream_unref (stream);
12292     return FALSE;
12293   }
12294 samples_failed:
12295 segments_failed:
12296   {
12297     /* we posted an error already */
12298     /* free stbl sub-atoms */
12299     gst_qtdemux_stbl_free (stream);
12300     gst_qtdemux_stream_unref (stream);
12301     return FALSE;
12302   }
12303 existing_stream:
12304   {
12305     GST_INFO_OBJECT (qtdemux, "stream with track id %i already exists",
12306         track_id);
12307     return TRUE;
12308   }
12309 unknown_stream:
12310   {
12311     GST_INFO_OBJECT (qtdemux, "unknown subtype %" GST_FOURCC_FORMAT,
12312         GST_FOURCC_ARGS (stream->subtype));
12313     gst_qtdemux_stream_unref (stream);
12314     return TRUE;
12315   }
12316 }
12317
12318 /* If we can estimate the overall bitrate, and don't have information about the
12319  * stream bitrate for exactly one stream, this guesses the stream bitrate as
12320  * the overall bitrate minus the sum of the bitrates of all other streams. This
12321  * should be useful for the common case where we have one audio and one video
12322  * stream and can estimate the bitrate of one, but not the other. */
12323 static void
12324 gst_qtdemux_guess_bitrate (GstQTDemux * qtdemux)
12325 {
12326   QtDemuxStream *stream = NULL;
12327   gint64 size, sys_bitrate, sum_bitrate = 0;
12328   GstClockTime duration;
12329   guint bitrate;
12330   gint i;
12331
12332   if (qtdemux->fragmented)
12333     return;
12334
12335   GST_DEBUG_OBJECT (qtdemux, "Looking for streams with unknown bitrate");
12336
12337   if (!gst_pad_peer_query_duration (qtdemux->sinkpad, GST_FORMAT_BYTES, &size)
12338       || size <= 0) {
12339     GST_DEBUG_OBJECT (qtdemux,
12340         "Size in bytes of the stream not known - bailing");
12341     return;
12342   }
12343
12344   /* Subtract the header size */
12345   GST_DEBUG_OBJECT (qtdemux, "Total size %" G_GINT64_FORMAT ", header size %u",
12346       size, qtdemux->header_size);
12347
12348   if (size < qtdemux->header_size)
12349     return;
12350
12351   size = size - qtdemux->header_size;
12352
12353   if (!gst_qtdemux_get_duration (qtdemux, &duration)) {
12354     GST_DEBUG_OBJECT (qtdemux, "Stream duration not known - bailing");
12355     return;
12356   }
12357
12358   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
12359     QtDemuxStream *str = QTDEMUX_NTH_STREAM (qtdemux, i);
12360     switch (str->subtype) {
12361       case FOURCC_soun:
12362       case FOURCC_vide:
12363         GST_DEBUG_OBJECT (qtdemux, "checking bitrate for %" GST_PTR_FORMAT,
12364             CUR_STREAM (str)->caps);
12365         /* retrieve bitrate, prefer avg then max */
12366         bitrate = 0;
12367         if (str->stream_tags) {
12368           if (gst_tag_list_get_uint (str->stream_tags,
12369                   GST_TAG_MAXIMUM_BITRATE, &bitrate))
12370             GST_DEBUG_OBJECT (qtdemux, "max-bitrate: %u", bitrate);
12371           if (gst_tag_list_get_uint (str->stream_tags,
12372                   GST_TAG_NOMINAL_BITRATE, &bitrate))
12373             GST_DEBUG_OBJECT (qtdemux, "nominal-bitrate: %u", bitrate);
12374           if (gst_tag_list_get_uint (str->stream_tags,
12375                   GST_TAG_BITRATE, &bitrate))
12376             GST_DEBUG_OBJECT (qtdemux, "bitrate: %u", bitrate);
12377         }
12378         if (bitrate)
12379           sum_bitrate += bitrate;
12380         else {
12381           if (stream) {
12382             GST_DEBUG_OBJECT (qtdemux,
12383                 ">1 stream with unknown bitrate - bailing");
12384             return;
12385           } else
12386             stream = str;
12387         }
12388
12389       default:
12390         /* For other subtypes, we assume no significant impact on bitrate */
12391         break;
12392     }
12393   }
12394
12395   if (!stream) {
12396     GST_DEBUG_OBJECT (qtdemux, "All stream bitrates are known");
12397     return;
12398   }
12399
12400   sys_bitrate = gst_util_uint64_scale (size, GST_SECOND * 8, duration);
12401
12402   if (sys_bitrate < sum_bitrate) {
12403     /* This can happen, since sum_bitrate might be derived from maximum
12404      * bitrates and not average bitrates */
12405     GST_DEBUG_OBJECT (qtdemux,
12406         "System bitrate less than sum bitrate - bailing");
12407     return;
12408   }
12409
12410   bitrate = sys_bitrate - sum_bitrate;
12411   GST_DEBUG_OBJECT (qtdemux, "System bitrate = %" G_GINT64_FORMAT
12412       ", Stream bitrate = %u", sys_bitrate, bitrate);
12413
12414   if (!stream->stream_tags)
12415     stream->stream_tags = gst_tag_list_new_empty ();
12416   else
12417     stream->stream_tags = gst_tag_list_make_writable (stream->stream_tags);
12418
12419   gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
12420       GST_TAG_BITRATE, bitrate, NULL);
12421 }
12422
12423 static GstFlowReturn
12424 qtdemux_prepare_streams (GstQTDemux * qtdemux)
12425 {
12426   GstFlowReturn ret = GST_FLOW_OK;
12427   gint i;
12428
12429   GST_DEBUG_OBJECT (qtdemux, "prepare streams");
12430
12431   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
12432     QtDemuxStream *stream = QTDEMUX_NTH_STREAM (qtdemux, i);
12433     guint32 sample_num = 0;
12434
12435     GST_DEBUG_OBJECT (qtdemux, "track-id %u, fourcc %" GST_FOURCC_FORMAT,
12436         stream->track_id, GST_FOURCC_ARGS (CUR_STREAM (stream)->fourcc));
12437
12438     if (qtdemux->fragmented) {
12439       /* need all moov samples first */
12440       GST_OBJECT_LOCK (qtdemux);
12441       while (stream->n_samples == 0)
12442         if ((ret = qtdemux_add_fragmented_samples (qtdemux)) != GST_FLOW_OK)
12443           break;
12444       GST_OBJECT_UNLOCK (qtdemux);
12445     } else {
12446       /* discard any stray moof */
12447       qtdemux->moof_offset = 0;
12448     }
12449
12450     /* prepare braking */
12451     if (ret != GST_FLOW_ERROR)
12452       ret = GST_FLOW_OK;
12453
12454     /* in pull mode, we should have parsed some sample info by now;
12455      * and quite some code will not handle no samples.
12456      * in push mode, we'll just have to deal with it */
12457     if (G_UNLIKELY (qtdemux->pullbased && !stream->n_samples)) {
12458       GST_DEBUG_OBJECT (qtdemux, "no samples for stream; discarding");
12459       g_ptr_array_remove_index (qtdemux->active_streams, i);
12460       i--;
12461       continue;
12462     } else if (stream->track_id == qtdemux->chapters_track_id &&
12463         (stream->subtype == FOURCC_text || stream->subtype == FOURCC_sbtl)) {
12464       /* TODO - parse chapters track and expose it as GstToc; For now just ignore it
12465          so that it doesn't look like a subtitle track */
12466       g_ptr_array_remove_index (qtdemux->active_streams, i);
12467       i--;
12468       continue;
12469     }
12470
12471     /* parse the initial sample for use in setting the frame rate cap */
12472     while (sample_num == 0 && sample_num < stream->n_samples) {
12473       if (!qtdemux_parse_samples (qtdemux, stream, sample_num))
12474         break;
12475       ++sample_num;
12476     }
12477   }
12478
12479   return ret;
12480 }
12481
12482 static gboolean
12483 _stream_equal_func (const QtDemuxStream * stream, const gchar * stream_id)
12484 {
12485   return g_strcmp0 (stream->stream_id, stream_id) == 0;
12486 }
12487
12488 static gboolean
12489 qtdemux_is_streams_update (GstQTDemux * qtdemux)
12490 {
12491   gint i;
12492
12493   /* Different length, updated */
12494   if (QTDEMUX_N_STREAMS (qtdemux) != qtdemux->old_streams->len)
12495     return TRUE;
12496
12497   /* streams in list are sorted in track-id order */
12498   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
12499     /* Different stream-id, updated */
12500     if (g_strcmp0 (QTDEMUX_NTH_STREAM (qtdemux, i)->stream_id,
12501             QTDEMUX_NTH_OLD_STREAM (qtdemux, i)->stream_id))
12502       return TRUE;
12503   }
12504
12505   return FALSE;
12506 }
12507
12508 static gboolean
12509 qtdemux_reuse_and_configure_stream (GstQTDemux * qtdemux,
12510     QtDemuxStream * oldstream, QtDemuxStream * newstream)
12511 {
12512   /* Connect old stream's srcpad to new stream */
12513   newstream->pad = oldstream->pad;
12514   oldstream->pad = NULL;
12515
12516   /* unset new_stream to prevent stream-start event */
12517   newstream->new_stream = FALSE;
12518
12519   return gst_qtdemux_configure_stream (qtdemux, newstream);
12520 }
12521
12522 /* g_ptr_array_find_with_equal_func is available since 2.54,
12523  * replacement until we can depend unconditionally on the real one in GLib */
12524 #if !GLIB_CHECK_VERSION(2,54,0)
12525 #define g_ptr_array_find_with_equal_func qtdemux_ptr_array_find_with_equal_func
12526 static gboolean
12527 qtdemux_ptr_array_find_with_equal_func (GPtrArray * haystack,
12528     gconstpointer needle, GEqualFunc equal_func, guint * index_)
12529 {
12530   guint i;
12531
12532   g_return_val_if_fail (haystack != NULL, FALSE);
12533
12534   if (equal_func == NULL)
12535     equal_func = g_direct_equal;
12536
12537   for (i = 0; i < haystack->len; i++) {
12538     if (equal_func (g_ptr_array_index (haystack, i), needle)) {
12539       if (index_ != NULL)
12540         *index_ = i;
12541       return TRUE;
12542     }
12543   }
12544
12545   return FALSE;
12546 }
12547 #endif
12548
12549 static gboolean
12550 qtdemux_update_streams (GstQTDemux * qtdemux)
12551 {
12552   gint i;
12553   g_assert (qtdemux->streams_aware);
12554
12555   /* At below, figure out which stream in active_streams has identical stream-id
12556    * with that of in old_streams. If there is matching stream-id,
12557    * corresponding newstream will not be exposed again,
12558    * but demux will reuse srcpad of matched old stream
12559    *
12560    * active_streams : newly created streams from the latest moov
12561    * old_streams : existing streams (belong to previous moov)
12562    */
12563
12564   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
12565     QtDemuxStream *stream = QTDEMUX_NTH_STREAM (qtdemux, i);
12566     QtDemuxStream *oldstream = NULL;
12567     guint target;
12568
12569     GST_DEBUG_OBJECT (qtdemux, "track-id %u, fourcc %" GST_FOURCC_FORMAT,
12570         stream->track_id, GST_FOURCC_ARGS (CUR_STREAM (stream)->fourcc));
12571
12572     if (g_ptr_array_find_with_equal_func (qtdemux->old_streams,
12573             stream->stream_id, (GEqualFunc) _stream_equal_func, &target)) {
12574       oldstream = QTDEMUX_NTH_OLD_STREAM (qtdemux, target);
12575
12576       /* null pad stream cannot be reused */
12577       if (oldstream->pad == NULL)
12578         oldstream = NULL;
12579     }
12580
12581     if (oldstream) {
12582       GST_DEBUG_OBJECT (qtdemux, "Reuse track-id %d", oldstream->track_id);
12583
12584       if (!qtdemux_reuse_and_configure_stream (qtdemux, oldstream, stream))
12585         return FALSE;
12586
12587       /* we don't need to preserve order of old streams */
12588       g_ptr_array_remove_fast (qtdemux->old_streams, oldstream);
12589     } else {
12590       GstTagList *list;
12591
12592       /* now we have all info and can expose */
12593       list = stream->stream_tags;
12594       stream->stream_tags = NULL;
12595       if (!gst_qtdemux_add_stream (qtdemux, stream, list))
12596         return FALSE;
12597     }
12598   }
12599
12600   return TRUE;
12601 }
12602
12603 /* Must be called with expose lock */
12604 static GstFlowReturn
12605 qtdemux_expose_streams (GstQTDemux * qtdemux)
12606 {
12607   gint i;
12608
12609   GST_DEBUG_OBJECT (qtdemux, "exposing streams");
12610
12611   if (!qtdemux_is_streams_update (qtdemux)) {
12612     GST_DEBUG_OBJECT (qtdemux, "Reuse all streams");
12613     for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
12614       QtDemuxStream *new_stream = QTDEMUX_NTH_STREAM (qtdemux, i);
12615       QtDemuxStream *old_stream = QTDEMUX_NTH_OLD_STREAM (qtdemux, i);
12616       if (!qtdemux_reuse_and_configure_stream (qtdemux, old_stream, new_stream))
12617         return GST_FLOW_ERROR;
12618     }
12619
12620     g_ptr_array_remove_range (qtdemux->old_streams,
12621         0, qtdemux->old_streams->len);
12622
12623     return GST_FLOW_OK;
12624   }
12625
12626   if (qtdemux->streams_aware) {
12627     if (!qtdemux_update_streams (qtdemux))
12628       return GST_FLOW_ERROR;
12629   } else {
12630     for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
12631       QtDemuxStream *stream = QTDEMUX_NTH_STREAM (qtdemux, i);
12632       GstTagList *list;
12633
12634       /* now we have all info and can expose */
12635       list = stream->stream_tags;
12636       stream->stream_tags = NULL;
12637       if (!gst_qtdemux_add_stream (qtdemux, stream, list))
12638         return GST_FLOW_ERROR;
12639
12640     }
12641   }
12642
12643   gst_qtdemux_guess_bitrate (qtdemux);
12644
12645   gst_element_no_more_pads (GST_ELEMENT_CAST (qtdemux));
12646
12647   /* If we have still old_streams, it's no more used stream */
12648   for (i = 0; i < qtdemux->old_streams->len; i++) {
12649     QtDemuxStream *stream = QTDEMUX_NTH_OLD_STREAM (qtdemux, i);
12650
12651     if (stream->pad) {
12652       GstEvent *event;
12653
12654       event = gst_event_new_eos ();
12655       if (qtdemux->segment_seqnum)
12656         gst_event_set_seqnum (event, qtdemux->segment_seqnum);
12657
12658       gst_pad_push_event (stream->pad, event);
12659     }
12660   }
12661
12662   g_ptr_array_remove_range (qtdemux->old_streams, 0, qtdemux->old_streams->len);
12663
12664   /* check if we should post a redirect in case there is a single trak
12665    * and it is a redirecting trak */
12666   if (QTDEMUX_N_STREAMS (qtdemux) == 1 &&
12667       QTDEMUX_NTH_STREAM (qtdemux, 0)->redirect_uri != NULL) {
12668     GstMessage *m;
12669
12670     GST_INFO_OBJECT (qtdemux, "Issuing a redirect due to a single track with "
12671         "an external content");
12672     m = gst_message_new_element (GST_OBJECT_CAST (qtdemux),
12673         gst_structure_new ("redirect",
12674             "new-location", G_TYPE_STRING,
12675             QTDEMUX_NTH_STREAM (qtdemux, 0)->redirect_uri, NULL));
12676     gst_element_post_message (GST_ELEMENT_CAST (qtdemux), m);
12677     qtdemux->posted_redirect = TRUE;
12678   }
12679
12680   g_ptr_array_foreach (qtdemux->active_streams,
12681       (GFunc) qtdemux_do_allocation, qtdemux);
12682
12683   qtdemux->need_segment = TRUE;
12684
12685   qtdemux->exposed = TRUE;
12686   return GST_FLOW_OK;
12687 }
12688
12689 /* check if major or compatible brand is 3GP */
12690 static inline gboolean
12691 qtdemux_is_brand_3gp (GstQTDemux * qtdemux, gboolean major)
12692 {
12693   if (major) {
12694     return ((qtdemux->major_brand & GST_MAKE_FOURCC (255, 255, 0, 0)) ==
12695         FOURCC_3g__);
12696   } else if (qtdemux->comp_brands != NULL) {
12697     GstMapInfo map;
12698     guint8 *data;
12699     gsize size;
12700     gboolean res = FALSE;
12701
12702     gst_buffer_map (qtdemux->comp_brands, &map, GST_MAP_READ);
12703     data = map.data;
12704     size = map.size;
12705     while (size >= 4) {
12706       res = res || ((QT_FOURCC (data) & GST_MAKE_FOURCC (255, 255, 0, 0)) ==
12707           FOURCC_3g__);
12708       data += 4;
12709       size -= 4;
12710     }
12711     gst_buffer_unmap (qtdemux->comp_brands, &map);
12712     return res;
12713   } else {
12714     return FALSE;
12715   }
12716 }
12717
12718 /* check if tag is a spec'ed 3GP tag keyword storing a string */
12719 static inline gboolean
12720 qtdemux_is_string_tag_3gp (GstQTDemux * qtdemux, guint32 fourcc)
12721 {
12722   return fourcc == FOURCC_cprt || fourcc == FOURCC_gnre || fourcc == FOURCC_titl
12723       || fourcc == FOURCC_dscp || fourcc == FOURCC_perf || fourcc == FOURCC_auth
12724       || fourcc == FOURCC_albm;
12725 }
12726
12727 static void
12728 qtdemux_tag_add_location (GstQTDemux * qtdemux, GstTagList * taglist,
12729     const char *tag, const char *dummy, GNode * node)
12730 {
12731   const gchar *env_vars[] = { "GST_QT_TAG_ENCODING", "GST_TAG_ENCODING", NULL };
12732   int offset;
12733   char *name;
12734   gchar *data;
12735   gdouble longitude, latitude, altitude;
12736   gint len;
12737
12738   len = QT_UINT32 (node->data);
12739   if (len <= 14)
12740     goto short_read;
12741
12742   data = node->data;
12743   offset = 14;
12744
12745   /* TODO: language code skipped */
12746
12747   name = gst_tag_freeform_string_to_utf8 (data + offset, -1, env_vars);
12748
12749   if (!name) {
12750     /* do not alarm in trivial case, but bail out otherwise */
12751     if (*(data + offset) != 0) {
12752       GST_DEBUG_OBJECT (qtdemux, "failed to convert %s tag to UTF-8, "
12753           "giving up", tag);
12754     }
12755   } else {
12756     gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE,
12757         GST_TAG_GEO_LOCATION_NAME, name, NULL);
12758     offset += strlen (name);
12759     g_free (name);
12760   }
12761
12762   if (len < offset + 2 + 4 + 4 + 4)
12763     goto short_read;
12764
12765   /* +1 +1 = skip null-terminator and location role byte */
12766   offset += 1 + 1;
12767   /* table in spec says unsigned, semantics say negative has meaning ... */
12768   longitude = QT_SFP32 (data + offset);
12769
12770   offset += 4;
12771   latitude = QT_SFP32 (data + offset);
12772
12773   offset += 4;
12774   altitude = QT_SFP32 (data + offset);
12775
12776   /* one invalid means all are invalid */
12777   if (longitude >= -180.0 && longitude <= 180.0 &&
12778       latitude >= -90.0 && latitude <= 90.0) {
12779     gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE,
12780         GST_TAG_GEO_LOCATION_LATITUDE, latitude,
12781         GST_TAG_GEO_LOCATION_LONGITUDE, longitude,
12782         GST_TAG_GEO_LOCATION_ELEVATION, altitude, NULL);
12783   }
12784
12785   /* TODO: no GST_TAG_, so astronomical body and additional notes skipped */
12786
12787   return;
12788
12789   /* ERRORS */
12790 short_read:
12791   {
12792     GST_DEBUG_OBJECT (qtdemux, "short read parsing 3GP location");
12793     return;
12794   }
12795 }
12796
12797
12798 static void
12799 qtdemux_tag_add_year (GstQTDemux * qtdemux, GstTagList * taglist,
12800     const char *tag, const char *dummy, GNode * node)
12801 {
12802   guint16 y;
12803   GDate *date;
12804   gint len;
12805
12806   len = QT_UINT32 (node->data);
12807   if (len < 14)
12808     return;
12809
12810   y = QT_UINT16 ((guint8 *) node->data + 12);
12811   if (y == 0) {
12812     GST_DEBUG_OBJECT (qtdemux, "year: %u is not a valid year", y);
12813     return;
12814   }
12815   GST_DEBUG_OBJECT (qtdemux, "year: %u", y);
12816
12817   date = g_date_new_dmy (1, 1, y);
12818   gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag, date, NULL);
12819   g_date_free (date);
12820 }
12821
12822 static void
12823 qtdemux_tag_add_classification (GstQTDemux * qtdemux, GstTagList * taglist,
12824     const char *tag, const char *dummy, GNode * node)
12825 {
12826   int offset;
12827   char *tag_str = NULL;
12828   guint8 *entity;
12829   guint16 table;
12830   gint len;
12831
12832   len = QT_UINT32 (node->data);
12833   if (len <= 20)
12834     goto short_read;
12835
12836   offset = 12;
12837   entity = (guint8 *) node->data + offset;
12838   if (entity[0] == 0 || entity[1] == 0 || entity[2] == 0 || entity[3] == 0) {
12839     GST_DEBUG_OBJECT (qtdemux,
12840         "classification info: %c%c%c%c invalid classification entity",
12841         entity[0], entity[1], entity[2], entity[3]);
12842     return;
12843   }
12844
12845   offset += 4;
12846   table = QT_UINT16 ((guint8 *) node->data + offset);
12847
12848   /* Language code skipped */
12849
12850   offset += 4;
12851
12852   /* Tag format: "XXXX://Y[YYYY]/classification info string"
12853    * XXXX: classification entity, fixed length 4 chars.
12854    * Y[YYYY]: classification table, max 5 chars.
12855    */
12856   tag_str = g_strdup_printf ("----://%u/%s",
12857       table, (char *) node->data + offset);
12858
12859   /* memcpy To be sure we're preserving byte order */
12860   memcpy (tag_str, entity, 4);
12861   GST_DEBUG_OBJECT (qtdemux, "classification info: %s", tag_str);
12862
12863   gst_tag_list_add (taglist, GST_TAG_MERGE_APPEND, tag, tag_str, NULL);
12864
12865   g_free (tag_str);
12866
12867   return;
12868
12869   /* ERRORS */
12870 short_read:
12871   {
12872     GST_DEBUG_OBJECT (qtdemux, "short read parsing 3GP classification");
12873     return;
12874   }
12875 }
12876
12877 static gboolean
12878 qtdemux_tag_add_str_full (GstQTDemux * qtdemux, GstTagList * taglist,
12879     const char *tag, const char *dummy, GNode * node)
12880 {
12881   const gchar *env_vars[] = { "GST_QT_TAG_ENCODING", "GST_TAG_ENCODING", NULL };
12882   GNode *data;
12883   char *s;
12884   int len;
12885   guint32 type;
12886   int offset;
12887   gboolean ret = TRUE;
12888   const gchar *charset = NULL;
12889
12890   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
12891   if (data) {
12892     len = QT_UINT32 (data->data);
12893     type = QT_UINT32 ((guint8 *) data->data + 8);
12894     if (type == 0x00000001 && len > 16) {
12895       s = gst_tag_freeform_string_to_utf8 ((char *) data->data + 16, len - 16,
12896           env_vars);
12897       if (s) {
12898         GST_DEBUG_OBJECT (qtdemux, "adding tag %s", GST_STR_NULL (s));
12899         gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag, s, NULL);
12900         g_free (s);
12901       } else {
12902         GST_DEBUG_OBJECT (qtdemux, "failed to convert %s tag to UTF-8", tag);
12903       }
12904     }
12905   } else {
12906     len = QT_UINT32 (node->data);
12907     type = QT_UINT32 ((guint8 *) node->data + 4);
12908     if ((type >> 24) == 0xa9 && len > 8 + 4) {
12909       gint str_len;
12910       gint lang_code;
12911
12912       /* Type starts with the (C) symbol, so the next data is a list
12913        * of (string size(16), language code(16), string) */
12914
12915       str_len = QT_UINT16 ((guint8 *) node->data + 8);
12916       lang_code = QT_UINT16 ((guint8 *) node->data + 10);
12917
12918       /* the string + fourcc + size + 2 16bit fields,
12919        * means that there are more tags in this atom */
12920       if (len > str_len + 8 + 4) {
12921         /* TODO how to represent the same tag in different languages? */
12922         GST_WARNING_OBJECT (qtdemux, "Ignoring metadata entry with multiple "
12923             "text alternatives, reading only first one");
12924       }
12925
12926       offset = 12;
12927       len = MIN (len, str_len + 8 + 4); /* remove trailing strings that we don't use */
12928       GST_DEBUG_OBJECT (qtdemux, "found international text tag");
12929
12930       if (lang_code < 0x800) {  /* MAC encoded string */
12931         charset = "mac";
12932       }
12933     } else if (len > 14 && qtdemux_is_string_tag_3gp (qtdemux,
12934             QT_FOURCC ((guint8 *) node->data + 4))) {
12935       guint32 type = QT_UINT32 ((guint8 *) node->data + 8);
12936
12937       /* we go for 3GP style encoding if major brands claims so,
12938        * or if no hope for data be ok UTF-8, and compatible 3GP brand present */
12939       if (qtdemux_is_brand_3gp (qtdemux, TRUE) ||
12940           (qtdemux_is_brand_3gp (qtdemux, FALSE) &&
12941               ((type & 0x00FFFFFF) == 0x0) && (type >> 24 <= 0xF))) {
12942         offset = 14;
12943         /* 16-bit Language code is ignored here as well */
12944         GST_DEBUG_OBJECT (qtdemux, "found 3gpp text tag");
12945       } else {
12946         goto normal;
12947       }
12948     } else {
12949     normal:
12950       offset = 8;
12951       GST_DEBUG_OBJECT (qtdemux, "found normal text tag");
12952       ret = FALSE;              /* may have to fallback */
12953     }
12954     if (charset) {
12955       GError *err = NULL;
12956
12957       s = g_convert ((gchar *) node->data + offset, len - offset, "utf8",
12958           charset, NULL, NULL, &err);
12959       if (err) {
12960         GST_DEBUG_OBJECT (qtdemux, "Failed to convert string from charset %s:"
12961             " %s(%d): %s", charset, g_quark_to_string (err->domain), err->code,
12962             err->message);
12963         g_error_free (err);
12964       }
12965     } else {
12966       s = gst_tag_freeform_string_to_utf8 ((char *) node->data + offset,
12967           len - offset, env_vars);
12968     }
12969     if (s) {
12970       GST_DEBUG_OBJECT (qtdemux, "adding tag %s", GST_STR_NULL (s));
12971       gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag, s, NULL);
12972       g_free (s);
12973       ret = TRUE;
12974     } else {
12975       GST_DEBUG_OBJECT (qtdemux, "failed to convert %s tag to UTF-8", tag);
12976     }
12977   }
12978   return ret;
12979 }
12980
12981 static void
12982 qtdemux_tag_add_str (GstQTDemux * qtdemux, GstTagList * taglist,
12983     const char *tag, const char *dummy, GNode * node)
12984 {
12985   qtdemux_tag_add_str_full (qtdemux, taglist, tag, dummy, node);
12986 }
12987
12988 static void
12989 qtdemux_tag_add_keywords (GstQTDemux * qtdemux, GstTagList * taglist,
12990     const char *tag, const char *dummy, GNode * node)
12991 {
12992   const gchar *env_vars[] = { "GST_QT_TAG_ENCODING", "GST_TAG_ENCODING", NULL };
12993   guint8 *data;
12994   char *s, *t, *k = NULL;
12995   int len;
12996   int offset;
12997   int count;
12998
12999   /* first try normal string tag if major brand not 3GP */
13000   if (!qtdemux_is_brand_3gp (qtdemux, TRUE)) {
13001     if (!qtdemux_tag_add_str_full (qtdemux, taglist, tag, dummy, node)) {
13002       /* hm, that did not work, maybe 3gpp storage in non-3gpp major brand;
13003        * let's try it 3gpp way after minor safety check */
13004       data = node->data;
13005       if (QT_UINT32 (data) < 15 || !qtdemux_is_brand_3gp (qtdemux, FALSE))
13006         return;
13007     } else
13008       return;
13009   }
13010
13011   GST_DEBUG_OBJECT (qtdemux, "found 3gpp keyword tag");
13012
13013   data = node->data;
13014
13015   len = QT_UINT32 (data);
13016   if (len < 15)
13017     goto short_read;
13018
13019   count = QT_UINT8 (data + 14);
13020   offset = 15;
13021   for (; count; count--) {
13022     gint slen;
13023
13024     if (offset + 1 > len)
13025       goto short_read;
13026     slen = QT_UINT8 (data + offset);
13027     offset += 1;
13028     if (offset + slen > len)
13029       goto short_read;
13030     s = gst_tag_freeform_string_to_utf8 ((char *) node->data + offset,
13031         slen, env_vars);
13032     if (s) {
13033       GST_DEBUG_OBJECT (qtdemux, "adding keyword %s", GST_STR_NULL (s));
13034       if (k) {
13035         t = g_strjoin (",", k, s, NULL);
13036         g_free (s);
13037         g_free (k);
13038         k = t;
13039       } else {
13040         k = s;
13041       }
13042     } else {
13043       GST_DEBUG_OBJECT (qtdemux, "failed to convert keyword to UTF-8");
13044     }
13045     offset += slen;
13046   }
13047
13048 done:
13049   if (k) {
13050     GST_DEBUG_OBJECT (qtdemux, "adding tag %s", GST_STR_NULL (k));
13051     gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag, k, NULL);
13052   }
13053   g_free (k);
13054
13055   return;
13056
13057   /* ERRORS */
13058 short_read:
13059   {
13060     GST_DEBUG_OBJECT (qtdemux, "short read parsing 3GP keywords");
13061     goto done;
13062   }
13063 }
13064
13065 static void
13066 qtdemux_tag_add_num (GstQTDemux * qtdemux, GstTagList * taglist,
13067     const char *tag1, const char *tag2, GNode * node)
13068 {
13069   GNode *data;
13070   int len;
13071   int type;
13072   int n1, n2;
13073
13074   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
13075   if (data) {
13076     len = QT_UINT32 (data->data);
13077     type = QT_UINT32 ((guint8 *) data->data + 8);
13078     if (type == 0x00000000 && len >= 22) {
13079       n1 = QT_UINT16 ((guint8 *) data->data + 18);
13080       n2 = QT_UINT16 ((guint8 *) data->data + 20);
13081       if (n1 > 0) {
13082         GST_DEBUG_OBJECT (qtdemux, "adding tag %s=%d", tag1, n1);
13083         gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag1, n1, NULL);
13084       }
13085       if (n2 > 0) {
13086         GST_DEBUG_OBJECT (qtdemux, "adding tag %s=%d", tag2, n2);
13087         gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag2, n2, NULL);
13088       }
13089     }
13090   }
13091 }
13092
13093 static void
13094 qtdemux_tag_add_tmpo (GstQTDemux * qtdemux, GstTagList * taglist,
13095     const char *tag1, const char *dummy, GNode * node)
13096 {
13097   GNode *data;
13098   int len;
13099   int type;
13100   int n1;
13101
13102   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
13103   if (data) {
13104     len = QT_UINT32 (data->data);
13105     type = QT_UINT32 ((guint8 *) data->data + 8);
13106     GST_DEBUG_OBJECT (qtdemux, "have tempo tag, type=%d,len=%d", type, len);
13107     /* some files wrongly have a type 0x0f=15, but it should be 0x15 */
13108     if ((type == 0x00000015 || type == 0x0000000f) && len >= 18) {
13109       n1 = QT_UINT16 ((guint8 *) data->data + 16);
13110       if (n1) {
13111         /* do not add bpm=0 */
13112         GST_DEBUG_OBJECT (qtdemux, "adding tag %d", n1);
13113         gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag1, (gdouble) n1,
13114             NULL);
13115       }
13116     }
13117   }
13118 }
13119
13120 static void
13121 qtdemux_tag_add_uint32 (GstQTDemux * qtdemux, GstTagList * taglist,
13122     const char *tag1, const char *dummy, GNode * node)
13123 {
13124   GNode *data;
13125   int len;
13126   int type;
13127   guint32 num;
13128
13129   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
13130   if (data) {
13131     len = QT_UINT32 (data->data);
13132     type = QT_UINT32 ((guint8 *) data->data + 8);
13133     GST_DEBUG_OBJECT (qtdemux, "have %s tag, type=%d,len=%d", tag1, type, len);
13134     /* some files wrongly have a type 0x0f=15, but it should be 0x15 */
13135     if ((type == 0x00000015 || type == 0x0000000f) && len >= 20) {
13136       num = QT_UINT32 ((guint8 *) data->data + 16);
13137       if (num) {
13138         /* do not add num=0 */
13139         GST_DEBUG_OBJECT (qtdemux, "adding tag %d", num);
13140         gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag1, num, NULL);
13141       }
13142     }
13143   }
13144 }
13145
13146 static void
13147 qtdemux_tag_add_covr (GstQTDemux * qtdemux, GstTagList * taglist,
13148     const char *tag1, const char *dummy, GNode * node)
13149 {
13150   GNode *data;
13151   int len;
13152   int type;
13153   GstSample *sample;
13154
13155   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
13156   if (data) {
13157     len = QT_UINT32 (data->data);
13158     type = QT_UINT32 ((guint8 *) data->data + 8);
13159     GST_DEBUG_OBJECT (qtdemux, "have covr tag, type=%d,len=%d", type, len);
13160     if ((type == 0x0000000d || type == 0x0000000e) && len > 16) {
13161       GstTagImageType image_type;
13162
13163       if (gst_tag_list_get_tag_size (taglist, GST_TAG_IMAGE) == 0)
13164         image_type = GST_TAG_IMAGE_TYPE_FRONT_COVER;
13165       else
13166         image_type = GST_TAG_IMAGE_TYPE_NONE;
13167
13168       if ((sample =
13169               gst_tag_image_data_to_image_sample ((guint8 *) data->data + 16,
13170                   len - 16, image_type))) {
13171         GST_DEBUG_OBJECT (qtdemux, "adding tag size %d", len - 16);
13172         gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag1, sample, NULL);
13173         gst_sample_unref (sample);
13174       }
13175     }
13176   }
13177 }
13178
13179 static void
13180 qtdemux_tag_add_date (GstQTDemux * qtdemux, GstTagList * taglist,
13181     const char *tag, const char *dummy, GNode * node)
13182 {
13183   GNode *data;
13184   GstDateTime *datetime = NULL;
13185   char *s;
13186   int len;
13187   int type;
13188
13189   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
13190   if (data) {
13191     len = QT_UINT32 (data->data);
13192     type = QT_UINT32 ((guint8 *) data->data + 8);
13193     if (type == 0x00000001 && len > 16) {
13194       guint y, m = 1, d = 1;
13195       gint ret;
13196
13197       s = g_strndup ((char *) data->data + 16, len - 16);
13198       GST_DEBUG_OBJECT (qtdemux, "adding date '%s'", s);
13199       datetime = gst_date_time_new_from_iso8601_string (s);
13200       if (datetime != NULL) {
13201         gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, GST_TAG_DATE_TIME,
13202             datetime, NULL);
13203         gst_date_time_unref (datetime);
13204       }
13205
13206       ret = sscanf (s, "%u-%u-%u", &y, &m, &d);
13207       if (ret >= 1 && y > 1500 && y < 3000) {
13208         GDate *date;
13209
13210         date = g_date_new_dmy (d, m, y);
13211         gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag, date, NULL);
13212         g_date_free (date);
13213       } else {
13214         GST_DEBUG_OBJECT (qtdemux, "could not parse date string '%s'", s);
13215       }
13216       g_free (s);
13217     }
13218   }
13219 }
13220
13221 static void
13222 qtdemux_tag_add_gnre (GstQTDemux * qtdemux, GstTagList * taglist,
13223     const char *tag, const char *dummy, GNode * node)
13224 {
13225   GNode *data;
13226
13227   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
13228
13229   /* re-route to normal string tag if major brand says so
13230    * or no data atom and compatible brand suggests so */
13231   if (qtdemux_is_brand_3gp (qtdemux, TRUE) ||
13232       (qtdemux_is_brand_3gp (qtdemux, FALSE) && !data)) {
13233     qtdemux_tag_add_str (qtdemux, taglist, tag, dummy, node);
13234     return;
13235   }
13236
13237   if (data) {
13238     guint len, type, n;
13239
13240     len = QT_UINT32 (data->data);
13241     type = QT_UINT32 ((guint8 *) data->data + 8);
13242     if (type == 0x00000000 && len >= 18) {
13243       n = QT_UINT16 ((guint8 *) data->data + 16);
13244       if (n > 0) {
13245         const gchar *genre;
13246
13247         genre = gst_tag_id3_genre_get (n - 1);
13248         if (genre != NULL) {
13249           GST_DEBUG_OBJECT (qtdemux, "adding %d [%s]", n, genre);
13250           gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag, genre, NULL);
13251         }
13252       }
13253     }
13254   }
13255 }
13256
13257 static void
13258 qtdemux_add_double_tag_from_str (GstQTDemux * demux, GstTagList * taglist,
13259     const gchar * tag, guint8 * data, guint32 datasize)
13260 {
13261   gdouble value;
13262   gchar *datacopy;
13263
13264   /* make a copy to have \0 at the end */
13265   datacopy = g_strndup ((gchar *) data, datasize);
13266
13267   /* convert the str to double */
13268   if (sscanf (datacopy, "%lf", &value) == 1) {
13269     GST_DEBUG_OBJECT (demux, "adding tag: %s [%s]", tag, datacopy);
13270     gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag, value, NULL);
13271   } else {
13272     GST_WARNING_OBJECT (demux, "Failed to parse double from string: %s",
13273         datacopy);
13274   }
13275   g_free (datacopy);
13276 }
13277
13278
13279 static void
13280 qtdemux_tag_add_revdns (GstQTDemux * demux, GstTagList * taglist,
13281     const char *tag, const char *tag_bis, GNode * node)
13282 {
13283   GNode *mean;
13284   GNode *name;
13285   GNode *data;
13286   guint32 meansize;
13287   guint32 namesize;
13288   guint32 datatype;
13289   guint32 datasize;
13290   const gchar *meanstr;
13291   const gchar *namestr;
13292
13293   /* checking the whole ---- atom size for consistency */
13294   if (QT_UINT32 (node->data) <= 4 + 12 + 12 + 16) {
13295     GST_WARNING_OBJECT (demux, "Tag ---- atom is too small, ignoring");
13296     return;
13297   }
13298
13299   mean = qtdemux_tree_get_child_by_type (node, FOURCC_mean);
13300   if (!mean) {
13301     GST_WARNING_OBJECT (demux, "No 'mean' atom found");
13302     return;
13303   }
13304
13305   meansize = QT_UINT32 (mean->data);
13306   if (meansize <= 12) {
13307     GST_WARNING_OBJECT (demux, "Small mean atom, ignoring the whole tag");
13308     return;
13309   }
13310   meanstr = ((gchar *) mean->data) + 12;
13311   meansize -= 12;
13312
13313   name = qtdemux_tree_get_child_by_type (node, FOURCC_name);
13314   if (!name) {
13315     GST_WARNING_OBJECT (demux, "'name' atom not found, ignoring tag");
13316     return;
13317   }
13318
13319   namesize = QT_UINT32 (name->data);
13320   if (namesize <= 12) {
13321     GST_WARNING_OBJECT (demux, "'name' atom is too small, ignoring tag");
13322     return;
13323   }
13324   namestr = ((gchar *) name->data) + 12;
13325   namesize -= 12;
13326
13327   /*
13328    * Data atom is:
13329    * uint32 - size
13330    * uint32 - name
13331    * uint8  - version
13332    * uint24 - data type
13333    * uint32 - all 0
13334    * rest   - the data
13335    */
13336   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
13337   if (!data) {
13338     GST_WARNING_OBJECT (demux, "No data atom in this tag");
13339     return;
13340   }
13341   datasize = QT_UINT32 (data->data);
13342   if (datasize <= 16) {
13343     GST_WARNING_OBJECT (demux, "Data atom too small");
13344     return;
13345   }
13346   datatype = QT_UINT32 (((gchar *) data->data) + 8) & 0xFFFFFF;
13347
13348   if ((strncmp (meanstr, "com.apple.iTunes", meansize) == 0) ||
13349       (strncmp (meanstr, "org.hydrogenaudio.replaygain", meansize) == 0)) {
13350     static const struct
13351     {
13352       const gchar name[28];
13353       const gchar tag[28];
13354     } tags[] = {
13355       {
13356       "replaygain_track_gain", GST_TAG_TRACK_GAIN}, {
13357       "replaygain_track_peak", GST_TAG_TRACK_PEAK}, {
13358       "replaygain_album_gain", GST_TAG_ALBUM_GAIN}, {
13359       "replaygain_album_peak", GST_TAG_ALBUM_PEAK}, {
13360       "MusicBrainz Track Id", GST_TAG_MUSICBRAINZ_TRACKID}, {
13361       "MusicBrainz Artist Id", GST_TAG_MUSICBRAINZ_ARTISTID}, {
13362       "MusicBrainz Album Id", GST_TAG_MUSICBRAINZ_ALBUMID}, {
13363       "MusicBrainz Album Artist Id", GST_TAG_MUSICBRAINZ_ALBUMARTISTID}
13364     };
13365     int i;
13366
13367     for (i = 0; i < G_N_ELEMENTS (tags); ++i) {
13368       if (!g_ascii_strncasecmp (tags[i].name, namestr, namesize)) {
13369         switch (gst_tag_get_type (tags[i].tag)) {
13370           case G_TYPE_DOUBLE:
13371             qtdemux_add_double_tag_from_str (demux, taglist, tags[i].tag,
13372                 ((guint8 *) data->data) + 16, datasize - 16);
13373             break;
13374           case G_TYPE_STRING:
13375             qtdemux_tag_add_str (demux, taglist, tags[i].tag, NULL, node);
13376             break;
13377           default:
13378             /* not reached */
13379             break;
13380         }
13381         break;
13382       }
13383     }
13384     if (i == G_N_ELEMENTS (tags))
13385       goto unknown_tag;
13386   } else {
13387     goto unknown_tag;
13388   }
13389
13390   return;
13391
13392 /* errors */
13393 unknown_tag:
13394 #ifndef GST_DISABLE_GST_DEBUG
13395   {
13396     gchar *namestr_dbg;
13397     gchar *meanstr_dbg;
13398
13399     meanstr_dbg = g_strndup (meanstr, meansize);
13400     namestr_dbg = g_strndup (namestr, namesize);
13401
13402     GST_WARNING_OBJECT (demux, "This tag %s:%s type:%u is not mapped, "
13403         "file a bug at bugzilla.gnome.org", meanstr_dbg, namestr_dbg, datatype);
13404
13405     g_free (namestr_dbg);
13406     g_free (meanstr_dbg);
13407   }
13408 #endif
13409   return;
13410 }
13411
13412 static void
13413 qtdemux_tag_add_id32 (GstQTDemux * demux, GstTagList * taglist, const char *tag,
13414     const char *tag_bis, GNode * node)
13415 {
13416   guint8 *data;
13417   GstBuffer *buf;
13418   guint len;
13419   GstTagList *id32_taglist = NULL;
13420
13421   GST_LOG_OBJECT (demux, "parsing ID32");
13422
13423   data = node->data;
13424   len = GST_READ_UINT32_BE (data);
13425
13426   /* need at least full box and language tag */
13427   if (len < 12 + 2)
13428     return;
13429
13430   buf = gst_buffer_new_allocate (NULL, len - 14, NULL);
13431   gst_buffer_fill (buf, 0, data + 14, len - 14);
13432
13433   id32_taglist = gst_tag_list_from_id3v2_tag (buf);
13434   if (id32_taglist) {
13435     GST_LOG_OBJECT (demux, "parsing ok");
13436     gst_tag_list_insert (taglist, id32_taglist, GST_TAG_MERGE_KEEP);
13437     gst_tag_list_unref (id32_taglist);
13438   } else {
13439     GST_LOG_OBJECT (demux, "parsing failed");
13440   }
13441
13442   gst_buffer_unref (buf);
13443 }
13444
13445 typedef void (*GstQTDemuxAddTagFunc) (GstQTDemux * demux, GstTagList * taglist,
13446     const char *tag, const char *tag_bis, GNode * node);
13447
13448 /* unmapped tags
13449 FOURCC_pcst -> if media is a podcast -> bool
13450 FOURCC_cpil -> if media is part of a compilation -> bool
13451 FOURCC_pgap -> if media is part of a gapless context -> bool
13452 FOURCC_tven -> the tv episode id e.g. S01E23 -> str
13453 */
13454
13455 static const struct
13456 {
13457   guint32 fourcc;
13458   const gchar *gst_tag;
13459   const gchar *gst_tag_bis;
13460   const GstQTDemuxAddTagFunc func;
13461 } add_funcs[] = {
13462   {
13463   FOURCC__nam, GST_TAG_TITLE, NULL, qtdemux_tag_add_str}, {
13464   FOURCC_titl, GST_TAG_TITLE, NULL, qtdemux_tag_add_str}, {
13465   FOURCC__grp, GST_TAG_GROUPING, NULL, qtdemux_tag_add_str}, {
13466   FOURCC__wrt, GST_TAG_COMPOSER, NULL, qtdemux_tag_add_str}, {
13467   FOURCC__ART, GST_TAG_ARTIST, NULL, qtdemux_tag_add_str}, {
13468   FOURCC_aART, GST_TAG_ALBUM_ARTIST, NULL, qtdemux_tag_add_str}, {
13469   FOURCC_perf, GST_TAG_ARTIST, NULL, qtdemux_tag_add_str}, {
13470   FOURCC_auth, GST_TAG_COMPOSER, NULL, qtdemux_tag_add_str}, {
13471   FOURCC__alb, GST_TAG_ALBUM, NULL, qtdemux_tag_add_str}, {
13472   FOURCC_albm, GST_TAG_ALBUM, NULL, qtdemux_tag_add_str}, {
13473   FOURCC_cprt, GST_TAG_COPYRIGHT, NULL, qtdemux_tag_add_str}, {
13474   FOURCC__cpy, GST_TAG_COPYRIGHT, NULL, qtdemux_tag_add_str}, {
13475   FOURCC__cmt, GST_TAG_COMMENT, NULL, qtdemux_tag_add_str}, {
13476   FOURCC__des, GST_TAG_DESCRIPTION, NULL, qtdemux_tag_add_str}, {
13477   FOURCC_desc, GST_TAG_DESCRIPTION, NULL, qtdemux_tag_add_str}, {
13478   FOURCC_dscp, GST_TAG_DESCRIPTION, NULL, qtdemux_tag_add_str}, {
13479   FOURCC__lyr, GST_TAG_LYRICS, NULL, qtdemux_tag_add_str}, {
13480   FOURCC__day, GST_TAG_DATE, NULL, qtdemux_tag_add_date}, {
13481   FOURCC_yrrc, GST_TAG_DATE, NULL, qtdemux_tag_add_year}, {
13482   FOURCC__too, GST_TAG_ENCODER, NULL, qtdemux_tag_add_str}, {
13483   FOURCC__inf, GST_TAG_COMMENT, NULL, qtdemux_tag_add_str}, {
13484   FOURCC_trkn, GST_TAG_TRACK_NUMBER, GST_TAG_TRACK_COUNT, qtdemux_tag_add_num}, {
13485   FOURCC_disk, GST_TAG_ALBUM_VOLUME_NUMBER, GST_TAG_ALBUM_VOLUME_COUNT,
13486         qtdemux_tag_add_num}, {
13487   FOURCC_disc, GST_TAG_ALBUM_VOLUME_NUMBER, GST_TAG_ALBUM_VOLUME_COUNT,
13488         qtdemux_tag_add_num}, {
13489   FOURCC__gen, GST_TAG_GENRE, NULL, qtdemux_tag_add_str}, {
13490   FOURCC_gnre, GST_TAG_GENRE, NULL, qtdemux_tag_add_gnre}, {
13491   FOURCC_tmpo, GST_TAG_BEATS_PER_MINUTE, NULL, qtdemux_tag_add_tmpo}, {
13492   FOURCC_covr, GST_TAG_IMAGE, NULL, qtdemux_tag_add_covr}, {
13493   FOURCC_sonm, GST_TAG_TITLE_SORTNAME, NULL, qtdemux_tag_add_str}, {
13494   FOURCC_soal, GST_TAG_ALBUM_SORTNAME, NULL, qtdemux_tag_add_str}, {
13495   FOURCC_soar, GST_TAG_ARTIST_SORTNAME, NULL, qtdemux_tag_add_str}, {
13496   FOURCC_soaa, GST_TAG_ALBUM_ARTIST_SORTNAME, NULL, qtdemux_tag_add_str}, {
13497   FOURCC_soco, GST_TAG_COMPOSER_SORTNAME, NULL, qtdemux_tag_add_str}, {
13498   FOURCC_sosn, GST_TAG_SHOW_SORTNAME, NULL, qtdemux_tag_add_str}, {
13499   FOURCC_tvsh, GST_TAG_SHOW_NAME, NULL, qtdemux_tag_add_str}, {
13500   FOURCC_tvsn, GST_TAG_SHOW_SEASON_NUMBER, NULL, qtdemux_tag_add_uint32}, {
13501   FOURCC_tves, GST_TAG_SHOW_EPISODE_NUMBER, NULL, qtdemux_tag_add_uint32}, {
13502   FOURCC_kywd, GST_TAG_KEYWORDS, NULL, qtdemux_tag_add_keywords}, {
13503   FOURCC_keyw, GST_TAG_KEYWORDS, NULL, qtdemux_tag_add_str}, {
13504   FOURCC__enc, GST_TAG_ENCODER, NULL, qtdemux_tag_add_str}, {
13505   FOURCC_loci, GST_TAG_GEO_LOCATION_NAME, NULL, qtdemux_tag_add_location}, {
13506   FOURCC_clsf, GST_QT_DEMUX_CLASSIFICATION_TAG, NULL,
13507         qtdemux_tag_add_classification}, {
13508   FOURCC__mak, GST_TAG_DEVICE_MANUFACTURER, NULL, qtdemux_tag_add_str}, {
13509   FOURCC__mod, GST_TAG_DEVICE_MODEL, NULL, qtdemux_tag_add_str}, {
13510   FOURCC__swr, GST_TAG_APPLICATION_NAME, NULL, qtdemux_tag_add_str}, {
13511
13512     /* This is a special case, some tags are stored in this
13513      * 'reverse dns naming', according to:
13514      * http://atomicparsley.sourceforge.net/mpeg-4files.html and
13515      * bug #614471
13516      */
13517   FOURCC_____, "", NULL, qtdemux_tag_add_revdns}, {
13518     /* see http://www.mp4ra.org/specs.html for ID32 in meta box */
13519   FOURCC_ID32, "", NULL, qtdemux_tag_add_id32}
13520 };
13521
13522 struct _GstQtDemuxTagList
13523 {
13524   GstQTDemux *demux;
13525   GstTagList *taglist;
13526 };
13527 typedef struct _GstQtDemuxTagList GstQtDemuxTagList;
13528
13529 static void
13530 qtdemux_tag_add_blob (GNode * node, GstQtDemuxTagList * qtdemuxtaglist)
13531 {
13532   gint len;
13533   guint8 *data;
13534   GstBuffer *buf;
13535   gchar *media_type;
13536   const gchar *style;
13537   GstSample *sample;
13538   GstStructure *s;
13539   guint i;
13540   guint8 ndata[4];
13541   GstQTDemux *demux = qtdemuxtaglist->demux;
13542   GstTagList *taglist = qtdemuxtaglist->taglist;
13543
13544   data = node->data;
13545   len = QT_UINT32 (data);
13546   buf = gst_buffer_new_and_alloc (len);
13547   gst_buffer_fill (buf, 0, data, len);
13548
13549   /* heuristic to determine style of tag */
13550   if (QT_FOURCC (data + 4) == FOURCC_____ ||
13551       (len > 8 + 12 && QT_FOURCC (data + 12) == FOURCC_data))
13552     style = "itunes";
13553   else if (demux->major_brand == FOURCC_qt__)
13554     style = "quicktime";
13555   /* fall back to assuming iso/3gp tag style */
13556   else
13557     style = "iso";
13558
13559   /* santize the name for the caps. */
13560   for (i = 0; i < 4; i++) {
13561     guint8 d = data[4 + i];
13562     if (g_ascii_isalnum (d))
13563       ndata[i] = g_ascii_tolower (d);
13564     else
13565       ndata[i] = '_';
13566   }
13567
13568   media_type = g_strdup_printf ("application/x-gst-qt-%c%c%c%c-tag",
13569       ndata[0], ndata[1], ndata[2], ndata[3]);
13570   GST_DEBUG_OBJECT (demux, "media type %s", media_type);
13571
13572   s = gst_structure_new (media_type, "style", G_TYPE_STRING, style, NULL);
13573   sample = gst_sample_new (buf, NULL, NULL, s);
13574   gst_buffer_unref (buf);
13575   g_free (media_type);
13576
13577   GST_DEBUG_OBJECT (demux, "adding private tag; size %d, info %" GST_PTR_FORMAT,
13578       len, s);
13579
13580   gst_tag_list_add (taglist, GST_TAG_MERGE_APPEND,
13581       GST_QT_DEMUX_PRIVATE_TAG, sample, NULL);
13582
13583   gst_sample_unref (sample);
13584 }
13585
13586 static void
13587 qtdemux_parse_udta (GstQTDemux * qtdemux, GstTagList * taglist, GNode * udta)
13588 {
13589   GNode *meta;
13590   GNode *ilst;
13591   GNode *xmp_;
13592   GNode *node;
13593   gint i;
13594   GstQtDemuxTagList demuxtaglist;
13595
13596   demuxtaglist.demux = qtdemux;
13597   demuxtaglist.taglist = taglist;
13598
13599   meta = qtdemux_tree_get_child_by_type (udta, FOURCC_meta);
13600   if (meta != NULL) {
13601     ilst = qtdemux_tree_get_child_by_type (meta, FOURCC_ilst);
13602     if (ilst == NULL) {
13603       GST_LOG_OBJECT (qtdemux, "no ilst");
13604       return;
13605     }
13606   } else {
13607     ilst = udta;
13608     GST_LOG_OBJECT (qtdemux, "no meta so using udta itself");
13609   }
13610
13611   i = 0;
13612   while (i < G_N_ELEMENTS (add_funcs)) {
13613     node = qtdemux_tree_get_child_by_type (ilst, add_funcs[i].fourcc);
13614     if (node) {
13615       gint len;
13616
13617       len = QT_UINT32 (node->data);
13618       if (len < 12) {
13619         GST_DEBUG_OBJECT (qtdemux, "too small tag atom %" GST_FOURCC_FORMAT,
13620             GST_FOURCC_ARGS (add_funcs[i].fourcc));
13621       } else {
13622         add_funcs[i].func (qtdemux, taglist, add_funcs[i].gst_tag,
13623             add_funcs[i].gst_tag_bis, node);
13624       }
13625       g_node_destroy (node);
13626     } else {
13627       i++;
13628     }
13629   }
13630
13631   /* parsed nodes have been removed, pass along remainder as blob */
13632   g_node_children_foreach (ilst, G_TRAVERSE_ALL,
13633       (GNodeForeachFunc) qtdemux_tag_add_blob, &demuxtaglist);
13634
13635   /* parse up XMP_ node if existing */
13636   xmp_ = qtdemux_tree_get_child_by_type (udta, FOURCC_XMP_);
13637   if (xmp_ != NULL) {
13638     GstBuffer *buf;
13639     GstTagList *xmptaglist;
13640
13641     buf = _gst_buffer_new_wrapped (((guint8 *) xmp_->data) + 8,
13642         QT_UINT32 ((guint8 *) xmp_->data) - 8, NULL);
13643     xmptaglist = gst_tag_list_from_xmp_buffer (buf);
13644     gst_buffer_unref (buf);
13645
13646     qtdemux_handle_xmp_taglist (qtdemux, taglist, xmptaglist);
13647   } else {
13648     GST_DEBUG_OBJECT (qtdemux, "No XMP_ node found");
13649   }
13650 }
13651
13652 typedef struct
13653 {
13654   GstStructure *structure;      /* helper for sort function */
13655   gchar *location;
13656   guint min_req_bitrate;
13657   guint min_req_qt_version;
13658 } GstQtReference;
13659
13660 static gint
13661 qtdemux_redirects_sort_func (gconstpointer a, gconstpointer b)
13662 {
13663   GstQtReference *ref_a = (GstQtReference *) a;
13664   GstQtReference *ref_b = (GstQtReference *) b;
13665
13666   if (ref_b->min_req_qt_version != ref_a->min_req_qt_version)
13667     return ref_b->min_req_qt_version - ref_a->min_req_qt_version;
13668
13669   /* known bitrates go before unknown; higher bitrates go first */
13670   return ref_b->min_req_bitrate - ref_a->min_req_bitrate;
13671 }
13672
13673 /* sort the redirects and post a message for the application.
13674  */
13675 static void
13676 qtdemux_process_redirects (GstQTDemux * qtdemux, GList * references)
13677 {
13678   GstQtReference *best;
13679   GstStructure *s;
13680   GstMessage *msg;
13681   GValue list_val = { 0, };
13682   GList *l;
13683
13684   g_assert (references != NULL);
13685
13686   references = g_list_sort (references, qtdemux_redirects_sort_func);
13687
13688   best = (GstQtReference *) references->data;
13689
13690   g_value_init (&list_val, GST_TYPE_LIST);
13691
13692   for (l = references; l != NULL; l = l->next) {
13693     GstQtReference *ref = (GstQtReference *) l->data;
13694     GValue struct_val = { 0, };
13695
13696     ref->structure = gst_structure_new ("redirect",
13697         "new-location", G_TYPE_STRING, ref->location, NULL);
13698
13699     if (ref->min_req_bitrate > 0) {
13700       gst_structure_set (ref->structure, "minimum-bitrate", G_TYPE_INT,
13701           ref->min_req_bitrate, NULL);
13702     }
13703
13704     g_value_init (&struct_val, GST_TYPE_STRUCTURE);
13705     g_value_set_boxed (&struct_val, ref->structure);
13706     gst_value_list_append_value (&list_val, &struct_val);
13707     g_value_unset (&struct_val);
13708     /* don't free anything here yet, since we need best->structure below */
13709   }
13710
13711   g_assert (best != NULL);
13712   s = gst_structure_copy (best->structure);
13713
13714   if (g_list_length (references) > 1) {
13715     gst_structure_set_value (s, "locations", &list_val);
13716   }
13717
13718   g_value_unset (&list_val);
13719
13720   for (l = references; l != NULL; l = l->next) {
13721     GstQtReference *ref = (GstQtReference *) l->data;
13722
13723     gst_structure_free (ref->structure);
13724     g_free (ref->location);
13725     g_free (ref);
13726   }
13727   g_list_free (references);
13728
13729   GST_INFO_OBJECT (qtdemux, "posting redirect message: %" GST_PTR_FORMAT, s);
13730   msg = gst_message_new_element (GST_OBJECT_CAST (qtdemux), s);
13731   gst_element_post_message (GST_ELEMENT_CAST (qtdemux), msg);
13732   qtdemux->posted_redirect = TRUE;
13733 }
13734
13735 /* look for redirect nodes, collect all redirect information and
13736  * process it.
13737  */
13738 static gboolean
13739 qtdemux_parse_redirects (GstQTDemux * qtdemux)
13740 {
13741   GNode *rmra, *rmda, *rdrf;
13742
13743   rmra = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_rmra);
13744   if (rmra) {
13745     GList *redirects = NULL;
13746
13747     rmda = qtdemux_tree_get_child_by_type (rmra, FOURCC_rmda);
13748     while (rmda) {
13749       GstQtReference ref = { NULL, NULL, 0, 0 };
13750       GNode *rmdr, *rmvc;
13751
13752       if ((rmdr = qtdemux_tree_get_child_by_type (rmda, FOURCC_rmdr))) {
13753         ref.min_req_bitrate = QT_UINT32 ((guint8 *) rmdr->data + 12);
13754         GST_LOG_OBJECT (qtdemux, "data rate atom, required bitrate = %u",
13755             ref.min_req_bitrate);
13756       }
13757
13758       if ((rmvc = qtdemux_tree_get_child_by_type (rmda, FOURCC_rmvc))) {
13759         guint32 package = QT_FOURCC ((guint8 *) rmvc->data + 12);
13760         guint version = QT_UINT32 ((guint8 *) rmvc->data + 16);
13761
13762 #ifndef GST_DISABLE_GST_DEBUG
13763         guint bitmask = QT_UINT32 ((guint8 *) rmvc->data + 20);
13764 #endif
13765         guint check_type = QT_UINT16 ((guint8 *) rmvc->data + 24);
13766
13767         GST_LOG_OBJECT (qtdemux,
13768             "version check atom [%" GST_FOURCC_FORMAT "], version=0x%08x"
13769             ", mask=%08x, check_type=%u", GST_FOURCC_ARGS (package), version,
13770             bitmask, check_type);
13771         if (package == FOURCC_qtim && check_type == 0) {
13772           ref.min_req_qt_version = version;
13773         }
13774       }
13775
13776       rdrf = qtdemux_tree_get_child_by_type (rmda, FOURCC_rdrf);
13777       if (rdrf) {
13778         guint32 ref_type;
13779         guint8 *ref_data;
13780         guint ref_len;
13781
13782         ref_len = QT_UINT32 ((guint8 *) rdrf->data);
13783         if (ref_len > 20) {
13784           ref_type = QT_FOURCC ((guint8 *) rdrf->data + 12);
13785           ref_data = (guint8 *) rdrf->data + 20;
13786           if (ref_type == FOURCC_alis) {
13787             guint record_len, record_version, fn_len;
13788
13789             if (ref_len > 70) {
13790               /* MacOSX alias record, google for alias-layout.txt */
13791               record_len = QT_UINT16 (ref_data + 4);
13792               record_version = QT_UINT16 (ref_data + 4 + 2);
13793               fn_len = QT_UINT8 (ref_data + 50);
13794               if (record_len > 50 && record_version == 2 && fn_len > 0) {
13795                 ref.location = g_strndup ((gchar *) ref_data + 51, fn_len);
13796               }
13797             } else {
13798               GST_WARNING_OBJECT (qtdemux, "Invalid rdrf/alis size (%u < 70)",
13799                   ref_len);
13800             }
13801           } else if (ref_type == FOURCC_url_) {
13802             ref.location = g_strndup ((gchar *) ref_data, ref_len - 8);
13803           } else {
13804             GST_DEBUG_OBJECT (qtdemux,
13805                 "unknown rdrf reference type %" GST_FOURCC_FORMAT,
13806                 GST_FOURCC_ARGS (ref_type));
13807           }
13808           if (ref.location != NULL) {
13809             GST_INFO_OBJECT (qtdemux, "New location: %s", ref.location);
13810             redirects =
13811                 g_list_prepend (redirects, g_memdup (&ref, sizeof (ref)));
13812           } else {
13813             GST_WARNING_OBJECT (qtdemux,
13814                 "Failed to extract redirect location from rdrf atom");
13815           }
13816         } else {
13817           GST_WARNING_OBJECT (qtdemux, "Invalid rdrf size (%u < 20)", ref_len);
13818         }
13819       }
13820
13821       /* look for others */
13822       rmda = qtdemux_tree_get_sibling_by_type (rmda, FOURCC_rmda);
13823     }
13824
13825     if (redirects != NULL) {
13826       qtdemux_process_redirects (qtdemux, redirects);
13827     }
13828   }
13829   return TRUE;
13830 }
13831
13832 static GstTagList *
13833 qtdemux_add_container_format (GstQTDemux * qtdemux, GstTagList * tags)
13834 {
13835   const gchar *fmt;
13836
13837   if (tags == NULL) {
13838     tags = gst_tag_list_new_empty ();
13839     gst_tag_list_set_scope (tags, GST_TAG_SCOPE_GLOBAL);
13840   }
13841
13842   if (qtdemux->major_brand == FOURCC_mjp2)
13843     fmt = "Motion JPEG 2000";
13844   else if ((qtdemux->major_brand & 0xffff) == FOURCC_3g__)
13845     fmt = "3GP";
13846   else if (qtdemux->major_brand == FOURCC_qt__)
13847     fmt = "Quicktime";
13848   else if (qtdemux->fragmented)
13849     fmt = "ISO fMP4";
13850   else
13851     fmt = "ISO MP4/M4A";
13852
13853   GST_LOG_OBJECT (qtdemux, "mapped %" GST_FOURCC_FORMAT " to '%s'",
13854       GST_FOURCC_ARGS (qtdemux->major_brand), fmt);
13855
13856   gst_tag_list_add (tags, GST_TAG_MERGE_REPLACE, GST_TAG_CONTAINER_FORMAT,
13857       fmt, NULL);
13858
13859   return tags;
13860 }
13861
13862 /* we have read the complete moov node now.
13863  * This function parses all of the relevant info, creates the traks and
13864  * prepares all data structures for playback
13865  */
13866 static gboolean
13867 qtdemux_parse_tree (GstQTDemux * qtdemux)
13868 {
13869   GNode *mvhd;
13870   GNode *trak;
13871   GNode *udta;
13872   GNode *mvex;
13873   GNode *pssh;
13874   guint64 creation_time;
13875   GstDateTime *datetime = NULL;
13876   gint version;
13877
13878   /* make sure we have a usable taglist */
13879   qtdemux->tag_list = gst_tag_list_make_writable (qtdemux->tag_list);
13880
13881   mvhd = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_mvhd);
13882   if (mvhd == NULL) {
13883     GST_LOG_OBJECT (qtdemux, "No mvhd node found, looking for redirects.");
13884     return qtdemux_parse_redirects (qtdemux);
13885   }
13886
13887   version = QT_UINT8 ((guint8 *) mvhd->data + 8);
13888   if (version == 1) {
13889     creation_time = QT_UINT64 ((guint8 *) mvhd->data + 12);
13890     qtdemux->timescale = QT_UINT32 ((guint8 *) mvhd->data + 28);
13891     qtdemux->duration = QT_UINT64 ((guint8 *) mvhd->data + 32);
13892   } else if (version == 0) {
13893     creation_time = QT_UINT32 ((guint8 *) mvhd->data + 12);
13894     qtdemux->timescale = QT_UINT32 ((guint8 *) mvhd->data + 20);
13895     qtdemux->duration = QT_UINT32 ((guint8 *) mvhd->data + 24);
13896   } else {
13897     GST_WARNING_OBJECT (qtdemux, "Unhandled mvhd version %d", version);
13898     return FALSE;
13899   }
13900
13901   /* Moving qt creation time (secs since 1904) to unix time */
13902   if (creation_time != 0) {
13903     /* Try to use epoch first as it should be faster and more commonly found */
13904     if (creation_time >= QTDEMUX_SECONDS_FROM_1904_TO_1970) {
13905       GTimeVal now;
13906
13907       creation_time -= QTDEMUX_SECONDS_FROM_1904_TO_1970;
13908       /* some data cleansing sanity */
13909       g_get_current_time (&now);
13910       if (now.tv_sec + 24 * 3600 < creation_time) {
13911         GST_DEBUG_OBJECT (qtdemux, "discarding bogus future creation time");
13912       } else {
13913         datetime = gst_date_time_new_from_unix_epoch_utc (creation_time);
13914       }
13915     } else {
13916       GDateTime *base_dt = g_date_time_new_utc (1904, 1, 1, 0, 0, 0);
13917       GDateTime *dt, *dt_local;
13918
13919       dt = g_date_time_add_seconds (base_dt, creation_time);
13920       dt_local = g_date_time_to_local (dt);
13921       datetime = gst_date_time_new_from_g_date_time (dt_local);
13922
13923       g_date_time_unref (base_dt);
13924       g_date_time_unref (dt);
13925     }
13926   }
13927   if (datetime) {
13928     /* Use KEEP as explicit tags should have a higher priority than mvhd tag */
13929     gst_tag_list_add (qtdemux->tag_list, GST_TAG_MERGE_KEEP, GST_TAG_DATE_TIME,
13930         datetime, NULL);
13931     gst_date_time_unref (datetime);
13932   }
13933
13934   GST_INFO_OBJECT (qtdemux, "timescale: %u", qtdemux->timescale);
13935   GST_INFO_OBJECT (qtdemux, "duration: %" G_GUINT64_FORMAT, qtdemux->duration);
13936
13937   /* check for fragmented file and get some (default) data */
13938   mvex = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_mvex);
13939   if (mvex) {
13940     GNode *mehd;
13941     GstByteReader mehd_data;
13942
13943     /* let track parsing or anyone know weird stuff might happen ... */
13944     qtdemux->fragmented = TRUE;
13945
13946     /* compensate for total duration */
13947     mehd = qtdemux_tree_get_child_by_type_full (mvex, FOURCC_mehd, &mehd_data);
13948     if (mehd)
13949       qtdemux_parse_mehd (qtdemux, &mehd_data);
13950   }
13951
13952   /* Update the movie segment duration, unless it was directly given to us
13953    * by upstream. Otherwise let it as is, as we don't want to mangle the
13954    * duration provided by upstream that may come e.g. from a MPD file. */
13955   if (!qtdemux->upstream_format_is_time) {
13956     GstClockTime duration;
13957     /* set duration in the segment info */
13958     gst_qtdemux_get_duration (qtdemux, &duration);
13959     qtdemux->segment.duration = duration;
13960     /* also do not exceed duration; stop is set that way post seek anyway,
13961      * and segment activation falls back to duration,
13962      * whereas loop only checks stop, so let's align this here as well */
13963     qtdemux->segment.stop = duration;
13964   }
13965
13966   /* parse all traks */
13967   trak = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_trak);
13968   while (trak) {
13969     qtdemux_parse_trak (qtdemux, trak);
13970     /* iterate all siblings */
13971     trak = qtdemux_tree_get_sibling_by_type (trak, FOURCC_trak);
13972   }
13973
13974   qtdemux->tag_list = gst_tag_list_make_writable (qtdemux->tag_list);
13975
13976   /* find tags */
13977   udta = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_udta);
13978   if (udta) {
13979     qtdemux_parse_udta (qtdemux, qtdemux->tag_list, udta);
13980   } else {
13981     GST_LOG_OBJECT (qtdemux, "No udta node found.");
13982   }
13983
13984   /* maybe also some tags in meta box */
13985   udta = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_meta);
13986   if (udta) {
13987     GST_DEBUG_OBJECT (qtdemux, "Parsing meta box for tags.");
13988     qtdemux_parse_udta (qtdemux, qtdemux->tag_list, udta);
13989   } else {
13990     GST_LOG_OBJECT (qtdemux, "No meta node found.");
13991   }
13992
13993   /* parse any protection system info */
13994   pssh = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_pssh);
13995   while (pssh) {
13996     GST_LOG_OBJECT (qtdemux, "Parsing pssh box.");
13997     qtdemux_parse_pssh (qtdemux, pssh);
13998     pssh = qtdemux_tree_get_sibling_by_type (pssh, FOURCC_pssh);
13999   }
14000
14001   qtdemux->tag_list = qtdemux_add_container_format (qtdemux, qtdemux->tag_list);
14002
14003   return TRUE;
14004 }
14005
14006 /* taken from ffmpeg */
14007 static int
14008 read_descr_size (guint8 * ptr, guint8 * end, guint8 ** end_out)
14009 {
14010   int count = 4;
14011   int len = 0;
14012
14013   while (count--) {
14014     int c;
14015
14016     if (ptr >= end)
14017       return -1;
14018
14019     c = *ptr++;
14020     len = (len << 7) | (c & 0x7f);
14021     if (!(c & 0x80))
14022       break;
14023   }
14024   *end_out = ptr;
14025   return len;
14026 }
14027
14028 static GList *
14029 parse_xiph_stream_headers (GstQTDemux * qtdemux, gpointer codec_data,
14030     gsize codec_data_size)
14031 {
14032   GList *list = NULL;
14033   guint8 *p = codec_data;
14034   gint i, offset, num_packets;
14035   guint *length, last;
14036
14037   GST_MEMDUMP_OBJECT (qtdemux, "xiph codec data", codec_data, codec_data_size);
14038
14039   if (codec_data == NULL || codec_data_size == 0)
14040     goto error;
14041
14042   /* start of the stream and vorbis audio or theora video, need to
14043    * send the codec_priv data as first three packets */
14044   num_packets = p[0] + 1;
14045   GST_DEBUG_OBJECT (qtdemux,
14046       "%u stream headers, total length=%" G_GSIZE_FORMAT " bytes",
14047       (guint) num_packets, codec_data_size);
14048
14049   /* Let's put some limits, Don't think there even is a xiph codec
14050    * with more than 3-4 headers */
14051   if (G_UNLIKELY (num_packets > 16)) {
14052     GST_WARNING_OBJECT (qtdemux,
14053         "Unlikely number of xiph headers, most likely not valid");
14054     goto error;
14055   }
14056
14057   length = g_alloca (num_packets * sizeof (guint));
14058   last = 0;
14059   offset = 1;
14060
14061   /* first packets, read length values */
14062   for (i = 0; i < num_packets - 1; i++) {
14063     length[i] = 0;
14064     while (offset < codec_data_size) {
14065       length[i] += p[offset];
14066       if (p[offset++] != 0xff)
14067         break;
14068     }
14069     last += length[i];
14070   }
14071   if (offset + last > codec_data_size)
14072     goto error;
14073
14074   /* last packet is the remaining size */
14075   length[i] = codec_data_size - offset - last;
14076
14077   for (i = 0; i < num_packets; i++) {
14078     GstBuffer *hdr;
14079
14080     GST_DEBUG_OBJECT (qtdemux, "buffer %d: %u bytes", i, (guint) length[i]);
14081
14082     if (offset + length[i] > codec_data_size)
14083       goto error;
14084
14085     hdr = gst_buffer_new_wrapped (g_memdup (p + offset, length[i]), length[i]);
14086     list = g_list_append (list, hdr);
14087
14088     offset += length[i];
14089   }
14090
14091   return list;
14092
14093   /* ERRORS */
14094 error:
14095   {
14096     if (list != NULL)
14097       g_list_free_full (list, (GDestroyNotify) gst_buffer_unref);
14098     return NULL;
14099   }
14100
14101 }
14102
14103 /* this can change the codec originally present in @list */
14104 static void
14105 gst_qtdemux_handle_esds (GstQTDemux * qtdemux, QtDemuxStream * stream,
14106     QtDemuxStreamStsdEntry * entry, GNode * esds, GstTagList * list)
14107 {
14108   int len = QT_UINT32 (esds->data);
14109   guint8 *ptr = esds->data;
14110   guint8 *end = ptr + len;
14111   int tag;
14112   guint8 *data_ptr = NULL;
14113   int data_len = 0;
14114   guint8 object_type_id = 0;
14115   guint8 stream_type = 0;
14116   const char *codec_name = NULL;
14117   GstCaps *caps = NULL;
14118
14119   GST_MEMDUMP_OBJECT (qtdemux, "esds", ptr, len);
14120   ptr += 8;
14121   GST_DEBUG_OBJECT (qtdemux, "version/flags = %08x", QT_UINT32 (ptr));
14122   ptr += 4;
14123   while (ptr + 1 < end) {
14124     tag = QT_UINT8 (ptr);
14125     GST_DEBUG_OBJECT (qtdemux, "tag = %02x", tag);
14126     ptr++;
14127     len = read_descr_size (ptr, end, &ptr);
14128     GST_DEBUG_OBJECT (qtdemux, "len = %d", len);
14129
14130     /* Check the stated amount of data is available for reading */
14131     if (len < 0 || ptr + len > end)
14132       break;
14133
14134     switch (tag) {
14135       case ES_DESCRIPTOR_TAG:
14136         GST_DEBUG_OBJECT (qtdemux, "ID 0x%04x", QT_UINT16 (ptr));
14137         GST_DEBUG_OBJECT (qtdemux, "priority 0x%04x", QT_UINT8 (ptr + 2));
14138         ptr += 3;
14139         break;
14140       case DECODER_CONFIG_DESC_TAG:{
14141         guint max_bitrate, avg_bitrate;
14142
14143         object_type_id = QT_UINT8 (ptr);
14144         stream_type = QT_UINT8 (ptr + 1) >> 2;
14145         max_bitrate = QT_UINT32 (ptr + 5);
14146         avg_bitrate = QT_UINT32 (ptr + 9);
14147         GST_DEBUG_OBJECT (qtdemux, "object_type_id %02x", object_type_id);
14148         GST_DEBUG_OBJECT (qtdemux, "stream_type %02x", stream_type);
14149         GST_DEBUG_OBJECT (qtdemux, "buffer_size_db %02x", QT_UINT24 (ptr + 2));
14150         GST_DEBUG_OBJECT (qtdemux, "max bitrate %u", max_bitrate);
14151         GST_DEBUG_OBJECT (qtdemux, "avg bitrate %u", avg_bitrate);
14152         if (max_bitrate > 0 && max_bitrate < G_MAXUINT32) {
14153           gst_tag_list_add (list, GST_TAG_MERGE_REPLACE,
14154               GST_TAG_MAXIMUM_BITRATE, max_bitrate, NULL);
14155         }
14156         if (avg_bitrate > 0 && avg_bitrate < G_MAXUINT32) {
14157           gst_tag_list_add (list, GST_TAG_MERGE_REPLACE, GST_TAG_BITRATE,
14158               avg_bitrate, NULL);
14159         }
14160         ptr += 13;
14161         break;
14162       }
14163       case DECODER_SPECIFIC_INFO_TAG:
14164         GST_MEMDUMP_OBJECT (qtdemux, "data", ptr, len);
14165         if (object_type_id == 0xe0 && len == 0x40) {
14166           guint8 *data;
14167           GstStructure *s;
14168           guint32 clut[16];
14169           gint i;
14170
14171           GST_DEBUG_OBJECT (qtdemux,
14172               "Have VOBSUB palette. Creating palette event");
14173           /* move to decConfigDescr data and read palette */
14174           data = ptr;
14175           for (i = 0; i < 16; i++) {
14176             clut[i] = QT_UINT32 (data);
14177             data += 4;
14178           }
14179
14180           s = gst_structure_new ("application/x-gst-dvd", "event",
14181               G_TYPE_STRING, "dvd-spu-clut-change",
14182               "clut00", G_TYPE_INT, clut[0], "clut01", G_TYPE_INT, clut[1],
14183               "clut02", G_TYPE_INT, clut[2], "clut03", G_TYPE_INT, clut[3],
14184               "clut04", G_TYPE_INT, clut[4], "clut05", G_TYPE_INT, clut[5],
14185               "clut06", G_TYPE_INT, clut[6], "clut07", G_TYPE_INT, clut[7],
14186               "clut08", G_TYPE_INT, clut[8], "clut09", G_TYPE_INT, clut[9],
14187               "clut10", G_TYPE_INT, clut[10], "clut11", G_TYPE_INT, clut[11],
14188               "clut12", G_TYPE_INT, clut[12], "clut13", G_TYPE_INT, clut[13],
14189               "clut14", G_TYPE_INT, clut[14], "clut15", G_TYPE_INT, clut[15],
14190               NULL);
14191
14192           /* store event and trigger custom processing */
14193           stream->pending_event =
14194               gst_event_new_custom (GST_EVENT_CUSTOM_DOWNSTREAM, s);
14195         } else {
14196           /* Generic codec_data handler puts it on the caps */
14197           data_ptr = ptr;
14198           data_len = len;
14199         }
14200
14201         ptr += len;
14202         break;
14203       case SL_CONFIG_DESC_TAG:
14204         GST_DEBUG_OBJECT (qtdemux, "data %02x", QT_UINT8 (ptr));
14205         ptr += 1;
14206         break;
14207       default:
14208         GST_DEBUG_OBJECT (qtdemux, "Unknown/unhandled descriptor tag %02x",
14209             tag);
14210         GST_MEMDUMP_OBJECT (qtdemux, "descriptor data", ptr, len);
14211         ptr += len;
14212         break;
14213     }
14214   }
14215
14216   /* object_type_id in the esds atom in mp4a and mp4v tells us which codec is
14217    * in use, and should also be used to override some other parameters for some
14218    * codecs. */
14219   switch (object_type_id) {
14220     case 0x20:                 /* MPEG-4 */
14221       /* 4 bytes for the visual_object_sequence_start_code and 1 byte for the
14222        * profile_and_level_indication */
14223       if (data_ptr != NULL && data_len >= 5 &&
14224           GST_READ_UINT32_BE (data_ptr) == 0x000001b0) {
14225         gst_codec_utils_mpeg4video_caps_set_level_and_profile (entry->caps,
14226             data_ptr + 4, data_len - 4);
14227       }
14228       break;                    /* Nothing special needed here */
14229     case 0x21:                 /* H.264 */
14230       codec_name = "H.264 / AVC";
14231       caps = gst_caps_new_simple ("video/x-h264",
14232           "stream-format", G_TYPE_STRING, "avc",
14233           "alignment", G_TYPE_STRING, "au", NULL);
14234       break;
14235     case 0x40:                 /* AAC (any) */
14236     case 0x66:                 /* AAC Main */
14237     case 0x67:                 /* AAC LC */
14238     case 0x68:                 /* AAC SSR */
14239       /* Override channels and rate based on the codec_data, as it's often
14240        * wrong. */
14241       /* Only do so for basic setup without HE-AAC extension */
14242       if (data_ptr && data_len == 2) {
14243         guint channels, rate;
14244
14245         channels = gst_codec_utils_aac_get_channels (data_ptr, data_len);
14246         if (channels > 0)
14247           entry->n_channels = channels;
14248
14249         rate = gst_codec_utils_aac_get_sample_rate (data_ptr, data_len);
14250         if (rate > 0)
14251           entry->rate = rate;
14252       }
14253
14254       /* Set level and profile if possible */
14255       if (data_ptr != NULL && data_len >= 2) {
14256         gst_codec_utils_aac_caps_set_level_and_profile (entry->caps,
14257             data_ptr, data_len);
14258       } else {
14259         const gchar *profile_str = NULL;
14260         GstBuffer *buffer;
14261         GstMapInfo map;
14262         guint8 *codec_data;
14263         gint rate_idx, profile;
14264
14265         /* No codec_data, let's invent something.
14266          * FIXME: This is wrong for SBR! */
14267
14268         GST_WARNING_OBJECT (qtdemux, "No codec_data for AAC available");
14269
14270         buffer = gst_buffer_new_and_alloc (2);
14271         gst_buffer_map (buffer, &map, GST_MAP_WRITE);
14272         codec_data = map.data;
14273
14274         rate_idx =
14275             gst_codec_utils_aac_get_index_from_sample_rate (CUR_STREAM
14276             (stream)->rate);
14277
14278         switch (object_type_id) {
14279           case 0x66:
14280             profile_str = "main";
14281             profile = 0;
14282             break;
14283           case 0x67:
14284             profile_str = "lc";
14285             profile = 1;
14286             break;
14287           case 0x68:
14288             profile_str = "ssr";
14289             profile = 2;
14290             break;
14291           default:
14292             profile = 3;
14293             break;
14294         }
14295
14296         codec_data[0] = ((profile + 1) << 3) | ((rate_idx & 0xE) >> 1);
14297         codec_data[1] =
14298             ((rate_idx & 0x1) << 7) | (CUR_STREAM (stream)->n_channels << 3);
14299
14300         gst_buffer_unmap (buffer, &map);
14301         gst_caps_set_simple (CUR_STREAM (stream)->caps, "codec_data",
14302             GST_TYPE_BUFFER, buffer, NULL);
14303         gst_buffer_unref (buffer);
14304
14305         if (profile_str) {
14306           gst_caps_set_simple (CUR_STREAM (stream)->caps, "profile",
14307               G_TYPE_STRING, profile_str, NULL);
14308         }
14309       }
14310       break;
14311     case 0x60:                 /* MPEG-2, various profiles */
14312     case 0x61:
14313     case 0x62:
14314     case 0x63:
14315     case 0x64:
14316     case 0x65:
14317       codec_name = "MPEG-2 video";
14318       caps = gst_caps_new_simple ("video/mpeg",
14319           "mpegversion", G_TYPE_INT, 2,
14320           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
14321       break;
14322     case 0x69:                 /* MPEG-2 BC audio */
14323     case 0x6B:                 /* MPEG-1 audio */
14324       caps = gst_caps_new_simple ("audio/mpeg",
14325           "mpegversion", G_TYPE_INT, 1, NULL);
14326       codec_name = "MPEG-1 audio";
14327       break;
14328     case 0x6A:                 /* MPEG-1 */
14329       codec_name = "MPEG-1 video";
14330       caps = gst_caps_new_simple ("video/mpeg",
14331           "mpegversion", G_TYPE_INT, 1,
14332           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
14333       break;
14334     case 0x6C:                 /* MJPEG */
14335       caps =
14336           gst_caps_new_simple ("image/jpeg", "parsed", G_TYPE_BOOLEAN, TRUE,
14337           NULL);
14338       codec_name = "Motion-JPEG";
14339       break;
14340     case 0x6D:                 /* PNG */
14341       caps =
14342           gst_caps_new_simple ("image/png", "parsed", G_TYPE_BOOLEAN, TRUE,
14343           NULL);
14344       codec_name = "PNG still images";
14345       break;
14346     case 0x6E:                 /* JPEG2000 */
14347       codec_name = "JPEG-2000";
14348       caps = gst_caps_new_simple ("image/x-j2c", "fields", G_TYPE_INT, 1, NULL);
14349       break;
14350     case 0xA4:                 /* Dirac */
14351       codec_name = "Dirac";
14352       caps = gst_caps_new_empty_simple ("video/x-dirac");
14353       break;
14354     case 0xA5:                 /* AC3 */
14355       codec_name = "AC-3 audio";
14356       caps = gst_caps_new_simple ("audio/x-ac3",
14357           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
14358       break;
14359     case 0xA9:                 /* AC3 */
14360       codec_name = "DTS audio";
14361       caps = gst_caps_new_simple ("audio/x-dts",
14362           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
14363       break;
14364     case 0xDD:
14365       if (stream_type == 0x05 && data_ptr) {
14366         GList *headers =
14367             parse_xiph_stream_headers (qtdemux, data_ptr, data_len);
14368         if (headers) {
14369           GList *tmp;
14370           GValue arr_val = G_VALUE_INIT;
14371           GValue buf_val = G_VALUE_INIT;
14372           GstStructure *s;
14373
14374           /* Let's assume it's vorbis if it's an audio stream of type 0xdd and we have codec data that extracts properly */
14375           codec_name = "Vorbis";
14376           caps = gst_caps_new_empty_simple ("audio/x-vorbis");
14377           g_value_init (&arr_val, GST_TYPE_ARRAY);
14378           g_value_init (&buf_val, GST_TYPE_BUFFER);
14379           for (tmp = headers; tmp; tmp = tmp->next) {
14380             g_value_set_boxed (&buf_val, (GstBuffer *) tmp->data);
14381             gst_value_array_append_value (&arr_val, &buf_val);
14382           }
14383           s = gst_caps_get_structure (caps, 0);
14384           gst_structure_take_value (s, "streamheader", &arr_val);
14385           g_value_unset (&buf_val);
14386           g_list_free (headers);
14387
14388           data_ptr = NULL;
14389           data_len = 0;
14390         }
14391       }
14392       break;
14393     case 0xE1:                 /* QCELP */
14394       /* QCELP, the codec_data is a riff tag (little endian) with
14395        * 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). */
14396       caps = gst_caps_new_empty_simple ("audio/qcelp");
14397       codec_name = "QCELP";
14398       break;
14399     default:
14400       break;
14401   }
14402
14403   /* If we have a replacement caps, then change our caps for this stream */
14404   if (caps) {
14405     gst_caps_unref (entry->caps);
14406     entry->caps = caps;
14407   }
14408
14409   if (codec_name && list)
14410     gst_tag_list_add (list, GST_TAG_MERGE_REPLACE,
14411         GST_TAG_AUDIO_CODEC, codec_name, NULL);
14412
14413   /* Add the codec_data attribute to caps, if we have it */
14414   if (data_ptr) {
14415     GstBuffer *buffer;
14416
14417     buffer = gst_buffer_new_and_alloc (data_len);
14418     gst_buffer_fill (buffer, 0, data_ptr, data_len);
14419
14420     GST_DEBUG_OBJECT (qtdemux, "setting codec_data from esds");
14421     GST_MEMDUMP_OBJECT (qtdemux, "codec_data from esds", data_ptr, data_len);
14422
14423     gst_caps_set_simple (entry->caps, "codec_data", GST_TYPE_BUFFER,
14424         buffer, NULL);
14425     gst_buffer_unref (buffer);
14426   }
14427
14428 }
14429
14430 static inline GstCaps *
14431 _get_unknown_codec_name (const gchar * type, guint32 fourcc)
14432 {
14433   GstCaps *caps;
14434   guint i;
14435   char *s, fourstr[5];
14436
14437   g_snprintf (fourstr, 5, "%" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (fourcc));
14438   for (i = 0; i < 4; i++) {
14439     if (!g_ascii_isalnum (fourstr[i]))
14440       fourstr[i] = '_';
14441   }
14442   s = g_strdup_printf ("%s/x-gst-fourcc-%s", type, g_strstrip (fourstr));
14443   caps = gst_caps_new_empty_simple (s);
14444   g_free (s);
14445   return caps;
14446 }
14447
14448 #define _codec(name) \
14449   do { \
14450     if (codec_name) { \
14451       *codec_name = g_strdup (name); \
14452     } \
14453   } while (0)
14454
14455 static GstCaps *
14456 qtdemux_video_caps (GstQTDemux * qtdemux, QtDemuxStream * stream,
14457     QtDemuxStreamStsdEntry * entry, guint32 fourcc,
14458     const guint8 * stsd_entry_data, gchar ** codec_name)
14459 {
14460   GstCaps *caps = NULL;
14461   GstVideoFormat format = GST_VIDEO_FORMAT_UNKNOWN;
14462
14463   switch (fourcc) {
14464     case FOURCC_png:
14465       _codec ("PNG still images");
14466       caps = gst_caps_new_empty_simple ("image/png");
14467       break;
14468     case FOURCC_jpeg:
14469       _codec ("JPEG still images");
14470       caps =
14471           gst_caps_new_simple ("image/jpeg", "parsed", G_TYPE_BOOLEAN, TRUE,
14472           NULL);
14473       break;
14474     case GST_MAKE_FOURCC ('m', 'j', 'p', 'a'):
14475     case GST_MAKE_FOURCC ('A', 'V', 'D', 'J'):
14476     case GST_MAKE_FOURCC ('M', 'J', 'P', 'G'):
14477     case GST_MAKE_FOURCC ('d', 'm', 'b', '1'):
14478       _codec ("Motion-JPEG");
14479       caps =
14480           gst_caps_new_simple ("image/jpeg", "parsed", G_TYPE_BOOLEAN, TRUE,
14481           NULL);
14482       break;
14483     case GST_MAKE_FOURCC ('m', 'j', 'p', 'b'):
14484       _codec ("Motion-JPEG format B");
14485       caps = gst_caps_new_empty_simple ("video/x-mjpeg-b");
14486       break;
14487     case FOURCC_mjp2:
14488       _codec ("JPEG-2000");
14489       /* override to what it should be according to spec, avoid palette_data */
14490       entry->bits_per_sample = 24;
14491       caps = gst_caps_new_simple ("image/x-j2c", "fields", G_TYPE_INT, 1, NULL);
14492       break;
14493     case FOURCC_SVQ3:
14494       _codec ("Sorensen video v.3");
14495       caps = gst_caps_new_simple ("video/x-svq",
14496           "svqversion", G_TYPE_INT, 3, NULL);
14497       break;
14498     case GST_MAKE_FOURCC ('s', 'v', 'q', 'i'):
14499     case GST_MAKE_FOURCC ('S', 'V', 'Q', '1'):
14500       _codec ("Sorensen video v.1");
14501       caps = gst_caps_new_simple ("video/x-svq",
14502           "svqversion", G_TYPE_INT, 1, NULL);
14503       break;
14504     case GST_MAKE_FOURCC ('W', 'R', 'A', 'W'):
14505       caps = gst_caps_new_empty_simple ("video/x-raw");
14506       gst_caps_set_simple (caps, "format", G_TYPE_STRING, "RGB8P", NULL);
14507       _codec ("Windows Raw RGB");
14508       stream->alignment = 32;
14509       break;
14510     case FOURCC_raw_:
14511     {
14512       guint16 bps;
14513
14514       bps = QT_UINT16 (stsd_entry_data + 82);
14515       switch (bps) {
14516         case 15:
14517           format = GST_VIDEO_FORMAT_RGB15;
14518           break;
14519         case 16:
14520           format = GST_VIDEO_FORMAT_RGB16;
14521           break;
14522         case 24:
14523           format = GST_VIDEO_FORMAT_RGB;
14524           break;
14525         case 32:
14526           format = GST_VIDEO_FORMAT_ARGB;
14527           break;
14528         default:
14529           /* unknown */
14530           break;
14531       }
14532       break;
14533     }
14534     case GST_MAKE_FOURCC ('y', 'v', '1', '2'):
14535       format = GST_VIDEO_FORMAT_I420;
14536       break;
14537     case GST_MAKE_FOURCC ('y', 'u', 'v', '2'):
14538     case GST_MAKE_FOURCC ('Y', 'u', 'v', '2'):
14539       format = GST_VIDEO_FORMAT_I420;
14540       break;
14541     case FOURCC_2vuy:
14542     case GST_MAKE_FOURCC ('2', 'V', 'u', 'y'):
14543       format = GST_VIDEO_FORMAT_UYVY;
14544       break;
14545     case GST_MAKE_FOURCC ('v', '3', '0', '8'):
14546       format = GST_VIDEO_FORMAT_v308;
14547       break;
14548     case GST_MAKE_FOURCC ('v', '2', '1', '6'):
14549       format = GST_VIDEO_FORMAT_v216;
14550       break;
14551     case FOURCC_v210:
14552       format = GST_VIDEO_FORMAT_v210;
14553       break;
14554     case GST_MAKE_FOURCC ('r', '2', '1', '0'):
14555       format = GST_VIDEO_FORMAT_r210;
14556       break;
14557       /* Packed YUV 4:4:4 10 bit in 32 bits, complex
14558          case GST_MAKE_FOURCC ('v', '4', '1', '0'):
14559          format = GST_VIDEO_FORMAT_v410;
14560          break;
14561        */
14562       /* Packed YUV 4:4:4:4 8 bit in 32 bits
14563        * but different order than AYUV
14564        case GST_MAKE_FOURCC ('v', '4', '0', '8'):
14565        format = GST_VIDEO_FORMAT_v408;
14566        break;
14567        */
14568     case GST_MAKE_FOURCC ('m', 'p', 'e', 'g'):
14569     case GST_MAKE_FOURCC ('m', 'p', 'g', '1'):
14570       _codec ("MPEG-1 video");
14571       caps = gst_caps_new_simple ("video/mpeg", "mpegversion", G_TYPE_INT, 1,
14572           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
14573       break;
14574     case GST_MAKE_FOURCC ('h', 'd', 'v', '1'): /* HDV 720p30 */
14575     case GST_MAKE_FOURCC ('h', 'd', 'v', '2'): /* HDV 1080i60 */
14576     case GST_MAKE_FOURCC ('h', 'd', 'v', '3'): /* HDV 1080i50 */
14577     case GST_MAKE_FOURCC ('h', 'd', 'v', '4'): /* HDV 720p24 */
14578     case GST_MAKE_FOURCC ('h', 'd', 'v', '5'): /* HDV 720p25 */
14579     case GST_MAKE_FOURCC ('h', 'd', 'v', '6'): /* HDV 1080p24 */
14580     case GST_MAKE_FOURCC ('h', 'd', 'v', '7'): /* HDV 1080p25 */
14581     case GST_MAKE_FOURCC ('h', 'd', 'v', '8'): /* HDV 1080p30 */
14582     case GST_MAKE_FOURCC ('h', 'd', 'v', '9'): /* HDV 720p60 */
14583     case GST_MAKE_FOURCC ('h', 'd', 'v', 'a'): /* HDV 720p50 */
14584     case GST_MAKE_FOURCC ('m', 'x', '5', 'n'): /* MPEG2 IMX NTSC 525/60 50mb/s produced by FCP */
14585     case GST_MAKE_FOURCC ('m', 'x', '5', 'p'): /* MPEG2 IMX PAL 625/60 50mb/s produced by FCP */
14586     case GST_MAKE_FOURCC ('m', 'x', '4', 'n'): /* MPEG2 IMX NTSC 525/60 40mb/s produced by FCP */
14587     case GST_MAKE_FOURCC ('m', 'x', '4', 'p'): /* MPEG2 IMX PAL 625/60 40mb/s produced by FCP */
14588     case GST_MAKE_FOURCC ('m', 'x', '3', 'n'): /* MPEG2 IMX NTSC 525/60 30mb/s produced by FCP */
14589     case GST_MAKE_FOURCC ('m', 'x', '3', 'p'): /* MPEG2 IMX PAL 625/50 30mb/s produced by FCP */
14590     case GST_MAKE_FOURCC ('x', 'd', 'v', '1'): /* XDCAM HD 720p30 35Mb/s */
14591     case GST_MAKE_FOURCC ('x', 'd', 'v', '2'): /* XDCAM HD 1080i60 35Mb/s */
14592     case GST_MAKE_FOURCC ('x', 'd', 'v', '3'): /* XDCAM HD 1080i50 35Mb/s */
14593     case GST_MAKE_FOURCC ('x', 'd', 'v', '4'): /* XDCAM HD 720p24 35Mb/s */
14594     case GST_MAKE_FOURCC ('x', 'd', 'v', '5'): /* XDCAM HD 720p25 35Mb/s */
14595     case GST_MAKE_FOURCC ('x', 'd', 'v', '6'): /* XDCAM HD 1080p24 35Mb/s */
14596     case GST_MAKE_FOURCC ('x', 'd', 'v', '7'): /* XDCAM HD 1080p25 35Mb/s */
14597     case GST_MAKE_FOURCC ('x', 'd', 'v', '8'): /* XDCAM HD 1080p30 35Mb/s */
14598     case GST_MAKE_FOURCC ('x', 'd', 'v', '9'): /* XDCAM HD 720p60 35Mb/s */
14599     case GST_MAKE_FOURCC ('x', 'd', 'v', 'a'): /* XDCAM HD 720p50 35Mb/s */
14600     case GST_MAKE_FOURCC ('x', 'd', 'v', 'b'): /* XDCAM EX 1080i60 50Mb/s CBR */
14601     case GST_MAKE_FOURCC ('x', 'd', 'v', 'c'): /* XDCAM EX 1080i50 50Mb/s CBR */
14602     case GST_MAKE_FOURCC ('x', 'd', 'v', 'd'): /* XDCAM HD 1080p24 50Mb/s CBR */
14603     case GST_MAKE_FOURCC ('x', 'd', 'v', 'e'): /* XDCAM HD 1080p25 50Mb/s CBR */
14604     case GST_MAKE_FOURCC ('x', 'd', 'v', 'f'): /* XDCAM HD 1080p30 50Mb/s CBR */
14605     case GST_MAKE_FOURCC ('x', 'd', '5', '1'): /* XDCAM HD422 720p30 50Mb/s CBR */
14606     case GST_MAKE_FOURCC ('x', 'd', '5', '4'): /* XDCAM HD422 720p24 50Mb/s CBR */
14607     case GST_MAKE_FOURCC ('x', 'd', '5', '5'): /* XDCAM HD422 720p25 50Mb/s CBR */
14608     case GST_MAKE_FOURCC ('x', 'd', '5', '9'): /* XDCAM HD422 720p60 50Mb/s CBR */
14609     case GST_MAKE_FOURCC ('x', 'd', '5', 'a'): /* XDCAM HD422 720p50 50Mb/s CBR */
14610     case GST_MAKE_FOURCC ('x', 'd', '5', 'b'): /* XDCAM HD422 1080i50 50Mb/s CBR */
14611     case GST_MAKE_FOURCC ('x', 'd', '5', 'c'): /* XDCAM HD422 1080i50 50Mb/s CBR */
14612     case GST_MAKE_FOURCC ('x', 'd', '5', 'd'): /* XDCAM HD422 1080p24 50Mb/s CBR */
14613     case GST_MAKE_FOURCC ('x', 'd', '5', 'e'): /* XDCAM HD422 1080p25 50Mb/s CBR */
14614     case GST_MAKE_FOURCC ('x', 'd', '5', 'f'): /* XDCAM HD422 1080p30 50Mb/s CBR */
14615     case GST_MAKE_FOURCC ('x', 'd', 'h', 'd'): /* XDCAM HD 540p */
14616     case GST_MAKE_FOURCC ('x', 'd', 'h', '2'): /* XDCAM HD422 540p */
14617     case GST_MAKE_FOURCC ('A', 'V', 'm', 'p'): /* AVID IMX PAL */
14618     case GST_MAKE_FOURCC ('m', 'p', 'g', '2'): /* AVID IMX PAL */
14619     case GST_MAKE_FOURCC ('m', 'p', '2', 'v'): /* AVID IMX PAL */
14620     case GST_MAKE_FOURCC ('m', '2', 'v', '1'):
14621       _codec ("MPEG-2 video");
14622       caps = gst_caps_new_simple ("video/mpeg", "mpegversion", G_TYPE_INT, 2,
14623           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
14624       break;
14625     case GST_MAKE_FOURCC ('g', 'i', 'f', ' '):
14626       _codec ("GIF still images");
14627       caps = gst_caps_new_empty_simple ("image/gif");
14628       break;
14629     case FOURCC_h263:
14630     case GST_MAKE_FOURCC ('H', '2', '6', '3'):
14631     case FOURCC_s263:
14632     case GST_MAKE_FOURCC ('U', '2', '6', '3'):
14633       _codec ("H.263");
14634       /* ffmpeg uses the height/width props, don't know why */
14635       caps = gst_caps_new_simple ("video/x-h263",
14636           "variant", G_TYPE_STRING, "itu", NULL);
14637       break;
14638     case FOURCC_mp4v:
14639     case FOURCC_MP4V:
14640       _codec ("MPEG-4 video");
14641       caps = gst_caps_new_simple ("video/mpeg", "mpegversion", G_TYPE_INT, 4,
14642           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
14643       break;
14644     case GST_MAKE_FOURCC ('3', 'i', 'v', 'd'):
14645     case GST_MAKE_FOURCC ('3', 'I', 'V', 'D'):
14646       _codec ("Microsoft MPEG-4 4.3");  /* FIXME? */
14647       caps = gst_caps_new_simple ("video/x-msmpeg",
14648           "msmpegversion", G_TYPE_INT, 43, NULL);
14649       break;
14650     case GST_MAKE_FOURCC ('D', 'I', 'V', '3'):
14651       _codec ("DivX 3");
14652       caps = gst_caps_new_simple ("video/x-divx",
14653           "divxversion", G_TYPE_INT, 3, NULL);
14654       break;
14655     case GST_MAKE_FOURCC ('D', 'I', 'V', 'X'):
14656     case GST_MAKE_FOURCC ('d', 'i', 'v', 'x'):
14657       _codec ("DivX 4");
14658       caps = gst_caps_new_simple ("video/x-divx",
14659           "divxversion", G_TYPE_INT, 4, NULL);
14660       break;
14661     case GST_MAKE_FOURCC ('D', 'X', '5', '0'):
14662       _codec ("DivX 5");
14663       caps = gst_caps_new_simple ("video/x-divx",
14664           "divxversion", G_TYPE_INT, 5, NULL);
14665       break;
14666
14667     case GST_MAKE_FOURCC ('F', 'F', 'V', '1'):
14668       _codec ("FFV1");
14669       caps = gst_caps_new_simple ("video/x-ffv",
14670           "ffvversion", G_TYPE_INT, 1, NULL);
14671       break;
14672
14673     case GST_MAKE_FOURCC ('3', 'I', 'V', '1'):
14674     case GST_MAKE_FOURCC ('3', 'I', 'V', '2'):
14675     case FOURCC_XVID:
14676     case FOURCC_xvid:
14677     case FOURCC_FMP4:
14678     case FOURCC_fmp4:
14679     case GST_MAKE_FOURCC ('U', 'M', 'P', '4'):
14680       caps = gst_caps_new_simple ("video/mpeg", "mpegversion", G_TYPE_INT, 4,
14681           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
14682       _codec ("MPEG-4");
14683       break;
14684
14685     case GST_MAKE_FOURCC ('c', 'v', 'i', 'd'):
14686       _codec ("Cinepak");
14687       caps = gst_caps_new_empty_simple ("video/x-cinepak");
14688       break;
14689     case GST_MAKE_FOURCC ('q', 'd', 'r', 'w'):
14690       _codec ("Apple QuickDraw");
14691       caps = gst_caps_new_empty_simple ("video/x-qdrw");
14692       break;
14693     case GST_MAKE_FOURCC ('r', 'p', 'z', 'a'):
14694       _codec ("Apple video");
14695       caps = gst_caps_new_empty_simple ("video/x-apple-video");
14696       break;
14697     case FOURCC_H264:
14698     case FOURCC_avc1:
14699       _codec ("H.264 / AVC");
14700       caps = gst_caps_new_simple ("video/x-h264",
14701           "stream-format", G_TYPE_STRING, "avc",
14702           "alignment", G_TYPE_STRING, "au", NULL);
14703       break;
14704     case FOURCC_avc3:
14705       _codec ("H.264 / AVC");
14706       caps = gst_caps_new_simple ("video/x-h264",
14707           "stream-format", G_TYPE_STRING, "avc3",
14708           "alignment", G_TYPE_STRING, "au", NULL);
14709       break;
14710     case FOURCC_H265:
14711     case FOURCC_hvc1:
14712       _codec ("H.265 / HEVC");
14713       caps = gst_caps_new_simple ("video/x-h265",
14714           "stream-format", G_TYPE_STRING, "hvc1",
14715           "alignment", G_TYPE_STRING, "au", NULL);
14716       break;
14717     case FOURCC_hev1:
14718       _codec ("H.265 / HEVC");
14719       caps = gst_caps_new_simple ("video/x-h265",
14720           "stream-format", G_TYPE_STRING, "hev1",
14721           "alignment", G_TYPE_STRING, "au", NULL);
14722       break;
14723     case FOURCC_rle_:
14724       _codec ("Run-length encoding");
14725       caps = gst_caps_new_simple ("video/x-rle",
14726           "layout", G_TYPE_STRING, "quicktime", NULL);
14727       break;
14728     case FOURCC_WRLE:
14729       _codec ("Run-length encoding");
14730       caps = gst_caps_new_simple ("video/x-rle",
14731           "layout", G_TYPE_STRING, "microsoft", NULL);
14732       break;
14733     case GST_MAKE_FOURCC ('I', 'V', '3', '2'):
14734     case GST_MAKE_FOURCC ('i', 'v', '3', '2'):
14735       _codec ("Indeo Video 3");
14736       caps = gst_caps_new_simple ("video/x-indeo",
14737           "indeoversion", G_TYPE_INT, 3, NULL);
14738       break;
14739     case GST_MAKE_FOURCC ('I', 'V', '4', '1'):
14740     case GST_MAKE_FOURCC ('i', 'v', '4', '1'):
14741       _codec ("Intel Video 4");
14742       caps = gst_caps_new_simple ("video/x-indeo",
14743           "indeoversion", G_TYPE_INT, 4, NULL);
14744       break;
14745     case FOURCC_dvcp:
14746     case FOURCC_dvc_:
14747     case GST_MAKE_FOURCC ('d', 'v', 's', 'd'):
14748     case GST_MAKE_FOURCC ('D', 'V', 'S', 'D'):
14749     case GST_MAKE_FOURCC ('d', 'v', 'c', 's'):
14750     case GST_MAKE_FOURCC ('D', 'V', 'C', 'S'):
14751     case GST_MAKE_FOURCC ('d', 'v', '2', '5'):
14752     case GST_MAKE_FOURCC ('d', 'v', 'p', 'p'):
14753       _codec ("DV Video");
14754       caps = gst_caps_new_simple ("video/x-dv", "dvversion", G_TYPE_INT, 25,
14755           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
14756       break;
14757     case FOURCC_dv5n:          /* DVCPRO50 NTSC */
14758     case FOURCC_dv5p:          /* DVCPRO50 PAL */
14759       _codec ("DVCPro50 Video");
14760       caps = gst_caps_new_simple ("video/x-dv", "dvversion", G_TYPE_INT, 50,
14761           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
14762       break;
14763     case GST_MAKE_FOURCC ('d', 'v', 'h', '5'): /* DVCPRO HD 50i produced by FCP */
14764     case GST_MAKE_FOURCC ('d', 'v', 'h', '6'): /* DVCPRO HD 60i produced by FCP */
14765       _codec ("DVCProHD Video");
14766       caps = gst_caps_new_simple ("video/x-dv", "dvversion", G_TYPE_INT, 100,
14767           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
14768       break;
14769     case GST_MAKE_FOURCC ('s', 'm', 'c', ' '):
14770       _codec ("Apple Graphics (SMC)");
14771       caps = gst_caps_new_empty_simple ("video/x-smc");
14772       break;
14773     case GST_MAKE_FOURCC ('V', 'P', '3', '1'):
14774       _codec ("VP3");
14775       caps = gst_caps_new_empty_simple ("video/x-vp3");
14776       break;
14777     case GST_MAKE_FOURCC ('V', 'P', '6', 'F'):
14778       _codec ("VP6 Flash");
14779       caps = gst_caps_new_empty_simple ("video/x-vp6-flash");
14780       break;
14781     case FOURCC_XiTh:
14782       _codec ("Theora");
14783       caps = gst_caps_new_empty_simple ("video/x-theora");
14784       /* theora uses one byte of padding in the data stream because it does not
14785        * allow 0 sized packets while theora does */
14786       entry->padding = 1;
14787       break;
14788     case FOURCC_drac:
14789       _codec ("Dirac");
14790       caps = gst_caps_new_empty_simple ("video/x-dirac");
14791       break;
14792     case GST_MAKE_FOURCC ('t', 'i', 'f', 'f'):
14793       _codec ("TIFF still images");
14794       caps = gst_caps_new_empty_simple ("image/tiff");
14795       break;
14796     case GST_MAKE_FOURCC ('i', 'c', 'o', 'd'):
14797       _codec ("Apple Intermediate Codec");
14798       caps = gst_caps_from_string ("video/x-apple-intermediate-codec");
14799       break;
14800     case GST_MAKE_FOURCC ('A', 'V', 'd', 'n'):
14801       _codec ("AVID DNxHD");
14802       caps = gst_caps_from_string ("video/x-dnxhd");
14803       break;
14804     case FOURCC_VP80:
14805     case FOURCC_vp08:
14806       _codec ("On2 VP8");
14807       caps = gst_caps_from_string ("video/x-vp8");
14808       break;
14809     case FOURCC_vp09:
14810       _codec ("Google VP9");
14811       caps = gst_caps_from_string ("video/x-vp9");
14812       break;
14813     case FOURCC_apcs:
14814       _codec ("Apple ProRes LT");
14815       caps =
14816           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING, "lt",
14817           NULL);
14818       break;
14819     case FOURCC_apch:
14820       _codec ("Apple ProRes HQ");
14821       caps =
14822           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING, "hq",
14823           NULL);
14824       break;
14825     case FOURCC_apcn:
14826       _codec ("Apple ProRes");
14827       caps =
14828           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING,
14829           "standard", NULL);
14830       break;
14831     case FOURCC_apco:
14832       _codec ("Apple ProRes Proxy");
14833       caps =
14834           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING,
14835           "proxy", NULL);
14836       break;
14837     case FOURCC_ap4h:
14838       _codec ("Apple ProRes 4444");
14839       caps =
14840           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING,
14841           "4444", NULL);
14842       break;
14843     case FOURCC_ap4x:
14844       _codec ("Apple ProRes 4444 XQ");
14845       caps =
14846           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING,
14847           "4444xq", NULL);
14848       break;
14849     case FOURCC_cfhd:
14850       _codec ("GoPro CineForm");
14851       caps = gst_caps_from_string ("video/x-cineform");
14852       break;
14853     case FOURCC_vc_1:
14854     case FOURCC_ovc1:
14855       _codec ("VC-1");
14856       caps = gst_caps_new_simple ("video/x-wmv",
14857           "wmvversion", G_TYPE_INT, 3, "format", G_TYPE_STRING, "WVC1", NULL);
14858       break;
14859     case FOURCC_av01:
14860       _codec ("AV1");
14861       caps = gst_caps_new_empty_simple ("video/x-av1");
14862       break;
14863     case GST_MAKE_FOURCC ('k', 'p', 'c', 'd'):
14864     default:
14865     {
14866       caps = _get_unknown_codec_name ("video", fourcc);
14867       break;
14868     }
14869   }
14870
14871   if (format != GST_VIDEO_FORMAT_UNKNOWN) {
14872     GstVideoInfo info;
14873
14874     gst_video_info_init (&info);
14875     gst_video_info_set_format (&info, format, entry->width, entry->height);
14876
14877     caps = gst_video_info_to_caps (&info);
14878     *codec_name = gst_pb_utils_get_codec_description (caps);
14879
14880     /* enable clipping for raw video streams */
14881     stream->need_clip = TRUE;
14882     stream->alignment = 32;
14883   }
14884
14885   return caps;
14886 }
14887
14888 static guint
14889 round_up_pow2 (guint n)
14890 {
14891   n = n - 1;
14892   n = n | (n >> 1);
14893   n = n | (n >> 2);
14894   n = n | (n >> 4);
14895   n = n | (n >> 8);
14896   n = n | (n >> 16);
14897   return n + 1;
14898 }
14899
14900 static GstCaps *
14901 qtdemux_audio_caps (GstQTDemux * qtdemux, QtDemuxStream * stream,
14902     QtDemuxStreamStsdEntry * entry, guint32 fourcc, const guint8 * data,
14903     int len, gchar ** codec_name)
14904 {
14905   GstCaps *caps;
14906   const GstStructure *s;
14907   const gchar *name;
14908   gint endian = 0;
14909   GstAudioFormat format = 0;
14910   gint depth;
14911
14912   GST_DEBUG_OBJECT (qtdemux, "resolve fourcc 0x%08x", GUINT32_TO_BE (fourcc));
14913
14914   depth = entry->bytes_per_packet * 8;
14915
14916   switch (fourcc) {
14917     case GST_MAKE_FOURCC ('N', 'O', 'N', 'E'):
14918     case FOURCC_raw_:
14919       /* 8-bit audio is unsigned */
14920       if (depth == 8)
14921         format = GST_AUDIO_FORMAT_U8;
14922       /* otherwise it's signed and big-endian just like 'twos' */
14923     case FOURCC_twos:
14924       endian = G_BIG_ENDIAN;
14925       /* fall-through */
14926     case FOURCC_sowt:
14927     {
14928       gchar *str;
14929
14930       if (!endian)
14931         endian = G_LITTLE_ENDIAN;
14932
14933       if (!format)
14934         format = gst_audio_format_build_integer (TRUE, endian, depth, depth);
14935
14936       str = g_strdup_printf ("Raw %d-bit PCM audio", depth);
14937       _codec (str);
14938       g_free (str);
14939
14940       caps = gst_caps_new_simple ("audio/x-raw",
14941           "format", G_TYPE_STRING, gst_audio_format_to_string (format),
14942           "layout", G_TYPE_STRING, "interleaved", NULL);
14943       stream->alignment = GST_ROUND_UP_8 (depth);
14944       stream->alignment = round_up_pow2 (stream->alignment);
14945       break;
14946     }
14947     case GST_MAKE_FOURCC ('f', 'l', '6', '4'):
14948       _codec ("Raw 64-bit floating-point audio");
14949       caps = gst_caps_new_simple ("audio/x-raw",
14950           "format", G_TYPE_STRING, "F64BE",
14951           "layout", G_TYPE_STRING, "interleaved", NULL);
14952       stream->alignment = 8;
14953       break;
14954     case GST_MAKE_FOURCC ('f', 'l', '3', '2'):
14955       _codec ("Raw 32-bit floating-point audio");
14956       caps = gst_caps_new_simple ("audio/x-raw",
14957           "format", G_TYPE_STRING, "F32BE",
14958           "layout", G_TYPE_STRING, "interleaved", NULL);
14959       stream->alignment = 4;
14960       break;
14961     case FOURCC_in24:
14962       _codec ("Raw 24-bit PCM audio");
14963       /* we assume BIG ENDIAN, an enda box will tell us to change this to little
14964        * endian later */
14965       caps = gst_caps_new_simple ("audio/x-raw",
14966           "format", G_TYPE_STRING, "S24BE",
14967           "layout", G_TYPE_STRING, "interleaved", NULL);
14968       stream->alignment = 4;
14969       break;
14970     case GST_MAKE_FOURCC ('i', 'n', '3', '2'):
14971       _codec ("Raw 32-bit PCM audio");
14972       caps = gst_caps_new_simple ("audio/x-raw",
14973           "format", G_TYPE_STRING, "S32BE",
14974           "layout", G_TYPE_STRING, "interleaved", NULL);
14975       stream->alignment = 4;
14976       break;
14977     case GST_MAKE_FOURCC ('s', '1', '6', 'l'):
14978       _codec ("Raw 16-bit PCM audio");
14979       caps = gst_caps_new_simple ("audio/x-raw",
14980           "format", G_TYPE_STRING, "S16LE",
14981           "layout", G_TYPE_STRING, "interleaved", NULL);
14982       stream->alignment = 2;
14983       break;
14984     case FOURCC_ulaw:
14985       _codec ("Mu-law audio");
14986       caps = gst_caps_new_empty_simple ("audio/x-mulaw");
14987       break;
14988     case FOURCC_alaw:
14989       _codec ("A-law audio");
14990       caps = gst_caps_new_empty_simple ("audio/x-alaw");
14991       break;
14992     case 0x0200736d:
14993     case 0x6d730002:
14994       _codec ("Microsoft ADPCM");
14995       /* Microsoft ADPCM-ACM code 2 */
14996       caps = gst_caps_new_simple ("audio/x-adpcm",
14997           "layout", G_TYPE_STRING, "microsoft", NULL);
14998       break;
14999     case 0x1100736d:
15000     case 0x6d730011:
15001       _codec ("DVI/IMA ADPCM");
15002       caps = gst_caps_new_simple ("audio/x-adpcm",
15003           "layout", G_TYPE_STRING, "dvi", NULL);
15004       break;
15005     case 0x1700736d:
15006     case 0x6d730017:
15007       _codec ("DVI/Intel IMA ADPCM");
15008       /* FIXME DVI/Intel IMA ADPCM/ACM code 17 */
15009       caps = gst_caps_new_simple ("audio/x-adpcm",
15010           "layout", G_TYPE_STRING, "quicktime", NULL);
15011       break;
15012     case 0x5500736d:
15013     case 0x6d730055:
15014       /* MPEG layer 3, CBR only (pre QT4.1) */
15015     case FOURCC__mp3:
15016       _codec ("MPEG-1 layer 3");
15017       /* MPEG layer 3, CBR & VBR (QT4.1 and later) */
15018       caps = gst_caps_new_simple ("audio/mpeg", "layer", G_TYPE_INT, 3,
15019           "mpegversion", G_TYPE_INT, 1, NULL);
15020       break;
15021     case GST_MAKE_FOURCC ('.', 'm', 'p', '2'):
15022       _codec ("MPEG-1 layer 2");
15023       /* MPEG layer 2 */
15024       caps = gst_caps_new_simple ("audio/mpeg", "layer", G_TYPE_INT, 2,
15025           "mpegversion", G_TYPE_INT, 1, NULL);
15026       break;
15027     case 0x20736d:
15028     case GST_MAKE_FOURCC ('e', 'c', '-', '3'):
15029       _codec ("EAC-3 audio");
15030       caps = gst_caps_new_simple ("audio/x-eac3",
15031           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
15032       entry->sampled = TRUE;
15033       break;
15034     case GST_MAKE_FOURCC ('s', 'a', 'c', '3'): // Nero Recode
15035     case FOURCC_ac_3:
15036       _codec ("AC-3 audio");
15037       caps = gst_caps_new_simple ("audio/x-ac3",
15038           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
15039       entry->sampled = TRUE;
15040       break;
15041     case GST_MAKE_FOURCC ('d', 't', 's', 'c'):
15042     case GST_MAKE_FOURCC ('D', 'T', 'S', ' '):
15043       _codec ("DTS audio");
15044       caps = gst_caps_new_simple ("audio/x-dts",
15045           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
15046       entry->sampled = TRUE;
15047       break;
15048     case GST_MAKE_FOURCC ('d', 't', 's', 'h'): // DTS-HD
15049     case GST_MAKE_FOURCC ('d', 't', 's', 'l'): // DTS-HD Lossless
15050       _codec ("DTS-HD audio");
15051       caps = gst_caps_new_simple ("audio/x-dts",
15052           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
15053       entry->sampled = TRUE;
15054       break;
15055     case FOURCC_MAC3:
15056       _codec ("MACE-3");
15057       caps = gst_caps_new_simple ("audio/x-mace",
15058           "maceversion", G_TYPE_INT, 3, NULL);
15059       break;
15060     case FOURCC_MAC6:
15061       _codec ("MACE-6");
15062       caps = gst_caps_new_simple ("audio/x-mace",
15063           "maceversion", G_TYPE_INT, 6, NULL);
15064       break;
15065     case GST_MAKE_FOURCC ('O', 'g', 'g', 'V'):
15066       /* ogg/vorbis */
15067       caps = gst_caps_new_empty_simple ("application/ogg");
15068       break;
15069     case GST_MAKE_FOURCC ('d', 'v', 'c', 'a'):
15070       _codec ("DV audio");
15071       caps = gst_caps_new_empty_simple ("audio/x-dv");
15072       break;
15073     case FOURCC_mp4a:
15074       _codec ("MPEG-4 AAC audio");
15075       caps = gst_caps_new_simple ("audio/mpeg",
15076           "mpegversion", G_TYPE_INT, 4, "framed", G_TYPE_BOOLEAN, TRUE,
15077           "stream-format", G_TYPE_STRING, "raw", NULL);
15078       break;
15079     case GST_MAKE_FOURCC ('Q', 'D', 'M', 'C'):
15080       _codec ("QDesign Music");
15081       caps = gst_caps_new_empty_simple ("audio/x-qdm");
15082       break;
15083     case FOURCC_QDM2:
15084       _codec ("QDesign Music v.2");
15085       /* FIXME: QDesign music version 2 (no constant) */
15086       if (FALSE && data) {
15087         caps = gst_caps_new_simple ("audio/x-qdm2",
15088             "framesize", G_TYPE_INT, QT_UINT32 (data + 52),
15089             "bitrate", G_TYPE_INT, QT_UINT32 (data + 40),
15090             "blocksize", G_TYPE_INT, QT_UINT32 (data + 44), NULL);
15091       } else {
15092         caps = gst_caps_new_empty_simple ("audio/x-qdm2");
15093       }
15094       break;
15095     case FOURCC_agsm:
15096       _codec ("GSM audio");
15097       caps = gst_caps_new_empty_simple ("audio/x-gsm");
15098       break;
15099     case FOURCC_samr:
15100       _codec ("AMR audio");
15101       caps = gst_caps_new_empty_simple ("audio/AMR");
15102       break;
15103     case FOURCC_sawb:
15104       _codec ("AMR-WB audio");
15105       caps = gst_caps_new_empty_simple ("audio/AMR-WB");
15106       break;
15107     case FOURCC_ima4:
15108       _codec ("Quicktime IMA ADPCM");
15109       caps = gst_caps_new_simple ("audio/x-adpcm",
15110           "layout", G_TYPE_STRING, "quicktime", NULL);
15111       break;
15112     case FOURCC_alac:
15113       _codec ("Apple lossless audio");
15114       caps = gst_caps_new_empty_simple ("audio/x-alac");
15115       break;
15116     case FOURCC_fLaC:
15117       _codec ("Free Lossless Audio Codec");
15118       caps = gst_caps_new_simple ("audio/x-flac",
15119           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
15120       break;
15121     case GST_MAKE_FOURCC ('Q', 'c', 'l', 'p'):
15122       _codec ("QualComm PureVoice");
15123       caps = gst_caps_from_string ("audio/qcelp");
15124       break;
15125     case FOURCC_wma_:
15126     case FOURCC_owma:
15127       _codec ("WMA");
15128       caps = gst_caps_new_empty_simple ("audio/x-wma");
15129       break;
15130     case FOURCC_opus:
15131       _codec ("Opus");
15132       caps = gst_caps_new_empty_simple ("audio/x-opus");
15133       break;
15134     case FOURCC_lpcm:
15135     {
15136       guint32 flags = 0;
15137       guint32 depth = 0;
15138       guint32 width = 0;
15139       GstAudioFormat format;
15140       enum
15141       {
15142         FLAG_IS_FLOAT = 0x1,
15143         FLAG_IS_BIG_ENDIAN = 0x2,
15144         FLAG_IS_SIGNED = 0x4,
15145         FLAG_IS_PACKED = 0x8,
15146         FLAG_IS_ALIGNED_HIGH = 0x10,
15147         FLAG_IS_NON_INTERLEAVED = 0x20
15148       };
15149       _codec ("Raw LPCM audio");
15150
15151       if (data && len >= 36) {
15152         depth = QT_UINT32 (data + 24);
15153         flags = QT_UINT32 (data + 28);
15154         width = QT_UINT32 (data + 32) * 8 / entry->n_channels;
15155       }
15156       if ((flags & FLAG_IS_FLOAT) == 0) {
15157         if (depth == 0)
15158           depth = 16;
15159         if (width == 0)
15160           width = 16;
15161         if ((flags & FLAG_IS_ALIGNED_HIGH))
15162           depth = width;
15163
15164         format = gst_audio_format_build_integer ((flags & FLAG_IS_SIGNED) ?
15165             TRUE : FALSE, (flags & FLAG_IS_BIG_ENDIAN) ?
15166             G_BIG_ENDIAN : G_LITTLE_ENDIAN, width, depth);
15167         caps = gst_caps_new_simple ("audio/x-raw",
15168             "format", G_TYPE_STRING,
15169             format !=
15170             GST_AUDIO_FORMAT_UNKNOWN ? gst_audio_format_to_string (format) :
15171             "UNKNOWN", "layout", G_TYPE_STRING,
15172             (flags & FLAG_IS_NON_INTERLEAVED) ? "non-interleaved" :
15173             "interleaved", NULL);
15174         stream->alignment = GST_ROUND_UP_8 (depth);
15175         stream->alignment = round_up_pow2 (stream->alignment);
15176       } else {
15177         if (width == 0)
15178           width = 32;
15179         if (width == 64) {
15180           if (flags & FLAG_IS_BIG_ENDIAN)
15181             format = GST_AUDIO_FORMAT_F64BE;
15182           else
15183             format = GST_AUDIO_FORMAT_F64LE;
15184         } else {
15185           if (flags & FLAG_IS_BIG_ENDIAN)
15186             format = GST_AUDIO_FORMAT_F32BE;
15187           else
15188             format = GST_AUDIO_FORMAT_F32LE;
15189         }
15190         caps = gst_caps_new_simple ("audio/x-raw",
15191             "format", G_TYPE_STRING, gst_audio_format_to_string (format),
15192             "layout", G_TYPE_STRING, (flags & FLAG_IS_NON_INTERLEAVED) ?
15193             "non-interleaved" : "interleaved", NULL);
15194         stream->alignment = width / 8;
15195       }
15196       break;
15197     }
15198     case GST_MAKE_FOURCC ('q', 't', 'v', 'r'):
15199       /* ? */
15200     default:
15201     {
15202       caps = _get_unknown_codec_name ("audio", fourcc);
15203       break;
15204     }
15205   }
15206
15207   if (caps) {
15208     GstCaps *templ_caps =
15209         gst_static_pad_template_get_caps (&gst_qtdemux_audiosrc_template);
15210     GstCaps *intersection = gst_caps_intersect (caps, templ_caps);
15211     gst_caps_unref (caps);
15212     gst_caps_unref (templ_caps);
15213     caps = intersection;
15214   }
15215
15216   /* enable clipping for raw audio streams */
15217   s = gst_caps_get_structure (caps, 0);
15218   name = gst_structure_get_name (s);
15219   if (g_str_has_prefix (name, "audio/x-raw")) {
15220     stream->need_clip = TRUE;
15221     stream->max_buffer_size = 4096 * entry->bytes_per_frame;
15222     GST_DEBUG ("setting max buffer size to %d", stream->max_buffer_size);
15223   }
15224   return caps;
15225 }
15226
15227 static GstCaps *
15228 qtdemux_sub_caps (GstQTDemux * qtdemux, QtDemuxStream * stream,
15229     QtDemuxStreamStsdEntry * entry, guint32 fourcc,
15230     const guint8 * stsd_entry_data, gchar ** codec_name)
15231 {
15232   GstCaps *caps;
15233
15234   GST_DEBUG_OBJECT (qtdemux, "resolve fourcc 0x%08x", GUINT32_TO_BE (fourcc));
15235
15236   switch (fourcc) {
15237     case FOURCC_mp4s:
15238       _codec ("DVD subtitle");
15239       caps = gst_caps_new_empty_simple ("subpicture/x-dvd");
15240       stream->need_process = TRUE;
15241       break;
15242     case FOURCC_text:
15243       _codec ("Quicktime timed text");
15244       goto text;
15245     case FOURCC_tx3g:
15246       _codec ("3GPP timed text");
15247     text:
15248       caps = gst_caps_new_simple ("text/x-raw", "format", G_TYPE_STRING,
15249           "utf8", NULL);
15250       /* actual text piece needs to be extracted */
15251       stream->need_process = TRUE;
15252       break;
15253     case FOURCC_stpp:
15254       _codec ("XML subtitles");
15255       caps = gst_caps_new_empty_simple ("application/ttml+xml");
15256       break;
15257     case FOURCC_c608:
15258       _codec ("CEA 608 Closed Caption");
15259       caps =
15260           gst_caps_new_simple ("closedcaption/x-cea-608", "format",
15261           G_TYPE_STRING, "cc_data", NULL);
15262       stream->need_process = TRUE;
15263       break;
15264     case FOURCC_c708:
15265       _codec ("CEA 708 Closed Caption");
15266       caps =
15267           gst_caps_new_simple ("closedcaption/x-cea-708", "format",
15268           G_TYPE_STRING, "cdp", NULL);
15269       stream->need_process = TRUE;
15270       break;
15271
15272     default:
15273     {
15274       caps = _get_unknown_codec_name ("text", fourcc);
15275       break;
15276     }
15277   }
15278   return caps;
15279 }
15280
15281 static GstCaps *
15282 qtdemux_generic_caps (GstQTDemux * qtdemux, QtDemuxStream * stream,
15283     QtDemuxStreamStsdEntry * entry, guint32 fourcc,
15284     const guint8 * stsd_entry_data, gchar ** codec_name)
15285 {
15286   GstCaps *caps;
15287
15288   switch (fourcc) {
15289     case FOURCC_m1v:
15290       _codec ("MPEG 1 video");
15291       caps = gst_caps_new_simple ("video/mpeg", "mpegversion", G_TYPE_INT, 1,
15292           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
15293       break;
15294     default:
15295       caps = NULL;
15296       break;
15297   }
15298   return caps;
15299 }
15300
15301 static void
15302 gst_qtdemux_append_protection_system_id (GstQTDemux * qtdemux,
15303     const gchar * system_id)
15304 {
15305   gint i;
15306
15307   if (!qtdemux->protection_system_ids)
15308     qtdemux->protection_system_ids =
15309         g_ptr_array_new_with_free_func ((GDestroyNotify) g_free);
15310   /* Check whether we already have an entry for this system ID. */
15311   for (i = 0; i < qtdemux->protection_system_ids->len; ++i) {
15312     const gchar *id = g_ptr_array_index (qtdemux->protection_system_ids, i);
15313     if (g_ascii_strcasecmp (system_id, id) == 0) {
15314       return;
15315     }
15316   }
15317   GST_DEBUG_OBJECT (qtdemux, "Adding cenc protection system ID %s", system_id);
15318   g_ptr_array_add (qtdemux->protection_system_ids, g_ascii_strdown (system_id,
15319           -1));
15320 }