5476d0e24a18e61a49dc3f65764569a82a7dc99d
[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   /* buffer needs potentially be split, e.g. CEA608 subtitles */
353   gboolean need_split;
354
355   /* current position */
356   guint32 segment_index;
357   guint32 sample_index;
358   GstClockTime time_position;   /* in gst time */
359   guint64 accumulated_base;
360
361   /* the Gst segment we are processing out, used for clipping */
362   GstSegment segment;
363
364   /* quicktime segments */
365   guint32 n_segments;
366   QtDemuxSegment *segments;
367   gboolean dummy_segment;
368   guint32 from_sample;
369   guint32 to_sample;
370
371   gboolean sent_eos;
372   GstTagList *stream_tags;
373   gboolean send_global_tags;
374
375   GstEvent *pending_event;
376
377   GstByteReader stco;
378   GstByteReader stsz;
379   GstByteReader stsc;
380   GstByteReader stts;
381   GstByteReader stss;
382   GstByteReader stps;
383   GstByteReader ctts;
384
385   gboolean chunks_are_samples;  /* TRUE means treat chunks as samples */
386   gint64 stbl_index;
387   /* stco */
388   guint co_size;
389   GstByteReader co_chunk;
390   guint32 first_chunk;
391   guint32 current_chunk;
392   guint32 last_chunk;
393   guint32 samples_per_chunk;
394   guint32 stsd_sample_description_id;
395   guint32 stco_sample_index;
396   /* stsz */
397   guint32 sample_size;          /* 0 means variable sizes are stored in stsz */
398   /* stsc */
399   guint32 stsc_index;
400   guint32 n_samples_per_chunk;
401   guint32 stsc_chunk_index;
402   guint32 stsc_sample_index;
403   guint64 chunk_offset;
404   /* stts */
405   guint32 stts_index;
406   guint32 stts_samples;
407   guint32 n_sample_times;
408   guint32 stts_sample_index;
409   guint64 stts_time;
410   guint32 stts_duration;
411   /* stss */
412   gboolean stss_present;
413   guint32 n_sample_syncs;
414   guint32 stss_index;
415   /* stps */
416   gboolean stps_present;
417   guint32 n_sample_partial_syncs;
418   guint32 stps_index;
419   QtDemuxRandomAccessEntry *ra_entries;
420   guint n_ra_entries;
421
422   const QtDemuxRandomAccessEntry *pending_seek;
423
424   /* ctts */
425   gboolean ctts_present;
426   guint32 n_composition_times;
427   guint32 ctts_index;
428   guint32 ctts_sample_index;
429   guint32 ctts_count;
430   gint32 ctts_soffset;
431
432   /* cslg */
433   guint32 cslg_shift;
434
435   /* fragmented */
436   gboolean parsed_trex;
437   guint32 def_sample_description_index; /* index is 1-based */
438   guint32 def_sample_duration;
439   guint32 def_sample_size;
440   guint32 def_sample_flags;
441
442   gboolean disabled;
443
444   /* stereoscopic video streams */
445   GstVideoMultiviewMode multiview_mode;
446   GstVideoMultiviewFlags multiview_flags;
447
448   /* protected streams */
449   gboolean protected;
450   guint32 protection_scheme_type;
451   guint32 protection_scheme_version;
452   gpointer protection_scheme_info;      /* specific to the protection scheme */
453   GQueue protection_scheme_event_queue;
454
455   gint ref_count;               /* atomic */
456 };
457
458 /* Contains properties and cryptographic info for a set of samples from a
459  * track protected using Common Encryption (cenc) */
460 struct _QtDemuxCencSampleSetInfo
461 {
462   GstStructure *default_properties;
463
464   /* @crypto_info holds one GstStructure per sample */
465   GPtrArray *crypto_info;
466 };
467
468 static const gchar *
469 qt_demux_state_string (enum QtDemuxState state)
470 {
471   switch (state) {
472     case QTDEMUX_STATE_INITIAL:
473       return "<INITIAL>";
474     case QTDEMUX_STATE_HEADER:
475       return "<HEADER>";
476     case QTDEMUX_STATE_MOVIE:
477       return "<MOVIE>";
478     case QTDEMUX_STATE_BUFFER_MDAT:
479       return "<BUFFER_MDAT>";
480     default:
481       return "<UNKNOWN>";
482   }
483 }
484
485 static GNode *qtdemux_tree_get_child_by_type (GNode * node, guint32 fourcc);
486 static GNode *qtdemux_tree_get_child_by_type_full (GNode * node,
487     guint32 fourcc, GstByteReader * parser);
488 static GNode *qtdemux_tree_get_sibling_by_type (GNode * node, guint32 fourcc);
489 static GNode *qtdemux_tree_get_sibling_by_type_full (GNode * node,
490     guint32 fourcc, GstByteReader * parser);
491
492 static GstFlowReturn qtdemux_add_fragmented_samples (GstQTDemux * qtdemux);
493
494 static void gst_qtdemux_check_send_pending_segment (GstQTDemux * demux);
495
496 static GstStaticPadTemplate gst_qtdemux_sink_template =
497     GST_STATIC_PAD_TEMPLATE ("sink",
498     GST_PAD_SINK,
499     GST_PAD_ALWAYS,
500     GST_STATIC_CAPS ("video/quicktime; video/mj2; audio/x-m4a; "
501         "application/x-3gp")
502     );
503
504 static GstStaticPadTemplate gst_qtdemux_videosrc_template =
505 GST_STATIC_PAD_TEMPLATE ("video_%u",
506     GST_PAD_SRC,
507     GST_PAD_SOMETIMES,
508     GST_STATIC_CAPS_ANY);
509
510 static GstStaticPadTemplate gst_qtdemux_audiosrc_template =
511 GST_STATIC_PAD_TEMPLATE ("audio_%u",
512     GST_PAD_SRC,
513     GST_PAD_SOMETIMES,
514     GST_STATIC_CAPS_ANY);
515
516 static GstStaticPadTemplate gst_qtdemux_subsrc_template =
517 GST_STATIC_PAD_TEMPLATE ("subtitle_%u",
518     GST_PAD_SRC,
519     GST_PAD_SOMETIMES,
520     GST_STATIC_CAPS_ANY);
521
522 #define gst_qtdemux_parent_class parent_class
523 G_DEFINE_TYPE (GstQTDemux, gst_qtdemux, GST_TYPE_ELEMENT);
524
525 static void gst_qtdemux_dispose (GObject * object);
526
527 static guint32
528 gst_qtdemux_find_index_linear (GstQTDemux * qtdemux, QtDemuxStream * str,
529     GstClockTime media_time);
530 static guint32
531 gst_qtdemux_find_index_for_given_media_offset_linear (GstQTDemux * qtdemux,
532     QtDemuxStream * str, gint64 media_offset);
533
534 #if 0
535 static void gst_qtdemux_set_index (GstElement * element, GstIndex * index);
536 static GstIndex *gst_qtdemux_get_index (GstElement * element);
537 #endif
538 static GstStateChangeReturn gst_qtdemux_change_state (GstElement * element,
539     GstStateChange transition);
540 static void gst_qtdemux_set_context (GstElement * element,
541     GstContext * context);
542 static gboolean qtdemux_sink_activate (GstPad * sinkpad, GstObject * parent);
543 static gboolean qtdemux_sink_activate_mode (GstPad * sinkpad,
544     GstObject * parent, GstPadMode mode, gboolean active);
545
546 static void gst_qtdemux_loop (GstPad * pad);
547 static GstFlowReturn gst_qtdemux_chain (GstPad * sinkpad, GstObject * parent,
548     GstBuffer * inbuf);
549 static gboolean gst_qtdemux_handle_sink_event (GstPad * pad, GstObject * parent,
550     GstEvent * event);
551 static gboolean gst_qtdemux_handle_sink_query (GstPad * pad, GstObject * parent,
552     GstQuery * query);
553 static gboolean gst_qtdemux_setcaps (GstQTDemux * qtdemux, GstCaps * caps);
554 static gboolean gst_qtdemux_configure_stream (GstQTDemux * qtdemux,
555     QtDemuxStream * stream);
556 static void gst_qtdemux_stream_check_and_change_stsd_index (GstQTDemux * demux,
557     QtDemuxStream * stream);
558 static GstFlowReturn gst_qtdemux_process_adapter (GstQTDemux * demux,
559     gboolean force);
560
561 static void gst_qtdemux_check_seekability (GstQTDemux * demux);
562
563 static gboolean qtdemux_parse_moov (GstQTDemux * qtdemux,
564     const guint8 * buffer, guint length);
565 static gboolean qtdemux_parse_node (GstQTDemux * qtdemux, GNode * node,
566     const guint8 * buffer, guint length);
567 static gboolean qtdemux_parse_tree (GstQTDemux * qtdemux);
568 static void qtdemux_parse_udta (GstQTDemux * qtdemux, GstTagList * taglist,
569     GNode * udta);
570
571 static void gst_qtdemux_handle_esds (GstQTDemux * qtdemux,
572     QtDemuxStream * stream, QtDemuxStreamStsdEntry * entry, GNode * esds,
573     GstTagList * list);
574 static GstCaps *qtdemux_video_caps (GstQTDemux * qtdemux,
575     QtDemuxStream * stream, QtDemuxStreamStsdEntry * entry, guint32 fourcc,
576     const guint8 * stsd_entry_data, gchar ** codec_name);
577 static GstCaps *qtdemux_audio_caps (GstQTDemux * qtdemux,
578     QtDemuxStream * stream, QtDemuxStreamStsdEntry * entry, guint32 fourcc,
579     const guint8 * data, int len, gchar ** codec_name);
580 static GstCaps *qtdemux_sub_caps (GstQTDemux * qtdemux, QtDemuxStream * stream,
581     QtDemuxStreamStsdEntry * entry, guint32 fourcc, const guint8 * data,
582     gchar ** codec_name);
583 static GstCaps *qtdemux_generic_caps (GstQTDemux * qtdemux,
584     QtDemuxStream * stream, QtDemuxStreamStsdEntry * entry, guint32 fourcc,
585     const guint8 * stsd_entry_data, gchar ** codec_name);
586
587 static gboolean qtdemux_parse_samples (GstQTDemux * qtdemux,
588     QtDemuxStream * stream, guint32 n);
589 static GstFlowReturn qtdemux_expose_streams (GstQTDemux * qtdemux);
590 static QtDemuxStream *gst_qtdemux_stream_ref (QtDemuxStream * stream);
591 static void gst_qtdemux_stream_unref (QtDemuxStream * stream);
592 static void gst_qtdemux_stream_clear (QtDemuxStream * stream);
593 static GstFlowReturn qtdemux_prepare_streams (GstQTDemux * qtdemux);
594 static void qtdemux_do_allocation (QtDemuxStream * stream,
595     GstQTDemux * qtdemux);
596 static gboolean gst_qtdemux_activate_segment (GstQTDemux * qtdemux,
597     QtDemuxStream * stream, guint32 seg_idx, GstClockTime offset);
598 static gboolean gst_qtdemux_stream_update_segment (GstQTDemux * qtdemux,
599     QtDemuxStream * stream, gint seg_idx, GstClockTime offset,
600     GstClockTime * _start, GstClockTime * _stop);
601 static void gst_qtdemux_send_gap_for_segment (GstQTDemux * demux,
602     QtDemuxStream * stream, gint segment_index, GstClockTime pos);
603
604 static gboolean qtdemux_pull_mfro_mfra (GstQTDemux * qtdemux);
605 static void check_update_duration (GstQTDemux * qtdemux, GstClockTime duration);
606
607 static gchar *qtdemux_uuid_bytes_to_string (gconstpointer uuid_bytes);
608
609 static GstStructure *qtdemux_get_cenc_sample_properties (GstQTDemux * qtdemux,
610     QtDemuxStream * stream, guint sample_index);
611 static void gst_qtdemux_append_protection_system_id (GstQTDemux * qtdemux,
612     const gchar * id);
613 static void qtdemux_gst_structure_free (GstStructure * gststructure);
614 static void gst_qtdemux_reset (GstQTDemux * qtdemux, gboolean hard);
615
616 static void
617 gst_qtdemux_class_init (GstQTDemuxClass * klass)
618 {
619   GObjectClass *gobject_class;
620   GstElementClass *gstelement_class;
621
622   gobject_class = (GObjectClass *) klass;
623   gstelement_class = (GstElementClass *) klass;
624
625   parent_class = g_type_class_peek_parent (klass);
626
627   gobject_class->dispose = gst_qtdemux_dispose;
628
629   gstelement_class->change_state = GST_DEBUG_FUNCPTR (gst_qtdemux_change_state);
630 #if 0
631   gstelement_class->set_index = GST_DEBUG_FUNCPTR (gst_qtdemux_set_index);
632   gstelement_class->get_index = GST_DEBUG_FUNCPTR (gst_qtdemux_get_index);
633 #endif
634   gstelement_class->set_context = GST_DEBUG_FUNCPTR (gst_qtdemux_set_context);
635
636   gst_tag_register_musicbrainz_tags ();
637
638   gst_element_class_add_static_pad_template (gstelement_class,
639       &gst_qtdemux_sink_template);
640   gst_element_class_add_static_pad_template (gstelement_class,
641       &gst_qtdemux_videosrc_template);
642   gst_element_class_add_static_pad_template (gstelement_class,
643       &gst_qtdemux_audiosrc_template);
644   gst_element_class_add_static_pad_template (gstelement_class,
645       &gst_qtdemux_subsrc_template);
646   gst_element_class_set_static_metadata (gstelement_class, "QuickTime demuxer",
647       "Codec/Demuxer",
648       "Demultiplex a QuickTime file into audio and video streams",
649       "David Schleef <ds@schleef.org>, Wim Taymans <wim@fluendo.com>");
650
651   GST_DEBUG_CATEGORY_INIT (qtdemux_debug, "qtdemux", 0, "qtdemux plugin");
652   gst_riff_init ();
653 }
654
655 static void
656 gst_qtdemux_init (GstQTDemux * qtdemux)
657 {
658   qtdemux->sinkpad =
659       gst_pad_new_from_static_template (&gst_qtdemux_sink_template, "sink");
660   gst_pad_set_activate_function (qtdemux->sinkpad, qtdemux_sink_activate);
661   gst_pad_set_activatemode_function (qtdemux->sinkpad,
662       qtdemux_sink_activate_mode);
663   gst_pad_set_chain_function (qtdemux->sinkpad, gst_qtdemux_chain);
664   gst_pad_set_event_function (qtdemux->sinkpad, gst_qtdemux_handle_sink_event);
665   gst_pad_set_query_function (qtdemux->sinkpad, gst_qtdemux_handle_sink_query);
666   gst_element_add_pad (GST_ELEMENT_CAST (qtdemux), qtdemux->sinkpad);
667
668   qtdemux->adapter = gst_adapter_new ();
669   g_queue_init (&qtdemux->protection_event_queue);
670   qtdemux->flowcombiner = gst_flow_combiner_new ();
671   g_mutex_init (&qtdemux->expose_lock);
672
673   qtdemux->active_streams = g_ptr_array_new_with_free_func
674       ((GDestroyNotify) gst_qtdemux_stream_unref);
675   qtdemux->old_streams = g_ptr_array_new_with_free_func
676       ((GDestroyNotify) gst_qtdemux_stream_unref);
677
678   GST_OBJECT_FLAG_SET (qtdemux, GST_ELEMENT_FLAG_INDEXABLE);
679
680   gst_qtdemux_reset (qtdemux, TRUE);
681 }
682
683 static void
684 gst_qtdemux_dispose (GObject * object)
685 {
686   GstQTDemux *qtdemux = GST_QTDEMUX (object);
687
688   if (qtdemux->adapter) {
689     g_object_unref (G_OBJECT (qtdemux->adapter));
690     qtdemux->adapter = NULL;
691   }
692   gst_tag_list_unref (qtdemux->tag_list);
693   gst_flow_combiner_free (qtdemux->flowcombiner);
694   g_queue_foreach (&qtdemux->protection_event_queue, (GFunc) gst_event_unref,
695       NULL);
696   g_queue_clear (&qtdemux->protection_event_queue);
697
698   g_free (qtdemux->cenc_aux_info_sizes);
699   qtdemux->cenc_aux_info_sizes = NULL;
700   g_mutex_clear (&qtdemux->expose_lock);
701
702   g_ptr_array_free (qtdemux->active_streams, TRUE);
703   g_ptr_array_free (qtdemux->old_streams, TRUE);
704
705   G_OBJECT_CLASS (parent_class)->dispose (object);
706 }
707
708 static void
709 gst_qtdemux_post_no_playable_stream_error (GstQTDemux * qtdemux)
710 {
711   if (qtdemux->posted_redirect) {
712     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
713         (_("This file contains no playable streams.")),
714         ("no known streams found, a redirect message has been posted"));
715   } else {
716     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
717         (_("This file contains no playable streams.")),
718         ("no known streams found"));
719   }
720 }
721
722 static GstBuffer *
723 _gst_buffer_new_wrapped (gpointer mem, gsize size, GFreeFunc free_func)
724 {
725   return gst_buffer_new_wrapped_full (free_func ? 0 : GST_MEMORY_FLAG_READONLY,
726       mem, size, 0, size, mem, free_func);
727 }
728
729 static GstFlowReturn
730 gst_qtdemux_pull_atom (GstQTDemux * qtdemux, guint64 offset, guint64 size,
731     GstBuffer ** buf)
732 {
733   GstFlowReturn flow;
734   GstMapInfo map;
735   gsize bsize;
736
737   if (G_UNLIKELY (size == 0)) {
738     GstFlowReturn ret;
739     GstBuffer *tmp = NULL;
740
741     ret = gst_qtdemux_pull_atom (qtdemux, offset, sizeof (guint32), &tmp);
742     if (ret != GST_FLOW_OK)
743       return ret;
744
745     gst_buffer_map (tmp, &map, GST_MAP_READ);
746     size = QT_UINT32 (map.data);
747     GST_DEBUG_OBJECT (qtdemux, "size 0x%08" G_GINT64_MODIFIER "x", size);
748
749     gst_buffer_unmap (tmp, &map);
750     gst_buffer_unref (tmp);
751   }
752
753   /* Sanity check: catch bogus sizes (fuzzed/broken files) */
754   if (G_UNLIKELY (size > QTDEMUX_MAX_ATOM_SIZE)) {
755     if (qtdemux->state != QTDEMUX_STATE_MOVIE && qtdemux->got_moov) {
756       /* we're pulling header but already got most interesting bits,
757        * so never mind the rest (e.g. tags) (that much) */
758       GST_WARNING_OBJECT (qtdemux, "atom has bogus size %" G_GUINT64_FORMAT,
759           size);
760       return GST_FLOW_EOS;
761     } else {
762       GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
763           (_("This file is invalid and cannot be played.")),
764           ("atom has bogus size %" G_GUINT64_FORMAT, size));
765       return GST_FLOW_ERROR;
766     }
767   }
768
769   flow = gst_pad_pull_range (qtdemux->sinkpad, offset, size, buf);
770
771   if (G_UNLIKELY (flow != GST_FLOW_OK))
772     return flow;
773
774   bsize = gst_buffer_get_size (*buf);
775   /* Catch short reads - we don't want any partial atoms */
776   if (G_UNLIKELY (bsize < size)) {
777     GST_WARNING_OBJECT (qtdemux,
778         "short read: %" G_GSIZE_FORMAT " < %" G_GUINT64_FORMAT, bsize, size);
779     gst_buffer_unref (*buf);
780     *buf = NULL;
781     return GST_FLOW_EOS;
782   }
783
784   return flow;
785 }
786
787 #if 1
788 static gboolean
789 gst_qtdemux_src_convert (GstQTDemux * qtdemux, GstPad * pad,
790     GstFormat src_format, gint64 src_value, GstFormat dest_format,
791     gint64 * dest_value)
792 {
793   gboolean res = TRUE;
794   QtDemuxStream *stream = gst_pad_get_element_private (pad);
795   gint32 index;
796
797   if (stream->subtype != FOURCC_vide) {
798     res = FALSE;
799     goto done;
800   }
801
802   switch (src_format) {
803     case GST_FORMAT_TIME:
804       switch (dest_format) {
805         case GST_FORMAT_BYTES:{
806           index = gst_qtdemux_find_index_linear (qtdemux, stream, src_value);
807           if (-1 == index) {
808             res = FALSE;
809             goto done;
810           }
811
812           *dest_value = stream->samples[index].offset;
813
814           GST_DEBUG_OBJECT (qtdemux, "Format Conversion Time->Offset :%"
815               GST_TIME_FORMAT "->%" G_GUINT64_FORMAT,
816               GST_TIME_ARGS (src_value), *dest_value);
817           break;
818         }
819         default:
820           res = FALSE;
821           break;
822       }
823       break;
824     case GST_FORMAT_BYTES:
825       switch (dest_format) {
826         case GST_FORMAT_TIME:{
827           index =
828               gst_qtdemux_find_index_for_given_media_offset_linear (qtdemux,
829               stream, src_value);
830
831           if (-1 == index) {
832             res = FALSE;
833             goto done;
834           }
835
836           *dest_value =
837               QTSTREAMTIME_TO_GSTTIME (stream,
838               stream->samples[index].timestamp);
839           GST_DEBUG_OBJECT (qtdemux,
840               "Format Conversion Offset->Time :%" G_GUINT64_FORMAT "->%"
841               GST_TIME_FORMAT, src_value, GST_TIME_ARGS (*dest_value));
842           break;
843         }
844         default:
845           res = FALSE;
846           break;
847       }
848       break;
849     default:
850       res = FALSE;
851       break;
852   }
853
854 done:
855   return res;
856 }
857 #endif
858
859 static gboolean
860 gst_qtdemux_get_duration (GstQTDemux * qtdemux, GstClockTime * duration)
861 {
862   gboolean res = FALSE;
863
864   *duration = GST_CLOCK_TIME_NONE;
865
866   if (qtdemux->duration != 0 &&
867       qtdemux->duration != G_MAXINT64 && qtdemux->timescale != 0) {
868     *duration = QTTIME_TO_GSTTIME (qtdemux, qtdemux->duration);
869     res = TRUE;
870   } else {
871     *duration = GST_CLOCK_TIME_NONE;
872   }
873
874   return res;
875 }
876
877 static gboolean
878 gst_qtdemux_handle_src_query (GstPad * pad, GstObject * parent,
879     GstQuery * query)
880 {
881   gboolean res = FALSE;
882   GstQTDemux *qtdemux = GST_QTDEMUX (parent);
883
884   GST_LOG_OBJECT (pad, "%s query", GST_QUERY_TYPE_NAME (query));
885
886   switch (GST_QUERY_TYPE (query)) {
887     case GST_QUERY_POSITION:{
888       GstFormat fmt;
889
890       gst_query_parse_position (query, &fmt, NULL);
891       if (fmt == GST_FORMAT_TIME
892           && GST_CLOCK_TIME_IS_VALID (qtdemux->segment.position)) {
893         gst_query_set_position (query, GST_FORMAT_TIME,
894             qtdemux->segment.position);
895         res = TRUE;
896       }
897     }
898       break;
899     case GST_QUERY_DURATION:{
900       GstFormat fmt;
901
902       gst_query_parse_duration (query, &fmt, NULL);
903       if (fmt == GST_FORMAT_TIME) {
904         /* First try to query upstream */
905         res = gst_pad_query_default (pad, parent, query);
906         if (!res) {
907           GstClockTime duration;
908           if (gst_qtdemux_get_duration (qtdemux, &duration) && duration > 0) {
909             gst_query_set_duration (query, GST_FORMAT_TIME, duration);
910             res = TRUE;
911           }
912         }
913       }
914       break;
915     }
916     case GST_QUERY_CONVERT:{
917       GstFormat src_fmt, dest_fmt;
918       gint64 src_value, dest_value = 0;
919
920       gst_query_parse_convert (query, &src_fmt, &src_value, &dest_fmt, NULL);
921
922       res = gst_qtdemux_src_convert (qtdemux, pad,
923           src_fmt, src_value, dest_fmt, &dest_value);
924       if (res)
925         gst_query_set_convert (query, src_fmt, src_value, dest_fmt, dest_value);
926
927       break;
928     }
929     case GST_QUERY_FORMATS:
930       gst_query_set_formats (query, 2, GST_FORMAT_TIME, GST_FORMAT_BYTES);
931       res = TRUE;
932       break;
933     case GST_QUERY_SEEKING:{
934       GstFormat fmt;
935       gboolean seekable;
936
937       /* try upstream first */
938       res = gst_pad_query_default (pad, parent, query);
939
940       if (!res) {
941         gst_query_parse_seeking (query, &fmt, NULL, NULL, NULL);
942         if (fmt == GST_FORMAT_TIME) {
943           GstClockTime duration;
944
945           gst_qtdemux_get_duration (qtdemux, &duration);
946           seekable = TRUE;
947           if (!qtdemux->pullbased) {
948             GstQuery *q;
949
950             /* we might be able with help from upstream */
951             seekable = FALSE;
952             q = gst_query_new_seeking (GST_FORMAT_BYTES);
953             if (gst_pad_peer_query (qtdemux->sinkpad, q)) {
954               gst_query_parse_seeking (q, &fmt, &seekable, NULL, NULL);
955               GST_LOG_OBJECT (qtdemux, "upstream BYTE seekable %d", seekable);
956             }
957             gst_query_unref (q);
958           }
959           gst_query_set_seeking (query, GST_FORMAT_TIME, seekable, 0, duration);
960           res = TRUE;
961         }
962       }
963       break;
964     }
965     case GST_QUERY_SEGMENT:
966     {
967       GstFormat format;
968       gint64 start, stop;
969
970       format = qtdemux->segment.format;
971
972       start =
973           gst_segment_to_stream_time (&qtdemux->segment, format,
974           qtdemux->segment.start);
975       if ((stop = qtdemux->segment.stop) == -1)
976         stop = qtdemux->segment.duration;
977       else
978         stop = gst_segment_to_stream_time (&qtdemux->segment, format, stop);
979
980       gst_query_set_segment (query, qtdemux->segment.rate, format, start, stop);
981       res = TRUE;
982       break;
983     }
984     default:
985       res = gst_pad_query_default (pad, parent, query);
986       break;
987   }
988
989   return res;
990 }
991
992 static void
993 gst_qtdemux_push_tags (GstQTDemux * qtdemux, QtDemuxStream * stream)
994 {
995   if (G_LIKELY (stream->pad)) {
996     GST_DEBUG_OBJECT (qtdemux, "Checking pad %s:%s for tags",
997         GST_DEBUG_PAD_NAME (stream->pad));
998
999     if (!gst_tag_list_is_empty (stream->stream_tags)) {
1000       GST_DEBUG_OBJECT (qtdemux, "Sending tags %" GST_PTR_FORMAT,
1001           stream->stream_tags);
1002       gst_pad_push_event (stream->pad,
1003           gst_event_new_tag (gst_tag_list_ref (stream->stream_tags)));
1004     }
1005
1006     if (G_UNLIKELY (stream->send_global_tags)) {
1007       GST_DEBUG_OBJECT (qtdemux, "Sending global tags %" GST_PTR_FORMAT,
1008           qtdemux->tag_list);
1009       gst_pad_push_event (stream->pad,
1010           gst_event_new_tag (gst_tag_list_ref (qtdemux->tag_list)));
1011       stream->send_global_tags = FALSE;
1012     }
1013   }
1014 }
1015
1016 /* push event on all source pads; takes ownership of the event */
1017 static void
1018 gst_qtdemux_push_event (GstQTDemux * qtdemux, GstEvent * event)
1019 {
1020   gboolean has_valid_stream = FALSE;
1021   GstEventType etype = GST_EVENT_TYPE (event);
1022   guint i;
1023
1024   GST_DEBUG_OBJECT (qtdemux, "pushing %s event on all source pads",
1025       GST_EVENT_TYPE_NAME (event));
1026
1027   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
1028     GstPad *pad;
1029     QtDemuxStream *stream = QTDEMUX_NTH_STREAM (qtdemux, i);
1030     GST_DEBUG_OBJECT (qtdemux, "pushing on track-id %u", stream->track_id);
1031
1032     if ((pad = stream->pad)) {
1033       has_valid_stream = TRUE;
1034
1035       if (etype == GST_EVENT_EOS) {
1036         /* let's not send twice */
1037         if (stream->sent_eos)
1038           continue;
1039         stream->sent_eos = TRUE;
1040       }
1041
1042       gst_pad_push_event (pad, gst_event_ref (event));
1043     }
1044   }
1045
1046   gst_event_unref (event);
1047
1048   /* if it is EOS and there are no pads, post an error */
1049   if (!has_valid_stream && etype == GST_EVENT_EOS) {
1050     gst_qtdemux_post_no_playable_stream_error (qtdemux);
1051   }
1052 }
1053
1054 typedef struct
1055 {
1056   guint64 media_time;
1057 } FindData;
1058
1059 static gint
1060 find_func (QtDemuxSample * s1, gint64 * media_time, gpointer user_data)
1061 {
1062   if ((gint64) s1->timestamp > *media_time)
1063     return 1;
1064   if ((gint64) s1->timestamp == *media_time)
1065     return 0;
1066
1067   return -1;
1068 }
1069
1070 /* find the index of the sample that includes the data for @media_time using a
1071  * binary search.  Only to be called in optimized cases of linear search below.
1072  *
1073  * Returns the index of the sample with the corresponding *DTS*.
1074  */
1075 static guint32
1076 gst_qtdemux_find_index (GstQTDemux * qtdemux, QtDemuxStream * str,
1077     guint64 media_time)
1078 {
1079   QtDemuxSample *result;
1080   guint32 index;
1081
1082   /* convert media_time to mov format */
1083   media_time =
1084       gst_util_uint64_scale_ceil (media_time, str->timescale, GST_SECOND);
1085
1086   result = gst_util_array_binary_search (str->samples, str->stbl_index + 1,
1087       sizeof (QtDemuxSample), (GCompareDataFunc) find_func,
1088       GST_SEARCH_MODE_BEFORE, &media_time, NULL);
1089
1090   if (G_LIKELY (result))
1091     index = result - str->samples;
1092   else
1093     index = 0;
1094
1095   return index;
1096 }
1097
1098
1099
1100 /* find the index of the sample that includes the data for @media_offset using a
1101  * linear search
1102  *
1103  * Returns the index of the sample.
1104  */
1105 static guint32
1106 gst_qtdemux_find_index_for_given_media_offset_linear (GstQTDemux * qtdemux,
1107     QtDemuxStream * str, gint64 media_offset)
1108 {
1109   QtDemuxSample *result = str->samples;
1110   guint32 index = 0;
1111
1112   if (result == NULL || str->n_samples == 0)
1113     return -1;
1114
1115   if (media_offset == result->offset)
1116     return index;
1117
1118   result++;
1119   while (index < str->n_samples - 1) {
1120     if (!qtdemux_parse_samples (qtdemux, str, index + 1))
1121       goto parse_failed;
1122
1123     if (media_offset < result->offset)
1124       break;
1125
1126     index++;
1127     result++;
1128   }
1129   return index;
1130
1131   /* ERRORS */
1132 parse_failed:
1133   {
1134     GST_LOG_OBJECT (qtdemux, "Parsing of index %u failed!", index + 1);
1135     return -1;
1136   }
1137 }
1138
1139 /* find the index of the sample that includes the data for @media_time using a
1140  * linear search, and keeping in mind that not all samples may have been parsed
1141  * yet.  If possible, it will delegate to binary search.
1142  *
1143  * Returns the index of the sample.
1144  */
1145 static guint32
1146 gst_qtdemux_find_index_linear (GstQTDemux * qtdemux, QtDemuxStream * str,
1147     GstClockTime media_time)
1148 {
1149   guint32 index = 0;
1150   guint64 mov_time;
1151   QtDemuxSample *sample;
1152
1153   /* convert media_time to mov format */
1154   mov_time =
1155       gst_util_uint64_scale_ceil (media_time, str->timescale, GST_SECOND);
1156
1157   sample = str->samples;
1158   if (mov_time == sample->timestamp + sample->pts_offset)
1159     return index;
1160
1161   /* use faster search if requested time in already parsed range */
1162   sample = str->samples + str->stbl_index;
1163   if (str->stbl_index >= 0 && mov_time <= sample->timestamp) {
1164     index = gst_qtdemux_find_index (qtdemux, str, media_time);
1165     sample = str->samples + index;
1166   } else {
1167     while (index < str->n_samples - 1) {
1168       if (!qtdemux_parse_samples (qtdemux, str, index + 1))
1169         goto parse_failed;
1170
1171       sample = str->samples + index + 1;
1172       if (mov_time < sample->timestamp) {
1173         sample = str->samples + index;
1174         break;
1175       }
1176
1177       index++;
1178     }
1179   }
1180
1181   /* sample->timestamp is now <= media_time, need to find the corresponding
1182    * PTS now by looking backwards */
1183   while (index > 0 && sample->timestamp + sample->pts_offset > mov_time) {
1184     index--;
1185     sample = str->samples + index;
1186   }
1187
1188   return index;
1189
1190   /* ERRORS */
1191 parse_failed:
1192   {
1193     GST_LOG_OBJECT (qtdemux, "Parsing of index %u failed!", index + 1);
1194     return -1;
1195   }
1196 }
1197
1198 /* find the index of the keyframe needed to decode the sample at @index
1199  * of stream @str, or of a subsequent keyframe (depending on @next)
1200  *
1201  * Returns the index of the keyframe.
1202  */
1203 static guint32
1204 gst_qtdemux_find_keyframe (GstQTDemux * qtdemux, QtDemuxStream * str,
1205     guint32 index, gboolean next)
1206 {
1207   guint32 new_index = index;
1208
1209   if (index >= str->n_samples) {
1210     new_index = str->n_samples;
1211     goto beach;
1212   }
1213
1214   /* all keyframes, return index */
1215   if (str->all_keyframe) {
1216     new_index = index;
1217     goto beach;
1218   }
1219
1220   /* else search until we have a keyframe */
1221   while (new_index < str->n_samples) {
1222     if (next && !qtdemux_parse_samples (qtdemux, str, new_index))
1223       goto parse_failed;
1224
1225     if (str->samples[new_index].keyframe)
1226       break;
1227
1228     if (new_index == 0)
1229       break;
1230
1231     if (next)
1232       new_index++;
1233     else
1234       new_index--;
1235   }
1236
1237   if (new_index == str->n_samples) {
1238     GST_DEBUG_OBJECT (qtdemux, "no next keyframe");
1239     new_index = -1;
1240   }
1241
1242 beach:
1243   GST_DEBUG_OBJECT (qtdemux, "searching for keyframe index %s index %u "
1244       "gave %u", next ? "after" : "before", index, new_index);
1245
1246   return new_index;
1247
1248   /* ERRORS */
1249 parse_failed:
1250   {
1251     GST_LOG_OBJECT (qtdemux, "Parsing of index %u failed!", new_index);
1252     return -1;
1253   }
1254 }
1255
1256 /* find the segment for @time_position for @stream
1257  *
1258  * Returns the index of the segment containing @time_position.
1259  * Returns the last segment and sets the @eos variable to TRUE
1260  * if the time is beyond the end. @eos may be NULL
1261  */
1262 static guint32
1263 gst_qtdemux_find_segment (GstQTDemux * qtdemux, QtDemuxStream * stream,
1264     GstClockTime time_position)
1265 {
1266   gint i;
1267   guint32 seg_idx;
1268
1269   GST_LOG_OBJECT (stream->pad, "finding segment for %" GST_TIME_FORMAT,
1270       GST_TIME_ARGS (time_position));
1271
1272   seg_idx = -1;
1273   for (i = 0; i < stream->n_segments; i++) {
1274     QtDemuxSegment *segment = &stream->segments[i];
1275
1276     GST_LOG_OBJECT (stream->pad,
1277         "looking at segment %" GST_TIME_FORMAT "-%" GST_TIME_FORMAT,
1278         GST_TIME_ARGS (segment->time), GST_TIME_ARGS (segment->stop_time));
1279
1280     /* For the last segment we include stop_time in the last segment */
1281     if (i < stream->n_segments - 1) {
1282       if (segment->time <= time_position && time_position < segment->stop_time) {
1283         GST_LOG_OBJECT (stream->pad, "segment %d matches", i);
1284         seg_idx = i;
1285         break;
1286       }
1287     } else {
1288       /* Last segment always matches */
1289       seg_idx = i;
1290       break;
1291     }
1292   }
1293   return seg_idx;
1294 }
1295
1296 /* move the stream @str to the sample position @index.
1297  *
1298  * Updates @str->sample_index and marks discontinuity if needed.
1299  */
1300 static void
1301 gst_qtdemux_move_stream (GstQTDemux * qtdemux, QtDemuxStream * str,
1302     guint32 index)
1303 {
1304   /* no change needed */
1305   if (index == str->sample_index)
1306     return;
1307
1308   GST_DEBUG_OBJECT (qtdemux, "moving to sample %u of %u", index,
1309       str->n_samples);
1310
1311   /* position changed, we have a discont */
1312   str->sample_index = index;
1313   str->offset_in_sample = 0;
1314   /* Each time we move in the stream we store the position where we are
1315    * starting from */
1316   str->from_sample = index;
1317   str->discont = TRUE;
1318 }
1319
1320 static void
1321 gst_qtdemux_adjust_seek (GstQTDemux * qtdemux, gint64 desired_time,
1322     gboolean use_sparse, gboolean next, gint64 * key_time, gint64 * key_offset)
1323 {
1324   guint64 min_offset;
1325   gint64 min_byte_offset = -1;
1326   guint i;
1327
1328   min_offset = desired_time;
1329
1330   /* for each stream, find the index of the sample in the segment
1331    * and move back to the previous keyframe. */
1332   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
1333     QtDemuxStream *str;
1334     guint32 index, kindex;
1335     guint32 seg_idx;
1336     GstClockTime media_start;
1337     GstClockTime media_time;
1338     GstClockTime seg_time;
1339     QtDemuxSegment *seg;
1340     gboolean empty_segment = FALSE;
1341
1342     str = QTDEMUX_NTH_STREAM (qtdemux, i);
1343
1344     if (CUR_STREAM (str)->sparse && !use_sparse)
1345       continue;
1346
1347     seg_idx = gst_qtdemux_find_segment (qtdemux, str, desired_time);
1348     GST_DEBUG_OBJECT (qtdemux, "align segment %d", seg_idx);
1349
1350     /* get segment and time in the segment */
1351     seg = &str->segments[seg_idx];
1352     seg_time = (desired_time - seg->time) * seg->rate;
1353
1354     while (QTSEGMENT_IS_EMPTY (seg)) {
1355       seg_time = 0;
1356       empty_segment = TRUE;
1357       GST_DEBUG_OBJECT (str->pad, "Segment %d is empty, moving to next one",
1358           seg_idx);
1359       seg_idx++;
1360       if (seg_idx == str->n_segments)
1361         break;
1362       seg = &str->segments[seg_idx];
1363     }
1364
1365     if (seg_idx == str->n_segments) {
1366       /* FIXME track shouldn't have the last segment as empty, but if it
1367        * happens we better handle it */
1368       continue;
1369     }
1370
1371     /* get the media time in the segment */
1372     media_start = seg->media_start + seg_time;
1373
1374     /* get the index of the sample with media time */
1375     index = gst_qtdemux_find_index_linear (qtdemux, str, media_start);
1376     GST_DEBUG_OBJECT (qtdemux, "sample for %" GST_TIME_FORMAT " at %u"
1377         " at offset %" G_GUINT64_FORMAT " (empty segment: %d)",
1378         GST_TIME_ARGS (media_start), index, str->samples[index].offset,
1379         empty_segment);
1380
1381     /* shift to next frame if we are looking for next keyframe */
1382     if (next && QTSAMPLE_PTS_NO_CSLG (str, &str->samples[index]) < media_start
1383         && index < str->stbl_index)
1384       index++;
1385
1386     if (!empty_segment) {
1387       /* find previous keyframe */
1388       kindex = gst_qtdemux_find_keyframe (qtdemux, str, index, next);
1389
1390       /* we will settle for one before if none found after */
1391       if (next && kindex == -1)
1392         kindex = gst_qtdemux_find_keyframe (qtdemux, str, index, FALSE);
1393
1394       /* if the keyframe is at a different position, we need to update the
1395        * requested seek time */
1396       if (index != kindex) {
1397         index = kindex;
1398
1399         /* get timestamp of keyframe */
1400         media_time = QTSAMPLE_PTS_NO_CSLG (str, &str->samples[kindex]);
1401         GST_DEBUG_OBJECT (qtdemux,
1402             "keyframe at %u with time %" GST_TIME_FORMAT " at offset %"
1403             G_GUINT64_FORMAT, kindex, GST_TIME_ARGS (media_time),
1404             str->samples[kindex].offset);
1405
1406         /* keyframes in the segment get a chance to change the
1407          * desired_offset. keyframes out of the segment are
1408          * ignored. */
1409         if (media_time >= seg->media_start) {
1410           GstClockTime seg_time;
1411
1412           /* this keyframe is inside the segment, convert back to
1413            * segment time */
1414           seg_time = (media_time - seg->media_start) + seg->time;
1415           if ((!next && (seg_time < min_offset)) ||
1416               (next && (seg_time > min_offset)))
1417             min_offset = seg_time;
1418         }
1419       }
1420     }
1421
1422     if (min_byte_offset < 0 || str->samples[index].offset < min_byte_offset)
1423       min_byte_offset = str->samples[index].offset;
1424   }
1425
1426   if (key_time)
1427     *key_time = min_offset;
1428   if (key_offset)
1429     *key_offset = min_byte_offset;
1430 }
1431
1432 static gboolean
1433 gst_qtdemux_convert_seek (GstPad * pad, GstFormat * format,
1434     GstSeekType cur_type, gint64 * cur, GstSeekType stop_type, gint64 * stop)
1435 {
1436   gboolean res;
1437
1438   g_return_val_if_fail (format != NULL, FALSE);
1439   g_return_val_if_fail (cur != NULL, FALSE);
1440   g_return_val_if_fail (stop != NULL, FALSE);
1441
1442   if (*format == GST_FORMAT_TIME)
1443     return TRUE;
1444
1445   res = TRUE;
1446   if (cur_type != GST_SEEK_TYPE_NONE)
1447     res = gst_pad_query_convert (pad, *format, *cur, GST_FORMAT_TIME, cur);
1448   if (res && stop_type != GST_SEEK_TYPE_NONE)
1449     res = gst_pad_query_convert (pad, *format, *stop, GST_FORMAT_TIME, stop);
1450
1451   if (res)
1452     *format = GST_FORMAT_TIME;
1453
1454   return res;
1455 }
1456
1457 /* perform seek in push based mode:
1458    find BYTE position to move to based on time and delegate to upstream
1459 */
1460 static gboolean
1461 gst_qtdemux_do_push_seek (GstQTDemux * qtdemux, GstPad * pad, GstEvent * event)
1462 {
1463   gdouble rate;
1464   GstFormat format;
1465   GstSeekFlags flags;
1466   GstSeekType cur_type, stop_type;
1467   gint64 cur, stop, key_cur;
1468   gboolean res;
1469   gint64 byte_cur;
1470   gint64 original_stop;
1471   guint32 seqnum;
1472
1473   GST_DEBUG_OBJECT (qtdemux, "doing push-based seek");
1474
1475   gst_event_parse_seek (event, &rate, &format, &flags,
1476       &cur_type, &cur, &stop_type, &stop);
1477   seqnum = gst_event_get_seqnum (event);
1478
1479   /* only forward streaming and seeking is possible */
1480   if (rate <= 0)
1481     goto unsupported_seek;
1482
1483   /* convert to TIME if needed and possible */
1484   if (!gst_qtdemux_convert_seek (pad, &format, cur_type, &cur,
1485           stop_type, &stop))
1486     goto no_format;
1487
1488   /* Upstream seek in bytes will have undefined stop, but qtdemux stores
1489    * the original stop position to use when upstream pushes the new segment
1490    * for this seek */
1491   original_stop = stop;
1492   stop = -1;
1493
1494   /* find reasonable corresponding BYTE position,
1495    * also try to mind about keyframes, since we can not go back a bit for them
1496    * later on */
1497   /* determining @next here based on SNAP_BEFORE/SNAP_AFTER should
1498    * mostly just work, but let's not yet boldly go there  ... */
1499   gst_qtdemux_adjust_seek (qtdemux, cur, FALSE, FALSE, &key_cur, &byte_cur);
1500
1501   if (byte_cur == -1)
1502     goto abort_seek;
1503
1504   GST_DEBUG_OBJECT (qtdemux, "Pushing BYTE seek rate %g, "
1505       "start %" G_GINT64_FORMAT ", stop %" G_GINT64_FORMAT, rate, byte_cur,
1506       stop);
1507
1508   GST_OBJECT_LOCK (qtdemux);
1509   qtdemux->seek_offset = byte_cur;
1510   if (!(flags & GST_SEEK_FLAG_KEY_UNIT)) {
1511     qtdemux->push_seek_start = cur;
1512   } else {
1513     qtdemux->push_seek_start = key_cur;
1514   }
1515
1516   if (stop_type == GST_SEEK_TYPE_NONE) {
1517     qtdemux->push_seek_stop = qtdemux->segment.stop;
1518   } else {
1519     qtdemux->push_seek_stop = original_stop;
1520   }
1521   GST_OBJECT_UNLOCK (qtdemux);
1522
1523   qtdemux->segment_seqnum = seqnum;
1524   /* BYTE seek event */
1525   event = gst_event_new_seek (rate, GST_FORMAT_BYTES, flags, cur_type, byte_cur,
1526       stop_type, stop);
1527   gst_event_set_seqnum (event, seqnum);
1528   res = gst_pad_push_event (qtdemux->sinkpad, event);
1529
1530   return res;
1531
1532   /* ERRORS */
1533 abort_seek:
1534   {
1535     GST_DEBUG_OBJECT (qtdemux, "could not determine byte position to seek to, "
1536         "seek aborted.");
1537     return FALSE;
1538   }
1539 unsupported_seek:
1540   {
1541     GST_DEBUG_OBJECT (qtdemux, "unsupported seek, seek aborted.");
1542     return FALSE;
1543   }
1544 no_format:
1545   {
1546     GST_DEBUG_OBJECT (qtdemux, "unsupported format given, seek aborted.");
1547     return FALSE;
1548   }
1549 }
1550
1551 /* perform the seek.
1552  *
1553  * We set all segment_indexes in the streams to unknown and
1554  * adjust the time_position to the desired position. this is enough
1555  * to trigger a segment switch in the streaming thread to start
1556  * streaming from the desired position.
1557  *
1558  * Keyframe seeking is a little more complicated when dealing with
1559  * segments. Ideally we want to move to the previous keyframe in
1560  * the segment but there might not be a keyframe in the segment. In
1561  * fact, none of the segments could contain a keyframe. We take a
1562  * practical approach: seek to the previous keyframe in the segment,
1563  * if there is none, seek to the beginning of the segment.
1564  *
1565  * Called with STREAM_LOCK
1566  */
1567 static gboolean
1568 gst_qtdemux_perform_seek (GstQTDemux * qtdemux, GstSegment * segment,
1569     guint32 seqnum, GstSeekFlags flags)
1570 {
1571   gint64 desired_offset;
1572   guint i;
1573
1574   desired_offset = segment->position;
1575
1576   GST_DEBUG_OBJECT (qtdemux, "seeking to %" GST_TIME_FORMAT,
1577       GST_TIME_ARGS (desired_offset));
1578
1579   /* may not have enough fragmented info to do this adjustment,
1580    * and we can't scan (and probably should not) at this time with
1581    * possibly flushing upstream */
1582   if ((flags & GST_SEEK_FLAG_KEY_UNIT) && !qtdemux->fragmented) {
1583     gint64 min_offset;
1584     gboolean next, before, after;
1585
1586     before = ! !(flags & GST_SEEK_FLAG_SNAP_BEFORE);
1587     after = ! !(flags & GST_SEEK_FLAG_SNAP_AFTER);
1588     next = after && !before;
1589     if (segment->rate < 0)
1590       next = !next;
1591
1592     gst_qtdemux_adjust_seek (qtdemux, desired_offset, TRUE, next, &min_offset,
1593         NULL);
1594     GST_DEBUG_OBJECT (qtdemux, "keyframe seek, align to %"
1595         GST_TIME_FORMAT, GST_TIME_ARGS (min_offset));
1596     desired_offset = min_offset;
1597   }
1598
1599   /* and set all streams to the final position */
1600   gst_flow_combiner_reset (qtdemux->flowcombiner);
1601   qtdemux->segment_seqnum = seqnum;
1602   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
1603     QtDemuxStream *stream = QTDEMUX_NTH_STREAM (qtdemux, i);
1604
1605     stream->time_position = desired_offset;
1606     stream->accumulated_base = 0;
1607     stream->sample_index = -1;
1608     stream->offset_in_sample = 0;
1609     stream->segment_index = -1;
1610     stream->sent_eos = FALSE;
1611
1612     if (segment->flags & GST_SEEK_FLAG_FLUSH)
1613       gst_segment_init (&stream->segment, GST_FORMAT_TIME);
1614   }
1615   segment->position = desired_offset;
1616   segment->time = desired_offset;
1617   if (segment->rate >= 0) {
1618     segment->start = desired_offset;
1619
1620     /* we stop at the end */
1621     if (segment->stop == -1)
1622       segment->stop = segment->duration;
1623   } else {
1624     segment->stop = desired_offset;
1625   }
1626
1627   if (qtdemux->fragmented)
1628     qtdemux->fragmented_seek_pending = TRUE;
1629
1630   return TRUE;
1631 }
1632
1633 /* do a seek in pull based mode */
1634 static gboolean
1635 gst_qtdemux_do_seek (GstQTDemux * qtdemux, GstPad * pad, GstEvent * event)
1636 {
1637   gdouble rate;
1638   GstFormat format;
1639   GstSeekFlags flags;
1640   GstSeekType cur_type, stop_type;
1641   gint64 cur, stop;
1642   gboolean flush;
1643   gboolean update;
1644   GstSegment seeksegment;
1645   guint32 seqnum = GST_SEQNUM_INVALID;
1646   GstEvent *flush_event;
1647   gboolean ret;
1648
1649   if (event) {
1650     GST_DEBUG_OBJECT (qtdemux, "doing seek with event");
1651
1652     gst_event_parse_seek (event, &rate, &format, &flags,
1653         &cur_type, &cur, &stop_type, &stop);
1654     seqnum = gst_event_get_seqnum (event);
1655
1656     /* we have to have a format as the segment format. Try to convert
1657      * if not. */
1658     if (!gst_qtdemux_convert_seek (pad, &format, cur_type, &cur,
1659             stop_type, &stop))
1660       goto no_format;
1661
1662     GST_DEBUG_OBJECT (qtdemux, "seek format %s", gst_format_get_name (format));
1663   } else {
1664     GST_DEBUG_OBJECT (qtdemux, "doing seek without event");
1665     flags = 0;
1666   }
1667
1668   flush = flags & GST_SEEK_FLAG_FLUSH;
1669
1670   /* stop streaming, either by flushing or by pausing the task */
1671   if (flush) {
1672     flush_event = gst_event_new_flush_start ();
1673     if (seqnum != GST_SEQNUM_INVALID)
1674       gst_event_set_seqnum (flush_event, seqnum);
1675     /* unlock upstream pull_range */
1676     gst_pad_push_event (qtdemux->sinkpad, gst_event_ref (flush_event));
1677     /* make sure out loop function exits */
1678     gst_qtdemux_push_event (qtdemux, flush_event);
1679   } else {
1680     /* non flushing seek, pause the task */
1681     gst_pad_pause_task (qtdemux->sinkpad);
1682   }
1683
1684   /* wait for streaming to finish */
1685   GST_PAD_STREAM_LOCK (qtdemux->sinkpad);
1686
1687   /* copy segment, we need this because we still need the old
1688    * segment when we close the current segment. */
1689   memcpy (&seeksegment, &qtdemux->segment, sizeof (GstSegment));
1690
1691   if (event) {
1692     /* configure the segment with the seek variables */
1693     GST_DEBUG_OBJECT (qtdemux, "configuring seek");
1694     if (!gst_segment_do_seek (&seeksegment, rate, format, flags,
1695             cur_type, cur, stop_type, stop, &update)) {
1696       ret = FALSE;
1697       GST_ERROR_OBJECT (qtdemux, "inconsistent seek values, doing nothing");
1698     } else {
1699       /* now do the seek */
1700       ret = gst_qtdemux_perform_seek (qtdemux, &seeksegment, seqnum, flags);
1701     }
1702   } else {
1703     /* now do the seek */
1704     ret = gst_qtdemux_perform_seek (qtdemux, &seeksegment, seqnum, flags);
1705   }
1706
1707   /* prepare for streaming again */
1708   if (flush) {
1709     flush_event = gst_event_new_flush_stop (TRUE);
1710     if (seqnum != GST_SEQNUM_INVALID)
1711       gst_event_set_seqnum (flush_event, seqnum);
1712
1713     gst_pad_push_event (qtdemux->sinkpad, gst_event_ref (flush_event));
1714     gst_qtdemux_push_event (qtdemux, flush_event);
1715   }
1716
1717   /* commit the new segment */
1718   memcpy (&qtdemux->segment, &seeksegment, sizeof (GstSegment));
1719
1720   if (qtdemux->segment.flags & GST_SEEK_FLAG_SEGMENT) {
1721     GstMessage *msg = gst_message_new_segment_start (GST_OBJECT_CAST (qtdemux),
1722         qtdemux->segment.format, qtdemux->segment.position);
1723     if (seqnum != GST_SEQNUM_INVALID)
1724       gst_message_set_seqnum (msg, seqnum);
1725     gst_element_post_message (GST_ELEMENT_CAST (qtdemux), msg);
1726   }
1727
1728   /* restart streaming, NEWSEGMENT will be sent from the streaming thread. */
1729   gst_pad_start_task (qtdemux->sinkpad, (GstTaskFunction) gst_qtdemux_loop,
1730       qtdemux->sinkpad, NULL);
1731
1732   GST_PAD_STREAM_UNLOCK (qtdemux->sinkpad);
1733
1734   return ret;
1735
1736   /* ERRORS */
1737 no_format:
1738   {
1739     GST_DEBUG_OBJECT (qtdemux, "unsupported format given, seek aborted.");
1740     return FALSE;
1741   }
1742 }
1743
1744 static gboolean
1745 qtdemux_ensure_index (GstQTDemux * qtdemux)
1746 {
1747   guint i;
1748
1749   GST_DEBUG_OBJECT (qtdemux, "collecting all metadata for all streams");
1750
1751   /* Build complete index */
1752   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
1753     QtDemuxStream *stream = QTDEMUX_NTH_STREAM (qtdemux, i);
1754
1755     if (!qtdemux_parse_samples (qtdemux, stream, stream->n_samples - 1)) {
1756       GST_LOG_OBJECT (qtdemux,
1757           "Building complete index of track-id %u for seeking failed!",
1758           stream->track_id);
1759       return FALSE;
1760     }
1761   }
1762
1763   return TRUE;
1764 }
1765
1766 static gboolean
1767 gst_qtdemux_handle_src_event (GstPad * pad, GstObject * parent,
1768     GstEvent * event)
1769 {
1770   gboolean res = TRUE;
1771   GstQTDemux *qtdemux = GST_QTDEMUX (parent);
1772
1773   switch (GST_EVENT_TYPE (event)) {
1774     case GST_EVENT_SEEK:
1775     {
1776 #ifndef GST_DISABLE_GST_DEBUG
1777       GstClockTime ts = gst_util_get_timestamp ();
1778 #endif
1779       guint32 seqnum = gst_event_get_seqnum (event);
1780
1781       qtdemux->received_seek = TRUE;
1782
1783       if (seqnum == qtdemux->segment_seqnum) {
1784         GST_LOG_OBJECT (pad,
1785             "Drop duplicated SEEK event seqnum %" G_GUINT32_FORMAT, seqnum);
1786         gst_event_unref (event);
1787         return TRUE;
1788       }
1789
1790       if (qtdemux->upstream_format_is_time && qtdemux->fragmented) {
1791         /* seek should be handled by upstream, we might need to re-download fragments */
1792         GST_DEBUG_OBJECT (qtdemux,
1793             "let upstream handle seek for fragmented playback");
1794         goto upstream;
1795       }
1796
1797       /* Build complete index for seeking;
1798        * if not a fragmented file at least */
1799       if (!qtdemux->fragmented)
1800         if (!qtdemux_ensure_index (qtdemux))
1801           goto index_failed;
1802 #ifndef GST_DISABLE_GST_DEBUG
1803       ts = gst_util_get_timestamp () - ts;
1804       GST_INFO_OBJECT (qtdemux,
1805           "Time taken to parse index %" GST_TIME_FORMAT, GST_TIME_ARGS (ts));
1806 #endif
1807     }
1808       if (qtdemux->pullbased) {
1809         res = gst_qtdemux_do_seek (qtdemux, pad, event);
1810       } else if (gst_pad_push_event (qtdemux->sinkpad, gst_event_ref (event))) {
1811         GST_DEBUG_OBJECT (qtdemux, "Upstream successfully seeked");
1812         res = TRUE;
1813       } else if (qtdemux->state == QTDEMUX_STATE_MOVIE
1814           && QTDEMUX_N_STREAMS (qtdemux)
1815           && !qtdemux->fragmented) {
1816         res = gst_qtdemux_do_push_seek (qtdemux, pad, event);
1817       } else {
1818         GST_DEBUG_OBJECT (qtdemux,
1819             "ignoring seek in push mode in current state");
1820         res = FALSE;
1821       }
1822       gst_event_unref (event);
1823       break;
1824     default:
1825     upstream:
1826       res = gst_pad_event_default (pad, parent, event);
1827       break;
1828   }
1829
1830 done:
1831   return res;
1832
1833   /* ERRORS */
1834 index_failed:
1835   {
1836     GST_ERROR_OBJECT (qtdemux, "Index failed");
1837     gst_event_unref (event);
1838     res = FALSE;
1839     goto done;
1840   }
1841 }
1842
1843 /* Find, for each track, the first sample in coding order that has a file offset >= @byte_pos.
1844  *
1845  * If @fw is false, the coding order is explored backwards.
1846  *
1847  * If @set is true, each stream will be moved to its matched sample, or EOS if no matching
1848  * sample is found for that track.
1849  *
1850  * The stream and sample index of the sample with the minimum offset in the direction explored
1851  * (see @fw) is returned in the output parameters @_stream and @_index respectively.
1852  *
1853  * @_time is set to the QTSAMPLE_PTS of the matched sample with the minimum QTSAMPLE_PTS in the
1854  * direction explored, which may not always match the QTSAMPLE_PTS of the sample returned in
1855  * @_stream and @_index. */
1856 static void
1857 gst_qtdemux_find_sample (GstQTDemux * qtdemux, gint64 byte_pos, gboolean fw,
1858     gboolean set, QtDemuxStream ** _stream, gint * _index, gint64 * _time)
1859 {
1860   gint i, index;
1861   gint64 time, min_time;
1862   QtDemuxStream *stream;
1863   gint iter;
1864
1865   min_time = -1;
1866   stream = NULL;
1867   index = -1;
1868
1869   for (iter = 0; iter < QTDEMUX_N_STREAMS (qtdemux); iter++) {
1870     QtDemuxStream *str;
1871     gint inc;
1872     gboolean set_sample;
1873
1874     str = QTDEMUX_NTH_STREAM (qtdemux, iter);
1875     set_sample = !set;
1876
1877     if (fw) {
1878       i = 0;
1879       inc = 1;
1880     } else {
1881       i = str->n_samples - 1;
1882       inc = -1;
1883     }
1884
1885     for (; (i >= 0) && (i < str->n_samples); i += inc) {
1886       if (str->samples[i].size == 0)
1887         continue;
1888
1889       if (fw && (str->samples[i].offset < byte_pos))
1890         continue;
1891
1892       if (!fw && (str->samples[i].offset + str->samples[i].size > byte_pos))
1893         continue;
1894
1895       /* move stream to first available sample */
1896       if (set) {
1897         gst_qtdemux_move_stream (qtdemux, str, i);
1898         set_sample = TRUE;
1899       }
1900
1901       /* avoid index from sparse streams since they might be far away */
1902       if (!CUR_STREAM (str)->sparse) {
1903         /* determine min/max time */
1904         time = QTSAMPLE_PTS (str, &str->samples[i]);
1905         if (min_time == -1 || (!fw && time > min_time) ||
1906             (fw && time < min_time)) {
1907           min_time = time;
1908         }
1909
1910         /* determine stream with leading sample, to get its position */
1911         if (!stream ||
1912             (fw && (str->samples[i].offset < stream->samples[index].offset)) ||
1913             (!fw && (str->samples[i].offset > stream->samples[index].offset))) {
1914           stream = str;
1915           index = i;
1916         }
1917       }
1918       break;
1919     }
1920
1921     /* no sample for this stream, mark eos */
1922     if (!set_sample)
1923       gst_qtdemux_move_stream (qtdemux, str, str->n_samples);
1924   }
1925
1926   if (_time)
1927     *_time = min_time;
1928   if (_stream)
1929     *_stream = stream;
1930   if (_index)
1931     *_index = index;
1932 }
1933
1934 /* Copied from mpegtsbase code */
1935 /* FIXME: replace this function when we add new util function for stream-id creation */
1936 static gchar *
1937 _get_upstream_id (GstQTDemux * demux)
1938 {
1939   gchar *upstream_id = gst_pad_get_stream_id (demux->sinkpad);
1940
1941   if (!upstream_id) {
1942     /* Try to create one from the upstream URI, else use a randome number */
1943     GstQuery *query;
1944     gchar *uri = NULL;
1945
1946     /* Try to generate one from the URI query and
1947      * if it fails take a random number instead */
1948     query = gst_query_new_uri ();
1949     if (gst_element_query (GST_ELEMENT_CAST (demux), query)) {
1950       gst_query_parse_uri (query, &uri);
1951     }
1952
1953     if (uri) {
1954       GChecksum *cs;
1955
1956       /* And then generate an SHA256 sum of the URI */
1957       cs = g_checksum_new (G_CHECKSUM_SHA256);
1958       g_checksum_update (cs, (const guchar *) uri, strlen (uri));
1959       g_free (uri);
1960       upstream_id = g_strdup (g_checksum_get_string (cs));
1961       g_checksum_free (cs);
1962     } else {
1963       /* Just get some random number if the URI query fails */
1964       GST_FIXME_OBJECT (demux, "Creating random stream-id, consider "
1965           "implementing a deterministic way of creating a stream-id");
1966       upstream_id =
1967           g_strdup_printf ("%08x%08x%08x%08x", g_random_int (), g_random_int (),
1968           g_random_int (), g_random_int ());
1969     }
1970
1971     gst_query_unref (query);
1972   }
1973   return upstream_id;
1974 }
1975
1976 static QtDemuxStream *
1977 _create_stream (GstQTDemux * demux, guint32 track_id)
1978 {
1979   QtDemuxStream *stream;
1980   gchar *upstream_id;
1981
1982   stream = g_new0 (QtDemuxStream, 1);
1983   stream->demux = demux;
1984   stream->track_id = track_id;
1985   upstream_id = _get_upstream_id (demux);
1986   stream->stream_id = g_strdup_printf ("%s/%03u", upstream_id, track_id);
1987   g_free (upstream_id);
1988   /* new streams always need a discont */
1989   stream->discont = TRUE;
1990   /* we enable clipping for raw audio/video streams */
1991   stream->need_clip = FALSE;
1992   stream->need_process = FALSE;
1993   stream->segment_index = -1;
1994   stream->time_position = 0;
1995   stream->sample_index = -1;
1996   stream->offset_in_sample = 0;
1997   stream->new_stream = TRUE;
1998   stream->multiview_mode = GST_VIDEO_MULTIVIEW_MODE_NONE;
1999   stream->multiview_flags = GST_VIDEO_MULTIVIEW_FLAGS_NONE;
2000   stream->protected = FALSE;
2001   stream->protection_scheme_type = 0;
2002   stream->protection_scheme_version = 0;
2003   stream->protection_scheme_info = NULL;
2004   stream->n_samples_moof = 0;
2005   stream->duration_moof = 0;
2006   stream->duration_last_moof = 0;
2007   stream->alignment = 1;
2008   stream->stream_tags = gst_tag_list_new_empty ();
2009   gst_tag_list_set_scope (stream->stream_tags, GST_TAG_SCOPE_STREAM);
2010   g_queue_init (&stream->protection_scheme_event_queue);
2011   stream->ref_count = 1;
2012   /* consistent default for push based mode */
2013   gst_segment_init (&stream->segment, GST_FORMAT_TIME);
2014   return stream;
2015 }
2016
2017 static gboolean
2018 gst_qtdemux_setcaps (GstQTDemux * demux, GstCaps * caps)
2019 {
2020   GstStructure *structure;
2021   const gchar *variant;
2022   const GstCaps *mediacaps = NULL;
2023
2024   GST_DEBUG_OBJECT (demux, "Sink set caps: %" GST_PTR_FORMAT, caps);
2025
2026   structure = gst_caps_get_structure (caps, 0);
2027   variant = gst_structure_get_string (structure, "variant");
2028
2029   if (variant && strcmp (variant, "mss-fragmented") == 0) {
2030     QtDemuxStream *stream;
2031     const GValue *value;
2032
2033     demux->fragmented = TRUE;
2034     demux->mss_mode = TRUE;
2035
2036     if (QTDEMUX_N_STREAMS (demux) > 1) {
2037       /* can't do this, we can only renegotiate for another mss format */
2038       return FALSE;
2039     }
2040
2041     value = gst_structure_get_value (structure, "media-caps");
2042     /* create stream */
2043     if (value) {
2044       const GValue *timescale_v;
2045
2046       /* TODO update when stream changes during playback */
2047
2048       if (QTDEMUX_N_STREAMS (demux) == 0) {
2049         stream = _create_stream (demux, 1);
2050         g_ptr_array_add (demux->active_streams, stream);
2051         /* mss has no stsd/stsd entry, use id 0 as default */
2052         stream->stsd_entries_length = 1;
2053         stream->stsd_sample_description_id = stream->cur_stsd_entry_index = 0;
2054         stream->stsd_entries = g_new0 (QtDemuxStreamStsdEntry, 1);
2055       } else {
2056         stream = QTDEMUX_NTH_STREAM (demux, 0);
2057       }
2058
2059       timescale_v = gst_structure_get_value (structure, "timescale");
2060       if (timescale_v) {
2061         stream->timescale = g_value_get_uint64 (timescale_v);
2062       } else {
2063         /* default mss timescale */
2064         stream->timescale = 10000000;
2065       }
2066       demux->timescale = stream->timescale;
2067
2068       mediacaps = gst_value_get_caps (value);
2069       if (!CUR_STREAM (stream)->caps
2070           || !gst_caps_is_equal_fixed (mediacaps, CUR_STREAM (stream)->caps)) {
2071         GST_DEBUG_OBJECT (demux, "We have a new caps %" GST_PTR_FORMAT,
2072             mediacaps);
2073         stream->new_caps = TRUE;
2074       }
2075       gst_caps_replace (&CUR_STREAM (stream)->caps, (GstCaps *) mediacaps);
2076       structure = gst_caps_get_structure (mediacaps, 0);
2077       if (g_str_has_prefix (gst_structure_get_name (structure), "video")) {
2078         stream->subtype = FOURCC_vide;
2079
2080         gst_structure_get_int (structure, "width", &CUR_STREAM (stream)->width);
2081         gst_structure_get_int (structure, "height",
2082             &CUR_STREAM (stream)->height);
2083         gst_structure_get_fraction (structure, "framerate",
2084             &CUR_STREAM (stream)->fps_n, &CUR_STREAM (stream)->fps_d);
2085       } else if (g_str_has_prefix (gst_structure_get_name (structure), "audio")) {
2086         gint rate = 0;
2087         stream->subtype = FOURCC_soun;
2088         gst_structure_get_int (structure, "channels",
2089             &CUR_STREAM (stream)->n_channels);
2090         gst_structure_get_int (structure, "rate", &rate);
2091         CUR_STREAM (stream)->rate = rate;
2092       }
2093     }
2094     gst_caps_replace (&demux->media_caps, (GstCaps *) mediacaps);
2095   } else {
2096     demux->mss_mode = FALSE;
2097   }
2098
2099   return TRUE;
2100 }
2101
2102 static void
2103 gst_qtdemux_reset (GstQTDemux * qtdemux, gboolean hard)
2104 {
2105   gint i;
2106
2107   GST_DEBUG_OBJECT (qtdemux, "Resetting demux");
2108   gst_pad_stop_task (qtdemux->sinkpad);
2109
2110   if (hard || qtdemux->upstream_format_is_time) {
2111     qtdemux->state = QTDEMUX_STATE_INITIAL;
2112     qtdemux->neededbytes = 16;
2113     qtdemux->todrop = 0;
2114     qtdemux->pullbased = FALSE;
2115     qtdemux->posted_redirect = FALSE;
2116     qtdemux->first_mdat = -1;
2117     qtdemux->header_size = 0;
2118     qtdemux->mdatoffset = -1;
2119     qtdemux->restoredata_offset = -1;
2120     if (qtdemux->mdatbuffer)
2121       gst_buffer_unref (qtdemux->mdatbuffer);
2122     if (qtdemux->restoredata_buffer)
2123       gst_buffer_unref (qtdemux->restoredata_buffer);
2124     qtdemux->mdatbuffer = NULL;
2125     qtdemux->restoredata_buffer = NULL;
2126     qtdemux->mdatleft = 0;
2127     qtdemux->mdatsize = 0;
2128     if (qtdemux->comp_brands)
2129       gst_buffer_unref (qtdemux->comp_brands);
2130     qtdemux->comp_brands = NULL;
2131     qtdemux->last_moov_offset = -1;
2132     if (qtdemux->moov_node_compressed) {
2133       g_node_destroy (qtdemux->moov_node_compressed);
2134       if (qtdemux->moov_node)
2135         g_free (qtdemux->moov_node->data);
2136     }
2137     qtdemux->moov_node_compressed = NULL;
2138     if (qtdemux->moov_node)
2139       g_node_destroy (qtdemux->moov_node);
2140     qtdemux->moov_node = NULL;
2141     if (qtdemux->tag_list)
2142       gst_mini_object_unref (GST_MINI_OBJECT_CAST (qtdemux->tag_list));
2143     qtdemux->tag_list = gst_tag_list_new_empty ();
2144     gst_tag_list_set_scope (qtdemux->tag_list, GST_TAG_SCOPE_GLOBAL);
2145 #if 0
2146     if (qtdemux->element_index)
2147       gst_object_unref (qtdemux->element_index);
2148     qtdemux->element_index = NULL;
2149 #endif
2150     qtdemux->major_brand = 0;
2151     qtdemux->upstream_format_is_time = FALSE;
2152     qtdemux->upstream_seekable = FALSE;
2153     qtdemux->upstream_size = 0;
2154
2155     qtdemux->fragment_start = -1;
2156     qtdemux->fragment_start_offset = -1;
2157     qtdemux->duration = 0;
2158     qtdemux->moof_offset = 0;
2159     qtdemux->chapters_track_id = 0;
2160     qtdemux->have_group_id = FALSE;
2161     qtdemux->group_id = G_MAXUINT;
2162
2163     g_queue_foreach (&qtdemux->protection_event_queue, (GFunc) gst_event_unref,
2164         NULL);
2165     g_queue_clear (&qtdemux->protection_event_queue);
2166
2167     qtdemux->received_seek = FALSE;
2168     qtdemux->first_moof_already_parsed = FALSE;
2169   }
2170   qtdemux->offset = 0;
2171   gst_adapter_clear (qtdemux->adapter);
2172   gst_segment_init (&qtdemux->segment, GST_FORMAT_TIME);
2173   qtdemux->need_segment = TRUE;
2174
2175   if (hard) {
2176     qtdemux->segment_seqnum = GST_SEQNUM_INVALID;
2177     g_ptr_array_remove_range (qtdemux->active_streams,
2178         0, qtdemux->active_streams->len);
2179     g_ptr_array_remove_range (qtdemux->old_streams,
2180         0, qtdemux->old_streams->len);
2181     qtdemux->n_video_streams = 0;
2182     qtdemux->n_audio_streams = 0;
2183     qtdemux->n_sub_streams = 0;
2184     qtdemux->exposed = FALSE;
2185     qtdemux->fragmented = FALSE;
2186     qtdemux->mss_mode = FALSE;
2187     gst_caps_replace (&qtdemux->media_caps, NULL);
2188     qtdemux->timescale = 0;
2189     qtdemux->got_moov = FALSE;
2190     qtdemux->cenc_aux_info_offset = 0;
2191     qtdemux->cenc_aux_info_sizes = NULL;
2192     qtdemux->cenc_aux_sample_count = 0;
2193     if (qtdemux->protection_system_ids) {
2194       g_ptr_array_free (qtdemux->protection_system_ids, TRUE);
2195       qtdemux->protection_system_ids = NULL;
2196     }
2197     qtdemux->streams_aware = GST_OBJECT_PARENT (qtdemux)
2198         && GST_OBJECT_FLAG_IS_SET (GST_OBJECT_PARENT (qtdemux),
2199         GST_BIN_FLAG_STREAMS_AWARE);
2200
2201     if (qtdemux->preferred_protection_system_id) {
2202       g_free (qtdemux->preferred_protection_system_id);
2203       qtdemux->preferred_protection_system_id = NULL;
2204     }
2205   } else if (qtdemux->mss_mode) {
2206     gst_flow_combiner_reset (qtdemux->flowcombiner);
2207     g_ptr_array_foreach (qtdemux->active_streams,
2208         (GFunc) gst_qtdemux_stream_clear, NULL);
2209   } else {
2210     gst_flow_combiner_reset (qtdemux->flowcombiner);
2211     for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
2212       QtDemuxStream *stream = QTDEMUX_NTH_STREAM (qtdemux, i);
2213       stream->sent_eos = FALSE;
2214       stream->time_position = 0;
2215       stream->accumulated_base = 0;
2216     }
2217   }
2218 }
2219
2220
2221 /* Maps the @segment to the qt edts internal segments and pushes
2222  * the correspnding segment event.
2223  *
2224  * If it ends up being at a empty segment, a gap will be pushed and the next
2225  * edts segment will be activated in sequence.
2226  *
2227  * To be used in push-mode only */
2228 static void
2229 gst_qtdemux_map_and_push_segments (GstQTDemux * qtdemux, GstSegment * segment)
2230 {
2231   gint i, iter;
2232
2233   for (iter = 0; iter < QTDEMUX_N_STREAMS (qtdemux); iter++) {
2234     QtDemuxStream *stream = QTDEMUX_NTH_STREAM (qtdemux, iter);
2235
2236     stream->time_position = segment->start;
2237
2238     /* in push mode we should be guaranteed that we will have empty segments
2239      * at the beginning and then one segment after, other scenarios are not
2240      * supported and are discarded when parsing the edts */
2241     for (i = 0; i < stream->n_segments; i++) {
2242       if (stream->segments[i].stop_time > segment->start) {
2243         /* push the empty segment and move to the next one */
2244         gst_qtdemux_activate_segment (qtdemux, stream, i,
2245             stream->time_position);
2246         if (QTSEGMENT_IS_EMPTY (&stream->segments[i])) {
2247           gst_qtdemux_send_gap_for_segment (qtdemux, stream, i,
2248               stream->time_position);
2249
2250           /* accumulate previous segments */
2251           if (GST_CLOCK_TIME_IS_VALID (stream->segment.stop))
2252             stream->accumulated_base +=
2253                 (stream->segment.stop -
2254                 stream->segment.start) / ABS (stream->segment.rate);
2255           continue;
2256         }
2257
2258         g_assert (i == stream->n_segments - 1);
2259       }
2260     }
2261   }
2262 }
2263
2264 static void
2265 gst_qtdemux_stream_concat (GstQTDemux * qtdemux, GPtrArray * dest,
2266     GPtrArray * src)
2267 {
2268   guint i;
2269   guint len;
2270
2271   len = src->len;
2272
2273   if (len == 0)
2274     return;
2275
2276   for (i = 0; i < len; i++) {
2277     QtDemuxStream *stream = g_ptr_array_index (src, i);
2278
2279 #ifndef GST_DISABLE_GST_DEBUG
2280     GST_DEBUG_OBJECT (qtdemux, "Move stream %p (stream-id %s) to %p",
2281         stream, GST_STR_NULL (stream->stream_id), dest);
2282 #endif
2283     g_ptr_array_add (dest, gst_qtdemux_stream_ref (stream));
2284   }
2285
2286   g_ptr_array_remove_range (src, 0, len);
2287 }
2288
2289 static gboolean
2290 gst_qtdemux_handle_sink_event (GstPad * sinkpad, GstObject * parent,
2291     GstEvent * event)
2292 {
2293   GstQTDemux *demux = GST_QTDEMUX (parent);
2294   gboolean res = TRUE;
2295
2296   GST_LOG_OBJECT (demux, "handling %s event", GST_EVENT_TYPE_NAME (event));
2297
2298   switch (GST_EVENT_TYPE (event)) {
2299     case GST_EVENT_SEGMENT:
2300     {
2301       gint64 offset = 0;
2302       QtDemuxStream *stream;
2303       gint idx;
2304       GstSegment segment;
2305
2306       /* some debug output */
2307       gst_event_copy_segment (event, &segment);
2308       GST_DEBUG_OBJECT (demux, "received newsegment %" GST_SEGMENT_FORMAT,
2309           &segment);
2310
2311       if (segment.format == GST_FORMAT_TIME) {
2312         demux->upstream_format_is_time = TRUE;
2313         demux->segment_seqnum = gst_event_get_seqnum (event);
2314       } else {
2315         GST_DEBUG_OBJECT (demux, "Not storing upstream newsegment, "
2316             "not in time format");
2317
2318         /* chain will send initial newsegment after pads have been added */
2319         if (demux->state != QTDEMUX_STATE_MOVIE || !QTDEMUX_N_STREAMS (demux)) {
2320           GST_DEBUG_OBJECT (demux, "still starting, eating event");
2321           goto exit;
2322         }
2323       }
2324
2325       /* check if this matches a time seek we received previously
2326        * FIXME for backwards compatibility reasons we use the
2327        * seek_offset here to compare. In the future we might want to
2328        * change this to use the seqnum as it uniquely should identify
2329        * the segment that corresponds to the seek. */
2330       GST_DEBUG_OBJECT (demux, "Stored seek offset: %" G_GINT64_FORMAT
2331           ", received segment offset %" G_GINT64_FORMAT,
2332           demux->seek_offset, segment.start);
2333       if (segment.format == GST_FORMAT_BYTES
2334           && demux->seek_offset == segment.start) {
2335         GST_OBJECT_LOCK (demux);
2336         offset = segment.start;
2337
2338         segment.format = GST_FORMAT_TIME;
2339         segment.start = demux->push_seek_start;
2340         segment.stop = demux->push_seek_stop;
2341         GST_DEBUG_OBJECT (demux, "Replaced segment with stored seek "
2342             "segment %" GST_TIME_FORMAT " - %" GST_TIME_FORMAT,
2343             GST_TIME_ARGS (segment.start), GST_TIME_ARGS (segment.stop));
2344         GST_OBJECT_UNLOCK (demux);
2345       }
2346
2347       /* we only expect a BYTE segment, e.g. following a seek */
2348       if (segment.format == GST_FORMAT_BYTES) {
2349         if (GST_CLOCK_TIME_IS_VALID (segment.start)) {
2350           offset = segment.start;
2351
2352           gst_qtdemux_find_sample (demux, segment.start, TRUE, FALSE, NULL,
2353               NULL, (gint64 *) & segment.start);
2354           if ((gint64) segment.start < 0)
2355             segment.start = 0;
2356         }
2357         if (GST_CLOCK_TIME_IS_VALID (segment.stop)) {
2358           gst_qtdemux_find_sample (demux, segment.stop, FALSE, FALSE, NULL,
2359               NULL, (gint64 *) & segment.stop);
2360           /* keyframe seeking should already arrange for start >= stop,
2361            * but make sure in other rare cases */
2362           segment.stop = MAX (segment.stop, segment.start);
2363         }
2364       } else if (segment.format == GST_FORMAT_TIME) {
2365         /* push all data on the adapter before starting this
2366          * new segment */
2367         gst_qtdemux_process_adapter (demux, TRUE);
2368       } else {
2369         GST_DEBUG_OBJECT (demux, "unsupported segment format, ignoring");
2370         goto exit;
2371       }
2372
2373       /* We shouldn't modify upstream driven TIME FORMAT segment */
2374       if (!demux->upstream_format_is_time) {
2375         /* accept upstream's notion of segment and distribute along */
2376         segment.format = GST_FORMAT_TIME;
2377         segment.position = segment.time = segment.start;
2378         segment.duration = demux->segment.duration;
2379         segment.base = gst_segment_to_running_time (&demux->segment,
2380             GST_FORMAT_TIME, demux->segment.position);
2381       }
2382
2383       gst_segment_copy_into (&segment, &demux->segment);
2384       GST_DEBUG_OBJECT (demux, "Pushing newseg %" GST_SEGMENT_FORMAT, &segment);
2385
2386       /* map segment to internal qt segments and push on each stream */
2387       if (QTDEMUX_N_STREAMS (demux)) {
2388         demux->need_segment = TRUE;
2389         gst_qtdemux_check_send_pending_segment (demux);
2390       }
2391
2392       /* clear leftover in current segment, if any */
2393       gst_adapter_clear (demux->adapter);
2394
2395       /* set up streaming thread */
2396       demux->offset = offset;
2397       if (demux->upstream_format_is_time) {
2398         GST_DEBUG_OBJECT (demux, "Upstream is driving in time format, "
2399             "set values to restart reading from a new atom");
2400         demux->neededbytes = 16;
2401         demux->todrop = 0;
2402       } else {
2403         gst_qtdemux_find_sample (demux, offset, TRUE, TRUE, &stream, &idx,
2404             NULL);
2405         if (stream) {
2406           demux->todrop = stream->samples[idx].offset - offset;
2407           demux->neededbytes = demux->todrop + stream->samples[idx].size;
2408         } else {
2409           /* set up for EOS */
2410           demux->neededbytes = -1;
2411           demux->todrop = 0;
2412         }
2413       }
2414     exit:
2415       gst_event_unref (event);
2416       res = TRUE;
2417       goto drop;
2418     }
2419     case GST_EVENT_FLUSH_START:
2420     {
2421       if (gst_event_get_seqnum (event) == demux->offset_seek_seqnum) {
2422         gst_event_unref (event);
2423         goto drop;
2424       }
2425       QTDEMUX_EXPOSE_LOCK (demux);
2426       res = gst_pad_event_default (demux->sinkpad, parent, event);
2427       QTDEMUX_EXPOSE_UNLOCK (demux);
2428       goto drop;
2429     }
2430     case GST_EVENT_FLUSH_STOP:
2431     {
2432       guint64 dur;
2433
2434       dur = demux->segment.duration;
2435       gst_qtdemux_reset (demux, FALSE);
2436       demux->segment.duration = dur;
2437
2438       if (gst_event_get_seqnum (event) == demux->offset_seek_seqnum) {
2439         gst_event_unref (event);
2440         goto drop;
2441       }
2442       break;
2443     }
2444     case GST_EVENT_EOS:
2445       /* If we are in push mode, and get an EOS before we've seen any streams,
2446        * then error out - we have nowhere to send the EOS */
2447       if (!demux->pullbased) {
2448         gint i;
2449         gboolean has_valid_stream = FALSE;
2450         for (i = 0; i < QTDEMUX_N_STREAMS (demux); i++) {
2451           if (QTDEMUX_NTH_STREAM (demux, i)->pad != NULL) {
2452             has_valid_stream = TRUE;
2453             break;
2454           }
2455         }
2456         if (!has_valid_stream)
2457           gst_qtdemux_post_no_playable_stream_error (demux);
2458         else {
2459           GST_DEBUG_OBJECT (demux, "Data still available after EOS: %u",
2460               (guint) gst_adapter_available (demux->adapter));
2461           if (gst_qtdemux_process_adapter (demux, TRUE) != GST_FLOW_OK) {
2462             res = FALSE;
2463           }
2464         }
2465       }
2466       break;
2467     case GST_EVENT_CAPS:{
2468       GstCaps *caps = NULL;
2469
2470       gst_event_parse_caps (event, &caps);
2471       gst_qtdemux_setcaps (demux, caps);
2472       res = TRUE;
2473       gst_event_unref (event);
2474       goto drop;
2475     }
2476     case GST_EVENT_PROTECTION:
2477     {
2478       const gchar *system_id = NULL;
2479
2480       gst_event_parse_protection (event, &system_id, NULL, NULL);
2481       GST_DEBUG_OBJECT (demux, "Received protection event for system ID %s",
2482           system_id);
2483       gst_qtdemux_append_protection_system_id (demux, system_id);
2484       /* save the event for later, for source pads that have not been created */
2485       g_queue_push_tail (&demux->protection_event_queue, gst_event_ref (event));
2486       /* send it to all pads that already exist */
2487       gst_qtdemux_push_event (demux, event);
2488       res = TRUE;
2489       goto drop;
2490     }
2491     case GST_EVENT_STREAM_START:
2492     {
2493       res = TRUE;
2494       gst_event_unref (event);
2495
2496       /* Drain all the buffers */
2497       gst_qtdemux_process_adapter (demux, TRUE);
2498       gst_qtdemux_reset (demux, FALSE);
2499       /* We expect new moov box after new stream-start event */
2500       if (demux->exposed) {
2501         gst_qtdemux_stream_concat (demux,
2502             demux->old_streams, demux->active_streams);
2503       }
2504
2505       goto drop;
2506     }
2507     default:
2508       break;
2509   }
2510
2511   res = gst_pad_event_default (demux->sinkpad, parent, event) & res;
2512
2513 drop:
2514   return res;
2515 }
2516
2517 static gboolean
2518 gst_qtdemux_handle_sink_query (GstPad * pad, GstObject * parent,
2519     GstQuery * query)
2520 {
2521   GstQTDemux *demux = GST_QTDEMUX (parent);
2522   gboolean res = FALSE;
2523
2524   switch (GST_QUERY_TYPE (query)) {
2525     case GST_QUERY_BITRATE:
2526     {
2527       GstClockTime duration;
2528
2529       /* populate demux->upstream_size if not done yet */
2530       gst_qtdemux_check_seekability (demux);
2531
2532       if (demux->upstream_size != -1
2533           && gst_qtdemux_get_duration (demux, &duration)) {
2534         guint bitrate =
2535             gst_util_uint64_scale (8 * demux->upstream_size, GST_SECOND,
2536             duration);
2537
2538         GST_LOG_OBJECT (demux, "bitrate query byte length: %" G_GUINT64_FORMAT
2539             " duration %" GST_TIME_FORMAT " resulting a bitrate of %u",
2540             demux->upstream_size, GST_TIME_ARGS (duration), bitrate);
2541
2542         /* TODO: better results based on ranges/index tables */
2543         gst_query_set_bitrate (query, bitrate);
2544         res = TRUE;
2545       }
2546       break;
2547     }
2548     default:
2549       res = gst_pad_query_default (pad, (GstObject *) demux, query);
2550       break;
2551   }
2552
2553   return res;
2554 }
2555
2556
2557 #if 0
2558 static void
2559 gst_qtdemux_set_index (GstElement * element, GstIndex * index)
2560 {
2561   GstQTDemux *demux = GST_QTDEMUX (element);
2562
2563   GST_OBJECT_LOCK (demux);
2564   if (demux->element_index)
2565     gst_object_unref (demux->element_index);
2566   if (index) {
2567     demux->element_index = gst_object_ref (index);
2568   } else {
2569     demux->element_index = NULL;
2570   }
2571   GST_OBJECT_UNLOCK (demux);
2572   /* object lock might be taken again */
2573   if (index)
2574     gst_index_get_writer_id (index, GST_OBJECT (element), &demux->index_id);
2575   GST_DEBUG_OBJECT (demux, "Set index %" GST_PTR_FORMAT "for writer id %d",
2576       demux->element_index, demux->index_id);
2577 }
2578
2579 static GstIndex *
2580 gst_qtdemux_get_index (GstElement * element)
2581 {
2582   GstIndex *result = NULL;
2583   GstQTDemux *demux = GST_QTDEMUX (element);
2584
2585   GST_OBJECT_LOCK (demux);
2586   if (demux->element_index)
2587     result = gst_object_ref (demux->element_index);
2588   GST_OBJECT_UNLOCK (demux);
2589
2590   GST_DEBUG_OBJECT (demux, "Returning index %" GST_PTR_FORMAT, result);
2591
2592   return result;
2593 }
2594 #endif
2595
2596 static void
2597 gst_qtdemux_stbl_free (QtDemuxStream * stream)
2598 {
2599   g_free ((gpointer) stream->stco.data);
2600   stream->stco.data = NULL;
2601   g_free ((gpointer) stream->stsz.data);
2602   stream->stsz.data = NULL;
2603   g_free ((gpointer) stream->stsc.data);
2604   stream->stsc.data = NULL;
2605   g_free ((gpointer) stream->stts.data);
2606   stream->stts.data = NULL;
2607   g_free ((gpointer) stream->stss.data);
2608   stream->stss.data = NULL;
2609   g_free ((gpointer) stream->stps.data);
2610   stream->stps.data = NULL;
2611   g_free ((gpointer) stream->ctts.data);
2612   stream->ctts.data = NULL;
2613 }
2614
2615 static void
2616 gst_qtdemux_stream_flush_segments_data (QtDemuxStream * stream)
2617 {
2618   g_free (stream->segments);
2619   stream->segments = NULL;
2620   stream->segment_index = -1;
2621   stream->accumulated_base = 0;
2622 }
2623
2624 static void
2625 gst_qtdemux_stream_flush_samples_data (QtDemuxStream * stream)
2626 {
2627   g_free (stream->samples);
2628   stream->samples = NULL;
2629   gst_qtdemux_stbl_free (stream);
2630
2631   /* fragments */
2632   g_free (stream->ra_entries);
2633   stream->ra_entries = NULL;
2634   stream->n_ra_entries = 0;
2635
2636   stream->sample_index = -1;
2637   stream->stbl_index = -1;
2638   stream->n_samples = 0;
2639   stream->time_position = 0;
2640
2641   stream->n_samples_moof = 0;
2642   stream->duration_moof = 0;
2643   stream->duration_last_moof = 0;
2644 }
2645
2646 static void
2647 gst_qtdemux_stream_clear (QtDemuxStream * stream)
2648 {
2649   gint i;
2650   if (stream->allocator)
2651     gst_object_unref (stream->allocator);
2652   while (stream->buffers) {
2653     gst_buffer_unref (GST_BUFFER_CAST (stream->buffers->data));
2654     stream->buffers = g_slist_delete_link (stream->buffers, stream->buffers);
2655   }
2656   for (i = 0; i < stream->stsd_entries_length; i++) {
2657     QtDemuxStreamStsdEntry *entry = &stream->stsd_entries[i];
2658     if (entry->rgb8_palette) {
2659       gst_memory_unref (entry->rgb8_palette);
2660       entry->rgb8_palette = NULL;
2661     }
2662     entry->sparse = FALSE;
2663   }
2664
2665   if (stream->stream_tags)
2666     gst_tag_list_unref (stream->stream_tags);
2667
2668   stream->stream_tags = gst_tag_list_new_empty ();
2669   gst_tag_list_set_scope (stream->stream_tags, GST_TAG_SCOPE_STREAM);
2670   g_free (stream->redirect_uri);
2671   stream->redirect_uri = NULL;
2672   stream->sent_eos = FALSE;
2673   stream->protected = FALSE;
2674   if (stream->protection_scheme_info) {
2675     if (stream->protection_scheme_type == FOURCC_cenc) {
2676       QtDemuxCencSampleSetInfo *info =
2677           (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
2678       if (info->default_properties)
2679         gst_structure_free (info->default_properties);
2680       if (info->crypto_info)
2681         g_ptr_array_free (info->crypto_info, TRUE);
2682     }
2683     g_free (stream->protection_scheme_info);
2684     stream->protection_scheme_info = NULL;
2685   }
2686   stream->protection_scheme_type = 0;
2687   stream->protection_scheme_version = 0;
2688   g_queue_foreach (&stream->protection_scheme_event_queue,
2689       (GFunc) gst_event_unref, NULL);
2690   g_queue_clear (&stream->protection_scheme_event_queue);
2691   gst_qtdemux_stream_flush_segments_data (stream);
2692   gst_qtdemux_stream_flush_samples_data (stream);
2693 }
2694
2695 static void
2696 gst_qtdemux_stream_reset (QtDemuxStream * stream)
2697 {
2698   gint i;
2699   gst_qtdemux_stream_clear (stream);
2700   for (i = 0; i < stream->stsd_entries_length; i++) {
2701     QtDemuxStreamStsdEntry *entry = &stream->stsd_entries[i];
2702     if (entry->caps) {
2703       gst_caps_unref (entry->caps);
2704       entry->caps = NULL;
2705     }
2706   }
2707   g_free (stream->stsd_entries);
2708   stream->stsd_entries = NULL;
2709   stream->stsd_entries_length = 0;
2710 }
2711
2712 static QtDemuxStream *
2713 gst_qtdemux_stream_ref (QtDemuxStream * stream)
2714 {
2715   g_atomic_int_add (&stream->ref_count, 1);
2716
2717   return stream;
2718 }
2719
2720 static void
2721 gst_qtdemux_stream_unref (QtDemuxStream * stream)
2722 {
2723   if (g_atomic_int_dec_and_test (&stream->ref_count)) {
2724     gst_qtdemux_stream_reset (stream);
2725     gst_tag_list_unref (stream->stream_tags);
2726     if (stream->pad) {
2727       GstQTDemux *demux = stream->demux;
2728       gst_element_remove_pad (GST_ELEMENT_CAST (demux), stream->pad);
2729       gst_flow_combiner_remove_pad (demux->flowcombiner, stream->pad);
2730     }
2731     g_free (stream->stream_id);
2732     g_free (stream);
2733   }
2734 }
2735
2736 static GstStateChangeReturn
2737 gst_qtdemux_change_state (GstElement * element, GstStateChange transition)
2738 {
2739   GstQTDemux *qtdemux = GST_QTDEMUX (element);
2740   GstStateChangeReturn result = GST_STATE_CHANGE_FAILURE;
2741
2742   switch (transition) {
2743     case GST_STATE_CHANGE_READY_TO_PAUSED:
2744       gst_qtdemux_reset (qtdemux, TRUE);
2745       break;
2746     default:
2747       break;
2748   }
2749
2750   result = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
2751
2752   switch (transition) {
2753     case GST_STATE_CHANGE_PAUSED_TO_READY:{
2754       gst_qtdemux_reset (qtdemux, TRUE);
2755       break;
2756     }
2757     default:
2758       break;
2759   }
2760
2761   return result;
2762 }
2763
2764 static void
2765 gst_qtdemux_set_context (GstElement * element, GstContext * context)
2766 {
2767   GstQTDemux *qtdemux = GST_QTDEMUX (element);
2768
2769   g_return_if_fail (GST_IS_CONTEXT (context));
2770
2771   if (gst_context_has_context_type (context,
2772           "drm-preferred-decryption-system-id")) {
2773     const GstStructure *s;
2774
2775     s = gst_context_get_structure (context);
2776     g_free (qtdemux->preferred_protection_system_id);
2777     qtdemux->preferred_protection_system_id =
2778         g_strdup (gst_structure_get_string (s, "decryption-system-id"));
2779     GST_DEBUG_OBJECT (element, "set preferred decryption system to %s",
2780         qtdemux->preferred_protection_system_id);
2781   }
2782
2783   GST_ELEMENT_CLASS (parent_class)->set_context (element, context);
2784 }
2785
2786 static void
2787 qtdemux_parse_ftyp (GstQTDemux * qtdemux, const guint8 * buffer, gint length)
2788 {
2789   /* counts as header data */
2790   qtdemux->header_size += length;
2791
2792   /* only consider at least a sufficiently complete ftyp atom */
2793   if (length >= 20) {
2794     GstBuffer *buf;
2795
2796     qtdemux->major_brand = QT_FOURCC (buffer + 8);
2797     GST_DEBUG_OBJECT (qtdemux, "major brand: %" GST_FOURCC_FORMAT,
2798         GST_FOURCC_ARGS (qtdemux->major_brand));
2799     if (qtdemux->comp_brands)
2800       gst_buffer_unref (qtdemux->comp_brands);
2801     buf = qtdemux->comp_brands = gst_buffer_new_and_alloc (length - 16);
2802     gst_buffer_fill (buf, 0, buffer + 16, length - 16);
2803   }
2804 }
2805
2806 static void
2807 qtdemux_handle_xmp_taglist (GstQTDemux * qtdemux, GstTagList * taglist,
2808     GstTagList * xmptaglist)
2809 {
2810   /* Strip out bogus fields */
2811   if (xmptaglist) {
2812     if (gst_tag_list_get_scope (taglist) == GST_TAG_SCOPE_GLOBAL) {
2813       gst_tag_list_remove_tag (xmptaglist, GST_TAG_VIDEO_CODEC);
2814       gst_tag_list_remove_tag (xmptaglist, GST_TAG_AUDIO_CODEC);
2815     } else {
2816       gst_tag_list_remove_tag (xmptaglist, GST_TAG_CONTAINER_FORMAT);
2817     }
2818
2819     GST_DEBUG_OBJECT (qtdemux, "Found XMP tags %" GST_PTR_FORMAT, xmptaglist);
2820
2821     /* prioritize native tags using _KEEP mode */
2822     gst_tag_list_insert (taglist, xmptaglist, GST_TAG_MERGE_KEEP);
2823     gst_tag_list_unref (xmptaglist);
2824   }
2825 }
2826
2827 static void
2828 qtdemux_update_default_sample_encryption_settings (GstQTDemux * qtdemux,
2829     QtDemuxCencSampleSetInfo * info, guint32 is_encrypted, guint8 iv_size,
2830     const guint8 * kid)
2831 {
2832   GstBuffer *kid_buf = gst_buffer_new_allocate (NULL, 16, NULL);
2833   gst_buffer_fill (kid_buf, 0, kid, 16);
2834   if (info->default_properties)
2835     gst_structure_free (info->default_properties);
2836   info->default_properties =
2837       gst_structure_new ("application/x-cenc",
2838       "iv_size", G_TYPE_UINT, iv_size,
2839       "encrypted", G_TYPE_BOOLEAN, (is_encrypted == 1),
2840       "kid", GST_TYPE_BUFFER, kid_buf, NULL);
2841   GST_DEBUG_OBJECT (qtdemux, "default sample properties: "
2842       "is_encrypted=%u, iv_size=%u", is_encrypted, iv_size);
2843   gst_buffer_unref (kid_buf);
2844 }
2845
2846 static gboolean
2847 qtdemux_update_default_piff_encryption_settings (GstQTDemux * qtdemux,
2848     QtDemuxCencSampleSetInfo * info, GstByteReader * br)
2849 {
2850   guint32 algorithm_id = 0;
2851   const guint8 *kid;
2852   gboolean is_encrypted = TRUE;
2853   guint8 iv_size = 8;
2854
2855   if (!gst_byte_reader_get_uint24_le (br, &algorithm_id)) {
2856     GST_ERROR_OBJECT (qtdemux, "Error getting box's algorithm ID field");
2857     return FALSE;
2858   }
2859
2860   algorithm_id >>= 8;
2861   if (algorithm_id == 0) {
2862     is_encrypted = FALSE;
2863   } else if (algorithm_id == 1) {
2864     GST_DEBUG_OBJECT (qtdemux, "AES 128-bits CTR encrypted stream");
2865   } else if (algorithm_id == 2) {
2866     GST_DEBUG_OBJECT (qtdemux, "AES 128-bits CBC encrypted stream");
2867   }
2868
2869   if (!gst_byte_reader_get_uint8 (br, &iv_size))
2870     return FALSE;
2871
2872   if (!gst_byte_reader_get_data (br, 16, &kid))
2873     return FALSE;
2874
2875   qtdemux_update_default_sample_encryption_settings (qtdemux, info,
2876       is_encrypted, iv_size, kid);
2877   gst_structure_set (info->default_properties, "piff_algorithm_id",
2878       G_TYPE_UINT, algorithm_id, NULL);
2879   return TRUE;
2880 }
2881
2882
2883 static void
2884 qtdemux_parse_piff (GstQTDemux * qtdemux, const guint8 * buffer, gint length,
2885     guint offset)
2886 {
2887   GstByteReader br;
2888   guint8 version;
2889   guint32 flags = 0;
2890   guint i;
2891   guint iv_size = 8;
2892   QtDemuxStream *stream;
2893   GstStructure *structure;
2894   QtDemuxCencSampleSetInfo *ss_info = NULL;
2895   const gchar *system_id;
2896   gboolean uses_sub_sample_encryption = FALSE;
2897   guint32 sample_count;
2898
2899   if (QTDEMUX_N_STREAMS (qtdemux) == 0)
2900     return;
2901
2902   stream = QTDEMUX_NTH_STREAM (qtdemux, 0);
2903
2904   structure = gst_caps_get_structure (CUR_STREAM (stream)->caps, 0);
2905   if (!gst_structure_has_name (structure, "application/x-cenc")) {
2906     GST_WARNING_OBJECT (qtdemux,
2907         "Attempting PIFF box parsing on an unencrypted stream.");
2908     return;
2909   }
2910
2911   gst_structure_get (structure, GST_PROTECTION_SYSTEM_ID_CAPS_FIELD,
2912       G_TYPE_STRING, &system_id, NULL);
2913   gst_qtdemux_append_protection_system_id (qtdemux, system_id);
2914
2915   stream->protected = TRUE;
2916   stream->protection_scheme_type = FOURCC_cenc;
2917
2918   if (!stream->protection_scheme_info)
2919     stream->protection_scheme_info = g_new0 (QtDemuxCencSampleSetInfo, 1);
2920
2921   ss_info = (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
2922   if (!ss_info->default_properties) {
2923     ss_info->default_properties =
2924         gst_structure_new ("application/x-cenc",
2925         "iv_size", G_TYPE_UINT, iv_size, "encrypted", G_TYPE_BOOLEAN, TRUE,
2926         NULL);
2927
2928   }
2929
2930   if (ss_info->crypto_info) {
2931     GST_LOG_OBJECT (qtdemux, "unreffing existing crypto_info");
2932     g_ptr_array_free (ss_info->crypto_info, TRUE);
2933     ss_info->crypto_info = NULL;
2934   }
2935
2936   /* skip UUID */
2937   gst_byte_reader_init (&br, buffer + offset + 16, length - offset - 16);
2938
2939   if (!gst_byte_reader_get_uint8 (&br, &version)) {
2940     GST_ERROR_OBJECT (qtdemux, "Error getting box's version field");
2941     return;
2942   }
2943
2944   if (!gst_byte_reader_get_uint24_be (&br, &flags)) {
2945     GST_ERROR_OBJECT (qtdemux, "Error getting box's flags field");
2946     return;
2947   }
2948
2949   if ((flags & 0x000001)) {
2950     if (!qtdemux_update_default_piff_encryption_settings (qtdemux, ss_info,
2951             &br))
2952       return;
2953   } else if ((flags & 0x000002)) {
2954     uses_sub_sample_encryption = TRUE;
2955   }
2956
2957   if (!gst_structure_get_uint (ss_info->default_properties, "iv_size",
2958           &iv_size)) {
2959     GST_ERROR_OBJECT (qtdemux, "Error getting encryption IV size field");
2960     return;
2961   }
2962
2963   if (!gst_byte_reader_get_uint32_be (&br, &sample_count)) {
2964     GST_ERROR_OBJECT (qtdemux, "Error getting box's sample count field");
2965     return;
2966   }
2967
2968   ss_info->crypto_info =
2969       g_ptr_array_new_full (sample_count,
2970       (GDestroyNotify) qtdemux_gst_structure_free);
2971
2972   for (i = 0; i < sample_count; ++i) {
2973     GstStructure *properties;
2974     guint8 *data;
2975     GstBuffer *buf;
2976
2977     properties = qtdemux_get_cenc_sample_properties (qtdemux, stream, i);
2978     if (properties == NULL) {
2979       GST_ERROR_OBJECT (qtdemux, "failed to get properties for sample %u", i);
2980       qtdemux->cenc_aux_sample_count = i;
2981       return;
2982     }
2983
2984     if (!gst_byte_reader_dup_data (&br, iv_size, &data)) {
2985       GST_ERROR_OBJECT (qtdemux, "IV data not present for sample %u", i);
2986       gst_structure_free (properties);
2987       qtdemux->cenc_aux_sample_count = i;
2988       return;
2989     }
2990     buf = gst_buffer_new_wrapped (data, iv_size);
2991     gst_structure_set (properties, "iv", GST_TYPE_BUFFER, buf, NULL);
2992     gst_buffer_unref (buf);
2993
2994     if (uses_sub_sample_encryption) {
2995       guint16 n_subsamples;
2996       const GValue *kid_buf_value;
2997
2998       if (!gst_byte_reader_get_uint16_be (&br, &n_subsamples)
2999           || n_subsamples == 0) {
3000         GST_ERROR_OBJECT (qtdemux,
3001             "failed to get subsample count for sample %u", i);
3002         gst_structure_free (properties);
3003         qtdemux->cenc_aux_sample_count = i;
3004         return;
3005       }
3006       GST_LOG_OBJECT (qtdemux, "subsample count: %u", n_subsamples);
3007       if (!gst_byte_reader_dup_data (&br, n_subsamples * 6, &data)) {
3008         GST_ERROR_OBJECT (qtdemux, "failed to get subsample data for sample %u",
3009             i);
3010         gst_structure_free (properties);
3011         qtdemux->cenc_aux_sample_count = i;
3012         return;
3013       }
3014       buf = gst_buffer_new_wrapped (data, n_subsamples * 6);
3015
3016       kid_buf_value =
3017           gst_structure_get_value (ss_info->default_properties, "kid");
3018
3019       gst_structure_set (properties,
3020           "subsample_count", G_TYPE_UINT, n_subsamples,
3021           "subsamples", GST_TYPE_BUFFER, buf, NULL);
3022       gst_structure_set_value (properties, "kid", kid_buf_value);
3023       gst_buffer_unref (buf);
3024     } else {
3025       gst_structure_set (properties, "subsample_count", G_TYPE_UINT, 0, NULL);
3026     }
3027
3028     g_ptr_array_add (ss_info->crypto_info, properties);
3029   }
3030
3031   qtdemux->cenc_aux_sample_count = sample_count;
3032 }
3033
3034 static void
3035 qtdemux_parse_uuid (GstQTDemux * qtdemux, const guint8 * buffer, gint length)
3036 {
3037   static const guint8 xmp_uuid[] = { 0xBE, 0x7A, 0xCF, 0xCB,
3038     0x97, 0xA9, 0x42, 0xE8,
3039     0x9C, 0x71, 0x99, 0x94,
3040     0x91, 0xE3, 0xAF, 0xAC
3041   };
3042   static const guint8 playready_uuid[] = {
3043     0xd0, 0x8a, 0x4f, 0x18, 0x10, 0xf3, 0x4a, 0x82,
3044     0xb6, 0xc8, 0x32, 0xd8, 0xab, 0xa1, 0x83, 0xd3
3045   };
3046
3047   static const guint8 piff_sample_encryption_uuid[] = {
3048     0xa2, 0x39, 0x4f, 0x52, 0x5a, 0x9b, 0x4f, 0x14,
3049     0xa2, 0x44, 0x6c, 0x42, 0x7c, 0x64, 0x8d, 0xf4
3050   };
3051
3052   guint offset;
3053
3054   /* counts as header data */
3055   qtdemux->header_size += length;
3056
3057   offset = (QT_UINT32 (buffer) == 0) ? 16 : 8;
3058
3059   if (length <= offset + 16) {
3060     GST_DEBUG_OBJECT (qtdemux, "uuid atom is too short, skipping");
3061     return;
3062   }
3063
3064   if (memcmp (buffer + offset, xmp_uuid, 16) == 0) {
3065     GstBuffer *buf;
3066     GstTagList *taglist;
3067
3068     buf = _gst_buffer_new_wrapped ((guint8 *) buffer + offset + 16,
3069         length - offset - 16, NULL);
3070     taglist = gst_tag_list_from_xmp_buffer (buf);
3071     gst_buffer_unref (buf);
3072
3073     /* make sure we have a usable taglist */
3074     qtdemux->tag_list = gst_tag_list_make_writable (qtdemux->tag_list);
3075
3076     qtdemux_handle_xmp_taglist (qtdemux, qtdemux->tag_list, taglist);
3077
3078   } else if (memcmp (buffer + offset, playready_uuid, 16) == 0) {
3079     int len;
3080     const gunichar2 *s_utf16;
3081     char *contents;
3082
3083     len = GST_READ_UINT16_LE (buffer + offset + 0x30);
3084     s_utf16 = (const gunichar2 *) (buffer + offset + 0x32);
3085     contents = g_utf16_to_utf8 (s_utf16, len / 2, NULL, NULL, NULL);
3086     GST_ERROR_OBJECT (qtdemux, "contents: %s", contents);
3087
3088     g_free (contents);
3089
3090     GST_ELEMENT_ERROR (qtdemux, STREAM, DECRYPT,
3091         (_("Cannot play stream because it is encrypted with PlayReady DRM.")),
3092         (NULL));
3093   } else if (memcmp (buffer + offset, piff_sample_encryption_uuid, 16) == 0) {
3094     qtdemux_parse_piff (qtdemux, buffer, length, offset);
3095   } else {
3096     GST_DEBUG_OBJECT (qtdemux, "Ignoring unknown uuid: %08x-%08x-%08x-%08x",
3097         GST_READ_UINT32_LE (buffer + offset),
3098         GST_READ_UINT32_LE (buffer + offset + 4),
3099         GST_READ_UINT32_LE (buffer + offset + 8),
3100         GST_READ_UINT32_LE (buffer + offset + 12));
3101   }
3102 }
3103
3104 static void
3105 qtdemux_parse_sidx (GstQTDemux * qtdemux, const guint8 * buffer, gint length)
3106 {
3107   GstSidxParser sidx_parser;
3108   GstIsoffParserResult res;
3109   guint consumed;
3110
3111   gst_isoff_qt_sidx_parser_init (&sidx_parser);
3112
3113   res =
3114       gst_isoff_qt_sidx_parser_add_data (&sidx_parser, buffer, length,
3115       &consumed);
3116   GST_DEBUG_OBJECT (qtdemux, "sidx parse result: %d", res);
3117   if (res == GST_ISOFF_QT_PARSER_DONE) {
3118     check_update_duration (qtdemux, sidx_parser.cumulative_pts);
3119   }
3120   gst_isoff_qt_sidx_parser_clear (&sidx_parser);
3121 }
3122
3123 /* caller verifies at least 8 bytes in buf */
3124 static void
3125 extract_initial_length_and_fourcc (const guint8 * data, guint size,
3126     guint64 * plength, guint32 * pfourcc)
3127 {
3128   guint64 length;
3129   guint32 fourcc;
3130
3131   length = QT_UINT32 (data);
3132   GST_DEBUG ("length 0x%08" G_GINT64_MODIFIER "x", length);
3133   fourcc = QT_FOURCC (data + 4);
3134   GST_DEBUG ("atom type %" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (fourcc));
3135
3136   if (length == 0) {
3137     length = G_MAXUINT64;
3138   } else if (length == 1 && size >= 16) {
3139     /* this means we have an extended size, which is the 64 bit value of
3140      * the next 8 bytes */
3141     length = QT_UINT64 (data + 8);
3142     GST_DEBUG ("length 0x%08" G_GINT64_MODIFIER "x", length);
3143   }
3144
3145   if (plength)
3146     *plength = length;
3147   if (pfourcc)
3148     *pfourcc = fourcc;
3149 }
3150
3151 static gboolean
3152 qtdemux_parse_mehd (GstQTDemux * qtdemux, GstByteReader * br)
3153 {
3154   guint32 version = 0;
3155   GstClockTime duration = 0;
3156
3157   if (!gst_byte_reader_get_uint32_be (br, &version))
3158     goto failed;
3159
3160   version >>= 24;
3161   if (version == 1) {
3162     if (!gst_byte_reader_get_uint64_be (br, &duration))
3163       goto failed;
3164   } else {
3165     guint32 dur = 0;
3166
3167     if (!gst_byte_reader_get_uint32_be (br, &dur))
3168       goto failed;
3169     duration = dur;
3170   }
3171
3172   GST_INFO_OBJECT (qtdemux, "mehd duration: %" G_GUINT64_FORMAT, duration);
3173   qtdemux->duration = duration;
3174
3175   return TRUE;
3176
3177 failed:
3178   {
3179     GST_DEBUG_OBJECT (qtdemux, "parsing mehd failed");
3180     return FALSE;
3181   }
3182 }
3183
3184 static gboolean
3185 qtdemux_parse_trex (GstQTDemux * qtdemux, QtDemuxStream * stream,
3186     guint32 * ds_duration, guint32 * ds_size, guint32 * ds_flags)
3187 {
3188   if (!stream->parsed_trex && qtdemux->moov_node) {
3189     GNode *mvex, *trex;
3190     GstByteReader trex_data;
3191
3192     mvex = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_mvex);
3193     if (mvex) {
3194       trex = qtdemux_tree_get_child_by_type_full (mvex, FOURCC_trex,
3195           &trex_data);
3196       while (trex) {
3197         guint32 id = 0, sdi = 0, dur = 0, size = 0, flags = 0;
3198
3199         /* skip version/flags */
3200         if (!gst_byte_reader_skip (&trex_data, 4))
3201           goto next;
3202         if (!gst_byte_reader_get_uint32_be (&trex_data, &id))
3203           goto next;
3204         if (id != stream->track_id)
3205           goto next;
3206         if (!gst_byte_reader_get_uint32_be (&trex_data, &sdi))
3207           goto next;
3208         if (!gst_byte_reader_get_uint32_be (&trex_data, &dur))
3209           goto next;
3210         if (!gst_byte_reader_get_uint32_be (&trex_data, &size))
3211           goto next;
3212         if (!gst_byte_reader_get_uint32_be (&trex_data, &flags))
3213           goto next;
3214
3215         GST_DEBUG_OBJECT (qtdemux, "fragment defaults for stream %d; "
3216             "duration %d,  size %d, flags 0x%x", stream->track_id,
3217             dur, size, flags);
3218
3219         stream->parsed_trex = TRUE;
3220         stream->def_sample_description_index = sdi;
3221         stream->def_sample_duration = dur;
3222         stream->def_sample_size = size;
3223         stream->def_sample_flags = flags;
3224
3225       next:
3226         /* iterate all siblings */
3227         trex = qtdemux_tree_get_sibling_by_type_full (trex, FOURCC_trex,
3228             &trex_data);
3229       }
3230     }
3231   }
3232
3233   *ds_duration = stream->def_sample_duration;
3234   *ds_size = stream->def_sample_size;
3235   *ds_flags = stream->def_sample_flags;
3236
3237   /* even then, above values are better than random ... */
3238   if (G_UNLIKELY (!stream->parsed_trex)) {
3239     GST_WARNING_OBJECT (qtdemux,
3240         "failed to find fragment defaults for stream %d", stream->track_id);
3241     return FALSE;
3242   }
3243
3244   return TRUE;
3245 }
3246
3247 /* This method should be called whenever a more accurate duration might
3248  * have been found. It will update all relevant variables if/where needed
3249  */
3250 static void
3251 check_update_duration (GstQTDemux * qtdemux, GstClockTime duration)
3252 {
3253   guint i;
3254   guint64 movdur;
3255   GstClockTime prevdur;
3256
3257   movdur = GSTTIME_TO_QTTIME (qtdemux, duration);
3258
3259   if (movdur > qtdemux->duration) {
3260     prevdur = QTTIME_TO_GSTTIME (qtdemux, qtdemux->duration);
3261     GST_DEBUG_OBJECT (qtdemux,
3262         "Updating total duration to %" GST_TIME_FORMAT " was %" GST_TIME_FORMAT,
3263         GST_TIME_ARGS (duration), GST_TIME_ARGS (prevdur));
3264     qtdemux->duration = movdur;
3265     GST_DEBUG_OBJECT (qtdemux,
3266         "qtdemux->segment.duration: %" GST_TIME_FORMAT " .stop: %"
3267         GST_TIME_FORMAT, GST_TIME_ARGS (qtdemux->segment.duration),
3268         GST_TIME_ARGS (qtdemux->segment.stop));
3269     if (qtdemux->segment.duration == prevdur) {
3270       /* If the current segment has duration/stop identical to previous duration
3271        * update them also (because they were set at that point in time with
3272        * the wrong duration */
3273       /* We convert the value *from* the timescale version to avoid rounding errors */
3274       GstClockTime fixeddur = QTTIME_TO_GSTTIME (qtdemux, movdur);
3275       GST_DEBUG_OBJECT (qtdemux, "Updated segment.duration and segment.stop");
3276       qtdemux->segment.duration = fixeddur;
3277       qtdemux->segment.stop = fixeddur;
3278     }
3279   }
3280
3281   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
3282     QtDemuxStream *stream = QTDEMUX_NTH_STREAM (qtdemux, i);
3283
3284     movdur = GSTTIME_TO_QTSTREAMTIME (stream, duration);
3285     if (movdur > stream->duration) {
3286       GST_DEBUG_OBJECT (qtdemux,
3287           "Updating stream #%d duration to %" GST_TIME_FORMAT, i,
3288           GST_TIME_ARGS (duration));
3289       stream->duration = movdur;
3290       /* internal duration tracking state has been updated above, so */
3291       /* preserve an open-ended dummy segment rather than repeatedly updating
3292        * it and spamming downstream accordingly with segment events */
3293       if (stream->dummy_segment &&
3294           GST_CLOCK_TIME_IS_VALID (stream->segments[0].duration)) {
3295         /* Update all dummy values to new duration */
3296         stream->segments[0].stop_time = duration;
3297         stream->segments[0].duration = duration;
3298         stream->segments[0].media_stop = duration;
3299
3300         /* let downstream know we possibly have a new stop time */
3301         if (stream->segment_index != -1) {
3302           GstClockTime pos;
3303
3304           if (qtdemux->segment.rate >= 0) {
3305             pos = stream->segment.start;
3306           } else {
3307             pos = stream->segment.stop;
3308           }
3309
3310           gst_qtdemux_stream_update_segment (qtdemux, stream,
3311               stream->segment_index, pos, NULL, NULL);
3312         }
3313       }
3314     }
3315   }
3316 }
3317
3318 static gboolean
3319 qtdemux_parse_trun (GstQTDemux * qtdemux, GstByteReader * trun,
3320     QtDemuxStream * stream, guint32 d_sample_duration, guint32 d_sample_size,
3321     guint32 d_sample_flags, gint64 moof_offset, gint64 moof_length,
3322     gint64 * base_offset, gint64 * running_offset, gint64 decode_ts,
3323     gboolean has_tfdt)
3324 {
3325   GstClockTime gst_ts = GST_CLOCK_TIME_NONE;
3326   guint64 timestamp;
3327   gint32 data_offset = 0;
3328   guint32 flags = 0, first_flags = 0, samples_count = 0;
3329   gint i;
3330   guint8 *data;
3331   guint entry_size, dur_offset, size_offset, flags_offset = 0, ct_offset = 0;
3332   QtDemuxSample *sample;
3333   gboolean ismv = FALSE;
3334   gint64 initial_offset;
3335
3336   GST_LOG_OBJECT (qtdemux, "parsing trun track-id %d; "
3337       "default dur %d, size %d, flags 0x%x, base offset %" G_GINT64_FORMAT ", "
3338       "decode ts %" G_GINT64_FORMAT, stream->track_id, d_sample_duration,
3339       d_sample_size, d_sample_flags, *base_offset, decode_ts);
3340
3341   if (stream->pending_seek && moof_offset < stream->pending_seek->moof_offset) {
3342     GST_INFO_OBJECT (stream->pad, "skipping trun before seek target fragment");
3343     return TRUE;
3344   }
3345
3346   /* presence of stss or not can't really tell us much,
3347    * and flags and so on tend to be marginally reliable in these files */
3348   if (stream->subtype == FOURCC_soun) {
3349     GST_DEBUG_OBJECT (qtdemux,
3350         "sound track in fragmented file; marking all keyframes");
3351     stream->all_keyframe = TRUE;
3352   }
3353
3354   if (!gst_byte_reader_skip (trun, 1) ||
3355       !gst_byte_reader_get_uint24_be (trun, &flags))
3356     goto fail;
3357
3358   if (!gst_byte_reader_get_uint32_be (trun, &samples_count))
3359     goto fail;
3360
3361   if (flags & TR_DATA_OFFSET) {
3362     /* note this is really signed */
3363     if (!gst_byte_reader_get_int32_be (trun, &data_offset))
3364       goto fail;
3365     GST_LOG_OBJECT (qtdemux, "trun data offset %d", data_offset);
3366     /* default base offset = first byte of moof */
3367     if (*base_offset == -1) {
3368       GST_LOG_OBJECT (qtdemux, "base_offset at moof");
3369       *base_offset = moof_offset;
3370     }
3371     *running_offset = *base_offset + data_offset;
3372   } else {
3373     /* if no offset at all, that would mean data starts at moof start,
3374      * which is a bit wrong and is ismv crappy way, so compensate
3375      * assuming data is in mdat following moof */
3376     if (*base_offset == -1) {
3377       *base_offset = moof_offset + moof_length + 8;
3378       GST_LOG_OBJECT (qtdemux, "base_offset assumed in mdat after moof");
3379       ismv = TRUE;
3380     }
3381     if (*running_offset == -1)
3382       *running_offset = *base_offset;
3383   }
3384
3385   GST_LOG_OBJECT (qtdemux, "running offset now %" G_GINT64_FORMAT,
3386       *running_offset);
3387   GST_LOG_OBJECT (qtdemux, "trun offset %d, flags 0x%x, entries %d",
3388       data_offset, flags, samples_count);
3389
3390   if (flags & TR_FIRST_SAMPLE_FLAGS) {
3391     if (G_UNLIKELY (flags & TR_SAMPLE_FLAGS)) {
3392       GST_DEBUG_OBJECT (qtdemux,
3393           "invalid flags; SAMPLE and FIRST_SAMPLE present, discarding latter");
3394       flags ^= TR_FIRST_SAMPLE_FLAGS;
3395     } else {
3396       if (!gst_byte_reader_get_uint32_be (trun, &first_flags))
3397         goto fail;
3398       GST_LOG_OBJECT (qtdemux, "first flags: 0x%x", first_flags);
3399     }
3400   }
3401
3402   /* FIXME ? spec says other bits should also be checked to determine
3403    * entry size (and prefix size for that matter) */
3404   entry_size = 0;
3405   dur_offset = size_offset = 0;
3406   if (flags & TR_SAMPLE_DURATION) {
3407     GST_LOG_OBJECT (qtdemux, "entry duration present");
3408     dur_offset = entry_size;
3409     entry_size += 4;
3410   }
3411   if (flags & TR_SAMPLE_SIZE) {
3412     GST_LOG_OBJECT (qtdemux, "entry size present");
3413     size_offset = entry_size;
3414     entry_size += 4;
3415   }
3416   if (flags & TR_SAMPLE_FLAGS) {
3417     GST_LOG_OBJECT (qtdemux, "entry flags present");
3418     flags_offset = entry_size;
3419     entry_size += 4;
3420   }
3421   if (flags & TR_COMPOSITION_TIME_OFFSETS) {
3422     GST_LOG_OBJECT (qtdemux, "entry ct offset present");
3423     ct_offset = entry_size;
3424     entry_size += 4;
3425   }
3426
3427   if (!qt_atom_parser_has_chunks (trun, samples_count, entry_size))
3428     goto fail;
3429   data = (guint8 *) gst_byte_reader_peek_data_unchecked (trun);
3430
3431   if (stream->n_samples + samples_count >=
3432       QTDEMUX_MAX_SAMPLE_INDEX_SIZE / sizeof (QtDemuxSample))
3433     goto index_too_big;
3434
3435   GST_DEBUG_OBJECT (qtdemux, "allocating n_samples %u * %u (%.2f MB)",
3436       stream->n_samples + samples_count, (guint) sizeof (QtDemuxSample),
3437       (stream->n_samples + samples_count) *
3438       sizeof (QtDemuxSample) / (1024.0 * 1024.0));
3439
3440   /* create a new array of samples if it's the first sample parsed */
3441   if (stream->n_samples == 0) {
3442     g_assert (stream->samples == NULL);
3443     stream->samples = g_try_new0 (QtDemuxSample, samples_count);
3444     /* or try to reallocate it with space enough to insert the new samples */
3445   } else
3446     stream->samples = g_try_renew (QtDemuxSample, stream->samples,
3447         stream->n_samples + samples_count);
3448   if (stream->samples == NULL)
3449     goto out_of_memory;
3450
3451   if (qtdemux->fragment_start != -1) {
3452     timestamp = GSTTIME_TO_QTSTREAMTIME (stream, qtdemux->fragment_start);
3453     qtdemux->fragment_start = -1;
3454   } else {
3455     if (stream->n_samples == 0) {
3456       if (decode_ts > 0) {
3457         timestamp = decode_ts;
3458       } else if (stream->pending_seek != NULL) {
3459         /* if we don't have a timestamp from a tfdt box, we'll use the one
3460          * from the mfra seek table */
3461         GST_INFO_OBJECT (stream->pad, "pending seek ts = %" GST_TIME_FORMAT,
3462             GST_TIME_ARGS (stream->pending_seek->ts));
3463
3464         /* FIXME: this is not fully correct, the timestamp refers to the random
3465          * access sample refered to in the tfra entry, which may not necessarily
3466          * be the first sample in the tfrag/trun (but hopefully/usually is) */
3467         timestamp = GSTTIME_TO_QTSTREAMTIME (stream, stream->pending_seek->ts);
3468       } else {
3469         timestamp = 0;
3470       }
3471
3472       gst_ts = QTSTREAMTIME_TO_GSTTIME (stream, timestamp);
3473       GST_INFO_OBJECT (stream->pad, "first sample ts %" GST_TIME_FORMAT,
3474           GST_TIME_ARGS (gst_ts));
3475     } else {
3476       /* subsequent fragments extend stream */
3477       timestamp =
3478           stream->samples[stream->n_samples - 1].timestamp +
3479           stream->samples[stream->n_samples - 1].duration;
3480
3481       /* If this is a GST_FORMAT_BYTES stream and there's a significant
3482        * difference (1 sec.) between decode_ts and timestamp, prefer the
3483        * former */
3484       if (has_tfdt && !qtdemux->upstream_format_is_time
3485           && ABSDIFF (decode_ts, timestamp) >
3486           MAX (stream->duration_last_moof / 2,
3487               GSTTIME_TO_QTSTREAMTIME (stream, GST_SECOND))) {
3488         GST_INFO_OBJECT (qtdemux,
3489             "decode_ts (%" GST_TIME_FORMAT ") and timestamp (%" GST_TIME_FORMAT
3490             ") are significantly different (more than %" GST_TIME_FORMAT
3491             "), using decode_ts",
3492             GST_TIME_ARGS (QTSTREAMTIME_TO_GSTTIME (stream, decode_ts)),
3493             GST_TIME_ARGS (QTSTREAMTIME_TO_GSTTIME (stream, timestamp)),
3494             GST_TIME_ARGS (QTSTREAMTIME_TO_GSTTIME (stream,
3495                     MAX (stream->duration_last_moof / 2,
3496                         GSTTIME_TO_QTSTREAMTIME (stream, GST_SECOND)))));
3497         timestamp = decode_ts;
3498       }
3499
3500       gst_ts = QTSTREAMTIME_TO_GSTTIME (stream, timestamp);
3501       GST_INFO_OBJECT (qtdemux, "first sample ts %" GST_TIME_FORMAT
3502           " (extends previous samples)", GST_TIME_ARGS (gst_ts));
3503     }
3504   }
3505
3506   initial_offset = *running_offset;
3507
3508   sample = stream->samples + stream->n_samples;
3509   for (i = 0; i < samples_count; i++) {
3510     guint32 dur, size, sflags, ct;
3511
3512     /* first read sample data */
3513     if (flags & TR_SAMPLE_DURATION) {
3514       dur = QT_UINT32 (data + dur_offset);
3515     } else {
3516       dur = d_sample_duration;
3517     }
3518     if (flags & TR_SAMPLE_SIZE) {
3519       size = QT_UINT32 (data + size_offset);
3520     } else {
3521       size = d_sample_size;
3522     }
3523     if (flags & TR_FIRST_SAMPLE_FLAGS) {
3524       if (i == 0) {
3525         sflags = first_flags;
3526       } else {
3527         sflags = d_sample_flags;
3528       }
3529     } else if (flags & TR_SAMPLE_FLAGS) {
3530       sflags = QT_UINT32 (data + flags_offset);
3531     } else {
3532       sflags = d_sample_flags;
3533     }
3534     if (flags & TR_COMPOSITION_TIME_OFFSETS) {
3535       ct = QT_UINT32 (data + ct_offset);
3536     } else {
3537       ct = 0;
3538     }
3539     data += entry_size;
3540
3541     /* fill the sample information */
3542     sample->offset = *running_offset;
3543     sample->pts_offset = ct;
3544     sample->size = size;
3545     sample->timestamp = timestamp;
3546     sample->duration = dur;
3547     /* sample-is-difference-sample */
3548     /* ismv seems to use 0x40 for keyframe, 0xc0 for non-keyframe,
3549      * now idea how it relates to bitfield other than massive LE/BE confusion */
3550     sample->keyframe = ismv ? ((sflags & 0xff) == 0x40) : !(sflags & 0x10000);
3551     *running_offset += size;
3552     timestamp += dur;
3553     stream->duration_moof += dur;
3554     sample++;
3555   }
3556
3557   /* Update total duration if needed */
3558   check_update_duration (qtdemux, QTSTREAMTIME_TO_GSTTIME (stream, timestamp));
3559
3560   /* Pre-emptively figure out size of mdat based on trun information.
3561    * If the [mdat] atom is effectivelly read, it will be replaced by the actual
3562    * size, else we will still be able to use this when dealing with gap'ed
3563    * input */
3564   qtdemux->mdatleft = *running_offset - initial_offset;
3565   qtdemux->mdatoffset = initial_offset;
3566   qtdemux->mdatsize = qtdemux->mdatleft;
3567
3568   stream->n_samples += samples_count;
3569   stream->n_samples_moof += samples_count;
3570
3571   if (stream->pending_seek != NULL)
3572     stream->pending_seek = NULL;
3573
3574   return TRUE;
3575
3576 fail:
3577   {
3578     GST_WARNING_OBJECT (qtdemux, "failed to parse trun");
3579     return FALSE;
3580   }
3581 out_of_memory:
3582   {
3583     GST_WARNING_OBJECT (qtdemux, "failed to allocate %d samples",
3584         stream->n_samples);
3585     return FALSE;
3586   }
3587 index_too_big:
3588   {
3589     GST_WARNING_OBJECT (qtdemux, "not allocating index of %d samples, would "
3590         "be larger than %uMB (broken file?)", stream->n_samples,
3591         QTDEMUX_MAX_SAMPLE_INDEX_SIZE >> 20);
3592     return FALSE;
3593   }
3594 }
3595
3596 /* find stream with @id */
3597 static inline QtDemuxStream *
3598 qtdemux_find_stream (GstQTDemux * qtdemux, guint32 id)
3599 {
3600   QtDemuxStream *stream;
3601   gint i;
3602
3603   /* check */
3604   if (G_UNLIKELY (!id)) {
3605     GST_DEBUG_OBJECT (qtdemux, "invalid track id 0");
3606     return NULL;
3607   }
3608
3609   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
3610     stream = QTDEMUX_NTH_STREAM (qtdemux, i);
3611     if (stream->track_id == id)
3612       return stream;
3613   }
3614   if (qtdemux->mss_mode) {
3615     /* mss should have only 1 stream anyway */
3616     return QTDEMUX_NTH_STREAM (qtdemux, 0);
3617   }
3618
3619   return NULL;
3620 }
3621
3622 static gboolean
3623 qtdemux_parse_mfhd (GstQTDemux * qtdemux, GstByteReader * mfhd,
3624     guint32 * fragment_number)
3625 {
3626   if (!gst_byte_reader_skip (mfhd, 4))
3627     goto fail;
3628   if (!gst_byte_reader_get_uint32_be (mfhd, fragment_number))
3629     goto fail;
3630   return TRUE;
3631 fail:
3632   {
3633     GST_WARNING_OBJECT (qtdemux, "Failed to parse mfhd atom");
3634     return FALSE;
3635   }
3636 }
3637
3638 static gboolean
3639 qtdemux_parse_tfhd (GstQTDemux * qtdemux, GstByteReader * tfhd,
3640     QtDemuxStream ** stream, guint32 * default_sample_duration,
3641     guint32 * default_sample_size, guint32 * default_sample_flags,
3642     gint64 * base_offset)
3643 {
3644   guint32 flags = 0;
3645   guint32 track_id = 0;
3646
3647   if (!gst_byte_reader_skip (tfhd, 1) ||
3648       !gst_byte_reader_get_uint24_be (tfhd, &flags))
3649     goto invalid_track;
3650
3651   if (!gst_byte_reader_get_uint32_be (tfhd, &track_id))
3652     goto invalid_track;
3653
3654   *stream = qtdemux_find_stream (qtdemux, track_id);
3655   if (G_UNLIKELY (!*stream))
3656     goto unknown_stream;
3657
3658   if (flags & TF_DEFAULT_BASE_IS_MOOF)
3659     *base_offset = qtdemux->moof_offset;
3660
3661   if (flags & TF_BASE_DATA_OFFSET)
3662     if (!gst_byte_reader_get_uint64_be (tfhd, (guint64 *) base_offset))
3663       goto invalid_track;
3664
3665   /* obtain stream defaults */
3666   qtdemux_parse_trex (qtdemux, *stream,
3667       default_sample_duration, default_sample_size, default_sample_flags);
3668
3669   (*stream)->stsd_sample_description_id =
3670       (*stream)->def_sample_description_index - 1;
3671
3672   if (flags & TF_SAMPLE_DESCRIPTION_INDEX) {
3673     guint32 sample_description_index;
3674     if (!gst_byte_reader_get_uint32_be (tfhd, &sample_description_index))
3675       goto invalid_track;
3676     (*stream)->stsd_sample_description_id = sample_description_index - 1;
3677   }
3678
3679   if (qtdemux->mss_mode) {
3680     /* mss has no stsd entry */
3681     (*stream)->stsd_sample_description_id = 0;
3682   }
3683
3684   if (flags & TF_DEFAULT_SAMPLE_DURATION)
3685     if (!gst_byte_reader_get_uint32_be (tfhd, default_sample_duration))
3686       goto invalid_track;
3687
3688   if (flags & TF_DEFAULT_SAMPLE_SIZE)
3689     if (!gst_byte_reader_get_uint32_be (tfhd, default_sample_size))
3690       goto invalid_track;
3691
3692   if (flags & TF_DEFAULT_SAMPLE_FLAGS)
3693     if (!gst_byte_reader_get_uint32_be (tfhd, default_sample_flags))
3694       goto invalid_track;
3695
3696   return TRUE;
3697
3698 invalid_track:
3699   {
3700     GST_WARNING_OBJECT (qtdemux, "invalid track fragment header");
3701     return FALSE;
3702   }
3703 unknown_stream:
3704   {
3705     GST_DEBUG_OBJECT (qtdemux, "unknown stream in tfhd");
3706     return TRUE;
3707   }
3708 }
3709
3710 static gboolean
3711 qtdemux_parse_tfdt (GstQTDemux * qtdemux, GstByteReader * br,
3712     guint64 * decode_time)
3713 {
3714   guint32 version = 0;
3715
3716   if (!gst_byte_reader_get_uint32_be (br, &version))
3717     return FALSE;
3718
3719   version >>= 24;
3720   if (version == 1) {
3721     if (!gst_byte_reader_get_uint64_be (br, decode_time))
3722       goto failed;
3723   } else {
3724     guint32 dec_time = 0;
3725     if (!gst_byte_reader_get_uint32_be (br, &dec_time))
3726       goto failed;
3727     *decode_time = dec_time;
3728   }
3729
3730   GST_INFO_OBJECT (qtdemux, "Track fragment decode time: %" G_GUINT64_FORMAT,
3731       *decode_time);
3732
3733   return TRUE;
3734
3735 failed:
3736   {
3737     GST_DEBUG_OBJECT (qtdemux, "parsing tfdt failed");
3738     return FALSE;
3739   }
3740 }
3741
3742 /* Returns a pointer to a GstStructure containing the properties of
3743  * the stream sample identified by @sample_index. The caller must unref
3744  * the returned object after use. Returns NULL if unsuccessful. */
3745 static GstStructure *
3746 qtdemux_get_cenc_sample_properties (GstQTDemux * qtdemux,
3747     QtDemuxStream * stream, guint sample_index)
3748 {
3749   QtDemuxCencSampleSetInfo *info = NULL;
3750
3751   g_return_val_if_fail (stream != NULL, NULL);
3752   g_return_val_if_fail (stream->protected, NULL);
3753   g_return_val_if_fail (stream->protection_scheme_info != NULL, NULL);
3754
3755   info = (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
3756
3757   /* Currently, cenc properties for groups of samples are not supported, so
3758    * simply return a copy of the default sample properties */
3759   return gst_structure_copy (info->default_properties);
3760 }
3761
3762 /* Parses the sizes of sample auxiliary information contained within a stream,
3763  * as given in a saiz box. Returns array of sample_count guint8 size values,
3764  * or NULL on failure */
3765 static guint8 *
3766 qtdemux_parse_saiz (GstQTDemux * qtdemux, QtDemuxStream * stream,
3767     GstByteReader * br, guint32 * sample_count)
3768 {
3769   guint32 flags = 0;
3770   guint8 *info_sizes;
3771   guint8 default_info_size;
3772
3773   g_return_val_if_fail (qtdemux != NULL, NULL);
3774   g_return_val_if_fail (stream != NULL, NULL);
3775   g_return_val_if_fail (br != NULL, NULL);
3776   g_return_val_if_fail (sample_count != NULL, NULL);
3777
3778   if (!gst_byte_reader_get_uint32_be (br, &flags))
3779     return NULL;
3780
3781   if (flags & 0x1) {
3782     /* aux_info_type and aux_info_type_parameter are ignored */
3783     if (!gst_byte_reader_skip (br, 8))
3784       return NULL;
3785   }
3786
3787   if (!gst_byte_reader_get_uint8 (br, &default_info_size))
3788     return NULL;
3789   GST_DEBUG_OBJECT (qtdemux, "default_info_size: %u", default_info_size);
3790
3791   if (!gst_byte_reader_get_uint32_be (br, sample_count))
3792     return NULL;
3793   GST_DEBUG_OBJECT (qtdemux, "sample_count: %u", *sample_count);
3794
3795
3796   if (default_info_size == 0) {
3797     if (!gst_byte_reader_dup_data (br, *sample_count, &info_sizes)) {
3798       return NULL;
3799     }
3800   } else {
3801     info_sizes = g_new (guint8, *sample_count);
3802     memset (info_sizes, default_info_size, *sample_count);
3803   }
3804
3805   return info_sizes;
3806 }
3807
3808 /* Parses the offset of sample auxiliary information contained within a stream,
3809  * as given in a saio box. Returns TRUE if successful; FALSE otherwise. */
3810 static gboolean
3811 qtdemux_parse_saio (GstQTDemux * qtdemux, QtDemuxStream * stream,
3812     GstByteReader * br, guint32 * info_type, guint32 * info_type_parameter,
3813     guint64 * offset)
3814 {
3815   guint8 version = 0;
3816   guint32 flags = 0;
3817   guint32 aux_info_type = 0;
3818   guint32 aux_info_type_parameter = 0;
3819   guint32 entry_count;
3820   guint32 off_32;
3821   guint64 off_64;
3822   const guint8 *aux_info_type_data = NULL;
3823
3824   g_return_val_if_fail (qtdemux != NULL, FALSE);
3825   g_return_val_if_fail (stream != NULL, FALSE);
3826   g_return_val_if_fail (br != NULL, FALSE);
3827   g_return_val_if_fail (offset != NULL, FALSE);
3828
3829   if (!gst_byte_reader_get_uint8 (br, &version))
3830     return FALSE;
3831
3832   if (!gst_byte_reader_get_uint24_be (br, &flags))
3833     return FALSE;
3834
3835   if (flags & 0x1) {
3836
3837     if (!gst_byte_reader_get_data (br, 4, &aux_info_type_data))
3838       return FALSE;
3839     aux_info_type = QT_FOURCC (aux_info_type_data);
3840
3841     if (!gst_byte_reader_get_uint32_be (br, &aux_info_type_parameter))
3842       return FALSE;
3843   } else if (stream->protected) {
3844     aux_info_type = stream->protection_scheme_type;
3845   } else {
3846     aux_info_type = CUR_STREAM (stream)->fourcc;
3847   }
3848
3849   if (info_type)
3850     *info_type = aux_info_type;
3851   if (info_type_parameter)
3852     *info_type_parameter = aux_info_type_parameter;
3853
3854   GST_DEBUG_OBJECT (qtdemux, "aux_info_type: '%" GST_FOURCC_FORMAT "', "
3855       "aux_info_type_parameter:  %#06x",
3856       GST_FOURCC_ARGS (aux_info_type), aux_info_type_parameter);
3857
3858   if (!gst_byte_reader_get_uint32_be (br, &entry_count))
3859     return FALSE;
3860
3861   if (entry_count != 1) {
3862     GST_ERROR_OBJECT (qtdemux, "multiple offsets are not supported");
3863     return FALSE;
3864   }
3865
3866   if (version == 0) {
3867     if (!gst_byte_reader_get_uint32_be (br, &off_32))
3868       return FALSE;
3869     *offset = (guint64) off_32;
3870   } else {
3871     if (!gst_byte_reader_get_uint64_be (br, &off_64))
3872       return FALSE;
3873     *offset = off_64;
3874   }
3875
3876   GST_DEBUG_OBJECT (qtdemux, "offset: %" G_GUINT64_FORMAT, *offset);
3877   return TRUE;
3878 }
3879
3880 static void
3881 qtdemux_gst_structure_free (GstStructure * gststructure)
3882 {
3883   if (gststructure) {
3884     gst_structure_free (gststructure);
3885   }
3886 }
3887
3888 /* Parses auxiliary information relating to samples protected using Common
3889  * Encryption (cenc); the format of this information is defined in
3890  * ISO/IEC 23001-7. Returns TRUE if successful; FALSE otherwise. */
3891 static gboolean
3892 qtdemux_parse_cenc_aux_info (GstQTDemux * qtdemux, QtDemuxStream * stream,
3893     GstByteReader * br, guint8 * info_sizes, guint32 sample_count)
3894 {
3895   QtDemuxCencSampleSetInfo *ss_info = NULL;
3896   guint8 size;
3897   gint i;
3898   GPtrArray *old_crypto_info = NULL;
3899   guint old_entries = 0;
3900
3901   g_return_val_if_fail (qtdemux != NULL, FALSE);
3902   g_return_val_if_fail (stream != NULL, FALSE);
3903   g_return_val_if_fail (br != NULL, FALSE);
3904   g_return_val_if_fail (stream->protected, FALSE);
3905   g_return_val_if_fail (stream->protection_scheme_info != NULL, FALSE);
3906
3907   ss_info = (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
3908
3909   if (ss_info->crypto_info) {
3910     old_crypto_info = ss_info->crypto_info;
3911     /* Count number of non-null entries remaining at the tail end */
3912     for (i = old_crypto_info->len - 1; i >= 0; i--) {
3913       if (g_ptr_array_index (old_crypto_info, i) == NULL)
3914         break;
3915       old_entries++;
3916     }
3917   }
3918
3919   ss_info->crypto_info =
3920       g_ptr_array_new_full (sample_count + old_entries,
3921       (GDestroyNotify) qtdemux_gst_structure_free);
3922
3923   /* We preserve old entries because we parse the next moof in advance
3924    * of consuming all samples from the previous moof, and otherwise
3925    * we'd discard the corresponding crypto info for the samples
3926    * from the previous fragment. */
3927   if (old_entries) {
3928     GST_DEBUG_OBJECT (qtdemux, "Preserving %d old crypto info entries",
3929         old_entries);
3930     for (i = old_crypto_info->len - old_entries; i < old_crypto_info->len; i++) {
3931       g_ptr_array_add (ss_info->crypto_info, g_ptr_array_index (old_crypto_info,
3932               i));
3933       g_ptr_array_index (old_crypto_info, i) = NULL;
3934     }
3935   }
3936
3937   if (old_crypto_info) {
3938     /* Everything now belongs to the new array */
3939     g_ptr_array_free (old_crypto_info, TRUE);
3940   }
3941
3942   for (i = 0; i < sample_count; ++i) {
3943     GstStructure *properties;
3944     guint16 n_subsamples = 0;
3945     guint8 *data;
3946     guint iv_size;
3947     GstBuffer *buf;
3948
3949     properties = qtdemux_get_cenc_sample_properties (qtdemux, stream, i);
3950     if (properties == NULL) {
3951       GST_ERROR_OBJECT (qtdemux, "failed to get properties for sample %u", i);
3952       return FALSE;
3953     }
3954     if (!gst_structure_get_uint (properties, "iv_size", &iv_size)) {
3955       GST_ERROR_OBJECT (qtdemux, "failed to get iv_size for sample %u", i);
3956       gst_structure_free (properties);
3957       return FALSE;
3958     }
3959     if (!gst_byte_reader_dup_data (br, iv_size, &data)) {
3960       GST_ERROR_OBJECT (qtdemux, "failed to get IV for sample %u", i);
3961       gst_structure_free (properties);
3962       return FALSE;
3963     }
3964     buf = gst_buffer_new_wrapped (data, iv_size);
3965     gst_structure_set (properties, "iv", GST_TYPE_BUFFER, buf, NULL);
3966     gst_buffer_unref (buf);
3967     size = info_sizes[i];
3968     if (size > iv_size) {
3969       if (!gst_byte_reader_get_uint16_be (br, &n_subsamples)
3970           || !(n_subsamples > 0)) {
3971         gst_structure_free (properties);
3972         GST_ERROR_OBJECT (qtdemux,
3973             "failed to get subsample count for sample %u", i);
3974         return FALSE;
3975       }
3976       GST_LOG_OBJECT (qtdemux, "subsample count: %u", n_subsamples);
3977       if (!gst_byte_reader_dup_data (br, n_subsamples * 6, &data)) {
3978         GST_ERROR_OBJECT (qtdemux, "failed to get subsample data for sample %u",
3979             i);
3980         gst_structure_free (properties);
3981         return FALSE;
3982       }
3983       buf = gst_buffer_new_wrapped (data, n_subsamples * 6);
3984       if (!buf) {
3985         gst_structure_free (properties);
3986         return FALSE;
3987       }
3988       gst_structure_set (properties,
3989           "subsample_count", G_TYPE_UINT, n_subsamples,
3990           "subsamples", GST_TYPE_BUFFER, buf, NULL);
3991       gst_buffer_unref (buf);
3992     } else {
3993       gst_structure_set (properties, "subsample_count", G_TYPE_UINT, 0, NULL);
3994     }
3995     g_ptr_array_add (ss_info->crypto_info, properties);
3996   }
3997   return TRUE;
3998 }
3999
4000 /* Converts a UUID in raw byte form to a string representation, as defined in
4001  * RFC 4122. The caller takes ownership of the returned string and is
4002  * responsible for freeing it after use. */
4003 static gchar *
4004 qtdemux_uuid_bytes_to_string (gconstpointer uuid_bytes)
4005 {
4006   const guint8 *uuid = (const guint8 *) uuid_bytes;
4007
4008   return g_strdup_printf ("%02x%02x%02x%02x-%02x%02x-%02x%02x-"
4009       "%02x%02x-%02x%02x%02x%02x%02x%02x",
4010       uuid[0], uuid[1], uuid[2], uuid[3],
4011       uuid[4], uuid[5], uuid[6], uuid[7],
4012       uuid[8], uuid[9], uuid[10], uuid[11],
4013       uuid[12], uuid[13], uuid[14], uuid[15]);
4014 }
4015
4016 /* Parses a Protection System Specific Header box (pssh), as defined in the
4017  * Common Encryption (cenc) standard (ISO/IEC 23001-7), which contains
4018  * information needed by a specific content protection system in order to
4019  * decrypt cenc-protected tracks. Returns TRUE if successful; FALSE
4020  * otherwise. */
4021 static gboolean
4022 qtdemux_parse_pssh (GstQTDemux * qtdemux, GNode * node)
4023 {
4024   gchar *sysid_string;
4025   guint32 pssh_size = QT_UINT32 (node->data);
4026   GstBuffer *pssh = NULL;
4027   GstEvent *event = NULL;
4028   guint32 parent_box_type;
4029   gint i;
4030
4031   if (G_UNLIKELY (pssh_size < 32U)) {
4032     GST_ERROR_OBJECT (qtdemux, "invalid box size");
4033     return FALSE;
4034   }
4035
4036   sysid_string =
4037       qtdemux_uuid_bytes_to_string ((const guint8 *) node->data + 12);
4038
4039   gst_qtdemux_append_protection_system_id (qtdemux, sysid_string);
4040
4041   pssh = gst_buffer_new_wrapped (g_memdup (node->data, pssh_size), pssh_size);
4042   GST_LOG_OBJECT (qtdemux, "cenc pssh size: %" G_GSIZE_FORMAT,
4043       gst_buffer_get_size (pssh));
4044
4045   parent_box_type = QT_FOURCC ((const guint8 *) node->parent->data + 4);
4046
4047   /* Push an event containing the pssh box onto the queues of all streams. */
4048   event = gst_event_new_protection (sysid_string, pssh,
4049       (parent_box_type == FOURCC_moov) ? "isobmff/moov" : "isobmff/moof");
4050   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
4051     QtDemuxStream *stream = QTDEMUX_NTH_STREAM (qtdemux, i);
4052     GST_TRACE_OBJECT (qtdemux,
4053         "adding protection event for stream %s and system %s",
4054         stream->stream_id, sysid_string);
4055     g_queue_push_tail (&stream->protection_scheme_event_queue,
4056         gst_event_ref (event));
4057   }
4058   g_free (sysid_string);
4059   gst_event_unref (event);
4060   gst_buffer_unref (pssh);
4061   return TRUE;
4062 }
4063
4064 static gboolean
4065 qtdemux_parse_moof (GstQTDemux * qtdemux, const guint8 * buffer, guint length,
4066     guint64 moof_offset, QtDemuxStream * stream)
4067 {
4068   GNode *moof_node, *traf_node, *tfhd_node, *trun_node, *tfdt_node, *mfhd_node;
4069   GNode *uuid_node;
4070   GstByteReader mfhd_data, trun_data, tfhd_data, tfdt_data;
4071   GNode *saiz_node, *saio_node, *pssh_node;
4072   GstByteReader saiz_data, saio_data;
4073   guint32 ds_size = 0, ds_duration = 0, ds_flags = 0;
4074   gint64 base_offset, running_offset;
4075   guint32 frag_num;
4076   GstClockTime min_dts = GST_CLOCK_TIME_NONE;
4077
4078   /* NOTE @stream ignored */
4079
4080   moof_node = g_node_new ((guint8 *) buffer);
4081   qtdemux_parse_node (qtdemux, moof_node, buffer, length);
4082   qtdemux_node_dump (qtdemux, moof_node);
4083
4084   /* Get fragment number from mfhd and check it's valid */
4085   mfhd_node =
4086       qtdemux_tree_get_child_by_type_full (moof_node, FOURCC_mfhd, &mfhd_data);
4087   if (mfhd_node == NULL)
4088     goto missing_mfhd;
4089   if (!qtdemux_parse_mfhd (qtdemux, &mfhd_data, &frag_num))
4090     goto fail;
4091   GST_DEBUG_OBJECT (qtdemux, "Fragment #%d", frag_num);
4092
4093   /* unknown base_offset to start with */
4094   base_offset = running_offset = -1;
4095   traf_node = qtdemux_tree_get_child_by_type (moof_node, FOURCC_traf);
4096   while (traf_node) {
4097     guint64 decode_time = 0;
4098
4099     /* Fragment Header node */
4100     tfhd_node =
4101         qtdemux_tree_get_child_by_type_full (traf_node, FOURCC_tfhd,
4102         &tfhd_data);
4103     if (!tfhd_node)
4104       goto missing_tfhd;
4105     if (!qtdemux_parse_tfhd (qtdemux, &tfhd_data, &stream, &ds_duration,
4106             &ds_size, &ds_flags, &base_offset))
4107       goto missing_tfhd;
4108
4109     /* The following code assumes at most a single set of sample auxiliary
4110      * data in the fragment (consisting of a saiz box and a corresponding saio
4111      * box); in theory, however, there could be multiple sets of sample
4112      * auxiliary data in a fragment. */
4113     saiz_node =
4114         qtdemux_tree_get_child_by_type_full (traf_node, FOURCC_saiz,
4115         &saiz_data);
4116     if (saiz_node) {
4117       guint32 info_type = 0;
4118       guint64 offset = 0;
4119       guint32 info_type_parameter = 0;
4120
4121       g_free (qtdemux->cenc_aux_info_sizes);
4122
4123       qtdemux->cenc_aux_info_sizes =
4124           qtdemux_parse_saiz (qtdemux, stream, &saiz_data,
4125           &qtdemux->cenc_aux_sample_count);
4126       if (qtdemux->cenc_aux_info_sizes == NULL) {
4127         GST_ERROR_OBJECT (qtdemux, "failed to parse saiz box");
4128         goto fail;
4129       }
4130       saio_node =
4131           qtdemux_tree_get_child_by_type_full (traf_node, FOURCC_saio,
4132           &saio_data);
4133       if (!saio_node) {
4134         GST_ERROR_OBJECT (qtdemux, "saiz box without a corresponding saio box");
4135         g_free (qtdemux->cenc_aux_info_sizes);
4136         qtdemux->cenc_aux_info_sizes = NULL;
4137         goto fail;
4138       }
4139
4140       if (G_UNLIKELY (!qtdemux_parse_saio (qtdemux, stream, &saio_data,
4141                   &info_type, &info_type_parameter, &offset))) {
4142         GST_ERROR_OBJECT (qtdemux, "failed to parse saio box");
4143         g_free (qtdemux->cenc_aux_info_sizes);
4144         qtdemux->cenc_aux_info_sizes = NULL;
4145         goto fail;
4146       }
4147       if (base_offset > -1 && base_offset > qtdemux->moof_offset)
4148         offset += (guint64) (base_offset - qtdemux->moof_offset);
4149       if (info_type == FOURCC_cenc && info_type_parameter == 0U) {
4150         GstByteReader br;
4151         if (offset > length) {
4152           GST_DEBUG_OBJECT (qtdemux, "cenc auxiliary info stored out of moof");
4153           qtdemux->cenc_aux_info_offset = offset;
4154         } else {
4155           gst_byte_reader_init (&br, buffer + offset, length - offset);
4156           if (!qtdemux_parse_cenc_aux_info (qtdemux, stream, &br,
4157                   qtdemux->cenc_aux_info_sizes,
4158                   qtdemux->cenc_aux_sample_count)) {
4159             GST_ERROR_OBJECT (qtdemux, "failed to parse cenc auxiliary info");
4160             g_free (qtdemux->cenc_aux_info_sizes);
4161             qtdemux->cenc_aux_info_sizes = NULL;
4162             goto fail;
4163           }
4164         }
4165       }
4166     }
4167
4168     tfdt_node =
4169         qtdemux_tree_get_child_by_type_full (traf_node, FOURCC_tfdt,
4170         &tfdt_data);
4171     if (tfdt_node) {
4172       /* We'll use decode_time to interpolate timestamps
4173        * in case the input timestamps are missing */
4174       qtdemux_parse_tfdt (qtdemux, &tfdt_data, &decode_time);
4175
4176       GST_DEBUG_OBJECT (qtdemux, "decode time %" G_GINT64_FORMAT
4177           " (%" GST_TIME_FORMAT ")", decode_time,
4178           GST_TIME_ARGS (stream ? QTSTREAMTIME_TO_GSTTIME (stream,
4179                   decode_time) : GST_CLOCK_TIME_NONE));
4180
4181       /* Discard the fragment buffer timestamp info to avoid using it.
4182        * Rely on tfdt instead as it is more accurate than the timestamp
4183        * that is fetched from a manifest/playlist and is usually
4184        * less accurate. */
4185       qtdemux->fragment_start = -1;
4186     }
4187
4188     if (G_UNLIKELY (!stream)) {
4189       /* we lost track of offset, we'll need to regain it,
4190        * but can delay complaining until later or avoid doing so altogether */
4191       base_offset = -2;
4192       goto next;
4193     }
4194     if (G_UNLIKELY (base_offset < -1))
4195       goto lost_offset;
4196
4197     min_dts = MIN (min_dts, QTSTREAMTIME_TO_GSTTIME (stream, decode_time));
4198
4199     if (!qtdemux->pullbased) {
4200       /* Sample tables can grow enough to be problematic if the system memory
4201        * is very low (e.g. embedded devices) and the videos very long
4202        * (~8 MiB/hour for 25-30 fps video + typical AAC audio frames).
4203        * Fortunately, we can easily discard them for each new fragment when
4204        * we know qtdemux will not receive seeks outside of the current fragment.
4205        * adaptivedemux honors this assumption.
4206        * This optimization is also useful for applications that use qtdemux as
4207        * a push-based simple demuxer, like Media Source Extensions. */
4208       gst_qtdemux_stream_flush_samples_data (stream);
4209     }
4210
4211     /* initialise moof sample data */
4212     stream->n_samples_moof = 0;
4213     stream->duration_last_moof = stream->duration_moof;
4214     stream->duration_moof = 0;
4215
4216     /* Track Run node */
4217     trun_node =
4218         qtdemux_tree_get_child_by_type_full (traf_node, FOURCC_trun,
4219         &trun_data);
4220     while (trun_node) {
4221       qtdemux_parse_trun (qtdemux, &trun_data, stream,
4222           ds_duration, ds_size, ds_flags, moof_offset, length, &base_offset,
4223           &running_offset, decode_time, (tfdt_node != NULL));
4224       /* iterate all siblings */
4225       trun_node = qtdemux_tree_get_sibling_by_type_full (trun_node, FOURCC_trun,
4226           &trun_data);
4227     }
4228
4229     uuid_node = qtdemux_tree_get_child_by_type (traf_node, FOURCC_uuid);
4230     if (uuid_node) {
4231       guint8 *uuid_buffer = (guint8 *) uuid_node->data;
4232       guint32 box_length = QT_UINT32 (uuid_buffer);
4233
4234       qtdemux_parse_uuid (qtdemux, uuid_buffer, box_length);
4235     }
4236
4237     /* if no new base_offset provided for next traf,
4238      * base is end of current traf */
4239     base_offset = running_offset;
4240     running_offset = -1;
4241
4242     if (stream->n_samples_moof && stream->duration_moof)
4243       stream->new_caps = TRUE;
4244
4245   next:
4246     /* iterate all siblings */
4247     traf_node = qtdemux_tree_get_sibling_by_type (traf_node, FOURCC_traf);
4248   }
4249
4250   /* parse any protection system info */
4251   pssh_node = qtdemux_tree_get_child_by_type (moof_node, FOURCC_pssh);
4252   while (pssh_node) {
4253     GST_LOG_OBJECT (qtdemux, "Parsing pssh box.");
4254     qtdemux_parse_pssh (qtdemux, pssh_node);
4255     pssh_node = qtdemux_tree_get_sibling_by_type (pssh_node, FOURCC_pssh);
4256   }
4257
4258   if (!qtdemux->upstream_format_is_time && !qtdemux->first_moof_already_parsed
4259       && !qtdemux->received_seek && GST_CLOCK_TIME_IS_VALID (min_dts)
4260       && min_dts != 0) {
4261     /* Unless the user has explictly requested another seek, perform an
4262      * internal seek to the time specified in the tfdt.
4263      *
4264      * This way if the user opens a file where the first tfdt is 1 hour
4265      * into the presentation, they will not have to wait 1 hour for run
4266      * time to catch up and actual playback to start. */
4267     gint i;
4268
4269     GST_DEBUG_OBJECT (qtdemux, "First fragment has a non-zero tfdt, "
4270         "performing an internal seek to %" GST_TIME_FORMAT,
4271         GST_TIME_ARGS (min_dts));
4272
4273     qtdemux->segment.start = min_dts;
4274     qtdemux->segment.time = qtdemux->segment.position = min_dts;
4275
4276     for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
4277       QtDemuxStream *stream = QTDEMUX_NTH_STREAM (qtdemux, i);
4278       stream->time_position = min_dts;
4279     }
4280
4281     /* Before this code was run a segment was already sent when the moov was
4282      * parsed... which is OK -- some apps (mostly tests) expect a segment to
4283      * be emitted after a moov, and we can emit a second segment anyway for
4284      * special cases like this. */
4285     qtdemux->need_segment = TRUE;
4286   }
4287
4288   qtdemux->first_moof_already_parsed = TRUE;
4289
4290   g_node_destroy (moof_node);
4291   return TRUE;
4292
4293 missing_tfhd:
4294   {
4295     GST_DEBUG_OBJECT (qtdemux, "missing tfhd box");
4296     goto fail;
4297   }
4298 missing_mfhd:
4299   {
4300     GST_DEBUG_OBJECT (qtdemux, "Missing mfhd box");
4301     goto fail;
4302   }
4303 lost_offset:
4304   {
4305     GST_DEBUG_OBJECT (qtdemux, "lost offset");
4306     goto fail;
4307   }
4308 fail:
4309   {
4310     g_node_destroy (moof_node);
4311     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
4312         (_("This file is corrupt and cannot be played.")), (NULL));
4313     return FALSE;
4314   }
4315 }
4316
4317 #if 0
4318 /* might be used if some day we actually use mfra & co
4319  * for random access to fragments,
4320  * but that will require quite some modifications and much less relying
4321  * on a sample array */
4322 #endif
4323
4324 static gboolean
4325 qtdemux_parse_tfra (GstQTDemux * qtdemux, GNode * tfra_node)
4326 {
4327   QtDemuxStream *stream;
4328   guint32 ver_flags, track_id, len, num_entries, i;
4329   guint value_size, traf_size, trun_size, sample_size;
4330   guint64 time = 0, moof_offset = 0;
4331 #if 0
4332   GstBuffer *buf = NULL;
4333   GstFlowReturn ret;
4334 #endif
4335   GstByteReader tfra;
4336
4337   gst_byte_reader_init (&tfra, tfra_node->data, QT_UINT32 (tfra_node->data));
4338
4339   if (!gst_byte_reader_skip (&tfra, 8))
4340     return FALSE;
4341
4342   if (!gst_byte_reader_get_uint32_be (&tfra, &ver_flags))
4343     return FALSE;
4344
4345   if (!gst_byte_reader_get_uint32_be (&tfra, &track_id)
4346       || !gst_byte_reader_get_uint32_be (&tfra, &len)
4347       || !gst_byte_reader_get_uint32_be (&tfra, &num_entries))
4348     return FALSE;
4349
4350   GST_DEBUG_OBJECT (qtdemux, "parsing tfra box for track id %u", track_id);
4351
4352   stream = qtdemux_find_stream (qtdemux, track_id);
4353   if (stream == NULL)
4354     goto unknown_trackid;
4355
4356   value_size = ((ver_flags >> 24) == 1) ? sizeof (guint64) : sizeof (guint32);
4357   sample_size = (len & 3) + 1;
4358   trun_size = ((len & 12) >> 2) + 1;
4359   traf_size = ((len & 48) >> 4) + 1;
4360
4361   GST_DEBUG_OBJECT (qtdemux, "%u entries, sizes: value %u, traf %u, trun %u, "
4362       "sample %u", num_entries, value_size, traf_size, trun_size, sample_size);
4363
4364   if (num_entries == 0)
4365     goto no_samples;
4366
4367   if (!qt_atom_parser_has_chunks (&tfra, num_entries,
4368           value_size + value_size + traf_size + trun_size + sample_size))
4369     goto corrupt_file;
4370
4371   g_free (stream->ra_entries);
4372   stream->ra_entries = g_new (QtDemuxRandomAccessEntry, num_entries);
4373   stream->n_ra_entries = num_entries;
4374
4375   for (i = 0; i < num_entries; i++) {
4376     qt_atom_parser_get_offset (&tfra, value_size, &time);
4377     qt_atom_parser_get_offset (&tfra, value_size, &moof_offset);
4378     qt_atom_parser_get_uint_with_size_unchecked (&tfra, traf_size);
4379     qt_atom_parser_get_uint_with_size_unchecked (&tfra, trun_size);
4380     qt_atom_parser_get_uint_with_size_unchecked (&tfra, sample_size);
4381
4382     time = QTSTREAMTIME_TO_GSTTIME (stream, time);
4383
4384     GST_LOG_OBJECT (qtdemux, "fragment time: %" GST_TIME_FORMAT ", "
4385         " moof_offset: %" G_GUINT64_FORMAT, GST_TIME_ARGS (time), moof_offset);
4386
4387     stream->ra_entries[i].ts = time;
4388     stream->ra_entries[i].moof_offset = moof_offset;
4389
4390     /* don't want to go through the entire file and read all moofs at startup */
4391 #if 0
4392     ret = gst_qtdemux_pull_atom (qtdemux, moof_offset, 0, &buf);
4393     if (ret != GST_FLOW_OK)
4394       goto corrupt_file;
4395     qtdemux_parse_moof (qtdemux, GST_BUFFER_DATA (buf), GST_BUFFER_SIZE (buf),
4396         moof_offset, stream);
4397     gst_buffer_unref (buf);
4398 #endif
4399   }
4400
4401   check_update_duration (qtdemux, time);
4402
4403   return TRUE;
4404
4405 /* ERRORS */
4406 unknown_trackid:
4407   {
4408     GST_WARNING_OBJECT (qtdemux, "Couldn't find stream for track %u", track_id);
4409     return FALSE;
4410   }
4411 corrupt_file:
4412   {
4413     GST_WARNING_OBJECT (qtdemux, "broken traf box, ignoring");
4414     return FALSE;
4415   }
4416 no_samples:
4417   {
4418     GST_WARNING_OBJECT (qtdemux, "stream has no samples");
4419     return FALSE;
4420   }
4421 }
4422
4423 static gboolean
4424 qtdemux_pull_mfro_mfra (GstQTDemux * qtdemux)
4425 {
4426   GstMapInfo mfro_map = GST_MAP_INFO_INIT;
4427   GstMapInfo mfra_map = GST_MAP_INFO_INIT;
4428   GstBuffer *mfro = NULL, *mfra = NULL;
4429   GstFlowReturn flow;
4430   gboolean ret = FALSE;
4431   GNode *mfra_node, *tfra_node;
4432   guint64 mfra_offset = 0;
4433   guint32 fourcc, mfra_size;
4434   gint64 len;
4435
4436   /* query upstream size in bytes */
4437   if (!gst_pad_peer_query_duration (qtdemux->sinkpad, GST_FORMAT_BYTES, &len))
4438     goto size_query_failed;
4439
4440   /* mfro box should be at the very end of the file */
4441   flow = gst_qtdemux_pull_atom (qtdemux, len - 16, 16, &mfro);
4442   if (flow != GST_FLOW_OK)
4443     goto exit;
4444
4445   gst_buffer_map (mfro, &mfro_map, GST_MAP_READ);
4446
4447   fourcc = QT_FOURCC (mfro_map.data + 4);
4448   if (fourcc != FOURCC_mfro)
4449     goto exit;
4450
4451   GST_INFO_OBJECT (qtdemux, "Found mfro box");
4452   if (mfro_map.size < 16)
4453     goto invalid_mfro_size;
4454
4455   mfra_size = QT_UINT32 (mfro_map.data + 12);
4456   if (mfra_size >= len)
4457     goto invalid_mfra_size;
4458
4459   mfra_offset = len - mfra_size;
4460
4461   GST_INFO_OBJECT (qtdemux, "mfra offset: %" G_GUINT64_FORMAT ", size %u",
4462       mfra_offset, mfra_size);
4463
4464   /* now get and parse mfra box */
4465   flow = gst_qtdemux_pull_atom (qtdemux, mfra_offset, mfra_size, &mfra);
4466   if (flow != GST_FLOW_OK)
4467     goto broken_file;
4468
4469   gst_buffer_map (mfra, &mfra_map, GST_MAP_READ);
4470
4471   mfra_node = g_node_new ((guint8 *) mfra_map.data);
4472   qtdemux_parse_node (qtdemux, mfra_node, mfra_map.data, mfra_map.size);
4473
4474   tfra_node = qtdemux_tree_get_child_by_type (mfra_node, FOURCC_tfra);
4475
4476   while (tfra_node) {
4477     qtdemux_parse_tfra (qtdemux, tfra_node);
4478     /* iterate all siblings */
4479     tfra_node = qtdemux_tree_get_sibling_by_type (tfra_node, FOURCC_tfra);
4480   }
4481   g_node_destroy (mfra_node);
4482
4483   GST_INFO_OBJECT (qtdemux, "parsed movie fragment random access box (mfra)");
4484   ret = TRUE;
4485
4486 exit:
4487
4488   if (mfro) {
4489     if (mfro_map.memory != NULL)
4490       gst_buffer_unmap (mfro, &mfro_map);
4491     gst_buffer_unref (mfro);
4492   }
4493   if (mfra) {
4494     if (mfra_map.memory != NULL)
4495       gst_buffer_unmap (mfra, &mfra_map);
4496     gst_buffer_unref (mfra);
4497   }
4498   return ret;
4499
4500 /* ERRORS */
4501 size_query_failed:
4502   {
4503     GST_WARNING_OBJECT (qtdemux, "could not query upstream size");
4504     goto exit;
4505   }
4506 invalid_mfro_size:
4507   {
4508     GST_WARNING_OBJECT (qtdemux, "mfro size is too small");
4509     goto exit;
4510   }
4511 invalid_mfra_size:
4512   {
4513     GST_WARNING_OBJECT (qtdemux, "mfra_size in mfro box is invalid");
4514     goto exit;
4515   }
4516 broken_file:
4517   {
4518     GST_WARNING_OBJECT (qtdemux, "bogus mfra offset or size, broken file");
4519     goto exit;
4520   }
4521 }
4522
4523 static guint64
4524 add_offset (guint64 offset, guint64 advance)
4525 {
4526   /* Avoid 64-bit overflow by clamping */
4527   if (offset > G_MAXUINT64 - advance)
4528     return G_MAXUINT64;
4529   return offset + advance;
4530 }
4531
4532 static GstFlowReturn
4533 gst_qtdemux_loop_state_header (GstQTDemux * qtdemux)
4534 {
4535   guint64 length = 0;
4536   guint32 fourcc = 0;
4537   GstBuffer *buf = NULL;
4538   GstFlowReturn ret = GST_FLOW_OK;
4539   guint64 cur_offset = qtdemux->offset;
4540   GstMapInfo map;
4541
4542   ret = gst_pad_pull_range (qtdemux->sinkpad, cur_offset, 16, &buf);
4543   if (G_UNLIKELY (ret != GST_FLOW_OK))
4544     goto beach;
4545   gst_buffer_map (buf, &map, GST_MAP_READ);
4546   if (G_LIKELY (map.size >= 8))
4547     extract_initial_length_and_fourcc (map.data, map.size, &length, &fourcc);
4548   gst_buffer_unmap (buf, &map);
4549   gst_buffer_unref (buf);
4550
4551   /* maybe we already got most we needed, so only consider this eof */
4552   if (G_UNLIKELY (length == 0)) {
4553     GST_ELEMENT_WARNING (qtdemux, STREAM, DEMUX,
4554         (_("Invalid atom size.")),
4555         ("Header atom '%" GST_FOURCC_FORMAT "' has empty length",
4556             GST_FOURCC_ARGS (fourcc)));
4557     ret = GST_FLOW_EOS;
4558     goto beach;
4559   }
4560
4561   switch (fourcc) {
4562     case FOURCC_moof:
4563       /* record for later parsing when needed */
4564       if (!qtdemux->moof_offset) {
4565         qtdemux->moof_offset = qtdemux->offset;
4566       }
4567       if (qtdemux_pull_mfro_mfra (qtdemux)) {
4568         /* FIXME */
4569       } else {
4570         qtdemux->offset += length;      /* skip moof and keep going */
4571       }
4572       if (qtdemux->got_moov) {
4573         GST_INFO_OBJECT (qtdemux, "moof header, got moov, done with headers");
4574         ret = GST_FLOW_EOS;
4575         goto beach;
4576       }
4577       break;
4578     case FOURCC_mdat:
4579     case FOURCC_free:
4580     case FOURCC_skip:
4581     case FOURCC_wide:
4582     case FOURCC_PICT:
4583     case FOURCC_pnot:
4584     {
4585       GST_LOG_OBJECT (qtdemux,
4586           "skipping atom '%" GST_FOURCC_FORMAT "' at %" G_GUINT64_FORMAT,
4587           GST_FOURCC_ARGS (fourcc), cur_offset);
4588       qtdemux->offset = add_offset (qtdemux->offset, length);
4589       break;
4590     }
4591     case FOURCC_moov:
4592     {
4593       GstBuffer *moov = NULL;
4594
4595       if (qtdemux->got_moov) {
4596         GST_DEBUG_OBJECT (qtdemux, "Skipping moov atom as we have one already");
4597         qtdemux->offset = add_offset (qtdemux->offset, length);
4598         goto beach;
4599       }
4600
4601       ret = gst_pad_pull_range (qtdemux->sinkpad, cur_offset, length, &moov);
4602       if (ret != GST_FLOW_OK)
4603         goto beach;
4604       gst_buffer_map (moov, &map, GST_MAP_READ);
4605
4606       if (length != map.size) {
4607         /* Some files have a 'moov' atom at the end of the file which contains
4608          * a terminal 'free' atom where the body of the atom is missing.
4609          * Check for, and permit, this special case.
4610          */
4611         if (map.size >= 8) {
4612           guint8 *final_data = map.data + (map.size - 8);
4613           guint32 final_length = QT_UINT32 (final_data);
4614           guint32 final_fourcc = QT_FOURCC (final_data + 4);
4615
4616           if (final_fourcc == FOURCC_free
4617               && map.size + final_length - 8 == length) {
4618             /* Ok, we've found that special case. Allocate a new buffer with
4619              * that free atom actually present. */
4620             GstBuffer *newmoov = gst_buffer_new_and_alloc (length);
4621             gst_buffer_fill (newmoov, 0, map.data, map.size);
4622             gst_buffer_memset (newmoov, map.size, 0, final_length - 8);
4623             gst_buffer_unmap (moov, &map);
4624             gst_buffer_unref (moov);
4625             moov = newmoov;
4626             gst_buffer_map (moov, &map, GST_MAP_READ);
4627           }
4628         }
4629       }
4630
4631       if (length != map.size) {
4632         GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
4633             (_("This file is incomplete and cannot be played.")),
4634             ("We got less than expected (received %" G_GSIZE_FORMAT
4635                 ", wanted %u, offset %" G_GUINT64_FORMAT ")", map.size,
4636                 (guint) length, cur_offset));
4637         gst_buffer_unmap (moov, &map);
4638         gst_buffer_unref (moov);
4639         ret = GST_FLOW_ERROR;
4640         goto beach;
4641       }
4642       qtdemux->offset += length;
4643
4644       qtdemux_parse_moov (qtdemux, map.data, length);
4645       qtdemux_node_dump (qtdemux, qtdemux->moov_node);
4646
4647       qtdemux_parse_tree (qtdemux);
4648       if (qtdemux->moov_node_compressed) {
4649         g_node_destroy (qtdemux->moov_node_compressed);
4650         g_free (qtdemux->moov_node->data);
4651       }
4652       qtdemux->moov_node_compressed = NULL;
4653       g_node_destroy (qtdemux->moov_node);
4654       qtdemux->moov_node = NULL;
4655       gst_buffer_unmap (moov, &map);
4656       gst_buffer_unref (moov);
4657       qtdemux->got_moov = TRUE;
4658
4659       break;
4660     }
4661     case FOURCC_ftyp:
4662     {
4663       GstBuffer *ftyp = NULL;
4664
4665       /* extract major brand; might come in handy for ISO vs QT issues */
4666       ret = gst_qtdemux_pull_atom (qtdemux, cur_offset, length, &ftyp);
4667       if (ret != GST_FLOW_OK)
4668         goto beach;
4669       qtdemux->offset += length;
4670       gst_buffer_map (ftyp, &map, GST_MAP_READ);
4671       qtdemux_parse_ftyp (qtdemux, map.data, map.size);
4672       gst_buffer_unmap (ftyp, &map);
4673       gst_buffer_unref (ftyp);
4674       break;
4675     }
4676     case FOURCC_uuid:
4677     {
4678       GstBuffer *uuid = NULL;
4679
4680       /* uuid are extension atoms */
4681       ret = gst_qtdemux_pull_atom (qtdemux, cur_offset, length, &uuid);
4682       if (ret != GST_FLOW_OK)
4683         goto beach;
4684       qtdemux->offset += length;
4685       gst_buffer_map (uuid, &map, GST_MAP_READ);
4686       qtdemux_parse_uuid (qtdemux, map.data, map.size);
4687       gst_buffer_unmap (uuid, &map);
4688       gst_buffer_unref (uuid);
4689       break;
4690     }
4691     case FOURCC_sidx:
4692     {
4693       GstBuffer *sidx = NULL;
4694       ret = gst_qtdemux_pull_atom (qtdemux, cur_offset, length, &sidx);
4695       if (ret != GST_FLOW_OK)
4696         goto beach;
4697       qtdemux->offset += length;
4698       gst_buffer_map (sidx, &map, GST_MAP_READ);
4699       qtdemux_parse_sidx (qtdemux, map.data, map.size);
4700       gst_buffer_unmap (sidx, &map);
4701       gst_buffer_unref (sidx);
4702       break;
4703     }
4704     default:
4705     {
4706       GstBuffer *unknown = NULL;
4707
4708       GST_LOG_OBJECT (qtdemux,
4709           "unknown %08x '%" GST_FOURCC_FORMAT "' of size %" G_GUINT64_FORMAT
4710           " at %" G_GUINT64_FORMAT, fourcc, GST_FOURCC_ARGS (fourcc), length,
4711           cur_offset);
4712       ret = gst_qtdemux_pull_atom (qtdemux, cur_offset, length, &unknown);
4713       if (ret != GST_FLOW_OK)
4714         goto beach;
4715       gst_buffer_map (unknown, &map, GST_MAP_READ);
4716       GST_MEMDUMP ("Unknown tag", map.data, map.size);
4717       gst_buffer_unmap (unknown, &map);
4718       gst_buffer_unref (unknown);
4719       qtdemux->offset += length;
4720       break;
4721     }
4722   }
4723
4724 beach:
4725   if (ret == GST_FLOW_EOS && (qtdemux->got_moov || qtdemux->media_caps)) {
4726     /* digested all data, show what we have */
4727     qtdemux_prepare_streams (qtdemux);
4728     QTDEMUX_EXPOSE_LOCK (qtdemux);
4729     ret = qtdemux_expose_streams (qtdemux);
4730     QTDEMUX_EXPOSE_UNLOCK (qtdemux);
4731
4732     qtdemux->state = QTDEMUX_STATE_MOVIE;
4733     GST_DEBUG_OBJECT (qtdemux, "switching state to STATE_MOVIE (%d)",
4734         qtdemux->state);
4735     return ret;
4736   }
4737   return ret;
4738 }
4739
4740 /* Seeks to the previous keyframe of the indexed stream and
4741  * aligns other streams with respect to the keyframe timestamp
4742  * of indexed stream. Only called in case of Reverse Playback
4743  */
4744 static GstFlowReturn
4745 gst_qtdemux_seek_to_previous_keyframe (GstQTDemux * qtdemux)
4746 {
4747   guint32 seg_idx = 0, k_index = 0;
4748   guint32 ref_seg_idx, ref_k_index;
4749   GstClockTime k_pos = 0, last_stop = 0;
4750   QtDemuxSegment *seg = NULL;
4751   QtDemuxStream *ref_str = NULL;
4752   guint64 seg_media_start_mov;  /* segment media start time in mov format */
4753   guint64 target_ts;
4754   gint i;
4755
4756   /* Now we choose an arbitrary stream, get the previous keyframe timestamp
4757    * and finally align all the other streams on that timestamp with their
4758    * respective keyframes */
4759   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
4760     QtDemuxStream *str = QTDEMUX_NTH_STREAM (qtdemux, i);
4761
4762     /* No candidate yet, take the first stream */
4763     if (!ref_str) {
4764       ref_str = str;
4765       continue;
4766     }
4767
4768     /* So that stream has a segment, we prefer video streams */
4769     if (str->subtype == FOURCC_vide) {
4770       ref_str = str;
4771       break;
4772     }
4773   }
4774
4775   if (G_UNLIKELY (!ref_str)) {
4776     GST_DEBUG_OBJECT (qtdemux, "couldn't find any stream");
4777     goto eos;
4778   }
4779
4780   if (G_UNLIKELY (!ref_str->from_sample)) {
4781     GST_DEBUG_OBJECT (qtdemux, "reached the beginning of the file");
4782     goto eos;
4783   }
4784
4785   /* So that stream has been playing from from_sample to to_sample. We will
4786    * get the timestamp of the previous sample and search for a keyframe before
4787    * that. For audio streams we do an arbitrary jump in the past (10 samples) */
4788   if (ref_str->subtype == FOURCC_vide) {
4789     k_index = gst_qtdemux_find_keyframe (qtdemux, ref_str,
4790         ref_str->from_sample - 1, FALSE);
4791   } else {
4792     if (ref_str->from_sample >= 10)
4793       k_index = ref_str->from_sample - 10;
4794     else
4795       k_index = 0;
4796   }
4797
4798   target_ts =
4799       ref_str->samples[k_index].timestamp +
4800       ref_str->samples[k_index].pts_offset;
4801
4802   /* get current segment for that stream */
4803   seg = &ref_str->segments[ref_str->segment_index];
4804   /* Use segment start in original timescale for comparisons */
4805   seg_media_start_mov = seg->trak_media_start;
4806
4807   GST_LOG_OBJECT (qtdemux, "keyframe index %u ts %" G_GUINT64_FORMAT
4808       " seg start %" G_GUINT64_FORMAT " %" GST_TIME_FORMAT,
4809       k_index, target_ts, seg_media_start_mov,
4810       GST_TIME_ARGS (seg->media_start));
4811
4812   /* Crawl back through segments to find the one containing this I frame */
4813   while (target_ts < seg_media_start_mov) {
4814     GST_DEBUG_OBJECT (qtdemux,
4815         "keyframe position (sample %u) is out of segment %u " " target %"
4816         G_GUINT64_FORMAT " seg start %" G_GUINT64_FORMAT, k_index,
4817         ref_str->segment_index, target_ts, seg_media_start_mov);
4818
4819     if (G_UNLIKELY (!ref_str->segment_index)) {
4820       /* Reached first segment, let's consider it's EOS */
4821       goto eos;
4822     }
4823     ref_str->segment_index--;
4824     seg = &ref_str->segments[ref_str->segment_index];
4825     /* Use segment start in original timescale for comparisons */
4826     seg_media_start_mov = seg->trak_media_start;
4827   }
4828   /* Calculate time position of the keyframe and where we should stop */
4829   k_pos =
4830       QTSTREAMTIME_TO_GSTTIME (ref_str,
4831       target_ts - seg->trak_media_start) + seg->time;
4832   last_stop =
4833       QTSTREAMTIME_TO_GSTTIME (ref_str,
4834       ref_str->samples[ref_str->from_sample].timestamp -
4835       seg->trak_media_start) + seg->time;
4836
4837   GST_DEBUG_OBJECT (qtdemux, "preferred stream played from sample %u, "
4838       "now going to sample %u (pts %" GST_TIME_FORMAT ")", ref_str->from_sample,
4839       k_index, GST_TIME_ARGS (k_pos));
4840
4841   /* Set last_stop with the keyframe timestamp we pushed of that stream */
4842   qtdemux->segment.position = last_stop;
4843   GST_DEBUG_OBJECT (qtdemux, "last_stop now is %" GST_TIME_FORMAT,
4844       GST_TIME_ARGS (last_stop));
4845
4846   if (G_UNLIKELY (last_stop < qtdemux->segment.start)) {
4847     GST_DEBUG_OBJECT (qtdemux, "reached the beginning of segment");
4848     goto eos;
4849   }
4850
4851   ref_seg_idx = ref_str->segment_index;
4852   ref_k_index = k_index;
4853
4854   /* Align them all on this */
4855   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
4856     guint32 index = 0;
4857     GstClockTime seg_time = 0;
4858     QtDemuxStream *str = QTDEMUX_NTH_STREAM (qtdemux, i);
4859
4860     /* aligning reference stream again might lead to backing up to yet another
4861      * keyframe (due to timestamp rounding issues),
4862      * potentially putting more load on downstream; so let's try to avoid */
4863     if (str == ref_str) {
4864       seg_idx = ref_seg_idx;
4865       seg = &str->segments[seg_idx];
4866       k_index = ref_k_index;
4867       GST_DEBUG_OBJECT (qtdemux, "reference track-id %u segment %d, "
4868           "sample at index %d", str->track_id, ref_str->segment_index, k_index);
4869     } else {
4870       seg_idx = gst_qtdemux_find_segment (qtdemux, str, k_pos);
4871       GST_DEBUG_OBJECT (qtdemux,
4872           "track-id %u align segment %d for keyframe pos %" GST_TIME_FORMAT,
4873           str->track_id, seg_idx, GST_TIME_ARGS (k_pos));
4874
4875       /* get segment and time in the segment */
4876       seg = &str->segments[seg_idx];
4877       seg_time = k_pos - seg->time;
4878
4879       /* get the media time in the segment.
4880        * No adjustment for empty "filler" segments */
4881       if (seg->media_start != GST_CLOCK_TIME_NONE)
4882         seg_time += seg->media_start;
4883
4884       /* get the index of the sample with media time */
4885       index = gst_qtdemux_find_index_linear (qtdemux, str, seg_time);
4886       GST_DEBUG_OBJECT (qtdemux,
4887           "track-id %u sample for %" GST_TIME_FORMAT " at %u", str->track_id,
4888           GST_TIME_ARGS (seg_time), index);
4889
4890       /* find previous keyframe */
4891       k_index = gst_qtdemux_find_keyframe (qtdemux, str, index, FALSE);
4892     }
4893
4894     /* Remember until where we want to go */
4895     str->to_sample = str->from_sample - 1;
4896     /* Define our time position */
4897     target_ts =
4898         str->samples[k_index].timestamp + str->samples[k_index].pts_offset;
4899     str->time_position = QTSTREAMTIME_TO_GSTTIME (str, target_ts) + seg->time;
4900     if (seg->media_start != GST_CLOCK_TIME_NONE)
4901       str->time_position -= seg->media_start;
4902
4903     /* Now seek back in time */
4904     gst_qtdemux_move_stream (qtdemux, str, k_index);
4905     GST_DEBUG_OBJECT (qtdemux, "track-id %u keyframe at %u, time position %"
4906         GST_TIME_FORMAT " playing from sample %u to %u", str->track_id, k_index,
4907         GST_TIME_ARGS (str->time_position), str->from_sample, str->to_sample);
4908   }
4909
4910   return GST_FLOW_OK;
4911
4912 eos:
4913   return GST_FLOW_EOS;
4914 }
4915
4916 /*
4917  * Gets the current qt segment start, stop and position for the
4918  * given time offset. This is used in update_segment()
4919  */
4920 static void
4921 gst_qtdemux_stream_segment_get_boundaries (GstQTDemux * qtdemux,
4922     QtDemuxStream * stream, GstClockTime offset,
4923     GstClockTime * _start, GstClockTime * _stop, GstClockTime * _time)
4924 {
4925   GstClockTime seg_time;
4926   GstClockTime start, stop, time;
4927   QtDemuxSegment *segment;
4928
4929   segment = &stream->segments[stream->segment_index];
4930
4931   /* get time in this segment */
4932   seg_time = (offset - segment->time) * segment->rate;
4933
4934   GST_LOG_OBJECT (stream->pad, "seg_time %" GST_TIME_FORMAT,
4935       GST_TIME_ARGS (seg_time));
4936
4937   if (G_UNLIKELY (seg_time > segment->duration)) {
4938     GST_LOG_OBJECT (stream->pad,
4939         "seg_time > segment->duration %" GST_TIME_FORMAT,
4940         GST_TIME_ARGS (segment->duration));
4941     seg_time = segment->duration;
4942   }
4943
4944   /* qtdemux->segment.stop is in outside-time-realm, whereas
4945    * segment->media_stop is in track-time-realm.
4946    *
4947    * In order to compare the two, we need to bring segment.stop
4948    * into the track-time-realm
4949    *
4950    * FIXME - does this comment still hold? Don't see any conversion here */
4951
4952   stop = qtdemux->segment.stop;
4953   if (stop == GST_CLOCK_TIME_NONE)
4954     stop = qtdemux->segment.duration;
4955   if (stop == GST_CLOCK_TIME_NONE)
4956     stop = segment->media_stop;
4957   else
4958     stop =
4959         MIN (segment->media_stop, stop - segment->time + segment->media_start);
4960
4961   if (G_UNLIKELY (QTSEGMENT_IS_EMPTY (segment))) {
4962     start = segment->time + seg_time;
4963     time = offset;
4964     stop = start - seg_time + segment->duration;
4965   } else if (qtdemux->segment.rate >= 0) {
4966     start = MIN (segment->media_start + seg_time, stop);
4967     time = offset;
4968   } else {
4969     if (segment->media_start >= qtdemux->segment.start) {
4970       time = segment->time;
4971     } else {
4972       time = segment->time + (qtdemux->segment.start - segment->media_start);
4973     }
4974
4975     start = MAX (segment->media_start, qtdemux->segment.start);
4976     stop = MIN (segment->media_start + seg_time, stop);
4977   }
4978
4979   *_start = start;
4980   *_stop = stop;
4981   *_time = time;
4982 }
4983
4984 /*
4985  * Updates the qt segment used for the stream and pushes a new segment event
4986  * downstream on this stream's pad.
4987  */
4988 static gboolean
4989 gst_qtdemux_stream_update_segment (GstQTDemux * qtdemux, QtDemuxStream * stream,
4990     gint seg_idx, GstClockTime offset, GstClockTime * _start,
4991     GstClockTime * _stop)
4992 {
4993   QtDemuxSegment *segment;
4994   GstClockTime start = 0, stop = GST_CLOCK_TIME_NONE, time = 0;
4995   gdouble rate;
4996   GstEvent *event;
4997
4998   /* update the current segment */
4999   stream->segment_index = seg_idx;
5000
5001   /* get the segment */
5002   segment = &stream->segments[seg_idx];
5003
5004   if (G_UNLIKELY (offset < segment->time)) {
5005     GST_WARNING_OBJECT (stream->pad, "offset < segment->time %" GST_TIME_FORMAT,
5006         GST_TIME_ARGS (segment->time));
5007     return FALSE;
5008   }
5009
5010   /* segment lies beyond total indicated duration */
5011   if (G_UNLIKELY (qtdemux->segment.duration != GST_CLOCK_TIME_NONE &&
5012           segment->time > qtdemux->segment.duration)) {
5013     GST_WARNING_OBJECT (stream->pad, "file duration %" GST_TIME_FORMAT
5014         " < segment->time %" GST_TIME_FORMAT,
5015         GST_TIME_ARGS (qtdemux->segment.duration),
5016         GST_TIME_ARGS (segment->time));
5017     return FALSE;
5018   }
5019
5020   gst_qtdemux_stream_segment_get_boundaries (qtdemux, stream, offset,
5021       &start, &stop, &time);
5022
5023   GST_DEBUG_OBJECT (stream->pad, "new segment %d from %" GST_TIME_FORMAT
5024       " to %" GST_TIME_FORMAT ", time %" GST_TIME_FORMAT, seg_idx,
5025       GST_TIME_ARGS (start), GST_TIME_ARGS (stop), GST_TIME_ARGS (time));
5026
5027   /* combine global rate with that of the segment */
5028   rate = segment->rate * qtdemux->segment.rate;
5029
5030   /* Copy flags from main segment */
5031   stream->segment.flags = qtdemux->segment.flags;
5032
5033   /* update the segment values used for clipping */
5034   stream->segment.offset = qtdemux->segment.offset;
5035   stream->segment.base = qtdemux->segment.base + stream->accumulated_base;
5036   stream->segment.applied_rate = qtdemux->segment.applied_rate;
5037   stream->segment.rate = rate;
5038   stream->segment.start = start + QTSTREAMTIME_TO_GSTTIME (stream,
5039       stream->cslg_shift);
5040   stream->segment.stop = stop + QTSTREAMTIME_TO_GSTTIME (stream,
5041       stream->cslg_shift);
5042   stream->segment.time = time;
5043   stream->segment.position = stream->segment.start;
5044
5045   GST_DEBUG_OBJECT (stream->pad, "New segment: %" GST_SEGMENT_FORMAT,
5046       &stream->segment);
5047
5048   /* now prepare and send the segment */
5049   if (stream->pad) {
5050     event = gst_event_new_segment (&stream->segment);
5051     if (qtdemux->segment_seqnum != GST_SEQNUM_INVALID) {
5052       gst_event_set_seqnum (event, qtdemux->segment_seqnum);
5053     }
5054     gst_pad_push_event (stream->pad, event);
5055     /* assume we can send more data now */
5056     GST_PAD_LAST_FLOW_RETURN (stream->pad) = GST_FLOW_OK;
5057     /* clear to send tags on this pad now */
5058     gst_qtdemux_push_tags (qtdemux, stream);
5059   }
5060
5061   if (_start)
5062     *_start = start;
5063   if (_stop)
5064     *_stop = stop;
5065
5066   return TRUE;
5067 }
5068
5069 /* activate the given segment number @seg_idx of @stream at time @offset.
5070  * @offset is an absolute global position over all the segments.
5071  *
5072  * This will push out a NEWSEGMENT event with the right values and
5073  * position the stream index to the first decodable sample before
5074  * @offset.
5075  */
5076 static gboolean
5077 gst_qtdemux_activate_segment (GstQTDemux * qtdemux, QtDemuxStream * stream,
5078     guint32 seg_idx, GstClockTime offset)
5079 {
5080   QtDemuxSegment *segment;
5081   guint32 index, kf_index;
5082   GstClockTime start = 0, stop = GST_CLOCK_TIME_NONE;
5083
5084   GST_LOG_OBJECT (stream->pad, "activate segment %d, offset %" GST_TIME_FORMAT,
5085       seg_idx, GST_TIME_ARGS (offset));
5086
5087   if (!gst_qtdemux_stream_update_segment (qtdemux, stream, seg_idx, offset,
5088           &start, &stop))
5089     return FALSE;
5090
5091   segment = &stream->segments[stream->segment_index];
5092
5093   /* in the fragmented case, we pick a fragment that starts before our
5094    * desired position and rely on downstream to wait for a keyframe
5095    * (FIXME: doesn't seem to work so well with ismv and wmv, as no parser; the
5096    * tfra entries tells us which trun/sample the key unit is in, but we don't
5097    * make use of this additional information at the moment) */
5098   if (qtdemux->fragmented && !qtdemux->fragmented_seek_pending) {
5099     stream->to_sample = G_MAXUINT32;
5100     return TRUE;
5101   } else {
5102     /* well, it will be taken care of below */
5103     qtdemux->fragmented_seek_pending = FALSE;
5104     /* FIXME ideally the do_fragmented_seek can be done right here,
5105      * rather than at loop level
5106      * (which might even allow handling edit lists in a fragmented file) */
5107   }
5108
5109   /* We don't need to look for a sample in push-based */
5110   if (!qtdemux->pullbased)
5111     return TRUE;
5112
5113   /* and move to the keyframe before the indicated media time of the
5114    * segment */
5115   if (G_LIKELY (!QTSEGMENT_IS_EMPTY (segment))) {
5116     if (qtdemux->segment.rate >= 0) {
5117       index = gst_qtdemux_find_index_linear (qtdemux, stream, start);
5118       stream->to_sample = G_MAXUINT32;
5119       GST_DEBUG_OBJECT (stream->pad,
5120           "moving data pointer to %" GST_TIME_FORMAT ", index: %u, pts %"
5121           GST_TIME_FORMAT, GST_TIME_ARGS (start), index,
5122           GST_TIME_ARGS (QTSAMPLE_PTS (stream, &stream->samples[index])));
5123     } else {
5124       index = gst_qtdemux_find_index_linear (qtdemux, stream, stop);
5125       stream->to_sample = index;
5126       GST_DEBUG_OBJECT (stream->pad,
5127           "moving data pointer to %" GST_TIME_FORMAT ", index: %u, pts %"
5128           GST_TIME_FORMAT, GST_TIME_ARGS (stop), index,
5129           GST_TIME_ARGS (QTSAMPLE_PTS (stream, &stream->samples[index])));
5130     }
5131   } else {
5132     GST_DEBUG_OBJECT (stream->pad, "No need to look for keyframe, "
5133         "this is an empty segment");
5134     return TRUE;
5135   }
5136
5137   /* gst_qtdemux_parse_sample () called from gst_qtdemux_find_index_linear ()
5138    * encountered an error and printed a message so we return appropriately */
5139   if (index == -1)
5140     return FALSE;
5141
5142   /* we're at the right spot */
5143   if (index == stream->sample_index) {
5144     GST_DEBUG_OBJECT (stream->pad, "we are at the right index");
5145     return TRUE;
5146   }
5147
5148   /* find keyframe of the target index */
5149   kf_index = gst_qtdemux_find_keyframe (qtdemux, stream, index, FALSE);
5150
5151 /* *INDENT-OFF* */
5152 /* indent does stupid stuff with stream->samples[].timestamp */
5153
5154   /* if we move forwards, we don't have to go back to the previous
5155    * keyframe since we already sent that. We can also just jump to
5156    * the keyframe right before the target index if there is one. */
5157   if (index > stream->sample_index) {
5158     /* moving forwards check if we move past a keyframe */
5159     if (kf_index > stream->sample_index) {
5160       GST_DEBUG_OBJECT (stream->pad,
5161            "moving forwards to keyframe at %u (pts %" GST_TIME_FORMAT " dts %"GST_TIME_FORMAT" )", kf_index,
5162            GST_TIME_ARGS (QTSAMPLE_PTS(stream, &stream->samples[kf_index])),
5163            GST_TIME_ARGS (QTSAMPLE_DTS(stream, &stream->samples[kf_index])));
5164       gst_qtdemux_move_stream (qtdemux, stream, kf_index);
5165     } else {
5166       GST_DEBUG_OBJECT (stream->pad,
5167           "moving forwards, keyframe at %u (pts %" GST_TIME_FORMAT " dts %"GST_TIME_FORMAT" ) already sent", kf_index,
5168           GST_TIME_ARGS (QTSAMPLE_PTS (stream, &stream->samples[kf_index])),
5169           GST_TIME_ARGS (QTSAMPLE_DTS (stream, &stream->samples[kf_index])));
5170     }
5171   } else {
5172     GST_DEBUG_OBJECT (stream->pad,
5173         "moving backwards to keyframe at %u (pts %" GST_TIME_FORMAT " dts %"GST_TIME_FORMAT" )", kf_index,
5174         GST_TIME_ARGS (QTSAMPLE_PTS(stream, &stream->samples[kf_index])),
5175         GST_TIME_ARGS (QTSAMPLE_DTS(stream, &stream->samples[kf_index])));
5176     gst_qtdemux_move_stream (qtdemux, stream, kf_index);
5177   }
5178
5179 /* *INDENT-ON* */
5180
5181   return TRUE;
5182 }
5183
5184 /* prepare to get the current sample of @stream, getting essential values.
5185  *
5186  * This function will also prepare and send the segment when needed.
5187  *
5188  * Return FALSE if the stream is EOS.
5189  *
5190  * PULL-BASED
5191  */
5192 static gboolean
5193 gst_qtdemux_prepare_current_sample (GstQTDemux * qtdemux,
5194     QtDemuxStream * stream, gboolean * empty, guint64 * offset, guint * size,
5195     GstClockTime * dts, GstClockTime * pts, GstClockTime * duration,
5196     gboolean * keyframe)
5197 {
5198   QtDemuxSample *sample;
5199   GstClockTime time_position;
5200   guint32 seg_idx;
5201
5202   g_return_val_if_fail (stream != NULL, FALSE);
5203
5204   time_position = stream->time_position;
5205   if (G_UNLIKELY (time_position == GST_CLOCK_TIME_NONE))
5206     goto eos;
5207
5208   seg_idx = stream->segment_index;
5209   if (G_UNLIKELY (seg_idx == -1)) {
5210     /* find segment corresponding to time_position if we are looking
5211      * for a segment. */
5212     seg_idx = gst_qtdemux_find_segment (qtdemux, stream, time_position);
5213   }
5214
5215   /* different segment, activate it, sample_index will be set. */
5216   if (G_UNLIKELY (stream->segment_index != seg_idx))
5217     gst_qtdemux_activate_segment (qtdemux, stream, seg_idx, time_position);
5218
5219   if (G_UNLIKELY (QTSEGMENT_IS_EMPTY (&stream->
5220               segments[stream->segment_index]))) {
5221     QtDemuxSegment *seg = &stream->segments[stream->segment_index];
5222
5223     GST_LOG_OBJECT (qtdemux, "Empty segment activated,"
5224         " prepare empty sample");
5225
5226     *empty = TRUE;
5227     *pts = *dts = time_position;
5228     *duration = seg->duration - (time_position - seg->time);
5229
5230     return TRUE;
5231   }
5232
5233   *empty = FALSE;
5234
5235   if (stream->sample_index == -1)
5236     stream->sample_index = 0;
5237
5238   GST_LOG_OBJECT (qtdemux, "segment active, index = %u of %u",
5239       stream->sample_index, stream->n_samples);
5240
5241   if (G_UNLIKELY (stream->sample_index >= stream->n_samples)) {
5242     if (!qtdemux->fragmented)
5243       goto eos;
5244
5245     GST_INFO_OBJECT (qtdemux, "out of samples, trying to add more");
5246     do {
5247       GstFlowReturn flow;
5248
5249       GST_OBJECT_LOCK (qtdemux);
5250       flow = qtdemux_add_fragmented_samples (qtdemux);
5251       GST_OBJECT_UNLOCK (qtdemux);
5252
5253       if (flow != GST_FLOW_OK)
5254         goto eos;
5255     }
5256     while (stream->sample_index >= stream->n_samples);
5257   }
5258
5259   if (!qtdemux_parse_samples (qtdemux, stream, stream->sample_index)) {
5260     GST_LOG_OBJECT (qtdemux, "Parsing of index %u failed!",
5261         stream->sample_index);
5262     return FALSE;
5263   }
5264
5265   /* now get the info for the sample we're at */
5266   sample = &stream->samples[stream->sample_index];
5267
5268   *dts = QTSAMPLE_DTS (stream, sample);
5269   *pts = QTSAMPLE_PTS (stream, sample);
5270   *offset = sample->offset;
5271   *size = sample->size;
5272   *duration = QTSAMPLE_DUR_DTS (stream, sample, *dts);
5273   *keyframe = QTSAMPLE_KEYFRAME (stream, sample);
5274
5275   return TRUE;
5276
5277   /* special cases */
5278 eos:
5279   {
5280     stream->time_position = GST_CLOCK_TIME_NONE;
5281     return FALSE;
5282   }
5283 }
5284
5285 /* move to the next sample in @stream.
5286  *
5287  * Moves to the next segment when needed.
5288  */
5289 static void
5290 gst_qtdemux_advance_sample (GstQTDemux * qtdemux, QtDemuxStream * stream)
5291 {
5292   QtDemuxSample *sample;
5293   QtDemuxSegment *segment;
5294
5295   /* get current segment */
5296   segment = &stream->segments[stream->segment_index];
5297
5298   if (G_UNLIKELY (QTSEGMENT_IS_EMPTY (segment))) {
5299     GST_DEBUG_OBJECT (qtdemux, "Empty segment, no samples to advance");
5300     goto next_segment;
5301   }
5302
5303   if (G_UNLIKELY (stream->sample_index >= stream->to_sample)) {
5304     /* Mark the stream as EOS */
5305     GST_DEBUG_OBJECT (qtdemux,
5306         "reached max allowed sample %u, mark EOS", stream->to_sample);
5307     stream->time_position = GST_CLOCK_TIME_NONE;
5308     return;
5309   }
5310
5311   /* move to next sample */
5312   stream->sample_index++;
5313   stream->offset_in_sample = 0;
5314
5315   /* reached the last sample, we need the next segment */
5316   if (G_UNLIKELY (stream->sample_index >= stream->n_samples))
5317     goto next_segment;
5318
5319   if (!qtdemux_parse_samples (qtdemux, stream, stream->sample_index)) {
5320     GST_LOG_OBJECT (qtdemux, "Parsing of index %u failed!",
5321         stream->sample_index);
5322     return;
5323   }
5324
5325   /* get next sample */
5326   sample = &stream->samples[stream->sample_index];
5327
5328   /* see if we are past the segment */
5329   if (G_UNLIKELY (QTSAMPLE_DTS (stream, sample) >= segment->media_stop))
5330     goto next_segment;
5331
5332   if (QTSAMPLE_DTS (stream, sample) >= segment->media_start) {
5333     /* inside the segment, update time_position, looks very familiar to
5334      * GStreamer segments, doesn't it? */
5335     stream->time_position =
5336         QTSAMPLE_DTS (stream, sample) - segment->media_start + segment->time;
5337   } else {
5338     /* not yet in segment, time does not yet increment. This means
5339      * that we are still prerolling keyframes to the decoder so it can
5340      * decode the first sample of the segment. */
5341     stream->time_position = segment->time;
5342   }
5343   return;
5344
5345   /* move to the next segment */
5346 next_segment:
5347   {
5348     GST_DEBUG_OBJECT (qtdemux, "segment %d ended ", stream->segment_index);
5349
5350     if (stream->segment_index == stream->n_segments - 1) {
5351       /* are we at the end of the last segment, we're EOS */
5352       stream->time_position = GST_CLOCK_TIME_NONE;
5353     } else {
5354       /* else we're only at the end of the current segment */
5355       stream->time_position = segment->stop_time;
5356     }
5357     /* make sure we select a new segment */
5358
5359     /* accumulate previous segments */
5360     if (GST_CLOCK_TIME_IS_VALID (stream->segment.stop))
5361       stream->accumulated_base +=
5362           (stream->segment.stop -
5363           stream->segment.start) / ABS (stream->segment.rate);
5364
5365     stream->segment_index = -1;
5366   }
5367 }
5368
5369 static void
5370 gst_qtdemux_sync_streams (GstQTDemux * demux)
5371 {
5372   gint i;
5373
5374   if (QTDEMUX_N_STREAMS (demux) <= 1)
5375     return;
5376
5377   for (i = 0; i < QTDEMUX_N_STREAMS (demux); i++) {
5378     QtDemuxStream *stream;
5379     GstClockTime end_time;
5380
5381     stream = QTDEMUX_NTH_STREAM (demux, i);
5382
5383     if (!stream->pad)
5384       continue;
5385
5386     /* TODO advance time on subtitle streams here, if any some day */
5387
5388     /* some clips/trailers may have unbalanced streams at the end,
5389      * so send EOS on shorter stream to prevent stalling others */
5390
5391     /* do not mess with EOS if SEGMENT seeking */
5392     if (demux->segment.flags & GST_SEEK_FLAG_SEGMENT)
5393       continue;
5394
5395     if (demux->pullbased) {
5396       /* loop mode is sample time based */
5397       if (!STREAM_IS_EOS (stream))
5398         continue;
5399     } else {
5400       /* push mode is byte position based */
5401       if (stream->n_samples &&
5402           stream->samples[stream->n_samples - 1].offset >= demux->offset)
5403         continue;
5404     }
5405
5406     if (stream->sent_eos)
5407       continue;
5408
5409     /* only act if some gap */
5410     end_time = stream->segments[stream->n_segments - 1].stop_time;
5411     GST_LOG_OBJECT (demux, "current position: %" GST_TIME_FORMAT
5412         ", stream end: %" GST_TIME_FORMAT,
5413         GST_TIME_ARGS (demux->segment.position), GST_TIME_ARGS (end_time));
5414     if (GST_CLOCK_TIME_IS_VALID (end_time)
5415         && (end_time + 2 * GST_SECOND < demux->segment.position)) {
5416       GstEvent *event;
5417
5418       GST_DEBUG_OBJECT (demux, "sending EOS for stream %s",
5419           GST_PAD_NAME (stream->pad));
5420       stream->sent_eos = TRUE;
5421       event = gst_event_new_eos ();
5422       if (demux->segment_seqnum != GST_SEQNUM_INVALID)
5423         gst_event_set_seqnum (event, demux->segment_seqnum);
5424       gst_pad_push_event (stream->pad, event);
5425     }
5426   }
5427 }
5428
5429 /* EOS and NOT_LINKED need to be combined. This means that we return:
5430  *
5431  *  GST_FLOW_NOT_LINKED: when all pads NOT_LINKED.
5432  *  GST_FLOW_EOS: when all pads EOS or NOT_LINKED.
5433  */
5434 static GstFlowReturn
5435 gst_qtdemux_combine_flows (GstQTDemux * demux, QtDemuxStream * stream,
5436     GstFlowReturn ret)
5437 {
5438   GST_LOG_OBJECT (demux, "flow return: %s", gst_flow_get_name (ret));
5439
5440   if (stream->pad)
5441     ret = gst_flow_combiner_update_pad_flow (demux->flowcombiner, stream->pad,
5442         ret);
5443   else
5444     ret = gst_flow_combiner_update_flow (demux->flowcombiner, ret);
5445
5446   GST_LOG_OBJECT (demux, "combined flow return: %s", gst_flow_get_name (ret));
5447   return ret;
5448 }
5449
5450 /* the input buffer metadata must be writable. Returns NULL when the buffer is
5451  * completely clipped
5452  *
5453  * Should be used only with raw buffers */
5454 static GstBuffer *
5455 gst_qtdemux_clip_buffer (GstQTDemux * qtdemux, QtDemuxStream * stream,
5456     GstBuffer * buf)
5457 {
5458   guint64 start, stop, cstart, cstop, diff;
5459   GstClockTime pts, duration;
5460   gsize size, osize;
5461   gint num_rate, denom_rate;
5462   gint frame_size;
5463   gboolean clip_data;
5464   guint offset;
5465
5466   osize = size = gst_buffer_get_size (buf);
5467   offset = 0;
5468
5469   /* depending on the type, setup the clip parameters */
5470   if (stream->subtype == FOURCC_soun) {
5471     frame_size = CUR_STREAM (stream)->bytes_per_frame;
5472     num_rate = GST_SECOND;
5473     denom_rate = (gint) CUR_STREAM (stream)->rate;
5474     clip_data = TRUE;
5475   } else if (stream->subtype == FOURCC_vide) {
5476     frame_size = size;
5477     num_rate = CUR_STREAM (stream)->fps_n;
5478     denom_rate = CUR_STREAM (stream)->fps_d;
5479     clip_data = FALSE;
5480   } else
5481     goto wrong_type;
5482
5483   if (frame_size <= 0)
5484     goto bad_frame_size;
5485
5486   /* we can only clip if we have a valid pts */
5487   pts = GST_BUFFER_PTS (buf);
5488   if (G_UNLIKELY (!GST_CLOCK_TIME_IS_VALID (pts)))
5489     goto no_pts;
5490
5491   duration = GST_BUFFER_DURATION (buf);
5492
5493   if (G_UNLIKELY (!GST_CLOCK_TIME_IS_VALID (duration))) {
5494     duration =
5495         gst_util_uint64_scale_int (size / frame_size, num_rate, denom_rate);
5496   }
5497
5498   start = pts;
5499   stop = start + duration;
5500
5501   if (G_UNLIKELY (!gst_segment_clip (&stream->segment,
5502               GST_FORMAT_TIME, start, stop, &cstart, &cstop)))
5503     goto clipped;
5504
5505   /* see if some clipping happened */
5506   diff = cstart - start;
5507   if (diff > 0) {
5508     pts += diff;
5509     duration -= diff;
5510
5511     if (clip_data) {
5512       /* bring clipped time to samples and to bytes */
5513       diff = gst_util_uint64_scale_int (diff, denom_rate, num_rate);
5514       diff *= frame_size;
5515
5516       GST_DEBUG_OBJECT (qtdemux,
5517           "clipping start to %" GST_TIME_FORMAT " %"
5518           G_GUINT64_FORMAT " bytes", GST_TIME_ARGS (cstart), diff);
5519
5520       offset = diff;
5521       size -= diff;
5522     }
5523   }
5524   diff = stop - cstop;
5525   if (diff > 0) {
5526     duration -= diff;
5527
5528     if (clip_data) {
5529       /* bring clipped time to samples and then to bytes */
5530       diff = gst_util_uint64_scale_int (diff, denom_rate, num_rate);
5531       diff *= frame_size;
5532       GST_DEBUG_OBJECT (qtdemux,
5533           "clipping stop to %" GST_TIME_FORMAT " %" G_GUINT64_FORMAT
5534           " bytes", GST_TIME_ARGS (cstop), diff);
5535       size -= diff;
5536     }
5537   }
5538
5539   if (offset != 0 || size != osize)
5540     gst_buffer_resize (buf, offset, size);
5541
5542   GST_BUFFER_DTS (buf) = GST_CLOCK_TIME_NONE;
5543   GST_BUFFER_PTS (buf) = pts;
5544   GST_BUFFER_DURATION (buf) = duration;
5545
5546   return buf;
5547
5548   /* dropped buffer */
5549 wrong_type:
5550   {
5551     GST_DEBUG_OBJECT (qtdemux, "unknown stream type");
5552     return buf;
5553   }
5554 bad_frame_size:
5555   {
5556     GST_DEBUG_OBJECT (qtdemux, "bad frame size");
5557     return buf;
5558   }
5559 no_pts:
5560   {
5561     GST_DEBUG_OBJECT (qtdemux, "no pts on buffer");
5562     return buf;
5563   }
5564 clipped:
5565   {
5566     GST_DEBUG_OBJECT (qtdemux, "clipped buffer");
5567     gst_buffer_unref (buf);
5568     return NULL;
5569   }
5570 }
5571
5572 static GstBuffer *
5573 gst_qtdemux_align_buffer (GstQTDemux * demux,
5574     GstBuffer * buffer, gsize alignment)
5575 {
5576   GstMapInfo map;
5577
5578   gst_buffer_map (buffer, &map, GST_MAP_READ);
5579
5580   if (map.size < sizeof (guintptr)) {
5581     gst_buffer_unmap (buffer, &map);
5582     return buffer;
5583   }
5584
5585   if (((guintptr) map.data) & (alignment - 1)) {
5586     GstBuffer *new_buffer;
5587     GstAllocationParams params = { 0, alignment - 1, 0, 0, };
5588
5589     new_buffer = gst_buffer_new_allocate (NULL,
5590         gst_buffer_get_size (buffer), &params);
5591
5592     /* Copy data "by hand", so ensure alignment is kept: */
5593     gst_buffer_fill (new_buffer, 0, map.data, map.size);
5594
5595     gst_buffer_copy_into (new_buffer, buffer, GST_BUFFER_COPY_METADATA, 0, -1);
5596     GST_DEBUG_OBJECT (demux,
5597         "We want output aligned on %" G_GSIZE_FORMAT ", reallocated",
5598         alignment);
5599
5600     gst_buffer_unmap (buffer, &map);
5601     gst_buffer_unref (buffer);
5602
5603     return new_buffer;
5604   }
5605
5606   gst_buffer_unmap (buffer, &map);
5607   return buffer;
5608 }
5609
5610 static guint8 *
5611 convert_to_s334_1a (const guint8 * ccpair, guint8 ccpair_size, guint field,
5612     gsize * res)
5613 {
5614   guint8 *storage;
5615   gsize i;
5616
5617   /* We are converting from pairs to triplets */
5618   *res = ccpair_size / 2 * 3;
5619   storage = g_malloc (*res);
5620   for (i = 0; i * 2 < ccpair_size; i += 1) {
5621     /* FIXME: Use line offset 0 as we simply can't know here */
5622     if (field == 1)
5623       storage[i * 3] = 0x80 | 0x00;
5624     else
5625       storage[i * 3] = 0x00 | 0x00;
5626     storage[i * 3 + 1] = ccpair[i * 2];
5627     storage[i * 3 + 2] = ccpair[i * 2 + 1];
5628   }
5629
5630   return storage;
5631 }
5632
5633 static guint8 *
5634 extract_cc_from_data (QtDemuxStream * stream, const guint8 * data, gsize size,
5635     gsize * cclen)
5636 {
5637   guint8 *res = NULL;
5638   guint32 atom_length, fourcc;
5639   QtDemuxStreamStsdEntry *stsd_entry;
5640
5641   GST_MEMDUMP ("caption atom", data, size);
5642
5643   /* There might be multiple atoms */
5644
5645   *cclen = 0;
5646   if (size < 8)
5647     goto invalid_cdat;
5648   atom_length = QT_UINT32 (data);
5649   fourcc = QT_FOURCC (data + 4);
5650   if (G_UNLIKELY (atom_length > size || atom_length == 8))
5651     goto invalid_cdat;
5652
5653   GST_DEBUG_OBJECT (stream->pad, "here");
5654
5655   /* Check if we have somethig compatible */
5656   stsd_entry = CUR_STREAM (stream);
5657   switch (stsd_entry->fourcc) {
5658     case FOURCC_c608:{
5659       guint8 *cdat = NULL, *cdt2 = NULL;
5660       gsize cdat_size = 0, cdt2_size = 0;
5661       /* Should be cdat or cdt2 */
5662       if (fourcc != FOURCC_cdat && fourcc != FOURCC_cdt2) {
5663         GST_WARNING_OBJECT (stream->pad,
5664             "Unknown data atom (%" GST_FOURCC_FORMAT ") for CEA608",
5665             GST_FOURCC_ARGS (fourcc));
5666         goto invalid_cdat;
5667       }
5668
5669       /* Convert to S334-1 Annex A byte triplet */
5670       if (fourcc == FOURCC_cdat)
5671         cdat = convert_to_s334_1a (data + 8, atom_length - 8, 1, &cdat_size);
5672       else
5673         cdt2 = convert_to_s334_1a (data + 8, atom_length - 8, 2, &cdt2_size);
5674       GST_DEBUG_OBJECT (stream->pad, "size:%" G_GSIZE_FORMAT " atom_length:%u",
5675           size, atom_length);
5676
5677       /* Check for another atom ? */
5678       if (size > atom_length + 8) {
5679         guint32 new_atom_length = QT_UINT32 (data + atom_length);
5680         if (size >= atom_length + new_atom_length) {
5681           fourcc = QT_FOURCC (data + atom_length + 4);
5682           if (fourcc == FOURCC_cdat) {
5683             if (cdat == NULL)
5684               cdat =
5685                   convert_to_s334_1a (data + atom_length + 8,
5686                   new_atom_length - 8, 1, &cdat_size);
5687             else
5688               GST_WARNING_OBJECT (stream->pad,
5689                   "Got multiple [cdat] atoms in a c608 sample. This is unsupported for now. Please file a bug");
5690           } else {
5691             if (cdt2 == NULL)
5692               cdt2 =
5693                   convert_to_s334_1a (data + atom_length + 8,
5694                   new_atom_length - 8, 2, &cdt2_size);
5695             else
5696               GST_WARNING_OBJECT (stream->pad,
5697                   "Got multiple [cdt2] atoms in a c608 sample. This is unsupported for now. Please file a bug");
5698           }
5699         }
5700       }
5701
5702       *cclen = cdat_size + cdt2_size;
5703       res = g_malloc (*cclen);
5704       if (cdat_size)
5705         memcpy (res, cdat, cdat_size);
5706       if (cdt2_size)
5707         memcpy (res + cdat_size, cdt2, cdt2_size);
5708       g_free (cdat);
5709       g_free (cdt2);
5710     }
5711       break;
5712     case FOURCC_c708:
5713       if (fourcc != FOURCC_ccdp) {
5714         GST_WARNING_OBJECT (stream->pad,
5715             "Unknown data atom (%" GST_FOURCC_FORMAT ") for CEA708",
5716             GST_FOURCC_ARGS (fourcc));
5717         goto invalid_cdat;
5718       }
5719       *cclen = atom_length - 8;
5720       res = g_memdup (data + 8, *cclen);
5721       break;
5722     default:
5723       /* Keep this here in case other closed caption formats are added */
5724       g_assert_not_reached ();
5725       break;
5726   }
5727
5728   GST_MEMDUMP ("Output", res, *cclen);
5729   return res;
5730
5731   /* Errors */
5732 invalid_cdat:
5733   GST_WARNING ("[cdat] atom is too small or invalid");
5734   return NULL;
5735 }
5736
5737 /* the input buffer metadata must be writable,
5738  * but time/duration etc not yet set and need not be preserved */
5739 static GstBuffer *
5740 gst_qtdemux_process_buffer (GstQTDemux * qtdemux, QtDemuxStream * stream,
5741     GstBuffer * buf)
5742 {
5743   GstMapInfo map;
5744   guint nsize = 0;
5745   gchar *str;
5746
5747   /* not many cases for now */
5748   if (G_UNLIKELY (CUR_STREAM (stream)->fourcc == FOURCC_mp4s)) {
5749     /* send a one time dvd clut event */
5750     if (stream->pending_event && stream->pad)
5751       gst_pad_push_event (stream->pad, stream->pending_event);
5752     stream->pending_event = NULL;
5753   }
5754
5755   if (G_UNLIKELY (stream->subtype != FOURCC_text
5756           && stream->subtype != FOURCC_sbtl &&
5757           stream->subtype != FOURCC_subp && stream->subtype != FOURCC_clcp)) {
5758     return buf;
5759   }
5760
5761   gst_buffer_map (buf, &map, GST_MAP_READ);
5762
5763   /* empty buffer is sent to terminate previous subtitle */
5764   if (map.size <= 2) {
5765     gst_buffer_unmap (buf, &map);
5766     gst_buffer_unref (buf);
5767     return NULL;
5768   }
5769   if (stream->subtype == FOURCC_subp) {
5770     /* That's all the processing needed for subpictures */
5771     gst_buffer_unmap (buf, &map);
5772     return buf;
5773   }
5774
5775   if (stream->subtype == FOURCC_clcp) {
5776     guint8 *cc;
5777     gsize cclen = 0;
5778     /* For closed caption, we need to extract the information from the
5779      * [cdat],[cdt2] or [ccdp] atom */
5780     cc = extract_cc_from_data (stream, map.data, map.size, &cclen);
5781     gst_buffer_unmap (buf, &map);
5782     gst_buffer_unref (buf);
5783     if (cc) {
5784       buf = _gst_buffer_new_wrapped (cc, cclen, g_free);
5785     } else {
5786       /* Conversion failed or there's nothing */
5787       buf = NULL;
5788     }
5789     return buf;
5790   }
5791
5792   nsize = GST_READ_UINT16_BE (map.data);
5793   nsize = MIN (nsize, map.size - 2);
5794
5795   GST_LOG_OBJECT (qtdemux, "3GPP timed text subtitle: %d/%" G_GSIZE_FORMAT "",
5796       nsize, map.size);
5797
5798   /* takes care of UTF-8 validation or UTF-16 recognition,
5799    * no other encoding expected */
5800   str = gst_tag_freeform_string_to_utf8 ((gchar *) map.data + 2, nsize, NULL);
5801   gst_buffer_unmap (buf, &map);
5802   if (str) {
5803     gst_buffer_unref (buf);
5804     buf = _gst_buffer_new_wrapped (str, strlen (str), g_free);
5805   } else {
5806     /* this should not really happen unless the subtitle is corrupted */
5807     gst_buffer_unref (buf);
5808     buf = NULL;
5809   }
5810
5811   /* FIXME ? convert optional subsequent style info to markup */
5812
5813   return buf;
5814 }
5815
5816 static GstFlowReturn
5817 gst_qtdemux_push_buffer (GstQTDemux * qtdemux, QtDemuxStream * stream,
5818     GstBuffer * buf)
5819 {
5820   GstFlowReturn ret = GST_FLOW_OK;
5821   GstClockTime pts, duration;
5822
5823   if (stream->need_clip)
5824     buf = gst_qtdemux_clip_buffer (qtdemux, stream, buf);
5825
5826   if (G_UNLIKELY (buf == NULL))
5827     goto exit;
5828
5829   if (G_UNLIKELY (stream->discont)) {
5830     GST_LOG_OBJECT (qtdemux, "marking discont buffer");
5831     GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_DISCONT);
5832     stream->discont = FALSE;
5833   } else {
5834     GST_BUFFER_FLAG_UNSET (buf, GST_BUFFER_FLAG_DISCONT);
5835   }
5836
5837   GST_LOG_OBJECT (qtdemux,
5838       "Pushing buffer with dts %" GST_TIME_FORMAT ", pts %" GST_TIME_FORMAT
5839       ", duration %" GST_TIME_FORMAT " on pad %s",
5840       GST_TIME_ARGS (GST_BUFFER_DTS (buf)),
5841       GST_TIME_ARGS (GST_BUFFER_PTS (buf)),
5842       GST_TIME_ARGS (GST_BUFFER_DURATION (buf)), GST_PAD_NAME (stream->pad));
5843
5844   if (stream->protected && stream->protection_scheme_type == FOURCC_cenc) {
5845     GstStructure *crypto_info;
5846     QtDemuxCencSampleSetInfo *info =
5847         (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
5848     gint index;
5849     GstEvent *event;
5850
5851     while ((event = g_queue_pop_head (&stream->protection_scheme_event_queue))) {
5852       GST_TRACE_OBJECT (stream->pad, "pushing protection event: %"
5853           GST_PTR_FORMAT, event);
5854       gst_pad_push_event (stream->pad, event);
5855     }
5856
5857     if (info->crypto_info == NULL) {
5858       GST_DEBUG_OBJECT (qtdemux,
5859           "cenc metadata hasn't been parsed yet, pushing buffer as if it wasn't encrypted");
5860     } else {
5861       /* The end of the crypto_info array matches our n_samples position,
5862        * so count backward from there */
5863       index = stream->sample_index - stream->n_samples + info->crypto_info->len;
5864       if (G_LIKELY (index >= 0 && index < info->crypto_info->len)) {
5865         /* steal structure from array */
5866         crypto_info = g_ptr_array_index (info->crypto_info, index);
5867         g_ptr_array_index (info->crypto_info, index) = NULL;
5868         GST_LOG_OBJECT (qtdemux, "attaching cenc metadata [%u/%u]", index,
5869             info->crypto_info->len);
5870         if (!crypto_info || !gst_buffer_add_protection_meta (buf, crypto_info))
5871           GST_ERROR_OBJECT (qtdemux,
5872               "failed to attach cenc metadata to buffer");
5873       } else {
5874         GST_INFO_OBJECT (qtdemux, "No crypto info with index %d and sample %d",
5875             index, stream->sample_index);
5876       }
5877     }
5878   }
5879
5880   if (stream->alignment > 1)
5881     buf = gst_qtdemux_align_buffer (qtdemux, buf, stream->alignment);
5882
5883   pts = GST_BUFFER_PTS (buf);
5884   duration = GST_BUFFER_DURATION (buf);
5885
5886   ret = gst_pad_push (stream->pad, buf);
5887
5888   if (GST_CLOCK_TIME_IS_VALID (pts) && GST_CLOCK_TIME_IS_VALID (duration)) {
5889     /* mark position in stream, we'll need this to know when to send GAP event */
5890     stream->segment.position = pts + duration;
5891   }
5892
5893 exit:
5894
5895   return ret;
5896 }
5897
5898 static GstFlowReturn
5899 gst_qtdemux_split_and_push_buffer (GstQTDemux * qtdemux, QtDemuxStream * stream,
5900     GstBuffer * buf)
5901 {
5902   GstFlowReturn ret = GST_FLOW_OK;
5903
5904   if (stream->subtype == FOURCC_clcp
5905       && CUR_STREAM (stream)->fourcc == FOURCC_c608 && stream->need_split) {
5906     GstMapInfo map;
5907     guint n_output_buffers, n_field1 = 0, n_field2 = 0;
5908     guint n_triplets, i;
5909     guint field1_off = 0, field2_off = 0;
5910
5911     /* We have to split CEA608 buffers so that each outgoing buffer contains
5912      * one byte pair per field according to the framerate of the video track.
5913      *
5914      * If there is only a single byte pair per field we don't have to do
5915      * anything
5916      */
5917
5918     gst_buffer_map (buf, &map, GST_MAP_READ);
5919
5920     n_triplets = map.size / 3;
5921     for (i = 0; i < n_triplets; i++) {
5922       if (map.data[3 * i] & 0x80)
5923         n_field1++;
5924       else
5925         n_field2++;
5926     }
5927
5928     g_assert (n_field1 || n_field2);
5929
5930     /* If there's more than 1 frame we have to split, otherwise we can just
5931      * pass through */
5932     if (n_field1 > 1 || n_field2 > 1) {
5933       n_output_buffers =
5934           gst_util_uint64_scale (GST_BUFFER_DURATION (buf),
5935           CUR_STREAM (stream)->fps_n, GST_SECOND * CUR_STREAM (stream)->fps_d);
5936
5937       for (i = 0; i < n_output_buffers; i++) {
5938         GstBuffer *outbuf =
5939             gst_buffer_new_and_alloc ((n_field1 ? 3 : 0) + (n_field2 ? 3 : 0));
5940         GstMapInfo outmap;
5941         guint8 *outptr;
5942
5943         gst_buffer_map (outbuf, &outmap, GST_MAP_WRITE);
5944         outptr = outmap.data;
5945
5946         if (n_field1) {
5947           gboolean found = FALSE;
5948
5949           while (map.data + field1_off < map.data + map.size) {
5950             if (map.data[field1_off] & 0x80) {
5951               memcpy (outptr, &map.data[field1_off], 3);
5952               field1_off += 3;
5953               found = TRUE;
5954               break;
5955             }
5956             field1_off += 3;
5957           }
5958
5959           if (!found) {
5960             const guint8 empty[] = { 0x80, 0x80, 0x80 };
5961
5962             memcpy (outptr, empty, 3);
5963           }
5964
5965           outptr += 3;
5966         }
5967
5968         if (n_field2) {
5969           gboolean found = FALSE;
5970
5971           while (map.data + field2_off < map.data + map.size) {
5972             if ((map.data[field2_off] & 0x80) == 0) {
5973               memcpy (outptr, &map.data[field2_off], 3);
5974               field2_off += 3;
5975               found = TRUE;
5976               break;
5977             }
5978             field2_off += 3;
5979           }
5980
5981           if (!found) {
5982             const guint8 empty[] = { 0x00, 0x80, 0x80 };
5983
5984             memcpy (outptr, empty, 3);
5985           }
5986
5987           outptr += 3;
5988         }
5989
5990         gst_buffer_unmap (outbuf, &outmap);
5991
5992         GST_BUFFER_PTS (outbuf) =
5993             GST_BUFFER_PTS (buf) + gst_util_uint64_scale (i,
5994             GST_SECOND * CUR_STREAM (stream)->fps_d,
5995             CUR_STREAM (stream)->fps_n);
5996         GST_BUFFER_DURATION (outbuf) =
5997             gst_util_uint64_scale (GST_SECOND, CUR_STREAM (stream)->fps_d,
5998             CUR_STREAM (stream)->fps_n);
5999         GST_BUFFER_OFFSET (outbuf) = -1;
6000         GST_BUFFER_OFFSET_END (outbuf) = -1;
6001
6002         ret = gst_qtdemux_push_buffer (qtdemux, stream, outbuf);
6003
6004         if (ret != GST_FLOW_OK && ret != GST_FLOW_NOT_LINKED)
6005           break;
6006       }
6007       gst_buffer_unmap (buf, &map);
6008       gst_buffer_unref (buf);
6009     } else {
6010       gst_buffer_unmap (buf, &map);
6011       ret = gst_qtdemux_push_buffer (qtdemux, stream, buf);
6012     }
6013   } else {
6014     ret = gst_qtdemux_push_buffer (qtdemux, stream, buf);
6015   }
6016
6017   return ret;
6018 }
6019
6020 /* Sets a buffer's attributes properly and pushes it downstream.
6021  * Also checks for additional actions and custom processing that may
6022  * need to be done first.
6023  */
6024 static GstFlowReturn
6025 gst_qtdemux_decorate_and_push_buffer (GstQTDemux * qtdemux,
6026     QtDemuxStream * stream, GstBuffer * buf,
6027     GstClockTime dts, GstClockTime pts, GstClockTime duration,
6028     gboolean keyframe, GstClockTime position, guint64 byte_position)
6029 {
6030   GstFlowReturn ret = GST_FLOW_OK;
6031
6032   /* offset the timestamps according to the edit list */
6033
6034   if (G_UNLIKELY (CUR_STREAM (stream)->fourcc == FOURCC_rtsp)) {
6035     gchar *url;
6036     GstMapInfo map;
6037
6038     gst_buffer_map (buf, &map, GST_MAP_READ);
6039     url = g_strndup ((gchar *) map.data, map.size);
6040     gst_buffer_unmap (buf, &map);
6041     if (url != NULL && strlen (url) != 0) {
6042       /* we have RTSP redirect now */
6043       gst_element_post_message (GST_ELEMENT_CAST (qtdemux),
6044           gst_message_new_element (GST_OBJECT_CAST (qtdemux),
6045               gst_structure_new ("redirect",
6046                   "new-location", G_TYPE_STRING, url, NULL)));
6047       qtdemux->posted_redirect = TRUE;
6048     } else {
6049       GST_WARNING_OBJECT (qtdemux, "Redirect URI of stream is empty, not "
6050           "posting");
6051     }
6052     g_free (url);
6053   }
6054
6055   /* position reporting */
6056   if (qtdemux->segment.rate >= 0) {
6057     qtdemux->segment.position = position;
6058     gst_qtdemux_sync_streams (qtdemux);
6059   }
6060
6061   if (G_UNLIKELY (!stream->pad)) {
6062     GST_DEBUG_OBJECT (qtdemux, "No output pad for stream, ignoring");
6063     gst_buffer_unref (buf);
6064     goto exit;
6065   }
6066
6067   /* send out pending buffers */
6068   while (stream->buffers) {
6069     GstBuffer *buffer = (GstBuffer *) stream->buffers->data;
6070
6071     if (G_UNLIKELY (stream->discont)) {
6072       GST_LOG_OBJECT (qtdemux, "marking discont buffer");
6073       GST_BUFFER_FLAG_SET (buffer, GST_BUFFER_FLAG_DISCONT);
6074       stream->discont = FALSE;
6075     } else {
6076       GST_BUFFER_FLAG_UNSET (buf, GST_BUFFER_FLAG_DISCONT);
6077     }
6078
6079     if (stream->alignment > 1)
6080       buffer = gst_qtdemux_align_buffer (qtdemux, buffer, stream->alignment);
6081     gst_pad_push (stream->pad, buffer);
6082
6083     stream->buffers = g_slist_delete_link (stream->buffers, stream->buffers);
6084   }
6085
6086   /* we're going to modify the metadata */
6087   buf = gst_buffer_make_writable (buf);
6088
6089   if (G_UNLIKELY (stream->need_process))
6090     buf = gst_qtdemux_process_buffer (qtdemux, stream, buf);
6091
6092   if (!buf) {
6093     goto exit;
6094   }
6095
6096   GST_BUFFER_DTS (buf) = dts;
6097   GST_BUFFER_PTS (buf) = pts;
6098   GST_BUFFER_DURATION (buf) = duration;
6099   GST_BUFFER_OFFSET (buf) = -1;
6100   GST_BUFFER_OFFSET_END (buf) = -1;
6101
6102   if (!keyframe) {
6103     GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_DELTA_UNIT);
6104     stream->on_keyframe = FALSE;
6105   } else {
6106     stream->on_keyframe = TRUE;
6107   }
6108
6109   if (G_UNLIKELY (CUR_STREAM (stream)->rgb8_palette))
6110     gst_buffer_append_memory (buf,
6111         gst_memory_ref (CUR_STREAM (stream)->rgb8_palette));
6112
6113   if (G_UNLIKELY (CUR_STREAM (stream)->padding)) {
6114     gst_buffer_resize (buf, CUR_STREAM (stream)->padding, -1);
6115   }
6116 #if 0
6117   if (G_UNLIKELY (qtdemux->element_index)) {
6118     GstClockTime stream_time;
6119
6120     stream_time =
6121         gst_segment_to_stream_time (&stream->segment, GST_FORMAT_TIME,
6122         timestamp);
6123     if (GST_CLOCK_TIME_IS_VALID (stream_time)) {
6124       GST_LOG_OBJECT (qtdemux,
6125           "adding association %" GST_TIME_FORMAT "-> %"
6126           G_GUINT64_FORMAT, GST_TIME_ARGS (stream_time), byte_position);
6127       gst_index_add_association (qtdemux->element_index,
6128           qtdemux->index_id,
6129           keyframe ? GST_ASSOCIATION_FLAG_KEY_UNIT :
6130           GST_ASSOCIATION_FLAG_DELTA_UNIT, GST_FORMAT_TIME, stream_time,
6131           GST_FORMAT_BYTES, byte_position, NULL);
6132     }
6133   }
6134 #endif
6135
6136   ret = gst_qtdemux_split_and_push_buffer (qtdemux, stream, buf);
6137
6138 exit:
6139   return ret;
6140 }
6141
6142 static const QtDemuxRandomAccessEntry *
6143 gst_qtdemux_stream_seek_fragment (GstQTDemux * qtdemux, QtDemuxStream * stream,
6144     GstClockTime pos, gboolean after)
6145 {
6146   QtDemuxRandomAccessEntry *entries = stream->ra_entries;
6147   guint n_entries = stream->n_ra_entries;
6148   guint i;
6149
6150   /* we assume the table is sorted */
6151   for (i = 0; i < n_entries; ++i) {
6152     if (entries[i].ts > pos)
6153       break;
6154   }
6155
6156   /* FIXME: maybe save first moof_offset somewhere instead, but for now it's
6157    * probably okay to assume that the index lists the very first fragment */
6158   if (i == 0)
6159     return &entries[0];
6160
6161   if (after)
6162     return &entries[i];
6163   else
6164     return &entries[i - 1];
6165 }
6166
6167 static gboolean
6168 gst_qtdemux_do_fragmented_seek (GstQTDemux * qtdemux)
6169 {
6170   const QtDemuxRandomAccessEntry *best_entry = NULL;
6171   gint i;
6172
6173   GST_OBJECT_LOCK (qtdemux);
6174
6175   g_assert (QTDEMUX_N_STREAMS (qtdemux) > 0);
6176
6177   /* first see if we can determine where to go to using mfra,
6178    * before we start clearing things */
6179   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
6180     const QtDemuxRandomAccessEntry *entry;
6181     QtDemuxStream *stream;
6182     gboolean is_audio_or_video;
6183
6184     stream = QTDEMUX_NTH_STREAM (qtdemux, i);
6185
6186     if (stream->ra_entries == NULL)
6187       continue;
6188
6189     if (stream->subtype == FOURCC_vide || stream->subtype == FOURCC_soun)
6190       is_audio_or_video = TRUE;
6191     else
6192       is_audio_or_video = FALSE;
6193
6194     entry =
6195         gst_qtdemux_stream_seek_fragment (qtdemux, stream,
6196         stream->time_position, !is_audio_or_video);
6197
6198     GST_INFO_OBJECT (stream->pad, "%" GST_TIME_FORMAT " at offset "
6199         "%" G_GUINT64_FORMAT, GST_TIME_ARGS (entry->ts), entry->moof_offset);
6200
6201     stream->pending_seek = entry;
6202
6203     /* decide position to jump to just based on audio/video tracks, not subs */
6204     if (!is_audio_or_video)
6205       continue;
6206
6207     if (best_entry == NULL || entry->moof_offset < best_entry->moof_offset)
6208       best_entry = entry;
6209   }
6210
6211   /* no luck, will handle seek otherwise */
6212   if (best_entry == NULL) {
6213     GST_OBJECT_UNLOCK (qtdemux);
6214     return FALSE;
6215   }
6216
6217   /* ok, now we can prepare for processing as of located moof */
6218   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
6219     QtDemuxStream *stream;
6220
6221     stream = QTDEMUX_NTH_STREAM (qtdemux, i);
6222
6223     g_free (stream->samples);
6224     stream->samples = NULL;
6225     stream->n_samples = 0;
6226     stream->stbl_index = -1;    /* no samples have yet been parsed */
6227     stream->sample_index = -1;
6228
6229     if (stream->protection_scheme_info) {
6230       /* Clear out any old cenc crypto info entries as we'll move to a new moof */
6231       if (stream->protection_scheme_type == FOURCC_cenc) {
6232         QtDemuxCencSampleSetInfo *info =
6233             (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
6234         if (info->crypto_info) {
6235           g_ptr_array_free (info->crypto_info, TRUE);
6236           info->crypto_info = NULL;
6237         }
6238       }
6239     }
6240   }
6241
6242   GST_INFO_OBJECT (qtdemux, "seek to %" GST_TIME_FORMAT ", best fragment "
6243       "moof offset: %" G_GUINT64_FORMAT ", ts %" GST_TIME_FORMAT,
6244       GST_TIME_ARGS (QTDEMUX_NTH_STREAM (qtdemux, 0)->time_position),
6245       best_entry->moof_offset, GST_TIME_ARGS (best_entry->ts));
6246
6247   qtdemux->moof_offset = best_entry->moof_offset;
6248
6249   qtdemux_add_fragmented_samples (qtdemux);
6250
6251   GST_OBJECT_UNLOCK (qtdemux);
6252   return TRUE;
6253 }
6254
6255 static GstFlowReturn
6256 gst_qtdemux_loop_state_movie (GstQTDemux * qtdemux)
6257 {
6258   GstFlowReturn ret = GST_FLOW_OK;
6259   GstBuffer *buf = NULL;
6260   QtDemuxStream *stream, *target_stream = NULL;
6261   GstClockTime min_time;
6262   guint64 offset = 0;
6263   GstClockTime dts = GST_CLOCK_TIME_NONE;
6264   GstClockTime pts = GST_CLOCK_TIME_NONE;
6265   GstClockTime duration = 0;
6266   gboolean keyframe = FALSE;
6267   guint sample_size = 0;
6268   gboolean empty = 0;
6269   guint size;
6270   gint i;
6271
6272   if (qtdemux->fragmented_seek_pending) {
6273     GST_INFO_OBJECT (qtdemux, "pending fragmented seek");
6274     if (gst_qtdemux_do_fragmented_seek (qtdemux)) {
6275       GST_INFO_OBJECT (qtdemux, "fragmented seek done!");
6276       qtdemux->fragmented_seek_pending = FALSE;
6277     } else {
6278       GST_INFO_OBJECT (qtdemux, "fragmented seek still pending");
6279     }
6280   }
6281
6282   /* Figure out the next stream sample to output, min_time is expressed in
6283    * global time and runs over the edit list segments. */
6284   min_time = G_MAXUINT64;
6285   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
6286     GstClockTime position;
6287
6288     stream = QTDEMUX_NTH_STREAM (qtdemux, i);
6289     position = stream->time_position;
6290
6291     /* position of -1 is EOS */
6292     if (position != GST_CLOCK_TIME_NONE && position < min_time) {
6293       min_time = position;
6294       target_stream = stream;
6295     }
6296   }
6297   /* all are EOS */
6298   if (G_UNLIKELY (target_stream == NULL)) {
6299     GST_DEBUG_OBJECT (qtdemux, "all streams are EOS");
6300     goto eos;
6301   }
6302
6303   /* check for segment end */
6304   if (G_UNLIKELY (qtdemux->segment.stop != -1
6305           && ((qtdemux->segment.rate >= 0 && qtdemux->segment.stop <= min_time)
6306               || (qtdemux->segment.rate < 0
6307                   && qtdemux->segment.start > min_time))
6308           && target_stream->on_keyframe)) {
6309     GST_DEBUG_OBJECT (qtdemux, "we reached the end of our segment.");
6310     target_stream->time_position = GST_CLOCK_TIME_NONE;
6311     goto eos_stream;
6312   }
6313
6314   /* gap events for subtitle streams */
6315   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
6316     stream = QTDEMUX_NTH_STREAM (qtdemux, i);
6317     if (stream->pad && (stream->subtype == FOURCC_subp
6318             || stream->subtype == FOURCC_text
6319             || stream->subtype == FOURCC_sbtl)) {
6320       /* send one second gap events until the stream catches up */
6321       /* gaps can only be sent after segment is activated (segment.stop is no longer -1) */
6322       while (GST_CLOCK_TIME_IS_VALID (stream->segment.stop) &&
6323           GST_CLOCK_TIME_IS_VALID (stream->segment.position) &&
6324           stream->segment.position + GST_SECOND < min_time) {
6325         GstEvent *gap =
6326             gst_event_new_gap (stream->segment.position, GST_SECOND);
6327         gst_pad_push_event (stream->pad, gap);
6328         stream->segment.position += GST_SECOND;
6329       }
6330     }
6331   }
6332
6333   stream = target_stream;
6334   /* fetch info for the current sample of this stream */
6335   if (G_UNLIKELY (!gst_qtdemux_prepare_current_sample (qtdemux, stream, &empty,
6336               &offset, &sample_size, &dts, &pts, &duration, &keyframe)))
6337     goto eos_stream;
6338
6339   gst_qtdemux_stream_check_and_change_stsd_index (qtdemux, stream);
6340   if (stream->new_caps) {
6341     gst_qtdemux_configure_stream (qtdemux, stream);
6342     qtdemux_do_allocation (stream, qtdemux);
6343   }
6344
6345   /* If we're doing a keyframe-only trickmode, only push keyframes on video streams */
6346   if (G_UNLIKELY (qtdemux->segment.
6347           flags & GST_SEGMENT_FLAG_TRICKMODE_KEY_UNITS)) {
6348     if (stream->subtype == FOURCC_vide && !keyframe) {
6349       GST_LOG_OBJECT (qtdemux, "Skipping non-keyframe on track-id %u",
6350           stream->track_id);
6351       goto next;
6352     }
6353   }
6354
6355   GST_DEBUG_OBJECT (qtdemux,
6356       "pushing from track-id %u, empty %d offset %" G_GUINT64_FORMAT
6357       ", size %d, dts=%" GST_TIME_FORMAT ", pts=%" GST_TIME_FORMAT
6358       ", duration %" GST_TIME_FORMAT, stream->track_id, empty, offset,
6359       sample_size, GST_TIME_ARGS (dts), GST_TIME_ARGS (pts),
6360       GST_TIME_ARGS (duration));
6361
6362   if (G_UNLIKELY (empty)) {
6363     /* empty segment, push a gap if there's a second or more
6364      * difference and move to the next one */
6365     if ((pts + duration - stream->segment.position) >= GST_SECOND)
6366       gst_pad_push_event (stream->pad, gst_event_new_gap (pts, duration));
6367     stream->segment.position = pts + duration;
6368     goto next;
6369   }
6370
6371   /* hmm, empty sample, skip and move to next sample */
6372   if (G_UNLIKELY (sample_size <= 0))
6373     goto next;
6374
6375   /* last pushed sample was out of boundary, goto next sample */
6376   if (G_UNLIKELY (GST_PAD_LAST_FLOW_RETURN (stream->pad) == GST_FLOW_EOS))
6377     goto next;
6378
6379   if (stream->max_buffer_size == 0 || sample_size <= stream->max_buffer_size) {
6380     size = sample_size;
6381   } else {
6382     GST_DEBUG_OBJECT (qtdemux,
6383         "size %d larger than stream max_buffer_size %d, trimming",
6384         sample_size, stream->max_buffer_size);
6385     size =
6386         MIN (sample_size - stream->offset_in_sample, stream->max_buffer_size);
6387   }
6388
6389   if (qtdemux->cenc_aux_info_offset > 0) {
6390     GstMapInfo map;
6391     GstByteReader br;
6392     GstBuffer *aux_info = NULL;
6393
6394     /* pull the data stored before the sample */
6395     ret =
6396         gst_qtdemux_pull_atom (qtdemux, qtdemux->offset,
6397         offset + stream->offset_in_sample - qtdemux->offset, &aux_info);
6398     if (G_UNLIKELY (ret != GST_FLOW_OK))
6399       goto beach;
6400     gst_buffer_map (aux_info, &map, GST_MAP_READ);
6401     GST_DEBUG_OBJECT (qtdemux, "parsing cenc auxiliary info");
6402     gst_byte_reader_init (&br, map.data + 8, map.size);
6403     if (!qtdemux_parse_cenc_aux_info (qtdemux, stream, &br,
6404             qtdemux->cenc_aux_info_sizes, qtdemux->cenc_aux_sample_count)) {
6405       GST_ERROR_OBJECT (qtdemux, "failed to parse cenc auxiliary info");
6406       gst_buffer_unmap (aux_info, &map);
6407       gst_buffer_unref (aux_info);
6408       ret = GST_FLOW_ERROR;
6409       goto beach;
6410     }
6411     gst_buffer_unmap (aux_info, &map);
6412     gst_buffer_unref (aux_info);
6413   }
6414
6415   GST_LOG_OBJECT (qtdemux, "reading %d bytes @ %" G_GUINT64_FORMAT, size,
6416       offset);
6417
6418   if (stream->use_allocator) {
6419     /* if we have a per-stream allocator, use it */
6420     buf = gst_buffer_new_allocate (stream->allocator, size, &stream->params);
6421   }
6422
6423   ret = gst_qtdemux_pull_atom (qtdemux, offset + stream->offset_in_sample,
6424       size, &buf);
6425   if (G_UNLIKELY (ret != GST_FLOW_OK))
6426     goto beach;
6427
6428   if (size != sample_size) {
6429     pts += gst_util_uint64_scale_int (GST_SECOND,
6430         stream->offset_in_sample / CUR_STREAM (stream)->bytes_per_frame,
6431         stream->timescale);
6432     dts +=
6433         gst_util_uint64_scale_int (GST_SECOND,
6434         stream->offset_in_sample / CUR_STREAM (stream)->bytes_per_frame,
6435         stream->timescale);
6436     duration =
6437         gst_util_uint64_scale_int (GST_SECOND,
6438         size / CUR_STREAM (stream)->bytes_per_frame, stream->timescale);
6439   }
6440
6441   ret = gst_qtdemux_decorate_and_push_buffer (qtdemux, stream, buf,
6442       dts, pts, duration, keyframe, min_time, offset);
6443
6444   if (size != sample_size) {
6445     QtDemuxSample *sample = &stream->samples[stream->sample_index];
6446     QtDemuxSegment *segment = &stream->segments[stream->segment_index];
6447
6448     GstClockTime time_position = QTSTREAMTIME_TO_GSTTIME (stream,
6449         sample->timestamp +
6450         stream->offset_in_sample / CUR_STREAM (stream)->bytes_per_frame);
6451     if (time_position >= segment->media_start) {
6452       /* inside the segment, update time_position, looks very familiar to
6453        * GStreamer segments, doesn't it? */
6454       stream->time_position = (time_position - segment->media_start) +
6455           segment->time;
6456     } else {
6457       /* not yet in segment, time does not yet increment. This means
6458        * that we are still prerolling keyframes to the decoder so it can
6459        * decode the first sample of the segment. */
6460       stream->time_position = segment->time;
6461     }
6462   }
6463
6464   /* combine flows */
6465   ret = gst_qtdemux_combine_flows (qtdemux, stream, ret);
6466   /* ignore unlinked, we will not push on the pad anymore and we will EOS when
6467    * we have no more data for the pad to push */
6468   if (ret == GST_FLOW_EOS)
6469     ret = GST_FLOW_OK;
6470
6471   stream->offset_in_sample += size;
6472   if (stream->offset_in_sample >= sample_size) {
6473     gst_qtdemux_advance_sample (qtdemux, stream);
6474   }
6475   goto beach;
6476
6477 next:
6478   gst_qtdemux_advance_sample (qtdemux, stream);
6479
6480 beach:
6481   return ret;
6482
6483   /* special cases */
6484 eos:
6485   {
6486     GST_DEBUG_OBJECT (qtdemux, "No samples left for any streams - EOS");
6487     ret = GST_FLOW_EOS;
6488     goto beach;
6489   }
6490 eos_stream:
6491   {
6492     GST_DEBUG_OBJECT (qtdemux, "No samples left for stream");
6493     /* EOS will be raised if all are EOS */
6494     ret = GST_FLOW_OK;
6495     goto beach;
6496   }
6497 }
6498
6499 static void
6500 gst_qtdemux_loop (GstPad * pad)
6501 {
6502   GstQTDemux *qtdemux;
6503   guint64 cur_offset;
6504   GstFlowReturn ret;
6505
6506   qtdemux = GST_QTDEMUX (gst_pad_get_parent (pad));
6507
6508   cur_offset = qtdemux->offset;
6509   GST_LOG_OBJECT (qtdemux, "loop at position %" G_GUINT64_FORMAT ", state %s",
6510       cur_offset, qt_demux_state_string (qtdemux->state));
6511
6512   switch (qtdemux->state) {
6513     case QTDEMUX_STATE_INITIAL:
6514     case QTDEMUX_STATE_HEADER:
6515       ret = gst_qtdemux_loop_state_header (qtdemux);
6516       break;
6517     case QTDEMUX_STATE_MOVIE:
6518       ret = gst_qtdemux_loop_state_movie (qtdemux);
6519       if (qtdemux->segment.rate < 0 && ret == GST_FLOW_EOS) {
6520         ret = gst_qtdemux_seek_to_previous_keyframe (qtdemux);
6521       }
6522       break;
6523     default:
6524       /* ouch */
6525       goto invalid_state;
6526   }
6527
6528   /* if something went wrong, pause */
6529   if (ret != GST_FLOW_OK)
6530     goto pause;
6531
6532 done:
6533   gst_object_unref (qtdemux);
6534   return;
6535
6536   /* ERRORS */
6537 invalid_state:
6538   {
6539     GST_ELEMENT_ERROR (qtdemux, STREAM, FAILED,
6540         (NULL), ("streaming stopped, invalid state"));
6541     gst_pad_pause_task (pad);
6542     gst_qtdemux_push_event (qtdemux, gst_event_new_eos ());
6543     goto done;
6544   }
6545 pause:
6546   {
6547     const gchar *reason = gst_flow_get_name (ret);
6548
6549     GST_LOG_OBJECT (qtdemux, "pausing task, reason %s", reason);
6550
6551     gst_pad_pause_task (pad);
6552
6553     /* fatal errors need special actions */
6554     /* check EOS */
6555     if (ret == GST_FLOW_EOS) {
6556       if (QTDEMUX_N_STREAMS (qtdemux) == 0) {
6557         /* we have no streams, post an error */
6558         gst_qtdemux_post_no_playable_stream_error (qtdemux);
6559       }
6560       if (qtdemux->segment.flags & GST_SEEK_FLAG_SEGMENT) {
6561         gint64 stop;
6562
6563         if ((stop = qtdemux->segment.stop) == -1)
6564           stop = qtdemux->segment.duration;
6565
6566         if (qtdemux->segment.rate >= 0) {
6567           GstMessage *message;
6568           GstEvent *event;
6569
6570           GST_LOG_OBJECT (qtdemux, "Sending segment done, at end of segment");
6571           message = gst_message_new_segment_done (GST_OBJECT_CAST (qtdemux),
6572               GST_FORMAT_TIME, stop);
6573           event = gst_event_new_segment_done (GST_FORMAT_TIME, stop);
6574           if (qtdemux->segment_seqnum != GST_SEQNUM_INVALID) {
6575             gst_message_set_seqnum (message, qtdemux->segment_seqnum);
6576             gst_event_set_seqnum (event, qtdemux->segment_seqnum);
6577           }
6578           gst_element_post_message (GST_ELEMENT_CAST (qtdemux), message);
6579           gst_qtdemux_push_event (qtdemux, event);
6580         } else {
6581           GstMessage *message;
6582           GstEvent *event;
6583
6584           /*  For Reverse Playback */
6585           GST_LOG_OBJECT (qtdemux, "Sending segment done, at start of segment");
6586           message = gst_message_new_segment_done (GST_OBJECT_CAST (qtdemux),
6587               GST_FORMAT_TIME, qtdemux->segment.start);
6588           event = gst_event_new_segment_done (GST_FORMAT_TIME,
6589               qtdemux->segment.start);
6590           if (qtdemux->segment_seqnum != GST_SEQNUM_INVALID) {
6591             gst_message_set_seqnum (message, qtdemux->segment_seqnum);
6592             gst_event_set_seqnum (event, qtdemux->segment_seqnum);
6593           }
6594           gst_element_post_message (GST_ELEMENT_CAST (qtdemux), message);
6595           gst_qtdemux_push_event (qtdemux, event);
6596         }
6597       } else {
6598         GstEvent *event;
6599
6600         GST_LOG_OBJECT (qtdemux, "Sending EOS at end of segment");
6601         event = gst_event_new_eos ();
6602         if (qtdemux->segment_seqnum != GST_SEQNUM_INVALID)
6603           gst_event_set_seqnum (event, qtdemux->segment_seqnum);
6604         gst_qtdemux_push_event (qtdemux, event);
6605       }
6606     } else if (ret == GST_FLOW_NOT_LINKED || ret < GST_FLOW_EOS) {
6607       GST_ELEMENT_FLOW_ERROR (qtdemux, ret);
6608       gst_qtdemux_push_event (qtdemux, gst_event_new_eos ());
6609     }
6610     goto done;
6611   }
6612 }
6613
6614 /*
6615  * has_next_entry
6616  *
6617  * Returns if there are samples to be played.
6618  */
6619 static gboolean
6620 has_next_entry (GstQTDemux * demux)
6621 {
6622   QtDemuxStream *stream;
6623   gint i;
6624
6625   GST_DEBUG_OBJECT (demux, "Checking if there are samples not played yet");
6626
6627   for (i = 0; i < QTDEMUX_N_STREAMS (demux); i++) {
6628     stream = QTDEMUX_NTH_STREAM (demux, i);
6629
6630     if (stream->sample_index == -1) {
6631       stream->sample_index = 0;
6632       stream->offset_in_sample = 0;
6633     }
6634
6635     if (stream->sample_index >= stream->n_samples) {
6636       GST_LOG_OBJECT (demux, "track-id %u samples exhausted", stream->track_id);
6637       continue;
6638     }
6639     GST_DEBUG_OBJECT (demux, "Found a sample");
6640     return TRUE;
6641   }
6642
6643   GST_DEBUG_OBJECT (demux, "There wasn't any next sample");
6644   return FALSE;
6645 }
6646
6647 /*
6648  * next_entry_size
6649  *
6650  * Returns the size of the first entry at the current offset.
6651  * If -1, there are none (which means EOS or empty file).
6652  */
6653 static guint64
6654 next_entry_size (GstQTDemux * demux)
6655 {
6656   QtDemuxStream *stream, *target_stream = NULL;
6657   guint64 smalloffs = (guint64) - 1;
6658   QtDemuxSample *sample;
6659   gint i;
6660
6661   GST_LOG_OBJECT (demux, "Finding entry at offset %" G_GUINT64_FORMAT,
6662       demux->offset);
6663
6664   for (i = 0; i < QTDEMUX_N_STREAMS (demux); i++) {
6665     stream = QTDEMUX_NTH_STREAM (demux, i);
6666
6667     if (stream->sample_index == -1) {
6668       stream->sample_index = 0;
6669       stream->offset_in_sample = 0;
6670     }
6671
6672     if (stream->sample_index >= stream->n_samples) {
6673       GST_LOG_OBJECT (demux, "track-id %u samples exhausted", stream->track_id);
6674       continue;
6675     }
6676
6677     if (!qtdemux_parse_samples (demux, stream, stream->sample_index)) {
6678       GST_LOG_OBJECT (demux, "Parsing of index %u from stbl atom failed!",
6679           stream->sample_index);
6680       return -1;
6681     }
6682
6683     sample = &stream->samples[stream->sample_index];
6684
6685     GST_LOG_OBJECT (demux,
6686         "Checking track-id %u (sample_index:%d / offset:%" G_GUINT64_FORMAT
6687         " / size:%" G_GUINT32_FORMAT ")", stream->track_id,
6688         stream->sample_index, sample->offset, sample->size);
6689
6690     if (((smalloffs == -1)
6691             || (sample->offset < smalloffs)) && (sample->size)) {
6692       smalloffs = sample->offset;
6693       target_stream = stream;
6694     }
6695   }
6696
6697   if (!target_stream)
6698     return -1;
6699
6700   GST_LOG_OBJECT (demux,
6701       "track-id %u offset %" G_GUINT64_FORMAT " demux->offset :%"
6702       G_GUINT64_FORMAT, target_stream->track_id, smalloffs, demux->offset);
6703
6704   stream = target_stream;
6705   sample = &stream->samples[stream->sample_index];
6706
6707   if (sample->offset >= demux->offset) {
6708     demux->todrop = sample->offset - demux->offset;
6709     return sample->size + demux->todrop;
6710   }
6711
6712   GST_DEBUG_OBJECT (demux,
6713       "There wasn't any entry at offset %" G_GUINT64_FORMAT, demux->offset);
6714   return -1;
6715 }
6716
6717 static void
6718 gst_qtdemux_post_progress (GstQTDemux * demux, gint num, gint denom)
6719 {
6720   gint perc = (gint) ((gdouble) num * 100.0 / (gdouble) denom);
6721
6722   gst_element_post_message (GST_ELEMENT_CAST (demux),
6723       gst_message_new_element (GST_OBJECT_CAST (demux),
6724           gst_structure_new ("progress", "percent", G_TYPE_INT, perc, NULL)));
6725 }
6726
6727 static gboolean
6728 qtdemux_seek_offset (GstQTDemux * demux, guint64 offset)
6729 {
6730   GstEvent *event;
6731   gboolean res = 0;
6732
6733   GST_DEBUG_OBJECT (demux, "Seeking to %" G_GUINT64_FORMAT, offset);
6734
6735   event =
6736       gst_event_new_seek (1.0, GST_FORMAT_BYTES,
6737       GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_ACCURATE, GST_SEEK_TYPE_SET, offset,
6738       GST_SEEK_TYPE_NONE, -1);
6739
6740   /* store seqnum to drop flush events, they don't need to reach downstream */
6741   demux->offset_seek_seqnum = gst_event_get_seqnum (event);
6742   res = gst_pad_push_event (demux->sinkpad, event);
6743   demux->offset_seek_seqnum = GST_SEQNUM_INVALID;
6744
6745   return res;
6746 }
6747
6748 /* check for seekable upstream, above and beyond a mere query */
6749 static void
6750 gst_qtdemux_check_seekability (GstQTDemux * demux)
6751 {
6752   GstQuery *query;
6753   gboolean seekable = FALSE;
6754   gint64 start = -1, stop = -1;
6755
6756   if (demux->upstream_size)
6757     return;
6758
6759   if (demux->upstream_format_is_time)
6760     return;
6761
6762   query = gst_query_new_seeking (GST_FORMAT_BYTES);
6763   if (!gst_pad_peer_query (demux->sinkpad, query)) {
6764     GST_DEBUG_OBJECT (demux, "seeking query failed");
6765     goto done;
6766   }
6767
6768   gst_query_parse_seeking (query, NULL, &seekable, &start, &stop);
6769
6770   /* try harder to query upstream size if we didn't get it the first time */
6771   if (seekable && stop == -1) {
6772     GST_DEBUG_OBJECT (demux, "doing duration query to fix up unset stop");
6773     gst_pad_peer_query_duration (demux->sinkpad, GST_FORMAT_BYTES, &stop);
6774   }
6775
6776   /* if upstream doesn't know the size, it's likely that it's not seekable in
6777    * practice even if it technically may be seekable */
6778   if (seekable && (start != 0 || stop <= start)) {
6779     GST_DEBUG_OBJECT (demux, "seekable but unknown start/stop -> disable");
6780     seekable = FALSE;
6781   }
6782
6783 done:
6784   gst_query_unref (query);
6785
6786   GST_DEBUG_OBJECT (demux, "seekable: %d (%" G_GUINT64_FORMAT " - %"
6787       G_GUINT64_FORMAT ")", seekable, start, stop);
6788   demux->upstream_seekable = seekable;
6789   demux->upstream_size = seekable ? stop : -1;
6790 }
6791
6792 static void
6793 gst_qtdemux_drop_data (GstQTDemux * demux, gint bytes)
6794 {
6795   g_return_if_fail (bytes <= demux->todrop);
6796
6797   GST_LOG_OBJECT (demux, "Dropping %d bytes", bytes);
6798   gst_adapter_flush (demux->adapter, bytes);
6799   demux->neededbytes -= bytes;
6800   demux->offset += bytes;
6801   demux->todrop -= bytes;
6802 }
6803
6804 /* PUSH-MODE only: Send a segment, if not done already. */
6805 static void
6806 gst_qtdemux_check_send_pending_segment (GstQTDemux * demux)
6807 {
6808   if (G_UNLIKELY (demux->need_segment)) {
6809     gint i;
6810
6811     if (!demux->upstream_format_is_time) {
6812       gst_qtdemux_map_and_push_segments (demux, &demux->segment);
6813     } else {
6814       GstEvent *segment_event;
6815       segment_event = gst_event_new_segment (&demux->segment);
6816       if (demux->segment_seqnum != GST_SEQNUM_INVALID)
6817         gst_event_set_seqnum (segment_event, demux->segment_seqnum);
6818       gst_qtdemux_push_event (demux, segment_event);
6819     }
6820
6821     demux->need_segment = FALSE;
6822
6823     /* clear to send tags on all streams */
6824     for (i = 0; i < QTDEMUX_N_STREAMS (demux); i++) {
6825       QtDemuxStream *stream = QTDEMUX_NTH_STREAM (demux, i);
6826       gst_qtdemux_push_tags (demux, stream);
6827       if (CUR_STREAM (stream)->sparse) {
6828         GST_INFO_OBJECT (demux, "Sending gap event on stream %d", i);
6829         gst_pad_push_event (stream->pad,
6830             gst_event_new_gap (stream->segment.position, GST_CLOCK_TIME_NONE));
6831       }
6832     }
6833   }
6834 }
6835
6836 /* Used for push mode only. */
6837 static void
6838 gst_qtdemux_send_gap_for_segment (GstQTDemux * demux,
6839     QtDemuxStream * stream, gint segment_index, GstClockTime pos)
6840 {
6841   GstClockTime ts, dur;
6842
6843   ts = pos;
6844   dur =
6845       stream->segments[segment_index].duration - (pos -
6846       stream->segments[segment_index].time);
6847   stream->time_position += dur;
6848
6849   /* Only gaps with a duration of at least one second are propagated.
6850    * Same workaround as in pull mode.
6851    * (See 2e45926a96ec5298c6ef29bf912e5e6a06dc3e0e) */
6852   if (dur >= GST_SECOND) {
6853     GstEvent *gap;
6854     gap = gst_event_new_gap (ts, dur);
6855
6856     GST_DEBUG_OBJECT (stream->pad, "Pushing gap for empty "
6857         "segment: %" GST_PTR_FORMAT, gap);
6858     gst_pad_push_event (stream->pad, gap);
6859   }
6860 }
6861
6862 static GstFlowReturn
6863 gst_qtdemux_chain (GstPad * sinkpad, GstObject * parent, GstBuffer * inbuf)
6864 {
6865   GstQTDemux *demux;
6866
6867   demux = GST_QTDEMUX (parent);
6868
6869   GST_DEBUG_OBJECT (demux,
6870       "Received buffer pts:%" GST_TIME_FORMAT " dts:%" GST_TIME_FORMAT
6871       " offset:%" G_GUINT64_FORMAT " size:%" G_GSIZE_FORMAT " demux offset:%"
6872       G_GUINT64_FORMAT, GST_TIME_ARGS (GST_BUFFER_PTS (inbuf)),
6873       GST_TIME_ARGS (GST_BUFFER_DTS (inbuf)), GST_BUFFER_OFFSET (inbuf),
6874       gst_buffer_get_size (inbuf), demux->offset);
6875
6876   if (GST_BUFFER_FLAG_IS_SET (inbuf, GST_BUFFER_FLAG_DISCONT)) {
6877     gboolean is_gap_input = FALSE;
6878     gint i;
6879
6880     GST_DEBUG_OBJECT (demux, "Got DISCONT, marking all streams as DISCONT");
6881
6882     for (i = 0; i < QTDEMUX_N_STREAMS (demux); i++) {
6883       QTDEMUX_NTH_STREAM (demux, i)->discont = TRUE;
6884     }
6885
6886     /* Check if we can land back on our feet in the case where upstream is
6887      * handling the seeking/pushing of samples with gaps in between (like
6888      * in the case of trick-mode DASH for example) */
6889     if (demux->upstream_format_is_time
6890         && GST_BUFFER_OFFSET (inbuf) != GST_BUFFER_OFFSET_NONE) {
6891       for (i = 0; i < QTDEMUX_N_STREAMS (demux); i++) {
6892         guint32 res;
6893         QtDemuxStream *stream = QTDEMUX_NTH_STREAM (demux, i);
6894         GST_LOG_OBJECT (demux,
6895             "track-id #%u , checking if offset %" G_GUINT64_FORMAT
6896             " is a sample start", stream->track_id, GST_BUFFER_OFFSET (inbuf));
6897         res =
6898             gst_qtdemux_find_index_for_given_media_offset_linear (demux,
6899             stream, GST_BUFFER_OFFSET (inbuf));
6900         if (res != -1) {
6901           QtDemuxSample *sample = &stream->samples[res];
6902           GST_LOG_OBJECT (demux,
6903               "Checking if sample %d from track-id %u is valid (offset:%"
6904               G_GUINT64_FORMAT " size:%" G_GUINT32_FORMAT ")", res,
6905               stream->track_id, sample->offset, sample->size);
6906           if (sample->offset == GST_BUFFER_OFFSET (inbuf)) {
6907             GST_LOG_OBJECT (demux,
6908                 "new buffer corresponds to a valid sample : %" G_GUINT32_FORMAT,
6909                 res);
6910             is_gap_input = TRUE;
6911             /* We can go back to standard playback mode */
6912             demux->state = QTDEMUX_STATE_MOVIE;
6913             /* Remember which sample this stream is at */
6914             stream->sample_index = res;
6915             /* Finally update all push-based values to the expected values */
6916             demux->neededbytes = stream->samples[res].size;
6917             demux->offset = GST_BUFFER_OFFSET (inbuf);
6918             demux->mdatleft =
6919                 demux->mdatsize - demux->offset + demux->mdatoffset;
6920             demux->todrop = 0;
6921           }
6922         }
6923       }
6924       if (!is_gap_input) {
6925         GST_DEBUG_OBJECT (demux, "Resetting, actual DISCONT");
6926         /* Reset state if it's a real discont */
6927         demux->neededbytes = 16;
6928         demux->state = QTDEMUX_STATE_INITIAL;
6929         demux->offset = GST_BUFFER_OFFSET (inbuf);
6930         gst_adapter_clear (demux->adapter);
6931       }
6932     }
6933     /* Reverse fragmented playback, need to flush all we have before
6934      * consuming a new fragment.
6935      * The samples array have the timestamps calculated by accumulating the
6936      * durations but this won't work for reverse playback of fragments as
6937      * the timestamps of a subsequent fragment should be smaller than the
6938      * previously received one. */
6939     if (!is_gap_input && demux->fragmented && demux->segment.rate < 0) {
6940       gst_qtdemux_process_adapter (demux, TRUE);
6941       g_ptr_array_foreach (demux->active_streams,
6942           (GFunc) gst_qtdemux_stream_flush_samples_data, NULL);
6943     }
6944   }
6945
6946   gst_adapter_push (demux->adapter, inbuf);
6947
6948   GST_DEBUG_OBJECT (demux,
6949       "pushing in inbuf %p, neededbytes:%u, available:%" G_GSIZE_FORMAT, inbuf,
6950       demux->neededbytes, gst_adapter_available (demux->adapter));
6951
6952   return gst_qtdemux_process_adapter (demux, FALSE);
6953 }
6954
6955 static GstFlowReturn
6956 gst_qtdemux_process_adapter (GstQTDemux * demux, gboolean force)
6957 {
6958   GstFlowReturn ret = GST_FLOW_OK;
6959
6960   /* we never really mean to buffer that much */
6961   if (demux->neededbytes == -1) {
6962     goto eos;
6963   }
6964
6965   while (((gst_adapter_available (demux->adapter)) >= demux->neededbytes) &&
6966       (ret == GST_FLOW_OK || (ret == GST_FLOW_NOT_LINKED && force))) {
6967
6968 #ifndef GST_DISABLE_GST_DEBUG
6969     {
6970       guint64 discont_offset, distance_from_discont;
6971
6972       discont_offset = gst_adapter_offset_at_discont (demux->adapter);
6973       distance_from_discont =
6974           gst_adapter_distance_from_discont (demux->adapter);
6975
6976       GST_DEBUG_OBJECT (demux,
6977           "state:%s , demux->neededbytes:%d, demux->offset:%" G_GUINT64_FORMAT
6978           " adapter offset :%" G_GUINT64_FORMAT " (+ %" G_GUINT64_FORMAT
6979           " bytes)", qt_demux_state_string (demux->state), demux->neededbytes,
6980           demux->offset, discont_offset, distance_from_discont);
6981     }
6982 #endif
6983
6984     switch (demux->state) {
6985       case QTDEMUX_STATE_INITIAL:{
6986         const guint8 *data;
6987         guint32 fourcc;
6988         guint64 size;
6989
6990         gst_qtdemux_check_seekability (demux);
6991
6992         data = gst_adapter_map (demux->adapter, demux->neededbytes);
6993
6994         /* get fourcc/length, set neededbytes */
6995         extract_initial_length_and_fourcc ((guint8 *) data, demux->neededbytes,
6996             &size, &fourcc);
6997         gst_adapter_unmap (demux->adapter);
6998         data = NULL;
6999         GST_DEBUG_OBJECT (demux, "Peeking found [%" GST_FOURCC_FORMAT "] "
7000             "size: %" G_GUINT64_FORMAT, GST_FOURCC_ARGS (fourcc), size);
7001         if (size == 0) {
7002           GST_ELEMENT_ERROR (demux, STREAM, DEMUX,
7003               (_("This file is invalid and cannot be played.")),
7004               ("initial atom '%" GST_FOURCC_FORMAT "' has empty length",
7005                   GST_FOURCC_ARGS (fourcc)));
7006           ret = GST_FLOW_ERROR;
7007           break;
7008         }
7009         if (fourcc == FOURCC_mdat) {
7010           gint next_entry = next_entry_size (demux);
7011           if (QTDEMUX_N_STREAMS (demux) > 0 && (next_entry != -1
7012                   || !demux->fragmented)) {
7013             /* we have the headers, start playback */
7014             demux->state = QTDEMUX_STATE_MOVIE;
7015             demux->neededbytes = next_entry;
7016             demux->mdatleft = size;
7017             demux->mdatsize = demux->mdatleft;
7018           } else {
7019             /* no headers yet, try to get them */
7020             guint bs;
7021             gboolean res;
7022             guint64 old, target;
7023
7024           buffer_data:
7025             old = demux->offset;
7026             target = old + size;
7027
7028             /* try to jump over the atom with a seek */
7029             /* only bother if it seems worth doing so,
7030              * and avoids possible upstream/server problems */
7031             if (demux->upstream_seekable &&
7032                 demux->upstream_size > 4 * (1 << 20)) {
7033               res = qtdemux_seek_offset (demux, target);
7034             } else {
7035               GST_DEBUG_OBJECT (demux, "skipping seek");
7036               res = FALSE;
7037             }
7038
7039             if (res) {
7040               GST_DEBUG_OBJECT (demux, "seek success");
7041               /* remember the offset fo the first mdat so we can seek back to it
7042                * after we have the headers */
7043               if (fourcc == FOURCC_mdat && demux->first_mdat == -1) {
7044                 demux->first_mdat = old;
7045                 GST_DEBUG_OBJECT (demux, "first mdat at %" G_GUINT64_FORMAT,
7046                     demux->first_mdat);
7047               }
7048               /* seek worked, continue reading */
7049               demux->offset = target;
7050               demux->neededbytes = 16;
7051               demux->state = QTDEMUX_STATE_INITIAL;
7052             } else {
7053               /* seek failed, need to buffer */
7054               demux->offset = old;
7055               GST_DEBUG_OBJECT (demux, "seek failed/skipped");
7056               /* there may be multiple mdat (or alike) buffers */
7057               /* sanity check */
7058               if (demux->mdatbuffer)
7059                 bs = gst_buffer_get_size (demux->mdatbuffer);
7060               else
7061                 bs = 0;
7062               if (size + bs > 10 * (1 << 20))
7063                 goto no_moov;
7064               demux->state = QTDEMUX_STATE_BUFFER_MDAT;
7065               demux->neededbytes = size;
7066               if (!demux->mdatbuffer)
7067                 demux->mdatoffset = demux->offset;
7068             }
7069           }
7070         } else if (G_UNLIKELY (size > QTDEMUX_MAX_ATOM_SIZE)) {
7071           GST_ELEMENT_ERROR (demux, STREAM, DEMUX,
7072               (_("This file is invalid and cannot be played.")),
7073               ("atom %" GST_FOURCC_FORMAT " has bogus size %" G_GUINT64_FORMAT,
7074                   GST_FOURCC_ARGS (fourcc), size));
7075           ret = GST_FLOW_ERROR;
7076           break;
7077         } else {
7078           /* this means we already started buffering and still no moov header,
7079            * let's continue buffering everything till we get moov */
7080           if (demux->mdatbuffer && !(fourcc == FOURCC_moov
7081                   || fourcc == FOURCC_moof))
7082             goto buffer_data;
7083           demux->neededbytes = size;
7084           demux->state = QTDEMUX_STATE_HEADER;
7085         }
7086         break;
7087       }
7088       case QTDEMUX_STATE_HEADER:{
7089         const guint8 *data;
7090         guint32 fourcc;
7091
7092         GST_DEBUG_OBJECT (demux, "In header");
7093
7094         data = gst_adapter_map (demux->adapter, demux->neededbytes);
7095
7096         /* parse the header */
7097         extract_initial_length_and_fourcc (data, demux->neededbytes, NULL,
7098             &fourcc);
7099         if (fourcc == FOURCC_moov) {
7100           /* in usual fragmented setup we could try to scan for more
7101            * and end up at the the moov (after mdat) again */
7102           if (demux->got_moov && QTDEMUX_N_STREAMS (demux) > 0 &&
7103               (!demux->fragmented
7104                   || demux->last_moov_offset == demux->offset)) {
7105             GST_DEBUG_OBJECT (demux,
7106                 "Skipping moov atom as we have (this) one already");
7107           } else {
7108             GST_DEBUG_OBJECT (demux, "Parsing [moov]");
7109
7110             if (demux->got_moov && demux->fragmented) {
7111               GST_DEBUG_OBJECT (demux,
7112                   "Got a second moov, clean up data from old one");
7113               if (demux->moov_node_compressed) {
7114                 g_node_destroy (demux->moov_node_compressed);
7115                 if (demux->moov_node)
7116                   g_free (demux->moov_node->data);
7117               }
7118               demux->moov_node_compressed = NULL;
7119               if (demux->moov_node)
7120                 g_node_destroy (demux->moov_node);
7121               demux->moov_node = NULL;
7122             }
7123
7124             demux->last_moov_offset = demux->offset;
7125
7126             /* Update streams with new moov */
7127             gst_qtdemux_stream_concat (demux,
7128                 demux->old_streams, demux->active_streams);
7129
7130             qtdemux_parse_moov (demux, data, demux->neededbytes);
7131             qtdemux_node_dump (demux, demux->moov_node);
7132             qtdemux_parse_tree (demux);
7133             qtdemux_prepare_streams (demux);
7134             QTDEMUX_EXPOSE_LOCK (demux);
7135             qtdemux_expose_streams (demux);
7136             QTDEMUX_EXPOSE_UNLOCK (demux);
7137
7138             demux->got_moov = TRUE;
7139
7140             gst_qtdemux_check_send_pending_segment (demux);
7141
7142             if (demux->moov_node_compressed) {
7143               g_node_destroy (demux->moov_node_compressed);
7144               g_free (demux->moov_node->data);
7145             }
7146             demux->moov_node_compressed = NULL;
7147             g_node_destroy (demux->moov_node);
7148             demux->moov_node = NULL;
7149             GST_DEBUG_OBJECT (demux, "Finished parsing the header");
7150           }
7151         } else if (fourcc == FOURCC_moof) {
7152           if ((demux->got_moov || demux->media_caps) && demux->fragmented) {
7153             guint64 dist = 0;
7154             GstClockTime prev_pts;
7155             guint64 prev_offset;
7156             guint64 adapter_discont_offset, adapter_discont_dist;
7157
7158             GST_DEBUG_OBJECT (demux, "Parsing [moof]");
7159
7160             /*
7161              * The timestamp of the moof buffer is relevant as some scenarios
7162              * won't have the initial timestamp in the atoms. Whenever a new
7163              * buffer has started, we get that buffer's PTS and use it as a base
7164              * timestamp for the trun entries.
7165              *
7166              * To keep track of the current buffer timestamp and starting point
7167              * we use gst_adapter_prev_pts that gives us the PTS and the distance
7168              * from the beggining of the buffer, with the distance and demux->offset
7169              * we know if it is still the same buffer or not.
7170              */
7171             prev_pts = gst_adapter_prev_pts (demux->adapter, &dist);
7172             prev_offset = demux->offset - dist;
7173             if (demux->fragment_start_offset == -1
7174                 || prev_offset > demux->fragment_start_offset) {
7175               demux->fragment_start_offset = prev_offset;
7176               demux->fragment_start = prev_pts;
7177               GST_DEBUG_OBJECT (demux,
7178                   "New fragment start found at: %" G_GUINT64_FORMAT " : %"
7179                   GST_TIME_FORMAT, demux->fragment_start_offset,
7180                   GST_TIME_ARGS (demux->fragment_start));
7181             }
7182
7183             /* We can't use prev_offset() here because this would require
7184              * upstream to set consistent and correct offsets on all buffers
7185              * since the discont. Nothing ever did that in the past and we
7186              * would break backwards compatibility here then.
7187              * Instead take the offset we had at the last discont and count
7188              * the bytes from there. This works with old code as there would
7189              * be no discont between moov and moof, and also works with
7190              * adaptivedemux which correctly sets offset and will set the
7191              * DISCONT flag accordingly when needed.
7192              *
7193              * We also only do this for upstream TIME segments as otherwise
7194              * there are potential backwards compatibility problems with
7195              * seeking in PUSH mode and upstream providing inconsistent
7196              * timestamps. */
7197             adapter_discont_offset =
7198                 gst_adapter_offset_at_discont (demux->adapter);
7199             adapter_discont_dist =
7200                 gst_adapter_distance_from_discont (demux->adapter);
7201
7202             GST_DEBUG_OBJECT (demux,
7203                 "demux offset %" G_GUINT64_FORMAT " adapter offset %"
7204                 G_GUINT64_FORMAT " (+ %" G_GUINT64_FORMAT " bytes)",
7205                 demux->offset, adapter_discont_offset, adapter_discont_dist);
7206
7207             if (demux->upstream_format_is_time) {
7208               demux->moof_offset = adapter_discont_offset;
7209               if (demux->moof_offset != GST_BUFFER_OFFSET_NONE)
7210                 demux->moof_offset += adapter_discont_dist;
7211               if (demux->moof_offset == GST_BUFFER_OFFSET_NONE)
7212                 demux->moof_offset = demux->offset;
7213             } else {
7214               demux->moof_offset = demux->offset;
7215             }
7216
7217             if (!qtdemux_parse_moof (demux, data, demux->neededbytes,
7218                     demux->moof_offset, NULL)) {
7219               gst_adapter_unmap (demux->adapter);
7220               ret = GST_FLOW_ERROR;
7221               goto done;
7222             }
7223
7224             /* in MSS we need to expose the pads after the first moof as we won't get a moov */
7225             if (demux->mss_mode && !demux->exposed) {
7226               QTDEMUX_EXPOSE_LOCK (demux);
7227               qtdemux_expose_streams (demux);
7228               QTDEMUX_EXPOSE_UNLOCK (demux);
7229             }
7230
7231             gst_qtdemux_check_send_pending_segment (demux);
7232           } else {
7233             GST_DEBUG_OBJECT (demux, "Discarding [moof]");
7234           }
7235         } else if (fourcc == FOURCC_ftyp) {
7236           GST_DEBUG_OBJECT (demux, "Parsing [ftyp]");
7237           qtdemux_parse_ftyp (demux, data, demux->neededbytes);
7238         } else if (fourcc == FOURCC_uuid) {
7239           GST_DEBUG_OBJECT (demux, "Parsing [uuid]");
7240           qtdemux_parse_uuid (demux, data, demux->neededbytes);
7241         } else if (fourcc == FOURCC_sidx) {
7242           GST_DEBUG_OBJECT (demux, "Parsing [sidx]");
7243           qtdemux_parse_sidx (demux, data, demux->neededbytes);
7244         } else {
7245           switch (fourcc) {
7246             case FOURCC_styp:
7247               /* [styp] is like a [ftyp], but in fragment header. We ignore it for now
7248                * FALLTHROUGH */
7249             case FOURCC_skip:
7250             case FOURCC_free:
7251               /* [free] and [skip] are padding atoms */
7252               GST_DEBUG_OBJECT (demux,
7253                   "Skipping fourcc while parsing header : %" GST_FOURCC_FORMAT,
7254                   GST_FOURCC_ARGS (fourcc));
7255               break;
7256             default:
7257               GST_WARNING_OBJECT (demux,
7258                   "Unknown fourcc while parsing header : %" GST_FOURCC_FORMAT,
7259                   GST_FOURCC_ARGS (fourcc));
7260               /* Let's jump that one and go back to initial state */
7261               break;
7262           }
7263         }
7264         gst_adapter_unmap (demux->adapter);
7265         data = NULL;
7266
7267         if (demux->mdatbuffer && QTDEMUX_N_STREAMS (demux)) {
7268           gsize remaining_data_size = 0;
7269
7270           /* the mdat was before the header */
7271           GST_DEBUG_OBJECT (demux, "We have n_streams:%d and mdatbuffer:%p",
7272               QTDEMUX_N_STREAMS (demux), demux->mdatbuffer);
7273           /* restore our adapter/offset view of things with upstream;
7274            * put preceding buffered data ahead of current moov data.
7275            * This should also handle evil mdat, moov, mdat cases and alike */
7276           gst_adapter_flush (demux->adapter, demux->neededbytes);
7277
7278           /* Store any remaining data after the mdat for later usage */
7279           remaining_data_size = gst_adapter_available (demux->adapter);
7280           if (remaining_data_size > 0) {
7281             g_assert (demux->restoredata_buffer == NULL);
7282             demux->restoredata_buffer =
7283                 gst_adapter_take_buffer (demux->adapter, remaining_data_size);
7284             demux->restoredata_offset = demux->offset + demux->neededbytes;
7285             GST_DEBUG_OBJECT (demux,
7286                 "Stored %" G_GSIZE_FORMAT " post mdat bytes at offset %"
7287                 G_GUINT64_FORMAT, remaining_data_size,
7288                 demux->restoredata_offset);
7289           }
7290
7291           gst_adapter_push (demux->adapter, demux->mdatbuffer);
7292           demux->mdatbuffer = NULL;
7293           demux->offset = demux->mdatoffset;
7294           demux->neededbytes = next_entry_size (demux);
7295           demux->state = QTDEMUX_STATE_MOVIE;
7296           demux->mdatleft = gst_adapter_available (demux->adapter);
7297           demux->mdatsize = demux->mdatleft;
7298         } else {
7299           GST_DEBUG_OBJECT (demux, "Carrying on normally");
7300           gst_adapter_flush (demux->adapter, demux->neededbytes);
7301
7302           /* only go back to the mdat if there are samples to play */
7303           if (demux->got_moov && demux->first_mdat != -1
7304               && has_next_entry (demux)) {
7305             gboolean res;
7306
7307             /* we need to seek back */
7308             res = qtdemux_seek_offset (demux, demux->first_mdat);
7309             if (res) {
7310               demux->offset = demux->first_mdat;
7311             } else {
7312               GST_DEBUG_OBJECT (demux, "Seek back failed");
7313             }
7314           } else {
7315             demux->offset += demux->neededbytes;
7316           }
7317           demux->neededbytes = 16;
7318           demux->state = QTDEMUX_STATE_INITIAL;
7319         }
7320
7321         break;
7322       }
7323       case QTDEMUX_STATE_BUFFER_MDAT:{
7324         GstBuffer *buf;
7325         guint8 fourcc[4];
7326
7327         GST_DEBUG_OBJECT (demux, "Got our buffer at offset %" G_GUINT64_FORMAT,
7328             demux->offset);
7329         buf = gst_adapter_take_buffer (demux->adapter, demux->neededbytes);
7330         gst_buffer_extract (buf, 0, fourcc, 4);
7331         GST_DEBUG_OBJECT (demux, "mdatbuffer starts with %" GST_FOURCC_FORMAT,
7332             GST_FOURCC_ARGS (QT_FOURCC (fourcc)));
7333         if (demux->mdatbuffer)
7334           demux->mdatbuffer = gst_buffer_append (demux->mdatbuffer, buf);
7335         else
7336           demux->mdatbuffer = buf;
7337         demux->offset += demux->neededbytes;
7338         demux->neededbytes = 16;
7339         demux->state = QTDEMUX_STATE_INITIAL;
7340         gst_qtdemux_post_progress (demux, 1, 1);
7341
7342         break;
7343       }
7344       case QTDEMUX_STATE_MOVIE:{
7345         QtDemuxStream *stream = NULL;
7346         QtDemuxSample *sample;
7347         GstClockTime dts, pts, duration;
7348         gboolean keyframe;
7349         gint i;
7350
7351         GST_DEBUG_OBJECT (demux,
7352             "BEGIN // in MOVIE for offset %" G_GUINT64_FORMAT, demux->offset);
7353
7354         if (demux->fragmented) {
7355           GST_DEBUG_OBJECT (demux, "mdat remaining %" G_GUINT64_FORMAT,
7356               demux->mdatleft);
7357           if (G_LIKELY (demux->todrop < demux->mdatleft)) {
7358             /* if needed data starts within this atom,
7359              * then it should not exceed this atom */
7360             if (G_UNLIKELY (demux->neededbytes > demux->mdatleft)) {
7361               GST_ELEMENT_ERROR (demux, STREAM, DEMUX,
7362                   (_("This file is invalid and cannot be played.")),
7363                   ("sample data crosses atom boundary"));
7364               ret = GST_FLOW_ERROR;
7365               break;
7366             }
7367             demux->mdatleft -= demux->neededbytes;
7368           } else {
7369             GST_DEBUG_OBJECT (demux, "data atom emptied; resuming atom scan");
7370             /* so we are dropping more than left in this atom */
7371             gst_qtdemux_drop_data (demux, demux->mdatleft);
7372             demux->mdatleft = 0;
7373
7374             /* need to resume atom parsing so we do not miss any other pieces */
7375             demux->state = QTDEMUX_STATE_INITIAL;
7376             demux->neededbytes = 16;
7377
7378             /* check if there was any stored post mdat data from previous buffers */
7379             if (demux->restoredata_buffer) {
7380               g_assert (gst_adapter_available (demux->adapter) == 0);
7381
7382               gst_adapter_push (demux->adapter, demux->restoredata_buffer);
7383               demux->restoredata_buffer = NULL;
7384               demux->offset = demux->restoredata_offset;
7385             }
7386
7387             break;
7388           }
7389         }
7390
7391         if (demux->todrop) {
7392           if (demux->cenc_aux_info_offset > 0) {
7393             GstByteReader br;
7394             const guint8 *data;
7395
7396             GST_DEBUG_OBJECT (demux, "parsing cenc auxiliary info");
7397             data = gst_adapter_map (demux->adapter, demux->todrop);
7398             gst_byte_reader_init (&br, data + 8, demux->todrop);
7399             if (!qtdemux_parse_cenc_aux_info (demux,
7400                     QTDEMUX_NTH_STREAM (demux, 0), &br,
7401                     demux->cenc_aux_info_sizes, demux->cenc_aux_sample_count)) {
7402               GST_ERROR_OBJECT (demux, "failed to parse cenc auxiliary info");
7403               ret = GST_FLOW_ERROR;
7404               gst_adapter_unmap (demux->adapter);
7405               g_free (demux->cenc_aux_info_sizes);
7406               demux->cenc_aux_info_sizes = NULL;
7407               goto done;
7408             }
7409             demux->cenc_aux_info_offset = 0;
7410             g_free (demux->cenc_aux_info_sizes);
7411             demux->cenc_aux_info_sizes = NULL;
7412             gst_adapter_unmap (demux->adapter);
7413           }
7414           gst_qtdemux_drop_data (demux, demux->todrop);
7415         }
7416
7417         /* first buffer? */
7418         /* initial newsegment sent here after having added pads,
7419          * possible others in sink_event */
7420         gst_qtdemux_check_send_pending_segment (demux);
7421
7422         /* Figure out which stream this packet belongs to */
7423         for (i = 0; i < QTDEMUX_N_STREAMS (demux); i++) {
7424           stream = QTDEMUX_NTH_STREAM (demux, i);
7425           if (stream->sample_index >= stream->n_samples) {
7426             /* reset to be checked below G_UNLIKELY (stream == NULL) */
7427             stream = NULL;
7428             continue;
7429           }
7430           GST_LOG_OBJECT (demux,
7431               "Checking track-id %u (sample_index:%d / offset:%"
7432               G_GUINT64_FORMAT " / size:%d)", stream->track_id,
7433               stream->sample_index,
7434               stream->samples[stream->sample_index].offset,
7435               stream->samples[stream->sample_index].size);
7436
7437           if (stream->samples[stream->sample_index].offset == demux->offset)
7438             break;
7439         }
7440
7441         if (G_UNLIKELY (stream == NULL))
7442           goto unknown_stream;
7443
7444         gst_qtdemux_stream_check_and_change_stsd_index (demux, stream);
7445
7446         if (stream->new_caps) {
7447           gst_qtdemux_configure_stream (demux, stream);
7448         }
7449
7450         /* Put data in a buffer, set timestamps, caps, ... */
7451         sample = &stream->samples[stream->sample_index];
7452
7453         if (G_LIKELY (!(STREAM_IS_EOS (stream)))) {
7454           GST_DEBUG_OBJECT (demux, "stream : %" GST_FOURCC_FORMAT,
7455               GST_FOURCC_ARGS (CUR_STREAM (stream)->fourcc));
7456
7457           dts = QTSAMPLE_DTS (stream, sample);
7458           pts = QTSAMPLE_PTS (stream, sample);
7459           duration = QTSAMPLE_DUR_DTS (stream, sample, dts);
7460           keyframe = QTSAMPLE_KEYFRAME (stream, sample);
7461
7462           /* check for segment end */
7463           if (G_UNLIKELY (demux->segment.stop != -1
7464                   && demux->segment.stop <= pts && stream->on_keyframe)
7465               && !(demux->upstream_format_is_time && demux->segment.rate < 0)) {
7466             GST_DEBUG_OBJECT (demux, "we reached the end of our segment.");
7467             stream->time_position = GST_CLOCK_TIME_NONE;        /* this means EOS */
7468
7469             /* skip this data, stream is EOS */
7470             gst_adapter_flush (demux->adapter, demux->neededbytes);
7471             demux->offset += demux->neededbytes;
7472
7473             /* check if all streams are eos */
7474             ret = GST_FLOW_EOS;
7475             for (i = 0; i < QTDEMUX_N_STREAMS (demux); i++) {
7476               if (!STREAM_IS_EOS (QTDEMUX_NTH_STREAM (demux, i))) {
7477                 ret = GST_FLOW_OK;
7478                 break;
7479               }
7480             }
7481           } else {
7482             GstBuffer *outbuf;
7483
7484             outbuf =
7485                 gst_adapter_take_buffer (demux->adapter, demux->neededbytes);
7486
7487             /* FIXME: should either be an assert or a plain check */
7488             g_return_val_if_fail (outbuf != NULL, GST_FLOW_ERROR);
7489
7490             ret = gst_qtdemux_decorate_and_push_buffer (demux, stream, outbuf,
7491                 dts, pts, duration, keyframe, dts, demux->offset);
7492           }
7493
7494           /* combine flows */
7495           ret = gst_qtdemux_combine_flows (demux, stream, ret);
7496         } else {
7497           /* skip this data, stream is EOS */
7498           gst_adapter_flush (demux->adapter, demux->neededbytes);
7499         }
7500
7501         stream->sample_index++;
7502         stream->offset_in_sample = 0;
7503
7504         /* update current offset and figure out size of next buffer */
7505         GST_LOG_OBJECT (demux, "increasing offset %" G_GUINT64_FORMAT " by %u",
7506             demux->offset, demux->neededbytes);
7507         demux->offset += demux->neededbytes;
7508         GST_LOG_OBJECT (demux, "offset is now %" G_GUINT64_FORMAT,
7509             demux->offset);
7510
7511
7512         if (ret == GST_FLOW_EOS) {
7513           GST_DEBUG_OBJECT (demux, "All streams are EOS, signal upstream");
7514           demux->neededbytes = -1;
7515           goto eos;
7516         }
7517
7518         if ((demux->neededbytes = next_entry_size (demux)) == -1) {
7519           if (demux->fragmented) {
7520             GST_DEBUG_OBJECT (demux, "(temporarily) out of fragmented samples");
7521             /* there may be more to follow, only finish this atom */
7522             demux->todrop = demux->mdatleft;
7523             demux->neededbytes = demux->todrop;
7524             break;
7525           }
7526           goto eos;
7527         }
7528         if (ret != GST_FLOW_OK && ret != GST_FLOW_NOT_LINKED) {
7529           goto non_ok_unlinked_flow;
7530         }
7531         break;
7532       }
7533       default:
7534         goto invalid_state;
7535     }
7536   }
7537
7538   /* when buffering movie data, at least show user something is happening */
7539   if (ret == GST_FLOW_OK && demux->state == QTDEMUX_STATE_BUFFER_MDAT &&
7540       gst_adapter_available (demux->adapter) <= demux->neededbytes) {
7541     gst_qtdemux_post_progress (demux, gst_adapter_available (demux->adapter),
7542         demux->neededbytes);
7543   }
7544 done:
7545
7546   return ret;
7547
7548   /* ERRORS */
7549 non_ok_unlinked_flow:
7550   {
7551     GST_DEBUG_OBJECT (demux, "Stopping, combined return flow %s",
7552         gst_flow_get_name (ret));
7553     return ret;
7554   }
7555 unknown_stream:
7556   {
7557     GST_ELEMENT_ERROR (demux, STREAM, FAILED, (NULL), ("unknown stream found"));
7558     ret = GST_FLOW_ERROR;
7559     goto done;
7560   }
7561 eos:
7562   {
7563     GST_DEBUG_OBJECT (demux, "no next entry, EOS");
7564     ret = GST_FLOW_EOS;
7565     goto done;
7566   }
7567 invalid_state:
7568   {
7569     GST_ELEMENT_ERROR (demux, STREAM, FAILED,
7570         (NULL), ("qtdemuxer invalid state %d", demux->state));
7571     ret = GST_FLOW_ERROR;
7572     goto done;
7573   }
7574 no_moov:
7575   {
7576     GST_ELEMENT_ERROR (demux, STREAM, FAILED,
7577         (NULL), ("no 'moov' atom within the first 10 MB"));
7578     ret = GST_FLOW_ERROR;
7579     goto done;
7580   }
7581 }
7582
7583 static gboolean
7584 qtdemux_sink_activate (GstPad * sinkpad, GstObject * parent)
7585 {
7586   GstQuery *query;
7587   gboolean pull_mode;
7588
7589   query = gst_query_new_scheduling ();
7590
7591   if (!gst_pad_peer_query (sinkpad, query)) {
7592     gst_query_unref (query);
7593     goto activate_push;
7594   }
7595
7596   pull_mode = gst_query_has_scheduling_mode_with_flags (query,
7597       GST_PAD_MODE_PULL, GST_SCHEDULING_FLAG_SEEKABLE);
7598   gst_query_unref (query);
7599
7600   if (!pull_mode)
7601     goto activate_push;
7602
7603   GST_DEBUG_OBJECT (sinkpad, "activating pull");
7604   return gst_pad_activate_mode (sinkpad, GST_PAD_MODE_PULL, TRUE);
7605
7606 activate_push:
7607   {
7608     GST_DEBUG_OBJECT (sinkpad, "activating push");
7609     return gst_pad_activate_mode (sinkpad, GST_PAD_MODE_PUSH, TRUE);
7610   }
7611 }
7612
7613 static gboolean
7614 qtdemux_sink_activate_mode (GstPad * sinkpad, GstObject * parent,
7615     GstPadMode mode, gboolean active)
7616 {
7617   gboolean res;
7618   GstQTDemux *demux = GST_QTDEMUX (parent);
7619
7620   switch (mode) {
7621     case GST_PAD_MODE_PUSH:
7622       demux->pullbased = FALSE;
7623       res = TRUE;
7624       break;
7625     case GST_PAD_MODE_PULL:
7626       if (active) {
7627         demux->pullbased = TRUE;
7628         res = gst_pad_start_task (sinkpad, (GstTaskFunction) gst_qtdemux_loop,
7629             sinkpad, NULL);
7630       } else {
7631         res = gst_pad_stop_task (sinkpad);
7632       }
7633       break;
7634     default:
7635       res = FALSE;
7636       break;
7637   }
7638   return res;
7639 }
7640
7641 #ifdef HAVE_ZLIB
7642 static void *
7643 qtdemux_inflate (void *z_buffer, guint z_length, guint * length)
7644 {
7645   guint8 *buffer;
7646   z_stream z;
7647   int ret;
7648
7649   memset (&z, 0, sizeof (z));
7650   z.zalloc = NULL;
7651   z.zfree = NULL;
7652   z.opaque = NULL;
7653
7654   if ((ret = inflateInit (&z)) != Z_OK) {
7655     GST_ERROR ("inflateInit() returned %d", ret);
7656     return NULL;
7657   }
7658
7659   z.next_in = z_buffer;
7660   z.avail_in = z_length;
7661
7662   buffer = (guint8 *) g_malloc (*length);
7663   z.avail_out = *length;
7664   z.next_out = (Bytef *) buffer;
7665   do {
7666     ret = inflate (&z, Z_NO_FLUSH);
7667     if (ret == Z_STREAM_END) {
7668       break;
7669     } else if (ret != Z_OK) {
7670       GST_WARNING ("inflate() returned %d", ret);
7671       break;
7672     }
7673
7674     *length += 4096;
7675     buffer = (guint8 *) g_realloc (buffer, *length);
7676     z.next_out = (Bytef *) (buffer + z.total_out);
7677     z.avail_out += 4096;
7678   } while (z.avail_in > 0);
7679
7680   if (ret != Z_STREAM_END) {
7681     g_free (buffer);
7682     buffer = NULL;
7683     *length = 0;
7684   } else {
7685     *length = z.total_out;
7686   }
7687
7688   inflateEnd (&z);
7689
7690   return buffer;
7691 }
7692 #endif /* HAVE_ZLIB */
7693
7694 static gboolean
7695 qtdemux_parse_moov (GstQTDemux * qtdemux, const guint8 * buffer, guint length)
7696 {
7697   GNode *cmov;
7698
7699   qtdemux->moov_node = g_node_new ((guint8 *) buffer);
7700
7701   /* counts as header data */
7702   qtdemux->header_size += length;
7703
7704   GST_DEBUG_OBJECT (qtdemux, "parsing 'moov' atom");
7705   qtdemux_parse_node (qtdemux, qtdemux->moov_node, buffer, length);
7706
7707   cmov = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_cmov);
7708   if (cmov) {
7709     guint32 method;
7710     GNode *dcom;
7711     GNode *cmvd;
7712     guint32 dcom_len;
7713
7714     dcom = qtdemux_tree_get_child_by_type (cmov, FOURCC_dcom);
7715     cmvd = qtdemux_tree_get_child_by_type (cmov, FOURCC_cmvd);
7716     if (dcom == NULL || cmvd == NULL)
7717       goto invalid_compression;
7718
7719     dcom_len = QT_UINT32 (dcom->data);
7720     if (dcom_len < 12)
7721       goto invalid_compression;
7722
7723     method = QT_FOURCC ((guint8 *) dcom->data + 8);
7724     switch (method) {
7725 #ifdef HAVE_ZLIB
7726       case FOURCC_zlib:{
7727         guint uncompressed_length;
7728         guint compressed_length;
7729         guint8 *buf;
7730         guint32 cmvd_len;
7731
7732         cmvd_len = QT_UINT32 ((guint8 *) cmvd->data);
7733         if (cmvd_len < 12)
7734           goto invalid_compression;
7735
7736         uncompressed_length = QT_UINT32 ((guint8 *) cmvd->data + 8);
7737         compressed_length = cmvd_len - 12;
7738         GST_LOG ("length = %u", uncompressed_length);
7739
7740         buf =
7741             (guint8 *) qtdemux_inflate ((guint8 *) cmvd->data + 12,
7742             compressed_length, &uncompressed_length);
7743
7744         if (buf) {
7745           qtdemux->moov_node_compressed = qtdemux->moov_node;
7746           qtdemux->moov_node = g_node_new (buf);
7747
7748           qtdemux_parse_node (qtdemux, qtdemux->moov_node, buf,
7749               uncompressed_length);
7750         }
7751         break;
7752       }
7753 #endif /* HAVE_ZLIB */
7754       default:
7755         GST_WARNING_OBJECT (qtdemux, "unknown or unhandled header compression "
7756             "type %" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (method));
7757         break;
7758     }
7759   }
7760   return TRUE;
7761
7762   /* ERRORS */
7763 invalid_compression:
7764   {
7765     GST_ERROR_OBJECT (qtdemux, "invalid compressed header");
7766     return FALSE;
7767   }
7768 }
7769
7770 static gboolean
7771 qtdemux_parse_container (GstQTDemux * qtdemux, GNode * node, const guint8 * buf,
7772     const guint8 * end)
7773 {
7774   while (G_UNLIKELY (buf < end)) {
7775     GNode *child;
7776     guint32 len;
7777
7778     if (G_UNLIKELY (buf + 4 > end)) {
7779       GST_LOG_OBJECT (qtdemux, "buffer overrun");
7780       break;
7781     }
7782     len = QT_UINT32 (buf);
7783     if (G_UNLIKELY (len == 0)) {
7784       GST_LOG_OBJECT (qtdemux, "empty container");
7785       break;
7786     }
7787     if (G_UNLIKELY (len < 8)) {
7788       GST_WARNING_OBJECT (qtdemux, "length too short (%d < 8)", len);
7789       break;
7790     }
7791     if (G_UNLIKELY (len > (end - buf))) {
7792       GST_WARNING_OBJECT (qtdemux, "length too long (%d > %d)", len,
7793           (gint) (end - buf));
7794       break;
7795     }
7796
7797     child = g_node_new ((guint8 *) buf);
7798     g_node_append (node, child);
7799     GST_LOG_OBJECT (qtdemux, "adding new node of len %d", len);
7800     qtdemux_parse_node (qtdemux, child, buf, len);
7801
7802     buf += len;
7803   }
7804   return TRUE;
7805 }
7806
7807 static gboolean
7808 qtdemux_parse_theora_extension (GstQTDemux * qtdemux, QtDemuxStream * stream,
7809     GNode * xdxt)
7810 {
7811   int len = QT_UINT32 (xdxt->data);
7812   guint8 *buf = xdxt->data;
7813   guint8 *end = buf + len;
7814   GstBuffer *buffer;
7815
7816   /* skip size and type */
7817   buf += 8;
7818   end -= 8;
7819
7820   while (buf < end) {
7821     gint size;
7822     guint32 type;
7823
7824     size = QT_UINT32 (buf);
7825     type = QT_FOURCC (buf + 4);
7826
7827     GST_LOG_OBJECT (qtdemux, "%p %p", buf, end);
7828
7829     if (buf + size > end || size <= 0)
7830       break;
7831
7832     buf += 8;
7833     size -= 8;
7834
7835     GST_WARNING_OBJECT (qtdemux, "have cookie %" GST_FOURCC_FORMAT,
7836         GST_FOURCC_ARGS (type));
7837
7838     switch (type) {
7839       case FOURCC_tCtH:
7840         buffer = gst_buffer_new_and_alloc (size);
7841         gst_buffer_fill (buffer, 0, buf, size);
7842         stream->buffers = g_slist_append (stream->buffers, buffer);
7843         GST_LOG_OBJECT (qtdemux, "parsing theora header");
7844         break;
7845       case FOURCC_tCt_:
7846         buffer = gst_buffer_new_and_alloc (size);
7847         gst_buffer_fill (buffer, 0, buf, size);
7848         stream->buffers = g_slist_append (stream->buffers, buffer);
7849         GST_LOG_OBJECT (qtdemux, "parsing theora comment");
7850         break;
7851       case FOURCC_tCtC:
7852         buffer = gst_buffer_new_and_alloc (size);
7853         gst_buffer_fill (buffer, 0, buf, size);
7854         stream->buffers = g_slist_append (stream->buffers, buffer);
7855         GST_LOG_OBJECT (qtdemux, "parsing theora codebook");
7856         break;
7857       default:
7858         GST_WARNING_OBJECT (qtdemux,
7859             "unknown theora cookie %" GST_FOURCC_FORMAT,
7860             GST_FOURCC_ARGS (type));
7861         break;
7862     }
7863     buf += size;
7864   }
7865   return TRUE;
7866 }
7867
7868 static gboolean
7869 qtdemux_parse_node (GstQTDemux * qtdemux, GNode * node, const guint8 * buffer,
7870     guint length)
7871 {
7872   guint32 fourcc = 0;
7873   guint32 node_length = 0;
7874   const QtNodeType *type;
7875   const guint8 *end;
7876
7877   GST_LOG_OBJECT (qtdemux, "qtdemux_parse buffer %p length %u", buffer, length);
7878
7879   if (G_UNLIKELY (length < 8))
7880     goto not_enough_data;
7881
7882   node_length = QT_UINT32 (buffer);
7883   fourcc = QT_FOURCC (buffer + 4);
7884
7885   /* ignore empty nodes */
7886   if (G_UNLIKELY (fourcc == 0 || node_length == 8))
7887     return TRUE;
7888
7889   type = qtdemux_type_get (fourcc);
7890
7891   end = buffer + length;
7892
7893   GST_LOG_OBJECT (qtdemux,
7894       "parsing '%" GST_FOURCC_FORMAT "', length=%u, name '%s'",
7895       GST_FOURCC_ARGS (fourcc), node_length, type->name);
7896
7897   if (node_length > length)
7898     goto broken_atom_size;
7899
7900   if (type->flags & QT_FLAG_CONTAINER) {
7901     qtdemux_parse_container (qtdemux, node, buffer + 8, end);
7902   } else {
7903     switch (fourcc) {
7904       case FOURCC_stsd:
7905       {
7906         if (node_length < 20) {
7907           GST_LOG_OBJECT (qtdemux, "skipping small stsd box");
7908           break;
7909         }
7910         GST_DEBUG_OBJECT (qtdemux,
7911             "parsing stsd (sample table, sample description) atom");
7912         /* Skip over 8 byte atom hdr + 1 byte version, 3 bytes flags, 4 byte num_entries */
7913         qtdemux_parse_container (qtdemux, node, buffer + 16, end);
7914         break;
7915       }
7916       case FOURCC_mp4a:
7917       case FOURCC_alac:
7918       case FOURCC_fLaC:
7919       {
7920         guint32 version;
7921         guint32 offset;
7922         guint min_size;
7923
7924         /* also read alac (or whatever) in stead of mp4a in the following,
7925          * since a similar layout is used in other cases as well */
7926         if (fourcc == FOURCC_mp4a)
7927           min_size = 20;
7928         else if (fourcc == FOURCC_fLaC)
7929           min_size = 86;
7930         else
7931           min_size = 40;
7932
7933         /* There are two things we might encounter here: a true mp4a atom, and
7934            an mp4a entry in an stsd atom. The latter is what we're interested
7935            in, and it looks like an atom, but isn't really one. The true mp4a
7936            atom is short, so we detect it based on length here. */
7937         if (length < min_size) {
7938           GST_LOG_OBJECT (qtdemux, "skipping small %" GST_FOURCC_FORMAT " box",
7939               GST_FOURCC_ARGS (fourcc));
7940           break;
7941         }
7942
7943         /* 'version' here is the sound sample description version. Types 0 and
7944            1 are documented in the QTFF reference, but type 2 is not: it's
7945            described in Apple header files instead (struct SoundDescriptionV2
7946            in Movies.h) */
7947         version = QT_UINT16 (buffer + 16);
7948
7949         GST_DEBUG_OBJECT (qtdemux, "%" GST_FOURCC_FORMAT " version 0x%08x",
7950             GST_FOURCC_ARGS (fourcc), version);
7951
7952         /* parse any esds descriptors */
7953         switch (version) {
7954           case 0:
7955             offset = 0x24;
7956             break;
7957           case 1:
7958             offset = 0x34;
7959             break;
7960           case 2:
7961             offset = 0x48;
7962             break;
7963           default:
7964             GST_WARNING_OBJECT (qtdemux,
7965                 "unhandled %" GST_FOURCC_FORMAT " version 0x%08x",
7966                 GST_FOURCC_ARGS (fourcc), version);
7967             offset = 0;
7968             break;
7969         }
7970         if (offset)
7971           qtdemux_parse_container (qtdemux, node, buffer + offset, end);
7972         break;
7973       }
7974       case FOURCC_mp4v:
7975       case FOURCC_MP4V:
7976       case FOURCC_fmp4:
7977       case FOURCC_FMP4:
7978       case FOURCC_apcs:
7979       case FOURCC_apch:
7980       case FOURCC_apcn:
7981       case FOURCC_apco:
7982       case FOURCC_ap4h:
7983       case FOURCC_xvid:
7984       case FOURCC_XVID:
7985       case FOURCC_H264:
7986       case FOURCC_avc1:
7987       case FOURCC_avc3:
7988       case FOURCC_H265:
7989       case FOURCC_hvc1:
7990       case FOURCC_hev1:
7991       case FOURCC_mjp2:
7992       case FOURCC_encv:
7993       {
7994         guint32 version;
7995         guint32 str_len;
7996
7997         /* codec_data is contained inside these atoms, which all have
7998          * the same format. */
7999         /* video sample description size is 86 bytes without extension.
8000          * node_length have to be bigger than 86 bytes because video sample
8001          * description can include extenstions such as esds, fiel, glbl, etc. */
8002         if (node_length < 86) {
8003           GST_WARNING_OBJECT (qtdemux, "%" GST_FOURCC_FORMAT
8004               " sample description length too short (%u < 86)",
8005               GST_FOURCC_ARGS (fourcc), node_length);
8006           break;
8007         }
8008
8009         GST_DEBUG_OBJECT (qtdemux, "parsing in %" GST_FOURCC_FORMAT,
8010             GST_FOURCC_ARGS (fourcc));
8011
8012         /* version (2 bytes) : this is set to 0, unless a compressor has changed
8013          *              its data format.
8014          * revision level (2 bytes) : must be set to 0. */
8015         version = QT_UINT32 (buffer + 16);
8016         GST_DEBUG_OBJECT (qtdemux, "version %08x", version);
8017
8018         /* compressor name : PASCAL string and informative purposes
8019          * first byte : the number of bytes to be displayed.
8020          *              it has to be less than 32 because it is reserved
8021          *              space of 32 bytes total including itself. */
8022         str_len = QT_UINT8 (buffer + 50);
8023         if (str_len < 32)
8024           GST_DEBUG_OBJECT (qtdemux, "compressorname = %.*s", str_len,
8025               (char *) buffer + 51);
8026         else
8027           GST_WARNING_OBJECT (qtdemux,
8028               "compressorname length too big (%u > 31)", str_len);
8029
8030         GST_MEMDUMP_OBJECT (qtdemux, "video sample description", buffer,
8031             end - buffer);
8032         qtdemux_parse_container (qtdemux, node, buffer + 86, end);
8033         break;
8034       }
8035       case FOURCC_meta:
8036       {
8037         GST_DEBUG_OBJECT (qtdemux, "parsing meta atom");
8038
8039         /* You are reading this correctly. QTFF specifies that the
8040          * metadata atom is a short atom, whereas ISO BMFF specifies
8041          * it's a full atom. But since so many people are doing things
8042          * differently, we actually peek into the atom to see which
8043          * variant it is */
8044         if (length < 16) {
8045           GST_LOG_OBJECT (qtdemux, "skipping small %" GST_FOURCC_FORMAT " box",
8046               GST_FOURCC_ARGS (fourcc));
8047           break;
8048         }
8049         if (QT_FOURCC (buffer + 12) == FOURCC_hdlr) {
8050           /* Variant 1: What QTFF specifies. 'meta' is a short header which
8051            * starts with a 'hdlr' atom */
8052           qtdemux_parse_container (qtdemux, node, buffer + 8, end);
8053         } else if (QT_UINT32 (buffer + 8) == 0x00000000) {
8054           /* Variant 2: What ISO BMFF specifies. 'meta' is a _full_ atom
8055            * with version/flags both set to zero */
8056           qtdemux_parse_container (qtdemux, node, buffer + 12, end);
8057         } else
8058           GST_WARNING_OBJECT (qtdemux, "Unknown 'meta' atom format");
8059         break;
8060       }
8061       case FOURCC_mp4s:
8062       {
8063         GST_MEMDUMP_OBJECT (qtdemux, "mp4s", buffer, end - buffer);
8064         /* Skip 8 byte header, plus 8 byte version + flags + entry_count */
8065         qtdemux_parse_container (qtdemux, node, buffer + 16, end);
8066         break;
8067       }
8068       case FOURCC_XiTh:
8069       {
8070         guint32 version;
8071         guint32 offset;
8072
8073         if (length < 16) {
8074           GST_LOG_OBJECT (qtdemux, "skipping small %" GST_FOURCC_FORMAT " box",
8075               GST_FOURCC_ARGS (fourcc));
8076           break;
8077         }
8078
8079         version = QT_UINT32 (buffer + 12);
8080         GST_DEBUG_OBJECT (qtdemux, "parsing XiTh atom version 0x%08x", version);
8081
8082         switch (version) {
8083           case 0x00000001:
8084             offset = 0x62;
8085             break;
8086           default:
8087             GST_DEBUG_OBJECT (qtdemux, "unknown version 0x%08x", version);
8088             offset = 0;
8089             break;
8090         }
8091         if (offset) {
8092           if (length < offset) {
8093             GST_WARNING_OBJECT (qtdemux,
8094                 "skipping too small %" GST_FOURCC_FORMAT " box",
8095                 GST_FOURCC_ARGS (fourcc));
8096             break;
8097           }
8098           qtdemux_parse_container (qtdemux, node, buffer + offset, end);
8099         }
8100         break;
8101       }
8102       case FOURCC_in24:
8103       {
8104         qtdemux_parse_container (qtdemux, node, buffer + 0x34, end);
8105         break;
8106       }
8107       case FOURCC_uuid:
8108       {
8109         qtdemux_parse_uuid (qtdemux, buffer, end - buffer);
8110         break;
8111       }
8112       case FOURCC_enca:
8113       {
8114         qtdemux_parse_container (qtdemux, node, buffer + 36, end);
8115         break;
8116       }
8117       default:
8118         if (!strcmp (type->name, "unknown"))
8119           GST_MEMDUMP ("Unknown tag", buffer + 4, end - buffer - 4);
8120         break;
8121     }
8122   }
8123   GST_LOG_OBJECT (qtdemux, "parsed '%" GST_FOURCC_FORMAT "'",
8124       GST_FOURCC_ARGS (fourcc));
8125   return TRUE;
8126
8127 /* ERRORS */
8128 not_enough_data:
8129   {
8130     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
8131         (_("This file is corrupt and cannot be played.")),
8132         ("Not enough data for an atom header, got only %u bytes", length));
8133     return FALSE;
8134   }
8135 broken_atom_size:
8136   {
8137     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
8138         (_("This file is corrupt and cannot be played.")),
8139         ("Atom '%" GST_FOURCC_FORMAT "' has size of %u bytes, but we have only "
8140             "%u bytes available.", GST_FOURCC_ARGS (fourcc), node_length,
8141             length));
8142     return FALSE;
8143   }
8144 }
8145
8146 static GNode *
8147 qtdemux_tree_get_child_by_type (GNode * node, guint32 fourcc)
8148 {
8149   GNode *child;
8150   guint8 *buffer;
8151   guint32 child_fourcc;
8152
8153   for (child = g_node_first_child (node); child;
8154       child = g_node_next_sibling (child)) {
8155     buffer = (guint8 *) child->data;
8156
8157     child_fourcc = QT_FOURCC (buffer + 4);
8158
8159     if (G_UNLIKELY (child_fourcc == fourcc)) {
8160       return child;
8161     }
8162   }
8163   return NULL;
8164 }
8165
8166 static GNode *
8167 qtdemux_tree_get_child_by_type_full (GNode * node, guint32 fourcc,
8168     GstByteReader * parser)
8169 {
8170   GNode *child;
8171   guint8 *buffer;
8172   guint32 child_fourcc, child_len;
8173
8174   for (child = g_node_first_child (node); child;
8175       child = g_node_next_sibling (child)) {
8176     buffer = (guint8 *) child->data;
8177
8178     child_len = QT_UINT32 (buffer);
8179     child_fourcc = QT_FOURCC (buffer + 4);
8180
8181     if (G_UNLIKELY (child_fourcc == fourcc)) {
8182       if (G_UNLIKELY (child_len < (4 + 4)))
8183         return NULL;
8184       /* FIXME: must verify if atom length < parent atom length */
8185       gst_byte_reader_init (parser, buffer + (4 + 4), child_len - (4 + 4));
8186       return child;
8187     }
8188   }
8189   return NULL;
8190 }
8191
8192 static GNode *
8193 qtdemux_tree_get_child_by_index (GNode * node, guint index)
8194 {
8195   return g_node_nth_child (node, index);
8196 }
8197
8198 static GNode *
8199 qtdemux_tree_get_sibling_by_type_full (GNode * node, guint32 fourcc,
8200     GstByteReader * parser)
8201 {
8202   GNode *child;
8203   guint8 *buffer;
8204   guint32 child_fourcc, child_len;
8205
8206   for (child = g_node_next_sibling (node); child;
8207       child = g_node_next_sibling (child)) {
8208     buffer = (guint8 *) child->data;
8209
8210     child_fourcc = QT_FOURCC (buffer + 4);
8211
8212     if (child_fourcc == fourcc) {
8213       if (parser) {
8214         child_len = QT_UINT32 (buffer);
8215         if (G_UNLIKELY (child_len < (4 + 4)))
8216           return NULL;
8217         /* FIXME: must verify if atom length < parent atom length */
8218         gst_byte_reader_init (parser, buffer + (4 + 4), child_len - (4 + 4));
8219       }
8220       return child;
8221     }
8222   }
8223   return NULL;
8224 }
8225
8226 static GNode *
8227 qtdemux_tree_get_sibling_by_type (GNode * node, guint32 fourcc)
8228 {
8229   return qtdemux_tree_get_sibling_by_type_full (node, fourcc, NULL);
8230 }
8231
8232 static void
8233 qtdemux_do_allocation (QtDemuxStream * stream, GstQTDemux * qtdemux)
8234 {
8235 /* FIXME: This can only reliably work if demuxers have a
8236  * separate streaming thread per srcpad. This should be
8237  * done in a demuxer base class, which integrates parts
8238  * of multiqueue
8239  *
8240  * https://bugzilla.gnome.org/show_bug.cgi?id=701856
8241  */
8242 #if 0
8243   GstQuery *query;
8244
8245   query = gst_query_new_allocation (stream->caps, FALSE);
8246
8247   if (!gst_pad_peer_query (stream->pad, query)) {
8248     /* not a problem, just debug a little */
8249     GST_DEBUG_OBJECT (qtdemux, "peer ALLOCATION query failed");
8250   }
8251
8252   if (stream->allocator)
8253     gst_object_unref (stream->allocator);
8254
8255   if (gst_query_get_n_allocation_params (query) > 0) {
8256     /* try the allocator */
8257     gst_query_parse_nth_allocation_param (query, 0, &stream->allocator,
8258         &stream->params);
8259     stream->use_allocator = TRUE;
8260   } else {
8261     stream->allocator = NULL;
8262     gst_allocation_params_init (&stream->params);
8263     stream->use_allocator = FALSE;
8264   }
8265   gst_query_unref (query);
8266 #endif
8267 }
8268
8269 static gboolean
8270 pad_query (const GValue * item, GValue * value, gpointer user_data)
8271 {
8272   GstPad *pad = g_value_get_object (item);
8273   GstQuery *query = user_data;
8274   gboolean res;
8275
8276   res = gst_pad_peer_query (pad, query);
8277
8278   if (res) {
8279     g_value_set_boolean (value, TRUE);
8280     return FALSE;
8281   }
8282
8283   GST_INFO_OBJECT (pad, "pad peer query failed");
8284   return TRUE;
8285 }
8286
8287 static gboolean
8288 gst_qtdemux_run_query (GstElement * element, GstQuery * query,
8289     GstPadDirection direction)
8290 {
8291   GstIterator *it;
8292   GstIteratorFoldFunction func = pad_query;
8293   GValue res = { 0, };
8294
8295   g_value_init (&res, G_TYPE_BOOLEAN);
8296   g_value_set_boolean (&res, FALSE);
8297
8298   /* Ask neighbor */
8299   if (direction == GST_PAD_SRC)
8300     it = gst_element_iterate_src_pads (element);
8301   else
8302     it = gst_element_iterate_sink_pads (element);
8303
8304   while (gst_iterator_fold (it, func, &res, query) == GST_ITERATOR_RESYNC)
8305     gst_iterator_resync (it);
8306
8307   gst_iterator_free (it);
8308
8309   return g_value_get_boolean (&res);
8310 }
8311
8312 static void
8313 gst_qtdemux_request_protection_context (GstQTDemux * qtdemux,
8314     QtDemuxStream * stream)
8315 {
8316   GstQuery *query;
8317   GstContext *ctxt;
8318   GstElement *element = GST_ELEMENT (qtdemux);
8319   GstStructure *st;
8320   gchar **filtered_sys_ids;
8321   GValue event_list = G_VALUE_INIT;
8322   GList *walk;
8323
8324   /* 1. Check if we already have the context. */
8325   if (qtdemux->preferred_protection_system_id != NULL) {
8326     GST_LOG_OBJECT (element,
8327         "already have the protection context, no need to request it again");
8328     return;
8329   }
8330
8331   g_ptr_array_add (qtdemux->protection_system_ids, NULL);
8332   filtered_sys_ids = gst_protection_filter_systems_by_available_decryptors (
8333       (const gchar **) qtdemux->protection_system_ids->pdata);
8334
8335   g_ptr_array_remove_index (qtdemux->protection_system_ids,
8336       qtdemux->protection_system_ids->len - 1);
8337   GST_TRACE_OBJECT (qtdemux, "detected %u protection systems, we have "
8338       "decryptors for %u of them, running context request",
8339       qtdemux->protection_system_ids->len,
8340       filtered_sys_ids ? g_strv_length (filtered_sys_ids) : 0);
8341
8342
8343   if (stream->protection_scheme_event_queue.length) {
8344     GST_TRACE_OBJECT (qtdemux, "using stream event queue, length %u",
8345         stream->protection_scheme_event_queue.length);
8346     walk = stream->protection_scheme_event_queue.tail;
8347   } else {
8348     GST_TRACE_OBJECT (qtdemux, "using demuxer event queue, length %u",
8349         qtdemux->protection_event_queue.length);
8350     walk = qtdemux->protection_event_queue.tail;
8351   }
8352
8353   g_value_init (&event_list, GST_TYPE_LIST);
8354   for (; walk; walk = g_list_previous (walk)) {
8355     GValue *event_value = g_new0 (GValue, 1);
8356     g_value_init (event_value, GST_TYPE_EVENT);
8357     g_value_set_boxed (event_value, walk->data);
8358     gst_value_list_append_and_take_value (&event_list, event_value);
8359   }
8360
8361   /*  2a) Query downstream with GST_QUERY_CONTEXT for the context and
8362    *      check if downstream already has a context of the specific type
8363    *  2b) Query upstream as above.
8364    */
8365   query = gst_query_new_context ("drm-preferred-decryption-system-id");
8366   st = gst_query_writable_structure (query);
8367   gst_structure_set (st, "track-id", G_TYPE_UINT, stream->track_id,
8368       "available-stream-encryption-systems", G_TYPE_STRV, filtered_sys_ids,
8369       NULL);
8370   gst_structure_set_value (st, "stream-encryption-events", &event_list);
8371   if (gst_qtdemux_run_query (element, query, GST_PAD_SRC)) {
8372     gst_query_parse_context (query, &ctxt);
8373     GST_INFO_OBJECT (element, "found context (%p) in downstream query", ctxt);
8374     gst_element_set_context (element, ctxt);
8375   } else if (gst_qtdemux_run_query (element, query, GST_PAD_SINK)) {
8376     gst_query_parse_context (query, &ctxt);
8377     GST_INFO_OBJECT (element, "found context (%p) in upstream query", ctxt);
8378     gst_element_set_context (element, ctxt);
8379   } else {
8380     /* 3) Post a GST_MESSAGE_NEED_CONTEXT message on the bus with
8381      *    the required context type and afterwards check if a
8382      *    usable context was set now as in 1). The message could
8383      *    be handled by the parent bins of the element and the
8384      *    application.
8385      */
8386     GstMessage *msg;
8387
8388     GST_INFO_OBJECT (element, "posting need context message");
8389     msg = gst_message_new_need_context (GST_OBJECT_CAST (element),
8390         "drm-preferred-decryption-system-id");
8391     st = (GstStructure *) gst_message_get_structure (msg);
8392     gst_structure_set (st, "track-id", G_TYPE_UINT, stream->track_id,
8393         "available-stream-encryption-systems", G_TYPE_STRV, filtered_sys_ids,
8394         NULL);
8395
8396     gst_structure_set_value (st, "stream-encryption-events", &event_list);
8397     gst_element_post_message (element, msg);
8398   }
8399
8400   g_strfreev (filtered_sys_ids);
8401   g_value_unset (&event_list);
8402   gst_query_unref (query);
8403 }
8404
8405 static gboolean
8406 gst_qtdemux_configure_protected_caps (GstQTDemux * qtdemux,
8407     QtDemuxStream * stream)
8408 {
8409   GstStructure *s;
8410   const gchar *selected_system = NULL;
8411
8412   g_return_val_if_fail (qtdemux != NULL, FALSE);
8413   g_return_val_if_fail (stream != NULL, FALSE);
8414   g_return_val_if_fail (gst_caps_get_size (CUR_STREAM (stream)->caps) == 1,
8415       FALSE);
8416
8417   if (stream->protection_scheme_type != FOURCC_cenc) {
8418     GST_ERROR_OBJECT (qtdemux,
8419         "unsupported protection scheme: %" GST_FOURCC_FORMAT,
8420         GST_FOURCC_ARGS (stream->protection_scheme_type));
8421     return FALSE;
8422   }
8423   if (qtdemux->protection_system_ids == NULL) {
8424     GST_ERROR_OBJECT (qtdemux, "stream is protected using cenc, but no "
8425         "cenc protection system information has been found");
8426     return FALSE;
8427   }
8428
8429   gst_qtdemux_request_protection_context (qtdemux, stream);
8430   if (qtdemux->preferred_protection_system_id != NULL) {
8431     const gchar *preferred_system_array[] =
8432         { qtdemux->preferred_protection_system_id, NULL };
8433
8434     selected_system = gst_protection_select_system (preferred_system_array);
8435
8436     if (selected_system) {
8437       GST_TRACE_OBJECT (qtdemux, "selected preferred system %s",
8438           qtdemux->preferred_protection_system_id);
8439     } else {
8440       GST_WARNING_OBJECT (qtdemux, "could not select preferred system %s "
8441           "because there is no available decryptor",
8442           qtdemux->preferred_protection_system_id);
8443     }
8444   }
8445
8446   if (!selected_system) {
8447     g_ptr_array_add (qtdemux->protection_system_ids, NULL);
8448     selected_system = gst_protection_select_system ((const gchar **)
8449         qtdemux->protection_system_ids->pdata);
8450     g_ptr_array_remove_index (qtdemux->protection_system_ids,
8451         qtdemux->protection_system_ids->len - 1);
8452   }
8453
8454   if (!selected_system) {
8455     GST_ERROR_OBJECT (qtdemux, "stream is protected, but no "
8456         "suitable decryptor element has been found");
8457     return FALSE;
8458   }
8459
8460   GST_DEBUG_OBJECT (qtdemux, "selected protection system is %s",
8461       selected_system);
8462
8463   s = gst_caps_get_structure (CUR_STREAM (stream)->caps, 0);
8464   if (!gst_structure_has_name (s, "application/x-cenc")) {
8465     gst_structure_set (s,
8466         "original-media-type", G_TYPE_STRING, gst_structure_get_name (s),
8467         GST_PROTECTION_SYSTEM_ID_CAPS_FIELD, G_TYPE_STRING, selected_system,
8468         NULL);
8469     gst_structure_set_name (s, "application/x-cenc");
8470   }
8471   return TRUE;
8472 }
8473
8474 static gboolean
8475 gst_qtdemux_guess_framerate (GstQTDemux * qtdemux, QtDemuxStream * stream)
8476 {
8477   /* fps is calculated base on the duration of the average framerate since
8478    * qt does not have a fixed framerate. */
8479   gboolean fps_available = TRUE;
8480   guint32 first_duration = 0;
8481
8482   if (stream->n_samples > 0)
8483     first_duration = stream->samples[0].duration;
8484
8485   if ((stream->n_samples == 1 && first_duration == 0)
8486       || (qtdemux->fragmented && stream->n_samples_moof == 1)) {
8487     /* still frame */
8488     CUR_STREAM (stream)->fps_n = 0;
8489     CUR_STREAM (stream)->fps_d = 1;
8490   } else {
8491     if (stream->duration == 0 || stream->n_samples < 2) {
8492       CUR_STREAM (stream)->fps_n = stream->timescale;
8493       CUR_STREAM (stream)->fps_d = 1;
8494       fps_available = FALSE;
8495     } else {
8496       GstClockTime avg_duration;
8497       guint64 duration;
8498       guint32 n_samples;
8499
8500       /* duration and n_samples can be updated for fragmented format
8501        * so, framerate of fragmented format is calculated using data in a moof */
8502       if (qtdemux->fragmented && stream->n_samples_moof > 0
8503           && stream->duration_moof > 0) {
8504         n_samples = stream->n_samples_moof;
8505         duration = stream->duration_moof;
8506       } else {
8507         n_samples = stream->n_samples;
8508         duration = stream->duration;
8509       }
8510
8511       /* Calculate a framerate, ignoring the first sample which is sometimes truncated */
8512       /* stream->duration is guint64, timescale, n_samples are guint32 */
8513       avg_duration =
8514           gst_util_uint64_scale_round (duration -
8515           first_duration, GST_SECOND,
8516           (guint64) (stream->timescale) * (n_samples - 1));
8517
8518       GST_LOG_OBJECT (qtdemux,
8519           "Calculating avg sample duration based on stream (or moof) duration %"
8520           G_GUINT64_FORMAT
8521           " minus first sample %u, leaving %d samples gives %"
8522           GST_TIME_FORMAT, duration, first_duration,
8523           n_samples - 1, GST_TIME_ARGS (avg_duration));
8524
8525       gst_video_guess_framerate (avg_duration, &CUR_STREAM (stream)->fps_n,
8526           &CUR_STREAM (stream)->fps_d);
8527
8528       GST_DEBUG_OBJECT (qtdemux,
8529           "Calculating framerate, timescale %u gave fps_n %d fps_d %d",
8530           stream->timescale, CUR_STREAM (stream)->fps_n,
8531           CUR_STREAM (stream)->fps_d);
8532     }
8533   }
8534
8535   return fps_available;
8536 }
8537
8538 static gboolean
8539 gst_qtdemux_configure_stream (GstQTDemux * qtdemux, QtDemuxStream * stream)
8540 {
8541   if (stream->subtype == FOURCC_vide) {
8542     gboolean fps_available = gst_qtdemux_guess_framerate (qtdemux, stream);
8543
8544     if (CUR_STREAM (stream)->caps) {
8545       CUR_STREAM (stream)->caps =
8546           gst_caps_make_writable (CUR_STREAM (stream)->caps);
8547
8548       if (CUR_STREAM (stream)->width && CUR_STREAM (stream)->height)
8549         gst_caps_set_simple (CUR_STREAM (stream)->caps,
8550             "width", G_TYPE_INT, CUR_STREAM (stream)->width,
8551             "height", G_TYPE_INT, CUR_STREAM (stream)->height, NULL);
8552
8553       /* set framerate if calculated framerate is reliable */
8554       if (fps_available) {
8555         gst_caps_set_simple (CUR_STREAM (stream)->caps,
8556             "framerate", GST_TYPE_FRACTION, CUR_STREAM (stream)->fps_n,
8557             CUR_STREAM (stream)->fps_d, NULL);
8558       }
8559
8560       /* calculate pixel-aspect-ratio using display width and height */
8561       GST_DEBUG_OBJECT (qtdemux,
8562           "video size %dx%d, target display size %dx%d",
8563           CUR_STREAM (stream)->width, CUR_STREAM (stream)->height,
8564           stream->display_width, stream->display_height);
8565       /* qt file might have pasp atom */
8566       if (CUR_STREAM (stream)->par_w > 0 && CUR_STREAM (stream)->par_h > 0) {
8567         GST_DEBUG_OBJECT (qtdemux, "par %d:%d", CUR_STREAM (stream)->par_w,
8568             CUR_STREAM (stream)->par_h);
8569         gst_caps_set_simple (CUR_STREAM (stream)->caps, "pixel-aspect-ratio",
8570             GST_TYPE_FRACTION, CUR_STREAM (stream)->par_w,
8571             CUR_STREAM (stream)->par_h, NULL);
8572       } else if (stream->display_width > 0 && stream->display_height > 0
8573           && CUR_STREAM (stream)->width > 0
8574           && CUR_STREAM (stream)->height > 0) {
8575         gint n, d;
8576
8577         /* calculate the pixel aspect ratio using the display and pixel w/h */
8578         n = stream->display_width * CUR_STREAM (stream)->height;
8579         d = stream->display_height * CUR_STREAM (stream)->width;
8580         if (n == d)
8581           n = d = 1;
8582         GST_DEBUG_OBJECT (qtdemux, "setting PAR to %d/%d", n, d);
8583         CUR_STREAM (stream)->par_w = n;
8584         CUR_STREAM (stream)->par_h = d;
8585         gst_caps_set_simple (CUR_STREAM (stream)->caps, "pixel-aspect-ratio",
8586             GST_TYPE_FRACTION, CUR_STREAM (stream)->par_w,
8587             CUR_STREAM (stream)->par_h, NULL);
8588       }
8589
8590       if (CUR_STREAM (stream)->interlace_mode > 0) {
8591         if (CUR_STREAM (stream)->interlace_mode == 1) {
8592           gst_caps_set_simple (CUR_STREAM (stream)->caps, "interlace-mode",
8593               G_TYPE_STRING, "progressive", NULL);
8594         } else if (CUR_STREAM (stream)->interlace_mode == 2) {
8595           gst_caps_set_simple (CUR_STREAM (stream)->caps, "interlace-mode",
8596               G_TYPE_STRING, "interleaved", NULL);
8597           if (CUR_STREAM (stream)->field_order == 9) {
8598             gst_caps_set_simple (CUR_STREAM (stream)->caps, "field-order",
8599                 G_TYPE_STRING, "top-field-first", NULL);
8600           } else if (CUR_STREAM (stream)->field_order == 14) {
8601             gst_caps_set_simple (CUR_STREAM (stream)->caps, "field-order",
8602                 G_TYPE_STRING, "bottom-field-first", NULL);
8603           }
8604         }
8605       }
8606
8607       /* Create incomplete colorimetry here if needed */
8608       if (CUR_STREAM (stream)->colorimetry.range ||
8609           CUR_STREAM (stream)->colorimetry.matrix ||
8610           CUR_STREAM (stream)->colorimetry.transfer
8611           || CUR_STREAM (stream)->colorimetry.primaries) {
8612         gchar *colorimetry =
8613             gst_video_colorimetry_to_string (&CUR_STREAM (stream)->colorimetry);
8614         gst_caps_set_simple (CUR_STREAM (stream)->caps, "colorimetry",
8615             G_TYPE_STRING, colorimetry, NULL);
8616         g_free (colorimetry);
8617       }
8618
8619       if (stream->multiview_mode != GST_VIDEO_MULTIVIEW_MODE_NONE) {
8620         guint par_w = 1, par_h = 1;
8621
8622         if (CUR_STREAM (stream)->par_w > 0 && CUR_STREAM (stream)->par_h > 0) {
8623           par_w = CUR_STREAM (stream)->par_w;
8624           par_h = CUR_STREAM (stream)->par_h;
8625         }
8626
8627         if (gst_video_multiview_guess_half_aspect (stream->multiview_mode,
8628                 CUR_STREAM (stream)->width, CUR_STREAM (stream)->height, par_w,
8629                 par_h)) {
8630           stream->multiview_flags |= GST_VIDEO_MULTIVIEW_FLAGS_HALF_ASPECT;
8631         }
8632
8633         gst_caps_set_simple (CUR_STREAM (stream)->caps,
8634             "multiview-mode", G_TYPE_STRING,
8635             gst_video_multiview_mode_to_caps_string (stream->multiview_mode),
8636             "multiview-flags", GST_TYPE_VIDEO_MULTIVIEW_FLAGSET,
8637             stream->multiview_flags, GST_FLAG_SET_MASK_EXACT, NULL);
8638       }
8639     }
8640   }
8641
8642   else if (stream->subtype == FOURCC_soun) {
8643     if (CUR_STREAM (stream)->caps) {
8644       CUR_STREAM (stream)->caps =
8645           gst_caps_make_writable (CUR_STREAM (stream)->caps);
8646       if (CUR_STREAM (stream)->rate > 0)
8647         gst_caps_set_simple (CUR_STREAM (stream)->caps,
8648             "rate", G_TYPE_INT, (int) CUR_STREAM (stream)->rate, NULL);
8649       if (CUR_STREAM (stream)->n_channels > 0)
8650         gst_caps_set_simple (CUR_STREAM (stream)->caps,
8651             "channels", G_TYPE_INT, CUR_STREAM (stream)->n_channels, NULL);
8652       if (CUR_STREAM (stream)->n_channels > 2) {
8653         /* FIXME: Need to parse the 'chan' atom to get channel layouts
8654          * correctly; this is just the minimum we can do - assume
8655          * we don't actually have any channel positions. */
8656         gst_caps_set_simple (CUR_STREAM (stream)->caps,
8657             "channel-mask", GST_TYPE_BITMASK, G_GUINT64_CONSTANT (0), NULL);
8658       }
8659     }
8660   }
8661
8662   else if (stream->subtype == FOURCC_clcp && CUR_STREAM (stream)->caps) {
8663     const GstStructure *s;
8664     QtDemuxStream *fps_stream = NULL;
8665     gboolean fps_available = FALSE;
8666
8667     /* CEA608 closed caption tracks are a bit special in that each sample
8668      * can contain CCs for multiple frames, and CCs can be omitted and have to
8669      * be inferred from the duration of the sample then.
8670      *
8671      * As such we take the framerate from the (first) video track here for
8672      * CEA608 as there must be one CC byte pair for every video frame
8673      * according to the spec.
8674      *
8675      * For CEA708 all is fine and there is one sample per frame.
8676      */
8677
8678     s = gst_caps_get_structure (CUR_STREAM (stream)->caps, 0);
8679     if (gst_structure_has_name (s, "closedcaption/x-cea-608")) {
8680       gint i;
8681
8682       for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
8683         QtDemuxStream *tmp = QTDEMUX_NTH_STREAM (qtdemux, i);
8684
8685         if (tmp->subtype == FOURCC_vide) {
8686           fps_stream = tmp;
8687           break;
8688         }
8689       }
8690
8691       if (fps_stream) {
8692         fps_available = gst_qtdemux_guess_framerate (qtdemux, fps_stream);
8693         CUR_STREAM (stream)->fps_n = CUR_STREAM (fps_stream)->fps_n;
8694         CUR_STREAM (stream)->fps_d = CUR_STREAM (fps_stream)->fps_d;
8695       }
8696     } else {
8697       fps_available = gst_qtdemux_guess_framerate (qtdemux, stream);
8698       fps_stream = stream;
8699     }
8700
8701     CUR_STREAM (stream)->caps =
8702         gst_caps_make_writable (CUR_STREAM (stream)->caps);
8703
8704     /* set framerate if calculated framerate is reliable */
8705     if (fps_available) {
8706       gst_caps_set_simple (CUR_STREAM (stream)->caps,
8707           "framerate", GST_TYPE_FRACTION, CUR_STREAM (stream)->fps_n,
8708           CUR_STREAM (stream)->fps_d, NULL);
8709     }
8710   }
8711
8712   if (stream->pad) {
8713     GstCaps *prev_caps = NULL;
8714
8715     GST_PAD_ELEMENT_PRIVATE (stream->pad) = stream;
8716     gst_pad_set_event_function (stream->pad, gst_qtdemux_handle_src_event);
8717     gst_pad_set_query_function (stream->pad, gst_qtdemux_handle_src_query);
8718     gst_pad_set_active (stream->pad, TRUE);
8719
8720     gst_pad_use_fixed_caps (stream->pad);
8721
8722     if (stream->protected) {
8723       if (!gst_qtdemux_configure_protected_caps (qtdemux, stream)) {
8724         GST_ERROR_OBJECT (qtdemux,
8725             "Failed to configure protected stream caps.");
8726         return FALSE;
8727       }
8728     }
8729
8730     GST_DEBUG_OBJECT (qtdemux, "setting caps %" GST_PTR_FORMAT,
8731         CUR_STREAM (stream)->caps);
8732     if (stream->new_stream) {
8733       GstEvent *event;
8734       GstStreamFlags stream_flags = GST_STREAM_FLAG_NONE;
8735
8736       event =
8737           gst_pad_get_sticky_event (qtdemux->sinkpad, GST_EVENT_STREAM_START,
8738           0);
8739       if (event) {
8740         gst_event_parse_stream_flags (event, &stream_flags);
8741         if (gst_event_parse_group_id (event, &qtdemux->group_id))
8742           qtdemux->have_group_id = TRUE;
8743         else
8744           qtdemux->have_group_id = FALSE;
8745         gst_event_unref (event);
8746       } else if (!qtdemux->have_group_id) {
8747         qtdemux->have_group_id = TRUE;
8748         qtdemux->group_id = gst_util_group_id_next ();
8749       }
8750
8751       stream->new_stream = FALSE;
8752       event = gst_event_new_stream_start (stream->stream_id);
8753       if (qtdemux->have_group_id)
8754         gst_event_set_group_id (event, qtdemux->group_id);
8755       if (stream->disabled)
8756         stream_flags |= GST_STREAM_FLAG_UNSELECT;
8757       if (CUR_STREAM (stream)->sparse) {
8758         stream_flags |= GST_STREAM_FLAG_SPARSE;
8759       } else {
8760         stream_flags &= ~GST_STREAM_FLAG_SPARSE;
8761       }
8762       gst_event_set_stream_flags (event, stream_flags);
8763       gst_pad_push_event (stream->pad, event);
8764     }
8765
8766     prev_caps = gst_pad_get_current_caps (stream->pad);
8767
8768     if (CUR_STREAM (stream)->caps) {
8769       if (!prev_caps
8770           || !gst_caps_is_equal_fixed (prev_caps, CUR_STREAM (stream)->caps)) {
8771         GST_DEBUG_OBJECT (qtdemux, "setting caps %" GST_PTR_FORMAT,
8772             CUR_STREAM (stream)->caps);
8773         gst_pad_set_caps (stream->pad, CUR_STREAM (stream)->caps);
8774       } else {
8775         GST_DEBUG_OBJECT (qtdemux, "ignore duplicated caps");
8776       }
8777     } else {
8778       GST_WARNING_OBJECT (qtdemux, "stream without caps");
8779     }
8780
8781     if (prev_caps)
8782       gst_caps_unref (prev_caps);
8783     stream->new_caps = FALSE;
8784   }
8785   return TRUE;
8786 }
8787
8788 static void
8789 gst_qtdemux_stream_check_and_change_stsd_index (GstQTDemux * demux,
8790     QtDemuxStream * stream)
8791 {
8792   if (stream->cur_stsd_entry_index == stream->stsd_sample_description_id)
8793     return;
8794
8795   GST_DEBUG_OBJECT (stream->pad, "Changing stsd index from '%u' to '%u'",
8796       stream->cur_stsd_entry_index, stream->stsd_sample_description_id);
8797   if (G_UNLIKELY (stream->stsd_sample_description_id >=
8798           stream->stsd_entries_length)) {
8799     GST_ELEMENT_ERROR (demux, STREAM, DEMUX,
8800         (_("This file is invalid and cannot be played.")),
8801         ("New sample description id is out of bounds (%d >= %d)",
8802             stream->stsd_sample_description_id, stream->stsd_entries_length));
8803   } else {
8804     stream->cur_stsd_entry_index = stream->stsd_sample_description_id;
8805     stream->new_caps = TRUE;
8806   }
8807 }
8808
8809 static gboolean
8810 gst_qtdemux_add_stream (GstQTDemux * qtdemux,
8811     QtDemuxStream * stream, GstTagList * list)
8812 {
8813   gboolean ret = TRUE;
8814
8815   if (stream->subtype == FOURCC_vide) {
8816     gchar *name = g_strdup_printf ("video_%u", qtdemux->n_video_streams);
8817
8818     stream->pad =
8819         gst_pad_new_from_static_template (&gst_qtdemux_videosrc_template, name);
8820     g_free (name);
8821
8822     if (!gst_qtdemux_configure_stream (qtdemux, stream)) {
8823       gst_object_unref (stream->pad);
8824       stream->pad = NULL;
8825       ret = FALSE;
8826       goto done;
8827     }
8828
8829     qtdemux->n_video_streams++;
8830   } else if (stream->subtype == FOURCC_soun) {
8831     gchar *name = g_strdup_printf ("audio_%u", qtdemux->n_audio_streams);
8832
8833     stream->pad =
8834         gst_pad_new_from_static_template (&gst_qtdemux_audiosrc_template, name);
8835     g_free (name);
8836     if (!gst_qtdemux_configure_stream (qtdemux, stream)) {
8837       gst_object_unref (stream->pad);
8838       stream->pad = NULL;
8839       ret = FALSE;
8840       goto done;
8841     }
8842     qtdemux->n_audio_streams++;
8843   } else if (stream->subtype == FOURCC_strm) {
8844     GST_DEBUG_OBJECT (qtdemux, "stream type, not creating pad");
8845   } else if (stream->subtype == FOURCC_subp || stream->subtype == FOURCC_text
8846       || stream->subtype == FOURCC_sbtl || stream->subtype == FOURCC_subt
8847       || stream->subtype == FOURCC_clcp) {
8848     gchar *name = g_strdup_printf ("subtitle_%u", qtdemux->n_sub_streams);
8849
8850     stream->pad =
8851         gst_pad_new_from_static_template (&gst_qtdemux_subsrc_template, name);
8852     g_free (name);
8853     if (!gst_qtdemux_configure_stream (qtdemux, stream)) {
8854       gst_object_unref (stream->pad);
8855       stream->pad = NULL;
8856       ret = FALSE;
8857       goto done;
8858     }
8859     qtdemux->n_sub_streams++;
8860   } else if (CUR_STREAM (stream)->caps) {
8861     gchar *name = g_strdup_printf ("video_%u", qtdemux->n_video_streams);
8862
8863     stream->pad =
8864         gst_pad_new_from_static_template (&gst_qtdemux_videosrc_template, name);
8865     g_free (name);
8866     if (!gst_qtdemux_configure_stream (qtdemux, stream)) {
8867       gst_object_unref (stream->pad);
8868       stream->pad = NULL;
8869       ret = FALSE;
8870       goto done;
8871     }
8872     qtdemux->n_video_streams++;
8873   } else {
8874     GST_DEBUG_OBJECT (qtdemux, "unknown stream type");
8875     goto done;
8876   }
8877
8878   if (stream->pad) {
8879     GList *l;
8880
8881     GST_DEBUG_OBJECT (qtdemux, "adding pad %s %p to qtdemux %p",
8882         GST_OBJECT_NAME (stream->pad), stream->pad, qtdemux);
8883     gst_element_add_pad (GST_ELEMENT_CAST (qtdemux), stream->pad);
8884     gst_flow_combiner_add_pad (qtdemux->flowcombiner, stream->pad);
8885
8886     if (stream->stream_tags)
8887       gst_tag_list_unref (stream->stream_tags);
8888     stream->stream_tags = list;
8889     list = NULL;
8890     /* global tags go on each pad anyway */
8891     stream->send_global_tags = TRUE;
8892     /* send upstream GST_EVENT_PROTECTION events that were received before
8893        this source pad was created */
8894     for (l = qtdemux->protection_event_queue.head; l != NULL; l = l->next)
8895       gst_pad_push_event (stream->pad, gst_event_ref (l->data));
8896   }
8897 done:
8898   if (list)
8899     gst_tag_list_unref (list);
8900   return ret;
8901 }
8902
8903 /* find next atom with @fourcc starting at @offset */
8904 static GstFlowReturn
8905 qtdemux_find_atom (GstQTDemux * qtdemux, guint64 * offset,
8906     guint64 * length, guint32 fourcc)
8907 {
8908   GstFlowReturn ret;
8909   guint32 lfourcc;
8910   GstBuffer *buf;
8911
8912   GST_LOG_OBJECT (qtdemux, "finding fourcc %" GST_FOURCC_FORMAT " at offset %"
8913       G_GUINT64_FORMAT, GST_FOURCC_ARGS (fourcc), *offset);
8914
8915   while (TRUE) {
8916     GstMapInfo map;
8917
8918     buf = NULL;
8919     ret = gst_pad_pull_range (qtdemux->sinkpad, *offset, 16, &buf);
8920     if (G_UNLIKELY (ret != GST_FLOW_OK))
8921       goto locate_failed;
8922     if (G_UNLIKELY (gst_buffer_get_size (buf) != 16)) {
8923       /* likely EOF */
8924       ret = GST_FLOW_EOS;
8925       gst_buffer_unref (buf);
8926       goto locate_failed;
8927     }
8928     gst_buffer_map (buf, &map, GST_MAP_READ);
8929     extract_initial_length_and_fourcc (map.data, 16, length, &lfourcc);
8930     gst_buffer_unmap (buf, &map);
8931     gst_buffer_unref (buf);
8932
8933     if (G_UNLIKELY (*length == 0)) {
8934       GST_DEBUG_OBJECT (qtdemux, "invalid length 0");
8935       ret = GST_FLOW_ERROR;
8936       goto locate_failed;
8937     }
8938
8939     if (lfourcc == fourcc) {
8940       GST_DEBUG_OBJECT (qtdemux, "found fourcc at offset %" G_GUINT64_FORMAT,
8941           *offset);
8942       break;
8943     } else {
8944       GST_LOG_OBJECT (qtdemux,
8945           "skipping atom '%" GST_FOURCC_FORMAT "' at %" G_GUINT64_FORMAT,
8946           GST_FOURCC_ARGS (fourcc), *offset);
8947       *offset += *length;
8948     }
8949   }
8950
8951   return GST_FLOW_OK;
8952
8953 locate_failed:
8954   {
8955     /* might simply have had last one */
8956     GST_DEBUG_OBJECT (qtdemux, "fourcc not found");
8957     return ret;
8958   }
8959 }
8960
8961 /* should only do something in pull mode */
8962 /* call with OBJECT lock */
8963 static GstFlowReturn
8964 qtdemux_add_fragmented_samples (GstQTDemux * qtdemux)
8965 {
8966   guint64 length, offset;
8967   GstBuffer *buf = NULL;
8968   GstFlowReturn ret = GST_FLOW_OK;
8969   GstFlowReturn res = GST_FLOW_OK;
8970   GstMapInfo map;
8971
8972   offset = qtdemux->moof_offset;
8973   GST_DEBUG_OBJECT (qtdemux, "next moof at offset %" G_GUINT64_FORMAT, offset);
8974
8975   if (!offset) {
8976     GST_DEBUG_OBJECT (qtdemux, "no next moof");
8977     return GST_FLOW_EOS;
8978   }
8979
8980   /* best not do pull etc with lock held */
8981   GST_OBJECT_UNLOCK (qtdemux);
8982
8983   ret = qtdemux_find_atom (qtdemux, &offset, &length, FOURCC_moof);
8984   if (ret != GST_FLOW_OK)
8985     goto flow_failed;
8986
8987   ret = gst_qtdemux_pull_atom (qtdemux, offset, length, &buf);
8988   if (G_UNLIKELY (ret != GST_FLOW_OK))
8989     goto flow_failed;
8990   gst_buffer_map (buf, &map, GST_MAP_READ);
8991   if (!qtdemux_parse_moof (qtdemux, map.data, map.size, offset, NULL)) {
8992     gst_buffer_unmap (buf, &map);
8993     gst_buffer_unref (buf);
8994     buf = NULL;
8995     goto parse_failed;
8996   }
8997
8998   gst_buffer_unmap (buf, &map);
8999   gst_buffer_unref (buf);
9000   buf = NULL;
9001
9002   offset += length;
9003   /* look for next moof */
9004   ret = qtdemux_find_atom (qtdemux, &offset, &length, FOURCC_moof);
9005   if (G_UNLIKELY (ret != GST_FLOW_OK))
9006     goto flow_failed;
9007
9008 exit:
9009   GST_OBJECT_LOCK (qtdemux);
9010
9011   qtdemux->moof_offset = offset;
9012
9013   return res;
9014
9015 parse_failed:
9016   {
9017     GST_DEBUG_OBJECT (qtdemux, "failed to parse moof");
9018     offset = 0;
9019     res = GST_FLOW_ERROR;
9020     goto exit;
9021   }
9022 flow_failed:
9023   {
9024     /* maybe upstream temporarily flushing */
9025     if (ret != GST_FLOW_FLUSHING) {
9026       GST_DEBUG_OBJECT (qtdemux, "no next moof");
9027       offset = 0;
9028     } else {
9029       GST_DEBUG_OBJECT (qtdemux, "upstream WRONG_STATE");
9030       /* resume at current position next time */
9031     }
9032     res = ret;
9033     goto exit;
9034   }
9035 }
9036
9037 /* initialise bytereaders for stbl sub-atoms */
9038 static gboolean
9039 qtdemux_stbl_init (GstQTDemux * qtdemux, QtDemuxStream * stream, GNode * stbl)
9040 {
9041   stream->stbl_index = -1;      /* no samples have yet been parsed */
9042   stream->sample_index = -1;
9043
9044   /* time-to-sample atom */
9045   if (!qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stts, &stream->stts))
9046     goto corrupt_file;
9047
9048   /* copy atom data into a new buffer for later use */
9049   stream->stts.data = g_memdup (stream->stts.data, stream->stts.size);
9050
9051   /* skip version + flags */
9052   if (!gst_byte_reader_skip (&stream->stts, 1 + 3) ||
9053       !gst_byte_reader_get_uint32_be (&stream->stts, &stream->n_sample_times))
9054     goto corrupt_file;
9055   GST_LOG_OBJECT (qtdemux, "%u timestamp blocks", stream->n_sample_times);
9056
9057   /* make sure there's enough data */
9058   if (!qt_atom_parser_has_chunks (&stream->stts, stream->n_sample_times, 8)) {
9059     stream->n_sample_times = gst_byte_reader_get_remaining (&stream->stts) / 8;
9060     GST_LOG_OBJECT (qtdemux, "overriding to %u timestamp blocks",
9061         stream->n_sample_times);
9062     if (!stream->n_sample_times)
9063       goto corrupt_file;
9064   }
9065
9066   /* sync sample atom */
9067   stream->stps_present = FALSE;
9068   if ((stream->stss_present =
9069           ! !qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stss,
9070               &stream->stss) ? TRUE : FALSE) == TRUE) {
9071     /* copy atom data into a new buffer for later use */
9072     stream->stss.data = g_memdup (stream->stss.data, stream->stss.size);
9073
9074     /* skip version + flags */
9075     if (!gst_byte_reader_skip (&stream->stss, 1 + 3) ||
9076         !gst_byte_reader_get_uint32_be (&stream->stss, &stream->n_sample_syncs))
9077       goto corrupt_file;
9078
9079     if (stream->n_sample_syncs) {
9080       /* make sure there's enough data */
9081       if (!qt_atom_parser_has_chunks (&stream->stss, stream->n_sample_syncs, 4))
9082         goto corrupt_file;
9083     }
9084
9085     /* partial sync sample atom */
9086     if ((stream->stps_present =
9087             ! !qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stps,
9088                 &stream->stps) ? TRUE : FALSE) == TRUE) {
9089       /* copy atom data into a new buffer for later use */
9090       stream->stps.data = g_memdup (stream->stps.data, stream->stps.size);
9091
9092       /* skip version + flags */
9093       if (!gst_byte_reader_skip (&stream->stps, 1 + 3) ||
9094           !gst_byte_reader_get_uint32_be (&stream->stps,
9095               &stream->n_sample_partial_syncs))
9096         goto corrupt_file;
9097
9098       /* if there are no entries, the stss table contains the real
9099        * sync samples */
9100       if (stream->n_sample_partial_syncs) {
9101         /* make sure there's enough data */
9102         if (!qt_atom_parser_has_chunks (&stream->stps,
9103                 stream->n_sample_partial_syncs, 4))
9104           goto corrupt_file;
9105       }
9106     }
9107   }
9108
9109   /* sample size */
9110   if (!qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stsz, &stream->stsz))
9111     goto no_samples;
9112
9113   /* copy atom data into a new buffer for later use */
9114   stream->stsz.data = g_memdup (stream->stsz.data, stream->stsz.size);
9115
9116   /* skip version + flags */
9117   if (!gst_byte_reader_skip (&stream->stsz, 1 + 3) ||
9118       !gst_byte_reader_get_uint32_be (&stream->stsz, &stream->sample_size))
9119     goto corrupt_file;
9120
9121   if (!gst_byte_reader_get_uint32_be (&stream->stsz, &stream->n_samples))
9122     goto corrupt_file;
9123
9124   if (!stream->n_samples)
9125     goto no_samples;
9126
9127   /* sample-to-chunk atom */
9128   if (!qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stsc, &stream->stsc))
9129     goto corrupt_file;
9130
9131   /* copy atom data into a new buffer for later use */
9132   stream->stsc.data = g_memdup (stream->stsc.data, stream->stsc.size);
9133
9134   /* skip version + flags */
9135   if (!gst_byte_reader_skip (&stream->stsc, 1 + 3) ||
9136       !gst_byte_reader_get_uint32_be (&stream->stsc,
9137           &stream->n_samples_per_chunk))
9138     goto corrupt_file;
9139
9140   GST_DEBUG_OBJECT (qtdemux, "n_samples_per_chunk %u",
9141       stream->n_samples_per_chunk);
9142
9143   /* make sure there's enough data */
9144   if (!qt_atom_parser_has_chunks (&stream->stsc, stream->n_samples_per_chunk,
9145           12))
9146     goto corrupt_file;
9147
9148
9149   /* chunk offset */
9150   if (qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stco, &stream->stco))
9151     stream->co_size = sizeof (guint32);
9152   else if (qtdemux_tree_get_child_by_type_full (stbl, FOURCC_co64,
9153           &stream->stco))
9154     stream->co_size = sizeof (guint64);
9155   else
9156     goto corrupt_file;
9157
9158   /* copy atom data into a new buffer for later use */
9159   stream->stco.data = g_memdup (stream->stco.data, stream->stco.size);
9160
9161   /* skip version + flags */
9162   if (!gst_byte_reader_skip (&stream->stco, 1 + 3))
9163     goto corrupt_file;
9164
9165   /* chunks_are_samples == TRUE means treat chunks as samples */
9166   stream->chunks_are_samples = stream->sample_size
9167       && !CUR_STREAM (stream)->sampled;
9168   if (stream->chunks_are_samples) {
9169     /* treat chunks as samples */
9170     if (!gst_byte_reader_get_uint32_be (&stream->stco, &stream->n_samples))
9171       goto corrupt_file;
9172   } else {
9173     /* skip number of entries */
9174     if (!gst_byte_reader_skip (&stream->stco, 4))
9175       goto corrupt_file;
9176
9177     /* make sure there are enough data in the stsz atom */
9178     if (!stream->sample_size) {
9179       /* different sizes for each sample */
9180       if (!qt_atom_parser_has_chunks (&stream->stsz, stream->n_samples, 4))
9181         goto corrupt_file;
9182     }
9183   }
9184
9185   GST_DEBUG_OBJECT (qtdemux, "allocating n_samples %u * %u (%.2f MB)",
9186       stream->n_samples, (guint) sizeof (QtDemuxSample),
9187       stream->n_samples * sizeof (QtDemuxSample) / (1024.0 * 1024.0));
9188
9189   if (stream->n_samples >=
9190       QTDEMUX_MAX_SAMPLE_INDEX_SIZE / sizeof (QtDemuxSample)) {
9191     GST_WARNING_OBJECT (qtdemux, "not allocating index of %d samples, would "
9192         "be larger than %uMB (broken file?)", stream->n_samples,
9193         QTDEMUX_MAX_SAMPLE_INDEX_SIZE >> 20);
9194     return FALSE;
9195   }
9196
9197   g_assert (stream->samples == NULL);
9198   stream->samples = g_try_new0 (QtDemuxSample, stream->n_samples);
9199   if (!stream->samples) {
9200     GST_WARNING_OBJECT (qtdemux, "failed to allocate %d samples",
9201         stream->n_samples);
9202     return FALSE;
9203   }
9204
9205   /* composition time-to-sample */
9206   if ((stream->ctts_present =
9207           ! !qtdemux_tree_get_child_by_type_full (stbl, FOURCC_ctts,
9208               &stream->ctts) ? TRUE : FALSE) == TRUE) {
9209     GstByteReader cslg = GST_BYTE_READER_INIT (NULL, 0);
9210
9211     /* copy atom data into a new buffer for later use */
9212     stream->ctts.data = g_memdup (stream->ctts.data, stream->ctts.size);
9213
9214     /* skip version + flags */
9215     if (!gst_byte_reader_skip (&stream->ctts, 1 + 3)
9216         || !gst_byte_reader_get_uint32_be (&stream->ctts,
9217             &stream->n_composition_times))
9218       goto corrupt_file;
9219
9220     /* make sure there's enough data */
9221     if (!qt_atom_parser_has_chunks (&stream->ctts, stream->n_composition_times,
9222             4 + 4))
9223       goto corrupt_file;
9224
9225     /* This is optional, if missing we iterate the ctts */
9226     if (qtdemux_tree_get_child_by_type_full (stbl, FOURCC_cslg, &cslg)) {
9227       if (!gst_byte_reader_skip (&cslg, 1 + 3)
9228           || !gst_byte_reader_get_uint32_be (&cslg, &stream->cslg_shift)) {
9229         g_free ((gpointer) cslg.data);
9230         goto corrupt_file;
9231       }
9232     } else {
9233       gint32 cslg_least = 0;
9234       guint num_entries, pos;
9235       gint i;
9236
9237       pos = gst_byte_reader_get_pos (&stream->ctts);
9238       num_entries = stream->n_composition_times;
9239
9240       stream->cslg_shift = 0;
9241
9242       for (i = 0; i < num_entries; i++) {
9243         gint32 offset;
9244
9245         gst_byte_reader_skip_unchecked (&stream->ctts, 4);
9246         offset = gst_byte_reader_get_int32_be_unchecked (&stream->ctts);
9247         /* HACK: if sample_offset is larger than 2 * duration, ignore the box.
9248          * slightly inaccurate PTS could be more usable than corrupted one */
9249         if (G_UNLIKELY ((ABS (offset) / 2) > stream->duration)) {
9250           GST_WARNING_OBJECT (qtdemux,
9251               "Ignore corrupted ctts, sample_offset %" G_GINT32_FORMAT
9252               " larger than duration %" G_GUINT64_FORMAT,
9253               offset, stream->duration);
9254
9255           stream->cslg_shift = 0;
9256           stream->ctts_present = FALSE;
9257           return TRUE;
9258         }
9259
9260         if (offset < cslg_least)
9261           cslg_least = offset;
9262       }
9263
9264       if (cslg_least < 0)
9265         stream->cslg_shift = ABS (cslg_least);
9266       else
9267         stream->cslg_shift = 0;
9268
9269       /* reset the reader so we can generate sample table */
9270       gst_byte_reader_set_pos (&stream->ctts, pos);
9271     }
9272   } else {
9273     /* Ensure the cslg_shift value is consistent so we can use it
9274      * unconditionnally to produce TS and Segment */
9275     stream->cslg_shift = 0;
9276   }
9277
9278   return TRUE;
9279
9280 corrupt_file:
9281   {
9282     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
9283         (_("This file is corrupt and cannot be played.")), (NULL));
9284     return FALSE;
9285   }
9286 no_samples:
9287   {
9288     gst_qtdemux_stbl_free (stream);
9289     if (!qtdemux->fragmented) {
9290       /* not quite good */
9291       GST_WARNING_OBJECT (qtdemux, "stream has no samples");
9292       return FALSE;
9293     } else {
9294       /* may pick up samples elsewhere */
9295       return TRUE;
9296     }
9297   }
9298 }
9299
9300 /* collect samples from the next sample to be parsed up to sample @n for @stream
9301  * by reading the info from @stbl
9302  *
9303  * This code can be executed from both the streaming thread and the seeking
9304  * thread so it takes the object lock to protect itself
9305  */
9306 static gboolean
9307 qtdemux_parse_samples (GstQTDemux * qtdemux, QtDemuxStream * stream, guint32 n)
9308 {
9309   gint i, j, k;
9310   QtDemuxSample *samples, *first, *cur, *last;
9311   guint32 n_samples_per_chunk;
9312   guint32 n_samples;
9313
9314   GST_LOG_OBJECT (qtdemux, "parsing samples for stream fourcc %"
9315       GST_FOURCC_FORMAT ", pad %s",
9316       GST_FOURCC_ARGS (CUR_STREAM (stream)->fourcc),
9317       stream->pad ? GST_PAD_NAME (stream->pad) : "(NULL)");
9318
9319   n_samples = stream->n_samples;
9320
9321   if (n >= n_samples)
9322     goto out_of_samples;
9323
9324   GST_OBJECT_LOCK (qtdemux);
9325   if (n <= stream->stbl_index)
9326     goto already_parsed;
9327
9328   GST_DEBUG_OBJECT (qtdemux, "parsing up to sample %u", n);
9329
9330   if (!stream->stsz.data) {
9331     /* so we already parsed and passed all the moov samples;
9332      * onto fragmented ones */
9333     g_assert (qtdemux->fragmented);
9334     goto done;
9335   }
9336
9337   /* pointer to the sample table */
9338   samples = stream->samples;
9339
9340   /* starts from -1, moves to the next sample index to parse */
9341   stream->stbl_index++;
9342
9343   /* keep track of the first and last sample to fill */
9344   first = &samples[stream->stbl_index];
9345   last = &samples[n];
9346
9347   if (!stream->chunks_are_samples) {
9348     /* set the sample sizes */
9349     if (stream->sample_size == 0) {
9350       /* different sizes for each sample */
9351       for (cur = first; cur <= last; cur++) {
9352         cur->size = gst_byte_reader_get_uint32_be_unchecked (&stream->stsz);
9353         GST_LOG_OBJECT (qtdemux, "sample %d has size %u",
9354             (guint) (cur - samples), cur->size);
9355       }
9356     } else {
9357       /* samples have the same size */
9358       GST_LOG_OBJECT (qtdemux, "all samples have size %u", stream->sample_size);
9359       for (cur = first; cur <= last; cur++)
9360         cur->size = stream->sample_size;
9361     }
9362   }
9363
9364   n_samples_per_chunk = stream->n_samples_per_chunk;
9365   cur = first;
9366
9367   for (i = stream->stsc_index; i < n_samples_per_chunk; i++) {
9368     guint32 last_chunk;
9369
9370     if (stream->stsc_chunk_index >= stream->last_chunk
9371         || stream->stsc_chunk_index < stream->first_chunk) {
9372       stream->first_chunk =
9373           gst_byte_reader_get_uint32_be_unchecked (&stream->stsc);
9374       stream->samples_per_chunk =
9375           gst_byte_reader_get_uint32_be_unchecked (&stream->stsc);
9376       /* starts from 1 */
9377       stream->stsd_sample_description_id =
9378           gst_byte_reader_get_uint32_be_unchecked (&stream->stsc) - 1;
9379
9380       /* chunk numbers are counted from 1 it seems */
9381       if (G_UNLIKELY (stream->first_chunk == 0))
9382         goto corrupt_file;
9383
9384       --stream->first_chunk;
9385
9386       /* the last chunk of each entry is calculated by taking the first chunk
9387        * of the next entry; except if there is no next, where we fake it with
9388        * INT_MAX */
9389       if (G_UNLIKELY (i == (stream->n_samples_per_chunk - 1))) {
9390         stream->last_chunk = G_MAXUINT32;
9391       } else {
9392         stream->last_chunk =
9393             gst_byte_reader_peek_uint32_be_unchecked (&stream->stsc);
9394         if (G_UNLIKELY (stream->last_chunk == 0))
9395           goto corrupt_file;
9396
9397         --stream->last_chunk;
9398       }
9399
9400       GST_LOG_OBJECT (qtdemux,
9401           "entry %d has first_chunk %d, last_chunk %d, samples_per_chunk %d"
9402           "sample desc ID: %d", i, stream->first_chunk, stream->last_chunk,
9403           stream->samples_per_chunk, stream->stsd_sample_description_id);
9404
9405       if (G_UNLIKELY (stream->last_chunk < stream->first_chunk))
9406         goto corrupt_file;
9407
9408       if (stream->last_chunk != G_MAXUINT32) {
9409         if (!qt_atom_parser_peek_sub (&stream->stco,
9410                 stream->first_chunk * stream->co_size,
9411                 (stream->last_chunk - stream->first_chunk) * stream->co_size,
9412                 &stream->co_chunk))
9413           goto corrupt_file;
9414
9415       } else {
9416         stream->co_chunk = stream->stco;
9417         if (!gst_byte_reader_skip (&stream->co_chunk,
9418                 stream->first_chunk * stream->co_size))
9419           goto corrupt_file;
9420       }
9421
9422       stream->stsc_chunk_index = stream->first_chunk;
9423     }
9424
9425     last_chunk = stream->last_chunk;
9426
9427     if (stream->chunks_are_samples) {
9428       cur = &samples[stream->stsc_chunk_index];
9429
9430       for (j = stream->stsc_chunk_index; j < last_chunk; j++) {
9431         if (j > n) {
9432           /* save state */
9433           stream->stsc_chunk_index = j;
9434           goto done;
9435         }
9436
9437         cur->offset =
9438             qt_atom_parser_get_offset_unchecked (&stream->co_chunk,
9439             stream->co_size);
9440
9441         GST_LOG_OBJECT (qtdemux, "Created entry %d with offset "
9442             "%" G_GUINT64_FORMAT, j, cur->offset);
9443
9444         if (CUR_STREAM (stream)->samples_per_frame > 0 &&
9445             CUR_STREAM (stream)->bytes_per_frame > 0) {
9446           cur->size =
9447               (stream->samples_per_chunk * CUR_STREAM (stream)->n_channels) /
9448               CUR_STREAM (stream)->samples_per_frame *
9449               CUR_STREAM (stream)->bytes_per_frame;
9450         } else {
9451           cur->size = stream->samples_per_chunk;
9452         }
9453
9454         GST_DEBUG_OBJECT (qtdemux,
9455             "keyframe sample %d: timestamp %" GST_TIME_FORMAT ", size %u",
9456             j, GST_TIME_ARGS (QTSTREAMTIME_TO_GSTTIME (stream,
9457                     stream->stco_sample_index)), cur->size);
9458
9459         cur->timestamp = stream->stco_sample_index;
9460         cur->duration = stream->samples_per_chunk;
9461         cur->keyframe = TRUE;
9462         cur++;
9463
9464         stream->stco_sample_index += stream->samples_per_chunk;
9465       }
9466       stream->stsc_chunk_index = j;
9467     } else {
9468       for (j = stream->stsc_chunk_index; j < last_chunk; j++) {
9469         guint32 samples_per_chunk;
9470         guint64 chunk_offset;
9471
9472         if (!stream->stsc_sample_index
9473             && !qt_atom_parser_get_offset (&stream->co_chunk, stream->co_size,
9474                 &stream->chunk_offset))
9475           goto corrupt_file;
9476
9477         samples_per_chunk = stream->samples_per_chunk;
9478         chunk_offset = stream->chunk_offset;
9479
9480         for (k = stream->stsc_sample_index; k < samples_per_chunk; k++) {
9481           GST_LOG_OBJECT (qtdemux, "creating entry %d with offset %"
9482               G_GUINT64_FORMAT " and size %d",
9483               (guint) (cur - samples), chunk_offset, cur->size);
9484
9485           cur->offset = chunk_offset;
9486           chunk_offset += cur->size;
9487           cur++;
9488
9489           if (G_UNLIKELY (cur > last)) {
9490             /* save state */
9491             stream->stsc_sample_index = k + 1;
9492             stream->chunk_offset = chunk_offset;
9493             stream->stsc_chunk_index = j;
9494             goto done2;
9495           }
9496         }
9497         stream->stsc_sample_index = 0;
9498       }
9499       stream->stsc_chunk_index = j;
9500     }
9501     stream->stsc_index++;
9502   }
9503
9504   if (stream->chunks_are_samples)
9505     goto ctts;
9506 done2:
9507   {
9508     guint32 n_sample_times;
9509
9510     n_sample_times = stream->n_sample_times;
9511     cur = first;
9512
9513     for (i = stream->stts_index; i < n_sample_times; i++) {
9514       guint32 stts_samples;
9515       gint32 stts_duration;
9516       gint64 stts_time;
9517
9518       if (stream->stts_sample_index >= stream->stts_samples
9519           || !stream->stts_sample_index) {
9520
9521         stream->stts_samples =
9522             gst_byte_reader_get_uint32_be_unchecked (&stream->stts);
9523         stream->stts_duration =
9524             gst_byte_reader_get_uint32_be_unchecked (&stream->stts);
9525
9526         GST_LOG_OBJECT (qtdemux, "block %d, %u timestamps, duration %u",
9527             i, stream->stts_samples, stream->stts_duration);
9528
9529         stream->stts_sample_index = 0;
9530       }
9531
9532       stts_samples = stream->stts_samples;
9533       stts_duration = stream->stts_duration;
9534       stts_time = stream->stts_time;
9535
9536       for (j = stream->stts_sample_index; j < stts_samples; j++) {
9537         GST_DEBUG_OBJECT (qtdemux,
9538             "sample %d: index %d, timestamp %" GST_TIME_FORMAT,
9539             (guint) (cur - samples), j,
9540             GST_TIME_ARGS (QTSTREAMTIME_TO_GSTTIME (stream, stts_time)));
9541
9542         cur->timestamp = stts_time;
9543         cur->duration = stts_duration;
9544
9545         /* avoid 32-bit wrap-around,
9546          * but still mind possible 'negative' duration */
9547         stts_time += (gint64) stts_duration;
9548         cur++;
9549
9550         if (G_UNLIKELY (cur > last)) {
9551           /* save values */
9552           stream->stts_time = stts_time;
9553           stream->stts_sample_index = j + 1;
9554           if (stream->stts_sample_index >= stream->stts_samples)
9555             stream->stts_index++;
9556           goto done3;
9557         }
9558       }
9559       stream->stts_sample_index = 0;
9560       stream->stts_time = stts_time;
9561       stream->stts_index++;
9562     }
9563     /* fill up empty timestamps with the last timestamp, this can happen when
9564      * the last samples do not decode and so we don't have timestamps for them.
9565      * We however look at the last timestamp to estimate the track length so we
9566      * need something in here. */
9567     for (; cur < last; cur++) {
9568       GST_DEBUG_OBJECT (qtdemux,
9569           "fill sample %d: timestamp %" GST_TIME_FORMAT,
9570           (guint) (cur - samples),
9571           GST_TIME_ARGS (QTSTREAMTIME_TO_GSTTIME (stream, stream->stts_time)));
9572       cur->timestamp = stream->stts_time;
9573       cur->duration = -1;
9574     }
9575   }
9576 done3:
9577   {
9578     /* sample sync, can be NULL */
9579     if (stream->stss_present == TRUE) {
9580       guint32 n_sample_syncs;
9581
9582       n_sample_syncs = stream->n_sample_syncs;
9583
9584       if (!n_sample_syncs) {
9585         GST_DEBUG_OBJECT (qtdemux, "all samples are keyframes");
9586         stream->all_keyframe = TRUE;
9587       } else {
9588         for (i = stream->stss_index; i < n_sample_syncs; i++) {
9589           /* note that the first sample is index 1, not 0 */
9590           guint32 index;
9591
9592           index = gst_byte_reader_get_uint32_be_unchecked (&stream->stss);
9593
9594           if (G_LIKELY (index > 0 && index <= n_samples)) {
9595             index -= 1;
9596             samples[index].keyframe = TRUE;
9597             GST_DEBUG_OBJECT (qtdemux, "samples at %u is keyframe", index);
9598             /* and exit if we have enough samples */
9599             if (G_UNLIKELY (index >= n)) {
9600               i++;
9601               break;
9602             }
9603           }
9604         }
9605         /* save state */
9606         stream->stss_index = i;
9607       }
9608
9609       /* stps marks partial sync frames like open GOP I-Frames */
9610       if (stream->stps_present == TRUE) {
9611         guint32 n_sample_partial_syncs;
9612
9613         n_sample_partial_syncs = stream->n_sample_partial_syncs;
9614
9615         /* if there are no entries, the stss table contains the real
9616          * sync samples */
9617         if (n_sample_partial_syncs) {
9618           for (i = stream->stps_index; i < n_sample_partial_syncs; i++) {
9619             /* note that the first sample is index 1, not 0 */
9620             guint32 index;
9621
9622             index = gst_byte_reader_get_uint32_be_unchecked (&stream->stps);
9623
9624             if (G_LIKELY (index > 0 && index <= n_samples)) {
9625               index -= 1;
9626               samples[index].keyframe = TRUE;
9627               GST_DEBUG_OBJECT (qtdemux, "samples at %u is keyframe", index);
9628               /* and exit if we have enough samples */
9629               if (G_UNLIKELY (index >= n)) {
9630                 i++;
9631                 break;
9632               }
9633             }
9634           }
9635           /* save state */
9636           stream->stps_index = i;
9637         }
9638       }
9639     } else {
9640       /* no stss, all samples are keyframes */
9641       stream->all_keyframe = TRUE;
9642       GST_DEBUG_OBJECT (qtdemux, "setting all keyframes");
9643     }
9644   }
9645
9646 ctts:
9647   /* composition time to sample */
9648   if (stream->ctts_present == TRUE) {
9649     guint32 n_composition_times;
9650     guint32 ctts_count;
9651     gint32 ctts_soffset;
9652
9653     /* Fill in the pts_offsets */
9654     cur = first;
9655     n_composition_times = stream->n_composition_times;
9656
9657     for (i = stream->ctts_index; i < n_composition_times; i++) {
9658       if (stream->ctts_sample_index >= stream->ctts_count
9659           || !stream->ctts_sample_index) {
9660         stream->ctts_count =
9661             gst_byte_reader_get_uint32_be_unchecked (&stream->ctts);
9662         stream->ctts_soffset =
9663             gst_byte_reader_get_int32_be_unchecked (&stream->ctts);
9664         stream->ctts_sample_index = 0;
9665       }
9666
9667       ctts_count = stream->ctts_count;
9668       ctts_soffset = stream->ctts_soffset;
9669
9670       for (j = stream->ctts_sample_index; j < ctts_count; j++) {
9671         cur->pts_offset = ctts_soffset;
9672         cur++;
9673
9674         if (G_UNLIKELY (cur > last)) {
9675           /* save state */
9676           stream->ctts_sample_index = j + 1;
9677           goto done;
9678         }
9679       }
9680       stream->ctts_sample_index = 0;
9681       stream->ctts_index++;
9682     }
9683   }
9684 done:
9685   stream->stbl_index = n;
9686   /* if index has been completely parsed, free data that is no-longer needed */
9687   if (n + 1 == stream->n_samples) {
9688     gst_qtdemux_stbl_free (stream);
9689     GST_DEBUG_OBJECT (qtdemux, "parsed all available samples;");
9690     if (qtdemux->pullbased) {
9691       GST_DEBUG_OBJECT (qtdemux, "checking for more samples");
9692       while (n + 1 == stream->n_samples)
9693         if (qtdemux_add_fragmented_samples (qtdemux) != GST_FLOW_OK)
9694           break;
9695     }
9696   }
9697   GST_OBJECT_UNLOCK (qtdemux);
9698
9699   return TRUE;
9700
9701   /* SUCCESS */
9702 already_parsed:
9703   {
9704     GST_LOG_OBJECT (qtdemux,
9705         "Tried to parse up to sample %u but this sample has already been parsed",
9706         n);
9707     /* if fragmented, there may be more */
9708     if (qtdemux->fragmented && n == stream->stbl_index)
9709       goto done;
9710     GST_OBJECT_UNLOCK (qtdemux);
9711     return TRUE;
9712   }
9713   /* ERRORS */
9714 out_of_samples:
9715   {
9716     GST_LOG_OBJECT (qtdemux,
9717         "Tried to parse up to sample %u but there are only %u samples", n + 1,
9718         stream->n_samples);
9719     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
9720         (_("This file is corrupt and cannot be played.")), (NULL));
9721     return FALSE;
9722   }
9723 corrupt_file:
9724   {
9725     GST_OBJECT_UNLOCK (qtdemux);
9726     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
9727         (_("This file is corrupt and cannot be played.")), (NULL));
9728     return FALSE;
9729   }
9730 }
9731
9732 /* collect all segment info for @stream.
9733  */
9734 static gboolean
9735 qtdemux_parse_segments (GstQTDemux * qtdemux, QtDemuxStream * stream,
9736     GNode * trak)
9737 {
9738   GNode *edts;
9739   /* accept edts if they contain gaps at start and there is only
9740    * one media segment */
9741   gboolean allow_pushbased_edts = TRUE;
9742   gint media_segments_count = 0;
9743
9744   /* parse and prepare segment info from the edit list */
9745   GST_DEBUG_OBJECT (qtdemux, "looking for edit list container");
9746   stream->n_segments = 0;
9747   stream->segments = NULL;
9748   if ((edts = qtdemux_tree_get_child_by_type (trak, FOURCC_edts))) {
9749     GNode *elst;
9750     gint n_segments;
9751     gint segment_number, entry_size;
9752     guint64 time;
9753     GstClockTime stime;
9754     const guint8 *buffer;
9755     guint8 version;
9756     guint32 size;
9757
9758     GST_DEBUG_OBJECT (qtdemux, "looking for edit list");
9759     if (!(elst = qtdemux_tree_get_child_by_type (edts, FOURCC_elst)))
9760       goto done;
9761
9762     buffer = elst->data;
9763
9764     size = QT_UINT32 (buffer);
9765     /* version, flags, n_segments */
9766     if (size < 16) {
9767       GST_WARNING_OBJECT (qtdemux, "Invalid edit list");
9768       goto done;
9769     }
9770     version = QT_UINT8 (buffer + 8);
9771     entry_size = (version == 1) ? 20 : 12;
9772
9773     n_segments = QT_UINT32 (buffer + 12);
9774
9775     if (n_segments > 100000 || size < 16 + n_segments * entry_size) {
9776       GST_WARNING_OBJECT (qtdemux, "Invalid edit list");
9777       goto done;
9778     }
9779
9780     /* we might allocate a bit too much, at least allocate 1 segment */
9781     stream->segments = g_new (QtDemuxSegment, MAX (n_segments, 1));
9782
9783     /* segments always start from 0 */
9784     time = 0;
9785     stime = 0;
9786     buffer += 16;
9787     for (segment_number = 0; segment_number < n_segments; segment_number++) {
9788       guint64 duration;
9789       guint64 media_time;
9790       gboolean empty_edit = FALSE;
9791       QtDemuxSegment *segment;
9792       guint32 rate_int;
9793       GstClockTime media_start = GST_CLOCK_TIME_NONE;
9794
9795       if (version == 1) {
9796         media_time = QT_UINT64 (buffer + 8);
9797         duration = QT_UINT64 (buffer);
9798         if (media_time == G_MAXUINT64)
9799           empty_edit = TRUE;
9800       } else {
9801         media_time = QT_UINT32 (buffer + 4);
9802         duration = QT_UINT32 (buffer);
9803         if (media_time == G_MAXUINT32)
9804           empty_edit = TRUE;
9805       }
9806
9807       if (!empty_edit)
9808         media_start = QTSTREAMTIME_TO_GSTTIME (stream, media_time);
9809
9810       segment = &stream->segments[segment_number];
9811
9812       /* time and duration expressed in global timescale */
9813       segment->time = stime;
9814       if (duration != 0 || empty_edit) {
9815         /* edge case: empty edits with duration=zero are treated here.
9816          * (files should not have these anyway). */
9817
9818         /* add non scaled values so we don't cause roundoff errors */
9819         time += duration;
9820         stime = QTTIME_TO_GSTTIME (qtdemux, time);
9821         segment->duration = stime - segment->time;
9822       } else {
9823         /* zero duration does not imply media_start == media_stop
9824          * but, only specify media_start. The edit ends with the track. */
9825         stime = segment->duration = GST_CLOCK_TIME_NONE;
9826         /* Don't allow more edits after this one. */
9827         n_segments = segment_number + 1;
9828       }
9829       segment->stop_time = stime;
9830
9831       segment->trak_media_start = media_time;
9832       /* media_time expressed in stream timescale */
9833       if (!empty_edit) {
9834         segment->media_start = media_start;
9835         segment->media_stop = GST_CLOCK_TIME_IS_VALID (segment->duration)
9836             ? segment->media_start + segment->duration : GST_CLOCK_TIME_NONE;
9837         media_segments_count++;
9838       } else {
9839         segment->media_start = GST_CLOCK_TIME_NONE;
9840         segment->media_stop = GST_CLOCK_TIME_NONE;
9841       }
9842       rate_int = QT_UINT32 (buffer + ((version == 1) ? 16 : 8));
9843
9844       if (rate_int <= 1) {
9845         /* 0 is not allowed, some programs write 1 instead of the floating point
9846          * value */
9847         GST_WARNING_OBJECT (qtdemux, "found suspicious rate %" G_GUINT32_FORMAT,
9848             rate_int);
9849         segment->rate = 1;
9850       } else {
9851         segment->rate = rate_int / 65536.0;
9852       }
9853
9854       GST_DEBUG_OBJECT (qtdemux, "created segment %d time %" GST_TIME_FORMAT
9855           ", duration %" GST_TIME_FORMAT ", media_start %" GST_TIME_FORMAT
9856           " (%" G_GUINT64_FORMAT ") , media_stop %" GST_TIME_FORMAT
9857           " stop_time %" GST_TIME_FORMAT " rate %g, (%d) timescale %u",
9858           segment_number, GST_TIME_ARGS (segment->time),
9859           GST_TIME_ARGS (segment->duration),
9860           GST_TIME_ARGS (segment->media_start), media_time,
9861           GST_TIME_ARGS (segment->media_stop),
9862           GST_TIME_ARGS (segment->stop_time), segment->rate, rate_int,
9863           stream->timescale);
9864       if (segment->stop_time > qtdemux->segment.stop &&
9865           !qtdemux->upstream_format_is_time) {
9866         GST_WARNING_OBJECT (qtdemux, "Segment %d "
9867             " extends to %" GST_TIME_FORMAT
9868             " past the end of the declared movie duration %" GST_TIME_FORMAT
9869             " movie segment will be extended", segment_number,
9870             GST_TIME_ARGS (segment->stop_time),
9871             GST_TIME_ARGS (qtdemux->segment.stop));
9872         qtdemux->segment.stop = qtdemux->segment.duration = segment->stop_time;
9873       }
9874
9875       buffer += entry_size;
9876     }
9877     GST_DEBUG_OBJECT (qtdemux, "found %d segments", n_segments);
9878     stream->n_segments = n_segments;
9879     if (media_segments_count != 1)
9880       allow_pushbased_edts = FALSE;
9881   }
9882 done:
9883
9884   /* push based does not handle segments, so act accordingly here,
9885    * and warn if applicable */
9886   if (!qtdemux->pullbased && !allow_pushbased_edts) {
9887     GST_WARNING_OBJECT (qtdemux, "streaming; discarding edit list segments");
9888     /* remove and use default one below, we stream like it anyway */
9889     g_free (stream->segments);
9890     stream->segments = NULL;
9891     stream->n_segments = 0;
9892   }
9893
9894   /* no segments, create one to play the complete trak */
9895   if (stream->n_segments == 0) {
9896     GstClockTime stream_duration =
9897         QTSTREAMTIME_TO_GSTTIME (stream, stream->duration);
9898
9899     if (stream->segments == NULL)
9900       stream->segments = g_new (QtDemuxSegment, 1);
9901
9902     /* represent unknown our way */
9903     if (stream_duration == 0)
9904       stream_duration = GST_CLOCK_TIME_NONE;
9905
9906     stream->segments[0].time = 0;
9907     stream->segments[0].stop_time = stream_duration;
9908     stream->segments[0].duration = stream_duration;
9909     stream->segments[0].media_start = 0;
9910     stream->segments[0].media_stop = stream_duration;
9911     stream->segments[0].rate = 1.0;
9912     stream->segments[0].trak_media_start = 0;
9913
9914     GST_DEBUG_OBJECT (qtdemux, "created dummy segment %" GST_TIME_FORMAT,
9915         GST_TIME_ARGS (stream_duration));
9916     stream->n_segments = 1;
9917     stream->dummy_segment = TRUE;
9918   }
9919   GST_DEBUG_OBJECT (qtdemux, "using %d segments", stream->n_segments);
9920
9921   return TRUE;
9922 }
9923
9924 /*
9925  * Parses the stsd atom of a svq3 trak looking for
9926  * the SMI and gama atoms.
9927  */
9928 static void
9929 qtdemux_parse_svq3_stsd_data (GstQTDemux * qtdemux,
9930     const guint8 * stsd_entry_data, const guint8 ** gamma, GstBuffer ** seqh)
9931 {
9932   const guint8 *_gamma = NULL;
9933   GstBuffer *_seqh = NULL;
9934   const guint8 *stsd_data = stsd_entry_data;
9935   guint32 length = QT_UINT32 (stsd_data);
9936   guint16 version;
9937
9938   if (length < 32) {
9939     GST_WARNING_OBJECT (qtdemux, "stsd too short");
9940     goto end;
9941   }
9942
9943   stsd_data += 16;
9944   length -= 16;
9945   version = QT_UINT16 (stsd_data);
9946   if (version == 3) {
9947     if (length >= 70) {
9948       length -= 70;
9949       stsd_data += 70;
9950       while (length > 8) {
9951         guint32 fourcc, size;
9952         const guint8 *data;
9953         size = QT_UINT32 (stsd_data);
9954         fourcc = QT_FOURCC (stsd_data + 4);
9955         data = stsd_data + 8;
9956
9957         if (size == 0) {
9958           GST_WARNING_OBJECT (qtdemux, "Atom of size 0 found, aborting "
9959               "svq3 atom parsing");
9960           goto end;
9961         }
9962
9963         switch (fourcc) {
9964           case FOURCC_gama:{
9965             if (size == 12) {
9966               _gamma = data;
9967             } else {
9968               GST_WARNING_OBJECT (qtdemux, "Unexpected size %" G_GUINT32_FORMAT
9969                   " for gama atom, expected 12", size);
9970             }
9971             break;
9972           }
9973           case FOURCC_SMI_:{
9974             if (size > 16 && QT_FOURCC (data) == FOURCC_SEQH) {
9975               guint32 seqh_size;
9976               if (_seqh != NULL) {
9977                 GST_WARNING_OBJECT (qtdemux, "Unexpected second SEQH SMI atom "
9978                     " found, ignoring");
9979               } else {
9980                 seqh_size = QT_UINT32 (data + 4);
9981                 if (seqh_size > 0) {
9982                   _seqh = gst_buffer_new_and_alloc (seqh_size);
9983                   gst_buffer_fill (_seqh, 0, data + 8, seqh_size);
9984                 }
9985               }
9986             }
9987             break;
9988           }
9989           default:{
9990             GST_WARNING_OBJECT (qtdemux, "Unhandled atom %" GST_FOURCC_FORMAT
9991                 " in SVQ3 entry in stsd atom", GST_FOURCC_ARGS (fourcc));
9992           }
9993         }
9994
9995         if (size <= length) {
9996           length -= size;
9997           stsd_data += size;
9998         }
9999       }
10000     } else {
10001       GST_WARNING_OBJECT (qtdemux, "SVQ3 entry too short in stsd atom");
10002     }
10003   } else {
10004     GST_WARNING_OBJECT (qtdemux, "Unexpected version for SVQ3 entry %"
10005         G_GUINT16_FORMAT, version);
10006     goto end;
10007   }
10008
10009 end:
10010   if (gamma) {
10011     *gamma = _gamma;
10012   }
10013   if (seqh) {
10014     *seqh = _seqh;
10015   } else if (_seqh) {
10016     gst_buffer_unref (_seqh);
10017   }
10018 }
10019
10020 static gchar *
10021 qtdemux_get_rtsp_uri_from_hndl (GstQTDemux * qtdemux, GNode * minf)
10022 {
10023   GNode *dinf;
10024   GstByteReader dref;
10025   gchar *uri = NULL;
10026
10027   /*
10028    * Get 'dinf', to get its child 'dref', that might contain a 'hndl'
10029    * atom that might contain a 'data' atom with the rtsp uri.
10030    * This case was reported in bug #597497, some info about
10031    * the hndl atom can be found in TN1195
10032    */
10033   dinf = qtdemux_tree_get_child_by_type (minf, FOURCC_dinf);
10034   GST_DEBUG_OBJECT (qtdemux, "Trying to obtain rtsp URI for stream trak");
10035
10036   if (dinf) {
10037     guint32 dref_num_entries = 0;
10038     if (qtdemux_tree_get_child_by_type_full (dinf, FOURCC_dref, &dref) &&
10039         gst_byte_reader_skip (&dref, 4) &&
10040         gst_byte_reader_get_uint32_be (&dref, &dref_num_entries)) {
10041       gint i;
10042
10043       /* search dref entries for hndl atom */
10044       for (i = 0; i < dref_num_entries; i++) {
10045         guint32 size = 0, type;
10046         guint8 string_len = 0;
10047         if (gst_byte_reader_get_uint32_be (&dref, &size) &&
10048             qt_atom_parser_get_fourcc (&dref, &type)) {
10049           if (type == FOURCC_hndl) {
10050             GST_DEBUG_OBJECT (qtdemux, "Found hndl atom");
10051
10052             /* skip data reference handle bytes and the
10053              * following pascal string and some extra 4
10054              * bytes I have no idea what are */
10055             if (!gst_byte_reader_skip (&dref, 4) ||
10056                 !gst_byte_reader_get_uint8 (&dref, &string_len) ||
10057                 !gst_byte_reader_skip (&dref, string_len + 4)) {
10058               GST_WARNING_OBJECT (qtdemux, "Failed to parse hndl atom");
10059               break;
10060             }
10061
10062             /* iterate over the atoms to find the data atom */
10063             while (gst_byte_reader_get_remaining (&dref) >= 8) {
10064               guint32 atom_size;
10065               guint32 atom_type;
10066
10067               if (gst_byte_reader_get_uint32_be (&dref, &atom_size) &&
10068                   qt_atom_parser_get_fourcc (&dref, &atom_type)) {
10069                 if (atom_type == FOURCC_data) {
10070                   const guint8 *uri_aux = NULL;
10071
10072                   /* found the data atom that might contain the rtsp uri */
10073                   GST_DEBUG_OBJECT (qtdemux, "Found data atom inside "
10074                       "hndl atom, interpreting it as an URI");
10075                   if (gst_byte_reader_peek_data (&dref, atom_size - 8,
10076                           &uri_aux)) {
10077                     if (g_strstr_len ((gchar *) uri_aux, 7, "rtsp://") != NULL)
10078                       uri = g_strndup ((gchar *) uri_aux, atom_size - 8);
10079                     else
10080                       GST_WARNING_OBJECT (qtdemux, "Data atom in hndl atom "
10081                           "didn't contain a rtsp address");
10082                   } else {
10083                     GST_WARNING_OBJECT (qtdemux, "Failed to get the data "
10084                         "atom contents");
10085                   }
10086                   break;
10087                 }
10088                 /* skipping to the next entry */
10089                 if (!gst_byte_reader_skip (&dref, atom_size - 8))
10090                   break;
10091               } else {
10092                 GST_WARNING_OBJECT (qtdemux, "Failed to parse hndl child "
10093                     "atom header");
10094                 break;
10095               }
10096             }
10097             break;
10098           }
10099           /* skip to the next entry */
10100           if (!gst_byte_reader_skip (&dref, size - 8))
10101             break;
10102         } else {
10103           GST_WARNING_OBJECT (qtdemux, "Error parsing dref atom");
10104         }
10105       }
10106       GST_DEBUG_OBJECT (qtdemux, "Finished parsing dref atom");
10107     }
10108   }
10109   return uri;
10110 }
10111
10112 #define AMR_NB_ALL_MODES        0x81ff
10113 #define AMR_WB_ALL_MODES        0x83ff
10114 static guint
10115 qtdemux_parse_amr_bitrate (GstBuffer * buf, gboolean wb)
10116 {
10117   /* The 'damr' atom is of the form:
10118    *
10119    * | vendor | decoder_ver | mode_set | mode_change_period | frames/sample |
10120    *    32 b       8 b          16 b           8 b                 8 b
10121    *
10122    * The highest set bit of the first 7 (AMR-NB) or 8 (AMR-WB) bits of mode_set
10123    * represents the highest mode used in the stream (and thus the maximum
10124    * bitrate), with a couple of special cases as seen below.
10125    */
10126
10127   /* Map of frame type ID -> bitrate */
10128   static const guint nb_bitrates[] = {
10129     4750, 5150, 5900, 6700, 7400, 7950, 10200, 12200
10130   };
10131   static const guint wb_bitrates[] = {
10132     6600, 8850, 12650, 14250, 15850, 18250, 19850, 23050, 23850
10133   };
10134   GstMapInfo map;
10135   gsize max_mode;
10136   guint16 mode_set;
10137
10138   gst_buffer_map (buf, &map, GST_MAP_READ);
10139
10140   if (map.size != 0x11) {
10141     GST_DEBUG ("Atom should have size 0x11, not %" G_GSIZE_FORMAT, map.size);
10142     goto bad_data;
10143   }
10144
10145   if (QT_FOURCC (map.data + 4) != FOURCC_damr) {
10146     GST_DEBUG ("Unknown atom in %" GST_FOURCC_FORMAT,
10147         GST_FOURCC_ARGS (QT_UINT32 (map.data + 4)));
10148     goto bad_data;
10149   }
10150
10151   mode_set = QT_UINT16 (map.data + 13);
10152
10153   if (mode_set == (wb ? AMR_WB_ALL_MODES : AMR_NB_ALL_MODES))
10154     max_mode = 7 + (wb ? 1 : 0);
10155   else
10156     /* AMR-NB modes fo from 0-7, and AMR-WB modes go from 0-8 */
10157     max_mode = g_bit_nth_msf ((gulong) mode_set & (wb ? 0x1ff : 0xff), -1);
10158
10159   if (max_mode == -1) {
10160     GST_DEBUG ("No mode indication was found (mode set) = %x",
10161         (guint) mode_set);
10162     goto bad_data;
10163   }
10164
10165   gst_buffer_unmap (buf, &map);
10166   return wb ? wb_bitrates[max_mode] : nb_bitrates[max_mode];
10167
10168 bad_data:
10169   gst_buffer_unmap (buf, &map);
10170   return 0;
10171 }
10172
10173 static gboolean
10174 qtdemux_parse_transformation_matrix (GstQTDemux * qtdemux,
10175     GstByteReader * reader, guint32 * matrix, const gchar * atom)
10176 {
10177   /*
10178    * 9 values of 32 bits (fixed point 16.16, except 2 5 and 8 that are 2.30)
10179    * [0 1 2]
10180    * [3 4 5]
10181    * [6 7 8]
10182    */
10183
10184   if (gst_byte_reader_get_remaining (reader) < 36)
10185     return FALSE;
10186
10187   matrix[0] = gst_byte_reader_get_uint32_be_unchecked (reader);
10188   matrix[1] = gst_byte_reader_get_uint32_be_unchecked (reader);
10189   matrix[2] = gst_byte_reader_get_uint32_be_unchecked (reader);
10190   matrix[3] = gst_byte_reader_get_uint32_be_unchecked (reader);
10191   matrix[4] = gst_byte_reader_get_uint32_be_unchecked (reader);
10192   matrix[5] = gst_byte_reader_get_uint32_be_unchecked (reader);
10193   matrix[6] = gst_byte_reader_get_uint32_be_unchecked (reader);
10194   matrix[7] = gst_byte_reader_get_uint32_be_unchecked (reader);
10195   matrix[8] = gst_byte_reader_get_uint32_be_unchecked (reader);
10196
10197   GST_DEBUG_OBJECT (qtdemux, "Transformation matrix from atom %s", atom);
10198   GST_DEBUG_OBJECT (qtdemux, "%u.%u %u.%u %u.%u", matrix[0] >> 16,
10199       matrix[0] & 0xFFFF, matrix[1] >> 16, matrix[1] & 0xFF, matrix[2] >> 16,
10200       matrix[2] & 0xFF);
10201   GST_DEBUG_OBJECT (qtdemux, "%u.%u %u.%u %u.%u", matrix[3] >> 16,
10202       matrix[3] & 0xFFFF, matrix[4] >> 16, matrix[4] & 0xFF, matrix[5] >> 16,
10203       matrix[5] & 0xFF);
10204   GST_DEBUG_OBJECT (qtdemux, "%u.%u %u.%u %u.%u", matrix[6] >> 16,
10205       matrix[6] & 0xFFFF, matrix[7] >> 16, matrix[7] & 0xFF, matrix[8] >> 16,
10206       matrix[8] & 0xFF);
10207
10208   return TRUE;
10209 }
10210
10211 static void
10212 qtdemux_inspect_transformation_matrix (GstQTDemux * qtdemux,
10213     QtDemuxStream * stream, guint32 * matrix, GstTagList ** taglist)
10214 {
10215
10216 /* [a b c]
10217  * [d e f]
10218  * [g h i]
10219  *
10220  * This macro will only compare value abdegh, it expects cfi to have already
10221  * been checked
10222  */
10223 #define QTCHECK_MATRIX(m,a,b,d,e) ((m)[0] == (a << 16) && (m)[1] == (b << 16) && \
10224                                    (m)[3] == (d << 16) && (m)[4] == (e << 16))
10225
10226   /* only handle the cases where the last column has standard values */
10227   if (matrix[2] == 0 && matrix[5] == 0 && matrix[8] == 1 << 30) {
10228     const gchar *rotation_tag = NULL;
10229
10230     /* no rotation needed */
10231     if (QTCHECK_MATRIX (matrix, 1, 0, 0, 1)) {
10232       /* NOP */
10233     } else if (QTCHECK_MATRIX (matrix, 0, 1, G_MAXUINT16, 0)) {
10234       rotation_tag = "rotate-90";
10235     } else if (QTCHECK_MATRIX (matrix, G_MAXUINT16, 0, 0, G_MAXUINT16)) {
10236       rotation_tag = "rotate-180";
10237     } else if (QTCHECK_MATRIX (matrix, 0, G_MAXUINT16, 1, 0)) {
10238       rotation_tag = "rotate-270";
10239     } else {
10240       GST_FIXME_OBJECT (qtdemux, "Unhandled transformation matrix values");
10241     }
10242
10243     GST_DEBUG_OBJECT (qtdemux, "Transformation matrix rotation %s",
10244         rotation_tag);
10245     if (rotation_tag != NULL) {
10246       if (*taglist == NULL)
10247         *taglist = gst_tag_list_new_empty ();
10248       gst_tag_list_add (*taglist, GST_TAG_MERGE_REPLACE,
10249           GST_TAG_IMAGE_ORIENTATION, rotation_tag, NULL);
10250     }
10251   } else {
10252     GST_FIXME_OBJECT (qtdemux, "Unhandled transformation matrix values");
10253   }
10254 }
10255
10256 /* Parses the boxes defined in ISO/IEC 14496-12 that enable support for
10257  * protected streams (sinf, frma, schm and schi); if the protection scheme is
10258  * Common Encryption (cenc), the function will also parse the tenc box (defined
10259  * in ISO/IEC 23001-7). @container points to the node that contains these boxes
10260  * (typically an enc[v|a|t|s] sample entry); the function will set
10261  * @original_fmt to the fourcc of the original unencrypted stream format.
10262  * Returns TRUE if successful; FALSE otherwise. */
10263 static gboolean
10264 qtdemux_parse_protection_scheme_info (GstQTDemux * qtdemux,
10265     QtDemuxStream * stream, GNode * container, guint32 * original_fmt)
10266 {
10267   GNode *sinf;
10268   GNode *frma;
10269   GNode *schm;
10270   GNode *schi;
10271   QtDemuxCencSampleSetInfo *info;
10272   GNode *tenc;
10273   const guint8 *tenc_data;
10274
10275   g_return_val_if_fail (qtdemux != NULL, FALSE);
10276   g_return_val_if_fail (stream != NULL, FALSE);
10277   g_return_val_if_fail (container != NULL, FALSE);
10278   g_return_val_if_fail (original_fmt != NULL, FALSE);
10279
10280   sinf = qtdemux_tree_get_child_by_type (container, FOURCC_sinf);
10281   if (G_UNLIKELY (!sinf)) {
10282     if (stream->protection_scheme_type == FOURCC_cenc) {
10283       GST_ERROR_OBJECT (qtdemux, "sinf box does not contain schi box, which is "
10284           "mandatory for Common Encryption");
10285       return FALSE;
10286     }
10287     return TRUE;
10288   }
10289
10290   frma = qtdemux_tree_get_child_by_type (sinf, FOURCC_frma);
10291   if (G_UNLIKELY (!frma)) {
10292     GST_ERROR_OBJECT (qtdemux, "sinf box does not contain mandatory frma box");
10293     return FALSE;
10294   }
10295
10296   *original_fmt = QT_FOURCC ((const guint8 *) frma->data + 8);
10297   GST_DEBUG_OBJECT (qtdemux, "original stream format: '%" GST_FOURCC_FORMAT "'",
10298       GST_FOURCC_ARGS (*original_fmt));
10299
10300   schm = qtdemux_tree_get_child_by_type (sinf, FOURCC_schm);
10301   if (!schm) {
10302     GST_DEBUG_OBJECT (qtdemux, "sinf box does not contain schm box");
10303     return FALSE;
10304   }
10305   stream->protection_scheme_type = QT_FOURCC ((const guint8 *) schm->data + 12);
10306   stream->protection_scheme_version =
10307       QT_UINT32 ((const guint8 *) schm->data + 16);
10308
10309   GST_DEBUG_OBJECT (qtdemux,
10310       "protection_scheme_type: %" GST_FOURCC_FORMAT ", "
10311       "protection_scheme_version: %#010x",
10312       GST_FOURCC_ARGS (stream->protection_scheme_type),
10313       stream->protection_scheme_version);
10314
10315   schi = qtdemux_tree_get_child_by_type (sinf, FOURCC_schi);
10316   if (!schi) {
10317     GST_DEBUG_OBJECT (qtdemux, "sinf box does not contain schi box");
10318     return FALSE;
10319   }
10320   if (stream->protection_scheme_type != FOURCC_cenc &&
10321       stream->protection_scheme_type != FOURCC_piff) {
10322     GST_ERROR_OBJECT (qtdemux,
10323         "Invalid protection_scheme_type: %" GST_FOURCC_FORMAT,
10324         GST_FOURCC_ARGS (stream->protection_scheme_type));
10325     return FALSE;
10326   }
10327
10328   if (G_UNLIKELY (!stream->protection_scheme_info))
10329     stream->protection_scheme_info =
10330         g_malloc0 (sizeof (QtDemuxCencSampleSetInfo));
10331
10332   info = (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
10333
10334   if (stream->protection_scheme_type == FOURCC_cenc) {
10335     guint32 is_encrypted;
10336     guint8 iv_size;
10337     const guint8 *default_kid;
10338
10339     tenc = qtdemux_tree_get_child_by_type (schi, FOURCC_tenc);
10340     if (!tenc) {
10341       GST_ERROR_OBJECT (qtdemux, "schi box does not contain tenc box, "
10342           "which is mandatory for Common Encryption");
10343       return FALSE;
10344     }
10345     tenc_data = (const guint8 *) tenc->data + 12;
10346     is_encrypted = QT_UINT24 (tenc_data);
10347     iv_size = QT_UINT8 (tenc_data + 3);
10348     default_kid = (tenc_data + 4);
10349     qtdemux_update_default_sample_encryption_settings (qtdemux, info,
10350         is_encrypted, iv_size, default_kid);
10351   } else if (stream->protection_scheme_type == FOURCC_piff) {
10352     GstByteReader br;
10353     static const guint8 piff_track_encryption_uuid[] = {
10354       0x89, 0x74, 0xdb, 0xce, 0x7b, 0xe7, 0x4c, 0x51,
10355       0x84, 0xf9, 0x71, 0x48, 0xf9, 0x88, 0x25, 0x54
10356     };
10357
10358     tenc = qtdemux_tree_get_child_by_type (schi, FOURCC_uuid);
10359     if (!tenc) {
10360       GST_ERROR_OBJECT (qtdemux, "schi box does not contain tenc box, "
10361           "which is mandatory for Common Encryption");
10362       return FALSE;
10363     }
10364
10365     tenc_data = (const guint8 *) tenc->data + 8;
10366     if (memcmp (tenc_data, piff_track_encryption_uuid, 16) != 0) {
10367       gchar *box_uuid = qtdemux_uuid_bytes_to_string (tenc_data);
10368       GST_ERROR_OBJECT (qtdemux,
10369           "Unsupported track encryption box with uuid: %s", box_uuid);
10370       g_free (box_uuid);
10371       return FALSE;
10372     }
10373     tenc_data = (const guint8 *) tenc->data + 16 + 12;
10374     gst_byte_reader_init (&br, tenc_data, 20);
10375     if (!qtdemux_update_default_piff_encryption_settings (qtdemux, info, &br)) {
10376       GST_ERROR_OBJECT (qtdemux, "PIFF track box parsing error");
10377       return FALSE;
10378     }
10379     stream->protection_scheme_type = FOURCC_cenc;
10380   }
10381
10382   return TRUE;
10383 }
10384
10385 static gint
10386 qtdemux_track_id_compare_func (QtDemuxStream ** stream1,
10387     QtDemuxStream ** stream2)
10388 {
10389   return (gint) (*stream1)->track_id - (gint) (*stream2)->track_id;
10390 }
10391
10392 /* parse the traks.
10393  * With each track we associate a new QtDemuxStream that contains all the info
10394  * about the trak.
10395  * traks that do not decode to something (like strm traks) will not have a pad.
10396  */
10397 static gboolean
10398 qtdemux_parse_trak (GstQTDemux * qtdemux, GNode * trak)
10399 {
10400   GstByteReader tkhd;
10401   int offset;
10402   GNode *mdia;
10403   GNode *mdhd;
10404   GNode *hdlr;
10405   GNode *minf;
10406   GNode *stbl;
10407   GNode *stsd;
10408   GNode *mp4a;
10409   GNode *mp4v;
10410   GNode *esds;
10411   GNode *tref;
10412   GNode *udta;
10413   GNode *svmi;
10414
10415   QtDemuxStream *stream = NULL;
10416   const guint8 *stsd_data;
10417   const guint8 *stsd_entry_data;
10418   guint remaining_stsd_len;
10419   guint stsd_entry_count;
10420   guint stsd_index;
10421   guint16 lang_code;            /* quicktime lang code or packed iso code */
10422   guint32 version;
10423   guint32 tkhd_flags = 0;
10424   guint8 tkhd_version = 0;
10425   guint32 w = 0, h = 0;
10426   guint value_size, stsd_len, len;
10427   guint32 track_id;
10428   guint32 dummy;
10429
10430   GST_DEBUG_OBJECT (qtdemux, "parse_trak");
10431
10432   if (!qtdemux_tree_get_child_by_type_full (trak, FOURCC_tkhd, &tkhd)
10433       || !gst_byte_reader_get_uint8 (&tkhd, &tkhd_version)
10434       || !gst_byte_reader_get_uint24_be (&tkhd, &tkhd_flags))
10435     goto corrupt_file;
10436
10437   /* pick between 64 or 32 bits */
10438   value_size = tkhd_version == 1 ? 8 : 4;
10439   if (!gst_byte_reader_skip (&tkhd, value_size * 2) ||
10440       !gst_byte_reader_get_uint32_be (&tkhd, &track_id))
10441     goto corrupt_file;
10442
10443   /* Check if current moov has duplicated track_id */
10444   if (qtdemux_find_stream (qtdemux, track_id))
10445     goto existing_stream;
10446
10447   stream = _create_stream (qtdemux, track_id);
10448   stream->stream_tags = gst_tag_list_make_writable (stream->stream_tags);
10449
10450   /* need defaults for fragments */
10451   qtdemux_parse_trex (qtdemux, stream, &dummy, &dummy, &dummy);
10452
10453   if ((tkhd_flags & 1) == 0)
10454     stream->disabled = TRUE;
10455
10456   GST_LOG_OBJECT (qtdemux, "track[tkhd] version/flags/id: 0x%02x/%06x/%u",
10457       tkhd_version, tkhd_flags, stream->track_id);
10458
10459   if (!(mdia = qtdemux_tree_get_child_by_type (trak, FOURCC_mdia)))
10460     goto corrupt_file;
10461
10462   if (!(mdhd = qtdemux_tree_get_child_by_type (mdia, FOURCC_mdhd))) {
10463     /* be nice for some crooked mjp2 files that use mhdr for mdhd */
10464     if (qtdemux->major_brand != FOURCC_mjp2 ||
10465         !(mdhd = qtdemux_tree_get_child_by_type (mdia, FOURCC_mhdr)))
10466       goto corrupt_file;
10467   }
10468
10469   len = QT_UINT32 ((guint8 *) mdhd->data);
10470   version = QT_UINT32 ((guint8 *) mdhd->data + 8);
10471   GST_LOG_OBJECT (qtdemux, "track version/flags: %08x", version);
10472   if (version == 0x01000000) {
10473     if (len < 42)
10474       goto corrupt_file;
10475     stream->timescale = QT_UINT32 ((guint8 *) mdhd->data + 28);
10476     stream->duration = QT_UINT64 ((guint8 *) mdhd->data + 32);
10477     lang_code = QT_UINT16 ((guint8 *) mdhd->data + 40);
10478   } else {
10479     if (len < 30)
10480       goto corrupt_file;
10481     stream->timescale = QT_UINT32 ((guint8 *) mdhd->data + 20);
10482     stream->duration = QT_UINT32 ((guint8 *) mdhd->data + 24);
10483     lang_code = QT_UINT16 ((guint8 *) mdhd->data + 28);
10484   }
10485
10486   if (lang_code < 0x400) {
10487     qtdemux_lang_map_qt_code_to_iso (stream->lang_id, lang_code);
10488   } else if (lang_code == 0x7fff) {
10489     stream->lang_id[0] = 0;     /* unspecified */
10490   } else {
10491     stream->lang_id[0] = 0x60 + ((lang_code >> 10) & 0x1F);
10492     stream->lang_id[1] = 0x60 + ((lang_code >> 5) & 0x1F);
10493     stream->lang_id[2] = 0x60 + (lang_code & 0x1F);
10494     stream->lang_id[3] = 0;
10495   }
10496
10497   GST_LOG_OBJECT (qtdemux, "track timescale: %" G_GUINT32_FORMAT,
10498       stream->timescale);
10499   GST_LOG_OBJECT (qtdemux, "track duration: %" G_GUINT64_FORMAT,
10500       stream->duration);
10501   GST_LOG_OBJECT (qtdemux, "track language code/id: 0x%04x/%s",
10502       lang_code, stream->lang_id);
10503
10504   if (G_UNLIKELY (stream->timescale == 0 || qtdemux->timescale == 0))
10505     goto corrupt_file;
10506
10507   if ((tref = qtdemux_tree_get_child_by_type (trak, FOURCC_tref))) {
10508     /* chapters track reference */
10509     GNode *chap = qtdemux_tree_get_child_by_type (tref, FOURCC_chap);
10510     if (chap) {
10511       gsize length = GST_READ_UINT32_BE (chap->data);
10512       if (qtdemux->chapters_track_id)
10513         GST_FIXME_OBJECT (qtdemux, "Multiple CHAP tracks");
10514
10515       if (length >= 12) {
10516         qtdemux->chapters_track_id =
10517             GST_READ_UINT32_BE ((gint8 *) chap->data + 8);
10518       }
10519     }
10520   }
10521
10522   /* fragmented files may have bogus duration in moov */
10523   if (!qtdemux->fragmented &&
10524       qtdemux->duration != G_MAXINT64 && stream->duration != G_MAXINT32) {
10525     guint64 tdur1, tdur2;
10526
10527     /* don't overflow */
10528     tdur1 = stream->timescale * (guint64) qtdemux->duration;
10529     tdur2 = qtdemux->timescale * (guint64) stream->duration;
10530
10531     /* HACK:
10532      * some of those trailers, nowadays, have prologue images that are
10533      * themselves video tracks as well. I haven't really found a way to
10534      * identify those yet, except for just looking at their duration. */
10535     if (tdur1 != 0 && (tdur2 * 10 / tdur1) < 2) {
10536       GST_WARNING_OBJECT (qtdemux,
10537           "Track shorter than 20%% (%" G_GUINT64_FORMAT "/%" G_GUINT32_FORMAT
10538           " vs. %" G_GUINT64_FORMAT "/%" G_GUINT32_FORMAT ") of the stream "
10539           "found, assuming preview image or something; skipping track",
10540           stream->duration, stream->timescale, qtdemux->duration,
10541           qtdemux->timescale);
10542       gst_qtdemux_stream_unref (stream);
10543       return TRUE;
10544     }
10545   }
10546
10547   if (!(hdlr = qtdemux_tree_get_child_by_type (mdia, FOURCC_hdlr)))
10548     goto corrupt_file;
10549
10550   GST_LOG_OBJECT (qtdemux, "track type: %" GST_FOURCC_FORMAT,
10551       GST_FOURCC_ARGS (QT_FOURCC ((guint8 *) hdlr->data + 12)));
10552
10553   len = QT_UINT32 ((guint8 *) hdlr->data);
10554   if (len >= 20)
10555     stream->subtype = QT_FOURCC ((guint8 *) hdlr->data + 16);
10556   GST_LOG_OBJECT (qtdemux, "track subtype: %" GST_FOURCC_FORMAT,
10557       GST_FOURCC_ARGS (stream->subtype));
10558
10559   if (!(minf = qtdemux_tree_get_child_by_type (mdia, FOURCC_minf)))
10560     goto corrupt_file;
10561
10562   if (!(stbl = qtdemux_tree_get_child_by_type (minf, FOURCC_stbl)))
10563     goto corrupt_file;
10564
10565   /*parse svmi header if existing */
10566   svmi = qtdemux_tree_get_child_by_type (stbl, FOURCC_svmi);
10567   if (svmi) {
10568     len = QT_UINT32 ((guint8 *) svmi->data);
10569     version = QT_UINT32 ((guint8 *) svmi->data + 8);
10570     if (!version) {
10571       GstVideoMultiviewMode mode = GST_VIDEO_MULTIVIEW_MODE_NONE;
10572       GstVideoMultiviewFlags flags = GST_VIDEO_MULTIVIEW_FLAGS_NONE;
10573       guint8 frame_type, frame_layout;
10574
10575       /* MPEG-A stereo video */
10576       if (qtdemux->major_brand == FOURCC_ss02)
10577         flags |= GST_VIDEO_MULTIVIEW_FLAGS_MIXED_MONO;
10578
10579       frame_type = QT_UINT8 ((guint8 *) svmi->data + 12);
10580       frame_layout = QT_UINT8 ((guint8 *) svmi->data + 13) & 0x01;
10581       switch (frame_type) {
10582         case 0:
10583           mode = GST_VIDEO_MULTIVIEW_MODE_SIDE_BY_SIDE;
10584           break;
10585         case 1:
10586           mode = GST_VIDEO_MULTIVIEW_MODE_ROW_INTERLEAVED;
10587           break;
10588         case 2:
10589           mode = GST_VIDEO_MULTIVIEW_MODE_FRAME_BY_FRAME;
10590           break;
10591         case 3:
10592           /* mode 3 is primary/secondary view sequence, ie
10593            * left/right views in separate tracks. See section 7.2
10594            * of ISO/IEC 23000-11:2009 */
10595           GST_FIXME_OBJECT (qtdemux,
10596               "Implement stereo video in separate streams");
10597       }
10598
10599       if ((frame_layout & 0x1) == 0)
10600         flags |= GST_VIDEO_MULTIVIEW_FLAGS_RIGHT_VIEW_FIRST;
10601
10602       GST_LOG_OBJECT (qtdemux,
10603           "StereoVideo: composition type: %u, is_left_first: %u",
10604           frame_type, frame_layout);
10605       stream->multiview_mode = mode;
10606       stream->multiview_flags = flags;
10607     }
10608   }
10609
10610   /* parse rest of tkhd */
10611   if (stream->subtype == FOURCC_vide) {
10612     guint32 matrix[9];
10613
10614     /* version 1 uses some 64-bit ints */
10615     if (!gst_byte_reader_skip (&tkhd, 20 + value_size))
10616       goto corrupt_file;
10617
10618     if (!qtdemux_parse_transformation_matrix (qtdemux, &tkhd, matrix, "tkhd"))
10619       goto corrupt_file;
10620
10621     if (!gst_byte_reader_get_uint32_be (&tkhd, &w)
10622         || !gst_byte_reader_get_uint32_be (&tkhd, &h))
10623       goto corrupt_file;
10624
10625     qtdemux_inspect_transformation_matrix (qtdemux, stream, matrix,
10626         &stream->stream_tags);
10627   }
10628
10629   /* parse stsd */
10630   if (!(stsd = qtdemux_tree_get_child_by_type (stbl, FOURCC_stsd)))
10631     goto corrupt_file;
10632   stsd_data = (const guint8 *) stsd->data;
10633
10634   /* stsd should at least have one entry */
10635   stsd_len = QT_UINT32 (stsd_data);
10636   if (stsd_len < 24) {
10637     /* .. but skip stream with empty stsd produced by some Vivotek cameras */
10638     if (stream->subtype == FOURCC_vivo) {
10639       gst_qtdemux_stream_unref (stream);
10640       return TRUE;
10641     } else {
10642       goto corrupt_file;
10643     }
10644   }
10645
10646   stream->stsd_entries_length = stsd_entry_count = QT_UINT32 (stsd_data + 12);
10647   stream->stsd_entries = g_new0 (QtDemuxStreamStsdEntry, stsd_entry_count);
10648   GST_LOG_OBJECT (qtdemux, "stsd len:           %d", stsd_len);
10649   GST_LOG_OBJECT (qtdemux, "stsd entry count:   %u", stsd_entry_count);
10650
10651   stsd_entry_data = stsd_data + 16;
10652   remaining_stsd_len = stsd_len - 16;
10653   for (stsd_index = 0; stsd_index < stsd_entry_count; stsd_index++) {
10654     guint32 fourcc;
10655     gchar *codec = NULL;
10656     QtDemuxStreamStsdEntry *entry = &stream->stsd_entries[stsd_index];
10657
10658     /* and that entry should fit within stsd */
10659     len = QT_UINT32 (stsd_entry_data);
10660     if (len > remaining_stsd_len)
10661       goto corrupt_file;
10662
10663     entry->fourcc = fourcc = QT_FOURCC (stsd_entry_data + 4);
10664     GST_LOG_OBJECT (qtdemux, "stsd type:          %" GST_FOURCC_FORMAT,
10665         GST_FOURCC_ARGS (entry->fourcc));
10666     GST_LOG_OBJECT (qtdemux, "stsd type len:      %d", len);
10667
10668     if ((fourcc == FOURCC_drms) || (fourcc == FOURCC_drmi))
10669       goto error_encrypted;
10670
10671     if (fourcc == FOURCC_encv || fourcc == FOURCC_enca) {
10672       /* FIXME this looks wrong, there might be multiple children
10673        * with the same type */
10674       GNode *enc = qtdemux_tree_get_child_by_type (stsd, fourcc);
10675       stream->protected = TRUE;
10676       if (!qtdemux_parse_protection_scheme_info (qtdemux, stream, enc, &fourcc))
10677         GST_ERROR_OBJECT (qtdemux, "Failed to parse protection scheme info");
10678     }
10679
10680     if (stream->subtype == FOURCC_vide) {
10681       GNode *colr;
10682       GNode *fiel;
10683       GNode *pasp;
10684       gboolean gray;
10685       gint depth, palette_size, palette_count;
10686       guint32 *palette_data = NULL;
10687
10688       entry->sampled = TRUE;
10689
10690       stream->display_width = w >> 16;
10691       stream->display_height = h >> 16;
10692
10693       offset = 16;
10694       if (len < 86)             /* TODO verify */
10695         goto corrupt_file;
10696
10697       entry->width = QT_UINT16 (stsd_entry_data + offset + 16);
10698       entry->height = QT_UINT16 (stsd_entry_data + offset + 18);
10699       entry->fps_n = 0;         /* this is filled in later */
10700       entry->fps_d = 0;         /* this is filled in later */
10701       entry->bits_per_sample = QT_UINT16 (stsd_entry_data + offset + 66);
10702       entry->color_table_id = QT_UINT16 (stsd_entry_data + offset + 68);
10703
10704       /* if color_table_id is 0, ctab atom must follow; however some files
10705        * produced by TMPEGEnc have color_table_id = 0 and no ctab atom, so
10706        * if color table is not present we'll correct the value */
10707       if (entry->color_table_id == 0 &&
10708           (len < 90
10709               || QT_FOURCC (stsd_entry_data + offset + 70) != FOURCC_ctab)) {
10710         entry->color_table_id = -1;
10711       }
10712
10713       GST_LOG_OBJECT (qtdemux, "width %d, height %d, bps %d, color table id %d",
10714           entry->width, entry->height, entry->bits_per_sample,
10715           entry->color_table_id);
10716
10717       depth = entry->bits_per_sample;
10718
10719       /* more than 32 bits means grayscale */
10720       gray = (depth > 32);
10721       /* low 32 bits specify the depth  */
10722       depth &= 0x1F;
10723
10724       /* different number of palette entries is determined by depth. */
10725       palette_count = 0;
10726       if ((depth == 1) || (depth == 2) || (depth == 4) || (depth == 8))
10727         palette_count = (1 << depth);
10728       palette_size = palette_count * 4;
10729
10730       if (entry->color_table_id) {
10731         switch (palette_count) {
10732           case 0:
10733             break;
10734           case 2:
10735             palette_data = g_memdup (ff_qt_default_palette_2, palette_size);
10736             break;
10737           case 4:
10738             palette_data = g_memdup (ff_qt_default_palette_4, palette_size);
10739             break;
10740           case 16:
10741             if (gray)
10742               palette_data =
10743                   g_memdup (ff_qt_grayscale_palette_16, palette_size);
10744             else
10745               palette_data = g_memdup (ff_qt_default_palette_16, palette_size);
10746             break;
10747           case 256:
10748             if (gray)
10749               palette_data =
10750                   g_memdup (ff_qt_grayscale_palette_256, palette_size);
10751             else
10752               palette_data = g_memdup (ff_qt_default_palette_256, palette_size);
10753             break;
10754           default:
10755             GST_ELEMENT_WARNING (qtdemux, STREAM, DEMUX,
10756                 (_("The video in this file might not play correctly.")),
10757                 ("unsupported palette depth %d", depth));
10758             break;
10759         }
10760       } else {
10761         gint i, j, start, end;
10762
10763         if (len < 94)
10764           goto corrupt_file;
10765
10766         /* read table */
10767         start = QT_UINT32 (stsd_entry_data + offset + 70);
10768         palette_count = QT_UINT16 (stsd_entry_data + offset + 74);
10769         end = QT_UINT16 (stsd_entry_data + offset + 76);
10770
10771         GST_LOG_OBJECT (qtdemux, "start %d, end %d, palette_count %d",
10772             start, end, palette_count);
10773
10774         if (end > 255)
10775           end = 255;
10776         if (start > end)
10777           start = end;
10778
10779         if (len < 94 + (end - start) * 8)
10780           goto corrupt_file;
10781
10782         /* palette is always the same size */
10783         palette_data = g_malloc0 (256 * 4);
10784         palette_size = 256 * 4;
10785
10786         for (j = 0, i = start; i <= end; j++, i++) {
10787           guint32 a, r, g, b;
10788
10789           a = QT_UINT16 (stsd_entry_data + offset + 78 + (j * 8));
10790           r = QT_UINT16 (stsd_entry_data + offset + 80 + (j * 8));
10791           g = QT_UINT16 (stsd_entry_data + offset + 82 + (j * 8));
10792           b = QT_UINT16 (stsd_entry_data + offset + 84 + (j * 8));
10793
10794           palette_data[i] = ((a & 0xff00) << 16) | ((r & 0xff00) << 8) |
10795               (g & 0xff00) | (b >> 8);
10796         }
10797       }
10798
10799       if (entry->caps)
10800         gst_caps_unref (entry->caps);
10801
10802       entry->caps =
10803           qtdemux_video_caps (qtdemux, stream, entry, fourcc, stsd_entry_data,
10804           &codec);
10805       if (G_UNLIKELY (!entry->caps)) {
10806         g_free (palette_data);
10807         goto unknown_stream;
10808       }
10809
10810       if (codec) {
10811         gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
10812             GST_TAG_VIDEO_CODEC, codec, NULL);
10813         g_free (codec);
10814         codec = NULL;
10815       }
10816
10817       if (palette_data) {
10818         GstStructure *s;
10819
10820         if (entry->rgb8_palette)
10821           gst_memory_unref (entry->rgb8_palette);
10822         entry->rgb8_palette = gst_memory_new_wrapped (GST_MEMORY_FLAG_READONLY,
10823             palette_data, palette_size, 0, palette_size, palette_data, g_free);
10824
10825         s = gst_caps_get_structure (entry->caps, 0);
10826
10827         /* non-raw video has a palette_data property. raw video has the palette as
10828          * an extra plane that we append to the output buffers before we push
10829          * them*/
10830         if (!gst_structure_has_name (s, "video/x-raw")) {
10831           GstBuffer *palette;
10832
10833           palette = gst_buffer_new ();
10834           gst_buffer_append_memory (palette, entry->rgb8_palette);
10835           entry->rgb8_palette = NULL;
10836
10837           gst_caps_set_simple (entry->caps, "palette_data",
10838               GST_TYPE_BUFFER, palette, NULL);
10839           gst_buffer_unref (palette);
10840         }
10841       } else if (palette_count != 0) {
10842         GST_ELEMENT_WARNING (qtdemux, STREAM, NOT_IMPLEMENTED,
10843             (NULL), ("Unsupported palette depth %d", depth));
10844       }
10845
10846       GST_LOG_OBJECT (qtdemux, "frame count:   %u",
10847           QT_UINT16 (stsd_entry_data + offset + 32));
10848
10849       esds = NULL;
10850       pasp = NULL;
10851       colr = NULL;
10852       fiel = NULL;
10853       /* pick 'the' stsd child */
10854       mp4v = qtdemux_tree_get_child_by_index (stsd, stsd_index);
10855       if (!stream->protected) {
10856         if (QTDEMUX_TREE_NODE_FOURCC (mp4v) != fourcc) {
10857           mp4v = NULL;
10858         }
10859       } else {
10860         if (QTDEMUX_TREE_NODE_FOURCC (mp4v) != FOURCC_encv) {
10861           mp4v = NULL;
10862         }
10863       }
10864
10865       if (mp4v) {
10866         esds = qtdemux_tree_get_child_by_type (mp4v, FOURCC_esds);
10867         pasp = qtdemux_tree_get_child_by_type (mp4v, FOURCC_pasp);
10868         colr = qtdemux_tree_get_child_by_type (mp4v, FOURCC_colr);
10869         fiel = qtdemux_tree_get_child_by_type (mp4v, FOURCC_fiel);
10870       }
10871
10872       if (pasp) {
10873         const guint8 *pasp_data = (const guint8 *) pasp->data;
10874         gint len = QT_UINT32 (pasp_data);
10875
10876         if (len == 16) {
10877           CUR_STREAM (stream)->par_w = QT_UINT32 (pasp_data + 8);
10878           CUR_STREAM (stream)->par_h = QT_UINT32 (pasp_data + 12);
10879         } else {
10880           CUR_STREAM (stream)->par_w = 0;
10881           CUR_STREAM (stream)->par_h = 0;
10882         }
10883       } else {
10884         CUR_STREAM (stream)->par_w = 0;
10885         CUR_STREAM (stream)->par_h = 0;
10886       }
10887
10888       if (fiel) {
10889         const guint8 *fiel_data = (const guint8 *) fiel->data;
10890         gint len = QT_UINT32 (fiel_data);
10891
10892         if (len == 10) {
10893           CUR_STREAM (stream)->interlace_mode = GST_READ_UINT8 (fiel_data + 8);
10894           CUR_STREAM (stream)->field_order = GST_READ_UINT8 (fiel_data + 9);
10895         }
10896       }
10897
10898       if (colr) {
10899         const guint8 *colr_data = (const guint8 *) colr->data;
10900         gint len = QT_UINT32 (colr_data);
10901
10902         if (len == 19 || len == 18) {
10903           guint32 color_type = GST_READ_UINT32_LE (colr_data + 8);
10904
10905           if (color_type == FOURCC_nclx || color_type == FOURCC_nclc) {
10906             guint16 primaries = GST_READ_UINT16_BE (colr_data + 12);
10907             guint16 transfer_function = GST_READ_UINT16_BE (colr_data + 14);
10908             guint16 matrix = GST_READ_UINT16_BE (colr_data + 16);
10909             gboolean full_range = len == 19 ? colr_data[17] >> 7 : FALSE;
10910
10911             switch (primaries) {
10912               case 1:
10913                 CUR_STREAM (stream)->colorimetry.primaries =
10914                     GST_VIDEO_COLOR_PRIMARIES_BT709;
10915                 break;
10916               case 5:
10917                 CUR_STREAM (stream)->colorimetry.primaries =
10918                     GST_VIDEO_COLOR_PRIMARIES_BT470BG;
10919                 break;
10920               case 6:
10921                 CUR_STREAM (stream)->colorimetry.primaries =
10922                     GST_VIDEO_COLOR_PRIMARIES_SMPTE170M;
10923                 break;
10924               case 9:
10925                 CUR_STREAM (stream)->colorimetry.primaries =
10926                     GST_VIDEO_COLOR_PRIMARIES_BT2020;
10927                 break;
10928               default:
10929                 break;
10930             }
10931
10932             switch (transfer_function) {
10933               case 1:
10934                 CUR_STREAM (stream)->colorimetry.transfer =
10935                     GST_VIDEO_TRANSFER_BT709;
10936                 break;
10937               case 7:
10938                 CUR_STREAM (stream)->colorimetry.transfer =
10939                     GST_VIDEO_TRANSFER_SMPTE240M;
10940                 break;
10941               default:
10942                 break;
10943             }
10944
10945             switch (matrix) {
10946               case 1:
10947                 CUR_STREAM (stream)->colorimetry.matrix =
10948                     GST_VIDEO_COLOR_MATRIX_BT709;
10949                 break;
10950               case 6:
10951                 CUR_STREAM (stream)->colorimetry.matrix =
10952                     GST_VIDEO_COLOR_MATRIX_BT601;
10953                 break;
10954               case 7:
10955                 CUR_STREAM (stream)->colorimetry.matrix =
10956                     GST_VIDEO_COLOR_MATRIX_SMPTE240M;
10957                 break;
10958               case 9:
10959                 CUR_STREAM (stream)->colorimetry.matrix =
10960                     GST_VIDEO_COLOR_MATRIX_BT2020;
10961                 break;
10962               default:
10963                 break;
10964             }
10965
10966             CUR_STREAM (stream)->colorimetry.range =
10967                 full_range ? GST_VIDEO_COLOR_RANGE_0_255 :
10968                 GST_VIDEO_COLOR_RANGE_16_235;
10969           } else {
10970             GST_DEBUG_OBJECT (qtdemux, "Unsupported color type");
10971           }
10972         } else {
10973           GST_WARNING_OBJECT (qtdemux, "Invalid colr atom size");
10974         }
10975       }
10976
10977       if (esds) {
10978         gst_qtdemux_handle_esds (qtdemux, stream, entry, esds,
10979             stream->stream_tags);
10980       } else {
10981         switch (fourcc) {
10982           case FOURCC_H264:
10983           case FOURCC_avc1:
10984           case FOURCC_avc3:
10985           {
10986             gint len = QT_UINT32 (stsd_entry_data) - 0x56;
10987             const guint8 *avc_data = stsd_entry_data + 0x56;
10988
10989             /* find avcC */
10990             while (len >= 0x8) {
10991               gint size;
10992
10993               if (QT_UINT32 (avc_data) <= len)
10994                 size = QT_UINT32 (avc_data) - 0x8;
10995               else
10996                 size = len - 0x8;
10997
10998               if (size < 1)
10999                 /* No real data, so break out */
11000                 break;
11001
11002               switch (QT_FOURCC (avc_data + 0x4)) {
11003                 case FOURCC_avcC:
11004                 {
11005                   /* parse, if found */
11006                   GstBuffer *buf;
11007
11008                   GST_DEBUG_OBJECT (qtdemux, "found avcC codec_data in stsd");
11009
11010                   /* First 4 bytes are the length of the atom, the next 4 bytes
11011                    * are the fourcc, the next 1 byte is the version, and the
11012                    * subsequent bytes are profile_tier_level structure like data. */
11013                   gst_codec_utils_h264_caps_set_level_and_profile (entry->caps,
11014                       avc_data + 8 + 1, size - 1);
11015                   buf = gst_buffer_new_and_alloc (size);
11016                   gst_buffer_fill (buf, 0, avc_data + 0x8, size);
11017                   gst_caps_set_simple (entry->caps,
11018                       "codec_data", GST_TYPE_BUFFER, buf, NULL);
11019                   gst_buffer_unref (buf);
11020
11021                   break;
11022                 }
11023                 case FOURCC_strf:
11024                 {
11025                   GstBuffer *buf;
11026
11027                   GST_DEBUG_OBJECT (qtdemux, "found strf codec_data in stsd");
11028
11029                   /* First 4 bytes are the length of the atom, the next 4 bytes
11030                    * are the fourcc, next 40 bytes are BITMAPINFOHEADER,
11031                    * next 1 byte is the version, and the
11032                    * subsequent bytes are sequence parameter set like data. */
11033
11034                   size -= 40;   /* we'll be skipping BITMAPINFOHEADER */
11035                   if (size > 1) {
11036                     gst_codec_utils_h264_caps_set_level_and_profile
11037                         (entry->caps, avc_data + 8 + 40 + 1, size - 1);
11038
11039                     buf = gst_buffer_new_and_alloc (size);
11040                     gst_buffer_fill (buf, 0, avc_data + 8 + 40, size);
11041                     gst_caps_set_simple (entry->caps,
11042                         "codec_data", GST_TYPE_BUFFER, buf, NULL);
11043                     gst_buffer_unref (buf);
11044                   }
11045                   break;
11046                 }
11047                 case FOURCC_btrt:
11048                 {
11049                   guint avg_bitrate, max_bitrate;
11050
11051                   /* bufferSizeDB, maxBitrate and avgBitrate - 4 bytes each */
11052                   if (size < 12)
11053                     break;
11054
11055                   max_bitrate = QT_UINT32 (avc_data + 0xc);
11056                   avg_bitrate = QT_UINT32 (avc_data + 0x10);
11057
11058                   if (!max_bitrate && !avg_bitrate)
11059                     break;
11060
11061                   /* Some muxers seem to swap the average and maximum bitrates
11062                    * (I'm looking at you, YouTube), so we swap for sanity. */
11063                   if (max_bitrate > 0 && max_bitrate < avg_bitrate) {
11064                     guint temp = avg_bitrate;
11065
11066                     avg_bitrate = max_bitrate;
11067                     max_bitrate = temp;
11068                   }
11069
11070                   if (max_bitrate > 0 && max_bitrate < G_MAXUINT32) {
11071                     gst_tag_list_add (stream->stream_tags,
11072                         GST_TAG_MERGE_REPLACE, GST_TAG_MAXIMUM_BITRATE,
11073                         max_bitrate, NULL);
11074                   }
11075                   if (avg_bitrate > 0 && avg_bitrate < G_MAXUINT32) {
11076                     gst_tag_list_add (stream->stream_tags,
11077                         GST_TAG_MERGE_REPLACE, GST_TAG_BITRATE, avg_bitrate,
11078                         NULL);
11079                   }
11080
11081                   break;
11082                 }
11083
11084                 default:
11085                   break;
11086               }
11087
11088               len -= size + 8;
11089               avc_data += size + 8;
11090             }
11091
11092             break;
11093           }
11094           case FOURCC_H265:
11095           case FOURCC_hvc1:
11096           case FOURCC_hev1:
11097           {
11098             gint len = QT_UINT32 (stsd_entry_data) - 0x56;
11099             const guint8 *hevc_data = stsd_entry_data + 0x56;
11100
11101             /* find hevc */
11102             while (len >= 0x8) {
11103               gint size;
11104
11105               if (QT_UINT32 (hevc_data) <= len)
11106                 size = QT_UINT32 (hevc_data) - 0x8;
11107               else
11108                 size = len - 0x8;
11109
11110               if (size < 1)
11111                 /* No real data, so break out */
11112                 break;
11113
11114               switch (QT_FOURCC (hevc_data + 0x4)) {
11115                 case FOURCC_hvcC:
11116                 {
11117                   /* parse, if found */
11118                   GstBuffer *buf;
11119
11120                   GST_DEBUG_OBJECT (qtdemux, "found hvcC codec_data in stsd");
11121
11122                   /* First 4 bytes are the length of the atom, the next 4 bytes
11123                    * are the fourcc, the next 1 byte is the version, and the
11124                    * subsequent bytes are sequence parameter set like data. */
11125                   gst_codec_utils_h265_caps_set_level_tier_and_profile
11126                       (entry->caps, hevc_data + 8 + 1, size - 1);
11127
11128                   buf = gst_buffer_new_and_alloc (size);
11129                   gst_buffer_fill (buf, 0, hevc_data + 0x8, size);
11130                   gst_caps_set_simple (entry->caps,
11131                       "codec_data", GST_TYPE_BUFFER, buf, NULL);
11132                   gst_buffer_unref (buf);
11133                   break;
11134                 }
11135                 default:
11136                   break;
11137               }
11138               len -= size + 8;
11139               hevc_data += size + 8;
11140             }
11141             break;
11142           }
11143           case FOURCC_mp4v:
11144           case FOURCC_MP4V:
11145           case FOURCC_fmp4:
11146           case FOURCC_FMP4:
11147           case FOURCC_xvid:
11148           case FOURCC_XVID:
11149           {
11150             GNode *glbl;
11151
11152             GST_DEBUG_OBJECT (qtdemux, "found %" GST_FOURCC_FORMAT,
11153                 GST_FOURCC_ARGS (fourcc));
11154
11155             /* codec data might be in glbl extension atom */
11156             glbl = mp4v ?
11157                 qtdemux_tree_get_child_by_type (mp4v, FOURCC_glbl) : NULL;
11158             if (glbl) {
11159               guint8 *data;
11160               GstBuffer *buf;
11161               gint len;
11162
11163               GST_DEBUG_OBJECT (qtdemux, "found glbl data in stsd");
11164               data = glbl->data;
11165               len = QT_UINT32 (data);
11166               if (len > 0x8) {
11167                 len -= 0x8;
11168                 buf = gst_buffer_new_and_alloc (len);
11169                 gst_buffer_fill (buf, 0, data + 8, len);
11170                 gst_caps_set_simple (entry->caps,
11171                     "codec_data", GST_TYPE_BUFFER, buf, NULL);
11172                 gst_buffer_unref (buf);
11173               }
11174             }
11175             break;
11176           }
11177           case FOURCC_mjp2:
11178           {
11179             /* see annex I of the jpeg2000 spec */
11180             GNode *jp2h, *ihdr, *colr, *mjp2, *field, *prefix, *cmap, *cdef;
11181             const guint8 *data;
11182             const gchar *colorspace = NULL;
11183             gint ncomp = 0;
11184             guint32 ncomp_map = 0;
11185             gint32 *comp_map = NULL;
11186             guint32 nchan_def = 0;
11187             gint32 *chan_def = NULL;
11188
11189             GST_DEBUG_OBJECT (qtdemux, "found mjp2");
11190             /* some required atoms */
11191             mjp2 = qtdemux_tree_get_child_by_index (stsd, stsd_index);
11192             if (!mjp2)
11193               break;
11194             jp2h = qtdemux_tree_get_child_by_type (mjp2, FOURCC_jp2h);
11195             if (!jp2h)
11196               break;
11197
11198             /* number of components; redundant with info in codestream, but useful
11199                to a muxer */
11200             ihdr = qtdemux_tree_get_child_by_type (jp2h, FOURCC_ihdr);
11201             if (!ihdr || QT_UINT32 (ihdr->data) != 22)
11202               break;
11203             ncomp = QT_UINT16 (((guint8 *) ihdr->data) + 16);
11204
11205             colr = qtdemux_tree_get_child_by_type (jp2h, FOURCC_colr);
11206             if (!colr)
11207               break;
11208             GST_DEBUG_OBJECT (qtdemux, "found colr");
11209             /* extract colour space info */
11210             if (QT_UINT8 ((guint8 *) colr->data + 8) == 1) {
11211               switch (QT_UINT32 ((guint8 *) colr->data + 11)) {
11212                 case 16:
11213                   colorspace = "sRGB";
11214                   break;
11215                 case 17:
11216                   colorspace = "GRAY";
11217                   break;
11218                 case 18:
11219                   colorspace = "sYUV";
11220                   break;
11221                 default:
11222                   colorspace = NULL;
11223                   break;
11224               }
11225             }
11226             if (!colorspace)
11227               /* colr is required, and only values 16, 17, and 18 are specified,
11228                  so error if we have no colorspace */
11229               break;
11230
11231             /* extract component mapping */
11232             cmap = qtdemux_tree_get_child_by_type (jp2h, FOURCC_cmap);
11233             if (cmap) {
11234               guint32 cmap_len = 0;
11235               int i;
11236               cmap_len = QT_UINT32 (cmap->data);
11237               if (cmap_len >= 8) {
11238                 /* normal box, subtract off header */
11239                 cmap_len -= 8;
11240                 /* cmap: { u16 cmp; u8 mtyp; u8 pcol; }* */
11241                 if (cmap_len % 4 == 0) {
11242                   ncomp_map = (cmap_len / 4);
11243                   comp_map = g_new0 (gint32, ncomp_map);
11244                   for (i = 0; i < ncomp_map; i++) {
11245                     guint16 cmp;
11246                     guint8 mtyp, pcol;
11247                     cmp = QT_UINT16 (((guint8 *) cmap->data) + 8 + i * 4);
11248                     mtyp = QT_UINT8 (((guint8 *) cmap->data) + 8 + i * 4 + 2);
11249                     pcol = QT_UINT8 (((guint8 *) cmap->data) + 8 + i * 4 + 3);
11250                     comp_map[i] = (mtyp << 24) | (pcol << 16) | cmp;
11251                   }
11252                 }
11253               }
11254             }
11255             /* extract channel definitions */
11256             cdef = qtdemux_tree_get_child_by_type (jp2h, FOURCC_cdef);
11257             if (cdef) {
11258               guint32 cdef_len = 0;
11259               int i;
11260               cdef_len = QT_UINT32 (cdef->data);
11261               if (cdef_len >= 10) {
11262                 /* normal box, subtract off header and len */
11263                 cdef_len -= 10;
11264                 /* cdef: u16 n; { u16 cn; u16 typ; u16 asoc; }* */
11265                 if (cdef_len % 6 == 0) {
11266                   nchan_def = (cdef_len / 6);
11267                   chan_def = g_new0 (gint32, nchan_def);
11268                   for (i = 0; i < nchan_def; i++)
11269                     chan_def[i] = -1;
11270                   for (i = 0; i < nchan_def; i++) {
11271                     guint16 cn, typ, asoc;
11272                     cn = QT_UINT16 (((guint8 *) cdef->data) + 10 + i * 6);
11273                     typ = QT_UINT16 (((guint8 *) cdef->data) + 10 + i * 6 + 2);
11274                     asoc = QT_UINT16 (((guint8 *) cdef->data) + 10 + i * 6 + 4);
11275                     if (cn < nchan_def) {
11276                       switch (typ) {
11277                         case 0:
11278                           chan_def[cn] = asoc;
11279                           break;
11280                         case 1:
11281                           chan_def[cn] = 0;     /* alpha */
11282                           break;
11283                         default:
11284                           chan_def[cn] = -typ;
11285                       }
11286                     }
11287                   }
11288                 }
11289               }
11290             }
11291
11292             gst_caps_set_simple (entry->caps,
11293                 "num-components", G_TYPE_INT, ncomp, NULL);
11294             gst_caps_set_simple (entry->caps,
11295                 "colorspace", G_TYPE_STRING, colorspace, NULL);
11296
11297             if (comp_map) {
11298               GValue arr = { 0, };
11299               GValue elt = { 0, };
11300               int i;
11301               g_value_init (&arr, GST_TYPE_ARRAY);
11302               g_value_init (&elt, G_TYPE_INT);
11303               for (i = 0; i < ncomp_map; i++) {
11304                 g_value_set_int (&elt, comp_map[i]);
11305                 gst_value_array_append_value (&arr, &elt);
11306               }
11307               gst_structure_set_value (gst_caps_get_structure (entry->caps, 0),
11308                   "component-map", &arr);
11309               g_value_unset (&elt);
11310               g_value_unset (&arr);
11311               g_free (comp_map);
11312             }
11313
11314             if (chan_def) {
11315               GValue arr = { 0, };
11316               GValue elt = { 0, };
11317               int i;
11318               g_value_init (&arr, GST_TYPE_ARRAY);
11319               g_value_init (&elt, G_TYPE_INT);
11320               for (i = 0; i < nchan_def; i++) {
11321                 g_value_set_int (&elt, chan_def[i]);
11322                 gst_value_array_append_value (&arr, &elt);
11323               }
11324               gst_structure_set_value (gst_caps_get_structure (entry->caps, 0),
11325                   "channel-definitions", &arr);
11326               g_value_unset (&elt);
11327               g_value_unset (&arr);
11328               g_free (chan_def);
11329             }
11330
11331             /* some optional atoms */
11332             field = qtdemux_tree_get_child_by_type (mjp2, FOURCC_fiel);
11333             prefix = qtdemux_tree_get_child_by_type (mjp2, FOURCC_jp2x);
11334
11335             /* indicate possible fields in caps */
11336             if (field) {
11337               data = (guint8 *) field->data + 8;
11338               if (*data != 1)
11339                 gst_caps_set_simple (entry->caps, "fields", G_TYPE_INT,
11340                     (gint) * data, NULL);
11341             }
11342             /* add codec_data if provided */
11343             if (prefix) {
11344               GstBuffer *buf;
11345               gint len;
11346
11347               GST_DEBUG_OBJECT (qtdemux, "found prefix data in stsd");
11348               data = prefix->data;
11349               len = QT_UINT32 (data);
11350               if (len > 0x8) {
11351                 len -= 0x8;
11352                 buf = gst_buffer_new_and_alloc (len);
11353                 gst_buffer_fill (buf, 0, data + 8, len);
11354                 gst_caps_set_simple (entry->caps,
11355                     "codec_data", GST_TYPE_BUFFER, buf, NULL);
11356                 gst_buffer_unref (buf);
11357               }
11358             }
11359             break;
11360           }
11361           case FOURCC_SVQ3:
11362           case FOURCC_VP31:
11363           {
11364             GstBuffer *buf;
11365             GstBuffer *seqh = NULL;
11366             const guint8 *gamma_data = NULL;
11367             gint len = QT_UINT32 (stsd_data);   /* FIXME review - why put the whole stsd in codec data? */
11368
11369             qtdemux_parse_svq3_stsd_data (qtdemux, stsd_entry_data, &gamma_data,
11370                 &seqh);
11371             if (gamma_data) {
11372               gst_caps_set_simple (entry->caps, "applied-gamma", G_TYPE_DOUBLE,
11373                   QT_FP32 (gamma_data), NULL);
11374             }
11375             if (seqh) {
11376               /* sorry for the bad name, but we don't know what this is, other
11377                * than its own fourcc */
11378               gst_caps_set_simple (entry->caps, "seqh", GST_TYPE_BUFFER, seqh,
11379                   NULL);
11380               gst_buffer_unref (seqh);
11381             }
11382
11383             GST_DEBUG_OBJECT (qtdemux, "found codec_data in stsd");
11384             buf = gst_buffer_new_and_alloc (len);
11385             gst_buffer_fill (buf, 0, stsd_data, len);
11386             gst_caps_set_simple (entry->caps,
11387                 "codec_data", GST_TYPE_BUFFER, buf, NULL);
11388             gst_buffer_unref (buf);
11389             break;
11390           }
11391           case FOURCC_jpeg:
11392           {
11393             /* https://developer.apple.com/standards/qtff-2001.pdf,
11394              * page 92, "Video Sample Description", under table 3.1 */
11395             GstByteReader br;
11396
11397             const gint compressor_offset =
11398                 16 + 4 + 4 * 3 + 2 * 2 + 2 * 4 + 4 + 2;
11399             const gint min_size = compressor_offset + 32 + 2 + 2;
11400             GNode *jpeg;
11401             guint32 len;
11402             guint16 color_table_id = 0;
11403             gboolean ok;
11404
11405             GST_DEBUG_OBJECT (qtdemux, "found jpeg");
11406
11407             /* recover information on interlaced/progressive */
11408             jpeg = qtdemux_tree_get_child_by_type (stsd, FOURCC_jpeg);
11409             if (!jpeg)
11410               break;
11411
11412             len = QT_UINT32 (jpeg->data);
11413             GST_DEBUG_OBJECT (qtdemux, "Found jpeg: len %u, need %d", len,
11414                 min_size);
11415             if (len >= min_size) {
11416               gst_byte_reader_init (&br, jpeg->data, len);
11417
11418               gst_byte_reader_skip (&br, compressor_offset + 32 + 2);
11419               gst_byte_reader_get_uint16_le (&br, &color_table_id);
11420               if (color_table_id != 0) {
11421                 /* the spec says there can be concatenated chunks in the data, and we want
11422                  * to find one called field. Walk through them. */
11423                 gint offset = min_size;
11424                 while (offset + 8 < len) {
11425                   guint32 size = 0, tag;
11426                   ok = gst_byte_reader_get_uint32_le (&br, &size);
11427                   ok &= gst_byte_reader_get_uint32_le (&br, &tag);
11428                   if (!ok || size < 8) {
11429                     GST_WARNING_OBJECT (qtdemux,
11430                         "Failed to walk optional chunk list");
11431                     break;
11432                   }
11433                   GST_DEBUG_OBJECT (qtdemux,
11434                       "Found optional %4.4s chunk, size %u",
11435                       (const char *) &tag, size);
11436                   if (tag == FOURCC_fiel) {
11437                     guint8 n_fields = 0, ordering = 0;
11438                     gst_byte_reader_get_uint8 (&br, &n_fields);
11439                     gst_byte_reader_get_uint8 (&br, &ordering);
11440                     if (n_fields == 1 || n_fields == 2) {
11441                       GST_DEBUG_OBJECT (qtdemux,
11442                           "Found fiel tag with %u fields, ordering %u",
11443                           n_fields, ordering);
11444                       if (n_fields == 2)
11445                         gst_caps_set_simple (CUR_STREAM (stream)->caps,
11446                             "interlace-mode", G_TYPE_STRING, "interleaved",
11447                             NULL);
11448                     } else {
11449                       GST_WARNING_OBJECT (qtdemux,
11450                           "Found fiel tag with invalid fields (%u)", n_fields);
11451                     }
11452                   }
11453                   offset += size;
11454                 }
11455               } else {
11456                 GST_DEBUG_OBJECT (qtdemux,
11457                     "Color table ID is 0, not trying to get interlacedness");
11458               }
11459             } else {
11460               GST_WARNING_OBJECT (qtdemux,
11461                   "Length of jpeg chunk is too small, not trying to get interlacedness");
11462             }
11463
11464             break;
11465           }
11466           case FOURCC_rle_:
11467           case FOURCC_WRLE:
11468           {
11469             gst_caps_set_simple (entry->caps,
11470                 "depth", G_TYPE_INT, QT_UINT16 (stsd_entry_data + offset + 66),
11471                 NULL);
11472             break;
11473           }
11474           case FOURCC_XiTh:
11475           {
11476             GNode *xith, *xdxt;
11477
11478             GST_DEBUG_OBJECT (qtdemux, "found XiTh");
11479             xith = qtdemux_tree_get_child_by_index (stsd, stsd_index);
11480             if (!xith)
11481               break;
11482
11483             xdxt = qtdemux_tree_get_child_by_type (xith, FOURCC_XdxT);
11484             if (!xdxt)
11485               break;
11486
11487             GST_DEBUG_OBJECT (qtdemux, "found XdxT node");
11488             /* collect the headers and store them in a stream list so that we can
11489              * send them out first */
11490             qtdemux_parse_theora_extension (qtdemux, stream, xdxt);
11491             break;
11492           }
11493           case FOURCC_ovc1:
11494           {
11495             GNode *ovc1;
11496             guint8 *ovc1_data;
11497             guint ovc1_len;
11498             GstBuffer *buf;
11499
11500             GST_DEBUG_OBJECT (qtdemux, "parse ovc1 header");
11501             ovc1 = qtdemux_tree_get_child_by_index (stsd, stsd_index);
11502             if (!ovc1)
11503               break;
11504             ovc1_data = ovc1->data;
11505             ovc1_len = QT_UINT32 (ovc1_data);
11506             if (ovc1_len <= 198) {
11507               GST_WARNING_OBJECT (qtdemux, "Too small ovc1 header, skipping");
11508               break;
11509             }
11510             buf = gst_buffer_new_and_alloc (ovc1_len - 198);
11511             gst_buffer_fill (buf, 0, ovc1_data + 198, ovc1_len - 198);
11512             gst_caps_set_simple (entry->caps,
11513                 "codec_data", GST_TYPE_BUFFER, buf, NULL);
11514             gst_buffer_unref (buf);
11515             break;
11516           }
11517           case FOURCC_vc_1:
11518           {
11519             gint len = QT_UINT32 (stsd_entry_data) - 0x56;
11520             const guint8 *vc1_data = stsd_entry_data + 0x56;
11521
11522             /* find dvc1 */
11523             while (len >= 8) {
11524               gint size;
11525
11526               if (QT_UINT32 (vc1_data) <= len)
11527                 size = QT_UINT32 (vc1_data) - 8;
11528               else
11529                 size = len - 8;
11530
11531               if (size < 1)
11532                 /* No real data, so break out */
11533                 break;
11534
11535               switch (QT_FOURCC (vc1_data + 0x4)) {
11536                 case GST_MAKE_FOURCC ('d', 'v', 'c', '1'):
11537                 {
11538                   GstBuffer *buf;
11539
11540                   GST_DEBUG_OBJECT (qtdemux, "found dvc1 codec_data in stsd");
11541                   buf = gst_buffer_new_and_alloc (size);
11542                   gst_buffer_fill (buf, 0, vc1_data + 8, size);
11543                   gst_caps_set_simple (entry->caps,
11544                       "codec_data", GST_TYPE_BUFFER, buf, NULL);
11545                   gst_buffer_unref (buf);
11546                   break;
11547                 }
11548                 default:
11549                   break;
11550               }
11551               len -= size + 8;
11552               vc1_data += size + 8;
11553             }
11554             break;
11555           }
11556           case FOURCC_av01:
11557           {
11558             gint len = QT_UINT32 (stsd_entry_data) - 0x56;
11559             const guint8 *av1_data = stsd_entry_data + 0x56;
11560
11561             /* find av1C */
11562             while (len >= 0x8) {
11563               gint size;
11564
11565               if (QT_UINT32 (av1_data) <= len)
11566                 size = QT_UINT32 (av1_data) - 0x8;
11567               else
11568                 size = len - 0x8;
11569
11570               if (size < 1)
11571                 /* No real data, so break out */
11572                 break;
11573
11574               switch (QT_FOURCC (av1_data + 0x4)) {
11575                 case FOURCC_av1C:
11576                 {
11577                   /* parse, if found */
11578                   GstBuffer *buf;
11579                   guint8 pres_delay_field;
11580
11581                   GST_DEBUG_OBJECT (qtdemux,
11582                       "found av1C codec_data in stsd of size %d", size);
11583
11584                   /* not enough data, just ignore and hope for the best */
11585                   if (size < 5)
11586                     break;
11587
11588                   /* Content is:
11589                    * 4 bytes: atom length
11590                    * 4 bytes: fourcc
11591                    * 1 byte: version
11592                    * 3 bytes: flags
11593                    * 3 bits: reserved
11594                    * 1 bits:  initial_presentation_delay_present
11595                    * 4 bits: initial_presentation_delay (if present else reserved
11596                    * rest: OBUs.
11597                    */
11598
11599                   if (av1_data[9] != 0) {
11600                     GST_WARNING ("Unknown version %d of av1C box", av1_data[9]);
11601                     break;
11602                   }
11603
11604                   /* We skip initial_presentation_delay* for now */
11605                   pres_delay_field = *(av1_data + 12);
11606                   if (pres_delay_field & (1 << 5)) {
11607                     gst_caps_set_simple (entry->caps,
11608                         "presentation-delay", G_TYPE_INT,
11609                         (gint) (pres_delay_field & 0x0F) + 1, NULL);
11610                   }
11611                   if (size > 5) {
11612                     buf = gst_buffer_new_and_alloc (size - 5);
11613                     GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_HEADER);
11614                     gst_buffer_fill (buf, 0, av1_data + 13, size - 5);
11615                     gst_caps_set_simple (entry->caps,
11616                         "codec_data", GST_TYPE_BUFFER, buf, NULL);
11617                     gst_buffer_unref (buf);
11618                   }
11619                   break;
11620                 }
11621                 default:
11622                   break;
11623               }
11624
11625               len -= size + 8;
11626               av1_data += size + 8;
11627             }
11628
11629             break;
11630           }
11631           default:
11632             break;
11633         }
11634       }
11635
11636       GST_INFO_OBJECT (qtdemux,
11637           "type %" GST_FOURCC_FORMAT " caps %" GST_PTR_FORMAT,
11638           GST_FOURCC_ARGS (fourcc), entry->caps);
11639
11640     } else if (stream->subtype == FOURCC_soun) {
11641       GNode *wave;
11642       int version, samplesize;
11643       guint16 compression_id;
11644       gboolean amrwb = FALSE;
11645
11646       offset = 16;
11647       /* sample description entry (16) + sound sample description v0 (20) */
11648       if (len < 36)
11649         goto corrupt_file;
11650
11651       version = QT_UINT32 (stsd_entry_data + offset);
11652       entry->n_channels = QT_UINT16 (stsd_entry_data + offset + 8);
11653       samplesize = QT_UINT16 (stsd_entry_data + offset + 10);
11654       compression_id = QT_UINT16 (stsd_entry_data + offset + 12);
11655       entry->rate = QT_FP32 (stsd_entry_data + offset + 16);
11656
11657       GST_LOG_OBJECT (qtdemux, "version/rev:      %08x", version);
11658       GST_LOG_OBJECT (qtdemux, "vendor:           %08x",
11659           QT_UINT32 (stsd_entry_data + offset + 4));
11660       GST_LOG_OBJECT (qtdemux, "n_channels:       %d", entry->n_channels);
11661       GST_LOG_OBJECT (qtdemux, "sample_size:      %d", samplesize);
11662       GST_LOG_OBJECT (qtdemux, "compression_id:   %d", compression_id);
11663       GST_LOG_OBJECT (qtdemux, "packet size:      %d",
11664           QT_UINT16 (stsd_entry_data + offset + 14));
11665       GST_LOG_OBJECT (qtdemux, "sample rate:      %g", entry->rate);
11666
11667       if (compression_id == 0xfffe)
11668         entry->sampled = TRUE;
11669
11670       /* first assume uncompressed audio */
11671       entry->bytes_per_sample = samplesize / 8;
11672       entry->samples_per_frame = entry->n_channels;
11673       entry->bytes_per_frame = entry->n_channels * entry->bytes_per_sample;
11674       entry->samples_per_packet = entry->samples_per_frame;
11675       entry->bytes_per_packet = entry->bytes_per_sample;
11676
11677       offset = 36;
11678       switch (fourcc) {
11679           /* Yes, these have to be hard-coded */
11680         case FOURCC_MAC6:
11681         {
11682           entry->samples_per_packet = 6;
11683           entry->bytes_per_packet = 1;
11684           entry->bytes_per_frame = 1 * entry->n_channels;
11685           entry->bytes_per_sample = 1;
11686           entry->samples_per_frame = 6 * entry->n_channels;
11687           break;
11688         }
11689         case FOURCC_MAC3:
11690         {
11691           entry->samples_per_packet = 3;
11692           entry->bytes_per_packet = 1;
11693           entry->bytes_per_frame = 1 * entry->n_channels;
11694           entry->bytes_per_sample = 1;
11695           entry->samples_per_frame = 3 * entry->n_channels;
11696           break;
11697         }
11698         case FOURCC_ima4:
11699         {
11700           entry->samples_per_packet = 64;
11701           entry->bytes_per_packet = 34;
11702           entry->bytes_per_frame = 34 * entry->n_channels;
11703           entry->bytes_per_sample = 2;
11704           entry->samples_per_frame = 64 * entry->n_channels;
11705           break;
11706         }
11707         case FOURCC_ulaw:
11708         case FOURCC_alaw:
11709         {
11710           entry->samples_per_packet = 1;
11711           entry->bytes_per_packet = 1;
11712           entry->bytes_per_frame = 1 * entry->n_channels;
11713           entry->bytes_per_sample = 1;
11714           entry->samples_per_frame = 1 * entry->n_channels;
11715           break;
11716         }
11717         case FOURCC_agsm:
11718         {
11719           entry->samples_per_packet = 160;
11720           entry->bytes_per_packet = 33;
11721           entry->bytes_per_frame = 33 * entry->n_channels;
11722           entry->bytes_per_sample = 2;
11723           entry->samples_per_frame = 160 * entry->n_channels;
11724           break;
11725         }
11726         default:
11727           break;
11728       }
11729
11730       if (version == 0x00010000) {
11731         /* sample description entry (16) + sound sample description v1 (20+16) */
11732         if (len < 52)
11733           goto corrupt_file;
11734
11735         switch (fourcc) {
11736           case FOURCC_twos:
11737           case FOURCC_sowt:
11738           case FOURCC_raw_:
11739           case FOURCC_lpcm:
11740             break;
11741           default:
11742           {
11743             /* only parse extra decoding config for non-pcm audio */
11744             entry->samples_per_packet = QT_UINT32 (stsd_entry_data + offset);
11745             entry->bytes_per_packet = QT_UINT32 (stsd_entry_data + offset + 4);
11746             entry->bytes_per_frame = QT_UINT32 (stsd_entry_data + offset + 8);
11747             entry->bytes_per_sample = QT_UINT32 (stsd_entry_data + offset + 12);
11748
11749             GST_LOG_OBJECT (qtdemux, "samples/packet:   %d",
11750                 entry->samples_per_packet);
11751             GST_LOG_OBJECT (qtdemux, "bytes/packet:     %d",
11752                 entry->bytes_per_packet);
11753             GST_LOG_OBJECT (qtdemux, "bytes/frame:      %d",
11754                 entry->bytes_per_frame);
11755             GST_LOG_OBJECT (qtdemux, "bytes/sample:     %d",
11756                 entry->bytes_per_sample);
11757
11758             if (!entry->sampled && entry->bytes_per_packet) {
11759               entry->samples_per_frame = (entry->bytes_per_frame /
11760                   entry->bytes_per_packet) * entry->samples_per_packet;
11761               GST_LOG_OBJECT (qtdemux, "samples/frame:    %d",
11762                   entry->samples_per_frame);
11763             }
11764             break;
11765           }
11766         }
11767       } else if (version == 0x00020000) {
11768         union
11769         {
11770           gdouble fp;
11771           guint64 val;
11772         } qtfp;
11773
11774         /* sample description entry (16) + sound sample description v2 (56) */
11775         if (len < 72)
11776           goto corrupt_file;
11777
11778         qtfp.val = QT_UINT64 (stsd_entry_data + offset + 4);
11779         entry->rate = qtfp.fp;
11780         entry->n_channels = QT_UINT32 (stsd_entry_data + offset + 12);
11781
11782         GST_LOG_OBJECT (qtdemux, "Sound sample description Version 2");
11783         GST_LOG_OBJECT (qtdemux, "sample rate:        %g", entry->rate);
11784         GST_LOG_OBJECT (qtdemux, "n_channels:         %d", entry->n_channels);
11785         GST_LOG_OBJECT (qtdemux, "bits/channel:       %d",
11786             QT_UINT32 (stsd_entry_data + offset + 20));
11787         GST_LOG_OBJECT (qtdemux, "format flags:       %X",
11788             QT_UINT32 (stsd_entry_data + offset + 24));
11789         GST_LOG_OBJECT (qtdemux, "bytes/packet:       %d",
11790             QT_UINT32 (stsd_entry_data + offset + 28));
11791         GST_LOG_OBJECT (qtdemux, "LPCM frames/packet: %d",
11792             QT_UINT32 (stsd_entry_data + offset + 32));
11793       } else if (version != 0x00000) {
11794         GST_WARNING_OBJECT (qtdemux, "unknown audio STSD version %08x",
11795             version);
11796       }
11797
11798       if (entry->caps)
11799         gst_caps_unref (entry->caps);
11800
11801       entry->caps = qtdemux_audio_caps (qtdemux, stream, entry, fourcc,
11802           stsd_entry_data + 32, len - 16, &codec);
11803
11804       switch (fourcc) {
11805         case FOURCC_in24:
11806         {
11807           GNode *enda;
11808           GNode *in24;
11809
11810           in24 = qtdemux_tree_get_child_by_type (stsd, FOURCC_in24);
11811
11812           enda = qtdemux_tree_get_child_by_type (in24, FOURCC_enda);
11813           if (!enda) {
11814             wave = qtdemux_tree_get_child_by_type (in24, FOURCC_wave);
11815             if (wave)
11816               enda = qtdemux_tree_get_child_by_type (wave, FOURCC_enda);
11817           }
11818           if (enda) {
11819             int enda_value = QT_UINT16 ((guint8 *) enda->data + 8);
11820             gst_caps_set_simple (entry->caps,
11821                 "format", G_TYPE_STRING, (enda_value) ? "S24LE" : "S24BE",
11822                 NULL);
11823           }
11824           break;
11825         }
11826         case FOURCC_owma:
11827         {
11828           const guint8 *owma_data;
11829           const gchar *codec_name = NULL;
11830           guint owma_len;
11831           GstBuffer *buf;
11832           gint version = 1;
11833           /* from http://msdn.microsoft.com/en-us/library/dd757720(VS.85).aspx */
11834           /* FIXME this should also be gst_riff_strf_auds,
11835            * but the latter one is actually missing bits-per-sample :( */
11836           typedef struct
11837           {
11838             gint16 wFormatTag;
11839             gint16 nChannels;
11840             gint32 nSamplesPerSec;
11841             gint32 nAvgBytesPerSec;
11842             gint16 nBlockAlign;
11843             gint16 wBitsPerSample;
11844             gint16 cbSize;
11845           } WAVEFORMATEX;
11846           WAVEFORMATEX *wfex;
11847
11848           GST_DEBUG_OBJECT (qtdemux, "parse owma");
11849           owma_data = stsd_entry_data;
11850           owma_len = QT_UINT32 (owma_data);
11851           if (owma_len <= 54) {
11852             GST_WARNING_OBJECT (qtdemux, "Too small owma header, skipping");
11853             break;
11854           }
11855           wfex = (WAVEFORMATEX *) (owma_data + 36);
11856           buf = gst_buffer_new_and_alloc (owma_len - 54);
11857           gst_buffer_fill (buf, 0, owma_data + 54, owma_len - 54);
11858           if (wfex->wFormatTag == 0x0161) {
11859             codec_name = "Windows Media Audio";
11860             version = 2;
11861           } else if (wfex->wFormatTag == 0x0162) {
11862             codec_name = "Windows Media Audio 9 Pro";
11863             version = 3;
11864           } else if (wfex->wFormatTag == 0x0163) {
11865             codec_name = "Windows Media Audio 9 Lossless";
11866             /* is that correct? gstffmpegcodecmap.c is missing it, but
11867              * fluendo codec seems to support it */
11868             version = 4;
11869           }
11870
11871           gst_caps_set_simple (entry->caps,
11872               "codec_data", GST_TYPE_BUFFER, buf,
11873               "wmaversion", G_TYPE_INT, version,
11874               "block_align", G_TYPE_INT,
11875               GST_READ_UINT16_LE (&wfex->nBlockAlign), "bitrate", G_TYPE_INT,
11876               GST_READ_UINT32_LE (&wfex->nAvgBytesPerSec), "width", G_TYPE_INT,
11877               GST_READ_UINT16_LE (&wfex->wBitsPerSample), "depth", G_TYPE_INT,
11878               GST_READ_UINT16_LE (&wfex->wBitsPerSample), NULL);
11879           gst_buffer_unref (buf);
11880
11881           if (codec_name) {
11882             g_free (codec);
11883             codec = g_strdup (codec_name);
11884           }
11885           break;
11886         }
11887         case FOURCC_wma_:
11888         {
11889           gint len = QT_UINT32 (stsd_entry_data) - offset;
11890           const guint8 *wfex_data = stsd_entry_data + offset;
11891           const gchar *codec_name = NULL;
11892           gint version = 1;
11893           /* from http://msdn.microsoft.com/en-us/library/dd757720(VS.85).aspx */
11894           /* FIXME this should also be gst_riff_strf_auds,
11895            * but the latter one is actually missing bits-per-sample :( */
11896           typedef struct
11897           {
11898             gint16 wFormatTag;
11899             gint16 nChannels;
11900             gint32 nSamplesPerSec;
11901             gint32 nAvgBytesPerSec;
11902             gint16 nBlockAlign;
11903             gint16 wBitsPerSample;
11904             gint16 cbSize;
11905           } WAVEFORMATEX;
11906           WAVEFORMATEX wfex;
11907
11908           /* FIXME: unify with similar wavformatex parsing code above */
11909           GST_DEBUG_OBJECT (qtdemux, "parse wma, looking for wfex");
11910
11911           /* find wfex */
11912           while (len >= 8) {
11913             gint size;
11914
11915             if (QT_UINT32 (wfex_data) <= len)
11916               size = QT_UINT32 (wfex_data) - 8;
11917             else
11918               size = len - 8;
11919
11920             if (size < 1)
11921               /* No real data, so break out */
11922               break;
11923
11924             switch (QT_FOURCC (wfex_data + 4)) {
11925               case GST_MAKE_FOURCC ('w', 'f', 'e', 'x'):
11926               {
11927                 GST_DEBUG_OBJECT (qtdemux, "found wfex in stsd");
11928
11929                 if (size < 8 + 18)
11930                   break;
11931
11932                 wfex.wFormatTag = GST_READ_UINT16_LE (wfex_data + 8 + 0);
11933                 wfex.nChannels = GST_READ_UINT16_LE (wfex_data + 8 + 2);
11934                 wfex.nSamplesPerSec = GST_READ_UINT32_LE (wfex_data + 8 + 4);
11935                 wfex.nAvgBytesPerSec = GST_READ_UINT32_LE (wfex_data + 8 + 8);
11936                 wfex.nBlockAlign = GST_READ_UINT16_LE (wfex_data + 8 + 12);
11937                 wfex.wBitsPerSample = GST_READ_UINT16_LE (wfex_data + 8 + 14);
11938                 wfex.cbSize = GST_READ_UINT16_LE (wfex_data + 8 + 16);
11939
11940                 GST_LOG_OBJECT (qtdemux, "Found wfex box in stsd:");
11941                 GST_LOG_OBJECT (qtdemux, "FormatTag = 0x%04x, Channels = %u, "
11942                     "SamplesPerSec = %u, AvgBytesPerSec = %u, BlockAlign = %u, "
11943                     "BitsPerSample = %u, Size = %u", wfex.wFormatTag,
11944                     wfex.nChannels, wfex.nSamplesPerSec, wfex.nAvgBytesPerSec,
11945                     wfex.nBlockAlign, wfex.wBitsPerSample, wfex.cbSize);
11946
11947                 if (wfex.wFormatTag == 0x0161) {
11948                   codec_name = "Windows Media Audio";
11949                   version = 2;
11950                 } else if (wfex.wFormatTag == 0x0162) {
11951                   codec_name = "Windows Media Audio 9 Pro";
11952                   version = 3;
11953                 } else if (wfex.wFormatTag == 0x0163) {
11954                   codec_name = "Windows Media Audio 9 Lossless";
11955                   /* is that correct? gstffmpegcodecmap.c is missing it, but
11956                    * fluendo codec seems to support it */
11957                   version = 4;
11958                 }
11959
11960                 gst_caps_set_simple (entry->caps,
11961                     "wmaversion", G_TYPE_INT, version,
11962                     "block_align", G_TYPE_INT, wfex.nBlockAlign,
11963                     "bitrate", G_TYPE_INT, wfex.nAvgBytesPerSec,
11964                     "width", G_TYPE_INT, wfex.wBitsPerSample,
11965                     "depth", G_TYPE_INT, wfex.wBitsPerSample, NULL);
11966
11967                 if (size > wfex.cbSize) {
11968                   GstBuffer *buf;
11969
11970                   buf = gst_buffer_new_and_alloc (size - wfex.cbSize);
11971                   gst_buffer_fill (buf, 0, wfex_data + 8 + wfex.cbSize,
11972                       size - wfex.cbSize);
11973                   gst_caps_set_simple (entry->caps,
11974                       "codec_data", GST_TYPE_BUFFER, buf, NULL);
11975                   gst_buffer_unref (buf);
11976                 } else {
11977                   GST_WARNING_OBJECT (qtdemux, "no codec data");
11978                 }
11979
11980                 if (codec_name) {
11981                   g_free (codec);
11982                   codec = g_strdup (codec_name);
11983                 }
11984                 break;
11985               }
11986               default:
11987                 break;
11988             }
11989             len -= size + 8;
11990             wfex_data += size + 8;
11991           }
11992           break;
11993         }
11994         case FOURCC_opus:
11995         {
11996           const guint8 *opus_data;
11997           guint8 *channel_mapping = NULL;
11998           guint32 rate;
11999           guint8 channels;
12000           guint8 channel_mapping_family;
12001           guint8 stream_count;
12002           guint8 coupled_count;
12003           guint8 i;
12004
12005           opus_data = stsd_entry_data;
12006
12007           channels = GST_READ_UINT8 (opus_data + 45);
12008           rate = GST_READ_UINT32_LE (opus_data + 48);
12009           channel_mapping_family = GST_READ_UINT8 (opus_data + 54);
12010           stream_count = GST_READ_UINT8 (opus_data + 55);
12011           coupled_count = GST_READ_UINT8 (opus_data + 56);
12012
12013           if (channels > 0) {
12014             channel_mapping = g_malloc (channels * sizeof (guint8));
12015             for (i = 0; i < channels; i++)
12016               channel_mapping[i] = GST_READ_UINT8 (opus_data + i + 57);
12017           }
12018
12019           entry->caps = gst_codec_utils_opus_create_caps (rate, channels,
12020               channel_mapping_family, stream_count, coupled_count,
12021               channel_mapping);
12022           break;
12023         }
12024         default:
12025           break;
12026       }
12027
12028       if (codec) {
12029         GstStructure *s;
12030         gint bitrate = 0;
12031
12032         gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
12033             GST_TAG_AUDIO_CODEC, codec, NULL);
12034         g_free (codec);
12035         codec = NULL;
12036
12037         /* some bitrate info may have ended up in caps */
12038         s = gst_caps_get_structure (entry->caps, 0);
12039         gst_structure_get_int (s, "bitrate", &bitrate);
12040         if (bitrate > 0)
12041           gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
12042               GST_TAG_BITRATE, bitrate, NULL);
12043       }
12044
12045       mp4a = qtdemux_tree_get_child_by_index (stsd, stsd_index);
12046       if (!stream->protected) {
12047       } else {
12048         if (QTDEMUX_TREE_NODE_FOURCC (mp4v) != FOURCC_encv) {
12049           mp4v = NULL;
12050         }
12051       }
12052       if (stream->protected && fourcc == FOURCC_mp4a) {
12053         if (QTDEMUX_TREE_NODE_FOURCC (mp4a) != FOURCC_enca) {
12054           mp4a = NULL;
12055         }
12056       } else {
12057         if (QTDEMUX_TREE_NODE_FOURCC (mp4a) != FOURCC_mp4a) {
12058           mp4a = NULL;
12059         }
12060       }
12061
12062       wave = NULL;
12063       esds = NULL;
12064       if (mp4a) {
12065         wave = qtdemux_tree_get_child_by_type (mp4a, FOURCC_wave);
12066         if (wave)
12067           esds = qtdemux_tree_get_child_by_type (wave, FOURCC_esds);
12068         if (!esds)
12069           esds = qtdemux_tree_get_child_by_type (mp4a, FOURCC_esds);
12070       }
12071
12072
12073       /* If the fourcc's bottom 16 bits gives 'sm', then the top
12074          16 bits is a byte-swapped wave-style codec identifier,
12075          and we can find a WAVE header internally to a 'wave' atom here.
12076          This can more clearly be thought of as 'ms' as the top 16 bits, and a
12077          codec id as the bottom 16 bits - but byte-swapped to store in QT (which
12078          is big-endian).
12079        */
12080       if ((fourcc & 0xffff) == (('s' << 8) | 'm')) {
12081         if (len < offset + 20) {
12082           GST_WARNING_OBJECT (qtdemux, "No wave atom in MS-style audio");
12083         } else {
12084           guint32 datalen = QT_UINT32 (stsd_entry_data + offset + 16);
12085           const guint8 *data = stsd_entry_data + offset + 16;
12086           GNode *wavenode;
12087           GNode *waveheadernode;
12088
12089           wavenode = g_node_new ((guint8 *) data);
12090           if (qtdemux_parse_node (qtdemux, wavenode, data, datalen)) {
12091             const guint8 *waveheader;
12092             guint32 headerlen;
12093
12094             waveheadernode = qtdemux_tree_get_child_by_type (wavenode, fourcc);
12095             if (waveheadernode) {
12096               waveheader = (const guint8 *) waveheadernode->data;
12097               headerlen = QT_UINT32 (waveheader);
12098
12099               if (headerlen > 8) {
12100                 gst_riff_strf_auds *header = NULL;
12101                 GstBuffer *headerbuf;
12102                 GstBuffer *extra;
12103
12104                 waveheader += 8;
12105                 headerlen -= 8;
12106
12107                 headerbuf = gst_buffer_new_and_alloc (headerlen);
12108                 gst_buffer_fill (headerbuf, 0, waveheader, headerlen);
12109
12110                 if (gst_riff_parse_strf_auds (GST_ELEMENT_CAST (qtdemux),
12111                         headerbuf, &header, &extra)) {
12112                   gst_caps_unref (entry->caps);
12113                   /* FIXME: Need to do something with the channel reorder map */
12114                   entry->caps =
12115                       gst_riff_create_audio_caps (header->format, NULL, header,
12116                       extra, NULL, NULL, NULL);
12117
12118                   if (extra)
12119                     gst_buffer_unref (extra);
12120                   g_free (header);
12121                 }
12122               }
12123             } else
12124               GST_DEBUG ("Didn't find waveheadernode for this codec");
12125           }
12126           g_node_destroy (wavenode);
12127         }
12128       } else if (esds) {
12129         gst_qtdemux_handle_esds (qtdemux, stream, entry, esds,
12130             stream->stream_tags);
12131       } else {
12132         switch (fourcc) {
12133 #if 0
12134             /* FIXME: what is in the chunk? */
12135           case FOURCC_QDMC:
12136           {
12137             gint len = QT_UINT32 (stsd_data);
12138
12139             /* seems to be always = 116 = 0x74 */
12140             break;
12141           }
12142 #endif
12143           case FOURCC_QDM2:
12144           {
12145             gint len = QT_UINT32 (stsd_entry_data);
12146
12147             if (len > 0x3C) {
12148               GstBuffer *buf = gst_buffer_new_and_alloc (len - 0x3C);
12149
12150               gst_buffer_fill (buf, 0, stsd_entry_data + 0x3C, len - 0x3C);
12151               gst_caps_set_simple (entry->caps,
12152                   "codec_data", GST_TYPE_BUFFER, buf, NULL);
12153               gst_buffer_unref (buf);
12154             }
12155             gst_caps_set_simple (entry->caps,
12156                 "samplesize", G_TYPE_INT, samplesize, NULL);
12157             break;
12158           }
12159           case FOURCC_alac:
12160           {
12161             GNode *alac, *wave = NULL;
12162
12163             /* apparently, m4a has this atom appended directly in the stsd entry,
12164              * while mov has it in a wave atom */
12165             alac = qtdemux_tree_get_child_by_type (stsd, FOURCC_alac);
12166             if (alac) {
12167               /* alac now refers to stsd entry atom */
12168               wave = qtdemux_tree_get_child_by_type (alac, FOURCC_wave);
12169               if (wave)
12170                 alac = qtdemux_tree_get_child_by_type (wave, FOURCC_alac);
12171               else
12172                 alac = qtdemux_tree_get_child_by_type (alac, FOURCC_alac);
12173             }
12174             if (alac) {
12175               const guint8 *alac_data = alac->data;
12176               gint len = QT_UINT32 (alac->data);
12177               GstBuffer *buf;
12178
12179               if (len < 36) {
12180                 GST_DEBUG_OBJECT (qtdemux,
12181                     "discarding alac atom with unexpected len %d", len);
12182               } else {
12183                 /* codec-data contains alac atom size and prefix,
12184                  * ffmpeg likes it that way, not quite gst-ish though ...*/
12185                 buf = gst_buffer_new_and_alloc (len);
12186                 gst_buffer_fill (buf, 0, alac->data, len);
12187                 gst_caps_set_simple (entry->caps,
12188                     "codec_data", GST_TYPE_BUFFER, buf, NULL);
12189                 gst_buffer_unref (buf);
12190
12191                 entry->bytes_per_frame = QT_UINT32 (alac_data + 12);
12192                 entry->n_channels = QT_UINT8 (alac_data + 21);
12193                 entry->rate = QT_UINT32 (alac_data + 32);
12194               }
12195             }
12196             gst_caps_set_simple (entry->caps,
12197                 "samplesize", G_TYPE_INT, samplesize, NULL);
12198             break;
12199           }
12200           case FOURCC_fLaC:
12201           {
12202             /* The codingname of the sample entry is 'fLaC' */
12203             GNode *flac = qtdemux_tree_get_child_by_type (stsd, FOURCC_fLaC);
12204
12205             if (flac) {
12206               /* The 'dfLa' box is added to the sample entry to convey
12207                  initializing information for the decoder. */
12208               const GNode *dfla =
12209                   qtdemux_tree_get_child_by_type (flac, FOURCC_dfLa);
12210
12211               if (dfla) {
12212                 const guint32 len = QT_UINT32 (dfla->data);
12213
12214                 /* Must contain at least dfLa box header (12),
12215                  * METADATA_BLOCK_HEADER (4), METADATA_BLOCK_STREAMINFO (34) */
12216                 if (len < 50) {
12217                   GST_DEBUG_OBJECT (qtdemux,
12218                       "discarding dfla atom with unexpected len %d", len);
12219                 } else {
12220                   /* skip dfLa header to get the METADATA_BLOCKs */
12221                   const guint8 *metadata_blocks = (guint8 *) dfla->data + 12;
12222                   const guint32 metadata_blocks_len = len - 12;
12223
12224                   gchar *stream_marker = g_strdup ("fLaC");
12225                   GstBuffer *block = gst_buffer_new_wrapped (stream_marker,
12226                       strlen (stream_marker));
12227
12228                   guint32 index = 0;
12229                   guint32 remainder = 0;
12230                   guint32 block_size = 0;
12231                   gboolean is_last = FALSE;
12232
12233                   GValue array = G_VALUE_INIT;
12234                   GValue value = G_VALUE_INIT;
12235
12236                   g_value_init (&array, GST_TYPE_ARRAY);
12237                   g_value_init (&value, GST_TYPE_BUFFER);
12238
12239                   gst_value_set_buffer (&value, block);
12240                   gst_value_array_append_value (&array, &value);
12241                   g_value_reset (&value);
12242
12243                   gst_buffer_unref (block);
12244
12245                   /* check there's at least one METADATA_BLOCK_HEADER's worth
12246                    * of data, and we haven't already finished parsing */
12247                   while (!is_last && ((index + 3) < metadata_blocks_len)) {
12248                     remainder = metadata_blocks_len - index;
12249
12250                     /* add the METADATA_BLOCK_HEADER size to the signalled size */
12251                     block_size = 4 +
12252                         (metadata_blocks[index + 1] << 16) +
12253                         (metadata_blocks[index + 2] << 8) +
12254                         metadata_blocks[index + 3];
12255
12256                     /* be careful not to read off end of box */
12257                     if (block_size > remainder) {
12258                       break;
12259                     }
12260
12261                     is_last = metadata_blocks[index] >> 7;
12262
12263                     block = gst_buffer_new_and_alloc (block_size);
12264
12265                     gst_buffer_fill (block, 0, &metadata_blocks[index],
12266                         block_size);
12267
12268                     gst_value_set_buffer (&value, block);
12269                     gst_value_array_append_value (&array, &value);
12270                     g_value_reset (&value);
12271
12272                     gst_buffer_unref (block);
12273
12274                     index += block_size;
12275                   }
12276
12277                   /* only append the metadata if we successfully read all of it */
12278                   if (is_last) {
12279                     gst_structure_set_value (gst_caps_get_structure (CUR_STREAM
12280                             (stream)->caps, 0), "streamheader", &array);
12281                   } else {
12282                     GST_WARNING_OBJECT (qtdemux,
12283                         "discarding all METADATA_BLOCKs due to invalid "
12284                         "block_size %d at idx %d, rem %d", block_size, index,
12285                         remainder);
12286                   }
12287
12288                   g_value_unset (&value);
12289                   g_value_unset (&array);
12290
12291                   /* The sample rate obtained from the stsd may not be accurate
12292                    * since it cannot represent rates greater than 65535Hz, so
12293                    * override that value with the sample rate from the
12294                    * METADATA_BLOCK_STREAMINFO block */
12295                   CUR_STREAM (stream)->rate =
12296                       (QT_UINT32 (metadata_blocks + 14) >> 12) & 0xFFFFF;
12297                 }
12298               }
12299             }
12300             break;
12301           }
12302           case FOURCC_sawb:
12303             /* Fallthrough! */
12304             amrwb = TRUE;
12305           case FOURCC_samr:
12306           {
12307             gint len = QT_UINT32 (stsd_entry_data);
12308
12309             if (len > 0x24) {
12310               GstBuffer *buf = gst_buffer_new_and_alloc (len - 0x24);
12311               guint bitrate;
12312
12313               gst_buffer_fill (buf, 0, stsd_entry_data + 0x24, len - 0x24);
12314
12315               /* If we have enough data, let's try to get the 'damr' atom. See
12316                * the 3GPP container spec (26.244) for more details. */
12317               if ((len - 0x34) > 8 &&
12318                   (bitrate = qtdemux_parse_amr_bitrate (buf, amrwb))) {
12319                 gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
12320                     GST_TAG_MAXIMUM_BITRATE, bitrate, NULL);
12321               }
12322
12323               gst_caps_set_simple (entry->caps,
12324                   "codec_data", GST_TYPE_BUFFER, buf, NULL);
12325               gst_buffer_unref (buf);
12326             }
12327             break;
12328           }
12329           case FOURCC_mp4a:
12330           {
12331             /* mp4a atom withtout ESDS; Attempt to build codec data from atom */
12332             gint len = QT_UINT32 (stsd_entry_data);
12333
12334             if (len >= 34) {
12335               guint16 sound_version = QT_UINT16 (stsd_entry_data + 16);
12336
12337               if (sound_version == 1) {
12338                 guint16 channels = QT_UINT16 (stsd_entry_data + 24);
12339                 guint32 time_scale = QT_UINT32 (stsd_entry_data + 30);
12340                 guint8 codec_data[2];
12341                 GstBuffer *buf;
12342                 gint profile = 2;       /* FIXME: Can this be determined somehow? There doesn't seem to be anything in mp4a atom that specifis compression */
12343
12344                 gint sample_rate_index =
12345                     gst_codec_utils_aac_get_index_from_sample_rate (time_scale);
12346
12347                 /* build AAC codec data */
12348                 codec_data[0] = profile << 3;
12349                 codec_data[0] |= ((sample_rate_index >> 1) & 0x7);
12350                 codec_data[1] = (sample_rate_index & 0x01) << 7;
12351                 codec_data[1] |= (channels & 0xF) << 3;
12352
12353                 buf = gst_buffer_new_and_alloc (2);
12354                 gst_buffer_fill (buf, 0, codec_data, 2);
12355                 gst_caps_set_simple (entry->caps,
12356                     "codec_data", GST_TYPE_BUFFER, buf, NULL);
12357                 gst_buffer_unref (buf);
12358               }
12359             }
12360             break;
12361           }
12362           case FOURCC_lpcm:
12363             /* Fully handled elsewhere */
12364             break;
12365           default:
12366             GST_INFO_OBJECT (qtdemux,
12367                 "unhandled type %" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (fourcc));
12368             break;
12369         }
12370       }
12371       GST_INFO_OBJECT (qtdemux,
12372           "type %" GST_FOURCC_FORMAT " caps %" GST_PTR_FORMAT,
12373           GST_FOURCC_ARGS (fourcc), entry->caps);
12374
12375     } else if (stream->subtype == FOURCC_strm) {
12376       if (fourcc == FOURCC_rtsp) {
12377         stream->redirect_uri = qtdemux_get_rtsp_uri_from_hndl (qtdemux, minf);
12378       } else {
12379         GST_INFO_OBJECT (qtdemux, "unhandled stream type %" GST_FOURCC_FORMAT,
12380             GST_FOURCC_ARGS (fourcc));
12381         goto unknown_stream;
12382       }
12383       entry->sampled = TRUE;
12384     } else if (stream->subtype == FOURCC_subp || stream->subtype == FOURCC_text
12385         || stream->subtype == FOURCC_sbtl || stream->subtype == FOURCC_subt
12386         || stream->subtype == FOURCC_clcp) {
12387
12388       entry->sampled = TRUE;
12389       entry->sparse = TRUE;
12390
12391       entry->caps =
12392           qtdemux_sub_caps (qtdemux, stream, entry, fourcc, stsd_entry_data,
12393           &codec);
12394       if (codec) {
12395         gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
12396             GST_TAG_SUBTITLE_CODEC, codec, NULL);
12397         g_free (codec);
12398         codec = NULL;
12399       }
12400
12401       /* hunt for sort-of codec data */
12402       switch (fourcc) {
12403         case FOURCC_mp4s:
12404         {
12405           GNode *mp4s = NULL;
12406           GNode *esds = NULL;
12407
12408           /* look for palette in a stsd->mp4s->esds sub-atom */
12409           mp4s = qtdemux_tree_get_child_by_type (stsd, FOURCC_mp4s);
12410           if (mp4s)
12411             esds = qtdemux_tree_get_child_by_type (mp4s, FOURCC_esds);
12412           if (esds == NULL) {
12413             /* Invalid STSD */
12414             GST_LOG_OBJECT (qtdemux, "Skipping invalid stsd: no esds child");
12415             break;
12416           }
12417
12418           gst_qtdemux_handle_esds (qtdemux, stream, entry, esds,
12419               stream->stream_tags);
12420           break;
12421         }
12422         default:
12423           GST_INFO_OBJECT (qtdemux,
12424               "unhandled type %" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (fourcc));
12425           break;
12426       }
12427       GST_INFO_OBJECT (qtdemux,
12428           "type %" GST_FOURCC_FORMAT " caps %" GST_PTR_FORMAT,
12429           GST_FOURCC_ARGS (fourcc), entry->caps);
12430     } else {
12431       /* everything in 1 sample */
12432       entry->sampled = TRUE;
12433
12434       entry->caps =
12435           qtdemux_generic_caps (qtdemux, stream, entry, fourcc, stsd_entry_data,
12436           &codec);
12437
12438       if (entry->caps == NULL)
12439         goto unknown_stream;
12440
12441       if (codec) {
12442         gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
12443             GST_TAG_SUBTITLE_CODEC, codec, NULL);
12444         g_free (codec);
12445         codec = NULL;
12446       }
12447     }
12448
12449     /* promote to sampled format */
12450     if (entry->fourcc == FOURCC_samr) {
12451       /* force mono 8000 Hz for AMR */
12452       entry->sampled = TRUE;
12453       entry->n_channels = 1;
12454       entry->rate = 8000;
12455     } else if (entry->fourcc == FOURCC_sawb) {
12456       /* force mono 16000 Hz for AMR-WB */
12457       entry->sampled = TRUE;
12458       entry->n_channels = 1;
12459       entry->rate = 16000;
12460     } else if (entry->fourcc == FOURCC_mp4a) {
12461       entry->sampled = TRUE;
12462     }
12463
12464
12465     stsd_entry_data += len;
12466     remaining_stsd_len -= len;
12467
12468   }
12469
12470   /* collect sample information */
12471   if (!qtdemux_stbl_init (qtdemux, stream, stbl))
12472     goto samples_failed;
12473
12474   if (qtdemux->fragmented) {
12475     guint64 offset;
12476
12477     /* need all moov samples as basis; probably not many if any at all */
12478     /* prevent moof parsing taking of at this time */
12479     offset = qtdemux->moof_offset;
12480     qtdemux->moof_offset = 0;
12481     if (stream->n_samples &&
12482         !qtdemux_parse_samples (qtdemux, stream, stream->n_samples - 1)) {
12483       qtdemux->moof_offset = offset;
12484       goto samples_failed;
12485     }
12486     qtdemux->moof_offset = 0;
12487     /* movie duration more reliable in this case (e.g. mehd) */
12488     if (qtdemux->segment.duration &&
12489         GST_CLOCK_TIME_IS_VALID (qtdemux->segment.duration))
12490       stream->duration =
12491           GSTTIME_TO_QTSTREAMTIME (stream, qtdemux->segment.duration);
12492   }
12493
12494   /* configure segments */
12495   if (!qtdemux_parse_segments (qtdemux, stream, trak))
12496     goto segments_failed;
12497
12498   /* add some language tag, if useful */
12499   if (stream->lang_id[0] != '\0' && strcmp (stream->lang_id, "unk") &&
12500       strcmp (stream->lang_id, "und")) {
12501     const gchar *lang_code;
12502
12503     /* convert ISO 639-2 code to ISO 639-1 */
12504     lang_code = gst_tag_get_language_code (stream->lang_id);
12505     gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
12506         GST_TAG_LANGUAGE_CODE, (lang_code) ? lang_code : stream->lang_id, NULL);
12507   }
12508
12509   /* Check for UDTA tags */
12510   if ((udta = qtdemux_tree_get_child_by_type (trak, FOURCC_udta))) {
12511     qtdemux_parse_udta (qtdemux, stream->stream_tags, udta);
12512   }
12513
12514   /* Insert and sort new stream in track-id order.
12515    * This will help in comparing old/new streams during stream update check */
12516   g_ptr_array_add (qtdemux->active_streams, stream);
12517   g_ptr_array_sort (qtdemux->active_streams,
12518       (GCompareFunc) qtdemux_track_id_compare_func);
12519   GST_DEBUG_OBJECT (qtdemux, "n_streams is now %d",
12520       QTDEMUX_N_STREAMS (qtdemux));
12521
12522   return TRUE;
12523
12524 /* ERRORS */
12525 corrupt_file:
12526   {
12527     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
12528         (_("This file is corrupt and cannot be played.")), (NULL));
12529     if (stream)
12530       gst_qtdemux_stream_unref (stream);
12531     return FALSE;
12532   }
12533 error_encrypted:
12534   {
12535     GST_ELEMENT_ERROR (qtdemux, STREAM, DECRYPT, (NULL), (NULL));
12536     gst_qtdemux_stream_unref (stream);
12537     return FALSE;
12538   }
12539 samples_failed:
12540 segments_failed:
12541   {
12542     /* we posted an error already */
12543     /* free stbl sub-atoms */
12544     gst_qtdemux_stbl_free (stream);
12545     gst_qtdemux_stream_unref (stream);
12546     return FALSE;
12547   }
12548 existing_stream:
12549   {
12550     GST_INFO_OBJECT (qtdemux, "stream with track id %i already exists",
12551         track_id);
12552     return TRUE;
12553   }
12554 unknown_stream:
12555   {
12556     GST_INFO_OBJECT (qtdemux, "unknown subtype %" GST_FOURCC_FORMAT,
12557         GST_FOURCC_ARGS (stream->subtype));
12558     gst_qtdemux_stream_unref (stream);
12559     return TRUE;
12560   }
12561 }
12562
12563 /* If we can estimate the overall bitrate, and don't have information about the
12564  * stream bitrate for exactly one stream, this guesses the stream bitrate as
12565  * the overall bitrate minus the sum of the bitrates of all other streams. This
12566  * should be useful for the common case where we have one audio and one video
12567  * stream and can estimate the bitrate of one, but not the other. */
12568 static void
12569 gst_qtdemux_guess_bitrate (GstQTDemux * qtdemux)
12570 {
12571   QtDemuxStream *stream = NULL;
12572   gint64 size, sys_bitrate, sum_bitrate = 0;
12573   GstClockTime duration;
12574   guint bitrate;
12575   gint i;
12576
12577   if (qtdemux->fragmented)
12578     return;
12579
12580   GST_DEBUG_OBJECT (qtdemux, "Looking for streams with unknown bitrate");
12581
12582   if (!gst_pad_peer_query_duration (qtdemux->sinkpad, GST_FORMAT_BYTES, &size)
12583       || size <= 0) {
12584     GST_DEBUG_OBJECT (qtdemux,
12585         "Size in bytes of the stream not known - bailing");
12586     return;
12587   }
12588
12589   /* Subtract the header size */
12590   GST_DEBUG_OBJECT (qtdemux, "Total size %" G_GINT64_FORMAT ", header size %u",
12591       size, qtdemux->header_size);
12592
12593   if (size < qtdemux->header_size)
12594     return;
12595
12596   size = size - qtdemux->header_size;
12597
12598   if (!gst_qtdemux_get_duration (qtdemux, &duration)) {
12599     GST_DEBUG_OBJECT (qtdemux, "Stream duration not known - bailing");
12600     return;
12601   }
12602
12603   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
12604     QtDemuxStream *str = QTDEMUX_NTH_STREAM (qtdemux, i);
12605     switch (str->subtype) {
12606       case FOURCC_soun:
12607       case FOURCC_vide:
12608         GST_DEBUG_OBJECT (qtdemux, "checking bitrate for %" GST_PTR_FORMAT,
12609             CUR_STREAM (str)->caps);
12610         /* retrieve bitrate, prefer avg then max */
12611         bitrate = 0;
12612         if (str->stream_tags) {
12613           if (gst_tag_list_get_uint (str->stream_tags,
12614                   GST_TAG_MAXIMUM_BITRATE, &bitrate))
12615             GST_DEBUG_OBJECT (qtdemux, "max-bitrate: %u", bitrate);
12616           if (gst_tag_list_get_uint (str->stream_tags,
12617                   GST_TAG_NOMINAL_BITRATE, &bitrate))
12618             GST_DEBUG_OBJECT (qtdemux, "nominal-bitrate: %u", bitrate);
12619           if (gst_tag_list_get_uint (str->stream_tags,
12620                   GST_TAG_BITRATE, &bitrate))
12621             GST_DEBUG_OBJECT (qtdemux, "bitrate: %u", bitrate);
12622         }
12623         if (bitrate)
12624           sum_bitrate += bitrate;
12625         else {
12626           if (stream) {
12627             GST_DEBUG_OBJECT (qtdemux,
12628                 ">1 stream with unknown bitrate - bailing");
12629             return;
12630           } else
12631             stream = str;
12632         }
12633
12634       default:
12635         /* For other subtypes, we assume no significant impact on bitrate */
12636         break;
12637     }
12638   }
12639
12640   if (!stream) {
12641     GST_DEBUG_OBJECT (qtdemux, "All stream bitrates are known");
12642     return;
12643   }
12644
12645   sys_bitrate = gst_util_uint64_scale (size, GST_SECOND * 8, duration);
12646
12647   if (sys_bitrate < sum_bitrate) {
12648     /* This can happen, since sum_bitrate might be derived from maximum
12649      * bitrates and not average bitrates */
12650     GST_DEBUG_OBJECT (qtdemux,
12651         "System bitrate less than sum bitrate - bailing");
12652     return;
12653   }
12654
12655   bitrate = sys_bitrate - sum_bitrate;
12656   GST_DEBUG_OBJECT (qtdemux, "System bitrate = %" G_GINT64_FORMAT
12657       ", Stream bitrate = %u", sys_bitrate, bitrate);
12658
12659   if (!stream->stream_tags)
12660     stream->stream_tags = gst_tag_list_new_empty ();
12661   else
12662     stream->stream_tags = gst_tag_list_make_writable (stream->stream_tags);
12663
12664   gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
12665       GST_TAG_BITRATE, bitrate, NULL);
12666 }
12667
12668 static GstFlowReturn
12669 qtdemux_prepare_streams (GstQTDemux * qtdemux)
12670 {
12671   GstFlowReturn ret = GST_FLOW_OK;
12672   gint i;
12673
12674   GST_DEBUG_OBJECT (qtdemux, "prepare streams");
12675
12676   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
12677     QtDemuxStream *stream = QTDEMUX_NTH_STREAM (qtdemux, i);
12678     guint32 sample_num = 0;
12679
12680     GST_DEBUG_OBJECT (qtdemux, "track-id %u, fourcc %" GST_FOURCC_FORMAT,
12681         stream->track_id, GST_FOURCC_ARGS (CUR_STREAM (stream)->fourcc));
12682
12683     if (qtdemux->fragmented) {
12684       /* need all moov samples first */
12685       GST_OBJECT_LOCK (qtdemux);
12686       while (stream->n_samples == 0)
12687         if ((ret = qtdemux_add_fragmented_samples (qtdemux)) != GST_FLOW_OK)
12688           break;
12689       GST_OBJECT_UNLOCK (qtdemux);
12690     } else {
12691       /* discard any stray moof */
12692       qtdemux->moof_offset = 0;
12693     }
12694
12695     /* prepare braking */
12696     if (ret != GST_FLOW_ERROR)
12697       ret = GST_FLOW_OK;
12698
12699     /* in pull mode, we should have parsed some sample info by now;
12700      * and quite some code will not handle no samples.
12701      * in push mode, we'll just have to deal with it */
12702     if (G_UNLIKELY (qtdemux->pullbased && !stream->n_samples)) {
12703       GST_DEBUG_OBJECT (qtdemux, "no samples for stream; discarding");
12704       g_ptr_array_remove_index (qtdemux->active_streams, i);
12705       i--;
12706       continue;
12707     } else if (stream->track_id == qtdemux->chapters_track_id &&
12708         (stream->subtype == FOURCC_text || stream->subtype == FOURCC_sbtl)) {
12709       /* TODO - parse chapters track and expose it as GstToc; For now just ignore it
12710          so that it doesn't look like a subtitle track */
12711       g_ptr_array_remove_index (qtdemux->active_streams, i);
12712       i--;
12713       continue;
12714     }
12715
12716     /* parse the initial sample for use in setting the frame rate cap */
12717     while (sample_num == 0 && sample_num < stream->n_samples) {
12718       if (!qtdemux_parse_samples (qtdemux, stream, sample_num))
12719         break;
12720       ++sample_num;
12721     }
12722   }
12723
12724   return ret;
12725 }
12726
12727 static gboolean
12728 _stream_equal_func (const QtDemuxStream * stream, const gchar * stream_id)
12729 {
12730   return g_strcmp0 (stream->stream_id, stream_id) == 0;
12731 }
12732
12733 static gboolean
12734 qtdemux_is_streams_update (GstQTDemux * qtdemux)
12735 {
12736   gint i;
12737
12738   /* Different length, updated */
12739   if (QTDEMUX_N_STREAMS (qtdemux) != qtdemux->old_streams->len)
12740     return TRUE;
12741
12742   /* streams in list are sorted in track-id order */
12743   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
12744     /* Different stream-id, updated */
12745     if (g_strcmp0 (QTDEMUX_NTH_STREAM (qtdemux, i)->stream_id,
12746             QTDEMUX_NTH_OLD_STREAM (qtdemux, i)->stream_id))
12747       return TRUE;
12748   }
12749
12750   return FALSE;
12751 }
12752
12753 static gboolean
12754 qtdemux_reuse_and_configure_stream (GstQTDemux * qtdemux,
12755     QtDemuxStream * oldstream, QtDemuxStream * newstream)
12756 {
12757   /* Connect old stream's srcpad to new stream */
12758   newstream->pad = oldstream->pad;
12759   oldstream->pad = NULL;
12760
12761   /* unset new_stream to prevent stream-start event */
12762   newstream->new_stream = FALSE;
12763
12764   return gst_qtdemux_configure_stream (qtdemux, newstream);
12765 }
12766
12767 /* g_ptr_array_find_with_equal_func is available since 2.54,
12768  * replacement until we can depend unconditionally on the real one in GLib */
12769 #if !GLIB_CHECK_VERSION(2,54,0)
12770 #define g_ptr_array_find_with_equal_func qtdemux_ptr_array_find_with_equal_func
12771 static gboolean
12772 qtdemux_ptr_array_find_with_equal_func (GPtrArray * haystack,
12773     gconstpointer needle, GEqualFunc equal_func, guint * index_)
12774 {
12775   guint i;
12776
12777   g_return_val_if_fail (haystack != NULL, FALSE);
12778
12779   if (equal_func == NULL)
12780     equal_func = g_direct_equal;
12781
12782   for (i = 0; i < haystack->len; i++) {
12783     if (equal_func (g_ptr_array_index (haystack, i), needle)) {
12784       if (index_ != NULL)
12785         *index_ = i;
12786       return TRUE;
12787     }
12788   }
12789
12790   return FALSE;
12791 }
12792 #endif
12793
12794 static gboolean
12795 qtdemux_update_streams (GstQTDemux * qtdemux)
12796 {
12797   gint i;
12798   g_assert (qtdemux->streams_aware);
12799
12800   /* At below, figure out which stream in active_streams has identical stream-id
12801    * with that of in old_streams. If there is matching stream-id,
12802    * corresponding newstream will not be exposed again,
12803    * but demux will reuse srcpad of matched old stream
12804    *
12805    * active_streams : newly created streams from the latest moov
12806    * old_streams : existing streams (belong to previous moov)
12807    */
12808
12809   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
12810     QtDemuxStream *stream = QTDEMUX_NTH_STREAM (qtdemux, i);
12811     QtDemuxStream *oldstream = NULL;
12812     guint target;
12813
12814     GST_DEBUG_OBJECT (qtdemux, "track-id %u, fourcc %" GST_FOURCC_FORMAT,
12815         stream->track_id, GST_FOURCC_ARGS (CUR_STREAM (stream)->fourcc));
12816
12817     if (g_ptr_array_find_with_equal_func (qtdemux->old_streams,
12818             stream->stream_id, (GEqualFunc) _stream_equal_func, &target)) {
12819       oldstream = QTDEMUX_NTH_OLD_STREAM (qtdemux, target);
12820
12821       /* null pad stream cannot be reused */
12822       if (oldstream->pad == NULL)
12823         oldstream = NULL;
12824     }
12825
12826     if (oldstream) {
12827       GST_DEBUG_OBJECT (qtdemux, "Reuse track-id %d", oldstream->track_id);
12828
12829       if (!qtdemux_reuse_and_configure_stream (qtdemux, oldstream, stream))
12830         return FALSE;
12831
12832       /* we don't need to preserve order of old streams */
12833       g_ptr_array_remove_fast (qtdemux->old_streams, oldstream);
12834     } else {
12835       GstTagList *list;
12836
12837       /* now we have all info and can expose */
12838       list = stream->stream_tags;
12839       stream->stream_tags = NULL;
12840       if (!gst_qtdemux_add_stream (qtdemux, stream, list))
12841         return FALSE;
12842     }
12843   }
12844
12845   return TRUE;
12846 }
12847
12848 /* Must be called with expose lock */
12849 static GstFlowReturn
12850 qtdemux_expose_streams (GstQTDemux * qtdemux)
12851 {
12852   gint i;
12853
12854   GST_DEBUG_OBJECT (qtdemux, "exposing streams");
12855
12856   if (!qtdemux_is_streams_update (qtdemux)) {
12857     GST_DEBUG_OBJECT (qtdemux, "Reuse all streams");
12858     for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
12859       QtDemuxStream *new_stream = QTDEMUX_NTH_STREAM (qtdemux, i);
12860       QtDemuxStream *old_stream = QTDEMUX_NTH_OLD_STREAM (qtdemux, i);
12861       if (!qtdemux_reuse_and_configure_stream (qtdemux, old_stream, new_stream))
12862         return GST_FLOW_ERROR;
12863     }
12864
12865     g_ptr_array_remove_range (qtdemux->old_streams,
12866         0, qtdemux->old_streams->len);
12867
12868     qtdemux->need_segment = TRUE;
12869
12870     return GST_FLOW_OK;
12871   }
12872
12873   if (qtdemux->streams_aware) {
12874     if (!qtdemux_update_streams (qtdemux))
12875       return GST_FLOW_ERROR;
12876   } else {
12877     for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
12878       QtDemuxStream *stream = QTDEMUX_NTH_STREAM (qtdemux, i);
12879       GstTagList *list;
12880
12881       /* now we have all info and can expose */
12882       list = stream->stream_tags;
12883       stream->stream_tags = NULL;
12884       if (!gst_qtdemux_add_stream (qtdemux, stream, list))
12885         return GST_FLOW_ERROR;
12886
12887     }
12888   }
12889
12890   gst_qtdemux_guess_bitrate (qtdemux);
12891
12892   gst_element_no_more_pads (GST_ELEMENT_CAST (qtdemux));
12893
12894   /* If we have still old_streams, it's no more used stream */
12895   for (i = 0; i < qtdemux->old_streams->len; i++) {
12896     QtDemuxStream *stream = QTDEMUX_NTH_OLD_STREAM (qtdemux, i);
12897
12898     if (stream->pad) {
12899       GstEvent *event;
12900
12901       event = gst_event_new_eos ();
12902       if (qtdemux->segment_seqnum)
12903         gst_event_set_seqnum (event, qtdemux->segment_seqnum);
12904
12905       gst_pad_push_event (stream->pad, event);
12906     }
12907   }
12908
12909   g_ptr_array_remove_range (qtdemux->old_streams, 0, qtdemux->old_streams->len);
12910
12911   /* check if we should post a redirect in case there is a single trak
12912    * and it is a redirecting trak */
12913   if (QTDEMUX_N_STREAMS (qtdemux) == 1 &&
12914       QTDEMUX_NTH_STREAM (qtdemux, 0)->redirect_uri != NULL) {
12915     GstMessage *m;
12916
12917     GST_INFO_OBJECT (qtdemux, "Issuing a redirect due to a single track with "
12918         "an external content");
12919     m = gst_message_new_element (GST_OBJECT_CAST (qtdemux),
12920         gst_structure_new ("redirect",
12921             "new-location", G_TYPE_STRING,
12922             QTDEMUX_NTH_STREAM (qtdemux, 0)->redirect_uri, NULL));
12923     gst_element_post_message (GST_ELEMENT_CAST (qtdemux), m);
12924     qtdemux->posted_redirect = TRUE;
12925   }
12926
12927   g_ptr_array_foreach (qtdemux->active_streams,
12928       (GFunc) qtdemux_do_allocation, qtdemux);
12929
12930   qtdemux->need_segment = TRUE;
12931
12932   qtdemux->exposed = TRUE;
12933   return GST_FLOW_OK;
12934 }
12935
12936 /* check if major or compatible brand is 3GP */
12937 static inline gboolean
12938 qtdemux_is_brand_3gp (GstQTDemux * qtdemux, gboolean major)
12939 {
12940   if (major) {
12941     return ((qtdemux->major_brand & GST_MAKE_FOURCC (255, 255, 0, 0)) ==
12942         FOURCC_3g__);
12943   } else if (qtdemux->comp_brands != NULL) {
12944     GstMapInfo map;
12945     guint8 *data;
12946     gsize size;
12947     gboolean res = FALSE;
12948
12949     gst_buffer_map (qtdemux->comp_brands, &map, GST_MAP_READ);
12950     data = map.data;
12951     size = map.size;
12952     while (size >= 4) {
12953       res = res || ((QT_FOURCC (data) & GST_MAKE_FOURCC (255, 255, 0, 0)) ==
12954           FOURCC_3g__);
12955       data += 4;
12956       size -= 4;
12957     }
12958     gst_buffer_unmap (qtdemux->comp_brands, &map);
12959     return res;
12960   } else {
12961     return FALSE;
12962   }
12963 }
12964
12965 /* check if tag is a spec'ed 3GP tag keyword storing a string */
12966 static inline gboolean
12967 qtdemux_is_string_tag_3gp (GstQTDemux * qtdemux, guint32 fourcc)
12968 {
12969   return fourcc == FOURCC_cprt || fourcc == FOURCC_gnre || fourcc == FOURCC_titl
12970       || fourcc == FOURCC_dscp || fourcc == FOURCC_perf || fourcc == FOURCC_auth
12971       || fourcc == FOURCC_albm;
12972 }
12973
12974 static void
12975 qtdemux_tag_add_location (GstQTDemux * qtdemux, GstTagList * taglist,
12976     const char *tag, const char *dummy, GNode * node)
12977 {
12978   const gchar *env_vars[] = { "GST_QT_TAG_ENCODING", "GST_TAG_ENCODING", NULL };
12979   int offset;
12980   char *name;
12981   gchar *data;
12982   gdouble longitude, latitude, altitude;
12983   gint len;
12984
12985   len = QT_UINT32 (node->data);
12986   if (len <= 14)
12987     goto short_read;
12988
12989   data = node->data;
12990   offset = 14;
12991
12992   /* TODO: language code skipped */
12993
12994   name = gst_tag_freeform_string_to_utf8 (data + offset, -1, env_vars);
12995
12996   if (!name) {
12997     /* do not alarm in trivial case, but bail out otherwise */
12998     if (*(data + offset) != 0) {
12999       GST_DEBUG_OBJECT (qtdemux, "failed to convert %s tag to UTF-8, "
13000           "giving up", tag);
13001     }
13002   } else {
13003     gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE,
13004         GST_TAG_GEO_LOCATION_NAME, name, NULL);
13005     offset += strlen (name);
13006     g_free (name);
13007   }
13008
13009   if (len < offset + 2 + 4 + 4 + 4)
13010     goto short_read;
13011
13012   /* +1 +1 = skip null-terminator and location role byte */
13013   offset += 1 + 1;
13014   /* table in spec says unsigned, semantics say negative has meaning ... */
13015   longitude = QT_SFP32 (data + offset);
13016
13017   offset += 4;
13018   latitude = QT_SFP32 (data + offset);
13019
13020   offset += 4;
13021   altitude = QT_SFP32 (data + offset);
13022
13023   /* one invalid means all are invalid */
13024   if (longitude >= -180.0 && longitude <= 180.0 &&
13025       latitude >= -90.0 && latitude <= 90.0) {
13026     gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE,
13027         GST_TAG_GEO_LOCATION_LATITUDE, latitude,
13028         GST_TAG_GEO_LOCATION_LONGITUDE, longitude,
13029         GST_TAG_GEO_LOCATION_ELEVATION, altitude, NULL);
13030   }
13031
13032   /* TODO: no GST_TAG_, so astronomical body and additional notes skipped */
13033
13034   return;
13035
13036   /* ERRORS */
13037 short_read:
13038   {
13039     GST_DEBUG_OBJECT (qtdemux, "short read parsing 3GP location");
13040     return;
13041   }
13042 }
13043
13044
13045 static void
13046 qtdemux_tag_add_year (GstQTDemux * qtdemux, GstTagList * taglist,
13047     const char *tag, const char *dummy, GNode * node)
13048 {
13049   guint16 y;
13050   GDate *date;
13051   gint len;
13052
13053   len = QT_UINT32 (node->data);
13054   if (len < 14)
13055     return;
13056
13057   y = QT_UINT16 ((guint8 *) node->data + 12);
13058   if (y == 0) {
13059     GST_DEBUG_OBJECT (qtdemux, "year: %u is not a valid year", y);
13060     return;
13061   }
13062   GST_DEBUG_OBJECT (qtdemux, "year: %u", y);
13063
13064   date = g_date_new_dmy (1, 1, y);
13065   gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag, date, NULL);
13066   g_date_free (date);
13067 }
13068
13069 static void
13070 qtdemux_tag_add_classification (GstQTDemux * qtdemux, GstTagList * taglist,
13071     const char *tag, const char *dummy, GNode * node)
13072 {
13073   int offset;
13074   char *tag_str = NULL;
13075   guint8 *entity;
13076   guint16 table;
13077   gint len;
13078
13079   len = QT_UINT32 (node->data);
13080   if (len <= 20)
13081     goto short_read;
13082
13083   offset = 12;
13084   entity = (guint8 *) node->data + offset;
13085   if (entity[0] == 0 || entity[1] == 0 || entity[2] == 0 || entity[3] == 0) {
13086     GST_DEBUG_OBJECT (qtdemux,
13087         "classification info: %c%c%c%c invalid classification entity",
13088         entity[0], entity[1], entity[2], entity[3]);
13089     return;
13090   }
13091
13092   offset += 4;
13093   table = QT_UINT16 ((guint8 *) node->data + offset);
13094
13095   /* Language code skipped */
13096
13097   offset += 4;
13098
13099   /* Tag format: "XXXX://Y[YYYY]/classification info string"
13100    * XXXX: classification entity, fixed length 4 chars.
13101    * Y[YYYY]: classification table, max 5 chars.
13102    */
13103   tag_str = g_strdup_printf ("----://%u/%s",
13104       table, (char *) node->data + offset);
13105
13106   /* memcpy To be sure we're preserving byte order */
13107   memcpy (tag_str, entity, 4);
13108   GST_DEBUG_OBJECT (qtdemux, "classification info: %s", tag_str);
13109
13110   gst_tag_list_add (taglist, GST_TAG_MERGE_APPEND, tag, tag_str, NULL);
13111
13112   g_free (tag_str);
13113
13114   return;
13115
13116   /* ERRORS */
13117 short_read:
13118   {
13119     GST_DEBUG_OBJECT (qtdemux, "short read parsing 3GP classification");
13120     return;
13121   }
13122 }
13123
13124 static gboolean
13125 qtdemux_tag_add_str_full (GstQTDemux * qtdemux, GstTagList * taglist,
13126     const char *tag, const char *dummy, GNode * node)
13127 {
13128   const gchar *env_vars[] = { "GST_QT_TAG_ENCODING", "GST_TAG_ENCODING", NULL };
13129   GNode *data;
13130   char *s;
13131   int len;
13132   guint32 type;
13133   int offset;
13134   gboolean ret = TRUE;
13135   const gchar *charset = NULL;
13136
13137   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
13138   if (data) {
13139     len = QT_UINT32 (data->data);
13140     type = QT_UINT32 ((guint8 *) data->data + 8);
13141     if (type == 0x00000001 && len > 16) {
13142       s = gst_tag_freeform_string_to_utf8 ((char *) data->data + 16, len - 16,
13143           env_vars);
13144       if (s) {
13145         GST_DEBUG_OBJECT (qtdemux, "adding tag %s", GST_STR_NULL (s));
13146         gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag, s, NULL);
13147         g_free (s);
13148       } else {
13149         GST_DEBUG_OBJECT (qtdemux, "failed to convert %s tag to UTF-8", tag);
13150       }
13151     }
13152   } else {
13153     len = QT_UINT32 (node->data);
13154     type = QT_UINT32 ((guint8 *) node->data + 4);
13155     if ((type >> 24) == 0xa9 && len > 8 + 4) {
13156       gint str_len;
13157       gint lang_code;
13158
13159       /* Type starts with the (C) symbol, so the next data is a list
13160        * of (string size(16), language code(16), string) */
13161
13162       str_len = QT_UINT16 ((guint8 *) node->data + 8);
13163       lang_code = QT_UINT16 ((guint8 *) node->data + 10);
13164
13165       /* the string + fourcc + size + 2 16bit fields,
13166        * means that there are more tags in this atom */
13167       if (len > str_len + 8 + 4) {
13168         /* TODO how to represent the same tag in different languages? */
13169         GST_WARNING_OBJECT (qtdemux, "Ignoring metadata entry with multiple "
13170             "text alternatives, reading only first one");
13171       }
13172
13173       offset = 12;
13174       len = MIN (len, str_len + 8 + 4); /* remove trailing strings that we don't use */
13175       GST_DEBUG_OBJECT (qtdemux, "found international text tag");
13176
13177       if (lang_code < 0x800) {  /* MAC encoded string */
13178         charset = "mac";
13179       }
13180     } else if (len > 14 && qtdemux_is_string_tag_3gp (qtdemux,
13181             QT_FOURCC ((guint8 *) node->data + 4))) {
13182       guint32 type = QT_UINT32 ((guint8 *) node->data + 8);
13183
13184       /* we go for 3GP style encoding if major brands claims so,
13185        * or if no hope for data be ok UTF-8, and compatible 3GP brand present */
13186       if (qtdemux_is_brand_3gp (qtdemux, TRUE) ||
13187           (qtdemux_is_brand_3gp (qtdemux, FALSE) &&
13188               ((type & 0x00FFFFFF) == 0x0) && (type >> 24 <= 0xF))) {
13189         offset = 14;
13190         /* 16-bit Language code is ignored here as well */
13191         GST_DEBUG_OBJECT (qtdemux, "found 3gpp text tag");
13192       } else {
13193         goto normal;
13194       }
13195     } else {
13196     normal:
13197       offset = 8;
13198       GST_DEBUG_OBJECT (qtdemux, "found normal text tag");
13199       ret = FALSE;              /* may have to fallback */
13200     }
13201     if (charset) {
13202       GError *err = NULL;
13203
13204       s = g_convert ((gchar *) node->data + offset, len - offset, "utf8",
13205           charset, NULL, NULL, &err);
13206       if (err) {
13207         GST_DEBUG_OBJECT (qtdemux, "Failed to convert string from charset %s:"
13208             " %s(%d): %s", charset, g_quark_to_string (err->domain), err->code,
13209             err->message);
13210         g_error_free (err);
13211       }
13212     } else {
13213       s = gst_tag_freeform_string_to_utf8 ((char *) node->data + offset,
13214           len - offset, env_vars);
13215     }
13216     if (s) {
13217       GST_DEBUG_OBJECT (qtdemux, "adding tag %s", GST_STR_NULL (s));
13218       gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag, s, NULL);
13219       g_free (s);
13220       ret = TRUE;
13221     } else {
13222       GST_DEBUG_OBJECT (qtdemux, "failed to convert %s tag to UTF-8", tag);
13223     }
13224   }
13225   return ret;
13226 }
13227
13228 static void
13229 qtdemux_tag_add_str (GstQTDemux * qtdemux, GstTagList * taglist,
13230     const char *tag, const char *dummy, GNode * node)
13231 {
13232   qtdemux_tag_add_str_full (qtdemux, taglist, tag, dummy, node);
13233 }
13234
13235 static void
13236 qtdemux_tag_add_keywords (GstQTDemux * qtdemux, GstTagList * taglist,
13237     const char *tag, const char *dummy, GNode * node)
13238 {
13239   const gchar *env_vars[] = { "GST_QT_TAG_ENCODING", "GST_TAG_ENCODING", NULL };
13240   guint8 *data;
13241   char *s, *t, *k = NULL;
13242   int len;
13243   int offset;
13244   int count;
13245
13246   /* first try normal string tag if major brand not 3GP */
13247   if (!qtdemux_is_brand_3gp (qtdemux, TRUE)) {
13248     if (!qtdemux_tag_add_str_full (qtdemux, taglist, tag, dummy, node)) {
13249       /* hm, that did not work, maybe 3gpp storage in non-3gpp major brand;
13250        * let's try it 3gpp way after minor safety check */
13251       data = node->data;
13252       if (QT_UINT32 (data) < 15 || !qtdemux_is_brand_3gp (qtdemux, FALSE))
13253         return;
13254     } else
13255       return;
13256   }
13257
13258   GST_DEBUG_OBJECT (qtdemux, "found 3gpp keyword tag");
13259
13260   data = node->data;
13261
13262   len = QT_UINT32 (data);
13263   if (len < 15)
13264     goto short_read;
13265
13266   count = QT_UINT8 (data + 14);
13267   offset = 15;
13268   for (; count; count--) {
13269     gint slen;
13270
13271     if (offset + 1 > len)
13272       goto short_read;
13273     slen = QT_UINT8 (data + offset);
13274     offset += 1;
13275     if (offset + slen > len)
13276       goto short_read;
13277     s = gst_tag_freeform_string_to_utf8 ((char *) node->data + offset,
13278         slen, env_vars);
13279     if (s) {
13280       GST_DEBUG_OBJECT (qtdemux, "adding keyword %s", GST_STR_NULL (s));
13281       if (k) {
13282         t = g_strjoin (",", k, s, NULL);
13283         g_free (s);
13284         g_free (k);
13285         k = t;
13286       } else {
13287         k = s;
13288       }
13289     } else {
13290       GST_DEBUG_OBJECT (qtdemux, "failed to convert keyword to UTF-8");
13291     }
13292     offset += slen;
13293   }
13294
13295 done:
13296   if (k) {
13297     GST_DEBUG_OBJECT (qtdemux, "adding tag %s", GST_STR_NULL (k));
13298     gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag, k, NULL);
13299   }
13300   g_free (k);
13301
13302   return;
13303
13304   /* ERRORS */
13305 short_read:
13306   {
13307     GST_DEBUG_OBJECT (qtdemux, "short read parsing 3GP keywords");
13308     goto done;
13309   }
13310 }
13311
13312 static void
13313 qtdemux_tag_add_num (GstQTDemux * qtdemux, GstTagList * taglist,
13314     const char *tag1, const char *tag2, GNode * node)
13315 {
13316   GNode *data;
13317   int len;
13318   int type;
13319   int n1, n2;
13320
13321   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
13322   if (data) {
13323     len = QT_UINT32 (data->data);
13324     type = QT_UINT32 ((guint8 *) data->data + 8);
13325     if (type == 0x00000000 && len >= 22) {
13326       n1 = QT_UINT16 ((guint8 *) data->data + 18);
13327       n2 = QT_UINT16 ((guint8 *) data->data + 20);
13328       if (n1 > 0) {
13329         GST_DEBUG_OBJECT (qtdemux, "adding tag %s=%d", tag1, n1);
13330         gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag1, n1, NULL);
13331       }
13332       if (n2 > 0) {
13333         GST_DEBUG_OBJECT (qtdemux, "adding tag %s=%d", tag2, n2);
13334         gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag2, n2, NULL);
13335       }
13336     }
13337   }
13338 }
13339
13340 static void
13341 qtdemux_tag_add_tmpo (GstQTDemux * qtdemux, GstTagList * taglist,
13342     const char *tag1, const char *dummy, GNode * node)
13343 {
13344   GNode *data;
13345   int len;
13346   int type;
13347   int n1;
13348
13349   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
13350   if (data) {
13351     len = QT_UINT32 (data->data);
13352     type = QT_UINT32 ((guint8 *) data->data + 8);
13353     GST_DEBUG_OBJECT (qtdemux, "have tempo tag, type=%d,len=%d", type, len);
13354     /* some files wrongly have a type 0x0f=15, but it should be 0x15 */
13355     if ((type == 0x00000015 || type == 0x0000000f) && len >= 18) {
13356       n1 = QT_UINT16 ((guint8 *) data->data + 16);
13357       if (n1) {
13358         /* do not add bpm=0 */
13359         GST_DEBUG_OBJECT (qtdemux, "adding tag %d", n1);
13360         gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag1, (gdouble) n1,
13361             NULL);
13362       }
13363     }
13364   }
13365 }
13366
13367 static void
13368 qtdemux_tag_add_uint32 (GstQTDemux * qtdemux, GstTagList * taglist,
13369     const char *tag1, const char *dummy, GNode * node)
13370 {
13371   GNode *data;
13372   int len;
13373   int type;
13374   guint32 num;
13375
13376   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
13377   if (data) {
13378     len = QT_UINT32 (data->data);
13379     type = QT_UINT32 ((guint8 *) data->data + 8);
13380     GST_DEBUG_OBJECT (qtdemux, "have %s tag, type=%d,len=%d", tag1, type, len);
13381     /* some files wrongly have a type 0x0f=15, but it should be 0x15 */
13382     if ((type == 0x00000015 || type == 0x0000000f) && len >= 20) {
13383       num = QT_UINT32 ((guint8 *) data->data + 16);
13384       if (num) {
13385         /* do not add num=0 */
13386         GST_DEBUG_OBJECT (qtdemux, "adding tag %d", num);
13387         gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag1, num, NULL);
13388       }
13389     }
13390   }
13391 }
13392
13393 static void
13394 qtdemux_tag_add_covr (GstQTDemux * qtdemux, GstTagList * taglist,
13395     const char *tag1, const char *dummy, GNode * node)
13396 {
13397   GNode *data;
13398   int len;
13399   int type;
13400   GstSample *sample;
13401
13402   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
13403   if (data) {
13404     len = QT_UINT32 (data->data);
13405     type = QT_UINT32 ((guint8 *) data->data + 8);
13406     GST_DEBUG_OBJECT (qtdemux, "have covr tag, type=%d,len=%d", type, len);
13407     if ((type == 0x0000000d || type == 0x0000000e) && len > 16) {
13408       GstTagImageType image_type;
13409
13410       if (gst_tag_list_get_tag_size (taglist, GST_TAG_IMAGE) == 0)
13411         image_type = GST_TAG_IMAGE_TYPE_FRONT_COVER;
13412       else
13413         image_type = GST_TAG_IMAGE_TYPE_NONE;
13414
13415       if ((sample =
13416               gst_tag_image_data_to_image_sample ((guint8 *) data->data + 16,
13417                   len - 16, image_type))) {
13418         GST_DEBUG_OBJECT (qtdemux, "adding tag size %d", len - 16);
13419         gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag1, sample, NULL);
13420         gst_sample_unref (sample);
13421       }
13422     }
13423   }
13424 }
13425
13426 static void
13427 qtdemux_tag_add_date (GstQTDemux * qtdemux, GstTagList * taglist,
13428     const char *tag, const char *dummy, GNode * node)
13429 {
13430   GNode *data;
13431   GstDateTime *datetime = NULL;
13432   char *s;
13433   int len;
13434   int type;
13435
13436   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
13437   if (data) {
13438     len = QT_UINT32 (data->data);
13439     type = QT_UINT32 ((guint8 *) data->data + 8);
13440     if (type == 0x00000001 && len > 16) {
13441       guint y, m = 1, d = 1;
13442       gint ret;
13443
13444       s = g_strndup ((char *) data->data + 16, len - 16);
13445       GST_DEBUG_OBJECT (qtdemux, "adding date '%s'", s);
13446       datetime = gst_date_time_new_from_iso8601_string (s);
13447       if (datetime != NULL) {
13448         gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, GST_TAG_DATE_TIME,
13449             datetime, NULL);
13450         gst_date_time_unref (datetime);
13451       }
13452
13453       ret = sscanf (s, "%u-%u-%u", &y, &m, &d);
13454       if (ret >= 1 && y > 1500 && y < 3000) {
13455         GDate *date;
13456
13457         date = g_date_new_dmy (d, m, y);
13458         gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag, date, NULL);
13459         g_date_free (date);
13460       } else {
13461         GST_DEBUG_OBJECT (qtdemux, "could not parse date string '%s'", s);
13462       }
13463       g_free (s);
13464     }
13465   }
13466 }
13467
13468 static void
13469 qtdemux_tag_add_gnre (GstQTDemux * qtdemux, GstTagList * taglist,
13470     const char *tag, const char *dummy, GNode * node)
13471 {
13472   GNode *data;
13473
13474   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
13475
13476   /* re-route to normal string tag if major brand says so
13477    * or no data atom and compatible brand suggests so */
13478   if (qtdemux_is_brand_3gp (qtdemux, TRUE) ||
13479       (qtdemux_is_brand_3gp (qtdemux, FALSE) && !data)) {
13480     qtdemux_tag_add_str (qtdemux, taglist, tag, dummy, node);
13481     return;
13482   }
13483
13484   if (data) {
13485     guint len, type, n;
13486
13487     len = QT_UINT32 (data->data);
13488     type = QT_UINT32 ((guint8 *) data->data + 8);
13489     if (type == 0x00000000 && len >= 18) {
13490       n = QT_UINT16 ((guint8 *) data->data + 16);
13491       if (n > 0) {
13492         const gchar *genre;
13493
13494         genre = gst_tag_id3_genre_get (n - 1);
13495         if (genre != NULL) {
13496           GST_DEBUG_OBJECT (qtdemux, "adding %d [%s]", n, genre);
13497           gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag, genre, NULL);
13498         }
13499       }
13500     }
13501   }
13502 }
13503
13504 static void
13505 qtdemux_add_double_tag_from_str (GstQTDemux * demux, GstTagList * taglist,
13506     const gchar * tag, guint8 * data, guint32 datasize)
13507 {
13508   gdouble value;
13509   gchar *datacopy;
13510
13511   /* make a copy to have \0 at the end */
13512   datacopy = g_strndup ((gchar *) data, datasize);
13513
13514   /* convert the str to double */
13515   if (sscanf (datacopy, "%lf", &value) == 1) {
13516     GST_DEBUG_OBJECT (demux, "adding tag: %s [%s]", tag, datacopy);
13517     gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag, value, NULL);
13518   } else {
13519     GST_WARNING_OBJECT (demux, "Failed to parse double from string: %s",
13520         datacopy);
13521   }
13522   g_free (datacopy);
13523 }
13524
13525
13526 static void
13527 qtdemux_tag_add_revdns (GstQTDemux * demux, GstTagList * taglist,
13528     const char *tag, const char *tag_bis, GNode * node)
13529 {
13530   GNode *mean;
13531   GNode *name;
13532   GNode *data;
13533   guint32 meansize;
13534   guint32 namesize;
13535   guint32 datatype;
13536   guint32 datasize;
13537   const gchar *meanstr;
13538   const gchar *namestr;
13539
13540   /* checking the whole ---- atom size for consistency */
13541   if (QT_UINT32 (node->data) <= 4 + 12 + 12 + 16) {
13542     GST_WARNING_OBJECT (demux, "Tag ---- atom is too small, ignoring");
13543     return;
13544   }
13545
13546   mean = qtdemux_tree_get_child_by_type (node, FOURCC_mean);
13547   if (!mean) {
13548     GST_WARNING_OBJECT (demux, "No 'mean' atom found");
13549     return;
13550   }
13551
13552   meansize = QT_UINT32 (mean->data);
13553   if (meansize <= 12) {
13554     GST_WARNING_OBJECT (demux, "Small mean atom, ignoring the whole tag");
13555     return;
13556   }
13557   meanstr = ((gchar *) mean->data) + 12;
13558   meansize -= 12;
13559
13560   name = qtdemux_tree_get_child_by_type (node, FOURCC_name);
13561   if (!name) {
13562     GST_WARNING_OBJECT (demux, "'name' atom not found, ignoring tag");
13563     return;
13564   }
13565
13566   namesize = QT_UINT32 (name->data);
13567   if (namesize <= 12) {
13568     GST_WARNING_OBJECT (demux, "'name' atom is too small, ignoring tag");
13569     return;
13570   }
13571   namestr = ((gchar *) name->data) + 12;
13572   namesize -= 12;
13573
13574   /*
13575    * Data atom is:
13576    * uint32 - size
13577    * uint32 - name
13578    * uint8  - version
13579    * uint24 - data type
13580    * uint32 - all 0
13581    * rest   - the data
13582    */
13583   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
13584   if (!data) {
13585     GST_WARNING_OBJECT (demux, "No data atom in this tag");
13586     return;
13587   }
13588   datasize = QT_UINT32 (data->data);
13589   if (datasize <= 16) {
13590     GST_WARNING_OBJECT (demux, "Data atom too small");
13591     return;
13592   }
13593   datatype = QT_UINT32 (((gchar *) data->data) + 8) & 0xFFFFFF;
13594
13595   if ((strncmp (meanstr, "com.apple.iTunes", meansize) == 0) ||
13596       (strncmp (meanstr, "org.hydrogenaudio.replaygain", meansize) == 0)) {
13597     static const struct
13598     {
13599       const gchar name[28];
13600       const gchar tag[28];
13601     } tags[] = {
13602       {
13603       "replaygain_track_gain", GST_TAG_TRACK_GAIN}, {
13604       "replaygain_track_peak", GST_TAG_TRACK_PEAK}, {
13605       "replaygain_album_gain", GST_TAG_ALBUM_GAIN}, {
13606       "replaygain_album_peak", GST_TAG_ALBUM_PEAK}, {
13607       "MusicBrainz Track Id", GST_TAG_MUSICBRAINZ_TRACKID}, {
13608       "MusicBrainz Artist Id", GST_TAG_MUSICBRAINZ_ARTISTID}, {
13609       "MusicBrainz Album Id", GST_TAG_MUSICBRAINZ_ALBUMID}, {
13610       "MusicBrainz Album Artist Id", GST_TAG_MUSICBRAINZ_ALBUMARTISTID}
13611     };
13612     int i;
13613
13614     for (i = 0; i < G_N_ELEMENTS (tags); ++i) {
13615       if (!g_ascii_strncasecmp (tags[i].name, namestr, namesize)) {
13616         switch (gst_tag_get_type (tags[i].tag)) {
13617           case G_TYPE_DOUBLE:
13618             qtdemux_add_double_tag_from_str (demux, taglist, tags[i].tag,
13619                 ((guint8 *) data->data) + 16, datasize - 16);
13620             break;
13621           case G_TYPE_STRING:
13622             qtdemux_tag_add_str (demux, taglist, tags[i].tag, NULL, node);
13623             break;
13624           default:
13625             /* not reached */
13626             break;
13627         }
13628         break;
13629       }
13630     }
13631     if (i == G_N_ELEMENTS (tags))
13632       goto unknown_tag;
13633   } else {
13634     goto unknown_tag;
13635   }
13636
13637   return;
13638
13639 /* errors */
13640 unknown_tag:
13641 #ifndef GST_DISABLE_GST_DEBUG
13642   {
13643     gchar *namestr_dbg;
13644     gchar *meanstr_dbg;
13645
13646     meanstr_dbg = g_strndup (meanstr, meansize);
13647     namestr_dbg = g_strndup (namestr, namesize);
13648
13649     GST_WARNING_OBJECT (demux, "This tag %s:%s type:%u is not mapped, "
13650         "file a bug at bugzilla.gnome.org", meanstr_dbg, namestr_dbg, datatype);
13651
13652     g_free (namestr_dbg);
13653     g_free (meanstr_dbg);
13654   }
13655 #endif
13656   return;
13657 }
13658
13659 static void
13660 qtdemux_tag_add_id32 (GstQTDemux * demux, GstTagList * taglist, const char *tag,
13661     const char *tag_bis, GNode * node)
13662 {
13663   guint8 *data;
13664   GstBuffer *buf;
13665   guint len;
13666   GstTagList *id32_taglist = NULL;
13667
13668   GST_LOG_OBJECT (demux, "parsing ID32");
13669
13670   data = node->data;
13671   len = GST_READ_UINT32_BE (data);
13672
13673   /* need at least full box and language tag */
13674   if (len < 12 + 2)
13675     return;
13676
13677   buf = gst_buffer_new_allocate (NULL, len - 14, NULL);
13678   gst_buffer_fill (buf, 0, data + 14, len - 14);
13679
13680   id32_taglist = gst_tag_list_from_id3v2_tag (buf);
13681   if (id32_taglist) {
13682     GST_LOG_OBJECT (demux, "parsing ok");
13683     gst_tag_list_insert (taglist, id32_taglist, GST_TAG_MERGE_KEEP);
13684     gst_tag_list_unref (id32_taglist);
13685   } else {
13686     GST_LOG_OBJECT (demux, "parsing failed");
13687   }
13688
13689   gst_buffer_unref (buf);
13690 }
13691
13692 typedef void (*GstQTDemuxAddTagFunc) (GstQTDemux * demux, GstTagList * taglist,
13693     const char *tag, const char *tag_bis, GNode * node);
13694
13695 /* unmapped tags
13696 FOURCC_pcst -> if media is a podcast -> bool
13697 FOURCC_cpil -> if media is part of a compilation -> bool
13698 FOURCC_pgap -> if media is part of a gapless context -> bool
13699 FOURCC_tven -> the tv episode id e.g. S01E23 -> str
13700 */
13701
13702 static const struct
13703 {
13704   guint32 fourcc;
13705   const gchar *gst_tag;
13706   const gchar *gst_tag_bis;
13707   const GstQTDemuxAddTagFunc func;
13708 } add_funcs[] = {
13709   {
13710   FOURCC__nam, GST_TAG_TITLE, NULL, qtdemux_tag_add_str}, {
13711   FOURCC_titl, GST_TAG_TITLE, NULL, qtdemux_tag_add_str}, {
13712   FOURCC__grp, GST_TAG_GROUPING, NULL, qtdemux_tag_add_str}, {
13713   FOURCC__wrt, GST_TAG_COMPOSER, NULL, qtdemux_tag_add_str}, {
13714   FOURCC__ART, GST_TAG_ARTIST, NULL, qtdemux_tag_add_str}, {
13715   FOURCC_aART, GST_TAG_ALBUM_ARTIST, NULL, qtdemux_tag_add_str}, {
13716   FOURCC_perf, GST_TAG_ARTIST, NULL, qtdemux_tag_add_str}, {
13717   FOURCC_auth, GST_TAG_COMPOSER, NULL, qtdemux_tag_add_str}, {
13718   FOURCC__alb, GST_TAG_ALBUM, NULL, qtdemux_tag_add_str}, {
13719   FOURCC_albm, GST_TAG_ALBUM, NULL, qtdemux_tag_add_str}, {
13720   FOURCC_cprt, GST_TAG_COPYRIGHT, NULL, qtdemux_tag_add_str}, {
13721   FOURCC__cpy, GST_TAG_COPYRIGHT, NULL, qtdemux_tag_add_str}, {
13722   FOURCC__cmt, GST_TAG_COMMENT, NULL, qtdemux_tag_add_str}, {
13723   FOURCC__des, GST_TAG_DESCRIPTION, NULL, qtdemux_tag_add_str}, {
13724   FOURCC_desc, GST_TAG_DESCRIPTION, NULL, qtdemux_tag_add_str}, {
13725   FOURCC_dscp, GST_TAG_DESCRIPTION, NULL, qtdemux_tag_add_str}, {
13726   FOURCC__lyr, GST_TAG_LYRICS, NULL, qtdemux_tag_add_str}, {
13727   FOURCC__day, GST_TAG_DATE, NULL, qtdemux_tag_add_date}, {
13728   FOURCC_yrrc, GST_TAG_DATE, NULL, qtdemux_tag_add_year}, {
13729   FOURCC__too, GST_TAG_ENCODER, NULL, qtdemux_tag_add_str}, {
13730   FOURCC__inf, GST_TAG_COMMENT, NULL, qtdemux_tag_add_str}, {
13731   FOURCC_trkn, GST_TAG_TRACK_NUMBER, GST_TAG_TRACK_COUNT, qtdemux_tag_add_num}, {
13732   FOURCC_disk, GST_TAG_ALBUM_VOLUME_NUMBER, GST_TAG_ALBUM_VOLUME_COUNT,
13733         qtdemux_tag_add_num}, {
13734   FOURCC_disc, GST_TAG_ALBUM_VOLUME_NUMBER, GST_TAG_ALBUM_VOLUME_COUNT,
13735         qtdemux_tag_add_num}, {
13736   FOURCC__gen, GST_TAG_GENRE, NULL, qtdemux_tag_add_str}, {
13737   FOURCC_gnre, GST_TAG_GENRE, NULL, qtdemux_tag_add_gnre}, {
13738   FOURCC_tmpo, GST_TAG_BEATS_PER_MINUTE, NULL, qtdemux_tag_add_tmpo}, {
13739   FOURCC_covr, GST_TAG_IMAGE, NULL, qtdemux_tag_add_covr}, {
13740   FOURCC_sonm, GST_TAG_TITLE_SORTNAME, NULL, qtdemux_tag_add_str}, {
13741   FOURCC_soal, GST_TAG_ALBUM_SORTNAME, NULL, qtdemux_tag_add_str}, {
13742   FOURCC_soar, GST_TAG_ARTIST_SORTNAME, NULL, qtdemux_tag_add_str}, {
13743   FOURCC_soaa, GST_TAG_ALBUM_ARTIST_SORTNAME, NULL, qtdemux_tag_add_str}, {
13744   FOURCC_soco, GST_TAG_COMPOSER_SORTNAME, NULL, qtdemux_tag_add_str}, {
13745   FOURCC_sosn, GST_TAG_SHOW_SORTNAME, NULL, qtdemux_tag_add_str}, {
13746   FOURCC_tvsh, GST_TAG_SHOW_NAME, NULL, qtdemux_tag_add_str}, {
13747   FOURCC_tvsn, GST_TAG_SHOW_SEASON_NUMBER, NULL, qtdemux_tag_add_uint32}, {
13748   FOURCC_tves, GST_TAG_SHOW_EPISODE_NUMBER, NULL, qtdemux_tag_add_uint32}, {
13749   FOURCC_kywd, GST_TAG_KEYWORDS, NULL, qtdemux_tag_add_keywords}, {
13750   FOURCC_keyw, GST_TAG_KEYWORDS, NULL, qtdemux_tag_add_str}, {
13751   FOURCC__enc, GST_TAG_ENCODER, NULL, qtdemux_tag_add_str}, {
13752   FOURCC_loci, GST_TAG_GEO_LOCATION_NAME, NULL, qtdemux_tag_add_location}, {
13753   FOURCC_clsf, GST_QT_DEMUX_CLASSIFICATION_TAG, NULL,
13754         qtdemux_tag_add_classification}, {
13755   FOURCC__mak, GST_TAG_DEVICE_MANUFACTURER, NULL, qtdemux_tag_add_str}, {
13756   FOURCC__mod, GST_TAG_DEVICE_MODEL, NULL, qtdemux_tag_add_str}, {
13757   FOURCC__swr, GST_TAG_APPLICATION_NAME, NULL, qtdemux_tag_add_str}, {
13758
13759     /* This is a special case, some tags are stored in this
13760      * 'reverse dns naming', according to:
13761      * http://atomicparsley.sourceforge.net/mpeg-4files.html and
13762      * bug #614471
13763      */
13764   FOURCC_____, "", NULL, qtdemux_tag_add_revdns}, {
13765     /* see http://www.mp4ra.org/specs.html for ID32 in meta box */
13766   FOURCC_ID32, "", NULL, qtdemux_tag_add_id32}
13767 };
13768
13769 struct _GstQtDemuxTagList
13770 {
13771   GstQTDemux *demux;
13772   GstTagList *taglist;
13773 };
13774 typedef struct _GstQtDemuxTagList GstQtDemuxTagList;
13775
13776 static void
13777 qtdemux_tag_add_blob (GNode * node, GstQtDemuxTagList * qtdemuxtaglist)
13778 {
13779   gint len;
13780   guint8 *data;
13781   GstBuffer *buf;
13782   gchar *media_type;
13783   const gchar *style;
13784   GstSample *sample;
13785   GstStructure *s;
13786   guint i;
13787   guint8 ndata[4];
13788   GstQTDemux *demux = qtdemuxtaglist->demux;
13789   GstTagList *taglist = qtdemuxtaglist->taglist;
13790
13791   data = node->data;
13792   len = QT_UINT32 (data);
13793   buf = gst_buffer_new_and_alloc (len);
13794   gst_buffer_fill (buf, 0, data, len);
13795
13796   /* heuristic to determine style of tag */
13797   if (QT_FOURCC (data + 4) == FOURCC_____ ||
13798       (len > 8 + 12 && QT_FOURCC (data + 12) == FOURCC_data))
13799     style = "itunes";
13800   else if (demux->major_brand == FOURCC_qt__)
13801     style = "quicktime";
13802   /* fall back to assuming iso/3gp tag style */
13803   else
13804     style = "iso";
13805
13806   /* santize the name for the caps. */
13807   for (i = 0; i < 4; i++) {
13808     guint8 d = data[4 + i];
13809     if (g_ascii_isalnum (d))
13810       ndata[i] = g_ascii_tolower (d);
13811     else
13812       ndata[i] = '_';
13813   }
13814
13815   media_type = g_strdup_printf ("application/x-gst-qt-%c%c%c%c-tag",
13816       ndata[0], ndata[1], ndata[2], ndata[3]);
13817   GST_DEBUG_OBJECT (demux, "media type %s", media_type);
13818
13819   s = gst_structure_new (media_type, "style", G_TYPE_STRING, style, NULL);
13820   sample = gst_sample_new (buf, NULL, NULL, s);
13821   gst_buffer_unref (buf);
13822   g_free (media_type);
13823
13824   GST_DEBUG_OBJECT (demux, "adding private tag; size %d, info %" GST_PTR_FORMAT,
13825       len, s);
13826
13827   gst_tag_list_add (taglist, GST_TAG_MERGE_APPEND,
13828       GST_QT_DEMUX_PRIVATE_TAG, sample, NULL);
13829
13830   gst_sample_unref (sample);
13831 }
13832
13833 static void
13834 qtdemux_parse_udta (GstQTDemux * qtdemux, GstTagList * taglist, GNode * udta)
13835 {
13836   GNode *meta;
13837   GNode *ilst;
13838   GNode *xmp_;
13839   GNode *node;
13840   gint i;
13841   GstQtDemuxTagList demuxtaglist;
13842
13843   demuxtaglist.demux = qtdemux;
13844   demuxtaglist.taglist = taglist;
13845
13846   meta = qtdemux_tree_get_child_by_type (udta, FOURCC_meta);
13847   if (meta != NULL) {
13848     ilst = qtdemux_tree_get_child_by_type (meta, FOURCC_ilst);
13849     if (ilst == NULL) {
13850       GST_LOG_OBJECT (qtdemux, "no ilst");
13851       return;
13852     }
13853   } else {
13854     ilst = udta;
13855     GST_LOG_OBJECT (qtdemux, "no meta so using udta itself");
13856   }
13857
13858   i = 0;
13859   while (i < G_N_ELEMENTS (add_funcs)) {
13860     node = qtdemux_tree_get_child_by_type (ilst, add_funcs[i].fourcc);
13861     if (node) {
13862       gint len;
13863
13864       len = QT_UINT32 (node->data);
13865       if (len < 12) {
13866         GST_DEBUG_OBJECT (qtdemux, "too small tag atom %" GST_FOURCC_FORMAT,
13867             GST_FOURCC_ARGS (add_funcs[i].fourcc));
13868       } else {
13869         add_funcs[i].func (qtdemux, taglist, add_funcs[i].gst_tag,
13870             add_funcs[i].gst_tag_bis, node);
13871       }
13872       g_node_destroy (node);
13873     } else {
13874       i++;
13875     }
13876   }
13877
13878   /* parsed nodes have been removed, pass along remainder as blob */
13879   g_node_children_foreach (ilst, G_TRAVERSE_ALL,
13880       (GNodeForeachFunc) qtdemux_tag_add_blob, &demuxtaglist);
13881
13882   /* parse up XMP_ node if existing */
13883   xmp_ = qtdemux_tree_get_child_by_type (udta, FOURCC_XMP_);
13884   if (xmp_ != NULL) {
13885     GstBuffer *buf;
13886     GstTagList *xmptaglist;
13887
13888     buf = _gst_buffer_new_wrapped (((guint8 *) xmp_->data) + 8,
13889         QT_UINT32 ((guint8 *) xmp_->data) - 8, NULL);
13890     xmptaglist = gst_tag_list_from_xmp_buffer (buf);
13891     gst_buffer_unref (buf);
13892
13893     qtdemux_handle_xmp_taglist (qtdemux, taglist, xmptaglist);
13894   } else {
13895     GST_DEBUG_OBJECT (qtdemux, "No XMP_ node found");
13896   }
13897 }
13898
13899 typedef struct
13900 {
13901   GstStructure *structure;      /* helper for sort function */
13902   gchar *location;
13903   guint min_req_bitrate;
13904   guint min_req_qt_version;
13905 } GstQtReference;
13906
13907 static gint
13908 qtdemux_redirects_sort_func (gconstpointer a, gconstpointer b)
13909 {
13910   GstQtReference *ref_a = (GstQtReference *) a;
13911   GstQtReference *ref_b = (GstQtReference *) b;
13912
13913   if (ref_b->min_req_qt_version != ref_a->min_req_qt_version)
13914     return ref_b->min_req_qt_version - ref_a->min_req_qt_version;
13915
13916   /* known bitrates go before unknown; higher bitrates go first */
13917   return ref_b->min_req_bitrate - ref_a->min_req_bitrate;
13918 }
13919
13920 /* sort the redirects and post a message for the application.
13921  */
13922 static void
13923 qtdemux_process_redirects (GstQTDemux * qtdemux, GList * references)
13924 {
13925   GstQtReference *best;
13926   GstStructure *s;
13927   GstMessage *msg;
13928   GValue list_val = { 0, };
13929   GList *l;
13930
13931   g_assert (references != NULL);
13932
13933   references = g_list_sort (references, qtdemux_redirects_sort_func);
13934
13935   best = (GstQtReference *) references->data;
13936
13937   g_value_init (&list_val, GST_TYPE_LIST);
13938
13939   for (l = references; l != NULL; l = l->next) {
13940     GstQtReference *ref = (GstQtReference *) l->data;
13941     GValue struct_val = { 0, };
13942
13943     ref->structure = gst_structure_new ("redirect",
13944         "new-location", G_TYPE_STRING, ref->location, NULL);
13945
13946     if (ref->min_req_bitrate > 0) {
13947       gst_structure_set (ref->structure, "minimum-bitrate", G_TYPE_INT,
13948           ref->min_req_bitrate, NULL);
13949     }
13950
13951     g_value_init (&struct_val, GST_TYPE_STRUCTURE);
13952     g_value_set_boxed (&struct_val, ref->structure);
13953     gst_value_list_append_value (&list_val, &struct_val);
13954     g_value_unset (&struct_val);
13955     /* don't free anything here yet, since we need best->structure below */
13956   }
13957
13958   g_assert (best != NULL);
13959   s = gst_structure_copy (best->structure);
13960
13961   if (g_list_length (references) > 1) {
13962     gst_structure_set_value (s, "locations", &list_val);
13963   }
13964
13965   g_value_unset (&list_val);
13966
13967   for (l = references; l != NULL; l = l->next) {
13968     GstQtReference *ref = (GstQtReference *) l->data;
13969
13970     gst_structure_free (ref->structure);
13971     g_free (ref->location);
13972     g_free (ref);
13973   }
13974   g_list_free (references);
13975
13976   GST_INFO_OBJECT (qtdemux, "posting redirect message: %" GST_PTR_FORMAT, s);
13977   msg = gst_message_new_element (GST_OBJECT_CAST (qtdemux), s);
13978   gst_element_post_message (GST_ELEMENT_CAST (qtdemux), msg);
13979   qtdemux->posted_redirect = TRUE;
13980 }
13981
13982 /* look for redirect nodes, collect all redirect information and
13983  * process it.
13984  */
13985 static gboolean
13986 qtdemux_parse_redirects (GstQTDemux * qtdemux)
13987 {
13988   GNode *rmra, *rmda, *rdrf;
13989
13990   rmra = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_rmra);
13991   if (rmra) {
13992     GList *redirects = NULL;
13993
13994     rmda = qtdemux_tree_get_child_by_type (rmra, FOURCC_rmda);
13995     while (rmda) {
13996       GstQtReference ref = { NULL, NULL, 0, 0 };
13997       GNode *rmdr, *rmvc;
13998
13999       if ((rmdr = qtdemux_tree_get_child_by_type (rmda, FOURCC_rmdr))) {
14000         ref.min_req_bitrate = QT_UINT32 ((guint8 *) rmdr->data + 12);
14001         GST_LOG_OBJECT (qtdemux, "data rate atom, required bitrate = %u",
14002             ref.min_req_bitrate);
14003       }
14004
14005       if ((rmvc = qtdemux_tree_get_child_by_type (rmda, FOURCC_rmvc))) {
14006         guint32 package = QT_FOURCC ((guint8 *) rmvc->data + 12);
14007         guint version = QT_UINT32 ((guint8 *) rmvc->data + 16);
14008
14009 #ifndef GST_DISABLE_GST_DEBUG
14010         guint bitmask = QT_UINT32 ((guint8 *) rmvc->data + 20);
14011 #endif
14012         guint check_type = QT_UINT16 ((guint8 *) rmvc->data + 24);
14013
14014         GST_LOG_OBJECT (qtdemux,
14015             "version check atom [%" GST_FOURCC_FORMAT "], version=0x%08x"
14016             ", mask=%08x, check_type=%u", GST_FOURCC_ARGS (package), version,
14017             bitmask, check_type);
14018         if (package == FOURCC_qtim && check_type == 0) {
14019           ref.min_req_qt_version = version;
14020         }
14021       }
14022
14023       rdrf = qtdemux_tree_get_child_by_type (rmda, FOURCC_rdrf);
14024       if (rdrf) {
14025         guint32 ref_type;
14026         guint8 *ref_data;
14027         guint ref_len;
14028
14029         ref_len = QT_UINT32 ((guint8 *) rdrf->data);
14030         if (ref_len > 20) {
14031           ref_type = QT_FOURCC ((guint8 *) rdrf->data + 12);
14032           ref_data = (guint8 *) rdrf->data + 20;
14033           if (ref_type == FOURCC_alis) {
14034             guint record_len, record_version, fn_len;
14035
14036             if (ref_len > 70) {
14037               /* MacOSX alias record, google for alias-layout.txt */
14038               record_len = QT_UINT16 (ref_data + 4);
14039               record_version = QT_UINT16 (ref_data + 4 + 2);
14040               fn_len = QT_UINT8 (ref_data + 50);
14041               if (record_len > 50 && record_version == 2 && fn_len > 0) {
14042                 ref.location = g_strndup ((gchar *) ref_data + 51, fn_len);
14043               }
14044             } else {
14045               GST_WARNING_OBJECT (qtdemux, "Invalid rdrf/alis size (%u < 70)",
14046                   ref_len);
14047             }
14048           } else if (ref_type == FOURCC_url_) {
14049             ref.location = g_strndup ((gchar *) ref_data, ref_len - 8);
14050           } else {
14051             GST_DEBUG_OBJECT (qtdemux,
14052                 "unknown rdrf reference type %" GST_FOURCC_FORMAT,
14053                 GST_FOURCC_ARGS (ref_type));
14054           }
14055           if (ref.location != NULL) {
14056             GST_INFO_OBJECT (qtdemux, "New location: %s", ref.location);
14057             redirects =
14058                 g_list_prepend (redirects, g_memdup (&ref, sizeof (ref)));
14059           } else {
14060             GST_WARNING_OBJECT (qtdemux,
14061                 "Failed to extract redirect location from rdrf atom");
14062           }
14063         } else {
14064           GST_WARNING_OBJECT (qtdemux, "Invalid rdrf size (%u < 20)", ref_len);
14065         }
14066       }
14067
14068       /* look for others */
14069       rmda = qtdemux_tree_get_sibling_by_type (rmda, FOURCC_rmda);
14070     }
14071
14072     if (redirects != NULL) {
14073       qtdemux_process_redirects (qtdemux, redirects);
14074     }
14075   }
14076   return TRUE;
14077 }
14078
14079 static GstTagList *
14080 qtdemux_add_container_format (GstQTDemux * qtdemux, GstTagList * tags)
14081 {
14082   const gchar *fmt;
14083
14084   if (tags == NULL) {
14085     tags = gst_tag_list_new_empty ();
14086     gst_tag_list_set_scope (tags, GST_TAG_SCOPE_GLOBAL);
14087   }
14088
14089   if (qtdemux->major_brand == FOURCC_mjp2)
14090     fmt = "Motion JPEG 2000";
14091   else if ((qtdemux->major_brand & 0xffff) == FOURCC_3g__)
14092     fmt = "3GP";
14093   else if (qtdemux->major_brand == FOURCC_qt__)
14094     fmt = "Quicktime";
14095   else if (qtdemux->fragmented)
14096     fmt = "ISO fMP4";
14097   else
14098     fmt = "ISO MP4/M4A";
14099
14100   GST_LOG_OBJECT (qtdemux, "mapped %" GST_FOURCC_FORMAT " to '%s'",
14101       GST_FOURCC_ARGS (qtdemux->major_brand), fmt);
14102
14103   gst_tag_list_add (tags, GST_TAG_MERGE_REPLACE, GST_TAG_CONTAINER_FORMAT,
14104       fmt, NULL);
14105
14106   return tags;
14107 }
14108
14109 /* we have read the complete moov node now.
14110  * This function parses all of the relevant info, creates the traks and
14111  * prepares all data structures for playback
14112  */
14113 static gboolean
14114 qtdemux_parse_tree (GstQTDemux * qtdemux)
14115 {
14116   GNode *mvhd;
14117   GNode *trak;
14118   GNode *udta;
14119   GNode *mvex;
14120   GNode *pssh;
14121   guint64 creation_time;
14122   GstDateTime *datetime = NULL;
14123   gint version;
14124
14125   /* make sure we have a usable taglist */
14126   qtdemux->tag_list = gst_tag_list_make_writable (qtdemux->tag_list);
14127
14128   mvhd = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_mvhd);
14129   if (mvhd == NULL) {
14130     GST_LOG_OBJECT (qtdemux, "No mvhd node found, looking for redirects.");
14131     return qtdemux_parse_redirects (qtdemux);
14132   }
14133
14134   version = QT_UINT8 ((guint8 *) mvhd->data + 8);
14135   if (version == 1) {
14136     creation_time = QT_UINT64 ((guint8 *) mvhd->data + 12);
14137     qtdemux->timescale = QT_UINT32 ((guint8 *) mvhd->data + 28);
14138     qtdemux->duration = QT_UINT64 ((guint8 *) mvhd->data + 32);
14139   } else if (version == 0) {
14140     creation_time = QT_UINT32 ((guint8 *) mvhd->data + 12);
14141     qtdemux->timescale = QT_UINT32 ((guint8 *) mvhd->data + 20);
14142     qtdemux->duration = QT_UINT32 ((guint8 *) mvhd->data + 24);
14143   } else {
14144     GST_WARNING_OBJECT (qtdemux, "Unhandled mvhd version %d", version);
14145     return FALSE;
14146   }
14147
14148   /* Moving qt creation time (secs since 1904) to unix time */
14149   if (creation_time != 0) {
14150     /* Try to use epoch first as it should be faster and more commonly found */
14151     if (creation_time >= QTDEMUX_SECONDS_FROM_1904_TO_1970) {
14152       GTimeVal now;
14153
14154       creation_time -= QTDEMUX_SECONDS_FROM_1904_TO_1970;
14155       /* some data cleansing sanity */
14156       g_get_current_time (&now);
14157       if (now.tv_sec + 24 * 3600 < creation_time) {
14158         GST_DEBUG_OBJECT (qtdemux, "discarding bogus future creation time");
14159       } else {
14160         datetime = gst_date_time_new_from_unix_epoch_utc (creation_time);
14161       }
14162     } else {
14163       GDateTime *base_dt = g_date_time_new_utc (1904, 1, 1, 0, 0, 0);
14164       GDateTime *dt, *dt_local;
14165
14166       dt = g_date_time_add_seconds (base_dt, creation_time);
14167       dt_local = g_date_time_to_local (dt);
14168       datetime = gst_date_time_new_from_g_date_time (dt_local);
14169
14170       g_date_time_unref (base_dt);
14171       g_date_time_unref (dt);
14172     }
14173   }
14174   if (datetime) {
14175     /* Use KEEP as explicit tags should have a higher priority than mvhd tag */
14176     gst_tag_list_add (qtdemux->tag_list, GST_TAG_MERGE_KEEP, GST_TAG_DATE_TIME,
14177         datetime, NULL);
14178     gst_date_time_unref (datetime);
14179   }
14180
14181   GST_INFO_OBJECT (qtdemux, "timescale: %u", qtdemux->timescale);
14182   GST_INFO_OBJECT (qtdemux, "duration: %" G_GUINT64_FORMAT, qtdemux->duration);
14183
14184   /* check for fragmented file and get some (default) data */
14185   mvex = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_mvex);
14186   if (mvex) {
14187     GNode *mehd;
14188     GstByteReader mehd_data;
14189
14190     /* let track parsing or anyone know weird stuff might happen ... */
14191     qtdemux->fragmented = TRUE;
14192
14193     /* compensate for total duration */
14194     mehd = qtdemux_tree_get_child_by_type_full (mvex, FOURCC_mehd, &mehd_data);
14195     if (mehd)
14196       qtdemux_parse_mehd (qtdemux, &mehd_data);
14197   }
14198
14199   /* Update the movie segment duration, unless it was directly given to us
14200    * by upstream. Otherwise let it as is, as we don't want to mangle the
14201    * duration provided by upstream that may come e.g. from a MPD file. */
14202   if (!qtdemux->upstream_format_is_time) {
14203     GstClockTime duration;
14204     /* set duration in the segment info */
14205     gst_qtdemux_get_duration (qtdemux, &duration);
14206     qtdemux->segment.duration = duration;
14207     /* also do not exceed duration; stop is set that way post seek anyway,
14208      * and segment activation falls back to duration,
14209      * whereas loop only checks stop, so let's align this here as well */
14210     qtdemux->segment.stop = duration;
14211   }
14212
14213   /* parse all traks */
14214   trak = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_trak);
14215   while (trak) {
14216     qtdemux_parse_trak (qtdemux, trak);
14217     /* iterate all siblings */
14218     trak = qtdemux_tree_get_sibling_by_type (trak, FOURCC_trak);
14219   }
14220
14221   qtdemux->tag_list = gst_tag_list_make_writable (qtdemux->tag_list);
14222
14223   /* find tags */
14224   udta = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_udta);
14225   if (udta) {
14226     qtdemux_parse_udta (qtdemux, qtdemux->tag_list, udta);
14227   } else {
14228     GST_LOG_OBJECT (qtdemux, "No udta node found.");
14229   }
14230
14231   /* maybe also some tags in meta box */
14232   udta = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_meta);
14233   if (udta) {
14234     GST_DEBUG_OBJECT (qtdemux, "Parsing meta box for tags.");
14235     qtdemux_parse_udta (qtdemux, qtdemux->tag_list, udta);
14236   } else {
14237     GST_LOG_OBJECT (qtdemux, "No meta node found.");
14238   }
14239
14240   /* parse any protection system info */
14241   pssh = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_pssh);
14242   while (pssh) {
14243     GST_LOG_OBJECT (qtdemux, "Parsing pssh box.");
14244     qtdemux_parse_pssh (qtdemux, pssh);
14245     pssh = qtdemux_tree_get_sibling_by_type (pssh, FOURCC_pssh);
14246   }
14247
14248   qtdemux->tag_list = qtdemux_add_container_format (qtdemux, qtdemux->tag_list);
14249
14250   return TRUE;
14251 }
14252
14253 /* taken from ffmpeg */
14254 static int
14255 read_descr_size (guint8 * ptr, guint8 * end, guint8 ** end_out)
14256 {
14257   int count = 4;
14258   int len = 0;
14259
14260   while (count--) {
14261     int c;
14262
14263     if (ptr >= end)
14264       return -1;
14265
14266     c = *ptr++;
14267     len = (len << 7) | (c & 0x7f);
14268     if (!(c & 0x80))
14269       break;
14270   }
14271   *end_out = ptr;
14272   return len;
14273 }
14274
14275 static GList *
14276 parse_xiph_stream_headers (GstQTDemux * qtdemux, gpointer codec_data,
14277     gsize codec_data_size)
14278 {
14279   GList *list = NULL;
14280   guint8 *p = codec_data;
14281   gint i, offset, num_packets;
14282   guint *length, last;
14283
14284   GST_MEMDUMP_OBJECT (qtdemux, "xiph codec data", codec_data, codec_data_size);
14285
14286   if (codec_data == NULL || codec_data_size == 0)
14287     goto error;
14288
14289   /* start of the stream and vorbis audio or theora video, need to
14290    * send the codec_priv data as first three packets */
14291   num_packets = p[0] + 1;
14292   GST_DEBUG_OBJECT (qtdemux,
14293       "%u stream headers, total length=%" G_GSIZE_FORMAT " bytes",
14294       (guint) num_packets, codec_data_size);
14295
14296   /* Let's put some limits, Don't think there even is a xiph codec
14297    * with more than 3-4 headers */
14298   if (G_UNLIKELY (num_packets > 16)) {
14299     GST_WARNING_OBJECT (qtdemux,
14300         "Unlikely number of xiph headers, most likely not valid");
14301     goto error;
14302   }
14303
14304   length = g_alloca (num_packets * sizeof (guint));
14305   last = 0;
14306   offset = 1;
14307
14308   /* first packets, read length values */
14309   for (i = 0; i < num_packets - 1; i++) {
14310     length[i] = 0;
14311     while (offset < codec_data_size) {
14312       length[i] += p[offset];
14313       if (p[offset++] != 0xff)
14314         break;
14315     }
14316     last += length[i];
14317   }
14318   if (offset + last > codec_data_size)
14319     goto error;
14320
14321   /* last packet is the remaining size */
14322   length[i] = codec_data_size - offset - last;
14323
14324   for (i = 0; i < num_packets; i++) {
14325     GstBuffer *hdr;
14326
14327     GST_DEBUG_OBJECT (qtdemux, "buffer %d: %u bytes", i, (guint) length[i]);
14328
14329     if (offset + length[i] > codec_data_size)
14330       goto error;
14331
14332     hdr = gst_buffer_new_wrapped (g_memdup (p + offset, length[i]), length[i]);
14333     list = g_list_append (list, hdr);
14334
14335     offset += length[i];
14336   }
14337
14338   return list;
14339
14340   /* ERRORS */
14341 error:
14342   {
14343     if (list != NULL)
14344       g_list_free_full (list, (GDestroyNotify) gst_buffer_unref);
14345     return NULL;
14346   }
14347
14348 }
14349
14350 /* this can change the codec originally present in @list */
14351 static void
14352 gst_qtdemux_handle_esds (GstQTDemux * qtdemux, QtDemuxStream * stream,
14353     QtDemuxStreamStsdEntry * entry, GNode * esds, GstTagList * list)
14354 {
14355   int len = QT_UINT32 (esds->data);
14356   guint8 *ptr = esds->data;
14357   guint8 *end = ptr + len;
14358   int tag;
14359   guint8 *data_ptr = NULL;
14360   int data_len = 0;
14361   guint8 object_type_id = 0;
14362   guint8 stream_type = 0;
14363   const char *codec_name = NULL;
14364   GstCaps *caps = NULL;
14365
14366   GST_MEMDUMP_OBJECT (qtdemux, "esds", ptr, len);
14367   ptr += 8;
14368   GST_DEBUG_OBJECT (qtdemux, "version/flags = %08x", QT_UINT32 (ptr));
14369   ptr += 4;
14370   while (ptr + 1 < end) {
14371     tag = QT_UINT8 (ptr);
14372     GST_DEBUG_OBJECT (qtdemux, "tag = %02x", tag);
14373     ptr++;
14374     len = read_descr_size (ptr, end, &ptr);
14375     GST_DEBUG_OBJECT (qtdemux, "len = %d", len);
14376
14377     /* Check the stated amount of data is available for reading */
14378     if (len < 0 || ptr + len > end)
14379       break;
14380
14381     switch (tag) {
14382       case ES_DESCRIPTOR_TAG:
14383         GST_DEBUG_OBJECT (qtdemux, "ID 0x%04x", QT_UINT16 (ptr));
14384         GST_DEBUG_OBJECT (qtdemux, "priority 0x%04x", QT_UINT8 (ptr + 2));
14385         ptr += 3;
14386         break;
14387       case DECODER_CONFIG_DESC_TAG:{
14388         guint max_bitrate, avg_bitrate;
14389
14390         object_type_id = QT_UINT8 (ptr);
14391         stream_type = QT_UINT8 (ptr + 1) >> 2;
14392         max_bitrate = QT_UINT32 (ptr + 5);
14393         avg_bitrate = QT_UINT32 (ptr + 9);
14394         GST_DEBUG_OBJECT (qtdemux, "object_type_id %02x", object_type_id);
14395         GST_DEBUG_OBJECT (qtdemux, "stream_type %02x", stream_type);
14396         GST_DEBUG_OBJECT (qtdemux, "buffer_size_db %02x", QT_UINT24 (ptr + 2));
14397         GST_DEBUG_OBJECT (qtdemux, "max bitrate %u", max_bitrate);
14398         GST_DEBUG_OBJECT (qtdemux, "avg bitrate %u", avg_bitrate);
14399         if (max_bitrate > 0 && max_bitrate < G_MAXUINT32) {
14400           gst_tag_list_add (list, GST_TAG_MERGE_REPLACE,
14401               GST_TAG_MAXIMUM_BITRATE, max_bitrate, NULL);
14402         }
14403         if (avg_bitrate > 0 && avg_bitrate < G_MAXUINT32) {
14404           gst_tag_list_add (list, GST_TAG_MERGE_REPLACE, GST_TAG_BITRATE,
14405               avg_bitrate, NULL);
14406         }
14407         ptr += 13;
14408         break;
14409       }
14410       case DECODER_SPECIFIC_INFO_TAG:
14411         GST_MEMDUMP_OBJECT (qtdemux, "data", ptr, len);
14412         if (object_type_id == 0xe0 && len == 0x40) {
14413           guint8 *data;
14414           GstStructure *s;
14415           guint32 clut[16];
14416           gint i;
14417
14418           GST_DEBUG_OBJECT (qtdemux,
14419               "Have VOBSUB palette. Creating palette event");
14420           /* move to decConfigDescr data and read palette */
14421           data = ptr;
14422           for (i = 0; i < 16; i++) {
14423             clut[i] = QT_UINT32 (data);
14424             data += 4;
14425           }
14426
14427           s = gst_structure_new ("application/x-gst-dvd", "event",
14428               G_TYPE_STRING, "dvd-spu-clut-change",
14429               "clut00", G_TYPE_INT, clut[0], "clut01", G_TYPE_INT, clut[1],
14430               "clut02", G_TYPE_INT, clut[2], "clut03", G_TYPE_INT, clut[3],
14431               "clut04", G_TYPE_INT, clut[4], "clut05", G_TYPE_INT, clut[5],
14432               "clut06", G_TYPE_INT, clut[6], "clut07", G_TYPE_INT, clut[7],
14433               "clut08", G_TYPE_INT, clut[8], "clut09", G_TYPE_INT, clut[9],
14434               "clut10", G_TYPE_INT, clut[10], "clut11", G_TYPE_INT, clut[11],
14435               "clut12", G_TYPE_INT, clut[12], "clut13", G_TYPE_INT, clut[13],
14436               "clut14", G_TYPE_INT, clut[14], "clut15", G_TYPE_INT, clut[15],
14437               NULL);
14438
14439           /* store event and trigger custom processing */
14440           stream->pending_event =
14441               gst_event_new_custom (GST_EVENT_CUSTOM_DOWNSTREAM, s);
14442         } else {
14443           /* Generic codec_data handler puts it on the caps */
14444           data_ptr = ptr;
14445           data_len = len;
14446         }
14447
14448         ptr += len;
14449         break;
14450       case SL_CONFIG_DESC_TAG:
14451         GST_DEBUG_OBJECT (qtdemux, "data %02x", QT_UINT8 (ptr));
14452         ptr += 1;
14453         break;
14454       default:
14455         GST_DEBUG_OBJECT (qtdemux, "Unknown/unhandled descriptor tag %02x",
14456             tag);
14457         GST_MEMDUMP_OBJECT (qtdemux, "descriptor data", ptr, len);
14458         ptr += len;
14459         break;
14460     }
14461   }
14462
14463   /* object_type_id in the esds atom in mp4a and mp4v tells us which codec is
14464    * in use, and should also be used to override some other parameters for some
14465    * codecs. */
14466   switch (object_type_id) {
14467     case 0x20:                 /* MPEG-4 */
14468       /* 4 bytes for the visual_object_sequence_start_code and 1 byte for the
14469        * profile_and_level_indication */
14470       if (data_ptr != NULL && data_len >= 5 &&
14471           GST_READ_UINT32_BE (data_ptr) == 0x000001b0) {
14472         gst_codec_utils_mpeg4video_caps_set_level_and_profile (entry->caps,
14473             data_ptr + 4, data_len - 4);
14474       }
14475       break;                    /* Nothing special needed here */
14476     case 0x21:                 /* H.264 */
14477       codec_name = "H.264 / AVC";
14478       caps = gst_caps_new_simple ("video/x-h264",
14479           "stream-format", G_TYPE_STRING, "avc",
14480           "alignment", G_TYPE_STRING, "au", NULL);
14481       break;
14482     case 0x40:                 /* AAC (any) */
14483     case 0x66:                 /* AAC Main */
14484     case 0x67:                 /* AAC LC */
14485     case 0x68:                 /* AAC SSR */
14486       /* Override channels and rate based on the codec_data, as it's often
14487        * wrong. */
14488       /* Only do so for basic setup without HE-AAC extension */
14489       if (data_ptr && data_len == 2) {
14490         guint channels, rate;
14491
14492         channels = gst_codec_utils_aac_get_channels (data_ptr, data_len);
14493         if (channels > 0)
14494           entry->n_channels = channels;
14495
14496         rate = gst_codec_utils_aac_get_sample_rate (data_ptr, data_len);
14497         if (rate > 0)
14498           entry->rate = rate;
14499       }
14500
14501       /* Set level and profile if possible */
14502       if (data_ptr != NULL && data_len >= 2) {
14503         gst_codec_utils_aac_caps_set_level_and_profile (entry->caps,
14504             data_ptr, data_len);
14505       } else {
14506         const gchar *profile_str = NULL;
14507         GstBuffer *buffer;
14508         GstMapInfo map;
14509         guint8 *codec_data;
14510         gint rate_idx, profile;
14511
14512         /* No codec_data, let's invent something.
14513          * FIXME: This is wrong for SBR! */
14514
14515         GST_WARNING_OBJECT (qtdemux, "No codec_data for AAC available");
14516
14517         buffer = gst_buffer_new_and_alloc (2);
14518         gst_buffer_map (buffer, &map, GST_MAP_WRITE);
14519         codec_data = map.data;
14520
14521         rate_idx =
14522             gst_codec_utils_aac_get_index_from_sample_rate (CUR_STREAM
14523             (stream)->rate);
14524
14525         switch (object_type_id) {
14526           case 0x66:
14527             profile_str = "main";
14528             profile = 0;
14529             break;
14530           case 0x67:
14531             profile_str = "lc";
14532             profile = 1;
14533             break;
14534           case 0x68:
14535             profile_str = "ssr";
14536             profile = 2;
14537             break;
14538           default:
14539             profile = 3;
14540             break;
14541         }
14542
14543         codec_data[0] = ((profile + 1) << 3) | ((rate_idx & 0xE) >> 1);
14544         codec_data[1] =
14545             ((rate_idx & 0x1) << 7) | (CUR_STREAM (stream)->n_channels << 3);
14546
14547         gst_buffer_unmap (buffer, &map);
14548         gst_caps_set_simple (CUR_STREAM (stream)->caps, "codec_data",
14549             GST_TYPE_BUFFER, buffer, NULL);
14550         gst_buffer_unref (buffer);
14551
14552         if (profile_str) {
14553           gst_caps_set_simple (CUR_STREAM (stream)->caps, "profile",
14554               G_TYPE_STRING, profile_str, NULL);
14555         }
14556       }
14557       break;
14558     case 0x60:                 /* MPEG-2, various profiles */
14559     case 0x61:
14560     case 0x62:
14561     case 0x63:
14562     case 0x64:
14563     case 0x65:
14564       codec_name = "MPEG-2 video";
14565       caps = gst_caps_new_simple ("video/mpeg",
14566           "mpegversion", G_TYPE_INT, 2,
14567           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
14568       break;
14569     case 0x69:                 /* MPEG-2 BC audio */
14570     case 0x6B:                 /* MPEG-1 audio */
14571       caps = gst_caps_new_simple ("audio/mpeg",
14572           "mpegversion", G_TYPE_INT, 1, NULL);
14573       codec_name = "MPEG-1 audio";
14574       break;
14575     case 0x6A:                 /* MPEG-1 */
14576       codec_name = "MPEG-1 video";
14577       caps = gst_caps_new_simple ("video/mpeg",
14578           "mpegversion", G_TYPE_INT, 1,
14579           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
14580       break;
14581     case 0x6C:                 /* MJPEG */
14582       caps =
14583           gst_caps_new_simple ("image/jpeg", "parsed", G_TYPE_BOOLEAN, TRUE,
14584           NULL);
14585       codec_name = "Motion-JPEG";
14586       break;
14587     case 0x6D:                 /* PNG */
14588       caps =
14589           gst_caps_new_simple ("image/png", "parsed", G_TYPE_BOOLEAN, TRUE,
14590           NULL);
14591       codec_name = "PNG still images";
14592       break;
14593     case 0x6E:                 /* JPEG2000 */
14594       codec_name = "JPEG-2000";
14595       caps = gst_caps_new_simple ("image/x-j2c", "fields", G_TYPE_INT, 1, NULL);
14596       break;
14597     case 0xA4:                 /* Dirac */
14598       codec_name = "Dirac";
14599       caps = gst_caps_new_empty_simple ("video/x-dirac");
14600       break;
14601     case 0xA5:                 /* AC3 */
14602       codec_name = "AC-3 audio";
14603       caps = gst_caps_new_simple ("audio/x-ac3",
14604           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
14605       break;
14606     case 0xA9:                 /* AC3 */
14607       codec_name = "DTS audio";
14608       caps = gst_caps_new_simple ("audio/x-dts",
14609           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
14610       break;
14611     case 0xDD:
14612       if (stream_type == 0x05 && data_ptr) {
14613         GList *headers =
14614             parse_xiph_stream_headers (qtdemux, data_ptr, data_len);
14615         if (headers) {
14616           GList *tmp;
14617           GValue arr_val = G_VALUE_INIT;
14618           GValue buf_val = G_VALUE_INIT;
14619           GstStructure *s;
14620
14621           /* Let's assume it's vorbis if it's an audio stream of type 0xdd and we have codec data that extracts properly */
14622           codec_name = "Vorbis";
14623           caps = gst_caps_new_empty_simple ("audio/x-vorbis");
14624           g_value_init (&arr_val, GST_TYPE_ARRAY);
14625           g_value_init (&buf_val, GST_TYPE_BUFFER);
14626           for (tmp = headers; tmp; tmp = tmp->next) {
14627             g_value_set_boxed (&buf_val, (GstBuffer *) tmp->data);
14628             gst_value_array_append_value (&arr_val, &buf_val);
14629           }
14630           s = gst_caps_get_structure (caps, 0);
14631           gst_structure_take_value (s, "streamheader", &arr_val);
14632           g_value_unset (&buf_val);
14633           g_list_free (headers);
14634
14635           data_ptr = NULL;
14636           data_len = 0;
14637         }
14638       }
14639       break;
14640     case 0xE1:                 /* QCELP */
14641       /* QCELP, the codec_data is a riff tag (little endian) with
14642        * 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). */
14643       caps = gst_caps_new_empty_simple ("audio/qcelp");
14644       codec_name = "QCELP";
14645       break;
14646     default:
14647       break;
14648   }
14649
14650   /* If we have a replacement caps, then change our caps for this stream */
14651   if (caps) {
14652     gst_caps_unref (entry->caps);
14653     entry->caps = caps;
14654   }
14655
14656   if (codec_name && list)
14657     gst_tag_list_add (list, GST_TAG_MERGE_REPLACE,
14658         GST_TAG_AUDIO_CODEC, codec_name, NULL);
14659
14660   /* Add the codec_data attribute to caps, if we have it */
14661   if (data_ptr) {
14662     GstBuffer *buffer;
14663
14664     buffer = gst_buffer_new_and_alloc (data_len);
14665     gst_buffer_fill (buffer, 0, data_ptr, data_len);
14666
14667     GST_DEBUG_OBJECT (qtdemux, "setting codec_data from esds");
14668     GST_MEMDUMP_OBJECT (qtdemux, "codec_data from esds", data_ptr, data_len);
14669
14670     gst_caps_set_simple (entry->caps, "codec_data", GST_TYPE_BUFFER,
14671         buffer, NULL);
14672     gst_buffer_unref (buffer);
14673   }
14674
14675 }
14676
14677 static inline GstCaps *
14678 _get_unknown_codec_name (const gchar * type, guint32 fourcc)
14679 {
14680   GstCaps *caps;
14681   guint i;
14682   char *s, fourstr[5];
14683
14684   g_snprintf (fourstr, 5, "%" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (fourcc));
14685   for (i = 0; i < 4; i++) {
14686     if (!g_ascii_isalnum (fourstr[i]))
14687       fourstr[i] = '_';
14688   }
14689   s = g_strdup_printf ("%s/x-gst-fourcc-%s", type, g_strstrip (fourstr));
14690   caps = gst_caps_new_empty_simple (s);
14691   g_free (s);
14692   return caps;
14693 }
14694
14695 #define _codec(name) \
14696   do { \
14697     if (codec_name) { \
14698       *codec_name = g_strdup (name); \
14699     } \
14700   } while (0)
14701
14702 static GstCaps *
14703 qtdemux_video_caps (GstQTDemux * qtdemux, QtDemuxStream * stream,
14704     QtDemuxStreamStsdEntry * entry, guint32 fourcc,
14705     const guint8 * stsd_entry_data, gchar ** codec_name)
14706 {
14707   GstCaps *caps = NULL;
14708   GstVideoFormat format = GST_VIDEO_FORMAT_UNKNOWN;
14709
14710   switch (fourcc) {
14711     case FOURCC_png:
14712       _codec ("PNG still images");
14713       caps = gst_caps_new_empty_simple ("image/png");
14714       break;
14715     case FOURCC_jpeg:
14716       _codec ("JPEG still images");
14717       caps =
14718           gst_caps_new_simple ("image/jpeg", "parsed", G_TYPE_BOOLEAN, TRUE,
14719           NULL);
14720       break;
14721     case GST_MAKE_FOURCC ('m', 'j', 'p', 'a'):
14722     case GST_MAKE_FOURCC ('A', 'V', 'D', 'J'):
14723     case GST_MAKE_FOURCC ('M', 'J', 'P', 'G'):
14724     case GST_MAKE_FOURCC ('d', 'm', 'b', '1'):
14725       _codec ("Motion-JPEG");
14726       caps =
14727           gst_caps_new_simple ("image/jpeg", "parsed", G_TYPE_BOOLEAN, TRUE,
14728           NULL);
14729       break;
14730     case GST_MAKE_FOURCC ('m', 'j', 'p', 'b'):
14731       _codec ("Motion-JPEG format B");
14732       caps = gst_caps_new_empty_simple ("video/x-mjpeg-b");
14733       break;
14734     case FOURCC_mjp2:
14735       _codec ("JPEG-2000");
14736       /* override to what it should be according to spec, avoid palette_data */
14737       entry->bits_per_sample = 24;
14738       caps = gst_caps_new_simple ("image/x-j2c", "fields", G_TYPE_INT, 1, NULL);
14739       break;
14740     case FOURCC_SVQ3:
14741       _codec ("Sorensen video v.3");
14742       caps = gst_caps_new_simple ("video/x-svq",
14743           "svqversion", G_TYPE_INT, 3, NULL);
14744       break;
14745     case GST_MAKE_FOURCC ('s', 'v', 'q', 'i'):
14746     case GST_MAKE_FOURCC ('S', 'V', 'Q', '1'):
14747       _codec ("Sorensen video v.1");
14748       caps = gst_caps_new_simple ("video/x-svq",
14749           "svqversion", G_TYPE_INT, 1, NULL);
14750       break;
14751     case GST_MAKE_FOURCC ('W', 'R', 'A', 'W'):
14752       caps = gst_caps_new_empty_simple ("video/x-raw");
14753       gst_caps_set_simple (caps, "format", G_TYPE_STRING, "RGB8P", NULL);
14754       _codec ("Windows Raw RGB");
14755       stream->alignment = 32;
14756       break;
14757     case FOURCC_raw_:
14758     {
14759       guint16 bps;
14760
14761       bps = QT_UINT16 (stsd_entry_data + 82);
14762       switch (bps) {
14763         case 15:
14764           format = GST_VIDEO_FORMAT_RGB15;
14765           break;
14766         case 16:
14767           format = GST_VIDEO_FORMAT_RGB16;
14768           break;
14769         case 24:
14770           format = GST_VIDEO_FORMAT_RGB;
14771           break;
14772         case 32:
14773           format = GST_VIDEO_FORMAT_ARGB;
14774           break;
14775         default:
14776           /* unknown */
14777           break;
14778       }
14779       break;
14780     }
14781     case GST_MAKE_FOURCC ('y', 'v', '1', '2'):
14782       format = GST_VIDEO_FORMAT_I420;
14783       break;
14784     case GST_MAKE_FOURCC ('y', 'u', 'v', '2'):
14785     case GST_MAKE_FOURCC ('Y', 'u', 'v', '2'):
14786       format = GST_VIDEO_FORMAT_I420;
14787       break;
14788     case FOURCC_2vuy:
14789     case GST_MAKE_FOURCC ('2', 'V', 'u', 'y'):
14790       format = GST_VIDEO_FORMAT_UYVY;
14791       break;
14792     case GST_MAKE_FOURCC ('v', '3', '0', '8'):
14793       format = GST_VIDEO_FORMAT_v308;
14794       break;
14795     case GST_MAKE_FOURCC ('v', '2', '1', '6'):
14796       format = GST_VIDEO_FORMAT_v216;
14797       break;
14798     case FOURCC_v210:
14799       format = GST_VIDEO_FORMAT_v210;
14800       break;
14801     case GST_MAKE_FOURCC ('r', '2', '1', '0'):
14802       format = GST_VIDEO_FORMAT_r210;
14803       break;
14804       /* Packed YUV 4:4:4 10 bit in 32 bits, complex
14805          case GST_MAKE_FOURCC ('v', '4', '1', '0'):
14806          format = GST_VIDEO_FORMAT_v410;
14807          break;
14808        */
14809       /* Packed YUV 4:4:4:4 8 bit in 32 bits
14810        * but different order than AYUV
14811        case GST_MAKE_FOURCC ('v', '4', '0', '8'):
14812        format = GST_VIDEO_FORMAT_v408;
14813        break;
14814        */
14815     case GST_MAKE_FOURCC ('m', 'p', 'e', 'g'):
14816     case GST_MAKE_FOURCC ('m', 'p', 'g', '1'):
14817       _codec ("MPEG-1 video");
14818       caps = gst_caps_new_simple ("video/mpeg", "mpegversion", G_TYPE_INT, 1,
14819           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
14820       break;
14821     case GST_MAKE_FOURCC ('h', 'd', 'v', '1'): /* HDV 720p30 */
14822     case GST_MAKE_FOURCC ('h', 'd', 'v', '2'): /* HDV 1080i60 */
14823     case GST_MAKE_FOURCC ('h', 'd', 'v', '3'): /* HDV 1080i50 */
14824     case GST_MAKE_FOURCC ('h', 'd', 'v', '4'): /* HDV 720p24 */
14825     case GST_MAKE_FOURCC ('h', 'd', 'v', '5'): /* HDV 720p25 */
14826     case GST_MAKE_FOURCC ('h', 'd', 'v', '6'): /* HDV 1080p24 */
14827     case GST_MAKE_FOURCC ('h', 'd', 'v', '7'): /* HDV 1080p25 */
14828     case GST_MAKE_FOURCC ('h', 'd', 'v', '8'): /* HDV 1080p30 */
14829     case GST_MAKE_FOURCC ('h', 'd', 'v', '9'): /* HDV 720p60 */
14830     case GST_MAKE_FOURCC ('h', 'd', 'v', 'a'): /* HDV 720p50 */
14831     case GST_MAKE_FOURCC ('m', 'x', '5', 'n'): /* MPEG2 IMX NTSC 525/60 50mb/s produced by FCP */
14832     case GST_MAKE_FOURCC ('m', 'x', '5', 'p'): /* MPEG2 IMX PAL 625/60 50mb/s produced by FCP */
14833     case GST_MAKE_FOURCC ('m', 'x', '4', 'n'): /* MPEG2 IMX NTSC 525/60 40mb/s produced by FCP */
14834     case GST_MAKE_FOURCC ('m', 'x', '4', 'p'): /* MPEG2 IMX PAL 625/60 40mb/s produced by FCP */
14835     case GST_MAKE_FOURCC ('m', 'x', '3', 'n'): /* MPEG2 IMX NTSC 525/60 30mb/s produced by FCP */
14836     case GST_MAKE_FOURCC ('m', 'x', '3', 'p'): /* MPEG2 IMX PAL 625/50 30mb/s produced by FCP */
14837     case GST_MAKE_FOURCC ('x', 'd', 'v', '1'): /* XDCAM HD 720p30 35Mb/s */
14838     case GST_MAKE_FOURCC ('x', 'd', 'v', '2'): /* XDCAM HD 1080i60 35Mb/s */
14839     case GST_MAKE_FOURCC ('x', 'd', 'v', '3'): /* XDCAM HD 1080i50 35Mb/s */
14840     case GST_MAKE_FOURCC ('x', 'd', 'v', '4'): /* XDCAM HD 720p24 35Mb/s */
14841     case GST_MAKE_FOURCC ('x', 'd', 'v', '5'): /* XDCAM HD 720p25 35Mb/s */
14842     case GST_MAKE_FOURCC ('x', 'd', 'v', '6'): /* XDCAM HD 1080p24 35Mb/s */
14843     case GST_MAKE_FOURCC ('x', 'd', 'v', '7'): /* XDCAM HD 1080p25 35Mb/s */
14844     case GST_MAKE_FOURCC ('x', 'd', 'v', '8'): /* XDCAM HD 1080p30 35Mb/s */
14845     case GST_MAKE_FOURCC ('x', 'd', 'v', '9'): /* XDCAM HD 720p60 35Mb/s */
14846     case GST_MAKE_FOURCC ('x', 'd', 'v', 'a'): /* XDCAM HD 720p50 35Mb/s */
14847     case GST_MAKE_FOURCC ('x', 'd', 'v', 'b'): /* XDCAM EX 1080i60 50Mb/s CBR */
14848     case GST_MAKE_FOURCC ('x', 'd', 'v', 'c'): /* XDCAM EX 1080i50 50Mb/s CBR */
14849     case GST_MAKE_FOURCC ('x', 'd', 'v', 'd'): /* XDCAM HD 1080p24 50Mb/s CBR */
14850     case GST_MAKE_FOURCC ('x', 'd', 'v', 'e'): /* XDCAM HD 1080p25 50Mb/s CBR */
14851     case GST_MAKE_FOURCC ('x', 'd', 'v', 'f'): /* XDCAM HD 1080p30 50Mb/s CBR */
14852     case GST_MAKE_FOURCC ('x', 'd', '5', '1'): /* XDCAM HD422 720p30 50Mb/s CBR */
14853     case GST_MAKE_FOURCC ('x', 'd', '5', '4'): /* XDCAM HD422 720p24 50Mb/s CBR */
14854     case GST_MAKE_FOURCC ('x', 'd', '5', '5'): /* XDCAM HD422 720p25 50Mb/s CBR */
14855     case GST_MAKE_FOURCC ('x', 'd', '5', '9'): /* XDCAM HD422 720p60 50Mb/s CBR */
14856     case GST_MAKE_FOURCC ('x', 'd', '5', 'a'): /* XDCAM HD422 720p50 50Mb/s CBR */
14857     case GST_MAKE_FOURCC ('x', 'd', '5', 'b'): /* XDCAM HD422 1080i50 50Mb/s CBR */
14858     case GST_MAKE_FOURCC ('x', 'd', '5', 'c'): /* XDCAM HD422 1080i50 50Mb/s CBR */
14859     case GST_MAKE_FOURCC ('x', 'd', '5', 'd'): /* XDCAM HD422 1080p24 50Mb/s CBR */
14860     case GST_MAKE_FOURCC ('x', 'd', '5', 'e'): /* XDCAM HD422 1080p25 50Mb/s CBR */
14861     case GST_MAKE_FOURCC ('x', 'd', '5', 'f'): /* XDCAM HD422 1080p30 50Mb/s CBR */
14862     case GST_MAKE_FOURCC ('x', 'd', 'h', 'd'): /* XDCAM HD 540p */
14863     case GST_MAKE_FOURCC ('x', 'd', 'h', '2'): /* XDCAM HD422 540p */
14864     case GST_MAKE_FOURCC ('A', 'V', 'm', 'p'): /* AVID IMX PAL */
14865     case GST_MAKE_FOURCC ('m', 'p', 'g', '2'): /* AVID IMX PAL */
14866     case GST_MAKE_FOURCC ('m', 'p', '2', 'v'): /* AVID IMX PAL */
14867     case GST_MAKE_FOURCC ('m', '2', 'v', '1'):
14868       _codec ("MPEG-2 video");
14869       caps = gst_caps_new_simple ("video/mpeg", "mpegversion", G_TYPE_INT, 2,
14870           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
14871       break;
14872     case GST_MAKE_FOURCC ('g', 'i', 'f', ' '):
14873       _codec ("GIF still images");
14874       caps = gst_caps_new_empty_simple ("image/gif");
14875       break;
14876     case FOURCC_h263:
14877     case GST_MAKE_FOURCC ('H', '2', '6', '3'):
14878     case FOURCC_s263:
14879     case GST_MAKE_FOURCC ('U', '2', '6', '3'):
14880       _codec ("H.263");
14881       /* ffmpeg uses the height/width props, don't know why */
14882       caps = gst_caps_new_simple ("video/x-h263",
14883           "variant", G_TYPE_STRING, "itu", NULL);
14884       break;
14885     case FOURCC_mp4v:
14886     case FOURCC_MP4V:
14887       _codec ("MPEG-4 video");
14888       caps = gst_caps_new_simple ("video/mpeg", "mpegversion", G_TYPE_INT, 4,
14889           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
14890       break;
14891     case GST_MAKE_FOURCC ('3', 'i', 'v', 'd'):
14892     case GST_MAKE_FOURCC ('3', 'I', 'V', 'D'):
14893       _codec ("Microsoft MPEG-4 4.3");  /* FIXME? */
14894       caps = gst_caps_new_simple ("video/x-msmpeg",
14895           "msmpegversion", G_TYPE_INT, 43, NULL);
14896       break;
14897     case GST_MAKE_FOURCC ('D', 'I', 'V', '3'):
14898       _codec ("DivX 3");
14899       caps = gst_caps_new_simple ("video/x-divx",
14900           "divxversion", G_TYPE_INT, 3, NULL);
14901       break;
14902     case GST_MAKE_FOURCC ('D', 'I', 'V', 'X'):
14903     case GST_MAKE_FOURCC ('d', 'i', 'v', 'x'):
14904       _codec ("DivX 4");
14905       caps = gst_caps_new_simple ("video/x-divx",
14906           "divxversion", G_TYPE_INT, 4, NULL);
14907       break;
14908     case GST_MAKE_FOURCC ('D', 'X', '5', '0'):
14909       _codec ("DivX 5");
14910       caps = gst_caps_new_simple ("video/x-divx",
14911           "divxversion", G_TYPE_INT, 5, NULL);
14912       break;
14913
14914     case GST_MAKE_FOURCC ('F', 'F', 'V', '1'):
14915       _codec ("FFV1");
14916       caps = gst_caps_new_simple ("video/x-ffv",
14917           "ffvversion", G_TYPE_INT, 1, NULL);
14918       break;
14919
14920     case GST_MAKE_FOURCC ('3', 'I', 'V', '1'):
14921     case GST_MAKE_FOURCC ('3', 'I', 'V', '2'):
14922     case FOURCC_XVID:
14923     case FOURCC_xvid:
14924     case FOURCC_FMP4:
14925     case FOURCC_fmp4:
14926     case GST_MAKE_FOURCC ('U', 'M', 'P', '4'):
14927       caps = gst_caps_new_simple ("video/mpeg", "mpegversion", G_TYPE_INT, 4,
14928           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
14929       _codec ("MPEG-4");
14930       break;
14931
14932     case GST_MAKE_FOURCC ('c', 'v', 'i', 'd'):
14933       _codec ("Cinepak");
14934       caps = gst_caps_new_empty_simple ("video/x-cinepak");
14935       break;
14936     case GST_MAKE_FOURCC ('q', 'd', 'r', 'w'):
14937       _codec ("Apple QuickDraw");
14938       caps = gst_caps_new_empty_simple ("video/x-qdrw");
14939       break;
14940     case GST_MAKE_FOURCC ('r', 'p', 'z', 'a'):
14941       _codec ("Apple video");
14942       caps = gst_caps_new_empty_simple ("video/x-apple-video");
14943       break;
14944     case FOURCC_H264:
14945     case FOURCC_avc1:
14946       _codec ("H.264 / AVC");
14947       caps = gst_caps_new_simple ("video/x-h264",
14948           "stream-format", G_TYPE_STRING, "avc",
14949           "alignment", G_TYPE_STRING, "au", NULL);
14950       break;
14951     case FOURCC_avc3:
14952       _codec ("H.264 / AVC");
14953       caps = gst_caps_new_simple ("video/x-h264",
14954           "stream-format", G_TYPE_STRING, "avc3",
14955           "alignment", G_TYPE_STRING, "au", NULL);
14956       break;
14957     case FOURCC_H265:
14958     case FOURCC_hvc1:
14959       _codec ("H.265 / HEVC");
14960       caps = gst_caps_new_simple ("video/x-h265",
14961           "stream-format", G_TYPE_STRING, "hvc1",
14962           "alignment", G_TYPE_STRING, "au", NULL);
14963       break;
14964     case FOURCC_hev1:
14965       _codec ("H.265 / HEVC");
14966       caps = gst_caps_new_simple ("video/x-h265",
14967           "stream-format", G_TYPE_STRING, "hev1",
14968           "alignment", G_TYPE_STRING, "au", NULL);
14969       break;
14970     case FOURCC_rle_:
14971       _codec ("Run-length encoding");
14972       caps = gst_caps_new_simple ("video/x-rle",
14973           "layout", G_TYPE_STRING, "quicktime", NULL);
14974       break;
14975     case FOURCC_WRLE:
14976       _codec ("Run-length encoding");
14977       caps = gst_caps_new_simple ("video/x-rle",
14978           "layout", G_TYPE_STRING, "microsoft", NULL);
14979       break;
14980     case GST_MAKE_FOURCC ('I', 'V', '3', '2'):
14981     case GST_MAKE_FOURCC ('i', 'v', '3', '2'):
14982       _codec ("Indeo Video 3");
14983       caps = gst_caps_new_simple ("video/x-indeo",
14984           "indeoversion", G_TYPE_INT, 3, NULL);
14985       break;
14986     case GST_MAKE_FOURCC ('I', 'V', '4', '1'):
14987     case GST_MAKE_FOURCC ('i', 'v', '4', '1'):
14988       _codec ("Intel Video 4");
14989       caps = gst_caps_new_simple ("video/x-indeo",
14990           "indeoversion", G_TYPE_INT, 4, NULL);
14991       break;
14992     case FOURCC_dvcp:
14993     case FOURCC_dvc_:
14994     case GST_MAKE_FOURCC ('d', 'v', 's', 'd'):
14995     case GST_MAKE_FOURCC ('D', 'V', 'S', 'D'):
14996     case GST_MAKE_FOURCC ('d', 'v', 'c', 's'):
14997     case GST_MAKE_FOURCC ('D', 'V', 'C', 'S'):
14998     case GST_MAKE_FOURCC ('d', 'v', '2', '5'):
14999     case GST_MAKE_FOURCC ('d', 'v', 'p', 'p'):
15000       _codec ("DV Video");
15001       caps = gst_caps_new_simple ("video/x-dv", "dvversion", G_TYPE_INT, 25,
15002           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
15003       break;
15004     case FOURCC_dv5n:          /* DVCPRO50 NTSC */
15005     case FOURCC_dv5p:          /* DVCPRO50 PAL */
15006       _codec ("DVCPro50 Video");
15007       caps = gst_caps_new_simple ("video/x-dv", "dvversion", G_TYPE_INT, 50,
15008           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
15009       break;
15010     case GST_MAKE_FOURCC ('d', 'v', 'h', '5'): /* DVCPRO HD 50i produced by FCP */
15011     case GST_MAKE_FOURCC ('d', 'v', 'h', '6'): /* DVCPRO HD 60i produced by FCP */
15012       _codec ("DVCProHD Video");
15013       caps = gst_caps_new_simple ("video/x-dv", "dvversion", G_TYPE_INT, 100,
15014           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
15015       break;
15016     case GST_MAKE_FOURCC ('s', 'm', 'c', ' '):
15017       _codec ("Apple Graphics (SMC)");
15018       caps = gst_caps_new_empty_simple ("video/x-smc");
15019       break;
15020     case GST_MAKE_FOURCC ('V', 'P', '3', '1'):
15021       _codec ("VP3");
15022       caps = gst_caps_new_empty_simple ("video/x-vp3");
15023       break;
15024     case GST_MAKE_FOURCC ('V', 'P', '6', 'F'):
15025       _codec ("VP6 Flash");
15026       caps = gst_caps_new_empty_simple ("video/x-vp6-flash");
15027       break;
15028     case FOURCC_XiTh:
15029       _codec ("Theora");
15030       caps = gst_caps_new_empty_simple ("video/x-theora");
15031       /* theora uses one byte of padding in the data stream because it does not
15032        * allow 0 sized packets while theora does */
15033       entry->padding = 1;
15034       break;
15035     case FOURCC_drac:
15036       _codec ("Dirac");
15037       caps = gst_caps_new_empty_simple ("video/x-dirac");
15038       break;
15039     case GST_MAKE_FOURCC ('t', 'i', 'f', 'f'):
15040       _codec ("TIFF still images");
15041       caps = gst_caps_new_empty_simple ("image/tiff");
15042       break;
15043     case GST_MAKE_FOURCC ('i', 'c', 'o', 'd'):
15044       _codec ("Apple Intermediate Codec");
15045       caps = gst_caps_from_string ("video/x-apple-intermediate-codec");
15046       break;
15047     case GST_MAKE_FOURCC ('A', 'V', 'd', 'n'):
15048       _codec ("AVID DNxHD");
15049       caps = gst_caps_from_string ("video/x-dnxhd");
15050       break;
15051     case FOURCC_VP80:
15052     case FOURCC_vp08:
15053       _codec ("On2 VP8");
15054       caps = gst_caps_from_string ("video/x-vp8");
15055       break;
15056     case FOURCC_vp09:
15057       _codec ("Google VP9");
15058       caps = gst_caps_from_string ("video/x-vp9");
15059       break;
15060     case FOURCC_apcs:
15061       _codec ("Apple ProRes LT");
15062       caps =
15063           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING, "lt",
15064           NULL);
15065       break;
15066     case FOURCC_apch:
15067       _codec ("Apple ProRes HQ");
15068       caps =
15069           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING, "hq",
15070           NULL);
15071       break;
15072     case FOURCC_apcn:
15073       _codec ("Apple ProRes");
15074       caps =
15075           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING,
15076           "standard", NULL);
15077       break;
15078     case FOURCC_apco:
15079       _codec ("Apple ProRes Proxy");
15080       caps =
15081           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING,
15082           "proxy", NULL);
15083       break;
15084     case FOURCC_ap4h:
15085       _codec ("Apple ProRes 4444");
15086       caps =
15087           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING,
15088           "4444", NULL);
15089       break;
15090     case FOURCC_ap4x:
15091       _codec ("Apple ProRes 4444 XQ");
15092       caps =
15093           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING,
15094           "4444xq", NULL);
15095       break;
15096     case FOURCC_cfhd:
15097       _codec ("GoPro CineForm");
15098       caps = gst_caps_from_string ("video/x-cineform");
15099       break;
15100     case FOURCC_vc_1:
15101     case FOURCC_ovc1:
15102       _codec ("VC-1");
15103       caps = gst_caps_new_simple ("video/x-wmv",
15104           "wmvversion", G_TYPE_INT, 3, "format", G_TYPE_STRING, "WVC1", NULL);
15105       break;
15106     case FOURCC_av01:
15107       _codec ("AV1");
15108       caps = gst_caps_new_empty_simple ("video/x-av1");
15109       break;
15110     case GST_MAKE_FOURCC ('k', 'p', 'c', 'd'):
15111     default:
15112     {
15113       caps = _get_unknown_codec_name ("video", fourcc);
15114       break;
15115     }
15116   }
15117
15118   if (format != GST_VIDEO_FORMAT_UNKNOWN) {
15119     GstVideoInfo info;
15120
15121     gst_video_info_init (&info);
15122     gst_video_info_set_format (&info, format, entry->width, entry->height);
15123
15124     caps = gst_video_info_to_caps (&info);
15125     *codec_name = gst_pb_utils_get_codec_description (caps);
15126
15127     /* enable clipping for raw video streams */
15128     stream->need_clip = TRUE;
15129     stream->alignment = 32;
15130   }
15131
15132   return caps;
15133 }
15134
15135 static guint
15136 round_up_pow2 (guint n)
15137 {
15138   n = n - 1;
15139   n = n | (n >> 1);
15140   n = n | (n >> 2);
15141   n = n | (n >> 4);
15142   n = n | (n >> 8);
15143   n = n | (n >> 16);
15144   return n + 1;
15145 }
15146
15147 static GstCaps *
15148 qtdemux_audio_caps (GstQTDemux * qtdemux, QtDemuxStream * stream,
15149     QtDemuxStreamStsdEntry * entry, guint32 fourcc, const guint8 * data,
15150     int len, gchar ** codec_name)
15151 {
15152   GstCaps *caps;
15153   const GstStructure *s;
15154   const gchar *name;
15155   gint endian = 0;
15156   GstAudioFormat format = 0;
15157   gint depth;
15158
15159   GST_DEBUG_OBJECT (qtdemux, "resolve fourcc 0x%08x", GUINT32_TO_BE (fourcc));
15160
15161   depth = entry->bytes_per_packet * 8;
15162
15163   switch (fourcc) {
15164     case GST_MAKE_FOURCC ('N', 'O', 'N', 'E'):
15165     case FOURCC_raw_:
15166       /* 8-bit audio is unsigned */
15167       if (depth == 8)
15168         format = GST_AUDIO_FORMAT_U8;
15169       /* otherwise it's signed and big-endian just like 'twos' */
15170     case FOURCC_twos:
15171       endian = G_BIG_ENDIAN;
15172       /* fall-through */
15173     case FOURCC_sowt:
15174     {
15175       gchar *str;
15176
15177       if (!endian)
15178         endian = G_LITTLE_ENDIAN;
15179
15180       if (!format)
15181         format = gst_audio_format_build_integer (TRUE, endian, depth, depth);
15182
15183       str = g_strdup_printf ("Raw %d-bit PCM audio", depth);
15184       _codec (str);
15185       g_free (str);
15186
15187       caps = gst_caps_new_simple ("audio/x-raw",
15188           "format", G_TYPE_STRING, gst_audio_format_to_string (format),
15189           "layout", G_TYPE_STRING, "interleaved", NULL);
15190       stream->alignment = GST_ROUND_UP_8 (depth);
15191       stream->alignment = round_up_pow2 (stream->alignment);
15192       break;
15193     }
15194     case GST_MAKE_FOURCC ('f', 'l', '6', '4'):
15195       _codec ("Raw 64-bit floating-point audio");
15196       caps = gst_caps_new_simple ("audio/x-raw",
15197           "format", G_TYPE_STRING, "F64BE",
15198           "layout", G_TYPE_STRING, "interleaved", NULL);
15199       stream->alignment = 8;
15200       break;
15201     case GST_MAKE_FOURCC ('f', 'l', '3', '2'):
15202       _codec ("Raw 32-bit floating-point audio");
15203       caps = gst_caps_new_simple ("audio/x-raw",
15204           "format", G_TYPE_STRING, "F32BE",
15205           "layout", G_TYPE_STRING, "interleaved", NULL);
15206       stream->alignment = 4;
15207       break;
15208     case FOURCC_in24:
15209       _codec ("Raw 24-bit PCM audio");
15210       /* we assume BIG ENDIAN, an enda box will tell us to change this to little
15211        * endian later */
15212       caps = gst_caps_new_simple ("audio/x-raw",
15213           "format", G_TYPE_STRING, "S24BE",
15214           "layout", G_TYPE_STRING, "interleaved", NULL);
15215       stream->alignment = 4;
15216       break;
15217     case GST_MAKE_FOURCC ('i', 'n', '3', '2'):
15218       _codec ("Raw 32-bit PCM audio");
15219       caps = gst_caps_new_simple ("audio/x-raw",
15220           "format", G_TYPE_STRING, "S32BE",
15221           "layout", G_TYPE_STRING, "interleaved", NULL);
15222       stream->alignment = 4;
15223       break;
15224     case GST_MAKE_FOURCC ('s', '1', '6', 'l'):
15225       _codec ("Raw 16-bit PCM audio");
15226       caps = gst_caps_new_simple ("audio/x-raw",
15227           "format", G_TYPE_STRING, "S16LE",
15228           "layout", G_TYPE_STRING, "interleaved", NULL);
15229       stream->alignment = 2;
15230       break;
15231     case FOURCC_ulaw:
15232       _codec ("Mu-law audio");
15233       caps = gst_caps_new_empty_simple ("audio/x-mulaw");
15234       break;
15235     case FOURCC_alaw:
15236       _codec ("A-law audio");
15237       caps = gst_caps_new_empty_simple ("audio/x-alaw");
15238       break;
15239     case 0x0200736d:
15240     case 0x6d730002:
15241       _codec ("Microsoft ADPCM");
15242       /* Microsoft ADPCM-ACM code 2 */
15243       caps = gst_caps_new_simple ("audio/x-adpcm",
15244           "layout", G_TYPE_STRING, "microsoft", NULL);
15245       break;
15246     case 0x1100736d:
15247     case 0x6d730011:
15248       _codec ("DVI/IMA ADPCM");
15249       caps = gst_caps_new_simple ("audio/x-adpcm",
15250           "layout", G_TYPE_STRING, "dvi", NULL);
15251       break;
15252     case 0x1700736d:
15253     case 0x6d730017:
15254       _codec ("DVI/Intel IMA ADPCM");
15255       /* FIXME DVI/Intel IMA ADPCM/ACM code 17 */
15256       caps = gst_caps_new_simple ("audio/x-adpcm",
15257           "layout", G_TYPE_STRING, "quicktime", NULL);
15258       break;
15259     case 0x5500736d:
15260     case 0x6d730055:
15261       /* MPEG layer 3, CBR only (pre QT4.1) */
15262     case FOURCC__mp3:
15263       _codec ("MPEG-1 layer 3");
15264       /* MPEG layer 3, CBR & VBR (QT4.1 and later) */
15265       caps = gst_caps_new_simple ("audio/mpeg", "layer", G_TYPE_INT, 3,
15266           "mpegversion", G_TYPE_INT, 1, NULL);
15267       break;
15268     case GST_MAKE_FOURCC ('.', 'm', 'p', '2'):
15269       _codec ("MPEG-1 layer 2");
15270       /* MPEG layer 2 */
15271       caps = gst_caps_new_simple ("audio/mpeg", "layer", G_TYPE_INT, 2,
15272           "mpegversion", G_TYPE_INT, 1, NULL);
15273       break;
15274     case 0x20736d:
15275     case GST_MAKE_FOURCC ('e', 'c', '-', '3'):
15276       _codec ("EAC-3 audio");
15277       caps = gst_caps_new_simple ("audio/x-eac3",
15278           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
15279       entry->sampled = TRUE;
15280       break;
15281     case GST_MAKE_FOURCC ('s', 'a', 'c', '3'): // Nero Recode
15282     case FOURCC_ac_3:
15283       _codec ("AC-3 audio");
15284       caps = gst_caps_new_simple ("audio/x-ac3",
15285           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
15286       entry->sampled = TRUE;
15287       break;
15288     case GST_MAKE_FOURCC ('d', 't', 's', 'c'):
15289     case GST_MAKE_FOURCC ('D', 'T', 'S', ' '):
15290       _codec ("DTS audio");
15291       caps = gst_caps_new_simple ("audio/x-dts",
15292           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
15293       entry->sampled = TRUE;
15294       break;
15295     case GST_MAKE_FOURCC ('d', 't', 's', 'h'): // DTS-HD
15296     case GST_MAKE_FOURCC ('d', 't', 's', 'l'): // DTS-HD Lossless
15297       _codec ("DTS-HD audio");
15298       caps = gst_caps_new_simple ("audio/x-dts",
15299           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
15300       entry->sampled = TRUE;
15301       break;
15302     case FOURCC_MAC3:
15303       _codec ("MACE-3");
15304       caps = gst_caps_new_simple ("audio/x-mace",
15305           "maceversion", G_TYPE_INT, 3, NULL);
15306       break;
15307     case FOURCC_MAC6:
15308       _codec ("MACE-6");
15309       caps = gst_caps_new_simple ("audio/x-mace",
15310           "maceversion", G_TYPE_INT, 6, NULL);
15311       break;
15312     case GST_MAKE_FOURCC ('O', 'g', 'g', 'V'):
15313       /* ogg/vorbis */
15314       caps = gst_caps_new_empty_simple ("application/ogg");
15315       break;
15316     case GST_MAKE_FOURCC ('d', 'v', 'c', 'a'):
15317       _codec ("DV audio");
15318       caps = gst_caps_new_empty_simple ("audio/x-dv");
15319       break;
15320     case FOURCC_mp4a:
15321       _codec ("MPEG-4 AAC audio");
15322       caps = gst_caps_new_simple ("audio/mpeg",
15323           "mpegversion", G_TYPE_INT, 4, "framed", G_TYPE_BOOLEAN, TRUE,
15324           "stream-format", G_TYPE_STRING, "raw", NULL);
15325       break;
15326     case GST_MAKE_FOURCC ('Q', 'D', 'M', 'C'):
15327       _codec ("QDesign Music");
15328       caps = gst_caps_new_empty_simple ("audio/x-qdm");
15329       break;
15330     case FOURCC_QDM2:
15331       _codec ("QDesign Music v.2");
15332       /* FIXME: QDesign music version 2 (no constant) */
15333       if (FALSE && data) {
15334         caps = gst_caps_new_simple ("audio/x-qdm2",
15335             "framesize", G_TYPE_INT, QT_UINT32 (data + 52),
15336             "bitrate", G_TYPE_INT, QT_UINT32 (data + 40),
15337             "blocksize", G_TYPE_INT, QT_UINT32 (data + 44), NULL);
15338       } else {
15339         caps = gst_caps_new_empty_simple ("audio/x-qdm2");
15340       }
15341       break;
15342     case FOURCC_agsm:
15343       _codec ("GSM audio");
15344       caps = gst_caps_new_empty_simple ("audio/x-gsm");
15345       break;
15346     case FOURCC_samr:
15347       _codec ("AMR audio");
15348       caps = gst_caps_new_empty_simple ("audio/AMR");
15349       break;
15350     case FOURCC_sawb:
15351       _codec ("AMR-WB audio");
15352       caps = gst_caps_new_empty_simple ("audio/AMR-WB");
15353       break;
15354     case FOURCC_ima4:
15355       _codec ("Quicktime IMA ADPCM");
15356       caps = gst_caps_new_simple ("audio/x-adpcm",
15357           "layout", G_TYPE_STRING, "quicktime", NULL);
15358       break;
15359     case FOURCC_alac:
15360       _codec ("Apple lossless audio");
15361       caps = gst_caps_new_empty_simple ("audio/x-alac");
15362       break;
15363     case FOURCC_fLaC:
15364       _codec ("Free Lossless Audio Codec");
15365       caps = gst_caps_new_simple ("audio/x-flac",
15366           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
15367       break;
15368     case GST_MAKE_FOURCC ('Q', 'c', 'l', 'p'):
15369       _codec ("QualComm PureVoice");
15370       caps = gst_caps_from_string ("audio/qcelp");
15371       break;
15372     case FOURCC_wma_:
15373     case FOURCC_owma:
15374       _codec ("WMA");
15375       caps = gst_caps_new_empty_simple ("audio/x-wma");
15376       break;
15377     case FOURCC_opus:
15378       _codec ("Opus");
15379       caps = gst_caps_new_empty_simple ("audio/x-opus");
15380       break;
15381     case FOURCC_lpcm:
15382     {
15383       guint32 flags = 0;
15384       guint32 depth = 0;
15385       guint32 width = 0;
15386       GstAudioFormat format;
15387       enum
15388       {
15389         FLAG_IS_FLOAT = 0x1,
15390         FLAG_IS_BIG_ENDIAN = 0x2,
15391         FLAG_IS_SIGNED = 0x4,
15392         FLAG_IS_PACKED = 0x8,
15393         FLAG_IS_ALIGNED_HIGH = 0x10,
15394         FLAG_IS_NON_INTERLEAVED = 0x20
15395       };
15396       _codec ("Raw LPCM audio");
15397
15398       if (data && len >= 36) {
15399         depth = QT_UINT32 (data + 24);
15400         flags = QT_UINT32 (data + 28);
15401         width = QT_UINT32 (data + 32) * 8 / entry->n_channels;
15402       }
15403       if ((flags & FLAG_IS_FLOAT) == 0) {
15404         if (depth == 0)
15405           depth = 16;
15406         if (width == 0)
15407           width = 16;
15408         if ((flags & FLAG_IS_ALIGNED_HIGH))
15409           depth = width;
15410
15411         format = gst_audio_format_build_integer ((flags & FLAG_IS_SIGNED) ?
15412             TRUE : FALSE, (flags & FLAG_IS_BIG_ENDIAN) ?
15413             G_BIG_ENDIAN : G_LITTLE_ENDIAN, width, depth);
15414         caps = gst_caps_new_simple ("audio/x-raw",
15415             "format", G_TYPE_STRING,
15416             format !=
15417             GST_AUDIO_FORMAT_UNKNOWN ? gst_audio_format_to_string (format) :
15418             "UNKNOWN", "layout", G_TYPE_STRING,
15419             (flags & FLAG_IS_NON_INTERLEAVED) ? "non-interleaved" :
15420             "interleaved", NULL);
15421         stream->alignment = GST_ROUND_UP_8 (depth);
15422         stream->alignment = round_up_pow2 (stream->alignment);
15423       } else {
15424         if (width == 0)
15425           width = 32;
15426         if (width == 64) {
15427           if (flags & FLAG_IS_BIG_ENDIAN)
15428             format = GST_AUDIO_FORMAT_F64BE;
15429           else
15430             format = GST_AUDIO_FORMAT_F64LE;
15431         } else {
15432           if (flags & FLAG_IS_BIG_ENDIAN)
15433             format = GST_AUDIO_FORMAT_F32BE;
15434           else
15435             format = GST_AUDIO_FORMAT_F32LE;
15436         }
15437         caps = gst_caps_new_simple ("audio/x-raw",
15438             "format", G_TYPE_STRING, gst_audio_format_to_string (format),
15439             "layout", G_TYPE_STRING, (flags & FLAG_IS_NON_INTERLEAVED) ?
15440             "non-interleaved" : "interleaved", NULL);
15441         stream->alignment = width / 8;
15442       }
15443       break;
15444     }
15445     case GST_MAKE_FOURCC ('q', 't', 'v', 'r'):
15446       /* ? */
15447     default:
15448     {
15449       caps = _get_unknown_codec_name ("audio", fourcc);
15450       break;
15451     }
15452   }
15453
15454   if (caps) {
15455     GstCaps *templ_caps =
15456         gst_static_pad_template_get_caps (&gst_qtdemux_audiosrc_template);
15457     GstCaps *intersection = gst_caps_intersect (caps, templ_caps);
15458     gst_caps_unref (caps);
15459     gst_caps_unref (templ_caps);
15460     caps = intersection;
15461   }
15462
15463   /* enable clipping for raw audio streams */
15464   s = gst_caps_get_structure (caps, 0);
15465   name = gst_structure_get_name (s);
15466   if (g_str_has_prefix (name, "audio/x-raw")) {
15467     stream->need_clip = TRUE;
15468     stream->max_buffer_size = 4096 * entry->bytes_per_frame;
15469     GST_DEBUG ("setting max buffer size to %d", stream->max_buffer_size);
15470   }
15471   return caps;
15472 }
15473
15474 static GstCaps *
15475 qtdemux_sub_caps (GstQTDemux * qtdemux, QtDemuxStream * stream,
15476     QtDemuxStreamStsdEntry * entry, guint32 fourcc,
15477     const guint8 * stsd_entry_data, gchar ** codec_name)
15478 {
15479   GstCaps *caps;
15480
15481   GST_DEBUG_OBJECT (qtdemux, "resolve fourcc 0x%08x", GUINT32_TO_BE (fourcc));
15482
15483   switch (fourcc) {
15484     case FOURCC_mp4s:
15485       _codec ("DVD subtitle");
15486       caps = gst_caps_new_empty_simple ("subpicture/x-dvd");
15487       stream->need_process = TRUE;
15488       break;
15489     case FOURCC_text:
15490       _codec ("Quicktime timed text");
15491       goto text;
15492     case FOURCC_tx3g:
15493       _codec ("3GPP timed text");
15494     text:
15495       caps = gst_caps_new_simple ("text/x-raw", "format", G_TYPE_STRING,
15496           "utf8", NULL);
15497       /* actual text piece needs to be extracted */
15498       stream->need_process = TRUE;
15499       break;
15500     case FOURCC_stpp:
15501       _codec ("XML subtitles");
15502       caps = gst_caps_new_empty_simple ("application/ttml+xml");
15503       break;
15504     case FOURCC_c608:
15505       _codec ("CEA 608 Closed Caption");
15506       caps =
15507           gst_caps_new_simple ("closedcaption/x-cea-608", "format",
15508           G_TYPE_STRING, "s334-1a", NULL);
15509       stream->need_process = TRUE;
15510       stream->need_split = TRUE;
15511       break;
15512     case FOURCC_c708:
15513       _codec ("CEA 708 Closed Caption");
15514       caps =
15515           gst_caps_new_simple ("closedcaption/x-cea-708", "format",
15516           G_TYPE_STRING, "cdp", NULL);
15517       stream->need_process = TRUE;
15518       break;
15519
15520     default:
15521     {
15522       caps = _get_unknown_codec_name ("text", fourcc);
15523       break;
15524     }
15525   }
15526   return caps;
15527 }
15528
15529 static GstCaps *
15530 qtdemux_generic_caps (GstQTDemux * qtdemux, QtDemuxStream * stream,
15531     QtDemuxStreamStsdEntry * entry, guint32 fourcc,
15532     const guint8 * stsd_entry_data, gchar ** codec_name)
15533 {
15534   GstCaps *caps;
15535
15536   switch (fourcc) {
15537     case FOURCC_m1v:
15538       _codec ("MPEG 1 video");
15539       caps = gst_caps_new_simple ("video/mpeg", "mpegversion", G_TYPE_INT, 1,
15540           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
15541       break;
15542     default:
15543       caps = NULL;
15544       break;
15545   }
15546   return caps;
15547 }
15548
15549 static void
15550 gst_qtdemux_append_protection_system_id (GstQTDemux * qtdemux,
15551     const gchar * system_id)
15552 {
15553   gint i;
15554
15555   if (!qtdemux->protection_system_ids)
15556     qtdemux->protection_system_ids =
15557         g_ptr_array_new_with_free_func ((GDestroyNotify) g_free);
15558   /* Check whether we already have an entry for this system ID. */
15559   for (i = 0; i < qtdemux->protection_system_ids->len; ++i) {
15560     const gchar *id = g_ptr_array_index (qtdemux->protection_system_ids, i);
15561     if (g_ascii_strcasecmp (system_id, id) == 0) {
15562       return;
15563     }
15564   }
15565   GST_DEBUG_OBJECT (qtdemux, "Adding cenc protection system ID %s", system_id);
15566   g_ptr_array_add (qtdemux->protection_system_ids, g_ascii_strdown (system_id,
15567           -1));
15568 }