qtdemux: Avoid warning when reporting about decryptors
[platform/upstream/gst-plugins-good.git] / gst / isomp4 / qtdemux.c
1 /* GStreamer
2  * Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu>
3  * Copyright (C) <2003> David A. Schleef <ds@schleef.org>
4  * Copyright (C) <2006> Wim Taymans <wim@fluendo.com>
5  * Copyright (C) <2007> Julien Moutte <julien@fluendo.com>
6  * Copyright (C) <2009> Tim-Philipp Müller <tim centricular net>
7  * Copyright (C) <2009> STEricsson <benjamin.gaignard@stericsson.com>
8  * Copyright (C) <2013> Sreerenj Balachandran <sreerenj.balachandran@intel.com>
9  * Copyright (C) <2013> Intel Corporation
10  * Copyright (C) <2014> Centricular Ltd
11  * Copyright (C) <2015> YouView TV Ltd.
12  * Copyright (C) <2016> British Broadcasting Corporation
13  *
14  * This library is free software; you can redistribute it and/or
15  * modify it under the terms of the GNU Library General Public
16  * License as published by the Free Software Foundation; either
17  * version 2 of the License, or (at your option) any later version.
18  *
19  * This library is distributed in the hope that it will be useful,
20  * but WITHOUT ANY WARRANTY; without even the implied warranty of
21  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
22  * Library General Public License for more details.
23  *
24  * You should have received a copy of the GNU Library General Public
25  * License along with this library; if not, write to the
26  * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
27  * Boston, MA 02110-1301, USA.
28  */
29
30 /**
31  * SECTION:element-qtdemux
32  *
33  * Demuxes a .mov file into raw or compressed audio and/or video streams.
34  *
35  * This element supports both push and pull-based scheduling, depending on the
36  * capabilities of the upstream elements.
37  *
38  * <refsect2>
39  * <title>Example launch line</title>
40  * |[
41  * gst-launch-1.0 filesrc location=test.mov ! qtdemux name=demux  demux.audio_0 ! queue ! decodebin ! audioconvert ! audioresample ! autoaudiosink   demux.video_0 ! queue ! decodebin ! videoconvert ! videoscale ! autovideosink
42  * ]| Play (parse and decode) a .mov file and try to output it to
43  * an automatically detected soundcard and videosink. If the MOV file contains
44  * compressed audio or video data, this will only work if you have the
45  * right decoder elements/plugins installed.
46  * </refsect2>
47  */
48
49 #ifdef HAVE_CONFIG_H
50 #include "config.h"
51 #endif
52
53 #include "gst/gst-i18n-plugin.h"
54
55 #include <glib/gprintf.h>
56 #include <gst/tag/tag.h>
57 #include <gst/audio/audio.h>
58 #include <gst/video/video.h>
59 #include <gst/riff/riff.h>
60 #include <gst/pbutils/pbutils.h>
61
62 #include "qtatomparser.h"
63 #include "qtdemux_types.h"
64 #include "qtdemux_dump.h"
65 #include "fourcc.h"
66 #include "descriptors.h"
67 #include "qtdemux_lang.h"
68 #include "qtdemux.h"
69 #include "qtpalette.h"
70
71 #include <stdio.h>
72 #include <stdlib.h>
73 #include <string.h>
74
75 #include <math.h>
76 #include <gst/math-compat.h>
77
78 #ifdef HAVE_ZLIB
79 # include <zlib.h>
80 #endif
81
82 /* max. size considered 'sane' for non-mdat atoms */
83 #define QTDEMUX_MAX_ATOM_SIZE (25*1024*1024)
84
85 /* if the sample index is larger than this, something is likely wrong */
86 #define QTDEMUX_MAX_SAMPLE_INDEX_SIZE (200*1024*1024)
87
88 /* For converting qt creation times to unix epoch times */
89 #define QTDEMUX_SECONDS_PER_DAY (60 * 60 * 24)
90 #define QTDEMUX_LEAP_YEARS_FROM_1904_TO_1970 17
91 #define QTDEMUX_SECONDS_FROM_1904_TO_1970 (((1970 - 1904) * (guint64) 365 + \
92     QTDEMUX_LEAP_YEARS_FROM_1904_TO_1970) * QTDEMUX_SECONDS_PER_DAY)
93
94 #define QTDEMUX_TREE_NODE_FOURCC(n) (QT_FOURCC(((guint8 *) (n)->data) + 4))
95
96 #define STREAM_IS_EOS(s) ((s)->time_position == GST_CLOCK_TIME_NONE)
97
98 #define ABSDIFF(x, y) ( (x) > (y) ? ((x) - (y)) : ((y) - (x)) )
99
100 #define QTDEMUX_FIRST_STREAM(demux) ((QtDemuxStream *)(demux)->active_streams \
101   ? (QtDemuxStream *)(demux)->active_streams->data : NULL)
102 #define QTDEMUX_STREAM(s) ((QtDemuxStream *)(s))
103
104 GST_DEBUG_CATEGORY (qtdemux_debug);
105 #define GST_CAT_DEFAULT qtdemux_debug
106
107 typedef struct _QtDemuxSegment QtDemuxSegment;
108 typedef struct _QtDemuxSample QtDemuxSample;
109
110 typedef struct _QtDemuxCencSampleSetInfo QtDemuxCencSampleSetInfo;
111
112 struct _QtDemuxSample
113 {
114   guint32 size;
115   gint32 pts_offset;            /* Add this value to timestamp to get the pts */
116   guint64 offset;
117   guint64 timestamp;            /* DTS In mov time */
118   guint32 duration;             /* In mov time */
119   gboolean keyframe;            /* TRUE when this packet is a keyframe */
120 };
121
122 /* Macros for converting to/from timescale */
123 #define QTSTREAMTIME_TO_GSTTIME(stream, value) (gst_util_uint64_scale((value), GST_SECOND, (stream)->timescale))
124 #define GSTTIME_TO_QTSTREAMTIME(stream, value) (gst_util_uint64_scale((value), (stream)->timescale, GST_SECOND))
125
126 #define QTTIME_TO_GSTTIME(qtdemux, value) (gst_util_uint64_scale((value), GST_SECOND, (qtdemux)->timescale))
127 #define GSTTIME_TO_QTTIME(qtdemux, value) (gst_util_uint64_scale((value), (qtdemux)->timescale, GST_SECOND))
128
129 /* timestamp is the DTS */
130 #define QTSAMPLE_DTS(stream,sample) (QTSTREAMTIME_TO_GSTTIME((stream), (sample)->timestamp))
131 /* timestamp + offset + cslg_shift is the outgoing PTS */
132 #define QTSAMPLE_PTS(stream,sample) (QTSTREAMTIME_TO_GSTTIME((stream), (sample)->timestamp + (stream)->cslg_shift + (sample)->pts_offset))
133 /* timestamp + offset is the PTS used for internal seek calcuations */
134 #define QTSAMPLE_PTS_NO_CSLG(stream,sample) (QTSTREAMTIME_TO_GSTTIME((stream), (sample)->timestamp + (sample)->pts_offset))
135 /* timestamp + duration - dts is the duration */
136 #define QTSAMPLE_DUR_DTS(stream, sample, dts) (QTSTREAMTIME_TO_GSTTIME ((stream), (sample)->timestamp + (sample)->duration) - (dts))
137
138 #define QTSAMPLE_KEYFRAME(stream,sample) ((stream)->all_keyframe || (sample)->keyframe)
139
140 #define QTDEMUX_EXPOSE_GET_LOCK(demux) (&((demux)->expose_lock))
141 #define QTDEMUX_EXPOSE_LOCK(demux) G_STMT_START { \
142     GST_TRACE("Locking from thread %p", g_thread_self()); \
143     g_mutex_lock (QTDEMUX_EXPOSE_GET_LOCK (demux)); \
144     GST_TRACE("Locked from thread %p", g_thread_self()); \
145  } G_STMT_END
146
147 #define QTDEMUX_EXPOSE_UNLOCK(demux) G_STMT_START { \
148     GST_TRACE("Unlocking from thread %p", g_thread_self()); \
149     g_mutex_unlock (QTDEMUX_EXPOSE_GET_LOCK (demux)); \
150  } G_STMT_END
151
152 /*
153  * Quicktime has tracks and segments. A track is a continuous piece of
154  * multimedia content. The track is not always played from start to finish but
155  * instead, pieces of the track are 'cut out' and played in sequence. This is
156  * what the segments do.
157  *
158  * Inside the track we have keyframes (K) and delta frames. The track has its
159  * own timing, which starts from 0 and extends to end. The position in the track
160  * is called the media_time.
161  *
162  * The segments now describe the pieces that should be played from this track
163  * and are basically tuples of media_time/duration/rate entries. We can have
164  * multiple segments and they are all played after one another. An example:
165  *
166  * segment 1: media_time: 1 second, duration: 1 second, rate 1
167  * segment 2: media_time: 3 second, duration: 2 second, rate 2
168  *
169  * To correctly play back this track, one must play: 1 second of media starting
170  * from media_time 1 followed by 2 seconds of media starting from media_time 3
171  * at a rate of 2.
172  *
173  * Each of the segments will be played at a specific time, the first segment at
174  * time 0, the second one after the duration of the first one, etc.. Note that
175  * the time in resulting playback is not identical to the media_time of the
176  * track anymore.
177  *
178  * Visually, assuming the track has 4 second of media_time:
179  *
180  *                (a)                   (b)          (c)              (d)
181  *         .-----------------------------------------------------------.
182  * track:  | K.....K.........K........K.......K.......K...........K... |
183  *         '-----------------------------------------------------------'
184  *         0              1              2              3              4
185  *           .------------^              ^   .----------^              ^
186  *          /              .-------------'  /       .------------------'
187  *         /              /          .-----'       /
188  *         .--------------.         .--------------.
189  *         | segment 1    |         | segment 2    |
190  *         '--------------'         '--------------'
191  *
192  * The challenge here is to cut out the right pieces of the track for each of
193  * the playback segments. This fortunately can easily be done with the SEGMENT
194  * events of GStreamer.
195  *
196  * For playback of segment 1, we need to provide the decoder with the keyframe
197  * (a), in the above figure, but we must instruct it only to output the decoded
198  * data between second 1 and 2. We do this with a SEGMENT event for 1 to 2, time
199  * position set to the time of the segment: 0.
200  *
201  * We then proceed to push data from keyframe (a) to frame (b). The decoder
202  * decodes but clips all before media_time 1.
203  *
204  * After finishing a segment, we push out a new SEGMENT event with the clipping
205  * boundaries of the new data.
206  *
207  * This is a good usecase for the GStreamer accumulated SEGMENT events.
208  */
209
210 struct _QtDemuxSegment
211 {
212   /* global time and duration, all gst time */
213   GstClockTime time;
214   GstClockTime stop_time;
215   GstClockTime duration;
216   /* media time of trak, all gst time */
217   GstClockTime media_start;
218   GstClockTime media_stop;
219   gdouble rate;
220   /* Media start time in trak timescale units */
221   guint32 trak_media_start;
222 };
223
224 #define QTSEGMENT_IS_EMPTY(s) ((s)->media_start == GST_CLOCK_TIME_NONE)
225
226 /* Used with fragmented MP4 files (mfra atom) */
227 typedef struct
228 {
229   GstClockTime ts;
230   guint64 moof_offset;
231 } QtDemuxRandomAccessEntry;
232
233 typedef struct _QtDemuxStreamStsdEntry
234 {
235   GstCaps *caps;
236   guint32 fourcc;
237   gboolean sparse;
238
239   /* video info */
240   gint width;
241   gint height;
242   gint par_w;
243   gint par_h;
244   /* Numerator/denominator framerate */
245   gint fps_n;
246   gint fps_d;
247   GstVideoColorimetry colorimetry;
248   guint16 bits_per_sample;
249   guint16 color_table_id;
250   GstMemory *rgb8_palette;
251   guint interlace_mode;
252   guint field_order;
253
254   /* audio info */
255   gdouble rate;
256   gint n_channels;
257   guint samples_per_packet;
258   guint samples_per_frame;
259   guint bytes_per_packet;
260   guint bytes_per_sample;
261   guint bytes_per_frame;
262   guint compression;
263
264   /* if we use chunks or samples */
265   gboolean sampled;
266   guint padding;
267
268 } QtDemuxStreamStsdEntry;
269
270 #define CUR_STREAM(s) (&((s)->stsd_entries[(s)->cur_stsd_entry_index]))
271
272 struct _QtDemuxStream
273 {
274   GstPad *pad;
275
276   GstQTDemux *demux;
277   gchar *stream_id;
278
279   QtDemuxStreamStsdEntry *stsd_entries;
280   guint stsd_entries_length;
281   guint cur_stsd_entry_index;
282
283   /* stream type */
284   guint32 subtype;
285
286   gboolean new_caps;            /* If TRUE, caps need to be generated (by
287                                  * calling _configure_stream()) This happens
288                                  * for MSS and fragmented streams */
289
290   gboolean new_stream;          /* signals that a stream_start is required */
291   gboolean on_keyframe;         /* if this stream last pushed buffer was a
292                                  * keyframe. This is important to identify
293                                  * where to stop pushing buffers after a
294                                  * segment stop time */
295
296   /* if the stream has a redirect URI in its headers, we store it here */
297   gchar *redirect_uri;
298
299   /* track id */
300   guint track_id;
301
302   /* duration/scale */
303   guint64 duration;             /* in timescale units */
304   guint32 timescale;
305
306   /* language */
307   gchar lang_id[4];             /* ISO 639-2T language code */
308
309   /* our samples */
310   guint32 n_samples;
311   QtDemuxSample *samples;
312   gboolean all_keyframe;        /* TRUE when all samples are keyframes (no stss) */
313   guint32 n_samples_moof;       /* sample count in a moof */
314   guint64 duration_moof;        /* duration in timescale of a moof, used for figure out
315                                  * the framerate of fragmented format stream */
316   guint64 duration_last_moof;
317
318   guint32 offset_in_sample;     /* Offset in the current sample, used for
319                                  * streams which have got exceedingly big
320                                  * sample size (such as 24s of raw audio).
321                                  * Only used when max_buffer_size is non-NULL */
322   guint32 max_buffer_size;      /* Maximum allowed size for output buffers.
323                                  * Currently only set for raw audio streams*/
324
325   /* video info */
326   /* aspect ratio */
327   gint display_width;
328   gint display_height;
329
330   /* allocation */
331   gboolean use_allocator;
332   GstAllocator *allocator;
333   GstAllocationParams params;
334
335   gsize alignment;
336
337   /* when a discontinuity is pending */
338   gboolean discont;
339
340   /* list of buffers to push first */
341   GSList *buffers;
342
343   /* if we need to clip this buffer. This is only needed for uncompressed
344    * data */
345   gboolean need_clip;
346
347   /* buffer needs some custom processing, e.g. subtitles */
348   gboolean need_process;
349
350   /* current position */
351   guint32 segment_index;
352   guint32 sample_index;
353   GstClockTime time_position;   /* in gst time */
354   guint64 accumulated_base;
355
356   /* the Gst segment we are processing out, used for clipping */
357   GstSegment segment;
358
359   /* quicktime segments */
360   guint32 n_segments;
361   QtDemuxSegment *segments;
362   gboolean dummy_segment;
363   guint32 from_sample;
364   guint32 to_sample;
365
366   gboolean sent_eos;
367   GstTagList *stream_tags;
368   gboolean send_global_tags;
369
370   GstEvent *pending_event;
371
372   GstByteReader stco;
373   GstByteReader stsz;
374   GstByteReader stsc;
375   GstByteReader stts;
376   GstByteReader stss;
377   GstByteReader stps;
378   GstByteReader ctts;
379
380   gboolean chunks_are_samples;  /* TRUE means treat chunks as samples */
381   gint64 stbl_index;
382   /* stco */
383   guint co_size;
384   GstByteReader co_chunk;
385   guint32 first_chunk;
386   guint32 current_chunk;
387   guint32 last_chunk;
388   guint32 samples_per_chunk;
389   guint32 stsd_sample_description_id;
390   guint32 stco_sample_index;
391   /* stsz */
392   guint32 sample_size;          /* 0 means variable sizes are stored in stsz */
393   /* stsc */
394   guint32 stsc_index;
395   guint32 n_samples_per_chunk;
396   guint32 stsc_chunk_index;
397   guint32 stsc_sample_index;
398   guint64 chunk_offset;
399   /* stts */
400   guint32 stts_index;
401   guint32 stts_samples;
402   guint32 n_sample_times;
403   guint32 stts_sample_index;
404   guint64 stts_time;
405   guint32 stts_duration;
406   /* stss */
407   gboolean stss_present;
408   guint32 n_sample_syncs;
409   guint32 stss_index;
410   /* stps */
411   gboolean stps_present;
412   guint32 n_sample_partial_syncs;
413   guint32 stps_index;
414   QtDemuxRandomAccessEntry *ra_entries;
415   guint n_ra_entries;
416
417   const QtDemuxRandomAccessEntry *pending_seek;
418
419   /* ctts */
420   gboolean ctts_present;
421   guint32 n_composition_times;
422   guint32 ctts_index;
423   guint32 ctts_sample_index;
424   guint32 ctts_count;
425   gint32 ctts_soffset;
426
427   /* cslg */
428   guint32 cslg_shift;
429
430   /* fragmented */
431   gboolean parsed_trex;
432   guint32 def_sample_description_index; /* index is 1-based */
433   guint32 def_sample_duration;
434   guint32 def_sample_size;
435   guint32 def_sample_flags;
436
437   gboolean disabled;
438
439   /* stereoscopic video streams */
440   GstVideoMultiviewMode multiview_mode;
441   GstVideoMultiviewFlags multiview_flags;
442
443   /* protected streams */
444   gboolean protected;
445   guint32 protection_scheme_type;
446   guint32 protection_scheme_version;
447   gpointer protection_scheme_info;      /* specific to the protection scheme */
448   GQueue protection_scheme_event_queue;
449 };
450
451 /* Contains properties and cryptographic info for a set of samples from a
452  * track protected using Common Encryption (cenc) */
453 struct _QtDemuxCencSampleSetInfo
454 {
455   GstStructure *default_properties;
456
457   /* @crypto_info holds one GstStructure per sample */
458   GPtrArray *crypto_info;
459 };
460
461 static const gchar *
462 qt_demux_state_string (enum QtDemuxState state)
463 {
464   switch (state) {
465     case QTDEMUX_STATE_INITIAL:
466       return "<INITIAL>";
467     case QTDEMUX_STATE_HEADER:
468       return "<HEADER>";
469     case QTDEMUX_STATE_MOVIE:
470       return "<MOVIE>";
471     case QTDEMUX_STATE_BUFFER_MDAT:
472       return "<BUFFER_MDAT>";
473     default:
474       return "<UNKNOWN>";
475   }
476 }
477
478 static GNode *qtdemux_tree_get_child_by_type (GNode * node, guint32 fourcc);
479 static GNode *qtdemux_tree_get_child_by_type_full (GNode * node,
480     guint32 fourcc, GstByteReader * parser);
481 static GNode *qtdemux_tree_get_sibling_by_type (GNode * node, guint32 fourcc);
482 static GNode *qtdemux_tree_get_sibling_by_type_full (GNode * node,
483     guint32 fourcc, GstByteReader * parser);
484
485 static GstFlowReturn qtdemux_add_fragmented_samples (GstQTDemux * qtdemux);
486
487 static void gst_qtdemux_check_send_pending_segment (GstQTDemux * demux);
488
489 static GstStaticPadTemplate gst_qtdemux_sink_template =
490     GST_STATIC_PAD_TEMPLATE ("sink",
491     GST_PAD_SINK,
492     GST_PAD_ALWAYS,
493     GST_STATIC_CAPS ("video/quicktime; video/mj2; audio/x-m4a; "
494         "application/x-3gp")
495     );
496
497 static GstStaticPadTemplate gst_qtdemux_videosrc_template =
498 GST_STATIC_PAD_TEMPLATE ("video_%u",
499     GST_PAD_SRC,
500     GST_PAD_SOMETIMES,
501     GST_STATIC_CAPS_ANY);
502
503 static GstStaticPadTemplate gst_qtdemux_audiosrc_template =
504 GST_STATIC_PAD_TEMPLATE ("audio_%u",
505     GST_PAD_SRC,
506     GST_PAD_SOMETIMES,
507     GST_STATIC_CAPS_ANY);
508
509 static GstStaticPadTemplate gst_qtdemux_subsrc_template =
510 GST_STATIC_PAD_TEMPLATE ("subtitle_%u",
511     GST_PAD_SRC,
512     GST_PAD_SOMETIMES,
513     GST_STATIC_CAPS_ANY);
514
515 #define gst_qtdemux_parent_class parent_class
516 G_DEFINE_TYPE (GstQTDemux, gst_qtdemux, GST_TYPE_ELEMENT);
517
518 static void gst_qtdemux_dispose (GObject * object);
519
520 static guint32
521 gst_qtdemux_find_index_linear (GstQTDemux * qtdemux, QtDemuxStream * str,
522     GstClockTime media_time);
523 static guint32
524 gst_qtdemux_find_index_for_given_media_offset_linear (GstQTDemux * qtdemux,
525     QtDemuxStream * str, gint64 media_offset);
526
527 #if 0
528 static void gst_qtdemux_set_index (GstElement * element, GstIndex * index);
529 static GstIndex *gst_qtdemux_get_index (GstElement * element);
530 #endif
531 static GstStateChangeReturn gst_qtdemux_change_state (GstElement * element,
532     GstStateChange transition);
533 static void gst_qtdemux_set_context (GstElement * element,
534     GstContext * context);
535 static gboolean qtdemux_sink_activate (GstPad * sinkpad, GstObject * parent);
536 static gboolean qtdemux_sink_activate_mode (GstPad * sinkpad,
537     GstObject * parent, GstPadMode mode, gboolean active);
538
539 static void gst_qtdemux_loop (GstPad * pad);
540 static GstFlowReturn gst_qtdemux_chain (GstPad * sinkpad, GstObject * parent,
541     GstBuffer * inbuf);
542 static gboolean gst_qtdemux_handle_sink_event (GstPad * pad, GstObject * parent,
543     GstEvent * event);
544 static gboolean gst_qtdemux_setcaps (GstQTDemux * qtdemux, GstCaps * caps);
545 static gboolean gst_qtdemux_configure_stream (GstQTDemux * qtdemux,
546     QtDemuxStream * stream);
547 static void gst_qtdemux_stream_check_and_change_stsd_index (GstQTDemux * demux,
548     QtDemuxStream * stream);
549 static GstFlowReturn gst_qtdemux_process_adapter (GstQTDemux * demux,
550     gboolean force);
551
552 static gboolean qtdemux_parse_moov (GstQTDemux * qtdemux,
553     const guint8 * buffer, guint length);
554 static gboolean qtdemux_parse_node (GstQTDemux * qtdemux, GNode * node,
555     const guint8 * buffer, guint length);
556 static gboolean qtdemux_parse_tree (GstQTDemux * qtdemux);
557 static void qtdemux_parse_udta (GstQTDemux * qtdemux, GstTagList * taglist,
558     GNode * udta);
559
560 static void gst_qtdemux_handle_esds (GstQTDemux * qtdemux,
561     QtDemuxStream * stream, QtDemuxStreamStsdEntry * entry, GNode * esds,
562     GstTagList * list);
563 static GstCaps *qtdemux_video_caps (GstQTDemux * qtdemux,
564     QtDemuxStream * stream, QtDemuxStreamStsdEntry * entry, guint32 fourcc,
565     const guint8 * stsd_entry_data, gchar ** codec_name);
566 static GstCaps *qtdemux_audio_caps (GstQTDemux * qtdemux,
567     QtDemuxStream * stream, QtDemuxStreamStsdEntry * entry, guint32 fourcc,
568     const guint8 * data, int len, gchar ** codec_name);
569 static GstCaps *qtdemux_sub_caps (GstQTDemux * qtdemux, QtDemuxStream * stream,
570     QtDemuxStreamStsdEntry * entry, guint32 fourcc, const guint8 * data,
571     gchar ** codec_name);
572 static GstCaps *qtdemux_generic_caps (GstQTDemux * qtdemux,
573     QtDemuxStream * stream, QtDemuxStreamStsdEntry * entry, guint32 fourcc,
574     const guint8 * stsd_entry_data, gchar ** codec_name);
575
576 static gboolean qtdemux_parse_samples (GstQTDemux * qtdemux,
577     QtDemuxStream * stream, guint32 n);
578 static GstFlowReturn qtdemux_expose_streams (GstQTDemux * qtdemux);
579 static void gst_qtdemux_stream_free (QtDemuxStream * stream);
580 static void gst_qtdemux_stream_clear (QtDemuxStream * stream);
581 static void gst_qtdemux_remove_stream (GstQTDemux * qtdemux,
582     QtDemuxStream * stream);
583 static GstFlowReturn qtdemux_prepare_streams (GstQTDemux * qtdemux);
584 static void qtdemux_do_allocation (GstQTDemux * qtdemux,
585     QtDemuxStream * stream);
586 static gboolean gst_qtdemux_activate_segment (GstQTDemux * qtdemux,
587     QtDemuxStream * stream, guint32 seg_idx, GstClockTime offset);
588 static gboolean gst_qtdemux_stream_update_segment (GstQTDemux * qtdemux,
589     QtDemuxStream * stream, gint seg_idx, GstClockTime offset,
590     GstClockTime * _start, GstClockTime * _stop);
591 static void gst_qtdemux_send_gap_for_segment (GstQTDemux * demux,
592     QtDemuxStream * stream, gint segment_index, GstClockTime pos);
593
594 static gboolean qtdemux_pull_mfro_mfra (GstQTDemux * qtdemux);
595 static void check_update_duration (GstQTDemux * qtdemux, GstClockTime duration);
596
597 static gchar *qtdemux_uuid_bytes_to_string (gconstpointer uuid_bytes);
598
599 static GstStructure *qtdemux_get_cenc_sample_properties (GstQTDemux * qtdemux,
600     QtDemuxStream * stream, guint sample_index);
601 static void gst_qtdemux_append_protection_system_id (GstQTDemux * qtdemux,
602     const gchar * id);
603 static void qtdemux_gst_structure_free (GstStructure * gststructure);
604 static void gst_qtdemux_reset (GstQTDemux * qtdemux, gboolean hard);
605
606 static void
607 gst_qtdemux_class_init (GstQTDemuxClass * klass)
608 {
609   GObjectClass *gobject_class;
610   GstElementClass *gstelement_class;
611
612   gobject_class = (GObjectClass *) klass;
613   gstelement_class = (GstElementClass *) klass;
614
615   parent_class = g_type_class_peek_parent (klass);
616
617   gobject_class->dispose = gst_qtdemux_dispose;
618
619   gstelement_class->change_state = GST_DEBUG_FUNCPTR (gst_qtdemux_change_state);
620 #if 0
621   gstelement_class->set_index = GST_DEBUG_FUNCPTR (gst_qtdemux_set_index);
622   gstelement_class->get_index = GST_DEBUG_FUNCPTR (gst_qtdemux_get_index);
623 #endif
624   gstelement_class->set_context = GST_DEBUG_FUNCPTR (gst_qtdemux_set_context);
625
626   gst_tag_register_musicbrainz_tags ();
627
628   gst_element_class_add_static_pad_template (gstelement_class,
629       &gst_qtdemux_sink_template);
630   gst_element_class_add_static_pad_template (gstelement_class,
631       &gst_qtdemux_videosrc_template);
632   gst_element_class_add_static_pad_template (gstelement_class,
633       &gst_qtdemux_audiosrc_template);
634   gst_element_class_add_static_pad_template (gstelement_class,
635       &gst_qtdemux_subsrc_template);
636   gst_element_class_set_static_metadata (gstelement_class, "QuickTime demuxer",
637       "Codec/Demuxer",
638       "Demultiplex a QuickTime file into audio and video streams",
639       "David Schleef <ds@schleef.org>, Wim Taymans <wim@fluendo.com>");
640
641   GST_DEBUG_CATEGORY_INIT (qtdemux_debug, "qtdemux", 0, "qtdemux plugin");
642   gst_riff_init ();
643 }
644
645 static void
646 gst_qtdemux_init (GstQTDemux * qtdemux)
647 {
648   qtdemux->sinkpad =
649       gst_pad_new_from_static_template (&gst_qtdemux_sink_template, "sink");
650   gst_pad_set_activate_function (qtdemux->sinkpad, qtdemux_sink_activate);
651   gst_pad_set_activatemode_function (qtdemux->sinkpad,
652       qtdemux_sink_activate_mode);
653   gst_pad_set_chain_function (qtdemux->sinkpad, gst_qtdemux_chain);
654   gst_pad_set_event_function (qtdemux->sinkpad, gst_qtdemux_handle_sink_event);
655   gst_element_add_pad (GST_ELEMENT_CAST (qtdemux), qtdemux->sinkpad);
656
657   qtdemux->adapter = gst_adapter_new ();
658   g_queue_init (&qtdemux->protection_event_queue);
659   qtdemux->flowcombiner = gst_flow_combiner_new ();
660   g_mutex_init (&qtdemux->expose_lock);
661
662   GST_OBJECT_FLAG_SET (qtdemux, GST_ELEMENT_FLAG_INDEXABLE);
663
664   gst_qtdemux_reset (qtdemux, TRUE);
665 }
666
667 static void
668 gst_qtdemux_dispose (GObject * object)
669 {
670   GstQTDemux *qtdemux = GST_QTDEMUX (object);
671
672   if (qtdemux->adapter) {
673     g_object_unref (G_OBJECT (qtdemux->adapter));
674     qtdemux->adapter = NULL;
675   }
676   gst_tag_list_unref (qtdemux->tag_list);
677   gst_flow_combiner_free (qtdemux->flowcombiner);
678   g_queue_foreach (&qtdemux->protection_event_queue, (GFunc) gst_event_unref,
679       NULL);
680   g_queue_clear (&qtdemux->protection_event_queue);
681
682   g_free (qtdemux->cenc_aux_info_sizes);
683   qtdemux->cenc_aux_info_sizes = NULL;
684   g_mutex_clear (&qtdemux->expose_lock);
685
686   G_OBJECT_CLASS (parent_class)->dispose (object);
687 }
688
689 static void
690 gst_qtdemux_post_no_playable_stream_error (GstQTDemux * qtdemux)
691 {
692   if (qtdemux->posted_redirect) {
693     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
694         (_("This file contains no playable streams.")),
695         ("no known streams found, a redirect message has been posted"));
696   } else {
697     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
698         (_("This file contains no playable streams.")),
699         ("no known streams found"));
700   }
701 }
702
703 static GstBuffer *
704 _gst_buffer_new_wrapped (gpointer mem, gsize size, GFreeFunc free_func)
705 {
706   return gst_buffer_new_wrapped_full (free_func ? 0 : GST_MEMORY_FLAG_READONLY,
707       mem, size, 0, size, mem, free_func);
708 }
709
710 static GstFlowReturn
711 gst_qtdemux_pull_atom (GstQTDemux * qtdemux, guint64 offset, guint64 size,
712     GstBuffer ** buf)
713 {
714   GstFlowReturn flow;
715   GstMapInfo map;
716   gsize bsize;
717
718   if (G_UNLIKELY (size == 0)) {
719     GstFlowReturn ret;
720     GstBuffer *tmp = NULL;
721
722     ret = gst_qtdemux_pull_atom (qtdemux, offset, sizeof (guint32), &tmp);
723     if (ret != GST_FLOW_OK)
724       return ret;
725
726     gst_buffer_map (tmp, &map, GST_MAP_READ);
727     size = QT_UINT32 (map.data);
728     GST_DEBUG_OBJECT (qtdemux, "size 0x%08" G_GINT64_MODIFIER "x", size);
729
730     gst_buffer_unmap (tmp, &map);
731     gst_buffer_unref (tmp);
732   }
733
734   /* Sanity check: catch bogus sizes (fuzzed/broken files) */
735   if (G_UNLIKELY (size > QTDEMUX_MAX_ATOM_SIZE)) {
736     if (qtdemux->state != QTDEMUX_STATE_MOVIE && qtdemux->got_moov) {
737       /* we're pulling header but already got most interesting bits,
738        * so never mind the rest (e.g. tags) (that much) */
739       GST_WARNING_OBJECT (qtdemux, "atom has bogus size %" G_GUINT64_FORMAT,
740           size);
741       return GST_FLOW_EOS;
742     } else {
743       GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
744           (_("This file is invalid and cannot be played.")),
745           ("atom has bogus size %" G_GUINT64_FORMAT, size));
746       return GST_FLOW_ERROR;
747     }
748   }
749
750   flow = gst_pad_pull_range (qtdemux->sinkpad, offset, size, buf);
751
752   if (G_UNLIKELY (flow != GST_FLOW_OK))
753     return flow;
754
755   bsize = gst_buffer_get_size (*buf);
756   /* Catch short reads - we don't want any partial atoms */
757   if (G_UNLIKELY (bsize < size)) {
758     GST_WARNING_OBJECT (qtdemux,
759         "short read: %" G_GSIZE_FORMAT " < %" G_GUINT64_FORMAT, bsize, size);
760     gst_buffer_unref (*buf);
761     *buf = NULL;
762     return GST_FLOW_EOS;
763   }
764
765   return flow;
766 }
767
768 #if 1
769 static gboolean
770 gst_qtdemux_src_convert (GstQTDemux * qtdemux, GstPad * pad,
771     GstFormat src_format, gint64 src_value, GstFormat dest_format,
772     gint64 * dest_value)
773 {
774   gboolean res = TRUE;
775   QtDemuxStream *stream = gst_pad_get_element_private (pad);
776   gint32 index;
777
778   if (stream->subtype != FOURCC_vide) {
779     res = FALSE;
780     goto done;
781   }
782
783   switch (src_format) {
784     case GST_FORMAT_TIME:
785       switch (dest_format) {
786         case GST_FORMAT_BYTES:{
787           index = gst_qtdemux_find_index_linear (qtdemux, stream, src_value);
788           if (-1 == index) {
789             res = FALSE;
790             goto done;
791           }
792
793           *dest_value = stream->samples[index].offset;
794
795           GST_DEBUG_OBJECT (qtdemux, "Format Conversion Time->Offset :%"
796               GST_TIME_FORMAT "->%" G_GUINT64_FORMAT,
797               GST_TIME_ARGS (src_value), *dest_value);
798           break;
799         }
800         default:
801           res = FALSE;
802           break;
803       }
804       break;
805     case GST_FORMAT_BYTES:
806       switch (dest_format) {
807         case GST_FORMAT_TIME:{
808           index =
809               gst_qtdemux_find_index_for_given_media_offset_linear (qtdemux,
810               stream, src_value);
811
812           if (-1 == index) {
813             res = FALSE;
814             goto done;
815           }
816
817           *dest_value =
818               QTSTREAMTIME_TO_GSTTIME (stream,
819               stream->samples[index].timestamp);
820           GST_DEBUG_OBJECT (qtdemux,
821               "Format Conversion Offset->Time :%" G_GUINT64_FORMAT "->%"
822               GST_TIME_FORMAT, src_value, GST_TIME_ARGS (*dest_value));
823           break;
824         }
825         default:
826           res = FALSE;
827           break;
828       }
829       break;
830     default:
831       res = FALSE;
832       break;
833   }
834
835 done:
836   return res;
837 }
838 #endif
839
840 static gboolean
841 gst_qtdemux_get_duration (GstQTDemux * qtdemux, GstClockTime * duration)
842 {
843   gboolean res = FALSE;
844
845   *duration = GST_CLOCK_TIME_NONE;
846
847   if (qtdemux->duration != 0 &&
848       qtdemux->duration != G_MAXINT64 && qtdemux->timescale != 0) {
849     *duration = QTTIME_TO_GSTTIME (qtdemux, qtdemux->duration);
850     res = TRUE;
851   } else {
852     *duration = GST_CLOCK_TIME_NONE;
853   }
854
855   return res;
856 }
857
858 static gboolean
859 gst_qtdemux_handle_src_query (GstPad * pad, GstObject * parent,
860     GstQuery * query)
861 {
862   gboolean res = FALSE;
863   GstQTDemux *qtdemux = GST_QTDEMUX (parent);
864
865   GST_LOG_OBJECT (pad, "%s query", GST_QUERY_TYPE_NAME (query));
866
867   switch (GST_QUERY_TYPE (query)) {
868     case GST_QUERY_POSITION:{
869       GstFormat fmt;
870
871       gst_query_parse_position (query, &fmt, NULL);
872       if (fmt == GST_FORMAT_TIME
873           && GST_CLOCK_TIME_IS_VALID (qtdemux->segment.position)) {
874         gst_query_set_position (query, GST_FORMAT_TIME,
875             qtdemux->segment.position);
876         res = TRUE;
877       }
878     }
879       break;
880     case GST_QUERY_DURATION:{
881       GstFormat fmt;
882
883       gst_query_parse_duration (query, &fmt, NULL);
884       if (fmt == GST_FORMAT_TIME) {
885         /* First try to query upstream */
886         res = gst_pad_query_default (pad, parent, query);
887         if (!res) {
888           GstClockTime duration;
889           if (gst_qtdemux_get_duration (qtdemux, &duration) && duration > 0) {
890             gst_query_set_duration (query, GST_FORMAT_TIME, duration);
891             res = TRUE;
892           }
893         }
894       }
895       break;
896     }
897     case GST_QUERY_CONVERT:{
898       GstFormat src_fmt, dest_fmt;
899       gint64 src_value, dest_value = 0;
900
901       gst_query_parse_convert (query, &src_fmt, &src_value, &dest_fmt, NULL);
902
903       res = gst_qtdemux_src_convert (qtdemux, pad,
904           src_fmt, src_value, dest_fmt, &dest_value);
905       if (res)
906         gst_query_set_convert (query, src_fmt, src_value, dest_fmt, dest_value);
907
908       break;
909     }
910     case GST_QUERY_FORMATS:
911       gst_query_set_formats (query, 2, GST_FORMAT_TIME, GST_FORMAT_BYTES);
912       res = TRUE;
913       break;
914     case GST_QUERY_SEEKING:{
915       GstFormat fmt;
916       gboolean seekable;
917
918       /* try upstream first */
919       res = gst_pad_query_default (pad, parent, query);
920
921       if (!res) {
922         gst_query_parse_seeking (query, &fmt, NULL, NULL, NULL);
923         if (fmt == GST_FORMAT_TIME) {
924           GstClockTime duration;
925
926           gst_qtdemux_get_duration (qtdemux, &duration);
927           seekable = TRUE;
928           if (!qtdemux->pullbased) {
929             GstQuery *q;
930
931             /* we might be able with help from upstream */
932             seekable = FALSE;
933             q = gst_query_new_seeking (GST_FORMAT_BYTES);
934             if (gst_pad_peer_query (qtdemux->sinkpad, q)) {
935               gst_query_parse_seeking (q, &fmt, &seekable, NULL, NULL);
936               GST_LOG_OBJECT (qtdemux, "upstream BYTE seekable %d", seekable);
937             }
938             gst_query_unref (q);
939           }
940           gst_query_set_seeking (query, GST_FORMAT_TIME, seekable, 0, duration);
941           res = TRUE;
942         }
943       }
944       break;
945     }
946     case GST_QUERY_SEGMENT:
947     {
948       GstFormat format;
949       gint64 start, stop;
950
951       format = qtdemux->segment.format;
952
953       start =
954           gst_segment_to_stream_time (&qtdemux->segment, format,
955           qtdemux->segment.start);
956       if ((stop = qtdemux->segment.stop) == -1)
957         stop = qtdemux->segment.duration;
958       else
959         stop = gst_segment_to_stream_time (&qtdemux->segment, format, stop);
960
961       gst_query_set_segment (query, qtdemux->segment.rate, format, start, stop);
962       res = TRUE;
963       break;
964     }
965     default:
966       res = gst_pad_query_default (pad, parent, query);
967       break;
968   }
969
970   return res;
971 }
972
973 static void
974 gst_qtdemux_push_tags (GstQTDemux * qtdemux, QtDemuxStream * stream)
975 {
976   if (G_LIKELY (stream->pad)) {
977     GST_DEBUG_OBJECT (qtdemux, "Checking pad %s:%s for tags",
978         GST_DEBUG_PAD_NAME (stream->pad));
979
980     if (!gst_tag_list_is_empty (stream->stream_tags)) {
981       GST_DEBUG_OBJECT (qtdemux, "Sending tags %" GST_PTR_FORMAT,
982           stream->stream_tags);
983       gst_pad_push_event (stream->pad,
984           gst_event_new_tag (gst_tag_list_ref (stream->stream_tags)));
985     }
986
987     if (G_UNLIKELY (stream->send_global_tags)) {
988       GST_DEBUG_OBJECT (qtdemux, "Sending global tags %" GST_PTR_FORMAT,
989           qtdemux->tag_list);
990       gst_pad_push_event (stream->pad,
991           gst_event_new_tag (gst_tag_list_ref (qtdemux->tag_list)));
992       stream->send_global_tags = FALSE;
993     }
994   }
995 }
996
997 /* push event on all source pads; takes ownership of the event */
998 static void
999 gst_qtdemux_push_event (GstQTDemux * qtdemux, GstEvent * event)
1000 {
1001   gboolean has_valid_stream = FALSE;
1002   GstEventType etype = GST_EVENT_TYPE (event);
1003   GList *iter;
1004
1005   GST_DEBUG_OBJECT (qtdemux, "pushing %s event on all source pads",
1006       GST_EVENT_TYPE_NAME (event));
1007
1008   for (iter = qtdemux->active_streams; iter; iter = g_list_next (iter)) {
1009     GstPad *pad;
1010     QtDemuxStream *stream = QTDEMUX_STREAM (iter->data);
1011     GST_DEBUG_OBJECT (qtdemux, "pushing on track-id %u", stream->track_id);
1012
1013     if ((pad = stream->pad)) {
1014       has_valid_stream = TRUE;
1015
1016       if (etype == GST_EVENT_EOS) {
1017         /* let's not send twice */
1018         if (stream->sent_eos)
1019           continue;
1020         stream->sent_eos = TRUE;
1021       }
1022
1023       gst_pad_push_event (pad, gst_event_ref (event));
1024     }
1025   }
1026
1027   gst_event_unref (event);
1028
1029   /* if it is EOS and there are no pads, post an error */
1030   if (!has_valid_stream && etype == GST_EVENT_EOS) {
1031     gst_qtdemux_post_no_playable_stream_error (qtdemux);
1032   }
1033 }
1034
1035 typedef struct
1036 {
1037   guint64 media_time;
1038 } FindData;
1039
1040 static gint
1041 find_func (QtDemuxSample * s1, gint64 * media_time, gpointer user_data)
1042 {
1043   if ((gint64) s1->timestamp > *media_time)
1044     return 1;
1045   if ((gint64) s1->timestamp == *media_time)
1046     return 0;
1047
1048   return -1;
1049 }
1050
1051 /* find the index of the sample that includes the data for @media_time using a
1052  * binary search.  Only to be called in optimized cases of linear search below.
1053  *
1054  * Returns the index of the sample with the corresponding *DTS*.
1055  */
1056 static guint32
1057 gst_qtdemux_find_index (GstQTDemux * qtdemux, QtDemuxStream * str,
1058     guint64 media_time)
1059 {
1060   QtDemuxSample *result;
1061   guint32 index;
1062
1063   /* convert media_time to mov format */
1064   media_time =
1065       gst_util_uint64_scale_ceil (media_time, str->timescale, GST_SECOND);
1066
1067   result = gst_util_array_binary_search (str->samples, str->stbl_index + 1,
1068       sizeof (QtDemuxSample), (GCompareDataFunc) find_func,
1069       GST_SEARCH_MODE_BEFORE, &media_time, NULL);
1070
1071   if (G_LIKELY (result))
1072     index = result - str->samples;
1073   else
1074     index = 0;
1075
1076   return index;
1077 }
1078
1079
1080
1081 /* find the index of the sample that includes the data for @media_offset using a
1082  * linear search
1083  *
1084  * Returns the index of the sample.
1085  */
1086 static guint32
1087 gst_qtdemux_find_index_for_given_media_offset_linear (GstQTDemux * qtdemux,
1088     QtDemuxStream * str, gint64 media_offset)
1089 {
1090   QtDemuxSample *result = str->samples;
1091   guint32 index = 0;
1092
1093   if (result == NULL || str->n_samples == 0)
1094     return -1;
1095
1096   if (media_offset == result->offset)
1097     return index;
1098
1099   result++;
1100   while (index < str->n_samples - 1) {
1101     if (!qtdemux_parse_samples (qtdemux, str, index + 1))
1102       goto parse_failed;
1103
1104     if (media_offset < result->offset)
1105       break;
1106
1107     index++;
1108     result++;
1109   }
1110   return index;
1111
1112   /* ERRORS */
1113 parse_failed:
1114   {
1115     GST_LOG_OBJECT (qtdemux, "Parsing of index %u failed!", index + 1);
1116     return -1;
1117   }
1118 }
1119
1120 /* find the index of the sample that includes the data for @media_time using a
1121  * linear search, and keeping in mind that not all samples may have been parsed
1122  * yet.  If possible, it will delegate to binary search.
1123  *
1124  * Returns the index of the sample.
1125  */
1126 static guint32
1127 gst_qtdemux_find_index_linear (GstQTDemux * qtdemux, QtDemuxStream * str,
1128     GstClockTime media_time)
1129 {
1130   guint32 index = 0;
1131   guint64 mov_time;
1132   QtDemuxSample *sample;
1133
1134   /* convert media_time to mov format */
1135   mov_time =
1136       gst_util_uint64_scale_ceil (media_time, str->timescale, GST_SECOND);
1137
1138   sample = str->samples;
1139   if (mov_time == sample->timestamp + sample->pts_offset)
1140     return index;
1141
1142   /* use faster search if requested time in already parsed range */
1143   sample = str->samples + str->stbl_index;
1144   if (str->stbl_index >= 0 && mov_time <= sample->timestamp) {
1145     index = gst_qtdemux_find_index (qtdemux, str, media_time);
1146     sample = str->samples + index;
1147   } else {
1148     while (index < str->n_samples - 1) {
1149       if (!qtdemux_parse_samples (qtdemux, str, index + 1))
1150         goto parse_failed;
1151
1152       sample = str->samples + index + 1;
1153       if (mov_time < sample->timestamp) {
1154         sample = str->samples + index;
1155         break;
1156       }
1157
1158       index++;
1159     }
1160   }
1161
1162   /* sample->timestamp is now <= media_time, need to find the corresponding
1163    * PTS now by looking backwards */
1164   while (index > 0 && sample->timestamp + sample->pts_offset > mov_time) {
1165     index--;
1166     sample = str->samples + index;
1167   }
1168
1169   return index;
1170
1171   /* ERRORS */
1172 parse_failed:
1173   {
1174     GST_LOG_OBJECT (qtdemux, "Parsing of index %u failed!", index + 1);
1175     return -1;
1176   }
1177 }
1178
1179 /* find the index of the keyframe needed to decode the sample at @index
1180  * of stream @str, or of a subsequent keyframe (depending on @next)
1181  *
1182  * Returns the index of the keyframe.
1183  */
1184 static guint32
1185 gst_qtdemux_find_keyframe (GstQTDemux * qtdemux, QtDemuxStream * str,
1186     guint32 index, gboolean next)
1187 {
1188   guint32 new_index = index;
1189
1190   if (index >= str->n_samples) {
1191     new_index = str->n_samples;
1192     goto beach;
1193   }
1194
1195   /* all keyframes, return index */
1196   if (str->all_keyframe) {
1197     new_index = index;
1198     goto beach;
1199   }
1200
1201   /* else search until we have a keyframe */
1202   while (new_index < str->n_samples) {
1203     if (next && !qtdemux_parse_samples (qtdemux, str, new_index))
1204       goto parse_failed;
1205
1206     if (str->samples[new_index].keyframe)
1207       break;
1208
1209     if (new_index == 0)
1210       break;
1211
1212     if (next)
1213       new_index++;
1214     else
1215       new_index--;
1216   }
1217
1218   if (new_index == str->n_samples) {
1219     GST_DEBUG_OBJECT (qtdemux, "no next keyframe");
1220     new_index = -1;
1221   }
1222
1223 beach:
1224   GST_DEBUG_OBJECT (qtdemux, "searching for keyframe index %s index %u "
1225       "gave %u", next ? "after" : "before", index, new_index);
1226
1227   return new_index;
1228
1229   /* ERRORS */
1230 parse_failed:
1231   {
1232     GST_LOG_OBJECT (qtdemux, "Parsing of index %u failed!", new_index);
1233     return -1;
1234   }
1235 }
1236
1237 /* find the segment for @time_position for @stream
1238  *
1239  * Returns the index of the segment containing @time_position.
1240  * Returns the last segment and sets the @eos variable to TRUE
1241  * if the time is beyond the end. @eos may be NULL
1242  */
1243 static guint32
1244 gst_qtdemux_find_segment (GstQTDemux * qtdemux, QtDemuxStream * stream,
1245     GstClockTime time_position)
1246 {
1247   gint i;
1248   guint32 seg_idx;
1249
1250   GST_LOG_OBJECT (stream->pad, "finding segment for %" GST_TIME_FORMAT,
1251       GST_TIME_ARGS (time_position));
1252
1253   seg_idx = -1;
1254   for (i = 0; i < stream->n_segments; i++) {
1255     QtDemuxSegment *segment = &stream->segments[i];
1256
1257     GST_LOG_OBJECT (stream->pad,
1258         "looking at segment %" GST_TIME_FORMAT "-%" GST_TIME_FORMAT,
1259         GST_TIME_ARGS (segment->time), GST_TIME_ARGS (segment->stop_time));
1260
1261     /* For the last segment we include stop_time in the last segment */
1262     if (i < stream->n_segments - 1) {
1263       if (segment->time <= time_position && time_position < segment->stop_time) {
1264         GST_LOG_OBJECT (stream->pad, "segment %d matches", i);
1265         seg_idx = i;
1266         break;
1267       }
1268     } else {
1269       /* Last segment always matches */
1270       seg_idx = i;
1271       break;
1272     }
1273   }
1274   return seg_idx;
1275 }
1276
1277 /* move the stream @str to the sample position @index.
1278  *
1279  * Updates @str->sample_index and marks discontinuity if needed.
1280  */
1281 static void
1282 gst_qtdemux_move_stream (GstQTDemux * qtdemux, QtDemuxStream * str,
1283     guint32 index)
1284 {
1285   /* no change needed */
1286   if (index == str->sample_index)
1287     return;
1288
1289   GST_DEBUG_OBJECT (qtdemux, "moving to sample %u of %u", index,
1290       str->n_samples);
1291
1292   /* position changed, we have a discont */
1293   str->sample_index = index;
1294   str->offset_in_sample = 0;
1295   /* Each time we move in the stream we store the position where we are
1296    * starting from */
1297   str->from_sample = index;
1298   str->discont = TRUE;
1299 }
1300
1301 static void
1302 gst_qtdemux_adjust_seek (GstQTDemux * qtdemux, gint64 desired_time,
1303     gboolean use_sparse, gboolean next, gint64 * key_time, gint64 * key_offset)
1304 {
1305   guint64 min_offset;
1306   gint64 min_byte_offset = -1;
1307   GList *iter;
1308
1309   min_offset = desired_time;
1310
1311   /* for each stream, find the index of the sample in the segment
1312    * and move back to the previous keyframe. */
1313   for (iter = qtdemux->active_streams; iter; iter = g_list_next (iter)) {
1314     QtDemuxStream *str;
1315     guint32 index, kindex;
1316     guint32 seg_idx;
1317     GstClockTime media_start;
1318     GstClockTime media_time;
1319     GstClockTime seg_time;
1320     QtDemuxSegment *seg;
1321     gboolean empty_segment = FALSE;
1322
1323     str = QTDEMUX_STREAM (iter->data);
1324
1325     if (CUR_STREAM (str)->sparse && !use_sparse)
1326       continue;
1327
1328     seg_idx = gst_qtdemux_find_segment (qtdemux, str, desired_time);
1329     GST_DEBUG_OBJECT (qtdemux, "align segment %d", seg_idx);
1330
1331     /* get segment and time in the segment */
1332     seg = &str->segments[seg_idx];
1333     seg_time = (desired_time - seg->time) * seg->rate;
1334
1335     while (QTSEGMENT_IS_EMPTY (seg)) {
1336       seg_time = 0;
1337       empty_segment = TRUE;
1338       GST_DEBUG_OBJECT (str->pad, "Segment %d is empty, moving to next one",
1339           seg_idx);
1340       seg_idx++;
1341       if (seg_idx == str->n_segments)
1342         break;
1343       seg = &str->segments[seg_idx];
1344     }
1345
1346     if (seg_idx == str->n_segments) {
1347       /* FIXME track shouldn't have the last segment as empty, but if it
1348        * happens we better handle it */
1349       continue;
1350     }
1351
1352     /* get the media time in the segment */
1353     media_start = seg->media_start + seg_time;
1354
1355     /* get the index of the sample with media time */
1356     index = gst_qtdemux_find_index_linear (qtdemux, str, media_start);
1357     GST_DEBUG_OBJECT (qtdemux, "sample for %" GST_TIME_FORMAT " at %u"
1358         " at offset %" G_GUINT64_FORMAT " (empty segment: %d)",
1359         GST_TIME_ARGS (media_start), index, str->samples[index].offset,
1360         empty_segment);
1361
1362     /* shift to next frame if we are looking for next keyframe */
1363     if (next && QTSAMPLE_PTS_NO_CSLG (str, &str->samples[index]) < media_start
1364         && index < str->stbl_index)
1365       index++;
1366
1367     if (!empty_segment) {
1368       /* find previous keyframe */
1369       kindex = gst_qtdemux_find_keyframe (qtdemux, str, index, next);
1370
1371       /* we will settle for one before if none found after */
1372       if (next && kindex == -1)
1373         kindex = gst_qtdemux_find_keyframe (qtdemux, str, index, FALSE);
1374
1375       /* if the keyframe is at a different position, we need to update the
1376        * requested seek time */
1377       if (index != kindex) {
1378         index = kindex;
1379
1380         /* get timestamp of keyframe */
1381         media_time = QTSAMPLE_PTS_NO_CSLG (str, &str->samples[kindex]);
1382         GST_DEBUG_OBJECT (qtdemux,
1383             "keyframe at %u with time %" GST_TIME_FORMAT " at offset %"
1384             G_GUINT64_FORMAT, kindex, GST_TIME_ARGS (media_time),
1385             str->samples[kindex].offset);
1386
1387         /* keyframes in the segment get a chance to change the
1388          * desired_offset. keyframes out of the segment are
1389          * ignored. */
1390         if (media_time >= seg->media_start) {
1391           GstClockTime seg_time;
1392
1393           /* this keyframe is inside the segment, convert back to
1394            * segment time */
1395           seg_time = (media_time - seg->media_start) + seg->time;
1396           if ((!next && (seg_time < min_offset)) ||
1397               (next && (seg_time > min_offset)))
1398             min_offset = seg_time;
1399         }
1400       }
1401     }
1402
1403     if (min_byte_offset < 0 || str->samples[index].offset < min_byte_offset)
1404       min_byte_offset = str->samples[index].offset;
1405   }
1406
1407   if (key_time)
1408     *key_time = min_offset;
1409   if (key_offset)
1410     *key_offset = min_byte_offset;
1411 }
1412
1413 static gboolean
1414 gst_qtdemux_convert_seek (GstPad * pad, GstFormat * format,
1415     GstSeekType cur_type, gint64 * cur, GstSeekType stop_type, gint64 * stop)
1416 {
1417   gboolean res;
1418
1419   g_return_val_if_fail (format != NULL, FALSE);
1420   g_return_val_if_fail (cur != NULL, FALSE);
1421   g_return_val_if_fail (stop != NULL, FALSE);
1422
1423   if (*format == GST_FORMAT_TIME)
1424     return TRUE;
1425
1426   res = TRUE;
1427   if (cur_type != GST_SEEK_TYPE_NONE)
1428     res = gst_pad_query_convert (pad, *format, *cur, GST_FORMAT_TIME, cur);
1429   if (res && stop_type != GST_SEEK_TYPE_NONE)
1430     res = gst_pad_query_convert (pad, *format, *stop, GST_FORMAT_TIME, stop);
1431
1432   if (res)
1433     *format = GST_FORMAT_TIME;
1434
1435   return res;
1436 }
1437
1438 /* perform seek in push based mode:
1439    find BYTE position to move to based on time and delegate to upstream
1440 */
1441 static gboolean
1442 gst_qtdemux_do_push_seek (GstQTDemux * qtdemux, GstPad * pad, GstEvent * event)
1443 {
1444   gdouble rate;
1445   GstFormat format;
1446   GstSeekFlags flags;
1447   GstSeekType cur_type, stop_type;
1448   gint64 cur, stop, key_cur;
1449   gboolean res;
1450   gint64 byte_cur;
1451   gint64 original_stop;
1452   guint32 seqnum;
1453
1454   GST_DEBUG_OBJECT (qtdemux, "doing push-based seek");
1455
1456   gst_event_parse_seek (event, &rate, &format, &flags,
1457       &cur_type, &cur, &stop_type, &stop);
1458   seqnum = gst_event_get_seqnum (event);
1459
1460   /* only forward streaming and seeking is possible */
1461   if (rate <= 0)
1462     goto unsupported_seek;
1463
1464   /* convert to TIME if needed and possible */
1465   if (!gst_qtdemux_convert_seek (pad, &format, cur_type, &cur,
1466           stop_type, &stop))
1467     goto no_format;
1468
1469   /* Upstream seek in bytes will have undefined stop, but qtdemux stores
1470    * the original stop position to use when upstream pushes the new segment
1471    * for this seek */
1472   original_stop = stop;
1473   stop = -1;
1474
1475   /* find reasonable corresponding BYTE position,
1476    * also try to mind about keyframes, since we can not go back a bit for them
1477    * later on */
1478   /* determining @next here based on SNAP_BEFORE/SNAP_AFTER should
1479    * mostly just work, but let's not yet boldly go there  ... */
1480   gst_qtdemux_adjust_seek (qtdemux, cur, FALSE, FALSE, &key_cur, &byte_cur);
1481
1482   if (byte_cur == -1)
1483     goto abort_seek;
1484
1485   GST_DEBUG_OBJECT (qtdemux, "Pushing BYTE seek rate %g, "
1486       "start %" G_GINT64_FORMAT ", stop %" G_GINT64_FORMAT, rate, byte_cur,
1487       stop);
1488
1489   GST_OBJECT_LOCK (qtdemux);
1490   qtdemux->seek_offset = byte_cur;
1491   if (!(flags & GST_SEEK_FLAG_KEY_UNIT)) {
1492     qtdemux->push_seek_start = cur;
1493   } else {
1494     qtdemux->push_seek_start = key_cur;
1495   }
1496
1497   if (stop_type == GST_SEEK_TYPE_NONE) {
1498     qtdemux->push_seek_stop = qtdemux->segment.stop;
1499   } else {
1500     qtdemux->push_seek_stop = original_stop;
1501   }
1502   GST_OBJECT_UNLOCK (qtdemux);
1503
1504   qtdemux->segment_seqnum = seqnum;
1505   /* BYTE seek event */
1506   event = gst_event_new_seek (rate, GST_FORMAT_BYTES, flags, cur_type, byte_cur,
1507       stop_type, stop);
1508   gst_event_set_seqnum (event, seqnum);
1509   res = gst_pad_push_event (qtdemux->sinkpad, event);
1510
1511   return res;
1512
1513   /* ERRORS */
1514 abort_seek:
1515   {
1516     GST_DEBUG_OBJECT (qtdemux, "could not determine byte position to seek to, "
1517         "seek aborted.");
1518     return FALSE;
1519   }
1520 unsupported_seek:
1521   {
1522     GST_DEBUG_OBJECT (qtdemux, "unsupported seek, seek aborted.");
1523     return FALSE;
1524   }
1525 no_format:
1526   {
1527     GST_DEBUG_OBJECT (qtdemux, "unsupported format given, seek aborted.");
1528     return FALSE;
1529   }
1530 }
1531
1532 /* perform the seek.
1533  *
1534  * We set all segment_indexes in the streams to unknown and
1535  * adjust the time_position to the desired position. this is enough
1536  * to trigger a segment switch in the streaming thread to start
1537  * streaming from the desired position.
1538  *
1539  * Keyframe seeking is a little more complicated when dealing with
1540  * segments. Ideally we want to move to the previous keyframe in
1541  * the segment but there might not be a keyframe in the segment. In
1542  * fact, none of the segments could contain a keyframe. We take a
1543  * practical approach: seek to the previous keyframe in the segment,
1544  * if there is none, seek to the beginning of the segment.
1545  *
1546  * Called with STREAM_LOCK
1547  */
1548 static gboolean
1549 gst_qtdemux_perform_seek (GstQTDemux * qtdemux, GstSegment * segment,
1550     guint32 seqnum, GstSeekFlags flags)
1551 {
1552   gint64 desired_offset;
1553   GList *iter;
1554
1555   desired_offset = segment->position;
1556
1557   GST_DEBUG_OBJECT (qtdemux, "seeking to %" GST_TIME_FORMAT,
1558       GST_TIME_ARGS (desired_offset));
1559
1560   /* may not have enough fragmented info to do this adjustment,
1561    * and we can't scan (and probably should not) at this time with
1562    * possibly flushing upstream */
1563   if ((flags & GST_SEEK_FLAG_KEY_UNIT) && !qtdemux->fragmented) {
1564     gint64 min_offset;
1565     gboolean next, before, after;
1566
1567     before = ! !(flags & GST_SEEK_FLAG_SNAP_BEFORE);
1568     after = ! !(flags & GST_SEEK_FLAG_SNAP_AFTER);
1569     next = after && !before;
1570     if (segment->rate < 0)
1571       next = !next;
1572
1573     gst_qtdemux_adjust_seek (qtdemux, desired_offset, TRUE, next, &min_offset,
1574         NULL);
1575     GST_DEBUG_OBJECT (qtdemux, "keyframe seek, align to %"
1576         GST_TIME_FORMAT, GST_TIME_ARGS (min_offset));
1577     desired_offset = min_offset;
1578   }
1579
1580   /* and set all streams to the final position */
1581   gst_flow_combiner_reset (qtdemux->flowcombiner);
1582   qtdemux->segment_seqnum = seqnum;
1583   for (iter = qtdemux->active_streams; iter; iter = g_list_next (iter)) {
1584     QtDemuxStream *stream = QTDEMUX_STREAM (iter->data);
1585
1586     stream->time_position = desired_offset;
1587     stream->accumulated_base = 0;
1588     stream->sample_index = -1;
1589     stream->offset_in_sample = 0;
1590     stream->segment_index = -1;
1591     stream->sent_eos = FALSE;
1592
1593     if (segment->flags & GST_SEEK_FLAG_FLUSH)
1594       gst_segment_init (&stream->segment, GST_FORMAT_TIME);
1595   }
1596   segment->position = desired_offset;
1597   segment->time = desired_offset;
1598   if (segment->rate >= 0) {
1599     segment->start = desired_offset;
1600
1601     /* we stop at the end */
1602     if (segment->stop == -1)
1603       segment->stop = segment->duration;
1604   } else {
1605     segment->stop = desired_offset;
1606   }
1607
1608   if (qtdemux->fragmented)
1609     qtdemux->fragmented_seek_pending = TRUE;
1610
1611   return TRUE;
1612 }
1613
1614 /* do a seek in pull based mode */
1615 static gboolean
1616 gst_qtdemux_do_seek (GstQTDemux * qtdemux, GstPad * pad, GstEvent * event)
1617 {
1618   gdouble rate;
1619   GstFormat format;
1620   GstSeekFlags flags;
1621   GstSeekType cur_type, stop_type;
1622   gint64 cur, stop;
1623   gboolean flush;
1624   gboolean update;
1625   GstSegment seeksegment;
1626   guint32 seqnum = GST_SEQNUM_INVALID;
1627   GstEvent *flush_event;
1628   gboolean ret;
1629
1630   if (event) {
1631     GST_DEBUG_OBJECT (qtdemux, "doing seek with event");
1632
1633     gst_event_parse_seek (event, &rate, &format, &flags,
1634         &cur_type, &cur, &stop_type, &stop);
1635     seqnum = gst_event_get_seqnum (event);
1636
1637     /* we have to have a format as the segment format. Try to convert
1638      * if not. */
1639     if (!gst_qtdemux_convert_seek (pad, &format, cur_type, &cur,
1640             stop_type, &stop))
1641       goto no_format;
1642
1643     GST_DEBUG_OBJECT (qtdemux, "seek format %s", gst_format_get_name (format));
1644   } else {
1645     GST_DEBUG_OBJECT (qtdemux, "doing seek without event");
1646     flags = 0;
1647   }
1648
1649   flush = flags & GST_SEEK_FLAG_FLUSH;
1650
1651   /* stop streaming, either by flushing or by pausing the task */
1652   if (flush) {
1653     flush_event = gst_event_new_flush_start ();
1654     if (seqnum != GST_SEQNUM_INVALID)
1655       gst_event_set_seqnum (flush_event, seqnum);
1656     /* unlock upstream pull_range */
1657     gst_pad_push_event (qtdemux->sinkpad, gst_event_ref (flush_event));
1658     /* make sure out loop function exits */
1659     gst_qtdemux_push_event (qtdemux, flush_event);
1660   } else {
1661     /* non flushing seek, pause the task */
1662     gst_pad_pause_task (qtdemux->sinkpad);
1663   }
1664
1665   /* wait for streaming to finish */
1666   GST_PAD_STREAM_LOCK (qtdemux->sinkpad);
1667
1668   /* copy segment, we need this because we still need the old
1669    * segment when we close the current segment. */
1670   memcpy (&seeksegment, &qtdemux->segment, sizeof (GstSegment));
1671
1672   if (event) {
1673     /* configure the segment with the seek variables */
1674     GST_DEBUG_OBJECT (qtdemux, "configuring seek");
1675     if (!gst_segment_do_seek (&seeksegment, rate, format, flags,
1676             cur_type, cur, stop_type, stop, &update)) {
1677       ret = FALSE;
1678       GST_ERROR_OBJECT (qtdemux, "inconsistent seek values, doing nothing");
1679     } else {
1680       /* now do the seek */
1681       ret = gst_qtdemux_perform_seek (qtdemux, &seeksegment, seqnum, flags);
1682     }
1683   } else {
1684     /* now do the seek */
1685     ret = gst_qtdemux_perform_seek (qtdemux, &seeksegment, seqnum, flags);
1686   }
1687
1688   /* prepare for streaming again */
1689   if (flush) {
1690     flush_event = gst_event_new_flush_stop (TRUE);
1691     if (seqnum != GST_SEQNUM_INVALID)
1692       gst_event_set_seqnum (flush_event, seqnum);
1693
1694     gst_pad_push_event (qtdemux->sinkpad, gst_event_ref (flush_event));
1695     gst_qtdemux_push_event (qtdemux, flush_event);
1696   }
1697
1698   /* commit the new segment */
1699   memcpy (&qtdemux->segment, &seeksegment, sizeof (GstSegment));
1700
1701   if (qtdemux->segment.flags & GST_SEEK_FLAG_SEGMENT) {
1702     GstMessage *msg = gst_message_new_segment_start (GST_OBJECT_CAST (qtdemux),
1703         qtdemux->segment.format, qtdemux->segment.position);
1704     if (seqnum != GST_SEQNUM_INVALID)
1705       gst_message_set_seqnum (msg, seqnum);
1706     gst_element_post_message (GST_ELEMENT_CAST (qtdemux), msg);
1707   }
1708
1709   /* restart streaming, NEWSEGMENT will be sent from the streaming thread. */
1710   gst_pad_start_task (qtdemux->sinkpad, (GstTaskFunction) gst_qtdemux_loop,
1711       qtdemux->sinkpad, NULL);
1712
1713   GST_PAD_STREAM_UNLOCK (qtdemux->sinkpad);
1714
1715   return ret;
1716
1717   /* ERRORS */
1718 no_format:
1719   {
1720     GST_DEBUG_OBJECT (qtdemux, "unsupported format given, seek aborted.");
1721     return FALSE;
1722   }
1723 }
1724
1725 static gboolean
1726 qtdemux_ensure_index (GstQTDemux * qtdemux)
1727 {
1728   GList *iter;
1729
1730   GST_DEBUG_OBJECT (qtdemux, "collecting all metadata for all streams");
1731
1732   /* Build complete index */
1733   for (iter = qtdemux->active_streams; iter; iter = g_list_next (iter)) {
1734     QtDemuxStream *stream = QTDEMUX_STREAM (iter->data);
1735
1736     if (!qtdemux_parse_samples (qtdemux, stream, stream->n_samples - 1)) {
1737       GST_LOG_OBJECT (qtdemux,
1738           "Building complete index of track-id %u for seeking failed!",
1739           stream->track_id);
1740       return FALSE;
1741     }
1742   }
1743
1744   return TRUE;
1745 }
1746
1747 static gboolean
1748 gst_qtdemux_handle_src_event (GstPad * pad, GstObject * parent,
1749     GstEvent * event)
1750 {
1751   gboolean res = TRUE;
1752   GstQTDemux *qtdemux = GST_QTDEMUX (parent);
1753
1754   switch (GST_EVENT_TYPE (event)) {
1755     case GST_EVENT_SEEK:
1756     {
1757 #ifndef GST_DISABLE_GST_DEBUG
1758       GstClockTime ts = gst_util_get_timestamp ();
1759 #endif
1760       guint32 seqnum = gst_event_get_seqnum (event);
1761
1762       qtdemux->received_seek = TRUE;
1763
1764       if (seqnum == qtdemux->segment_seqnum) {
1765         GST_LOG_OBJECT (pad,
1766             "Drop duplicated SEEK event seqnum %" G_GUINT32_FORMAT, seqnum);
1767         gst_event_unref (event);
1768         return TRUE;
1769       }
1770
1771       if (qtdemux->upstream_format_is_time && qtdemux->fragmented) {
1772         /* seek should be handled by upstream, we might need to re-download fragments */
1773         GST_DEBUG_OBJECT (qtdemux,
1774             "let upstream handle seek for fragmented playback");
1775         goto upstream;
1776       }
1777
1778       /* Build complete index for seeking;
1779        * if not a fragmented file at least */
1780       if (!qtdemux->fragmented)
1781         if (!qtdemux_ensure_index (qtdemux))
1782           goto index_failed;
1783 #ifndef GST_DISABLE_GST_DEBUG
1784       ts = gst_util_get_timestamp () - ts;
1785       GST_INFO_OBJECT (qtdemux,
1786           "Time taken to parse index %" GST_TIME_FORMAT, GST_TIME_ARGS (ts));
1787 #endif
1788     }
1789       if (qtdemux->pullbased) {
1790         res = gst_qtdemux_do_seek (qtdemux, pad, event);
1791       } else if (gst_pad_push_event (qtdemux->sinkpad, gst_event_ref (event))) {
1792         GST_DEBUG_OBJECT (qtdemux, "Upstream successfully seeked");
1793         res = TRUE;
1794       } else if (qtdemux->state == QTDEMUX_STATE_MOVIE && qtdemux->n_streams
1795           && !qtdemux->fragmented) {
1796         res = gst_qtdemux_do_push_seek (qtdemux, pad, event);
1797       } else {
1798         GST_DEBUG_OBJECT (qtdemux,
1799             "ignoring seek in push mode in current state");
1800         res = FALSE;
1801       }
1802       gst_event_unref (event);
1803       break;
1804     default:
1805     upstream:
1806       res = gst_pad_event_default (pad, parent, event);
1807       break;
1808   }
1809
1810 done:
1811   return res;
1812
1813   /* ERRORS */
1814 index_failed:
1815   {
1816     GST_ERROR_OBJECT (qtdemux, "Index failed");
1817     gst_event_unref (event);
1818     res = FALSE;
1819     goto done;
1820   }
1821 }
1822
1823 /* Find, for each track, the first sample in coding order that has a file offset >= @byte_pos.
1824  *
1825  * If @fw is false, the coding order is explored backwards.
1826  *
1827  * If @set is true, each stream will be moved to its matched sample, or EOS if no matching
1828  * sample is found for that track.
1829  *
1830  * The stream and sample index of the sample with the minimum offset in the direction explored
1831  * (see @fw) is returned in the output parameters @_stream and @_index respectively.
1832  *
1833  * @_time is set to the QTSAMPLE_PTS of the matched sample with the minimum QTSAMPLE_PTS in the
1834  * direction explored, which may not always match the QTSAMPLE_PTS of the sample returned in
1835  * @_stream and @_index. */
1836 static void
1837 gst_qtdemux_find_sample (GstQTDemux * qtdemux, gint64 byte_pos, gboolean fw,
1838     gboolean set, QtDemuxStream ** _stream, gint * _index, gint64 * _time)
1839 {
1840   gint i, index;
1841   gint64 time, min_time;
1842   QtDemuxStream *stream;
1843   GList *iter;
1844
1845   min_time = -1;
1846   stream = NULL;
1847   index = -1;
1848
1849   for (iter = qtdemux->active_streams; iter; iter = g_list_next (iter)) {
1850     QtDemuxStream *str;
1851     gint inc;
1852     gboolean set_sample;
1853
1854     str = QTDEMUX_STREAM (iter->data);
1855     set_sample = !set;
1856
1857     if (fw) {
1858       i = 0;
1859       inc = 1;
1860     } else {
1861       i = str->n_samples - 1;
1862       inc = -1;
1863     }
1864
1865     for (; (i >= 0) && (i < str->n_samples); i += inc) {
1866       if (str->samples[i].size == 0)
1867         continue;
1868
1869       if (fw && (str->samples[i].offset < byte_pos))
1870         continue;
1871
1872       if (!fw && (str->samples[i].offset + str->samples[i].size > byte_pos))
1873         continue;
1874
1875       /* move stream to first available sample */
1876       if (set) {
1877         gst_qtdemux_move_stream (qtdemux, str, i);
1878         set_sample = TRUE;
1879       }
1880
1881       /* avoid index from sparse streams since they might be far away */
1882       if (!CUR_STREAM (str)->sparse) {
1883         /* determine min/max time */
1884         time = QTSAMPLE_PTS (str, &str->samples[i]);
1885         if (min_time == -1 || (!fw && time > min_time) ||
1886             (fw && time < min_time)) {
1887           min_time = time;
1888         }
1889
1890         /* determine stream with leading sample, to get its position */
1891         if (!stream ||
1892             (fw && (str->samples[i].offset < stream->samples[index].offset)) ||
1893             (!fw && (str->samples[i].offset > stream->samples[index].offset))) {
1894           stream = str;
1895           index = i;
1896         }
1897       }
1898       break;
1899     }
1900
1901     /* no sample for this stream, mark eos */
1902     if (!set_sample)
1903       gst_qtdemux_move_stream (qtdemux, str, str->n_samples);
1904   }
1905
1906   if (_time)
1907     *_time = min_time;
1908   if (_stream)
1909     *_stream = stream;
1910   if (_index)
1911     *_index = index;
1912 }
1913
1914 /* Copied from mpegtsbase code */
1915 /* FIXME: replace this function when we add new util function for stream-id creation */
1916 static gchar *
1917 _get_upstream_id (GstQTDemux * demux)
1918 {
1919   gchar *upstream_id = gst_pad_get_stream_id (demux->sinkpad);
1920
1921   if (!upstream_id) {
1922     /* Try to create one from the upstream URI, else use a randome number */
1923     GstQuery *query;
1924     gchar *uri = NULL;
1925
1926     /* Try to generate one from the URI query and
1927      * if it fails take a random number instead */
1928     query = gst_query_new_uri ();
1929     if (gst_element_query (GST_ELEMENT_CAST (demux), query)) {
1930       gst_query_parse_uri (query, &uri);
1931     }
1932
1933     if (uri) {
1934       GChecksum *cs;
1935
1936       /* And then generate an SHA256 sum of the URI */
1937       cs = g_checksum_new (G_CHECKSUM_SHA256);
1938       g_checksum_update (cs, (const guchar *) uri, strlen (uri));
1939       g_free (uri);
1940       upstream_id = g_strdup (g_checksum_get_string (cs));
1941       g_checksum_free (cs);
1942     } else {
1943       /* Just get some random number if the URI query fails */
1944       GST_FIXME_OBJECT (demux, "Creating random stream-id, consider "
1945           "implementing a deterministic way of creating a stream-id");
1946       upstream_id =
1947           g_strdup_printf ("%08x%08x%08x%08x", g_random_int (), g_random_int (),
1948           g_random_int (), g_random_int ());
1949     }
1950
1951     gst_query_unref (query);
1952   }
1953   return upstream_id;
1954 }
1955
1956 static QtDemuxStream *
1957 _create_stream (GstQTDemux * demux, guint32 track_id)
1958 {
1959   QtDemuxStream *stream;
1960   gchar *upstream_id;
1961
1962   stream = g_new0 (QtDemuxStream, 1);
1963   stream->demux = demux;
1964   stream->track_id = track_id;
1965   upstream_id = _get_upstream_id (demux);
1966   stream->stream_id = g_strdup_printf ("%s/%03u", upstream_id, track_id);
1967   g_free (upstream_id);
1968   /* new streams always need a discont */
1969   stream->discont = TRUE;
1970   /* we enable clipping for raw audio/video streams */
1971   stream->need_clip = FALSE;
1972   stream->need_process = FALSE;
1973   stream->segment_index = -1;
1974   stream->time_position = 0;
1975   stream->sample_index = -1;
1976   stream->offset_in_sample = 0;
1977   stream->new_stream = TRUE;
1978   stream->multiview_mode = GST_VIDEO_MULTIVIEW_MODE_NONE;
1979   stream->multiview_flags = GST_VIDEO_MULTIVIEW_FLAGS_NONE;
1980   stream->protected = FALSE;
1981   stream->protection_scheme_type = 0;
1982   stream->protection_scheme_version = 0;
1983   stream->protection_scheme_info = NULL;
1984   stream->n_samples_moof = 0;
1985   stream->duration_moof = 0;
1986   stream->duration_last_moof = 0;
1987   stream->alignment = 1;
1988   stream->stream_tags = gst_tag_list_new_empty ();
1989   gst_tag_list_set_scope (stream->stream_tags, GST_TAG_SCOPE_STREAM);
1990   g_queue_init (&stream->protection_scheme_event_queue);
1991   return stream;
1992 }
1993
1994 static gboolean
1995 gst_qtdemux_setcaps (GstQTDemux * demux, GstCaps * caps)
1996 {
1997   GstStructure *structure;
1998   const gchar *variant;
1999   const GstCaps *mediacaps = NULL;
2000
2001   GST_DEBUG_OBJECT (demux, "Sink set caps: %" GST_PTR_FORMAT, caps);
2002
2003   structure = gst_caps_get_structure (caps, 0);
2004   variant = gst_structure_get_string (structure, "variant");
2005
2006   if (variant && strcmp (variant, "mss-fragmented") == 0) {
2007     QtDemuxStream *stream;
2008     const GValue *value;
2009
2010     demux->fragmented = TRUE;
2011     demux->mss_mode = TRUE;
2012
2013     if (demux->n_streams > 1) {
2014       /* can't do this, we can only renegotiate for another mss format */
2015       return FALSE;
2016     }
2017
2018     value = gst_structure_get_value (structure, "media-caps");
2019     /* create stream */
2020     if (value) {
2021       const GValue *timescale_v;
2022
2023       /* TODO update when stream changes during playback */
2024
2025       if (demux->n_streams == 0) {
2026         stream = _create_stream (demux, 1);
2027         demux->active_streams = g_list_append (demux->active_streams, stream);
2028         demux->n_streams = 1;
2029         /* mss has no stsd/stsd entry, use id 0 as default */
2030         stream->stsd_entries_length = 1;
2031         stream->stsd_sample_description_id = stream->cur_stsd_entry_index = 0;
2032         stream->stsd_entries = g_new0 (QtDemuxStreamStsdEntry, 1);
2033       } else {
2034         stream = QTDEMUX_FIRST_STREAM (demux);
2035       }
2036
2037       timescale_v = gst_structure_get_value (structure, "timescale");
2038       if (timescale_v) {
2039         stream->timescale = g_value_get_uint64 (timescale_v);
2040       } else {
2041         /* default mss timescale */
2042         stream->timescale = 10000000;
2043       }
2044       demux->timescale = stream->timescale;
2045
2046       mediacaps = gst_value_get_caps (value);
2047       if (!CUR_STREAM (stream)->caps
2048           || !gst_caps_is_equal_fixed (mediacaps, CUR_STREAM (stream)->caps)) {
2049         GST_DEBUG_OBJECT (demux, "We have a new caps %" GST_PTR_FORMAT,
2050             mediacaps);
2051         stream->new_caps = TRUE;
2052       }
2053       gst_caps_replace (&CUR_STREAM (stream)->caps, (GstCaps *) mediacaps);
2054       structure = gst_caps_get_structure (mediacaps, 0);
2055       if (g_str_has_prefix (gst_structure_get_name (structure), "video")) {
2056         stream->subtype = FOURCC_vide;
2057
2058         gst_structure_get_int (structure, "width", &CUR_STREAM (stream)->width);
2059         gst_structure_get_int (structure, "height",
2060             &CUR_STREAM (stream)->height);
2061         gst_structure_get_fraction (structure, "framerate",
2062             &CUR_STREAM (stream)->fps_n, &CUR_STREAM (stream)->fps_d);
2063       } else if (g_str_has_prefix (gst_structure_get_name (structure), "audio")) {
2064         gint rate = 0;
2065         stream->subtype = FOURCC_soun;
2066         gst_structure_get_int (structure, "channels",
2067             &CUR_STREAM (stream)->n_channels);
2068         gst_structure_get_int (structure, "rate", &rate);
2069         CUR_STREAM (stream)->rate = rate;
2070       }
2071     }
2072     gst_caps_replace (&demux->media_caps, (GstCaps *) mediacaps);
2073   } else {
2074     demux->mss_mode = FALSE;
2075   }
2076
2077   return TRUE;
2078 }
2079
2080 static void
2081 gst_qtdemux_reset (GstQTDemux * qtdemux, gboolean hard)
2082 {
2083   GList *iter;
2084
2085   GST_DEBUG_OBJECT (qtdemux, "Resetting demux");
2086   gst_pad_stop_task (qtdemux->sinkpad);
2087
2088   if (hard || qtdemux->upstream_format_is_time) {
2089     qtdemux->state = QTDEMUX_STATE_INITIAL;
2090     qtdemux->neededbytes = 16;
2091     qtdemux->todrop = 0;
2092     qtdemux->pullbased = FALSE;
2093     qtdemux->posted_redirect = FALSE;
2094     qtdemux->first_mdat = -1;
2095     qtdemux->header_size = 0;
2096     qtdemux->mdatoffset = -1;
2097     qtdemux->restoredata_offset = -1;
2098     if (qtdemux->mdatbuffer)
2099       gst_buffer_unref (qtdemux->mdatbuffer);
2100     if (qtdemux->restoredata_buffer)
2101       gst_buffer_unref (qtdemux->restoredata_buffer);
2102     qtdemux->mdatbuffer = NULL;
2103     qtdemux->restoredata_buffer = NULL;
2104     qtdemux->mdatleft = 0;
2105     qtdemux->mdatsize = 0;
2106     if (qtdemux->comp_brands)
2107       gst_buffer_unref (qtdemux->comp_brands);
2108     qtdemux->comp_brands = NULL;
2109     qtdemux->last_moov_offset = -1;
2110     if (qtdemux->moov_node_compressed) {
2111       g_node_destroy (qtdemux->moov_node_compressed);
2112       if (qtdemux->moov_node)
2113         g_free (qtdemux->moov_node->data);
2114     }
2115     qtdemux->moov_node_compressed = NULL;
2116     if (qtdemux->moov_node)
2117       g_node_destroy (qtdemux->moov_node);
2118     qtdemux->moov_node = NULL;
2119     if (qtdemux->tag_list)
2120       gst_mini_object_unref (GST_MINI_OBJECT_CAST (qtdemux->tag_list));
2121     qtdemux->tag_list = gst_tag_list_new_empty ();
2122     gst_tag_list_set_scope (qtdemux->tag_list, GST_TAG_SCOPE_GLOBAL);
2123 #if 0
2124     if (qtdemux->element_index)
2125       gst_object_unref (qtdemux->element_index);
2126     qtdemux->element_index = NULL;
2127 #endif
2128     qtdemux->major_brand = 0;
2129     qtdemux->upstream_format_is_time = FALSE;
2130     qtdemux->upstream_seekable = FALSE;
2131     qtdemux->upstream_size = 0;
2132
2133     qtdemux->fragment_start = -1;
2134     qtdemux->fragment_start_offset = -1;
2135     qtdemux->duration = 0;
2136     qtdemux->moof_offset = 0;
2137     qtdemux->chapters_track_id = 0;
2138     qtdemux->have_group_id = FALSE;
2139     qtdemux->group_id = G_MAXUINT;
2140
2141     g_queue_foreach (&qtdemux->protection_event_queue, (GFunc) gst_event_unref,
2142         NULL);
2143     g_queue_clear (&qtdemux->protection_event_queue);
2144
2145     qtdemux->received_seek = FALSE;
2146     qtdemux->first_moof_already_parsed = FALSE;
2147   }
2148   qtdemux->offset = 0;
2149   gst_adapter_clear (qtdemux->adapter);
2150   gst_segment_init (&qtdemux->segment, GST_FORMAT_TIME);
2151   qtdemux->need_segment = TRUE;
2152
2153   if (hard) {
2154     qtdemux->segment_seqnum = GST_SEQNUM_INVALID;
2155     g_list_free_full (qtdemux->active_streams,
2156         (GDestroyNotify) gst_qtdemux_stream_free);
2157     g_list_free_full (qtdemux->old_streams,
2158         (GDestroyNotify) gst_qtdemux_stream_free);
2159     qtdemux->active_streams = NULL;
2160     qtdemux->old_streams = NULL;
2161     qtdemux->n_streams = 0;
2162     qtdemux->n_video_streams = 0;
2163     qtdemux->n_audio_streams = 0;
2164     qtdemux->n_sub_streams = 0;
2165     qtdemux->exposed = FALSE;
2166     qtdemux->fragmented = FALSE;
2167     qtdemux->mss_mode = FALSE;
2168     gst_caps_replace (&qtdemux->media_caps, NULL);
2169     qtdemux->timescale = 0;
2170     qtdemux->got_moov = FALSE;
2171     qtdemux->cenc_aux_info_offset = 0;
2172     qtdemux->cenc_aux_info_sizes = NULL;
2173     qtdemux->cenc_aux_sample_count = 0;
2174     if (qtdemux->protection_system_ids) {
2175       g_ptr_array_free (qtdemux->protection_system_ids, TRUE);
2176       qtdemux->protection_system_ids = NULL;
2177     }
2178     qtdemux->streams_aware = GST_OBJECT_PARENT (qtdemux)
2179         && GST_OBJECT_FLAG_IS_SET (GST_OBJECT_PARENT (qtdemux),
2180         GST_BIN_FLAG_STREAMS_AWARE);
2181
2182     if (qtdemux->preferred_protection_system_id) {
2183       g_free (qtdemux->preferred_protection_system_id);
2184       qtdemux->preferred_protection_system_id = NULL;
2185     }
2186   } else if (qtdemux->mss_mode) {
2187     gst_flow_combiner_reset (qtdemux->flowcombiner);
2188     g_list_foreach (qtdemux->active_streams,
2189         (GFunc) gst_qtdemux_stream_clear, NULL);
2190   } else {
2191     gst_flow_combiner_reset (qtdemux->flowcombiner);
2192     for (iter = qtdemux->active_streams; iter; iter = g_list_next (iter)) {
2193       QtDemuxStream *stream = QTDEMUX_STREAM (iter->data);
2194       stream->sent_eos = FALSE;
2195       stream->time_position = 0;
2196       stream->accumulated_base = 0;
2197     }
2198   }
2199 }
2200
2201
2202 /* Maps the @segment to the qt edts internal segments and pushes
2203  * the correspnding segment event.
2204  *
2205  * If it ends up being at a empty segment, a gap will be pushed and the next
2206  * edts segment will be activated in sequence.
2207  *
2208  * To be used in push-mode only */
2209 static void
2210 gst_qtdemux_map_and_push_segments (GstQTDemux * qtdemux, GstSegment * segment)
2211 {
2212   gint i;
2213   GList *iter;
2214
2215   for (iter = qtdemux->active_streams; iter; iter = g_list_next (iter)) {
2216     QtDemuxStream *stream = QTDEMUX_STREAM (iter->data);
2217
2218     stream->time_position = segment->start;
2219
2220     /* in push mode we should be guaranteed that we will have empty segments
2221      * at the beginning and then one segment after, other scenarios are not
2222      * supported and are discarded when parsing the edts */
2223     for (i = 0; i < stream->n_segments; i++) {
2224       if (stream->segments[i].stop_time > segment->start) {
2225         /* push the empty segment and move to the next one */
2226         gst_qtdemux_activate_segment (qtdemux, stream, i,
2227             stream->time_position);
2228         if (QTSEGMENT_IS_EMPTY (&stream->segments[i])) {
2229           gst_qtdemux_send_gap_for_segment (qtdemux, stream, i,
2230               stream->time_position);
2231
2232           /* accumulate previous segments */
2233           if (GST_CLOCK_TIME_IS_VALID (stream->segment.stop))
2234             stream->accumulated_base +=
2235                 (stream->segment.stop -
2236                 stream->segment.start) / ABS (stream->segment.rate);
2237           continue;
2238         }
2239
2240         g_assert (i == stream->n_segments - 1);
2241       }
2242     }
2243   }
2244 }
2245
2246 static gboolean
2247 gst_qtdemux_handle_sink_event (GstPad * sinkpad, GstObject * parent,
2248     GstEvent * event)
2249 {
2250   GstQTDemux *demux = GST_QTDEMUX (parent);
2251   gboolean res = TRUE;
2252
2253   GST_LOG_OBJECT (demux, "handling %s event", GST_EVENT_TYPE_NAME (event));
2254
2255   switch (GST_EVENT_TYPE (event)) {
2256     case GST_EVENT_SEGMENT:
2257     {
2258       gint64 offset = 0;
2259       QtDemuxStream *stream;
2260       gint idx;
2261       GstSegment segment;
2262
2263       /* some debug output */
2264       gst_event_copy_segment (event, &segment);
2265       GST_DEBUG_OBJECT (demux, "received newsegment %" GST_SEGMENT_FORMAT,
2266           &segment);
2267
2268       if (segment.format == GST_FORMAT_TIME) {
2269         demux->upstream_format_is_time = TRUE;
2270         demux->segment_seqnum = gst_event_get_seqnum (event);
2271       } else {
2272         GST_DEBUG_OBJECT (demux, "Not storing upstream newsegment, "
2273             "not in time format");
2274
2275         /* chain will send initial newsegment after pads have been added */
2276         if (demux->state != QTDEMUX_STATE_MOVIE || !demux->n_streams) {
2277           GST_DEBUG_OBJECT (demux, "still starting, eating event");
2278           goto exit;
2279         }
2280       }
2281
2282       /* check if this matches a time seek we received previously
2283        * FIXME for backwards compatibility reasons we use the
2284        * seek_offset here to compare. In the future we might want to
2285        * change this to use the seqnum as it uniquely should identify
2286        * the segment that corresponds to the seek. */
2287       GST_DEBUG_OBJECT (demux, "Stored seek offset: %" G_GINT64_FORMAT
2288           ", received segment offset %" G_GINT64_FORMAT,
2289           demux->seek_offset, segment.start);
2290       if (segment.format == GST_FORMAT_BYTES
2291           && demux->seek_offset == segment.start) {
2292         GST_OBJECT_LOCK (demux);
2293         offset = segment.start;
2294
2295         segment.format = GST_FORMAT_TIME;
2296         segment.start = demux->push_seek_start;
2297         segment.stop = demux->push_seek_stop;
2298         GST_DEBUG_OBJECT (demux, "Replaced segment with stored seek "
2299             "segment %" GST_TIME_FORMAT " - %" GST_TIME_FORMAT,
2300             GST_TIME_ARGS (segment.start), GST_TIME_ARGS (segment.stop));
2301         GST_OBJECT_UNLOCK (demux);
2302       }
2303
2304       /* we only expect a BYTE segment, e.g. following a seek */
2305       if (segment.format == GST_FORMAT_BYTES) {
2306         if (GST_CLOCK_TIME_IS_VALID (segment.start)) {
2307           offset = segment.start;
2308
2309           gst_qtdemux_find_sample (demux, segment.start, TRUE, FALSE, NULL,
2310               NULL, (gint64 *) & segment.start);
2311           if ((gint64) segment.start < 0)
2312             segment.start = 0;
2313         }
2314         if (GST_CLOCK_TIME_IS_VALID (segment.stop)) {
2315           gst_qtdemux_find_sample (demux, segment.stop, FALSE, FALSE, NULL,
2316               NULL, (gint64 *) & segment.stop);
2317           /* keyframe seeking should already arrange for start >= stop,
2318            * but make sure in other rare cases */
2319           segment.stop = MAX (segment.stop, segment.start);
2320         }
2321       } else if (segment.format == GST_FORMAT_TIME) {
2322         /* push all data on the adapter before starting this
2323          * new segment */
2324         gst_qtdemux_process_adapter (demux, TRUE);
2325       } else {
2326         GST_DEBUG_OBJECT (demux, "unsupported segment format, ignoring");
2327         goto exit;
2328       }
2329
2330       /* We shouldn't modify upstream driven TIME FORMAT segment */
2331       if (!demux->upstream_format_is_time) {
2332         /* accept upstream's notion of segment and distribute along */
2333         segment.format = GST_FORMAT_TIME;
2334         segment.position = segment.time = segment.start;
2335         segment.duration = demux->segment.duration;
2336         segment.base = gst_segment_to_running_time (&demux->segment,
2337             GST_FORMAT_TIME, demux->segment.position);
2338       }
2339
2340       gst_segment_copy_into (&segment, &demux->segment);
2341       GST_DEBUG_OBJECT (demux, "Pushing newseg %" GST_SEGMENT_FORMAT, &segment);
2342
2343       /* map segment to internal qt segments and push on each stream */
2344       if (demux->n_streams) {
2345         demux->need_segment = TRUE;
2346         gst_qtdemux_check_send_pending_segment (demux);
2347       }
2348
2349       /* clear leftover in current segment, if any */
2350       gst_adapter_clear (demux->adapter);
2351
2352       /* set up streaming thread */
2353       demux->offset = offset;
2354       if (demux->upstream_format_is_time) {
2355         GST_DEBUG_OBJECT (demux, "Upstream is driving in time format, "
2356             "set values to restart reading from a new atom");
2357         demux->neededbytes = 16;
2358         demux->todrop = 0;
2359       } else {
2360         gst_qtdemux_find_sample (demux, offset, TRUE, TRUE, &stream, &idx,
2361             NULL);
2362         if (stream) {
2363           demux->todrop = stream->samples[idx].offset - offset;
2364           demux->neededbytes = demux->todrop + stream->samples[idx].size;
2365         } else {
2366           /* set up for EOS */
2367           demux->neededbytes = -1;
2368           demux->todrop = 0;
2369         }
2370       }
2371     exit:
2372       gst_event_unref (event);
2373       res = TRUE;
2374       goto drop;
2375     }
2376     case GST_EVENT_FLUSH_START:
2377     {
2378       if (gst_event_get_seqnum (event) == demux->offset_seek_seqnum) {
2379         gst_event_unref (event);
2380         goto drop;
2381       }
2382       QTDEMUX_EXPOSE_LOCK (demux);
2383       res = gst_pad_event_default (demux->sinkpad, parent, event);
2384       QTDEMUX_EXPOSE_UNLOCK (demux);
2385       goto drop;
2386     }
2387     case GST_EVENT_FLUSH_STOP:
2388     {
2389       guint64 dur;
2390
2391       dur = demux->segment.duration;
2392       gst_qtdemux_reset (demux, FALSE);
2393       demux->segment.duration = dur;
2394
2395       if (gst_event_get_seqnum (event) == demux->offset_seek_seqnum) {
2396         gst_event_unref (event);
2397         goto drop;
2398       }
2399       break;
2400     }
2401     case GST_EVENT_EOS:
2402       /* If we are in push mode, and get an EOS before we've seen any streams,
2403        * then error out - we have nowhere to send the EOS */
2404       if (!demux->pullbased) {
2405         GList *iter;
2406         gboolean has_valid_stream = FALSE;
2407         for (iter = demux->active_streams; iter; iter = g_list_next (iter)) {
2408           if (QTDEMUX_STREAM (iter->data)->pad != NULL) {
2409             has_valid_stream = TRUE;
2410             break;
2411           }
2412         }
2413         if (!has_valid_stream)
2414           gst_qtdemux_post_no_playable_stream_error (demux);
2415         else {
2416           GST_DEBUG_OBJECT (demux, "Data still available after EOS: %u",
2417               (guint) gst_adapter_available (demux->adapter));
2418           if (gst_qtdemux_process_adapter (demux, TRUE) != GST_FLOW_OK) {
2419             res = FALSE;
2420           }
2421         }
2422       }
2423       break;
2424     case GST_EVENT_CAPS:{
2425       GstCaps *caps = NULL;
2426
2427       gst_event_parse_caps (event, &caps);
2428       gst_qtdemux_setcaps (demux, caps);
2429       res = TRUE;
2430       gst_event_unref (event);
2431       goto drop;
2432     }
2433     case GST_EVENT_PROTECTION:
2434     {
2435       const gchar *system_id = NULL;
2436
2437       gst_event_parse_protection (event, &system_id, NULL, NULL);
2438       GST_DEBUG_OBJECT (demux, "Received protection event for system ID %s",
2439           system_id);
2440       gst_qtdemux_append_protection_system_id (demux, system_id);
2441       /* save the event for later, for source pads that have not been created */
2442       g_queue_push_tail (&demux->protection_event_queue, gst_event_ref (event));
2443       /* send it to all pads that already exist */
2444       gst_qtdemux_push_event (demux, event);
2445       res = TRUE;
2446       goto drop;
2447     }
2448     case GST_EVENT_STREAM_START:
2449     {
2450       res = TRUE;
2451       gst_event_unref (event);
2452
2453       /* Drain all the buffers */
2454       gst_qtdemux_process_adapter (demux, TRUE);
2455       gst_qtdemux_reset (demux, FALSE);
2456       /* We expect new moov box after new stream-start event */
2457       demux->old_streams =
2458           g_list_concat (demux->old_streams, demux->active_streams);
2459       demux->active_streams = NULL;
2460
2461       goto drop;
2462     }
2463     default:
2464       break;
2465   }
2466
2467   res = gst_pad_event_default (demux->sinkpad, parent, event) & res;
2468
2469 drop:
2470   return res;
2471 }
2472
2473 #if 0
2474 static void
2475 gst_qtdemux_set_index (GstElement * element, GstIndex * index)
2476 {
2477   GstQTDemux *demux = GST_QTDEMUX (element);
2478
2479   GST_OBJECT_LOCK (demux);
2480   if (demux->element_index)
2481     gst_object_unref (demux->element_index);
2482   if (index) {
2483     demux->element_index = gst_object_ref (index);
2484   } else {
2485     demux->element_index = NULL;
2486   }
2487   GST_OBJECT_UNLOCK (demux);
2488   /* object lock might be taken again */
2489   if (index)
2490     gst_index_get_writer_id (index, GST_OBJECT (element), &demux->index_id);
2491   GST_DEBUG_OBJECT (demux, "Set index %" GST_PTR_FORMAT "for writer id %d",
2492       demux->element_index, demux->index_id);
2493 }
2494
2495 static GstIndex *
2496 gst_qtdemux_get_index (GstElement * element)
2497 {
2498   GstIndex *result = NULL;
2499   GstQTDemux *demux = GST_QTDEMUX (element);
2500
2501   GST_OBJECT_LOCK (demux);
2502   if (demux->element_index)
2503     result = gst_object_ref (demux->element_index);
2504   GST_OBJECT_UNLOCK (demux);
2505
2506   GST_DEBUG_OBJECT (demux, "Returning index %" GST_PTR_FORMAT, result);
2507
2508   return result;
2509 }
2510 #endif
2511
2512 static void
2513 gst_qtdemux_stbl_free (QtDemuxStream * stream)
2514 {
2515   g_free ((gpointer) stream->stco.data);
2516   stream->stco.data = NULL;
2517   g_free ((gpointer) stream->stsz.data);
2518   stream->stsz.data = NULL;
2519   g_free ((gpointer) stream->stsc.data);
2520   stream->stsc.data = NULL;
2521   g_free ((gpointer) stream->stts.data);
2522   stream->stts.data = NULL;
2523   g_free ((gpointer) stream->stss.data);
2524   stream->stss.data = NULL;
2525   g_free ((gpointer) stream->stps.data);
2526   stream->stps.data = NULL;
2527   g_free ((gpointer) stream->ctts.data);
2528   stream->ctts.data = NULL;
2529 }
2530
2531 static void
2532 gst_qtdemux_stream_flush_segments_data (QtDemuxStream * stream)
2533 {
2534   g_free (stream->segments);
2535   stream->segments = NULL;
2536   stream->segment_index = -1;
2537   stream->accumulated_base = 0;
2538 }
2539
2540 static void
2541 gst_qtdemux_stream_flush_samples_data (QtDemuxStream * stream)
2542 {
2543   g_free (stream->samples);
2544   stream->samples = NULL;
2545   gst_qtdemux_stbl_free (stream);
2546
2547   /* fragments */
2548   g_free (stream->ra_entries);
2549   stream->ra_entries = NULL;
2550   stream->n_ra_entries = 0;
2551
2552   stream->sample_index = -1;
2553   stream->stbl_index = -1;
2554   stream->n_samples = 0;
2555   stream->time_position = 0;
2556
2557   stream->n_samples_moof = 0;
2558   stream->duration_moof = 0;
2559   stream->duration_last_moof = 0;
2560 }
2561
2562 static void
2563 gst_qtdemux_stream_clear (QtDemuxStream * stream)
2564 {
2565   gint i;
2566   if (stream->allocator)
2567     gst_object_unref (stream->allocator);
2568   while (stream->buffers) {
2569     gst_buffer_unref (GST_BUFFER_CAST (stream->buffers->data));
2570     stream->buffers = g_slist_delete_link (stream->buffers, stream->buffers);
2571   }
2572   for (i = 0; i < stream->stsd_entries_length; i++) {
2573     QtDemuxStreamStsdEntry *entry = &stream->stsd_entries[i];
2574     if (entry->rgb8_palette) {
2575       gst_memory_unref (entry->rgb8_palette);
2576       entry->rgb8_palette = NULL;
2577     }
2578     entry->sparse = FALSE;
2579   }
2580
2581   if (stream->stream_tags)
2582     gst_tag_list_unref (stream->stream_tags);
2583
2584   stream->stream_tags = gst_tag_list_new_empty ();
2585   gst_tag_list_set_scope (stream->stream_tags, GST_TAG_SCOPE_STREAM);
2586   g_free (stream->redirect_uri);
2587   stream->redirect_uri = NULL;
2588   stream->sent_eos = FALSE;
2589   stream->protected = FALSE;
2590   if (stream->protection_scheme_info) {
2591     if (stream->protection_scheme_type == FOURCC_cenc) {
2592       QtDemuxCencSampleSetInfo *info =
2593           (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
2594       if (info->default_properties)
2595         gst_structure_free (info->default_properties);
2596       if (info->crypto_info)
2597         g_ptr_array_free (info->crypto_info, TRUE);
2598     }
2599     g_free (stream->protection_scheme_info);
2600     stream->protection_scheme_info = NULL;
2601   }
2602   stream->protection_scheme_type = 0;
2603   stream->protection_scheme_version = 0;
2604   g_queue_foreach (&stream->protection_scheme_event_queue,
2605       (GFunc) gst_event_unref, NULL);
2606   g_queue_clear (&stream->protection_scheme_event_queue);
2607   gst_qtdemux_stream_flush_segments_data (stream);
2608   gst_qtdemux_stream_flush_samples_data (stream);
2609 }
2610
2611 static void
2612 gst_qtdemux_stream_reset (QtDemuxStream * stream)
2613 {
2614   gint i;
2615   gst_qtdemux_stream_clear (stream);
2616   for (i = 0; i < stream->stsd_entries_length; i++) {
2617     QtDemuxStreamStsdEntry *entry = &stream->stsd_entries[i];
2618     if (entry->caps) {
2619       gst_caps_unref (entry->caps);
2620       entry->caps = NULL;
2621     }
2622   }
2623   g_free (stream->stsd_entries);
2624   stream->stsd_entries = NULL;
2625   stream->stsd_entries_length = 0;
2626 }
2627
2628
2629 static void
2630 gst_qtdemux_stream_free (QtDemuxStream * stream)
2631 {
2632   gst_qtdemux_stream_reset (stream);
2633   gst_tag_list_unref (stream->stream_tags);
2634   if (stream->pad) {
2635     GstQTDemux *demux = stream->demux;
2636     gst_element_remove_pad (GST_ELEMENT_CAST (demux), stream->pad);
2637     gst_flow_combiner_remove_pad (demux->flowcombiner, stream->pad);
2638   }
2639   g_free (stream->stream_id);
2640   g_free (stream);
2641 }
2642
2643 static void
2644 gst_qtdemux_remove_stream (GstQTDemux * qtdemux, QtDemuxStream * stream)
2645 {
2646   qtdemux->active_streams = g_list_remove (qtdemux->active_streams, stream);
2647   gst_qtdemux_stream_free (stream);
2648   qtdemux->n_streams--;
2649 }
2650
2651 static GstStateChangeReturn
2652 gst_qtdemux_change_state (GstElement * element, GstStateChange transition)
2653 {
2654   GstQTDemux *qtdemux = GST_QTDEMUX (element);
2655   GstStateChangeReturn result = GST_STATE_CHANGE_FAILURE;
2656
2657   switch (transition) {
2658     case GST_STATE_CHANGE_READY_TO_PAUSED:
2659       gst_qtdemux_reset (qtdemux, TRUE);
2660       break;
2661     default:
2662       break;
2663   }
2664
2665   result = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
2666
2667   switch (transition) {
2668     case GST_STATE_CHANGE_PAUSED_TO_READY:{
2669       gst_qtdemux_reset (qtdemux, TRUE);
2670       break;
2671     }
2672     default:
2673       break;
2674   }
2675
2676   return result;
2677 }
2678
2679 static void
2680 gst_qtdemux_set_context (GstElement * element, GstContext * context)
2681 {
2682   GstQTDemux *qtdemux = GST_QTDEMUX (element);
2683
2684   g_return_if_fail (GST_IS_CONTEXT (context));
2685
2686   if (gst_context_has_context_type (context,
2687           "drm-preferred-decryption-system-id")) {
2688     const GstStructure *s;
2689
2690     s = gst_context_get_structure (context);
2691     g_free (qtdemux->preferred_protection_system_id);
2692     qtdemux->preferred_protection_system_id =
2693         g_strdup (gst_structure_get_string (s, "decryption-system-id"));
2694     GST_DEBUG_OBJECT (element, "set preferred decryption system to %s",
2695         qtdemux->preferred_protection_system_id);
2696   }
2697
2698   GST_ELEMENT_CLASS (parent_class)->set_context (element, context);
2699 }
2700
2701 static void
2702 qtdemux_parse_ftyp (GstQTDemux * qtdemux, const guint8 * buffer, gint length)
2703 {
2704   /* counts as header data */
2705   qtdemux->header_size += length;
2706
2707   /* only consider at least a sufficiently complete ftyp atom */
2708   if (length >= 20) {
2709     GstBuffer *buf;
2710
2711     qtdemux->major_brand = QT_FOURCC (buffer + 8);
2712     GST_DEBUG_OBJECT (qtdemux, "major brand: %" GST_FOURCC_FORMAT,
2713         GST_FOURCC_ARGS (qtdemux->major_brand));
2714     if (qtdemux->comp_brands)
2715       gst_buffer_unref (qtdemux->comp_brands);
2716     buf = qtdemux->comp_brands = gst_buffer_new_and_alloc (length - 16);
2717     gst_buffer_fill (buf, 0, buffer + 16, length - 16);
2718   }
2719 }
2720
2721 static void
2722 qtdemux_handle_xmp_taglist (GstQTDemux * qtdemux, GstTagList * taglist,
2723     GstTagList * xmptaglist)
2724 {
2725   /* Strip out bogus fields */
2726   if (xmptaglist) {
2727     if (gst_tag_list_get_scope (taglist) == GST_TAG_SCOPE_GLOBAL) {
2728       gst_tag_list_remove_tag (xmptaglist, GST_TAG_VIDEO_CODEC);
2729       gst_tag_list_remove_tag (xmptaglist, GST_TAG_AUDIO_CODEC);
2730     } else {
2731       gst_tag_list_remove_tag (xmptaglist, GST_TAG_CONTAINER_FORMAT);
2732     }
2733
2734     GST_DEBUG_OBJECT (qtdemux, "Found XMP tags %" GST_PTR_FORMAT, xmptaglist);
2735
2736     /* prioritize native tags using _KEEP mode */
2737     gst_tag_list_insert (taglist, xmptaglist, GST_TAG_MERGE_KEEP);
2738     gst_tag_list_unref (xmptaglist);
2739   }
2740 }
2741
2742 static void
2743 qtdemux_update_default_sample_encryption_settings (GstQTDemux * qtdemux,
2744     QtDemuxCencSampleSetInfo * info, guint32 is_encrypted, guint8 iv_size,
2745     const guint8 * kid)
2746 {
2747   GstBuffer *kid_buf = gst_buffer_new_allocate (NULL, 16, NULL);
2748   gst_buffer_fill (kid_buf, 0, kid, 16);
2749   if (info->default_properties)
2750     gst_structure_free (info->default_properties);
2751   info->default_properties =
2752       gst_structure_new ("application/x-cenc",
2753       "iv_size", G_TYPE_UINT, iv_size,
2754       "encrypted", G_TYPE_BOOLEAN, (is_encrypted == 1),
2755       "kid", GST_TYPE_BUFFER, kid_buf, NULL);
2756   GST_DEBUG_OBJECT (qtdemux, "default sample properties: "
2757       "is_encrypted=%u, iv_size=%u", is_encrypted, iv_size);
2758   gst_buffer_unref (kid_buf);
2759 }
2760
2761 static gboolean
2762 qtdemux_update_default_piff_encryption_settings (GstQTDemux * qtdemux,
2763     QtDemuxCencSampleSetInfo * info, GstByteReader * br)
2764 {
2765   guint32 algorithm_id = 0;
2766   const guint8 *kid;
2767   gboolean is_encrypted = TRUE;
2768   guint8 iv_size = 8;
2769
2770   if (!gst_byte_reader_get_uint24_le (br, &algorithm_id)) {
2771     GST_ERROR_OBJECT (qtdemux, "Error getting box's algorithm ID field");
2772     return FALSE;
2773   }
2774
2775   algorithm_id >>= 8;
2776   if (algorithm_id == 0) {
2777     is_encrypted = FALSE;
2778   } else if (algorithm_id == 1) {
2779     GST_DEBUG_OBJECT (qtdemux, "AES 128-bits CTR encrypted stream");
2780   } else if (algorithm_id == 2) {
2781     GST_DEBUG_OBJECT (qtdemux, "AES 128-bits CBC encrypted stream");
2782   }
2783
2784   if (!gst_byte_reader_get_uint8 (br, &iv_size))
2785     return FALSE;
2786
2787   if (!gst_byte_reader_get_data (br, 16, &kid))
2788     return FALSE;
2789
2790   qtdemux_update_default_sample_encryption_settings (qtdemux, info,
2791       is_encrypted, iv_size, kid);
2792   gst_structure_set (info->default_properties, "piff_algorithm_id",
2793       G_TYPE_UINT, algorithm_id, NULL);
2794   return TRUE;
2795 }
2796
2797
2798 static void
2799 qtdemux_parse_piff (GstQTDemux * qtdemux, const guint8 * buffer, gint length,
2800     guint offset)
2801 {
2802   GstByteReader br;
2803   guint8 version;
2804   guint32 flags = 0;
2805   guint i;
2806   guint iv_size = 8;
2807   QtDemuxStream *stream;
2808   GstStructure *structure;
2809   QtDemuxCencSampleSetInfo *ss_info = NULL;
2810   const gchar *system_id;
2811   gboolean uses_sub_sample_encryption = FALSE;
2812   guint32 sample_count;
2813
2814   stream = QTDEMUX_FIRST_STREAM (qtdemux);
2815   if (!stream)
2816     return;
2817
2818   structure = gst_caps_get_structure (CUR_STREAM (stream)->caps, 0);
2819   if (!gst_structure_has_name (structure, "application/x-cenc")) {
2820     GST_WARNING_OBJECT (qtdemux,
2821         "Attempting PIFF box parsing on an unencrypted stream.");
2822     return;
2823   }
2824
2825   gst_structure_get (structure, GST_PROTECTION_SYSTEM_ID_CAPS_FIELD,
2826       G_TYPE_STRING, &system_id, NULL);
2827   gst_qtdemux_append_protection_system_id (qtdemux, system_id);
2828
2829   stream->protected = TRUE;
2830   stream->protection_scheme_type = FOURCC_cenc;
2831
2832   if (!stream->protection_scheme_info)
2833     stream->protection_scheme_info = g_new0 (QtDemuxCencSampleSetInfo, 1);
2834
2835   ss_info = (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
2836   if (!ss_info->default_properties) {
2837     ss_info->default_properties =
2838         gst_structure_new ("application/x-cenc",
2839         "iv_size", G_TYPE_UINT, iv_size, "encrypted", G_TYPE_BOOLEAN, TRUE,
2840         NULL);
2841
2842   }
2843
2844   if (ss_info->crypto_info) {
2845     GST_LOG_OBJECT (qtdemux, "unreffing existing crypto_info");
2846     g_ptr_array_free (ss_info->crypto_info, TRUE);
2847     ss_info->crypto_info = NULL;
2848   }
2849
2850   /* skip UUID */
2851   gst_byte_reader_init (&br, buffer + offset + 16, length - offset - 16);
2852
2853   if (!gst_byte_reader_get_uint8 (&br, &version)) {
2854     GST_ERROR_OBJECT (qtdemux, "Error getting box's version field");
2855     return;
2856   }
2857
2858   if (!gst_byte_reader_get_uint24_be (&br, &flags)) {
2859     GST_ERROR_OBJECT (qtdemux, "Error getting box's flags field");
2860     return;
2861   }
2862
2863   if ((flags & 0x000001)) {
2864     if (!qtdemux_update_default_piff_encryption_settings (qtdemux, ss_info,
2865             &br))
2866       return;
2867   } else if ((flags & 0x000002)) {
2868     uses_sub_sample_encryption = TRUE;
2869   }
2870
2871   if (!gst_structure_get_uint (ss_info->default_properties, "iv_size",
2872           &iv_size)) {
2873     GST_ERROR_OBJECT (qtdemux, "Error getting encryption IV size field");
2874     return;
2875   }
2876
2877   if (!gst_byte_reader_get_uint32_be (&br, &sample_count)) {
2878     GST_ERROR_OBJECT (qtdemux, "Error getting box's sample count field");
2879     return;
2880   }
2881
2882   ss_info->crypto_info =
2883       g_ptr_array_new_full (sample_count,
2884       (GDestroyNotify) qtdemux_gst_structure_free);
2885
2886   for (i = 0; i < sample_count; ++i) {
2887     GstStructure *properties;
2888     guint8 *data;
2889     GstBuffer *buf;
2890
2891     properties = qtdemux_get_cenc_sample_properties (qtdemux, stream, i);
2892     if (properties == NULL) {
2893       GST_ERROR_OBJECT (qtdemux, "failed to get properties for sample %u", i);
2894       qtdemux->cenc_aux_sample_count = i;
2895       return;
2896     }
2897
2898     if (!gst_byte_reader_dup_data (&br, iv_size, &data)) {
2899       GST_ERROR_OBJECT (qtdemux, "IV data not present for sample %u", i);
2900       gst_structure_free (properties);
2901       qtdemux->cenc_aux_sample_count = i;
2902       return;
2903     }
2904     buf = gst_buffer_new_wrapped (data, iv_size);
2905     gst_structure_set (properties, "iv", GST_TYPE_BUFFER, buf, NULL);
2906     gst_buffer_unref (buf);
2907
2908     if (uses_sub_sample_encryption) {
2909       guint16 n_subsamples;
2910       const GValue *kid_buf_value;
2911
2912       if (!gst_byte_reader_get_uint16_be (&br, &n_subsamples)
2913           || n_subsamples == 0) {
2914         GST_ERROR_OBJECT (qtdemux,
2915             "failed to get subsample count for sample %u", i);
2916         gst_structure_free (properties);
2917         qtdemux->cenc_aux_sample_count = i;
2918         return;
2919       }
2920       GST_LOG_OBJECT (qtdemux, "subsample count: %u", n_subsamples);
2921       if (!gst_byte_reader_dup_data (&br, n_subsamples * 6, &data)) {
2922         GST_ERROR_OBJECT (qtdemux, "failed to get subsample data for sample %u",
2923             i);
2924         gst_structure_free (properties);
2925         qtdemux->cenc_aux_sample_count = i;
2926         return;
2927       }
2928       buf = gst_buffer_new_wrapped (data, n_subsamples * 6);
2929
2930       kid_buf_value =
2931           gst_structure_get_value (ss_info->default_properties, "kid");
2932
2933       gst_structure_set (properties,
2934           "subsample_count", G_TYPE_UINT, n_subsamples,
2935           "subsamples", GST_TYPE_BUFFER, buf, NULL);
2936       gst_structure_set_value (properties, "kid", kid_buf_value);
2937       gst_buffer_unref (buf);
2938     } else {
2939       gst_structure_set (properties, "subsample_count", G_TYPE_UINT, 0, NULL);
2940     }
2941
2942     g_ptr_array_add (ss_info->crypto_info, properties);
2943   }
2944
2945   qtdemux->cenc_aux_sample_count = sample_count;
2946 }
2947
2948 static void
2949 qtdemux_parse_uuid (GstQTDemux * qtdemux, const guint8 * buffer, gint length)
2950 {
2951   static const guint8 xmp_uuid[] = { 0xBE, 0x7A, 0xCF, 0xCB,
2952     0x97, 0xA9, 0x42, 0xE8,
2953     0x9C, 0x71, 0x99, 0x94,
2954     0x91, 0xE3, 0xAF, 0xAC
2955   };
2956   static const guint8 playready_uuid[] = {
2957     0xd0, 0x8a, 0x4f, 0x18, 0x10, 0xf3, 0x4a, 0x82,
2958     0xb6, 0xc8, 0x32, 0xd8, 0xab, 0xa1, 0x83, 0xd3
2959   };
2960
2961   static const guint8 piff_sample_encryption_uuid[] = {
2962     0xa2, 0x39, 0x4f, 0x52, 0x5a, 0x9b, 0x4f, 0x14,
2963     0xa2, 0x44, 0x6c, 0x42, 0x7c, 0x64, 0x8d, 0xf4
2964   };
2965
2966   guint offset;
2967
2968   /* counts as header data */
2969   qtdemux->header_size += length;
2970
2971   offset = (QT_UINT32 (buffer) == 0) ? 16 : 8;
2972
2973   if (length <= offset + 16) {
2974     GST_DEBUG_OBJECT (qtdemux, "uuid atom is too short, skipping");
2975     return;
2976   }
2977
2978   if (memcmp (buffer + offset, xmp_uuid, 16) == 0) {
2979     GstBuffer *buf;
2980     GstTagList *taglist;
2981
2982     buf = _gst_buffer_new_wrapped ((guint8 *) buffer + offset + 16,
2983         length - offset - 16, NULL);
2984     taglist = gst_tag_list_from_xmp_buffer (buf);
2985     gst_buffer_unref (buf);
2986
2987     /* make sure we have a usable taglist */
2988     qtdemux->tag_list = gst_tag_list_make_writable (qtdemux->tag_list);
2989
2990     qtdemux_handle_xmp_taglist (qtdemux, qtdemux->tag_list, taglist);
2991
2992   } else if (memcmp (buffer + offset, playready_uuid, 16) == 0) {
2993     int len;
2994     const gunichar2 *s_utf16;
2995     char *contents;
2996
2997     len = GST_READ_UINT16_LE (buffer + offset + 0x30);
2998     s_utf16 = (const gunichar2 *) (buffer + offset + 0x32);
2999     contents = g_utf16_to_utf8 (s_utf16, len / 2, NULL, NULL, NULL);
3000     GST_ERROR_OBJECT (qtdemux, "contents: %s", contents);
3001
3002     g_free (contents);
3003
3004     GST_ELEMENT_ERROR (qtdemux, STREAM, DECRYPT,
3005         (_("Cannot play stream because it is encrypted with PlayReady DRM.")),
3006         (NULL));
3007   } else if (memcmp (buffer + offset, piff_sample_encryption_uuid, 16) == 0) {
3008     qtdemux_parse_piff (qtdemux, buffer, length, offset);
3009   } else {
3010     GST_DEBUG_OBJECT (qtdemux, "Ignoring unknown uuid: %08x-%08x-%08x-%08x",
3011         GST_READ_UINT32_LE (buffer + offset),
3012         GST_READ_UINT32_LE (buffer + offset + 4),
3013         GST_READ_UINT32_LE (buffer + offset + 8),
3014         GST_READ_UINT32_LE (buffer + offset + 12));
3015   }
3016 }
3017
3018 static void
3019 qtdemux_parse_sidx (GstQTDemux * qtdemux, const guint8 * buffer, gint length)
3020 {
3021   GstSidxParser sidx_parser;
3022   GstIsoffParserResult res;
3023   guint consumed;
3024
3025   gst_isoff_qt_sidx_parser_init (&sidx_parser);
3026
3027   res =
3028       gst_isoff_qt_sidx_parser_add_data (&sidx_parser, buffer, length,
3029       &consumed);
3030   GST_DEBUG_OBJECT (qtdemux, "sidx parse result: %d", res);
3031   if (res == GST_ISOFF_QT_PARSER_DONE) {
3032     check_update_duration (qtdemux, sidx_parser.cumulative_pts);
3033   }
3034   gst_isoff_qt_sidx_parser_clear (&sidx_parser);
3035 }
3036
3037 /* caller verifies at least 8 bytes in buf */
3038 static void
3039 extract_initial_length_and_fourcc (const guint8 * data, guint size,
3040     guint64 * plength, guint32 * pfourcc)
3041 {
3042   guint64 length;
3043   guint32 fourcc;
3044
3045   length = QT_UINT32 (data);
3046   GST_DEBUG ("length 0x%08" G_GINT64_MODIFIER "x", length);
3047   fourcc = QT_FOURCC (data + 4);
3048   GST_DEBUG ("atom type %" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (fourcc));
3049
3050   if (length == 0) {
3051     length = G_MAXUINT64;
3052   } else if (length == 1 && size >= 16) {
3053     /* this means we have an extended size, which is the 64 bit value of
3054      * the next 8 bytes */
3055     length = QT_UINT64 (data + 8);
3056     GST_DEBUG ("length 0x%08" G_GINT64_MODIFIER "x", length);
3057   }
3058
3059   if (plength)
3060     *plength = length;
3061   if (pfourcc)
3062     *pfourcc = fourcc;
3063 }
3064
3065 static gboolean
3066 qtdemux_parse_mehd (GstQTDemux * qtdemux, GstByteReader * br)
3067 {
3068   guint32 version = 0;
3069   GstClockTime duration = 0;
3070
3071   if (!gst_byte_reader_get_uint32_be (br, &version))
3072     goto failed;
3073
3074   version >>= 24;
3075   if (version == 1) {
3076     if (!gst_byte_reader_get_uint64_be (br, &duration))
3077       goto failed;
3078   } else {
3079     guint32 dur = 0;
3080
3081     if (!gst_byte_reader_get_uint32_be (br, &dur))
3082       goto failed;
3083     duration = dur;
3084   }
3085
3086   GST_INFO_OBJECT (qtdemux, "mehd duration: %" G_GUINT64_FORMAT, duration);
3087   qtdemux->duration = duration;
3088
3089   return TRUE;
3090
3091 failed:
3092   {
3093     GST_DEBUG_OBJECT (qtdemux, "parsing mehd failed");
3094     return FALSE;
3095   }
3096 }
3097
3098 static gboolean
3099 qtdemux_parse_trex (GstQTDemux * qtdemux, QtDemuxStream * stream,
3100     guint32 * ds_duration, guint32 * ds_size, guint32 * ds_flags)
3101 {
3102   if (!stream->parsed_trex && qtdemux->moov_node) {
3103     GNode *mvex, *trex;
3104     GstByteReader trex_data;
3105
3106     mvex = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_mvex);
3107     if (mvex) {
3108       trex = qtdemux_tree_get_child_by_type_full (mvex, FOURCC_trex,
3109           &trex_data);
3110       while (trex) {
3111         guint32 id = 0, sdi = 0, dur = 0, size = 0, flags = 0;
3112
3113         /* skip version/flags */
3114         if (!gst_byte_reader_skip (&trex_data, 4))
3115           goto next;
3116         if (!gst_byte_reader_get_uint32_be (&trex_data, &id))
3117           goto next;
3118         if (id != stream->track_id)
3119           goto next;
3120         if (!gst_byte_reader_get_uint32_be (&trex_data, &sdi))
3121           goto next;
3122         if (!gst_byte_reader_get_uint32_be (&trex_data, &dur))
3123           goto next;
3124         if (!gst_byte_reader_get_uint32_be (&trex_data, &size))
3125           goto next;
3126         if (!gst_byte_reader_get_uint32_be (&trex_data, &flags))
3127           goto next;
3128
3129         GST_DEBUG_OBJECT (qtdemux, "fragment defaults for stream %d; "
3130             "duration %d,  size %d, flags 0x%x", stream->track_id,
3131             dur, size, flags);
3132
3133         stream->parsed_trex = TRUE;
3134         stream->def_sample_description_index = sdi;
3135         stream->def_sample_duration = dur;
3136         stream->def_sample_size = size;
3137         stream->def_sample_flags = flags;
3138
3139       next:
3140         /* iterate all siblings */
3141         trex = qtdemux_tree_get_sibling_by_type_full (trex, FOURCC_trex,
3142             &trex_data);
3143       }
3144     }
3145   }
3146
3147   *ds_duration = stream->def_sample_duration;
3148   *ds_size = stream->def_sample_size;
3149   *ds_flags = stream->def_sample_flags;
3150
3151   /* even then, above values are better than random ... */
3152   if (G_UNLIKELY (!stream->parsed_trex)) {
3153     GST_WARNING_OBJECT (qtdemux,
3154         "failed to find fragment defaults for stream %d", stream->track_id);
3155     return FALSE;
3156   }
3157
3158   return TRUE;
3159 }
3160
3161 /* This method should be called whenever a more accurate duration might
3162  * have been found. It will update all relevant variables if/where needed
3163  */
3164 static void
3165 check_update_duration (GstQTDemux * qtdemux, GstClockTime duration)
3166 {
3167   guint i;
3168   guint64 movdur;
3169   GstClockTime prevdur;
3170   GList *iter;
3171
3172   movdur = GSTTIME_TO_QTTIME (qtdemux, duration);
3173
3174   if (movdur > qtdemux->duration) {
3175     prevdur = QTTIME_TO_GSTTIME (qtdemux, qtdemux->duration);
3176     GST_DEBUG_OBJECT (qtdemux,
3177         "Updating total duration to %" GST_TIME_FORMAT " was %" GST_TIME_FORMAT,
3178         GST_TIME_ARGS (duration), GST_TIME_ARGS (prevdur));
3179     qtdemux->duration = movdur;
3180     GST_DEBUG_OBJECT (qtdemux,
3181         "qtdemux->segment.duration: %" GST_TIME_FORMAT " .stop: %"
3182         GST_TIME_FORMAT, GST_TIME_ARGS (qtdemux->segment.duration),
3183         GST_TIME_ARGS (qtdemux->segment.stop));
3184     if (qtdemux->segment.duration == prevdur) {
3185       /* If the current segment has duration/stop identical to previous duration
3186        * update them also (because they were set at that point in time with
3187        * the wrong duration */
3188       /* We convert the value *from* the timescale version to avoid rounding errors */
3189       GstClockTime fixeddur = QTTIME_TO_GSTTIME (qtdemux, movdur);
3190       GST_DEBUG_OBJECT (qtdemux, "Updated segment.duration and segment.stop");
3191       qtdemux->segment.duration = fixeddur;
3192       qtdemux->segment.stop = fixeddur;
3193     }
3194   }
3195   for (iter = qtdemux->active_streams, i = 0; iter;
3196       iter = g_list_next (iter), i++) {
3197     QtDemuxStream *stream = QTDEMUX_STREAM (iter->data);
3198
3199     movdur = GSTTIME_TO_QTSTREAMTIME (stream, duration);
3200     if (movdur > stream->duration) {
3201       GST_DEBUG_OBJECT (qtdemux,
3202           "Updating stream #%d duration to %" GST_TIME_FORMAT, i,
3203           GST_TIME_ARGS (duration));
3204       stream->duration = movdur;
3205       /* internal duration tracking state has been updated above, so */
3206       /* preserve an open-ended dummy segment rather than repeatedly updating
3207        * it and spamming downstream accordingly with segment events */
3208       if (stream->dummy_segment &&
3209           GST_CLOCK_TIME_IS_VALID (stream->segments[0].duration)) {
3210         /* Update all dummy values to new duration */
3211         stream->segments[0].stop_time = duration;
3212         stream->segments[0].duration = duration;
3213         stream->segments[0].media_stop = duration;
3214
3215         /* let downstream know we possibly have a new stop time */
3216         if (stream->segment_index != -1) {
3217           GstClockTime pos;
3218
3219           if (qtdemux->segment.rate >= 0) {
3220             pos = stream->segment.start;
3221           } else {
3222             pos = stream->segment.stop;
3223           }
3224
3225           gst_qtdemux_stream_update_segment (qtdemux, stream,
3226               stream->segment_index, pos, NULL, NULL);
3227         }
3228       }
3229     }
3230   }
3231 }
3232
3233 static gboolean
3234 qtdemux_parse_trun (GstQTDemux * qtdemux, GstByteReader * trun,
3235     QtDemuxStream * stream, guint32 d_sample_duration, guint32 d_sample_size,
3236     guint32 d_sample_flags, gint64 moof_offset, gint64 moof_length,
3237     gint64 * base_offset, gint64 * running_offset, gint64 decode_ts,
3238     gboolean has_tfdt)
3239 {
3240   GstClockTime gst_ts = GST_CLOCK_TIME_NONE;
3241   guint64 timestamp;
3242   gint32 data_offset = 0;
3243   guint32 flags = 0, first_flags = 0, samples_count = 0;
3244   gint i;
3245   guint8 *data;
3246   guint entry_size, dur_offset, size_offset, flags_offset = 0, ct_offset = 0;
3247   QtDemuxSample *sample;
3248   gboolean ismv = FALSE;
3249   gint64 initial_offset;
3250
3251   GST_LOG_OBJECT (qtdemux, "parsing trun track-id %d; "
3252       "default dur %d, size %d, flags 0x%x, base offset %" G_GINT64_FORMAT ", "
3253       "decode ts %" G_GINT64_FORMAT, stream->track_id, d_sample_duration,
3254       d_sample_size, d_sample_flags, *base_offset, decode_ts);
3255
3256   if (stream->pending_seek && moof_offset < stream->pending_seek->moof_offset) {
3257     GST_INFO_OBJECT (stream->pad, "skipping trun before seek target fragment");
3258     return TRUE;
3259   }
3260
3261   /* presence of stss or not can't really tell us much,
3262    * and flags and so on tend to be marginally reliable in these files */
3263   if (stream->subtype == FOURCC_soun) {
3264     GST_DEBUG_OBJECT (qtdemux,
3265         "sound track in fragmented file; marking all keyframes");
3266     stream->all_keyframe = TRUE;
3267   }
3268
3269   if (!gst_byte_reader_skip (trun, 1) ||
3270       !gst_byte_reader_get_uint24_be (trun, &flags))
3271     goto fail;
3272
3273   if (!gst_byte_reader_get_uint32_be (trun, &samples_count))
3274     goto fail;
3275
3276   if (flags & TR_DATA_OFFSET) {
3277     /* note this is really signed */
3278     if (!gst_byte_reader_get_int32_be (trun, &data_offset))
3279       goto fail;
3280     GST_LOG_OBJECT (qtdemux, "trun data offset %d", data_offset);
3281     /* default base offset = first byte of moof */
3282     if (*base_offset == -1) {
3283       GST_LOG_OBJECT (qtdemux, "base_offset at moof");
3284       *base_offset = moof_offset;
3285     }
3286     *running_offset = *base_offset + data_offset;
3287   } else {
3288     /* if no offset at all, that would mean data starts at moof start,
3289      * which is a bit wrong and is ismv crappy way, so compensate
3290      * assuming data is in mdat following moof */
3291     if (*base_offset == -1) {
3292       *base_offset = moof_offset + moof_length + 8;
3293       GST_LOG_OBJECT (qtdemux, "base_offset assumed in mdat after moof");
3294       ismv = TRUE;
3295     }
3296     if (*running_offset == -1)
3297       *running_offset = *base_offset;
3298   }
3299
3300   GST_LOG_OBJECT (qtdemux, "running offset now %" G_GINT64_FORMAT,
3301       *running_offset);
3302   GST_LOG_OBJECT (qtdemux, "trun offset %d, flags 0x%x, entries %d",
3303       data_offset, flags, samples_count);
3304
3305   if (flags & TR_FIRST_SAMPLE_FLAGS) {
3306     if (G_UNLIKELY (flags & TR_SAMPLE_FLAGS)) {
3307       GST_DEBUG_OBJECT (qtdemux,
3308           "invalid flags; SAMPLE and FIRST_SAMPLE present, discarding latter");
3309       flags ^= TR_FIRST_SAMPLE_FLAGS;
3310     } else {
3311       if (!gst_byte_reader_get_uint32_be (trun, &first_flags))
3312         goto fail;
3313       GST_LOG_OBJECT (qtdemux, "first flags: 0x%x", first_flags);
3314     }
3315   }
3316
3317   /* FIXME ? spec says other bits should also be checked to determine
3318    * entry size (and prefix size for that matter) */
3319   entry_size = 0;
3320   dur_offset = size_offset = 0;
3321   if (flags & TR_SAMPLE_DURATION) {
3322     GST_LOG_OBJECT (qtdemux, "entry duration present");
3323     dur_offset = entry_size;
3324     entry_size += 4;
3325   }
3326   if (flags & TR_SAMPLE_SIZE) {
3327     GST_LOG_OBJECT (qtdemux, "entry size present");
3328     size_offset = entry_size;
3329     entry_size += 4;
3330   }
3331   if (flags & TR_SAMPLE_FLAGS) {
3332     GST_LOG_OBJECT (qtdemux, "entry flags present");
3333     flags_offset = entry_size;
3334     entry_size += 4;
3335   }
3336   if (flags & TR_COMPOSITION_TIME_OFFSETS) {
3337     GST_LOG_OBJECT (qtdemux, "entry ct offset present");
3338     ct_offset = entry_size;
3339     entry_size += 4;
3340   }
3341
3342   if (!qt_atom_parser_has_chunks (trun, samples_count, entry_size))
3343     goto fail;
3344   data = (guint8 *) gst_byte_reader_peek_data_unchecked (trun);
3345
3346   if (stream->n_samples + samples_count >=
3347       QTDEMUX_MAX_SAMPLE_INDEX_SIZE / sizeof (QtDemuxSample))
3348     goto index_too_big;
3349
3350   GST_DEBUG_OBJECT (qtdemux, "allocating n_samples %u * %u (%.2f MB)",
3351       stream->n_samples + samples_count, (guint) sizeof (QtDemuxSample),
3352       (stream->n_samples + samples_count) *
3353       sizeof (QtDemuxSample) / (1024.0 * 1024.0));
3354
3355   /* create a new array of samples if it's the first sample parsed */
3356   if (stream->n_samples == 0) {
3357     g_assert (stream->samples == NULL);
3358     stream->samples = g_try_new0 (QtDemuxSample, samples_count);
3359     /* or try to reallocate it with space enough to insert the new samples */
3360   } else
3361     stream->samples = g_try_renew (QtDemuxSample, stream->samples,
3362         stream->n_samples + samples_count);
3363   if (stream->samples == NULL)
3364     goto out_of_memory;
3365
3366   if (qtdemux->fragment_start != -1) {
3367     timestamp = GSTTIME_TO_QTSTREAMTIME (stream, qtdemux->fragment_start);
3368     qtdemux->fragment_start = -1;
3369   } else {
3370     if (stream->n_samples == 0) {
3371       if (decode_ts > 0) {
3372         timestamp = decode_ts;
3373       } else if (stream->pending_seek != NULL) {
3374         /* if we don't have a timestamp from a tfdt box, we'll use the one
3375          * from the mfra seek table */
3376         GST_INFO_OBJECT (stream->pad, "pending seek ts = %" GST_TIME_FORMAT,
3377             GST_TIME_ARGS (stream->pending_seek->ts));
3378
3379         /* FIXME: this is not fully correct, the timestamp refers to the random
3380          * access sample refered to in the tfra entry, which may not necessarily
3381          * be the first sample in the tfrag/trun (but hopefully/usually is) */
3382         timestamp = GSTTIME_TO_QTSTREAMTIME (stream, stream->pending_seek->ts);
3383       } else {
3384         timestamp = 0;
3385       }
3386
3387       gst_ts = QTSTREAMTIME_TO_GSTTIME (stream, timestamp);
3388       GST_INFO_OBJECT (stream->pad, "first sample ts %" GST_TIME_FORMAT,
3389           GST_TIME_ARGS (gst_ts));
3390     } else {
3391       /* subsequent fragments extend stream */
3392       timestamp =
3393           stream->samples[stream->n_samples - 1].timestamp +
3394           stream->samples[stream->n_samples - 1].duration;
3395
3396       /* If this is a GST_FORMAT_BYTES stream and there's a significant
3397        * difference (1 sec.) between decode_ts and timestamp, prefer the
3398        * former */
3399       if (has_tfdt && !qtdemux->upstream_format_is_time
3400           && ABSDIFF (decode_ts, timestamp) >
3401           MAX (stream->duration_last_moof / 2,
3402               GSTTIME_TO_QTSTREAMTIME (stream, GST_SECOND))) {
3403         GST_INFO_OBJECT (qtdemux,
3404             "decode_ts (%" GST_TIME_FORMAT ") and timestamp (%" GST_TIME_FORMAT
3405             ") are significantly different (more than %" GST_TIME_FORMAT
3406             "), using decode_ts",
3407             GST_TIME_ARGS (QTSTREAMTIME_TO_GSTTIME (stream, decode_ts)),
3408             GST_TIME_ARGS (QTSTREAMTIME_TO_GSTTIME (stream, timestamp)),
3409             GST_TIME_ARGS (QTSTREAMTIME_TO_GSTTIME (stream,
3410                     MAX (stream->duration_last_moof / 2,
3411                         GSTTIME_TO_QTSTREAMTIME (stream, GST_SECOND)))));
3412         timestamp = decode_ts;
3413       }
3414
3415       gst_ts = QTSTREAMTIME_TO_GSTTIME (stream, timestamp);
3416       GST_INFO_OBJECT (qtdemux, "first sample ts %" GST_TIME_FORMAT
3417           " (extends previous samples)", GST_TIME_ARGS (gst_ts));
3418     }
3419   }
3420
3421   initial_offset = *running_offset;
3422
3423   sample = stream->samples + stream->n_samples;
3424   for (i = 0; i < samples_count; i++) {
3425     guint32 dur, size, sflags, ct;
3426
3427     /* first read sample data */
3428     if (flags & TR_SAMPLE_DURATION) {
3429       dur = QT_UINT32 (data + dur_offset);
3430     } else {
3431       dur = d_sample_duration;
3432     }
3433     if (flags & TR_SAMPLE_SIZE) {
3434       size = QT_UINT32 (data + size_offset);
3435     } else {
3436       size = d_sample_size;
3437     }
3438     if (flags & TR_FIRST_SAMPLE_FLAGS) {
3439       if (i == 0) {
3440         sflags = first_flags;
3441       } else {
3442         sflags = d_sample_flags;
3443       }
3444     } else if (flags & TR_SAMPLE_FLAGS) {
3445       sflags = QT_UINT32 (data + flags_offset);
3446     } else {
3447       sflags = d_sample_flags;
3448     }
3449     if (flags & TR_COMPOSITION_TIME_OFFSETS) {
3450       ct = QT_UINT32 (data + ct_offset);
3451     } else {
3452       ct = 0;
3453     }
3454     data += entry_size;
3455
3456     /* fill the sample information */
3457     sample->offset = *running_offset;
3458     sample->pts_offset = ct;
3459     sample->size = size;
3460     sample->timestamp = timestamp;
3461     sample->duration = dur;
3462     /* sample-is-difference-sample */
3463     /* ismv seems to use 0x40 for keyframe, 0xc0 for non-keyframe,
3464      * now idea how it relates to bitfield other than massive LE/BE confusion */
3465     sample->keyframe = ismv ? ((sflags & 0xff) == 0x40) : !(sflags & 0x10000);
3466     *running_offset += size;
3467     timestamp += dur;
3468     stream->duration_moof += dur;
3469     sample++;
3470   }
3471
3472   /* Update total duration if needed */
3473   check_update_duration (qtdemux, QTSTREAMTIME_TO_GSTTIME (stream, timestamp));
3474
3475   /* Pre-emptively figure out size of mdat based on trun information.
3476    * If the [mdat] atom is effectivelly read, it will be replaced by the actual
3477    * size, else we will still be able to use this when dealing with gap'ed
3478    * input */
3479   qtdemux->mdatleft = *running_offset - initial_offset;
3480   qtdemux->mdatoffset = initial_offset;
3481   qtdemux->mdatsize = qtdemux->mdatleft;
3482
3483   stream->n_samples += samples_count;
3484   stream->n_samples_moof += samples_count;
3485
3486   if (stream->pending_seek != NULL)
3487     stream->pending_seek = NULL;
3488
3489   return TRUE;
3490
3491 fail:
3492   {
3493     GST_WARNING_OBJECT (qtdemux, "failed to parse trun");
3494     return FALSE;
3495   }
3496 out_of_memory:
3497   {
3498     GST_WARNING_OBJECT (qtdemux, "failed to allocate %d samples",
3499         stream->n_samples);
3500     return FALSE;
3501   }
3502 index_too_big:
3503   {
3504     GST_WARNING_OBJECT (qtdemux, "not allocating index of %d samples, would "
3505         "be larger than %uMB (broken file?)", stream->n_samples,
3506         QTDEMUX_MAX_SAMPLE_INDEX_SIZE >> 20);
3507     return FALSE;
3508   }
3509 }
3510
3511 /* find stream with @id */
3512 static inline QtDemuxStream *
3513 qtdemux_find_stream (GstQTDemux * qtdemux, guint32 id)
3514 {
3515   QtDemuxStream *stream;
3516   GList *iter;
3517
3518   /* check */
3519   if (G_UNLIKELY (!id)) {
3520     GST_DEBUG_OBJECT (qtdemux, "invalid track id 0");
3521     return NULL;
3522   }
3523
3524   for (iter = qtdemux->active_streams; iter; iter = g_list_next (iter)) {
3525     stream = QTDEMUX_STREAM (iter->data);
3526     if (stream->track_id == id)
3527       return stream;
3528   }
3529   if (qtdemux->mss_mode) {
3530     /* mss should have only 1 stream anyway */
3531     return QTDEMUX_FIRST_STREAM (qtdemux);
3532   }
3533
3534   return NULL;
3535 }
3536
3537 static gboolean
3538 qtdemux_parse_mfhd (GstQTDemux * qtdemux, GstByteReader * mfhd,
3539     guint32 * fragment_number)
3540 {
3541   if (!gst_byte_reader_skip (mfhd, 4))
3542     goto fail;
3543   if (!gst_byte_reader_get_uint32_be (mfhd, fragment_number))
3544     goto fail;
3545   return TRUE;
3546 fail:
3547   {
3548     GST_WARNING_OBJECT (qtdemux, "Failed to parse mfhd atom");
3549     return FALSE;
3550   }
3551 }
3552
3553 static gboolean
3554 qtdemux_parse_tfhd (GstQTDemux * qtdemux, GstByteReader * tfhd,
3555     QtDemuxStream ** stream, guint32 * default_sample_duration,
3556     guint32 * default_sample_size, guint32 * default_sample_flags,
3557     gint64 * base_offset)
3558 {
3559   guint32 flags = 0;
3560   guint32 track_id = 0;
3561
3562   if (!gst_byte_reader_skip (tfhd, 1) ||
3563       !gst_byte_reader_get_uint24_be (tfhd, &flags))
3564     goto invalid_track;
3565
3566   if (!gst_byte_reader_get_uint32_be (tfhd, &track_id))
3567     goto invalid_track;
3568
3569   *stream = qtdemux_find_stream (qtdemux, track_id);
3570   if (G_UNLIKELY (!*stream))
3571     goto unknown_stream;
3572
3573   if (flags & TF_DEFAULT_BASE_IS_MOOF)
3574     *base_offset = qtdemux->moof_offset;
3575
3576   if (flags & TF_BASE_DATA_OFFSET)
3577     if (!gst_byte_reader_get_uint64_be (tfhd, (guint64 *) base_offset))
3578       goto invalid_track;
3579
3580   /* obtain stream defaults */
3581   qtdemux_parse_trex (qtdemux, *stream,
3582       default_sample_duration, default_sample_size, default_sample_flags);
3583
3584   (*stream)->stsd_sample_description_id =
3585       (*stream)->def_sample_description_index - 1;
3586
3587   if (flags & TF_SAMPLE_DESCRIPTION_INDEX) {
3588     guint32 sample_description_index;
3589     if (!gst_byte_reader_get_uint32_be (tfhd, &sample_description_index))
3590       goto invalid_track;
3591     (*stream)->stsd_sample_description_id = sample_description_index - 1;
3592   }
3593
3594   if (qtdemux->mss_mode) {
3595     /* mss has no stsd entry */
3596     (*stream)->stsd_sample_description_id = 0;
3597   }
3598
3599   if (flags & TF_DEFAULT_SAMPLE_DURATION)
3600     if (!gst_byte_reader_get_uint32_be (tfhd, default_sample_duration))
3601       goto invalid_track;
3602
3603   if (flags & TF_DEFAULT_SAMPLE_SIZE)
3604     if (!gst_byte_reader_get_uint32_be (tfhd, default_sample_size))
3605       goto invalid_track;
3606
3607   if (flags & TF_DEFAULT_SAMPLE_FLAGS)
3608     if (!gst_byte_reader_get_uint32_be (tfhd, default_sample_flags))
3609       goto invalid_track;
3610
3611   return TRUE;
3612
3613 invalid_track:
3614   {
3615     GST_WARNING_OBJECT (qtdemux, "invalid track fragment header");
3616     return FALSE;
3617   }
3618 unknown_stream:
3619   {
3620     GST_DEBUG_OBJECT (qtdemux, "unknown stream in tfhd");
3621     return TRUE;
3622   }
3623 }
3624
3625 static gboolean
3626 qtdemux_parse_tfdt (GstQTDemux * qtdemux, GstByteReader * br,
3627     guint64 * decode_time)
3628 {
3629   guint32 version = 0;
3630
3631   if (!gst_byte_reader_get_uint32_be (br, &version))
3632     return FALSE;
3633
3634   version >>= 24;
3635   if (version == 1) {
3636     if (!gst_byte_reader_get_uint64_be (br, decode_time))
3637       goto failed;
3638   } else {
3639     guint32 dec_time = 0;
3640     if (!gst_byte_reader_get_uint32_be (br, &dec_time))
3641       goto failed;
3642     *decode_time = dec_time;
3643   }
3644
3645   GST_INFO_OBJECT (qtdemux, "Track fragment decode time: %" G_GUINT64_FORMAT,
3646       *decode_time);
3647
3648   return TRUE;
3649
3650 failed:
3651   {
3652     GST_DEBUG_OBJECT (qtdemux, "parsing tfdt failed");
3653     return FALSE;
3654   }
3655 }
3656
3657 /* Returns a pointer to a GstStructure containing the properties of
3658  * the stream sample identified by @sample_index. The caller must unref
3659  * the returned object after use. Returns NULL if unsuccessful. */
3660 static GstStructure *
3661 qtdemux_get_cenc_sample_properties (GstQTDemux * qtdemux,
3662     QtDemuxStream * stream, guint sample_index)
3663 {
3664   QtDemuxCencSampleSetInfo *info = NULL;
3665
3666   g_return_val_if_fail (stream != NULL, NULL);
3667   g_return_val_if_fail (stream->protected, NULL);
3668   g_return_val_if_fail (stream->protection_scheme_info != NULL, NULL);
3669
3670   info = (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
3671
3672   /* Currently, cenc properties for groups of samples are not supported, so
3673    * simply return a copy of the default sample properties */
3674   return gst_structure_copy (info->default_properties);
3675 }
3676
3677 /* Parses the sizes of sample auxiliary information contained within a stream,
3678  * as given in a saiz box. Returns array of sample_count guint8 size values,
3679  * or NULL on failure */
3680 static guint8 *
3681 qtdemux_parse_saiz (GstQTDemux * qtdemux, QtDemuxStream * stream,
3682     GstByteReader * br, guint32 * sample_count)
3683 {
3684   guint32 flags = 0;
3685   guint8 *info_sizes;
3686   guint8 default_info_size;
3687
3688   g_return_val_if_fail (qtdemux != NULL, NULL);
3689   g_return_val_if_fail (stream != NULL, NULL);
3690   g_return_val_if_fail (br != NULL, NULL);
3691   g_return_val_if_fail (sample_count != NULL, NULL);
3692
3693   if (!gst_byte_reader_get_uint32_be (br, &flags))
3694     return NULL;
3695
3696   if (flags & 0x1) {
3697     /* aux_info_type and aux_info_type_parameter are ignored */
3698     if (!gst_byte_reader_skip (br, 8))
3699       return NULL;
3700   }
3701
3702   if (!gst_byte_reader_get_uint8 (br, &default_info_size))
3703     return NULL;
3704   GST_DEBUG_OBJECT (qtdemux, "default_info_size: %u", default_info_size);
3705
3706   if (!gst_byte_reader_get_uint32_be (br, sample_count))
3707     return NULL;
3708   GST_DEBUG_OBJECT (qtdemux, "sample_count: %u", *sample_count);
3709
3710
3711   if (default_info_size == 0) {
3712     if (!gst_byte_reader_dup_data (br, *sample_count, &info_sizes)) {
3713       return NULL;
3714     }
3715   } else {
3716     info_sizes = g_new (guint8, *sample_count);
3717     memset (info_sizes, default_info_size, *sample_count);
3718   }
3719
3720   return info_sizes;
3721 }
3722
3723 /* Parses the offset of sample auxiliary information contained within a stream,
3724  * as given in a saio box. Returns TRUE if successful; FALSE otherwise. */
3725 static gboolean
3726 qtdemux_parse_saio (GstQTDemux * qtdemux, QtDemuxStream * stream,
3727     GstByteReader * br, guint32 * info_type, guint32 * info_type_parameter,
3728     guint64 * offset)
3729 {
3730   guint8 version = 0;
3731   guint32 flags = 0;
3732   guint32 aux_info_type = 0;
3733   guint32 aux_info_type_parameter = 0;
3734   guint32 entry_count;
3735   guint32 off_32;
3736   guint64 off_64;
3737   const guint8 *aux_info_type_data = NULL;
3738
3739   g_return_val_if_fail (qtdemux != NULL, FALSE);
3740   g_return_val_if_fail (stream != NULL, FALSE);
3741   g_return_val_if_fail (br != NULL, FALSE);
3742   g_return_val_if_fail (offset != NULL, FALSE);
3743
3744   if (!gst_byte_reader_get_uint8 (br, &version))
3745     return FALSE;
3746
3747   if (!gst_byte_reader_get_uint24_be (br, &flags))
3748     return FALSE;
3749
3750   if (flags & 0x1) {
3751
3752     if (!gst_byte_reader_get_data (br, 4, &aux_info_type_data))
3753       return FALSE;
3754     aux_info_type = QT_FOURCC (aux_info_type_data);
3755
3756     if (!gst_byte_reader_get_uint32_be (br, &aux_info_type_parameter))
3757       return FALSE;
3758   } else if (stream->protected) {
3759     aux_info_type = stream->protection_scheme_type;
3760   } else {
3761     aux_info_type = CUR_STREAM (stream)->fourcc;
3762   }
3763
3764   if (info_type)
3765     *info_type = aux_info_type;
3766   if (info_type_parameter)
3767     *info_type_parameter = aux_info_type_parameter;
3768
3769   GST_DEBUG_OBJECT (qtdemux, "aux_info_type: '%" GST_FOURCC_FORMAT "', "
3770       "aux_info_type_parameter:  %#06x",
3771       GST_FOURCC_ARGS (aux_info_type), aux_info_type_parameter);
3772
3773   if (!gst_byte_reader_get_uint32_be (br, &entry_count))
3774     return FALSE;
3775
3776   if (entry_count != 1) {
3777     GST_ERROR_OBJECT (qtdemux, "multiple offsets are not supported");
3778     return FALSE;
3779   }
3780
3781   if (version == 0) {
3782     if (!gst_byte_reader_get_uint32_be (br, &off_32))
3783       return FALSE;
3784     *offset = (guint64) off_32;
3785   } else {
3786     if (!gst_byte_reader_get_uint64_be (br, &off_64))
3787       return FALSE;
3788     *offset = off_64;
3789   }
3790
3791   GST_DEBUG_OBJECT (qtdemux, "offset: %" G_GUINT64_FORMAT, *offset);
3792   return TRUE;
3793 }
3794
3795 static void
3796 qtdemux_gst_structure_free (GstStructure * gststructure)
3797 {
3798   if (gststructure) {
3799     gst_structure_free (gststructure);
3800   }
3801 }
3802
3803 /* Parses auxiliary information relating to samples protected using Common
3804  * Encryption (cenc); the format of this information is defined in
3805  * ISO/IEC 23001-7. Returns TRUE if successful; FALSE otherwise. */
3806 static gboolean
3807 qtdemux_parse_cenc_aux_info (GstQTDemux * qtdemux, QtDemuxStream * stream,
3808     GstByteReader * br, guint8 * info_sizes, guint32 sample_count)
3809 {
3810   QtDemuxCencSampleSetInfo *ss_info = NULL;
3811   guint8 size;
3812   gint i;
3813   GPtrArray *old_crypto_info = NULL;
3814   guint old_entries = 0;
3815
3816   g_return_val_if_fail (qtdemux != NULL, FALSE);
3817   g_return_val_if_fail (stream != NULL, FALSE);
3818   g_return_val_if_fail (br != NULL, FALSE);
3819   g_return_val_if_fail (stream->protected, FALSE);
3820   g_return_val_if_fail (stream->protection_scheme_info != NULL, FALSE);
3821
3822   ss_info = (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
3823
3824   if (ss_info->crypto_info) {
3825     old_crypto_info = ss_info->crypto_info;
3826     /* Count number of non-null entries remaining at the tail end */
3827     for (i = old_crypto_info->len - 1; i >= 0; i--) {
3828       if (g_ptr_array_index (old_crypto_info, i) == NULL)
3829         break;
3830       old_entries++;
3831     }
3832   }
3833
3834   ss_info->crypto_info =
3835       g_ptr_array_new_full (sample_count + old_entries,
3836       (GDestroyNotify) qtdemux_gst_structure_free);
3837
3838   /* We preserve old entries because we parse the next moof in advance
3839    * of consuming all samples from the previous moof, and otherwise
3840    * we'd discard the corresponding crypto info for the samples
3841    * from the previous fragment. */
3842   if (old_entries) {
3843     GST_DEBUG_OBJECT (qtdemux, "Preserving %d old crypto info entries",
3844         old_entries);
3845     for (i = old_crypto_info->len - old_entries; i < old_crypto_info->len; i++) {
3846       g_ptr_array_add (ss_info->crypto_info, g_ptr_array_index (old_crypto_info,
3847               i));
3848       g_ptr_array_index (old_crypto_info, i) = NULL;
3849     }
3850   }
3851
3852   if (old_crypto_info) {
3853     /* Everything now belongs to the new array */
3854     g_ptr_array_free (old_crypto_info, TRUE);
3855   }
3856
3857   for (i = 0; i < sample_count; ++i) {
3858     GstStructure *properties;
3859     guint16 n_subsamples = 0;
3860     guint8 *data;
3861     guint iv_size;
3862     GstBuffer *buf;
3863
3864     properties = qtdemux_get_cenc_sample_properties (qtdemux, stream, i);
3865     if (properties == NULL) {
3866       GST_ERROR_OBJECT (qtdemux, "failed to get properties for sample %u", i);
3867       return FALSE;
3868     }
3869     if (!gst_structure_get_uint (properties, "iv_size", &iv_size)) {
3870       GST_ERROR_OBJECT (qtdemux, "failed to get iv_size for sample %u", i);
3871       gst_structure_free (properties);
3872       return FALSE;
3873     }
3874     if (!gst_byte_reader_dup_data (br, iv_size, &data)) {
3875       GST_ERROR_OBJECT (qtdemux, "failed to get IV for sample %u", i);
3876       gst_structure_free (properties);
3877       return FALSE;
3878     }
3879     buf = gst_buffer_new_wrapped (data, iv_size);
3880     gst_structure_set (properties, "iv", GST_TYPE_BUFFER, buf, NULL);
3881     gst_buffer_unref (buf);
3882     size = info_sizes[i];
3883     if (size > iv_size) {
3884       if (!gst_byte_reader_get_uint16_be (br, &n_subsamples)
3885           || !(n_subsamples > 0)) {
3886         gst_structure_free (properties);
3887         GST_ERROR_OBJECT (qtdemux,
3888             "failed to get subsample count for sample %u", i);
3889         return FALSE;
3890       }
3891       GST_LOG_OBJECT (qtdemux, "subsample count: %u", n_subsamples);
3892       if (!gst_byte_reader_dup_data (br, n_subsamples * 6, &data)) {
3893         GST_ERROR_OBJECT (qtdemux, "failed to get subsample data for sample %u",
3894             i);
3895         gst_structure_free (properties);
3896         return FALSE;
3897       }
3898       buf = gst_buffer_new_wrapped (data, n_subsamples * 6);
3899       if (!buf) {
3900         gst_structure_free (properties);
3901         return FALSE;
3902       }
3903       gst_structure_set (properties,
3904           "subsample_count", G_TYPE_UINT, n_subsamples,
3905           "subsamples", GST_TYPE_BUFFER, buf, NULL);
3906       gst_buffer_unref (buf);
3907     } else {
3908       gst_structure_set (properties, "subsample_count", G_TYPE_UINT, 0, NULL);
3909     }
3910     g_ptr_array_add (ss_info->crypto_info, properties);
3911   }
3912   return TRUE;
3913 }
3914
3915 /* Converts a UUID in raw byte form to a string representation, as defined in
3916  * RFC 4122. The caller takes ownership of the returned string and is
3917  * responsible for freeing it after use. */
3918 static gchar *
3919 qtdemux_uuid_bytes_to_string (gconstpointer uuid_bytes)
3920 {
3921   const guint8 *uuid = (const guint8 *) uuid_bytes;
3922
3923   return g_strdup_printf ("%02x%02x%02x%02x-%02x%02x-%02x%02x-"
3924       "%02x%02x-%02x%02x%02x%02x%02x%02x",
3925       uuid[0], uuid[1], uuid[2], uuid[3],
3926       uuid[4], uuid[5], uuid[6], uuid[7],
3927       uuid[8], uuid[9], uuid[10], uuid[11],
3928       uuid[12], uuid[13], uuid[14], uuid[15]);
3929 }
3930
3931 /* Parses a Protection System Specific Header box (pssh), as defined in the
3932  * Common Encryption (cenc) standard (ISO/IEC 23001-7), which contains
3933  * information needed by a specific content protection system in order to
3934  * decrypt cenc-protected tracks. Returns TRUE if successful; FALSE
3935  * otherwise. */
3936 static gboolean
3937 qtdemux_parse_pssh (GstQTDemux * qtdemux, GNode * node)
3938 {
3939   gchar *sysid_string;
3940   guint32 pssh_size = QT_UINT32 (node->data);
3941   GstBuffer *pssh = NULL;
3942   GstEvent *event = NULL;
3943   guint32 parent_box_type;
3944   GList *iter;
3945
3946   if (G_UNLIKELY (pssh_size < 32U)) {
3947     GST_ERROR_OBJECT (qtdemux, "invalid box size");
3948     return FALSE;
3949   }
3950
3951   sysid_string =
3952       qtdemux_uuid_bytes_to_string ((const guint8 *) node->data + 12);
3953
3954   gst_qtdemux_append_protection_system_id (qtdemux, sysid_string);
3955
3956   pssh = gst_buffer_new_wrapped (g_memdup (node->data, pssh_size), pssh_size);
3957   GST_LOG_OBJECT (qtdemux, "cenc pssh size: %" G_GSIZE_FORMAT,
3958       gst_buffer_get_size (pssh));
3959
3960   parent_box_type = QT_FOURCC ((const guint8 *) node->parent->data + 4);
3961
3962   /* Push an event containing the pssh box onto the queues of all streams. */
3963   event = gst_event_new_protection (sysid_string, pssh,
3964       (parent_box_type == FOURCC_moov) ? "isobmff/moov" : "isobmff/moof");
3965   for (iter = qtdemux->active_streams; iter; iter = g_list_next (iter)) {
3966     QtDemuxStream *stream = QTDEMUX_STREAM (iter->data);
3967     GST_TRACE_OBJECT (qtdemux,
3968         "adding protection event for stream %s and system %s",
3969         stream->stream_id, sysid_string);
3970     g_queue_push_tail (&stream->protection_scheme_event_queue,
3971         gst_event_ref (event));
3972   }
3973   g_free (sysid_string);
3974   gst_event_unref (event);
3975   gst_buffer_unref (pssh);
3976   return TRUE;
3977 }
3978
3979 static gboolean
3980 qtdemux_parse_moof (GstQTDemux * qtdemux, const guint8 * buffer, guint length,
3981     guint64 moof_offset, QtDemuxStream * stream)
3982 {
3983   GNode *moof_node, *traf_node, *tfhd_node, *trun_node, *tfdt_node, *mfhd_node;
3984   GNode *uuid_node;
3985   GstByteReader mfhd_data, trun_data, tfhd_data, tfdt_data;
3986   GNode *saiz_node, *saio_node, *pssh_node;
3987   GstByteReader saiz_data, saio_data;
3988   guint32 ds_size = 0, ds_duration = 0, ds_flags = 0;
3989   gint64 base_offset, running_offset;
3990   guint32 frag_num;
3991   GstClockTime min_dts = GST_CLOCK_TIME_NONE;
3992
3993   /* NOTE @stream ignored */
3994
3995   moof_node = g_node_new ((guint8 *) buffer);
3996   qtdemux_parse_node (qtdemux, moof_node, buffer, length);
3997   qtdemux_node_dump (qtdemux, moof_node);
3998
3999   /* Get fragment number from mfhd and check it's valid */
4000   mfhd_node =
4001       qtdemux_tree_get_child_by_type_full (moof_node, FOURCC_mfhd, &mfhd_data);
4002   if (mfhd_node == NULL)
4003     goto missing_mfhd;
4004   if (!qtdemux_parse_mfhd (qtdemux, &mfhd_data, &frag_num))
4005     goto fail;
4006   GST_DEBUG_OBJECT (qtdemux, "Fragment #%d", frag_num);
4007
4008   /* unknown base_offset to start with */
4009   base_offset = running_offset = -1;
4010   traf_node = qtdemux_tree_get_child_by_type (moof_node, FOURCC_traf);
4011   while (traf_node) {
4012     guint64 decode_time = 0;
4013
4014     /* Fragment Header node */
4015     tfhd_node =
4016         qtdemux_tree_get_child_by_type_full (traf_node, FOURCC_tfhd,
4017         &tfhd_data);
4018     if (!tfhd_node)
4019       goto missing_tfhd;
4020     if (!qtdemux_parse_tfhd (qtdemux, &tfhd_data, &stream, &ds_duration,
4021             &ds_size, &ds_flags, &base_offset))
4022       goto missing_tfhd;
4023
4024     /* The following code assumes at most a single set of sample auxiliary
4025      * data in the fragment (consisting of a saiz box and a corresponding saio
4026      * box); in theory, however, there could be multiple sets of sample
4027      * auxiliary data in a fragment. */
4028     saiz_node =
4029         qtdemux_tree_get_child_by_type_full (traf_node, FOURCC_saiz,
4030         &saiz_data);
4031     if (saiz_node) {
4032       guint32 info_type = 0;
4033       guint64 offset = 0;
4034       guint32 info_type_parameter = 0;
4035
4036       g_free (qtdemux->cenc_aux_info_sizes);
4037
4038       qtdemux->cenc_aux_info_sizes =
4039           qtdemux_parse_saiz (qtdemux, stream, &saiz_data,
4040           &qtdemux->cenc_aux_sample_count);
4041       if (qtdemux->cenc_aux_info_sizes == NULL) {
4042         GST_ERROR_OBJECT (qtdemux, "failed to parse saiz box");
4043         goto fail;
4044       }
4045       saio_node =
4046           qtdemux_tree_get_child_by_type_full (traf_node, FOURCC_saio,
4047           &saio_data);
4048       if (!saio_node) {
4049         GST_ERROR_OBJECT (qtdemux, "saiz box without a corresponding saio box");
4050         g_free (qtdemux->cenc_aux_info_sizes);
4051         qtdemux->cenc_aux_info_sizes = NULL;
4052         goto fail;
4053       }
4054
4055       if (G_UNLIKELY (!qtdemux_parse_saio (qtdemux, stream, &saio_data,
4056                   &info_type, &info_type_parameter, &offset))) {
4057         GST_ERROR_OBJECT (qtdemux, "failed to parse saio box");
4058         g_free (qtdemux->cenc_aux_info_sizes);
4059         qtdemux->cenc_aux_info_sizes = NULL;
4060         goto fail;
4061       }
4062       if (base_offset > -1 && base_offset > qtdemux->moof_offset)
4063         offset += (guint64) (base_offset - qtdemux->moof_offset);
4064       if (info_type == FOURCC_cenc && info_type_parameter == 0U) {
4065         GstByteReader br;
4066         if (offset > length) {
4067           GST_DEBUG_OBJECT (qtdemux, "cenc auxiliary info stored out of moof");
4068           qtdemux->cenc_aux_info_offset = offset;
4069         } else {
4070           gst_byte_reader_init (&br, buffer + offset, length - offset);
4071           if (!qtdemux_parse_cenc_aux_info (qtdemux, stream, &br,
4072                   qtdemux->cenc_aux_info_sizes,
4073                   qtdemux->cenc_aux_sample_count)) {
4074             GST_ERROR_OBJECT (qtdemux, "failed to parse cenc auxiliary info");
4075             g_free (qtdemux->cenc_aux_info_sizes);
4076             qtdemux->cenc_aux_info_sizes = NULL;
4077             goto fail;
4078           }
4079         }
4080       }
4081     }
4082
4083     tfdt_node =
4084         qtdemux_tree_get_child_by_type_full (traf_node, FOURCC_tfdt,
4085         &tfdt_data);
4086     if (tfdt_node) {
4087       /* We'll use decode_time to interpolate timestamps
4088        * in case the input timestamps are missing */
4089       qtdemux_parse_tfdt (qtdemux, &tfdt_data, &decode_time);
4090
4091       GST_DEBUG_OBJECT (qtdemux, "decode time %" G_GINT64_FORMAT
4092           " (%" GST_TIME_FORMAT ")", decode_time,
4093           GST_TIME_ARGS (stream ? QTSTREAMTIME_TO_GSTTIME (stream,
4094                   decode_time) : GST_CLOCK_TIME_NONE));
4095
4096       /* Discard the fragment buffer timestamp info to avoid using it.
4097        * Rely on tfdt instead as it is more accurate than the timestamp
4098        * that is fetched from a manifest/playlist and is usually
4099        * less accurate. */
4100       qtdemux->fragment_start = -1;
4101     }
4102
4103     if (G_UNLIKELY (!stream)) {
4104       /* we lost track of offset, we'll need to regain it,
4105        * but can delay complaining until later or avoid doing so altogether */
4106       base_offset = -2;
4107       goto next;
4108     }
4109     if (G_UNLIKELY (base_offset < -1))
4110       goto lost_offset;
4111
4112     min_dts = MIN (min_dts, QTSTREAMTIME_TO_GSTTIME (stream, decode_time));
4113
4114     if (!qtdemux->pullbased) {
4115       /* Sample tables can grow enough to be problematic if the system memory
4116        * is very low (e.g. embedded devices) and the videos very long
4117        * (~8 MiB/hour for 25-30 fps video + typical AAC audio frames).
4118        * Fortunately, we can easily discard them for each new fragment when
4119        * we know qtdemux will not receive seeks outside of the current fragment.
4120        * adaptivedemux honors this assumption.
4121        * This optimization is also useful for applications that use qtdemux as
4122        * a push-based simple demuxer, like Media Source Extensions. */
4123       gst_qtdemux_stream_flush_samples_data (stream);
4124     }
4125
4126     /* initialise moof sample data */
4127     stream->n_samples_moof = 0;
4128     stream->duration_last_moof = stream->duration_moof;
4129     stream->duration_moof = 0;
4130
4131     /* Track Run node */
4132     trun_node =
4133         qtdemux_tree_get_child_by_type_full (traf_node, FOURCC_trun,
4134         &trun_data);
4135     while (trun_node) {
4136       qtdemux_parse_trun (qtdemux, &trun_data, stream,
4137           ds_duration, ds_size, ds_flags, moof_offset, length, &base_offset,
4138           &running_offset, decode_time, (tfdt_node != NULL));
4139       /* iterate all siblings */
4140       trun_node = qtdemux_tree_get_sibling_by_type_full (trun_node, FOURCC_trun,
4141           &trun_data);
4142     }
4143
4144     uuid_node = qtdemux_tree_get_child_by_type (traf_node, FOURCC_uuid);
4145     if (uuid_node) {
4146       guint8 *uuid_buffer = (guint8 *) uuid_node->data;
4147       guint32 box_length = QT_UINT32 (uuid_buffer);
4148
4149       qtdemux_parse_uuid (qtdemux, uuid_buffer, box_length);
4150     }
4151
4152     /* if no new base_offset provided for next traf,
4153      * base is end of current traf */
4154     base_offset = running_offset;
4155     running_offset = -1;
4156
4157     if (stream->n_samples_moof && stream->duration_moof)
4158       stream->new_caps = TRUE;
4159
4160   next:
4161     /* iterate all siblings */
4162     traf_node = qtdemux_tree_get_sibling_by_type (traf_node, FOURCC_traf);
4163   }
4164
4165   /* parse any protection system info */
4166   pssh_node = qtdemux_tree_get_child_by_type (moof_node, FOURCC_pssh);
4167   while (pssh_node) {
4168     GST_LOG_OBJECT (qtdemux, "Parsing pssh box.");
4169     qtdemux_parse_pssh (qtdemux, pssh_node);
4170     pssh_node = qtdemux_tree_get_sibling_by_type (pssh_node, FOURCC_pssh);
4171   }
4172
4173   if (!qtdemux->upstream_format_is_time && !qtdemux->first_moof_already_parsed
4174       && !qtdemux->received_seek && GST_CLOCK_TIME_IS_VALID (min_dts)
4175       && min_dts != 0) {
4176     /* Unless the user has explictly requested another seek, perform an
4177      * internal seek to the time specified in the tfdt.
4178      *
4179      * This way if the user opens a file where the first tfdt is 1 hour
4180      * into the presentation, they will not have to wait 1 hour for run
4181      * time to catch up and actual playback to start. */
4182     GList *iter;
4183
4184     GST_DEBUG_OBJECT (qtdemux, "First fragment has a non-zero tfdt, "
4185         "performing an internal seek to %" GST_TIME_FORMAT,
4186         GST_TIME_ARGS (min_dts));
4187
4188     qtdemux->segment.start = min_dts;
4189     qtdemux->segment.time = qtdemux->segment.position = min_dts;
4190
4191     for (iter = qtdemux->active_streams; iter; iter = g_list_next (iter)) {
4192       QtDemuxStream *stream = QTDEMUX_STREAM (iter->data);
4193       stream->time_position = min_dts;
4194     }
4195
4196     /* Before this code was run a segment was already sent when the moov was
4197      * parsed... which is OK -- some apps (mostly tests) expect a segment to
4198      * be emitted after a moov, and we can emit a second segment anyway for
4199      * special cases like this. */
4200     qtdemux->need_segment = TRUE;
4201   }
4202
4203   qtdemux->first_moof_already_parsed = TRUE;
4204
4205   g_node_destroy (moof_node);
4206   return TRUE;
4207
4208 missing_tfhd:
4209   {
4210     GST_DEBUG_OBJECT (qtdemux, "missing tfhd box");
4211     goto fail;
4212   }
4213 missing_mfhd:
4214   {
4215     GST_DEBUG_OBJECT (qtdemux, "Missing mfhd box");
4216     goto fail;
4217   }
4218 lost_offset:
4219   {
4220     GST_DEBUG_OBJECT (qtdemux, "lost offset");
4221     goto fail;
4222   }
4223 fail:
4224   {
4225     g_node_destroy (moof_node);
4226     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
4227         (_("This file is corrupt and cannot be played.")), (NULL));
4228     return FALSE;
4229   }
4230 }
4231
4232 #if 0
4233 /* might be used if some day we actually use mfra & co
4234  * for random access to fragments,
4235  * but that will require quite some modifications and much less relying
4236  * on a sample array */
4237 #endif
4238
4239 static gboolean
4240 qtdemux_parse_tfra (GstQTDemux * qtdemux, GNode * tfra_node)
4241 {
4242   QtDemuxStream *stream;
4243   guint32 ver_flags, track_id, len, num_entries, i;
4244   guint value_size, traf_size, trun_size, sample_size;
4245   guint64 time = 0, moof_offset = 0;
4246 #if 0
4247   GstBuffer *buf = NULL;
4248   GstFlowReturn ret;
4249 #endif
4250   GstByteReader tfra;
4251
4252   gst_byte_reader_init (&tfra, tfra_node->data, QT_UINT32 (tfra_node->data));
4253
4254   if (!gst_byte_reader_skip (&tfra, 8))
4255     return FALSE;
4256
4257   if (!gst_byte_reader_get_uint32_be (&tfra, &ver_flags))
4258     return FALSE;
4259
4260   if (!gst_byte_reader_get_uint32_be (&tfra, &track_id)
4261       || !gst_byte_reader_get_uint32_be (&tfra, &len)
4262       || !gst_byte_reader_get_uint32_be (&tfra, &num_entries))
4263     return FALSE;
4264
4265   GST_DEBUG_OBJECT (qtdemux, "parsing tfra box for track id %u", track_id);
4266
4267   stream = qtdemux_find_stream (qtdemux, track_id);
4268   if (stream == NULL)
4269     goto unknown_trackid;
4270
4271   value_size = ((ver_flags >> 24) == 1) ? sizeof (guint64) : sizeof (guint32);
4272   sample_size = (len & 3) + 1;
4273   trun_size = ((len & 12) >> 2) + 1;
4274   traf_size = ((len & 48) >> 4) + 1;
4275
4276   GST_DEBUG_OBJECT (qtdemux, "%u entries, sizes: value %u, traf %u, trun %u, "
4277       "sample %u", num_entries, value_size, traf_size, trun_size, sample_size);
4278
4279   if (num_entries == 0)
4280     goto no_samples;
4281
4282   if (!qt_atom_parser_has_chunks (&tfra, num_entries,
4283           value_size + value_size + traf_size + trun_size + sample_size))
4284     goto corrupt_file;
4285
4286   g_free (stream->ra_entries);
4287   stream->ra_entries = g_new (QtDemuxRandomAccessEntry, num_entries);
4288   stream->n_ra_entries = num_entries;
4289
4290   for (i = 0; i < num_entries; i++) {
4291     qt_atom_parser_get_offset (&tfra, value_size, &time);
4292     qt_atom_parser_get_offset (&tfra, value_size, &moof_offset);
4293     qt_atom_parser_get_uint_with_size_unchecked (&tfra, traf_size);
4294     qt_atom_parser_get_uint_with_size_unchecked (&tfra, trun_size);
4295     qt_atom_parser_get_uint_with_size_unchecked (&tfra, sample_size);
4296
4297     time = QTSTREAMTIME_TO_GSTTIME (stream, time);
4298
4299     GST_LOG_OBJECT (qtdemux, "fragment time: %" GST_TIME_FORMAT ", "
4300         " moof_offset: %" G_GUINT64_FORMAT, GST_TIME_ARGS (time), moof_offset);
4301
4302     stream->ra_entries[i].ts = time;
4303     stream->ra_entries[i].moof_offset = moof_offset;
4304
4305     /* don't want to go through the entire file and read all moofs at startup */
4306 #if 0
4307     ret = gst_qtdemux_pull_atom (qtdemux, moof_offset, 0, &buf);
4308     if (ret != GST_FLOW_OK)
4309       goto corrupt_file;
4310     qtdemux_parse_moof (qtdemux, GST_BUFFER_DATA (buf), GST_BUFFER_SIZE (buf),
4311         moof_offset, stream);
4312     gst_buffer_unref (buf);
4313 #endif
4314   }
4315
4316   check_update_duration (qtdemux, time);
4317
4318   return TRUE;
4319
4320 /* ERRORS */
4321 unknown_trackid:
4322   {
4323     GST_WARNING_OBJECT (qtdemux, "Couldn't find stream for track %u", track_id);
4324     return FALSE;
4325   }
4326 corrupt_file:
4327   {
4328     GST_WARNING_OBJECT (qtdemux, "broken traf box, ignoring");
4329     return FALSE;
4330   }
4331 no_samples:
4332   {
4333     GST_WARNING_OBJECT (qtdemux, "stream has no samples");
4334     return FALSE;
4335   }
4336 }
4337
4338 static gboolean
4339 qtdemux_pull_mfro_mfra (GstQTDemux * qtdemux)
4340 {
4341   GstMapInfo mfro_map = GST_MAP_INFO_INIT;
4342   GstMapInfo mfra_map = GST_MAP_INFO_INIT;
4343   GstBuffer *mfro = NULL, *mfra = NULL;
4344   GstFlowReturn flow;
4345   gboolean ret = FALSE;
4346   GNode *mfra_node, *tfra_node;
4347   guint64 mfra_offset = 0;
4348   guint32 fourcc, mfra_size;
4349   gint64 len;
4350
4351   /* query upstream size in bytes */
4352   if (!gst_pad_peer_query_duration (qtdemux->sinkpad, GST_FORMAT_BYTES, &len))
4353     goto size_query_failed;
4354
4355   /* mfro box should be at the very end of the file */
4356   flow = gst_qtdemux_pull_atom (qtdemux, len - 16, 16, &mfro);
4357   if (flow != GST_FLOW_OK)
4358     goto exit;
4359
4360   gst_buffer_map (mfro, &mfro_map, GST_MAP_READ);
4361
4362   fourcc = QT_FOURCC (mfro_map.data + 4);
4363   if (fourcc != FOURCC_mfro)
4364     goto exit;
4365
4366   GST_INFO_OBJECT (qtdemux, "Found mfro box");
4367   if (mfro_map.size < 16)
4368     goto invalid_mfro_size;
4369
4370   mfra_size = QT_UINT32 (mfro_map.data + 12);
4371   if (mfra_size >= len)
4372     goto invalid_mfra_size;
4373
4374   mfra_offset = len - mfra_size;
4375
4376   GST_INFO_OBJECT (qtdemux, "mfra offset: %" G_GUINT64_FORMAT ", size %u",
4377       mfra_offset, mfra_size);
4378
4379   /* now get and parse mfra box */
4380   flow = gst_qtdemux_pull_atom (qtdemux, mfra_offset, mfra_size, &mfra);
4381   if (flow != GST_FLOW_OK)
4382     goto broken_file;
4383
4384   gst_buffer_map (mfra, &mfra_map, GST_MAP_READ);
4385
4386   mfra_node = g_node_new ((guint8 *) mfra_map.data);
4387   qtdemux_parse_node (qtdemux, mfra_node, mfra_map.data, mfra_map.size);
4388
4389   tfra_node = qtdemux_tree_get_child_by_type (mfra_node, FOURCC_tfra);
4390
4391   while (tfra_node) {
4392     qtdemux_parse_tfra (qtdemux, tfra_node);
4393     /* iterate all siblings */
4394     tfra_node = qtdemux_tree_get_sibling_by_type (tfra_node, FOURCC_tfra);
4395   }
4396   g_node_destroy (mfra_node);
4397
4398   GST_INFO_OBJECT (qtdemux, "parsed movie fragment random access box (mfra)");
4399   ret = TRUE;
4400
4401 exit:
4402
4403   if (mfro) {
4404     if (mfro_map.memory != NULL)
4405       gst_buffer_unmap (mfro, &mfro_map);
4406     gst_buffer_unref (mfro);
4407   }
4408   if (mfra) {
4409     if (mfra_map.memory != NULL)
4410       gst_buffer_unmap (mfra, &mfra_map);
4411     gst_buffer_unref (mfra);
4412   }
4413   return ret;
4414
4415 /* ERRORS */
4416 size_query_failed:
4417   {
4418     GST_WARNING_OBJECT (qtdemux, "could not query upstream size");
4419     goto exit;
4420   }
4421 invalid_mfro_size:
4422   {
4423     GST_WARNING_OBJECT (qtdemux, "mfro size is too small");
4424     goto exit;
4425   }
4426 invalid_mfra_size:
4427   {
4428     GST_WARNING_OBJECT (qtdemux, "mfra_size in mfro box is invalid");
4429     goto exit;
4430   }
4431 broken_file:
4432   {
4433     GST_WARNING_OBJECT (qtdemux, "bogus mfra offset or size, broken file");
4434     goto exit;
4435   }
4436 }
4437
4438 static guint64
4439 add_offset (guint64 offset, guint64 advance)
4440 {
4441   /* Avoid 64-bit overflow by clamping */
4442   if (offset > G_MAXUINT64 - advance)
4443     return G_MAXUINT64;
4444   return offset + advance;
4445 }
4446
4447 static GstFlowReturn
4448 gst_qtdemux_loop_state_header (GstQTDemux * qtdemux)
4449 {
4450   guint64 length = 0;
4451   guint32 fourcc = 0;
4452   GstBuffer *buf = NULL;
4453   GstFlowReturn ret = GST_FLOW_OK;
4454   guint64 cur_offset = qtdemux->offset;
4455   GstMapInfo map;
4456
4457   ret = gst_pad_pull_range (qtdemux->sinkpad, cur_offset, 16, &buf);
4458   if (G_UNLIKELY (ret != GST_FLOW_OK))
4459     goto beach;
4460   gst_buffer_map (buf, &map, GST_MAP_READ);
4461   if (G_LIKELY (map.size >= 8))
4462     extract_initial_length_and_fourcc (map.data, map.size, &length, &fourcc);
4463   gst_buffer_unmap (buf, &map);
4464   gst_buffer_unref (buf);
4465
4466   /* maybe we already got most we needed, so only consider this eof */
4467   if (G_UNLIKELY (length == 0)) {
4468     GST_ELEMENT_WARNING (qtdemux, STREAM, DEMUX,
4469         (_("Invalid atom size.")),
4470         ("Header atom '%" GST_FOURCC_FORMAT "' has empty length",
4471             GST_FOURCC_ARGS (fourcc)));
4472     ret = GST_FLOW_EOS;
4473     goto beach;
4474   }
4475
4476   switch (fourcc) {
4477     case FOURCC_moof:
4478       /* record for later parsing when needed */
4479       if (!qtdemux->moof_offset) {
4480         qtdemux->moof_offset = qtdemux->offset;
4481       }
4482       if (qtdemux_pull_mfro_mfra (qtdemux)) {
4483         /* FIXME */
4484       } else {
4485         qtdemux->offset += length;      /* skip moof and keep going */
4486       }
4487       if (qtdemux->got_moov) {
4488         GST_INFO_OBJECT (qtdemux, "moof header, got moov, done with headers");
4489         ret = GST_FLOW_EOS;
4490         goto beach;
4491       }
4492       break;
4493     case FOURCC_mdat:
4494     case FOURCC_free:
4495     case FOURCC_skip:
4496     case FOURCC_wide:
4497     case FOURCC_PICT:
4498     case FOURCC_pnot:
4499     {
4500       GST_LOG_OBJECT (qtdemux,
4501           "skipping atom '%" GST_FOURCC_FORMAT "' at %" G_GUINT64_FORMAT,
4502           GST_FOURCC_ARGS (fourcc), cur_offset);
4503       qtdemux->offset = add_offset (qtdemux->offset, length);
4504       break;
4505     }
4506     case FOURCC_moov:
4507     {
4508       GstBuffer *moov = NULL;
4509
4510       if (qtdemux->got_moov) {
4511         GST_DEBUG_OBJECT (qtdemux, "Skipping moov atom as we have one already");
4512         qtdemux->offset = add_offset (qtdemux->offset, length);
4513         goto beach;
4514       }
4515
4516       ret = gst_pad_pull_range (qtdemux->sinkpad, cur_offset, length, &moov);
4517       if (ret != GST_FLOW_OK)
4518         goto beach;
4519       gst_buffer_map (moov, &map, GST_MAP_READ);
4520
4521       if (length != map.size) {
4522         /* Some files have a 'moov' atom at the end of the file which contains
4523          * a terminal 'free' atom where the body of the atom is missing.
4524          * Check for, and permit, this special case.
4525          */
4526         if (map.size >= 8) {
4527           guint8 *final_data = map.data + (map.size - 8);
4528           guint32 final_length = QT_UINT32 (final_data);
4529           guint32 final_fourcc = QT_FOURCC (final_data + 4);
4530
4531           if (final_fourcc == FOURCC_free
4532               && map.size + final_length - 8 == length) {
4533             /* Ok, we've found that special case. Allocate a new buffer with
4534              * that free atom actually present. */
4535             GstBuffer *newmoov = gst_buffer_new_and_alloc (length);
4536             gst_buffer_fill (newmoov, 0, map.data, map.size);
4537             gst_buffer_memset (newmoov, map.size, 0, final_length - 8);
4538             gst_buffer_unmap (moov, &map);
4539             gst_buffer_unref (moov);
4540             moov = newmoov;
4541             gst_buffer_map (moov, &map, GST_MAP_READ);
4542           }
4543         }
4544       }
4545
4546       if (length != map.size) {
4547         GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
4548             (_("This file is incomplete and cannot be played.")),
4549             ("We got less than expected (received %" G_GSIZE_FORMAT
4550                 ", wanted %u, offset %" G_GUINT64_FORMAT ")", map.size,
4551                 (guint) length, cur_offset));
4552         gst_buffer_unmap (moov, &map);
4553         gst_buffer_unref (moov);
4554         ret = GST_FLOW_ERROR;
4555         goto beach;
4556       }
4557       qtdemux->offset += length;
4558
4559       qtdemux_parse_moov (qtdemux, map.data, length);
4560       qtdemux_node_dump (qtdemux, qtdemux->moov_node);
4561
4562       qtdemux_parse_tree (qtdemux);
4563       if (qtdemux->moov_node_compressed) {
4564         g_node_destroy (qtdemux->moov_node_compressed);
4565         g_free (qtdemux->moov_node->data);
4566       }
4567       qtdemux->moov_node_compressed = NULL;
4568       g_node_destroy (qtdemux->moov_node);
4569       qtdemux->moov_node = NULL;
4570       gst_buffer_unmap (moov, &map);
4571       gst_buffer_unref (moov);
4572       qtdemux->got_moov = TRUE;
4573
4574       break;
4575     }
4576     case FOURCC_ftyp:
4577     {
4578       GstBuffer *ftyp = NULL;
4579
4580       /* extract major brand; might come in handy for ISO vs QT issues */
4581       ret = gst_qtdemux_pull_atom (qtdemux, cur_offset, length, &ftyp);
4582       if (ret != GST_FLOW_OK)
4583         goto beach;
4584       qtdemux->offset += length;
4585       gst_buffer_map (ftyp, &map, GST_MAP_READ);
4586       qtdemux_parse_ftyp (qtdemux, map.data, map.size);
4587       gst_buffer_unmap (ftyp, &map);
4588       gst_buffer_unref (ftyp);
4589       break;
4590     }
4591     case FOURCC_uuid:
4592     {
4593       GstBuffer *uuid = NULL;
4594
4595       /* uuid are extension atoms */
4596       ret = gst_qtdemux_pull_atom (qtdemux, cur_offset, length, &uuid);
4597       if (ret != GST_FLOW_OK)
4598         goto beach;
4599       qtdemux->offset += length;
4600       gst_buffer_map (uuid, &map, GST_MAP_READ);
4601       qtdemux_parse_uuid (qtdemux, map.data, map.size);
4602       gst_buffer_unmap (uuid, &map);
4603       gst_buffer_unref (uuid);
4604       break;
4605     }
4606     case FOURCC_sidx:
4607     {
4608       GstBuffer *sidx = NULL;
4609       ret = gst_qtdemux_pull_atom (qtdemux, cur_offset, length, &sidx);
4610       if (ret != GST_FLOW_OK)
4611         goto beach;
4612       qtdemux->offset += length;
4613       gst_buffer_map (sidx, &map, GST_MAP_READ);
4614       qtdemux_parse_sidx (qtdemux, map.data, map.size);
4615       gst_buffer_unmap (sidx, &map);
4616       gst_buffer_unref (sidx);
4617       break;
4618     }
4619     default:
4620     {
4621       GstBuffer *unknown = NULL;
4622
4623       GST_LOG_OBJECT (qtdemux,
4624           "unknown %08x '%" GST_FOURCC_FORMAT "' of size %" G_GUINT64_FORMAT
4625           " at %" G_GUINT64_FORMAT, fourcc, GST_FOURCC_ARGS (fourcc), length,
4626           cur_offset);
4627       ret = gst_qtdemux_pull_atom (qtdemux, cur_offset, length, &unknown);
4628       if (ret != GST_FLOW_OK)
4629         goto beach;
4630       gst_buffer_map (unknown, &map, GST_MAP_READ);
4631       GST_MEMDUMP ("Unknown tag", map.data, map.size);
4632       gst_buffer_unmap (unknown, &map);
4633       gst_buffer_unref (unknown);
4634       qtdemux->offset += length;
4635       break;
4636     }
4637   }
4638
4639 beach:
4640   if (ret == GST_FLOW_EOS && (qtdemux->got_moov || qtdemux->media_caps)) {
4641     /* digested all data, show what we have */
4642     qtdemux_prepare_streams (qtdemux);
4643     QTDEMUX_EXPOSE_LOCK (qtdemux);
4644     ret = qtdemux_expose_streams (qtdemux);
4645     QTDEMUX_EXPOSE_UNLOCK (qtdemux);
4646
4647     qtdemux->state = QTDEMUX_STATE_MOVIE;
4648     GST_DEBUG_OBJECT (qtdemux, "switching state to STATE_MOVIE (%d)",
4649         qtdemux->state);
4650     return ret;
4651   }
4652   return ret;
4653 }
4654
4655 /* Seeks to the previous keyframe of the indexed stream and
4656  * aligns other streams with respect to the keyframe timestamp
4657  * of indexed stream. Only called in case of Reverse Playback
4658  */
4659 static GstFlowReturn
4660 gst_qtdemux_seek_to_previous_keyframe (GstQTDemux * qtdemux)
4661 {
4662   guint32 seg_idx = 0, k_index = 0;
4663   guint32 ref_seg_idx, ref_k_index;
4664   GstClockTime k_pos = 0, last_stop = 0;
4665   QtDemuxSegment *seg = NULL;
4666   QtDemuxStream *ref_str = NULL;
4667   guint64 seg_media_start_mov;  /* segment media start time in mov format */
4668   guint64 target_ts;
4669   GList *iter;
4670
4671   /* Now we choose an arbitrary stream, get the previous keyframe timestamp
4672    * and finally align all the other streams on that timestamp with their
4673    * respective keyframes */
4674   for (iter = qtdemux->active_streams; iter; iter = g_list_next (iter)) {
4675     QtDemuxStream *str = QTDEMUX_STREAM (iter->data);
4676
4677     /* No candidate yet, take the first stream */
4678     if (!ref_str) {
4679       ref_str = str;
4680       continue;
4681     }
4682
4683     /* So that stream has a segment, we prefer video streams */
4684     if (str->subtype == FOURCC_vide) {
4685       ref_str = str;
4686       break;
4687     }
4688   }
4689
4690   if (G_UNLIKELY (!ref_str)) {
4691     GST_DEBUG_OBJECT (qtdemux, "couldn't find any stream");
4692     goto eos;
4693   }
4694
4695   if (G_UNLIKELY (!ref_str->from_sample)) {
4696     GST_DEBUG_OBJECT (qtdemux, "reached the beginning of the file");
4697     goto eos;
4698   }
4699
4700   /* So that stream has been playing from from_sample to to_sample. We will
4701    * get the timestamp of the previous sample and search for a keyframe before
4702    * that. For audio streams we do an arbitrary jump in the past (10 samples) */
4703   if (ref_str->subtype == FOURCC_vide) {
4704     k_index = gst_qtdemux_find_keyframe (qtdemux, ref_str,
4705         ref_str->from_sample - 1, FALSE);
4706   } else {
4707     if (ref_str->from_sample >= 10)
4708       k_index = ref_str->from_sample - 10;
4709     else
4710       k_index = 0;
4711   }
4712
4713   target_ts =
4714       ref_str->samples[k_index].timestamp +
4715       ref_str->samples[k_index].pts_offset;
4716
4717   /* get current segment for that stream */
4718   seg = &ref_str->segments[ref_str->segment_index];
4719   /* Use segment start in original timescale for comparisons */
4720   seg_media_start_mov = seg->trak_media_start;
4721
4722   GST_LOG_OBJECT (qtdemux, "keyframe index %u ts %" G_GUINT64_FORMAT
4723       " seg start %" G_GUINT64_FORMAT " %" GST_TIME_FORMAT "\n",
4724       k_index, target_ts, seg_media_start_mov,
4725       GST_TIME_ARGS (seg->media_start));
4726
4727   /* Crawl back through segments to find the one containing this I frame */
4728   while (target_ts < seg_media_start_mov) {
4729     GST_DEBUG_OBJECT (qtdemux,
4730         "keyframe position (sample %u) is out of segment %u " " target %"
4731         G_GUINT64_FORMAT " seg start %" G_GUINT64_FORMAT, k_index,
4732         ref_str->segment_index, target_ts, seg_media_start_mov);
4733
4734     if (G_UNLIKELY (!ref_str->segment_index)) {
4735       /* Reached first segment, let's consider it's EOS */
4736       goto eos;
4737     }
4738     ref_str->segment_index--;
4739     seg = &ref_str->segments[ref_str->segment_index];
4740     /* Use segment start in original timescale for comparisons */
4741     seg_media_start_mov = seg->trak_media_start;
4742   }
4743   /* Calculate time position of the keyframe and where we should stop */
4744   k_pos =
4745       QTSTREAMTIME_TO_GSTTIME (ref_str,
4746       target_ts - seg->trak_media_start) + seg->time;
4747   last_stop =
4748       QTSTREAMTIME_TO_GSTTIME (ref_str,
4749       ref_str->samples[ref_str->from_sample].timestamp -
4750       seg->trak_media_start) + seg->time;
4751
4752   GST_DEBUG_OBJECT (qtdemux, "preferred stream played from sample %u, "
4753       "now going to sample %u (pts %" GST_TIME_FORMAT ")", ref_str->from_sample,
4754       k_index, GST_TIME_ARGS (k_pos));
4755
4756   /* Set last_stop with the keyframe timestamp we pushed of that stream */
4757   qtdemux->segment.position = last_stop;
4758   GST_DEBUG_OBJECT (qtdemux, "last_stop now is %" GST_TIME_FORMAT,
4759       GST_TIME_ARGS (last_stop));
4760
4761   if (G_UNLIKELY (last_stop < qtdemux->segment.start)) {
4762     GST_DEBUG_OBJECT (qtdemux, "reached the beginning of segment");
4763     goto eos;
4764   }
4765
4766   ref_seg_idx = ref_str->segment_index;
4767   ref_k_index = k_index;
4768
4769   /* Align them all on this */
4770   for (iter = qtdemux->active_streams; iter; iter = g_list_next (iter)) {
4771     guint32 index = 0;
4772     GstClockTime seg_time = 0;
4773     QtDemuxStream *str = QTDEMUX_STREAM (iter->data);
4774
4775     /* aligning reference stream again might lead to backing up to yet another
4776      * keyframe (due to timestamp rounding issues),
4777      * potentially putting more load on downstream; so let's try to avoid */
4778     if (str == ref_str) {
4779       seg_idx = ref_seg_idx;
4780       seg = &str->segments[seg_idx];
4781       k_index = ref_k_index;
4782       GST_DEBUG_OBJECT (qtdemux, "reference track-id %u segment %d, "
4783           "sample at index %d", str->track_id, ref_str->segment_index, k_index);
4784     } else {
4785       seg_idx = gst_qtdemux_find_segment (qtdemux, str, k_pos);
4786       GST_DEBUG_OBJECT (qtdemux,
4787           "track-id %u align segment %d for keyframe pos %" GST_TIME_FORMAT,
4788           str->track_id, seg_idx, GST_TIME_ARGS (k_pos));
4789
4790       /* get segment and time in the segment */
4791       seg = &str->segments[seg_idx];
4792       seg_time = k_pos - seg->time;
4793
4794       /* get the media time in the segment.
4795        * No adjustment for empty "filler" segments */
4796       if (seg->media_start != GST_CLOCK_TIME_NONE)
4797         seg_time += seg->media_start;
4798
4799       /* get the index of the sample with media time */
4800       index = gst_qtdemux_find_index_linear (qtdemux, str, seg_time);
4801       GST_DEBUG_OBJECT (qtdemux,
4802           "track-id %u sample for %" GST_TIME_FORMAT " at %u", str->track_id,
4803           GST_TIME_ARGS (seg_time), index);
4804
4805       /* find previous keyframe */
4806       k_index = gst_qtdemux_find_keyframe (qtdemux, str, index, FALSE);
4807     }
4808
4809     /* Remember until where we want to go */
4810     str->to_sample = str->from_sample - 1;
4811     /* Define our time position */
4812     target_ts =
4813         str->samples[k_index].timestamp + str->samples[k_index].pts_offset;
4814     str->time_position = QTSTREAMTIME_TO_GSTTIME (str, target_ts) + seg->time;
4815     if (seg->media_start != GST_CLOCK_TIME_NONE)
4816       str->time_position -= seg->media_start;
4817
4818     /* Now seek back in time */
4819     gst_qtdemux_move_stream (qtdemux, str, k_index);
4820     GST_DEBUG_OBJECT (qtdemux, "track-id %u keyframe at %u, time position %"
4821         GST_TIME_FORMAT " playing from sample %u to %u", str->track_id, k_index,
4822         GST_TIME_ARGS (str->time_position), str->from_sample, str->to_sample);
4823   }
4824
4825   return GST_FLOW_OK;
4826
4827 eos:
4828   return GST_FLOW_EOS;
4829 }
4830
4831 /*
4832  * Gets the current qt segment start, stop and position for the
4833  * given time offset. This is used in update_segment()
4834  */
4835 static void
4836 gst_qtdemux_stream_segment_get_boundaries (GstQTDemux * qtdemux,
4837     QtDemuxStream * stream, GstClockTime offset,
4838     GstClockTime * _start, GstClockTime * _stop, GstClockTime * _time)
4839 {
4840   GstClockTime seg_time;
4841   GstClockTime start, stop, time;
4842   QtDemuxSegment *segment;
4843
4844   segment = &stream->segments[stream->segment_index];
4845
4846   /* get time in this segment */
4847   seg_time = (offset - segment->time) * segment->rate;
4848
4849   GST_LOG_OBJECT (stream->pad, "seg_time %" GST_TIME_FORMAT,
4850       GST_TIME_ARGS (seg_time));
4851
4852   if (G_UNLIKELY (seg_time > segment->duration)) {
4853     GST_LOG_OBJECT (stream->pad,
4854         "seg_time > segment->duration %" GST_TIME_FORMAT,
4855         GST_TIME_ARGS (segment->duration));
4856     seg_time = segment->duration;
4857   }
4858
4859   /* qtdemux->segment.stop is in outside-time-realm, whereas
4860    * segment->media_stop is in track-time-realm.
4861    *
4862    * In order to compare the two, we need to bring segment.stop
4863    * into the track-time-realm
4864    *
4865    * FIXME - does this comment still hold? Don't see any conversion here */
4866
4867   stop = qtdemux->segment.stop;
4868   if (stop == GST_CLOCK_TIME_NONE)
4869     stop = qtdemux->segment.duration;
4870   if (stop == GST_CLOCK_TIME_NONE)
4871     stop = segment->media_stop;
4872   else
4873     stop =
4874         MIN (segment->media_stop, stop - segment->time + segment->media_start);
4875
4876   if (G_UNLIKELY (QTSEGMENT_IS_EMPTY (segment))) {
4877     start = segment->time + seg_time;
4878     time = offset;
4879     stop = start - seg_time + segment->duration;
4880   } else if (qtdemux->segment.rate >= 0) {
4881     start = MIN (segment->media_start + seg_time, stop);
4882     time = offset;
4883   } else {
4884     if (segment->media_start >= qtdemux->segment.start) {
4885       time = segment->time;
4886     } else {
4887       time = segment->time + (qtdemux->segment.start - segment->media_start);
4888     }
4889
4890     start = MAX (segment->media_start, qtdemux->segment.start);
4891     stop = MIN (segment->media_start + seg_time, stop);
4892   }
4893
4894   *_start = start;
4895   *_stop = stop;
4896   *_time = time;
4897 }
4898
4899 /*
4900  * Updates the qt segment used for the stream and pushes a new segment event
4901  * downstream on this stream's pad.
4902  */
4903 static gboolean
4904 gst_qtdemux_stream_update_segment (GstQTDemux * qtdemux, QtDemuxStream * stream,
4905     gint seg_idx, GstClockTime offset, GstClockTime * _start,
4906     GstClockTime * _stop)
4907 {
4908   QtDemuxSegment *segment;
4909   GstClockTime start = 0, stop = GST_CLOCK_TIME_NONE, time = 0;
4910   gdouble rate;
4911   GstEvent *event;
4912
4913   /* update the current segment */
4914   stream->segment_index = seg_idx;
4915
4916   /* get the segment */
4917   segment = &stream->segments[seg_idx];
4918
4919   if (G_UNLIKELY (offset < segment->time)) {
4920     GST_WARNING_OBJECT (stream->pad, "offset < segment->time %" GST_TIME_FORMAT,
4921         GST_TIME_ARGS (segment->time));
4922     return FALSE;
4923   }
4924
4925   /* segment lies beyond total indicated duration */
4926   if (G_UNLIKELY (qtdemux->segment.duration != GST_CLOCK_TIME_NONE &&
4927           segment->time > qtdemux->segment.duration)) {
4928     GST_WARNING_OBJECT (stream->pad, "file duration %" GST_TIME_FORMAT
4929         " < segment->time %" GST_TIME_FORMAT,
4930         GST_TIME_ARGS (qtdemux->segment.duration),
4931         GST_TIME_ARGS (segment->time));
4932     return FALSE;
4933   }
4934
4935   gst_qtdemux_stream_segment_get_boundaries (qtdemux, stream, offset,
4936       &start, &stop, &time);
4937
4938   GST_DEBUG_OBJECT (stream->pad, "new segment %d from %" GST_TIME_FORMAT
4939       " to %" GST_TIME_FORMAT ", time %" GST_TIME_FORMAT, seg_idx,
4940       GST_TIME_ARGS (start), GST_TIME_ARGS (stop), GST_TIME_ARGS (time));
4941
4942   /* combine global rate with that of the segment */
4943   rate = segment->rate * qtdemux->segment.rate;
4944
4945   /* Copy flags from main segment */
4946   stream->segment.flags = qtdemux->segment.flags;
4947
4948   /* update the segment values used for clipping */
4949   stream->segment.offset = qtdemux->segment.offset;
4950   stream->segment.base = qtdemux->segment.base + stream->accumulated_base;
4951   stream->segment.applied_rate = qtdemux->segment.applied_rate;
4952   stream->segment.rate = rate;
4953   stream->segment.start = start + QTSTREAMTIME_TO_GSTTIME (stream,
4954       stream->cslg_shift);
4955   stream->segment.stop = stop + QTSTREAMTIME_TO_GSTTIME (stream,
4956       stream->cslg_shift);
4957   stream->segment.time = time;
4958   stream->segment.position = stream->segment.start;
4959
4960   GST_DEBUG_OBJECT (stream->pad, "New segment: %" GST_SEGMENT_FORMAT,
4961       &stream->segment);
4962
4963   /* now prepare and send the segment */
4964   if (stream->pad) {
4965     event = gst_event_new_segment (&stream->segment);
4966     if (qtdemux->segment_seqnum != GST_SEQNUM_INVALID) {
4967       gst_event_set_seqnum (event, qtdemux->segment_seqnum);
4968     }
4969     gst_pad_push_event (stream->pad, event);
4970     /* assume we can send more data now */
4971     GST_PAD_LAST_FLOW_RETURN (stream->pad) = GST_FLOW_OK;
4972     /* clear to send tags on this pad now */
4973     gst_qtdemux_push_tags (qtdemux, stream);
4974   }
4975
4976   if (_start)
4977     *_start = start;
4978   if (_stop)
4979     *_stop = stop;
4980
4981   return TRUE;
4982 }
4983
4984 /* activate the given segment number @seg_idx of @stream at time @offset.
4985  * @offset is an absolute global position over all the segments.
4986  *
4987  * This will push out a NEWSEGMENT event with the right values and
4988  * position the stream index to the first decodable sample before
4989  * @offset.
4990  */
4991 static gboolean
4992 gst_qtdemux_activate_segment (GstQTDemux * qtdemux, QtDemuxStream * stream,
4993     guint32 seg_idx, GstClockTime offset)
4994 {
4995   QtDemuxSegment *segment;
4996   guint32 index, kf_index;
4997   GstClockTime start = 0, stop = GST_CLOCK_TIME_NONE;
4998
4999   GST_LOG_OBJECT (stream->pad, "activate segment %d, offset %" GST_TIME_FORMAT,
5000       seg_idx, GST_TIME_ARGS (offset));
5001
5002   if (!gst_qtdemux_stream_update_segment (qtdemux, stream, seg_idx, offset,
5003           &start, &stop))
5004     return FALSE;
5005
5006   segment = &stream->segments[stream->segment_index];
5007
5008   /* in the fragmented case, we pick a fragment that starts before our
5009    * desired position and rely on downstream to wait for a keyframe
5010    * (FIXME: doesn't seem to work so well with ismv and wmv, as no parser; the
5011    * tfra entries tells us which trun/sample the key unit is in, but we don't
5012    * make use of this additional information at the moment) */
5013   if (qtdemux->fragmented && !qtdemux->fragmented_seek_pending) {
5014     stream->to_sample = G_MAXUINT32;
5015     return TRUE;
5016   } else {
5017     /* well, it will be taken care of below */
5018     qtdemux->fragmented_seek_pending = FALSE;
5019     /* FIXME ideally the do_fragmented_seek can be done right here,
5020      * rather than at loop level
5021      * (which might even allow handling edit lists in a fragmented file) */
5022   }
5023
5024   /* We don't need to look for a sample in push-based */
5025   if (!qtdemux->pullbased)
5026     return TRUE;
5027
5028   /* and move to the keyframe before the indicated media time of the
5029    * segment */
5030   if (G_LIKELY (!QTSEGMENT_IS_EMPTY (segment))) {
5031     if (qtdemux->segment.rate >= 0) {
5032       index = gst_qtdemux_find_index_linear (qtdemux, stream, start);
5033       stream->to_sample = G_MAXUINT32;
5034       GST_DEBUG_OBJECT (stream->pad,
5035           "moving data pointer to %" GST_TIME_FORMAT ", index: %u, pts %"
5036           GST_TIME_FORMAT, GST_TIME_ARGS (start), index,
5037           GST_TIME_ARGS (QTSAMPLE_PTS (stream, &stream->samples[index])));
5038     } else {
5039       index = gst_qtdemux_find_index_linear (qtdemux, stream, stop);
5040       stream->to_sample = index;
5041       GST_DEBUG_OBJECT (stream->pad,
5042           "moving data pointer to %" GST_TIME_FORMAT ", index: %u, pts %"
5043           GST_TIME_FORMAT, GST_TIME_ARGS (stop), index,
5044           GST_TIME_ARGS (QTSAMPLE_PTS (stream, &stream->samples[index])));
5045     }
5046   } else {
5047     GST_DEBUG_OBJECT (stream->pad, "No need to look for keyframe, "
5048         "this is an empty segment");
5049     return TRUE;
5050   }
5051
5052   /* gst_qtdemux_parse_sample () called from gst_qtdemux_find_index_linear ()
5053    * encountered an error and printed a message so we return appropriately */
5054   if (index == -1)
5055     return FALSE;
5056
5057   /* we're at the right spot */
5058   if (index == stream->sample_index) {
5059     GST_DEBUG_OBJECT (stream->pad, "we are at the right index");
5060     return TRUE;
5061   }
5062
5063   /* find keyframe of the target index */
5064   kf_index = gst_qtdemux_find_keyframe (qtdemux, stream, index, FALSE);
5065
5066 /* *INDENT-OFF* */
5067 /* indent does stupid stuff with stream->samples[].timestamp */
5068
5069   /* if we move forwards, we don't have to go back to the previous
5070    * keyframe since we already sent that. We can also just jump to
5071    * the keyframe right before the target index if there is one. */
5072   if (index > stream->sample_index) {
5073     /* moving forwards check if we move past a keyframe */
5074     if (kf_index > stream->sample_index) {
5075       GST_DEBUG_OBJECT (stream->pad,
5076            "moving forwards to keyframe at %u (pts %" GST_TIME_FORMAT " dts %"GST_TIME_FORMAT" )", kf_index,
5077            GST_TIME_ARGS (QTSAMPLE_PTS(stream, &stream->samples[kf_index])),
5078            GST_TIME_ARGS (QTSAMPLE_DTS(stream, &stream->samples[kf_index])));
5079       gst_qtdemux_move_stream (qtdemux, stream, kf_index);
5080     } else {
5081       GST_DEBUG_OBJECT (stream->pad,
5082           "moving forwards, keyframe at %u (pts %" GST_TIME_FORMAT " dts %"GST_TIME_FORMAT" ) already sent", kf_index,
5083           GST_TIME_ARGS (QTSAMPLE_PTS (stream, &stream->samples[kf_index])),
5084           GST_TIME_ARGS (QTSAMPLE_DTS (stream, &stream->samples[kf_index])));
5085     }
5086   } else {
5087     GST_DEBUG_OBJECT (stream->pad,
5088         "moving backwards to keyframe at %u (pts %" GST_TIME_FORMAT " dts %"GST_TIME_FORMAT" )", kf_index,
5089         GST_TIME_ARGS (QTSAMPLE_PTS(stream, &stream->samples[kf_index])),
5090         GST_TIME_ARGS (QTSAMPLE_DTS(stream, &stream->samples[kf_index])));
5091     gst_qtdemux_move_stream (qtdemux, stream, kf_index);
5092   }
5093
5094 /* *INDENT-ON* */
5095
5096   return TRUE;
5097 }
5098
5099 /* prepare to get the current sample of @stream, getting essential values.
5100  *
5101  * This function will also prepare and send the segment when needed.
5102  *
5103  * Return FALSE if the stream is EOS.
5104  *
5105  * PULL-BASED
5106  */
5107 static gboolean
5108 gst_qtdemux_prepare_current_sample (GstQTDemux * qtdemux,
5109     QtDemuxStream * stream, gboolean * empty, guint64 * offset, guint * size,
5110     GstClockTime * dts, GstClockTime * pts, GstClockTime * duration,
5111     gboolean * keyframe)
5112 {
5113   QtDemuxSample *sample;
5114   GstClockTime time_position;
5115   guint32 seg_idx;
5116
5117   g_return_val_if_fail (stream != NULL, FALSE);
5118
5119   time_position = stream->time_position;
5120   if (G_UNLIKELY (time_position == GST_CLOCK_TIME_NONE))
5121     goto eos;
5122
5123   seg_idx = stream->segment_index;
5124   if (G_UNLIKELY (seg_idx == -1)) {
5125     /* find segment corresponding to time_position if we are looking
5126      * for a segment. */
5127     seg_idx = gst_qtdemux_find_segment (qtdemux, stream, time_position);
5128   }
5129
5130   /* different segment, activate it, sample_index will be set. */
5131   if (G_UNLIKELY (stream->segment_index != seg_idx))
5132     gst_qtdemux_activate_segment (qtdemux, stream, seg_idx, time_position);
5133
5134   if (G_UNLIKELY (QTSEGMENT_IS_EMPTY (&stream->segments[stream->
5135                   segment_index]))) {
5136     QtDemuxSegment *seg = &stream->segments[stream->segment_index];
5137
5138     GST_LOG_OBJECT (qtdemux, "Empty segment activated,"
5139         " prepare empty sample");
5140
5141     *empty = TRUE;
5142     *pts = *dts = time_position;
5143     *duration = seg->duration - (time_position - seg->time);
5144
5145     return TRUE;
5146   }
5147
5148   *empty = FALSE;
5149
5150   if (stream->sample_index == -1)
5151     stream->sample_index = 0;
5152
5153   GST_LOG_OBJECT (qtdemux, "segment active, index = %u of %u",
5154       stream->sample_index, stream->n_samples);
5155
5156   if (G_UNLIKELY (stream->sample_index >= stream->n_samples)) {
5157     if (!qtdemux->fragmented)
5158       goto eos;
5159
5160     GST_INFO_OBJECT (qtdemux, "out of samples, trying to add more");
5161     do {
5162       GstFlowReturn flow;
5163
5164       GST_OBJECT_LOCK (qtdemux);
5165       flow = qtdemux_add_fragmented_samples (qtdemux);
5166       GST_OBJECT_UNLOCK (qtdemux);
5167
5168       if (flow != GST_FLOW_OK)
5169         goto eos;
5170     }
5171     while (stream->sample_index >= stream->n_samples);
5172   }
5173
5174   if (!qtdemux_parse_samples (qtdemux, stream, stream->sample_index)) {
5175     GST_LOG_OBJECT (qtdemux, "Parsing of index %u failed!",
5176         stream->sample_index);
5177     return FALSE;
5178   }
5179
5180   /* now get the info for the sample we're at */
5181   sample = &stream->samples[stream->sample_index];
5182
5183   *dts = QTSAMPLE_DTS (stream, sample);
5184   *pts = QTSAMPLE_PTS (stream, sample);
5185   *offset = sample->offset;
5186   *size = sample->size;
5187   *duration = QTSAMPLE_DUR_DTS (stream, sample, *dts);
5188   *keyframe = QTSAMPLE_KEYFRAME (stream, sample);
5189
5190   return TRUE;
5191
5192   /* special cases */
5193 eos:
5194   {
5195     stream->time_position = GST_CLOCK_TIME_NONE;
5196     return FALSE;
5197   }
5198 }
5199
5200 /* move to the next sample in @stream.
5201  *
5202  * Moves to the next segment when needed.
5203  */
5204 static void
5205 gst_qtdemux_advance_sample (GstQTDemux * qtdemux, QtDemuxStream * stream)
5206 {
5207   QtDemuxSample *sample;
5208   QtDemuxSegment *segment;
5209
5210   /* get current segment */
5211   segment = &stream->segments[stream->segment_index];
5212
5213   if (G_UNLIKELY (QTSEGMENT_IS_EMPTY (segment))) {
5214     GST_DEBUG_OBJECT (qtdemux, "Empty segment, no samples to advance");
5215     goto next_segment;
5216   }
5217
5218   if (G_UNLIKELY (stream->sample_index >= stream->to_sample)) {
5219     /* Mark the stream as EOS */
5220     GST_DEBUG_OBJECT (qtdemux,
5221         "reached max allowed sample %u, mark EOS", stream->to_sample);
5222     stream->time_position = GST_CLOCK_TIME_NONE;
5223     return;
5224   }
5225
5226   /* move to next sample */
5227   stream->sample_index++;
5228   stream->offset_in_sample = 0;
5229
5230   /* reached the last sample, we need the next segment */
5231   if (G_UNLIKELY (stream->sample_index >= stream->n_samples))
5232     goto next_segment;
5233
5234   if (!qtdemux_parse_samples (qtdemux, stream, stream->sample_index)) {
5235     GST_LOG_OBJECT (qtdemux, "Parsing of index %u failed!",
5236         stream->sample_index);
5237     return;
5238   }
5239
5240   /* get next sample */
5241   sample = &stream->samples[stream->sample_index];
5242
5243   /* see if we are past the segment */
5244   if (G_UNLIKELY (QTSAMPLE_DTS (stream, sample) >= segment->media_stop))
5245     goto next_segment;
5246
5247   if (QTSAMPLE_DTS (stream, sample) >= segment->media_start) {
5248     /* inside the segment, update time_position, looks very familiar to
5249      * GStreamer segments, doesn't it? */
5250     stream->time_position =
5251         QTSAMPLE_DTS (stream, sample) - segment->media_start + segment->time;
5252   } else {
5253     /* not yet in segment, time does not yet increment. This means
5254      * that we are still prerolling keyframes to the decoder so it can
5255      * decode the first sample of the segment. */
5256     stream->time_position = segment->time;
5257   }
5258   return;
5259
5260   /* move to the next segment */
5261 next_segment:
5262   {
5263     GST_DEBUG_OBJECT (qtdemux, "segment %d ended ", stream->segment_index);
5264
5265     if (stream->segment_index == stream->n_segments - 1) {
5266       /* are we at the end of the last segment, we're EOS */
5267       stream->time_position = GST_CLOCK_TIME_NONE;
5268     } else {
5269       /* else we're only at the end of the current segment */
5270       stream->time_position = segment->stop_time;
5271     }
5272     /* make sure we select a new segment */
5273
5274     /* accumulate previous segments */
5275     if (GST_CLOCK_TIME_IS_VALID (stream->segment.stop))
5276       stream->accumulated_base +=
5277           (stream->segment.stop -
5278           stream->segment.start) / ABS (stream->segment.rate);
5279
5280     stream->segment_index = -1;
5281   }
5282 }
5283
5284 static void
5285 gst_qtdemux_sync_streams (GstQTDemux * demux)
5286 {
5287   GList *iter;
5288
5289   if (demux->n_streams <= 1)
5290     return;
5291
5292   for (iter = demux->active_streams; iter; iter = g_list_next (iter)) {
5293     QtDemuxStream *stream;
5294     GstClockTime end_time;
5295
5296     stream = QTDEMUX_STREAM (iter->data);
5297
5298     if (!stream->pad)
5299       continue;
5300
5301     /* TODO advance time on subtitle streams here, if any some day */
5302
5303     /* some clips/trailers may have unbalanced streams at the end,
5304      * so send EOS on shorter stream to prevent stalling others */
5305
5306     /* do not mess with EOS if SEGMENT seeking */
5307     if (demux->segment.flags & GST_SEEK_FLAG_SEGMENT)
5308       continue;
5309
5310     if (demux->pullbased) {
5311       /* loop mode is sample time based */
5312       if (!STREAM_IS_EOS (stream))
5313         continue;
5314     } else {
5315       /* push mode is byte position based */
5316       if (stream->n_samples &&
5317           stream->samples[stream->n_samples - 1].offset >= demux->offset)
5318         continue;
5319     }
5320
5321     if (stream->sent_eos)
5322       continue;
5323
5324     /* only act if some gap */
5325     end_time = stream->segments[stream->n_segments - 1].stop_time;
5326     GST_LOG_OBJECT (demux, "current position: %" GST_TIME_FORMAT
5327         ", stream end: %" GST_TIME_FORMAT,
5328         GST_TIME_ARGS (demux->segment.position), GST_TIME_ARGS (end_time));
5329     if (GST_CLOCK_TIME_IS_VALID (end_time)
5330         && (end_time + 2 * GST_SECOND < demux->segment.position)) {
5331       GstEvent *event;
5332
5333       GST_DEBUG_OBJECT (demux, "sending EOS for stream %s",
5334           GST_PAD_NAME (stream->pad));
5335       stream->sent_eos = TRUE;
5336       event = gst_event_new_eos ();
5337       if (demux->segment_seqnum != GST_SEQNUM_INVALID)
5338         gst_event_set_seqnum (event, demux->segment_seqnum);
5339       gst_pad_push_event (stream->pad, event);
5340     }
5341   }
5342 }
5343
5344 /* EOS and NOT_LINKED need to be combined. This means that we return:
5345  *
5346  *  GST_FLOW_NOT_LINKED: when all pads NOT_LINKED.
5347  *  GST_FLOW_EOS: when all pads EOS or NOT_LINKED.
5348  */
5349 static GstFlowReturn
5350 gst_qtdemux_combine_flows (GstQTDemux * demux, QtDemuxStream * stream,
5351     GstFlowReturn ret)
5352 {
5353   GST_LOG_OBJECT (demux, "flow return: %s", gst_flow_get_name (ret));
5354
5355   if (stream->pad)
5356     ret = gst_flow_combiner_update_pad_flow (demux->flowcombiner, stream->pad,
5357         ret);
5358   else
5359     ret = gst_flow_combiner_update_flow (demux->flowcombiner, ret);
5360
5361   GST_LOG_OBJECT (demux, "combined flow return: %s", gst_flow_get_name (ret));
5362   return ret;
5363 }
5364
5365 /* the input buffer metadata must be writable. Returns NULL when the buffer is
5366  * completely clipped
5367  *
5368  * Should be used only with raw buffers */
5369 static GstBuffer *
5370 gst_qtdemux_clip_buffer (GstQTDemux * qtdemux, QtDemuxStream * stream,
5371     GstBuffer * buf)
5372 {
5373   guint64 start, stop, cstart, cstop, diff;
5374   GstClockTime pts, duration;
5375   gsize size, osize;
5376   gint num_rate, denom_rate;
5377   gint frame_size;
5378   gboolean clip_data;
5379   guint offset;
5380
5381   osize = size = gst_buffer_get_size (buf);
5382   offset = 0;
5383
5384   /* depending on the type, setup the clip parameters */
5385   if (stream->subtype == FOURCC_soun) {
5386     frame_size = CUR_STREAM (stream)->bytes_per_frame;
5387     num_rate = GST_SECOND;
5388     denom_rate = (gint) CUR_STREAM (stream)->rate;
5389     clip_data = TRUE;
5390   } else if (stream->subtype == FOURCC_vide) {
5391     frame_size = size;
5392     num_rate = CUR_STREAM (stream)->fps_n;
5393     denom_rate = CUR_STREAM (stream)->fps_d;
5394     clip_data = FALSE;
5395   } else
5396     goto wrong_type;
5397
5398   if (frame_size <= 0)
5399     goto bad_frame_size;
5400
5401   /* we can only clip if we have a valid pts */
5402   pts = GST_BUFFER_PTS (buf);
5403   if (G_UNLIKELY (!GST_CLOCK_TIME_IS_VALID (pts)))
5404     goto no_pts;
5405
5406   duration = GST_BUFFER_DURATION (buf);
5407
5408   if (G_UNLIKELY (!GST_CLOCK_TIME_IS_VALID (duration))) {
5409     duration =
5410         gst_util_uint64_scale_int (size / frame_size, num_rate, denom_rate);
5411   }
5412
5413   start = pts;
5414   stop = start + duration;
5415
5416   if (G_UNLIKELY (!gst_segment_clip (&stream->segment,
5417               GST_FORMAT_TIME, start, stop, &cstart, &cstop)))
5418     goto clipped;
5419
5420   /* see if some clipping happened */
5421   diff = cstart - start;
5422   if (diff > 0) {
5423     pts += diff;
5424     duration -= diff;
5425
5426     if (clip_data) {
5427       /* bring clipped time to samples and to bytes */
5428       diff = gst_util_uint64_scale_int (diff, denom_rate, num_rate);
5429       diff *= frame_size;
5430
5431       GST_DEBUG_OBJECT (qtdemux,
5432           "clipping start to %" GST_TIME_FORMAT " %"
5433           G_GUINT64_FORMAT " bytes", GST_TIME_ARGS (cstart), diff);
5434
5435       offset = diff;
5436       size -= diff;
5437     }
5438   }
5439   diff = stop - cstop;
5440   if (diff > 0) {
5441     duration -= diff;
5442
5443     if (clip_data) {
5444       /* bring clipped time to samples and then to bytes */
5445       diff = gst_util_uint64_scale_int (diff, denom_rate, num_rate);
5446       diff *= frame_size;
5447       GST_DEBUG_OBJECT (qtdemux,
5448           "clipping stop to %" GST_TIME_FORMAT " %" G_GUINT64_FORMAT
5449           " bytes", GST_TIME_ARGS (cstop), diff);
5450       size -= diff;
5451     }
5452   }
5453
5454   if (offset != 0 || size != osize)
5455     gst_buffer_resize (buf, offset, size);
5456
5457   GST_BUFFER_DTS (buf) = GST_CLOCK_TIME_NONE;
5458   GST_BUFFER_PTS (buf) = pts;
5459   GST_BUFFER_DURATION (buf) = duration;
5460
5461   return buf;
5462
5463   /* dropped buffer */
5464 wrong_type:
5465   {
5466     GST_DEBUG_OBJECT (qtdemux, "unknown stream type");
5467     return buf;
5468   }
5469 bad_frame_size:
5470   {
5471     GST_DEBUG_OBJECT (qtdemux, "bad frame size");
5472     return buf;
5473   }
5474 no_pts:
5475   {
5476     GST_DEBUG_OBJECT (qtdemux, "no pts on buffer");
5477     return buf;
5478   }
5479 clipped:
5480   {
5481     GST_DEBUG_OBJECT (qtdemux, "clipped buffer");
5482     gst_buffer_unref (buf);
5483     return NULL;
5484   }
5485 }
5486
5487 static GstBuffer *
5488 gst_qtdemux_align_buffer (GstQTDemux * demux,
5489     GstBuffer * buffer, gsize alignment)
5490 {
5491   GstMapInfo map;
5492
5493   gst_buffer_map (buffer, &map, GST_MAP_READ);
5494
5495   if (map.size < sizeof (guintptr)) {
5496     gst_buffer_unmap (buffer, &map);
5497     return buffer;
5498   }
5499
5500   if (((guintptr) map.data) & (alignment - 1)) {
5501     GstBuffer *new_buffer;
5502     GstAllocationParams params = { 0, alignment - 1, 0, 0, };
5503
5504     new_buffer = gst_buffer_new_allocate (NULL,
5505         gst_buffer_get_size (buffer), &params);
5506
5507     /* Copy data "by hand", so ensure alignment is kept: */
5508     gst_buffer_fill (new_buffer, 0, map.data, map.size);
5509
5510     gst_buffer_copy_into (new_buffer, buffer, GST_BUFFER_COPY_METADATA, 0, -1);
5511     GST_DEBUG_OBJECT (demux,
5512         "We want output aligned on %" G_GSIZE_FORMAT ", reallocated",
5513         alignment);
5514
5515     gst_buffer_unmap (buffer, &map);
5516     gst_buffer_unref (buffer);
5517
5518     return new_buffer;
5519   }
5520
5521   gst_buffer_unmap (buffer, &map);
5522   return buffer;
5523 }
5524
5525 static guint8 *
5526 convert_to_ccdata (const guint8 * ccpair, guint8 ccpair_size, guint field,
5527     gsize * res)
5528 {
5529   guint8 *storage;
5530   gsize i;
5531
5532   /* We are converting from pairs to triplets */
5533   *res = ccpair_size / 2 * 3;
5534   storage = g_malloc (*res);
5535   for (i = 0; i * 2 < ccpair_size; i += 1) {
5536     if (field == 1)
5537       storage[i * 3] = 0xfc;
5538     else
5539       storage[i * 3] = 0xfd;
5540     storage[i * 3 + 1] = ccpair[i * 2];
5541     storage[i * 3 + 2] = ccpair[i * 2 + 1];
5542   }
5543
5544   return storage;
5545 }
5546
5547 static guint8 *
5548 extract_cc_from_data (QtDemuxStream * stream, const guint8 * data, gsize size,
5549     gsize * cclen)
5550 {
5551   guint8 *res = NULL;
5552   guint32 atom_length, fourcc;
5553   QtDemuxStreamStsdEntry *stsd_entry;
5554
5555   GST_MEMDUMP ("caption atom", data, size);
5556
5557   /* There might be multiple atoms */
5558
5559   *cclen = 0;
5560   if (size < 8)
5561     goto invalid_cdat;
5562   atom_length = QT_UINT32 (data);
5563   fourcc = QT_FOURCC (data + 4);
5564   if (G_UNLIKELY (atom_length > size || atom_length == 8))
5565     goto invalid_cdat;
5566
5567   GST_DEBUG_OBJECT (stream->pad, "here");
5568
5569   /* Check if we have somethig compatible */
5570   stsd_entry = CUR_STREAM (stream);
5571   switch (stsd_entry->fourcc) {
5572     case FOURCC_c608:{
5573       guint8 *cdat = NULL, *cdt2 = NULL;
5574       gsize cdat_size = 0, cdt2_size = 0;
5575       /* Should be cdat or cdt2 */
5576       if (fourcc != FOURCC_cdat && fourcc != FOURCC_cdt2) {
5577         GST_WARNING_OBJECT (stream->pad,
5578             "Unknown data atom (%" GST_FOURCC_FORMAT ") for CEA608",
5579             GST_FOURCC_ARGS (fourcc));
5580         goto invalid_cdat;
5581       }
5582
5583       /* Convert to cc_data triplet */
5584       if (fourcc == FOURCC_cdat)
5585         cdat = convert_to_ccdata (data + 8, atom_length - 8, 1, &cdat_size);
5586       else
5587         cdt2 = convert_to_ccdata (data + 8, atom_length - 8, 2, &cdt2_size);
5588       GST_DEBUG_OBJECT (stream->pad, "size:%" G_GSIZE_FORMAT " atom_length:%u",
5589           size, atom_length);
5590
5591       /* Check for another atom ? */
5592       if (size > atom_length + 8) {
5593         guint32 new_atom_length = QT_UINT32 (data + atom_length);
5594         if (size >= atom_length + new_atom_length) {
5595           fourcc = QT_FOURCC (data + atom_length + 4);
5596           if (fourcc == FOURCC_cdat) {
5597             if (cdat == NULL)
5598               cdat =
5599                   convert_to_ccdata (data + atom_length + 8,
5600                   new_atom_length - 8, 1, &cdat_size);
5601             else
5602               GST_WARNING_OBJECT (stream->pad,
5603                   "Got multiple [cdat] atoms in a c608 sample. This is unsupported for now. Please file a bug");
5604           } else {
5605             if (cdt2 == NULL)
5606               cdt2 =
5607                   convert_to_ccdata (data + atom_length + 8,
5608                   new_atom_length - 8, 2, &cdt2_size);
5609             else
5610               GST_WARNING_OBJECT (stream->pad,
5611                   "Got multiple [cdt2] atoms in a c608 sample. This is unsupported for now. Please file a bug");
5612           }
5613         }
5614       }
5615
5616       *cclen = cdat_size + cdt2_size;
5617       res = g_malloc (*cclen);
5618       if (cdat_size)
5619         memcpy (res, cdat, cdat_size);
5620       if (cdt2_size)
5621         memcpy (res + cdat_size, cdt2, cdt2_size);
5622       g_free (cdat);
5623       g_free (cdt2);
5624     }
5625       break;
5626     case FOURCC_c708:
5627       if (fourcc != FOURCC_ccdp) {
5628         GST_WARNING_OBJECT (stream->pad,
5629             "Unknown data atom (%" GST_FOURCC_FORMAT ") for CEA708",
5630             GST_FOURCC_ARGS (fourcc));
5631         goto invalid_cdat;
5632       }
5633       *cclen = atom_length - 8;
5634       res = g_memdup (data + 8, *cclen);
5635       break;
5636     default:
5637       /* Keep this here in case other closed caption formats are added */
5638       g_assert_not_reached ();
5639       break;
5640   }
5641
5642   GST_MEMDUMP ("Output", res, *cclen);
5643   return res;
5644
5645   /* Errors */
5646 invalid_cdat:
5647   GST_WARNING ("[cdat] atom is too small or invalid");
5648   return NULL;
5649 }
5650
5651 /* the input buffer metadata must be writable,
5652  * but time/duration etc not yet set and need not be preserved */
5653 static GstBuffer *
5654 gst_qtdemux_process_buffer (GstQTDemux * qtdemux, QtDemuxStream * stream,
5655     GstBuffer * buf)
5656 {
5657   GstMapInfo map;
5658   guint nsize = 0;
5659   gchar *str;
5660
5661   /* not many cases for now */
5662   if (G_UNLIKELY (CUR_STREAM (stream)->fourcc == FOURCC_mp4s)) {
5663     /* send a one time dvd clut event */
5664     if (stream->pending_event && stream->pad)
5665       gst_pad_push_event (stream->pad, stream->pending_event);
5666     stream->pending_event = NULL;
5667   }
5668
5669   if (G_UNLIKELY (stream->subtype != FOURCC_text
5670           && stream->subtype != FOURCC_sbtl &&
5671           stream->subtype != FOURCC_subp && stream->subtype != FOURCC_clcp)) {
5672     return buf;
5673   }
5674
5675   gst_buffer_map (buf, &map, GST_MAP_READ);
5676
5677   /* empty buffer is sent to terminate previous subtitle */
5678   if (map.size <= 2) {
5679     gst_buffer_unmap (buf, &map);
5680     gst_buffer_unref (buf);
5681     return NULL;
5682   }
5683   if (stream->subtype == FOURCC_subp) {
5684     /* That's all the processing needed for subpictures */
5685     gst_buffer_unmap (buf, &map);
5686     return buf;
5687   }
5688
5689   if (stream->subtype == FOURCC_clcp) {
5690     guint8 *cc;
5691     gsize cclen = 0;
5692     /* For closed caption, we need to extract the information from the
5693      * [cdat],[cdt2] or [ccdp] atom */
5694     cc = extract_cc_from_data (stream, map.data, map.size, &cclen);
5695     gst_buffer_unmap (buf, &map);
5696     gst_buffer_unref (buf);
5697     if (cc) {
5698       buf = _gst_buffer_new_wrapped (cc, cclen, g_free);
5699     } else {
5700       /* Conversion failed or there's nothing */
5701       buf = NULL;
5702     }
5703     return buf;
5704   }
5705
5706   nsize = GST_READ_UINT16_BE (map.data);
5707   nsize = MIN (nsize, map.size - 2);
5708
5709   GST_LOG_OBJECT (qtdemux, "3GPP timed text subtitle: %d/%" G_GSIZE_FORMAT "",
5710       nsize, map.size);
5711
5712   /* takes care of UTF-8 validation or UTF-16 recognition,
5713    * no other encoding expected */
5714   str = gst_tag_freeform_string_to_utf8 ((gchar *) map.data + 2, nsize, NULL);
5715   gst_buffer_unmap (buf, &map);
5716   if (str) {
5717     gst_buffer_unref (buf);
5718     buf = _gst_buffer_new_wrapped (str, strlen (str), g_free);
5719   } else {
5720     /* this should not really happen unless the subtitle is corrupted */
5721     gst_buffer_unref (buf);
5722     buf = NULL;
5723   }
5724
5725   /* FIXME ? convert optional subsequent style info to markup */
5726
5727   return buf;
5728 }
5729
5730 /* Sets a buffer's attributes properly and pushes it downstream.
5731  * Also checks for additional actions and custom processing that may
5732  * need to be done first.
5733  */
5734 static GstFlowReturn
5735 gst_qtdemux_decorate_and_push_buffer (GstQTDemux * qtdemux,
5736     QtDemuxStream * stream, GstBuffer * buf,
5737     GstClockTime dts, GstClockTime pts, GstClockTime duration,
5738     gboolean keyframe, GstClockTime position, guint64 byte_position)
5739 {
5740   GstFlowReturn ret = GST_FLOW_OK;
5741
5742   /* offset the timestamps according to the edit list */
5743
5744   if (G_UNLIKELY (CUR_STREAM (stream)->fourcc == FOURCC_rtsp)) {
5745     gchar *url;
5746     GstMapInfo map;
5747
5748     gst_buffer_map (buf, &map, GST_MAP_READ);
5749     url = g_strndup ((gchar *) map.data, map.size);
5750     gst_buffer_unmap (buf, &map);
5751     if (url != NULL && strlen (url) != 0) {
5752       /* we have RTSP redirect now */
5753       gst_element_post_message (GST_ELEMENT_CAST (qtdemux),
5754           gst_message_new_element (GST_OBJECT_CAST (qtdemux),
5755               gst_structure_new ("redirect",
5756                   "new-location", G_TYPE_STRING, url, NULL)));
5757       qtdemux->posted_redirect = TRUE;
5758     } else {
5759       GST_WARNING_OBJECT (qtdemux, "Redirect URI of stream is empty, not "
5760           "posting");
5761     }
5762     g_free (url);
5763   }
5764
5765   /* position reporting */
5766   if (qtdemux->segment.rate >= 0) {
5767     qtdemux->segment.position = position;
5768     gst_qtdemux_sync_streams (qtdemux);
5769   }
5770
5771   if (G_UNLIKELY (!stream->pad)) {
5772     GST_DEBUG_OBJECT (qtdemux, "No output pad for stream, ignoring");
5773     gst_buffer_unref (buf);
5774     goto exit;
5775   }
5776
5777   /* send out pending buffers */
5778   while (stream->buffers) {
5779     GstBuffer *buffer = (GstBuffer *) stream->buffers->data;
5780
5781     if (G_UNLIKELY (stream->discont)) {
5782       GST_LOG_OBJECT (qtdemux, "marking discont buffer");
5783       GST_BUFFER_FLAG_SET (buffer, GST_BUFFER_FLAG_DISCONT);
5784       stream->discont = FALSE;
5785     } else {
5786       GST_BUFFER_FLAG_UNSET (buf, GST_BUFFER_FLAG_DISCONT);
5787     }
5788
5789     if (stream->alignment > 1)
5790       buffer = gst_qtdemux_align_buffer (qtdemux, buffer, stream->alignment);
5791     gst_pad_push (stream->pad, buffer);
5792
5793     stream->buffers = g_slist_delete_link (stream->buffers, stream->buffers);
5794   }
5795
5796   /* we're going to modify the metadata */
5797   buf = gst_buffer_make_writable (buf);
5798
5799   if (G_UNLIKELY (stream->need_process))
5800     buf = gst_qtdemux_process_buffer (qtdemux, stream, buf);
5801
5802   if (!buf) {
5803     goto exit;
5804   }
5805
5806   GST_BUFFER_DTS (buf) = dts;
5807   GST_BUFFER_PTS (buf) = pts;
5808   GST_BUFFER_DURATION (buf) = duration;
5809   GST_BUFFER_OFFSET (buf) = -1;
5810   GST_BUFFER_OFFSET_END (buf) = -1;
5811
5812   if (G_UNLIKELY (CUR_STREAM (stream)->rgb8_palette))
5813     gst_buffer_append_memory (buf,
5814         gst_memory_ref (CUR_STREAM (stream)->rgb8_palette));
5815
5816   if (G_UNLIKELY (CUR_STREAM (stream)->padding)) {
5817     gst_buffer_resize (buf, CUR_STREAM (stream)->padding, -1);
5818   }
5819 #if 0
5820   if (G_UNLIKELY (qtdemux->element_index)) {
5821     GstClockTime stream_time;
5822
5823     stream_time =
5824         gst_segment_to_stream_time (&stream->segment, GST_FORMAT_TIME,
5825         timestamp);
5826     if (GST_CLOCK_TIME_IS_VALID (stream_time)) {
5827       GST_LOG_OBJECT (qtdemux,
5828           "adding association %" GST_TIME_FORMAT "-> %"
5829           G_GUINT64_FORMAT, GST_TIME_ARGS (stream_time), byte_position);
5830       gst_index_add_association (qtdemux->element_index,
5831           qtdemux->index_id,
5832           keyframe ? GST_ASSOCIATION_FLAG_KEY_UNIT :
5833           GST_ASSOCIATION_FLAG_DELTA_UNIT, GST_FORMAT_TIME, stream_time,
5834           GST_FORMAT_BYTES, byte_position, NULL);
5835     }
5836   }
5837 #endif
5838
5839   if (stream->need_clip)
5840     buf = gst_qtdemux_clip_buffer (qtdemux, stream, buf);
5841
5842   if (G_UNLIKELY (buf == NULL))
5843     goto exit;
5844
5845   if (G_UNLIKELY (stream->discont)) {
5846     GST_LOG_OBJECT (qtdemux, "marking discont buffer");
5847     GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_DISCONT);
5848     stream->discont = FALSE;
5849   } else {
5850     GST_BUFFER_FLAG_UNSET (buf, GST_BUFFER_FLAG_DISCONT);
5851   }
5852
5853   if (!keyframe) {
5854     GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_DELTA_UNIT);
5855     stream->on_keyframe = FALSE;
5856   } else {
5857     stream->on_keyframe = TRUE;
5858   }
5859
5860
5861   GST_LOG_OBJECT (qtdemux,
5862       "Pushing buffer with dts %" GST_TIME_FORMAT ", pts %" GST_TIME_FORMAT
5863       ", duration %" GST_TIME_FORMAT " on pad %s", GST_TIME_ARGS (dts),
5864       GST_TIME_ARGS (pts), GST_TIME_ARGS (duration),
5865       GST_PAD_NAME (stream->pad));
5866
5867   if (stream->protected && stream->protection_scheme_type == FOURCC_cenc) {
5868     GstStructure *crypto_info;
5869     QtDemuxCencSampleSetInfo *info =
5870         (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
5871     gint index;
5872     GstEvent *event;
5873
5874     while ((event = g_queue_pop_head (&stream->protection_scheme_event_queue))) {
5875       GST_TRACE_OBJECT (stream->pad, "pushing protection event: %"
5876           GST_PTR_FORMAT, event);
5877       gst_pad_push_event (stream->pad, event);
5878     }
5879
5880     if (info->crypto_info == NULL) {
5881       GST_DEBUG_OBJECT (qtdemux,
5882           "cenc metadata hasn't been parsed yet, pushing buffer as if it wasn't encrypted");
5883     } else {
5884       /* The end of the crypto_info array matches our n_samples position,
5885        * so count backward from there */
5886       index = stream->sample_index - stream->n_samples + info->crypto_info->len;
5887       if (G_LIKELY (index >= 0 && index < info->crypto_info->len)) {
5888         /* steal structure from array */
5889         crypto_info = g_ptr_array_index (info->crypto_info, index);
5890         g_ptr_array_index (info->crypto_info, index) = NULL;
5891         GST_LOG_OBJECT (qtdemux, "attaching cenc metadata [%u/%u]", index,
5892             info->crypto_info->len);
5893         if (!crypto_info || !gst_buffer_add_protection_meta (buf, crypto_info))
5894           GST_ERROR_OBJECT (qtdemux,
5895               "failed to attach cenc metadata to buffer");
5896       } else {
5897         GST_INFO_OBJECT (qtdemux, "No crypto info with index %d and sample %d",
5898             index, stream->sample_index);
5899       }
5900     }
5901   }
5902
5903   if (stream->alignment > 1)
5904     buf = gst_qtdemux_align_buffer (qtdemux, buf, stream->alignment);
5905
5906   ret = gst_pad_push (stream->pad, buf);
5907
5908   if (GST_CLOCK_TIME_IS_VALID (pts) && GST_CLOCK_TIME_IS_VALID (duration)) {
5909     /* mark position in stream, we'll need this to know when to send GAP event */
5910     stream->segment.position = pts + duration;
5911   }
5912
5913 exit:
5914   return ret;
5915 }
5916
5917 static const QtDemuxRandomAccessEntry *
5918 gst_qtdemux_stream_seek_fragment (GstQTDemux * qtdemux, QtDemuxStream * stream,
5919     GstClockTime pos, gboolean after)
5920 {
5921   QtDemuxRandomAccessEntry *entries = stream->ra_entries;
5922   guint n_entries = stream->n_ra_entries;
5923   guint i;
5924
5925   /* we assume the table is sorted */
5926   for (i = 0; i < n_entries; ++i) {
5927     if (entries[i].ts > pos)
5928       break;
5929   }
5930
5931   /* FIXME: maybe save first moof_offset somewhere instead, but for now it's
5932    * probably okay to assume that the index lists the very first fragment */
5933   if (i == 0)
5934     return &entries[0];
5935
5936   if (after)
5937     return &entries[i];
5938   else
5939     return &entries[i - 1];
5940 }
5941
5942 static gboolean
5943 gst_qtdemux_do_fragmented_seek (GstQTDemux * qtdemux)
5944 {
5945   const QtDemuxRandomAccessEntry *best_entry = NULL;
5946   GList *iter;
5947
5948   GST_OBJECT_LOCK (qtdemux);
5949
5950   g_assert (qtdemux->n_streams > 0);
5951
5952   /* first see if we can determine where to go to using mfra,
5953    * before we start clearing things */
5954   for (iter = qtdemux->active_streams; iter; iter = g_list_next (iter)) {
5955     const QtDemuxRandomAccessEntry *entry;
5956     QtDemuxStream *stream;
5957     gboolean is_audio_or_video;
5958
5959     stream = QTDEMUX_STREAM (iter->data);
5960
5961     if (stream->ra_entries == NULL)
5962       continue;
5963
5964     if (stream->subtype == FOURCC_vide || stream->subtype == FOURCC_soun)
5965       is_audio_or_video = TRUE;
5966     else
5967       is_audio_or_video = FALSE;
5968
5969     entry =
5970         gst_qtdemux_stream_seek_fragment (qtdemux, stream,
5971         stream->time_position, !is_audio_or_video);
5972
5973     GST_INFO_OBJECT (stream->pad, "%" GST_TIME_FORMAT " at offset "
5974         "%" G_GUINT64_FORMAT, GST_TIME_ARGS (entry->ts), entry->moof_offset);
5975
5976     stream->pending_seek = entry;
5977
5978     /* decide position to jump to just based on audio/video tracks, not subs */
5979     if (!is_audio_or_video)
5980       continue;
5981
5982     if (best_entry == NULL || entry->moof_offset < best_entry->moof_offset)
5983       best_entry = entry;
5984   }
5985
5986   /* no luck, will handle seek otherwise */
5987   if (best_entry == NULL) {
5988     GST_OBJECT_UNLOCK (qtdemux);
5989     return FALSE;
5990   }
5991
5992   /* ok, now we can prepare for processing as of located moof */
5993   for (iter = qtdemux->active_streams; iter; iter = g_list_next (iter)) {
5994     QtDemuxStream *stream;
5995
5996     stream = QTDEMUX_STREAM (iter->data);
5997
5998     g_free (stream->samples);
5999     stream->samples = NULL;
6000     stream->n_samples = 0;
6001     stream->stbl_index = -1;    /* no samples have yet been parsed */
6002     stream->sample_index = -1;
6003
6004     if (stream->protection_scheme_info) {
6005       /* Clear out any old cenc crypto info entries as we'll move to a new moof */
6006       if (stream->protection_scheme_type == FOURCC_cenc) {
6007         QtDemuxCencSampleSetInfo *info =
6008             (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
6009         if (info->crypto_info) {
6010           g_ptr_array_free (info->crypto_info, TRUE);
6011           info->crypto_info = NULL;
6012         }
6013       }
6014     }
6015   }
6016
6017   GST_INFO_OBJECT (qtdemux, "seek to %" GST_TIME_FORMAT ", best fragment "
6018       "moof offset: %" G_GUINT64_FORMAT ", ts %" GST_TIME_FORMAT,
6019       GST_TIME_ARGS (QTDEMUX_FIRST_STREAM (qtdemux)->time_position),
6020       best_entry->moof_offset, GST_TIME_ARGS (best_entry->ts));
6021
6022   qtdemux->moof_offset = best_entry->moof_offset;
6023
6024   qtdemux_add_fragmented_samples (qtdemux);
6025
6026   GST_OBJECT_UNLOCK (qtdemux);
6027   return TRUE;
6028 }
6029
6030 static GstFlowReturn
6031 gst_qtdemux_loop_state_movie (GstQTDemux * qtdemux)
6032 {
6033   GstFlowReturn ret = GST_FLOW_OK;
6034   GstBuffer *buf = NULL;
6035   QtDemuxStream *stream, *target_stream = NULL;
6036   GstClockTime min_time;
6037   guint64 offset = 0;
6038   GstClockTime dts = GST_CLOCK_TIME_NONE;
6039   GstClockTime pts = GST_CLOCK_TIME_NONE;
6040   GstClockTime duration = 0;
6041   gboolean keyframe = FALSE;
6042   guint sample_size = 0;
6043   gboolean empty = 0;
6044   guint size;
6045   GList *iter;
6046
6047   if (qtdemux->fragmented_seek_pending) {
6048     GST_INFO_OBJECT (qtdemux, "pending fragmented seek");
6049     if (gst_qtdemux_do_fragmented_seek (qtdemux)) {
6050       GST_INFO_OBJECT (qtdemux, "fragmented seek done!");
6051       qtdemux->fragmented_seek_pending = FALSE;
6052     } else {
6053       GST_INFO_OBJECT (qtdemux, "fragmented seek still pending");
6054     }
6055   }
6056
6057   /* Figure out the next stream sample to output, min_time is expressed in
6058    * global time and runs over the edit list segments. */
6059   min_time = G_MAXUINT64;
6060   for (iter = qtdemux->active_streams; iter; iter = g_list_next (iter)) {
6061     GstClockTime position;
6062
6063     stream = QTDEMUX_STREAM (iter->data);
6064     position = stream->time_position;
6065
6066     /* position of -1 is EOS */
6067     if (position != GST_CLOCK_TIME_NONE && position < min_time) {
6068       min_time = position;
6069       target_stream = stream;
6070     }
6071   }
6072   /* all are EOS */
6073   if (G_UNLIKELY (target_stream == NULL)) {
6074     GST_DEBUG_OBJECT (qtdemux, "all streams are EOS");
6075     goto eos;
6076   }
6077
6078   /* check for segment end */
6079   if (G_UNLIKELY (qtdemux->segment.stop != -1
6080           && ((qtdemux->segment.rate >= 0 && qtdemux->segment.stop <= min_time)
6081               || (qtdemux->segment.rate < 0
6082                   && qtdemux->segment.start > min_time))
6083           && target_stream->on_keyframe)) {
6084     GST_DEBUG_OBJECT (qtdemux, "we reached the end of our segment.");
6085     target_stream->time_position = GST_CLOCK_TIME_NONE;
6086     goto eos_stream;
6087   }
6088
6089   /* gap events for subtitle streams */
6090   for (iter = qtdemux->active_streams; iter; iter = g_list_next (iter)) {
6091     stream = QTDEMUX_STREAM (iter->data);
6092     if (stream->pad && (stream->subtype == FOURCC_subp
6093             || stream->subtype == FOURCC_text
6094             || stream->subtype == FOURCC_sbtl)) {
6095       /* send one second gap events until the stream catches up */
6096       /* gaps can only be sent after segment is activated (segment.stop is no longer -1) */
6097       while (GST_CLOCK_TIME_IS_VALID (stream->segment.stop) &&
6098           GST_CLOCK_TIME_IS_VALID (stream->segment.position) &&
6099           stream->segment.position + GST_SECOND < min_time) {
6100         GstEvent *gap =
6101             gst_event_new_gap (stream->segment.position, GST_SECOND);
6102         gst_pad_push_event (stream->pad, gap);
6103         stream->segment.position += GST_SECOND;
6104       }
6105     }
6106   }
6107
6108   stream = target_stream;
6109   /* fetch info for the current sample of this stream */
6110   if (G_UNLIKELY (!gst_qtdemux_prepare_current_sample (qtdemux, stream, &empty,
6111               &offset, &sample_size, &dts, &pts, &duration, &keyframe)))
6112     goto eos_stream;
6113
6114   gst_qtdemux_stream_check_and_change_stsd_index (qtdemux, stream);
6115   if (stream->new_caps) {
6116     gst_qtdemux_configure_stream (qtdemux, stream);
6117     qtdemux_do_allocation (qtdemux, stream);
6118   }
6119
6120   /* If we're doing a keyframe-only trickmode, only push keyframes on video streams */
6121   if (G_UNLIKELY (qtdemux->
6122           segment.flags & GST_SEGMENT_FLAG_TRICKMODE_KEY_UNITS)) {
6123     if (stream->subtype == FOURCC_vide && !keyframe) {
6124       GST_LOG_OBJECT (qtdemux, "Skipping non-keyframe on track-id %u",
6125           stream->track_id);
6126       goto next;
6127     }
6128   }
6129
6130   GST_DEBUG_OBJECT (qtdemux,
6131       "pushing from track-id %u, empty %d offset %" G_GUINT64_FORMAT
6132       ", size %d, dts=%" GST_TIME_FORMAT ", pts=%" GST_TIME_FORMAT
6133       ", duration %" GST_TIME_FORMAT, stream->track_id, empty, offset,
6134       sample_size, GST_TIME_ARGS (dts), GST_TIME_ARGS (pts),
6135       GST_TIME_ARGS (duration));
6136
6137   if (G_UNLIKELY (empty)) {
6138     /* empty segment, push a gap if there's a second or more
6139      * difference and move to the next one */
6140     if ((pts + duration - stream->segment.position) >= GST_SECOND)
6141       gst_pad_push_event (stream->pad, gst_event_new_gap (pts, duration));
6142     stream->segment.position = pts + duration;
6143     goto next;
6144   }
6145
6146   /* hmm, empty sample, skip and move to next sample */
6147   if (G_UNLIKELY (sample_size <= 0))
6148     goto next;
6149
6150   /* last pushed sample was out of boundary, goto next sample */
6151   if (G_UNLIKELY (GST_PAD_LAST_FLOW_RETURN (stream->pad) == GST_FLOW_EOS))
6152     goto next;
6153
6154   if (stream->max_buffer_size == 0 || sample_size <= stream->max_buffer_size) {
6155     size = sample_size;
6156   } else {
6157     GST_DEBUG_OBJECT (qtdemux,
6158         "size %d larger than stream max_buffer_size %d, trimming",
6159         sample_size, stream->max_buffer_size);
6160     size =
6161         MIN (sample_size - stream->offset_in_sample, stream->max_buffer_size);
6162   }
6163
6164   if (qtdemux->cenc_aux_info_offset > 0) {
6165     GstMapInfo map;
6166     GstByteReader br;
6167     GstBuffer *aux_info = NULL;
6168
6169     /* pull the data stored before the sample */
6170     ret =
6171         gst_qtdemux_pull_atom (qtdemux, qtdemux->offset,
6172         offset + stream->offset_in_sample - qtdemux->offset, &aux_info);
6173     if (G_UNLIKELY (ret != GST_FLOW_OK))
6174       goto beach;
6175     gst_buffer_map (aux_info, &map, GST_MAP_READ);
6176     GST_DEBUG_OBJECT (qtdemux, "parsing cenc auxiliary info");
6177     gst_byte_reader_init (&br, map.data + 8, map.size);
6178     if (!qtdemux_parse_cenc_aux_info (qtdemux, stream, &br,
6179             qtdemux->cenc_aux_info_sizes, qtdemux->cenc_aux_sample_count)) {
6180       GST_ERROR_OBJECT (qtdemux, "failed to parse cenc auxiliary info");
6181       gst_buffer_unmap (aux_info, &map);
6182       gst_buffer_unref (aux_info);
6183       ret = GST_FLOW_ERROR;
6184       goto beach;
6185     }
6186     gst_buffer_unmap (aux_info, &map);
6187     gst_buffer_unref (aux_info);
6188   }
6189
6190   GST_LOG_OBJECT (qtdemux, "reading %d bytes @ %" G_GUINT64_FORMAT, size,
6191       offset);
6192
6193   if (stream->use_allocator) {
6194     /* if we have a per-stream allocator, use it */
6195     buf = gst_buffer_new_allocate (stream->allocator, size, &stream->params);
6196   }
6197
6198   ret = gst_qtdemux_pull_atom (qtdemux, offset + stream->offset_in_sample,
6199       size, &buf);
6200   if (G_UNLIKELY (ret != GST_FLOW_OK))
6201     goto beach;
6202
6203   if (size != sample_size) {
6204     pts += gst_util_uint64_scale_int (GST_SECOND,
6205         stream->offset_in_sample / CUR_STREAM (stream)->bytes_per_frame,
6206         stream->timescale);
6207     dts +=
6208         gst_util_uint64_scale_int (GST_SECOND,
6209         stream->offset_in_sample / CUR_STREAM (stream)->bytes_per_frame,
6210         stream->timescale);
6211     duration =
6212         gst_util_uint64_scale_int (GST_SECOND,
6213         size / CUR_STREAM (stream)->bytes_per_frame, stream->timescale);
6214   }
6215
6216   ret = gst_qtdemux_decorate_and_push_buffer (qtdemux, stream, buf,
6217       dts, pts, duration, keyframe, min_time, offset);
6218
6219   if (size != sample_size) {
6220     QtDemuxSample *sample = &stream->samples[stream->sample_index];
6221     QtDemuxSegment *segment = &stream->segments[stream->segment_index];
6222
6223     GstClockTime time_position = QTSTREAMTIME_TO_GSTTIME (stream,
6224         sample->timestamp +
6225         stream->offset_in_sample / CUR_STREAM (stream)->bytes_per_frame);
6226     if (time_position >= segment->media_start) {
6227       /* inside the segment, update time_position, looks very familiar to
6228        * GStreamer segments, doesn't it? */
6229       stream->time_position = (time_position - segment->media_start) +
6230           segment->time;
6231     } else {
6232       /* not yet in segment, time does not yet increment. This means
6233        * that we are still prerolling keyframes to the decoder so it can
6234        * decode the first sample of the segment. */
6235       stream->time_position = segment->time;
6236     }
6237   }
6238
6239   /* combine flows */
6240   ret = gst_qtdemux_combine_flows (qtdemux, stream, ret);
6241   /* ignore unlinked, we will not push on the pad anymore and we will EOS when
6242    * we have no more data for the pad to push */
6243   if (ret == GST_FLOW_EOS)
6244     ret = GST_FLOW_OK;
6245
6246   stream->offset_in_sample += size;
6247   if (stream->offset_in_sample >= sample_size) {
6248     gst_qtdemux_advance_sample (qtdemux, stream);
6249   }
6250   goto beach;
6251
6252 next:
6253   gst_qtdemux_advance_sample (qtdemux, stream);
6254
6255 beach:
6256   return ret;
6257
6258   /* special cases */
6259 eos:
6260   {
6261     GST_DEBUG_OBJECT (qtdemux, "No samples left for any streams - EOS");
6262     ret = GST_FLOW_EOS;
6263     goto beach;
6264   }
6265 eos_stream:
6266   {
6267     GST_DEBUG_OBJECT (qtdemux, "No samples left for stream");
6268     /* EOS will be raised if all are EOS */
6269     ret = GST_FLOW_OK;
6270     goto beach;
6271   }
6272 }
6273
6274 static void
6275 gst_qtdemux_loop (GstPad * pad)
6276 {
6277   GstQTDemux *qtdemux;
6278   guint64 cur_offset;
6279   GstFlowReturn ret;
6280
6281   qtdemux = GST_QTDEMUX (gst_pad_get_parent (pad));
6282
6283   cur_offset = qtdemux->offset;
6284   GST_LOG_OBJECT (qtdemux, "loop at position %" G_GUINT64_FORMAT ", state %s",
6285       cur_offset, qt_demux_state_string (qtdemux->state));
6286
6287   switch (qtdemux->state) {
6288     case QTDEMUX_STATE_INITIAL:
6289     case QTDEMUX_STATE_HEADER:
6290       ret = gst_qtdemux_loop_state_header (qtdemux);
6291       break;
6292     case QTDEMUX_STATE_MOVIE:
6293       ret = gst_qtdemux_loop_state_movie (qtdemux);
6294       if (qtdemux->segment.rate < 0 && ret == GST_FLOW_EOS) {
6295         ret = gst_qtdemux_seek_to_previous_keyframe (qtdemux);
6296       }
6297       break;
6298     default:
6299       /* ouch */
6300       goto invalid_state;
6301   }
6302
6303   /* if something went wrong, pause */
6304   if (ret != GST_FLOW_OK)
6305     goto pause;
6306
6307 done:
6308   gst_object_unref (qtdemux);
6309   return;
6310
6311   /* ERRORS */
6312 invalid_state:
6313   {
6314     GST_ELEMENT_ERROR (qtdemux, STREAM, FAILED,
6315         (NULL), ("streaming stopped, invalid state"));
6316     gst_pad_pause_task (pad);
6317     gst_qtdemux_push_event (qtdemux, gst_event_new_eos ());
6318     goto done;
6319   }
6320 pause:
6321   {
6322     const gchar *reason = gst_flow_get_name (ret);
6323
6324     GST_LOG_OBJECT (qtdemux, "pausing task, reason %s", reason);
6325
6326     gst_pad_pause_task (pad);
6327
6328     /* fatal errors need special actions */
6329     /* check EOS */
6330     if (ret == GST_FLOW_EOS) {
6331       if (qtdemux->n_streams == 0) {
6332         /* we have no streams, post an error */
6333         gst_qtdemux_post_no_playable_stream_error (qtdemux);
6334       }
6335       if (qtdemux->segment.flags & GST_SEEK_FLAG_SEGMENT) {
6336         gint64 stop;
6337
6338         if ((stop = qtdemux->segment.stop) == -1)
6339           stop = qtdemux->segment.duration;
6340
6341         if (qtdemux->segment.rate >= 0) {
6342           GstMessage *message;
6343           GstEvent *event;
6344
6345           GST_LOG_OBJECT (qtdemux, "Sending segment done, at end of segment");
6346           message = gst_message_new_segment_done (GST_OBJECT_CAST (qtdemux),
6347               GST_FORMAT_TIME, stop);
6348           event = gst_event_new_segment_done (GST_FORMAT_TIME, stop);
6349           if (qtdemux->segment_seqnum != GST_SEQNUM_INVALID) {
6350             gst_message_set_seqnum (message, qtdemux->segment_seqnum);
6351             gst_event_set_seqnum (event, qtdemux->segment_seqnum);
6352           }
6353           gst_element_post_message (GST_ELEMENT_CAST (qtdemux), message);
6354           gst_qtdemux_push_event (qtdemux, event);
6355         } else {
6356           GstMessage *message;
6357           GstEvent *event;
6358
6359           /*  For Reverse Playback */
6360           GST_LOG_OBJECT (qtdemux, "Sending segment done, at start of segment");
6361           message = gst_message_new_segment_done (GST_OBJECT_CAST (qtdemux),
6362               GST_FORMAT_TIME, qtdemux->segment.start);
6363           event = gst_event_new_segment_done (GST_FORMAT_TIME,
6364               qtdemux->segment.start);
6365           if (qtdemux->segment_seqnum != GST_SEQNUM_INVALID) {
6366             gst_message_set_seqnum (message, qtdemux->segment_seqnum);
6367             gst_event_set_seqnum (event, qtdemux->segment_seqnum);
6368           }
6369           gst_element_post_message (GST_ELEMENT_CAST (qtdemux), message);
6370           gst_qtdemux_push_event (qtdemux, event);
6371         }
6372       } else {
6373         GstEvent *event;
6374
6375         GST_LOG_OBJECT (qtdemux, "Sending EOS at end of segment");
6376         event = gst_event_new_eos ();
6377         if (qtdemux->segment_seqnum != GST_SEQNUM_INVALID)
6378           gst_event_set_seqnum (event, qtdemux->segment_seqnum);
6379         gst_qtdemux_push_event (qtdemux, event);
6380       }
6381     } else if (ret == GST_FLOW_NOT_LINKED || ret < GST_FLOW_EOS) {
6382       GST_ELEMENT_FLOW_ERROR (qtdemux, ret);
6383       gst_qtdemux_push_event (qtdemux, gst_event_new_eos ());
6384     }
6385     goto done;
6386   }
6387 }
6388
6389 /*
6390  * has_next_entry
6391  *
6392  * Returns if there are samples to be played.
6393  */
6394 static gboolean
6395 has_next_entry (GstQTDemux * demux)
6396 {
6397   QtDemuxStream *stream;
6398   GList *iter;
6399
6400   GST_DEBUG_OBJECT (demux, "Checking if there are samples not played yet");
6401
6402   for (iter = demux->active_streams; iter; iter = g_list_next (iter)) {
6403     stream = QTDEMUX_STREAM (iter->data);
6404
6405     if (stream->sample_index == -1) {
6406       stream->sample_index = 0;
6407       stream->offset_in_sample = 0;
6408     }
6409
6410     if (stream->sample_index >= stream->n_samples) {
6411       GST_LOG_OBJECT (demux, "track-id %u samples exhausted", stream->track_id);
6412       continue;
6413     }
6414     GST_DEBUG_OBJECT (demux, "Found a sample");
6415     return TRUE;
6416   }
6417
6418   GST_DEBUG_OBJECT (demux, "There wasn't any next sample");
6419   return FALSE;
6420 }
6421
6422 /*
6423  * next_entry_size
6424  *
6425  * Returns the size of the first entry at the current offset.
6426  * If -1, there are none (which means EOS or empty file).
6427  */
6428 static guint64
6429 next_entry_size (GstQTDemux * demux)
6430 {
6431   QtDemuxStream *stream, *target_stream = NULL;
6432   guint64 smalloffs = (guint64) - 1;
6433   QtDemuxSample *sample;
6434   GList *iter;
6435
6436   GST_LOG_OBJECT (demux, "Finding entry at offset %" G_GUINT64_FORMAT,
6437       demux->offset);
6438
6439   for (iter = demux->active_streams; iter; iter = g_list_next (iter)) {
6440     stream = QTDEMUX_STREAM (iter->data);
6441
6442     if (stream->sample_index == -1) {
6443       stream->sample_index = 0;
6444       stream->offset_in_sample = 0;
6445     }
6446
6447     if (stream->sample_index >= stream->n_samples) {
6448       GST_LOG_OBJECT (demux, "track-id %u samples exhausted", stream->track_id);
6449       continue;
6450     }
6451
6452     if (!qtdemux_parse_samples (demux, stream, stream->sample_index)) {
6453       GST_LOG_OBJECT (demux, "Parsing of index %u from stbl atom failed!",
6454           stream->sample_index);
6455       return -1;
6456     }
6457
6458     sample = &stream->samples[stream->sample_index];
6459
6460     GST_LOG_OBJECT (demux,
6461         "Checking track-id %u (sample_index:%d / offset:%" G_GUINT64_FORMAT
6462         " / size:%" G_GUINT32_FORMAT ")", stream->track_id,
6463         stream->sample_index, sample->offset, sample->size);
6464
6465     if (((smalloffs == -1)
6466             || (sample->offset < smalloffs)) && (sample->size)) {
6467       smalloffs = sample->offset;
6468       target_stream = stream;
6469     }
6470   }
6471
6472   if (!target_stream)
6473     return -1;
6474
6475   GST_LOG_OBJECT (demux,
6476       "track-id %u offset %" G_GUINT64_FORMAT " demux->offset :%"
6477       G_GUINT64_FORMAT, target_stream->track_id, smalloffs, demux->offset);
6478
6479   stream = target_stream;
6480   sample = &stream->samples[stream->sample_index];
6481
6482   if (sample->offset >= demux->offset) {
6483     demux->todrop = sample->offset - demux->offset;
6484     return sample->size + demux->todrop;
6485   }
6486
6487   GST_DEBUG_OBJECT (demux,
6488       "There wasn't any entry at offset %" G_GUINT64_FORMAT, demux->offset);
6489   return -1;
6490 }
6491
6492 static void
6493 gst_qtdemux_post_progress (GstQTDemux * demux, gint num, gint denom)
6494 {
6495   gint perc = (gint) ((gdouble) num * 100.0 / (gdouble) denom);
6496
6497   gst_element_post_message (GST_ELEMENT_CAST (demux),
6498       gst_message_new_element (GST_OBJECT_CAST (demux),
6499           gst_structure_new ("progress", "percent", G_TYPE_INT, perc, NULL)));
6500 }
6501
6502 static gboolean
6503 qtdemux_seek_offset (GstQTDemux * demux, guint64 offset)
6504 {
6505   GstEvent *event;
6506   gboolean res = 0;
6507
6508   GST_DEBUG_OBJECT (demux, "Seeking to %" G_GUINT64_FORMAT, offset);
6509
6510   event =
6511       gst_event_new_seek (1.0, GST_FORMAT_BYTES,
6512       GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_ACCURATE, GST_SEEK_TYPE_SET, offset,
6513       GST_SEEK_TYPE_NONE, -1);
6514
6515   /* store seqnum to drop flush events, they don't need to reach downstream */
6516   demux->offset_seek_seqnum = gst_event_get_seqnum (event);
6517   res = gst_pad_push_event (demux->sinkpad, event);
6518   demux->offset_seek_seqnum = GST_SEQNUM_INVALID;
6519
6520   return res;
6521 }
6522
6523 /* check for seekable upstream, above and beyond a mere query */
6524 static void
6525 gst_qtdemux_check_seekability (GstQTDemux * demux)
6526 {
6527   GstQuery *query;
6528   gboolean seekable = FALSE;
6529   gint64 start = -1, stop = -1;
6530
6531   if (demux->upstream_size)
6532     return;
6533
6534   if (demux->upstream_format_is_time)
6535     return;
6536
6537   query = gst_query_new_seeking (GST_FORMAT_BYTES);
6538   if (!gst_pad_peer_query (demux->sinkpad, query)) {
6539     GST_DEBUG_OBJECT (demux, "seeking query failed");
6540     goto done;
6541   }
6542
6543   gst_query_parse_seeking (query, NULL, &seekable, &start, &stop);
6544
6545   /* try harder to query upstream size if we didn't get it the first time */
6546   if (seekable && stop == -1) {
6547     GST_DEBUG_OBJECT (demux, "doing duration query to fix up unset stop");
6548     gst_pad_peer_query_duration (demux->sinkpad, GST_FORMAT_BYTES, &stop);
6549   }
6550
6551   /* if upstream doesn't know the size, it's likely that it's not seekable in
6552    * practice even if it technically may be seekable */
6553   if (seekable && (start != 0 || stop <= start)) {
6554     GST_DEBUG_OBJECT (demux, "seekable but unknown start/stop -> disable");
6555     seekable = FALSE;
6556   }
6557
6558 done:
6559   gst_query_unref (query);
6560
6561   GST_DEBUG_OBJECT (demux, "seekable: %d (%" G_GUINT64_FORMAT " - %"
6562       G_GUINT64_FORMAT ")", seekable, start, stop);
6563   demux->upstream_seekable = seekable;
6564   demux->upstream_size = seekable ? stop : -1;
6565 }
6566
6567 static void
6568 gst_qtdemux_drop_data (GstQTDemux * demux, gint bytes)
6569 {
6570   g_return_if_fail (bytes <= demux->todrop);
6571
6572   GST_LOG_OBJECT (demux, "Dropping %d bytes", bytes);
6573   gst_adapter_flush (demux->adapter, bytes);
6574   demux->neededbytes -= bytes;
6575   demux->offset += bytes;
6576   demux->todrop -= bytes;
6577 }
6578
6579 /* PUSH-MODE only: Send a segment, if not done already. */
6580 static void
6581 gst_qtdemux_check_send_pending_segment (GstQTDemux * demux)
6582 {
6583   if (G_UNLIKELY (demux->need_segment)) {
6584     gint i;
6585     GList *iter;
6586
6587     if (!demux->upstream_format_is_time) {
6588       gst_qtdemux_map_and_push_segments (demux, &demux->segment);
6589     } else {
6590       GstEvent *segment_event;
6591       segment_event = gst_event_new_segment (&demux->segment);
6592       if (demux->segment_seqnum != GST_SEQNUM_INVALID)
6593         gst_event_set_seqnum (segment_event, demux->segment_seqnum);
6594       gst_qtdemux_push_event (demux, segment_event);
6595     }
6596
6597     demux->need_segment = FALSE;
6598
6599     /* clear to send tags on all streams */
6600     for (iter = demux->active_streams, i = 0; iter;
6601         iter = g_list_next (iter), i++) {
6602       QtDemuxStream *stream = QTDEMUX_STREAM (iter->data);
6603       gst_qtdemux_push_tags (demux, stream);
6604       if (CUR_STREAM (stream)->sparse) {
6605         GST_INFO_OBJECT (demux, "Sending gap event on stream %d", i);
6606         gst_pad_push_event (stream->pad,
6607             gst_event_new_gap (stream->segment.position, GST_CLOCK_TIME_NONE));
6608       }
6609     }
6610   }
6611 }
6612
6613 /* Used for push mode only. */
6614 static void
6615 gst_qtdemux_send_gap_for_segment (GstQTDemux * demux,
6616     QtDemuxStream * stream, gint segment_index, GstClockTime pos)
6617 {
6618   GstClockTime ts, dur;
6619
6620   ts = pos;
6621   dur =
6622       stream->segments[segment_index].duration - (pos -
6623       stream->segments[segment_index].time);
6624   stream->time_position += dur;
6625
6626   /* Only gaps with a duration of at least one second are propagated.
6627    * Same workaround as in pull mode.
6628    * (See 2e45926a96ec5298c6ef29bf912e5e6a06dc3e0e) */
6629   if (dur >= GST_SECOND) {
6630     GstEvent *gap;
6631     gap = gst_event_new_gap (ts, dur);
6632
6633     GST_DEBUG_OBJECT (stream->pad, "Pushing gap for empty "
6634         "segment: %" GST_PTR_FORMAT, gap);
6635     gst_pad_push_event (stream->pad, gap);
6636   }
6637 }
6638
6639 static GstFlowReturn
6640 gst_qtdemux_chain (GstPad * sinkpad, GstObject * parent, GstBuffer * inbuf)
6641 {
6642   GstQTDemux *demux;
6643
6644   demux = GST_QTDEMUX (parent);
6645
6646   GST_DEBUG_OBJECT (demux,
6647       "Received buffer pts:%" GST_TIME_FORMAT " dts:%" GST_TIME_FORMAT
6648       " offset:%" G_GUINT64_FORMAT " size:%" G_GSIZE_FORMAT " demux offset:%"
6649       G_GUINT64_FORMAT, GST_TIME_ARGS (GST_BUFFER_PTS (inbuf)),
6650       GST_TIME_ARGS (GST_BUFFER_DTS (inbuf)), GST_BUFFER_OFFSET (inbuf),
6651       gst_buffer_get_size (inbuf), demux->offset);
6652
6653   if (GST_BUFFER_FLAG_IS_SET (inbuf, GST_BUFFER_FLAG_DISCONT)) {
6654     gboolean is_gap_input = FALSE;
6655     GList *iter;
6656
6657     GST_DEBUG_OBJECT (demux, "Got DISCONT, marking all streams as DISCONT");
6658
6659     for (iter = demux->active_streams; iter; iter = g_list_next (iter)) {
6660       QTDEMUX_STREAM (iter->data)->discont = TRUE;
6661     }
6662
6663     /* Check if we can land back on our feet in the case where upstream is
6664      * handling the seeking/pushing of samples with gaps in between (like
6665      * in the case of trick-mode DASH for example) */
6666     if (demux->upstream_format_is_time
6667         && GST_BUFFER_OFFSET (inbuf) != GST_BUFFER_OFFSET_NONE) {
6668       for (iter = demux->active_streams; iter; iter = g_list_next (iter)) {
6669         guint32 res;
6670         QtDemuxStream *stream = QTDEMUX_STREAM (iter->data);
6671         GST_LOG_OBJECT (demux,
6672             "track-id #%u , checking if offset %" G_GUINT64_FORMAT
6673             " is a sample start", stream->track_id, GST_BUFFER_OFFSET (inbuf));
6674         res =
6675             gst_qtdemux_find_index_for_given_media_offset_linear (demux,
6676             stream, GST_BUFFER_OFFSET (inbuf));
6677         if (res != -1) {
6678           QtDemuxSample *sample = &stream->samples[res];
6679           GST_LOG_OBJECT (demux,
6680               "Checking if sample %d from track-id %u is valid (offset:%"
6681               G_GUINT64_FORMAT " size:%" G_GUINT32_FORMAT ")", res,
6682               stream->track_id, sample->offset, sample->size);
6683           if (sample->offset == GST_BUFFER_OFFSET (inbuf)) {
6684             GST_LOG_OBJECT (demux,
6685                 "new buffer corresponds to a valid sample : %" G_GUINT32_FORMAT,
6686                 res);
6687             is_gap_input = TRUE;
6688             /* We can go back to standard playback mode */
6689             demux->state = QTDEMUX_STATE_MOVIE;
6690             /* Remember which sample this stream is at */
6691             stream->sample_index = res;
6692             /* Finally update all push-based values to the expected values */
6693             demux->neededbytes = stream->samples[res].size;
6694             demux->offset = GST_BUFFER_OFFSET (inbuf);
6695             demux->mdatleft =
6696                 demux->mdatsize - demux->offset + demux->mdatoffset;
6697             demux->todrop = 0;
6698           }
6699         }
6700       }
6701       if (!is_gap_input) {
6702         GST_DEBUG_OBJECT (demux, "Resetting, actual DISCONT");
6703         /* Reset state if it's a real discont */
6704         demux->neededbytes = 16;
6705         demux->state = QTDEMUX_STATE_INITIAL;
6706         demux->offset = GST_BUFFER_OFFSET (inbuf);
6707         gst_adapter_clear (demux->adapter);
6708       }
6709     }
6710     /* Reverse fragmented playback, need to flush all we have before
6711      * consuming a new fragment.
6712      * The samples array have the timestamps calculated by accumulating the
6713      * durations but this won't work for reverse playback of fragments as
6714      * the timestamps of a subsequent fragment should be smaller than the
6715      * previously received one. */
6716     if (!is_gap_input && demux->fragmented && demux->segment.rate < 0) {
6717       gst_qtdemux_process_adapter (demux, TRUE);
6718       g_list_foreach (demux->active_streams,
6719           (GFunc) gst_qtdemux_stream_flush_samples_data, NULL);
6720     }
6721   }
6722
6723   gst_adapter_push (demux->adapter, inbuf);
6724
6725   GST_DEBUG_OBJECT (demux,
6726       "pushing in inbuf %p, neededbytes:%u, available:%" G_GSIZE_FORMAT, inbuf,
6727       demux->neededbytes, gst_adapter_available (demux->adapter));
6728
6729   return gst_qtdemux_process_adapter (demux, FALSE);
6730 }
6731
6732 static GstFlowReturn
6733 gst_qtdemux_process_adapter (GstQTDemux * demux, gboolean force)
6734 {
6735   GstFlowReturn ret = GST_FLOW_OK;
6736
6737   /* we never really mean to buffer that much */
6738   if (demux->neededbytes == -1) {
6739     goto eos;
6740   }
6741
6742   while (((gst_adapter_available (demux->adapter)) >= demux->neededbytes) &&
6743       (ret == GST_FLOW_OK || (ret == GST_FLOW_NOT_LINKED && force))) {
6744
6745 #ifndef GST_DISABLE_GST_DEBUG
6746     {
6747       guint64 discont_offset, distance_from_discont;
6748
6749       discont_offset = gst_adapter_offset_at_discont (demux->adapter);
6750       distance_from_discont =
6751           gst_adapter_distance_from_discont (demux->adapter);
6752
6753       GST_DEBUG_OBJECT (demux,
6754           "state:%s , demux->neededbytes:%d, demux->offset:%" G_GUINT64_FORMAT
6755           " adapter offset :%" G_GUINT64_FORMAT " (+ %" G_GUINT64_FORMAT
6756           " bytes)", qt_demux_state_string (demux->state), demux->neededbytes,
6757           demux->offset, discont_offset, distance_from_discont);
6758     }
6759 #endif
6760
6761     switch (demux->state) {
6762       case QTDEMUX_STATE_INITIAL:{
6763         const guint8 *data;
6764         guint32 fourcc;
6765         guint64 size;
6766
6767         gst_qtdemux_check_seekability (demux);
6768
6769         data = gst_adapter_map (demux->adapter, demux->neededbytes);
6770
6771         /* get fourcc/length, set neededbytes */
6772         extract_initial_length_and_fourcc ((guint8 *) data, demux->neededbytes,
6773             &size, &fourcc);
6774         gst_adapter_unmap (demux->adapter);
6775         data = NULL;
6776         GST_DEBUG_OBJECT (demux, "Peeking found [%" GST_FOURCC_FORMAT "] "
6777             "size: %" G_GUINT64_FORMAT, GST_FOURCC_ARGS (fourcc), size);
6778         if (size == 0) {
6779           GST_ELEMENT_ERROR (demux, STREAM, DEMUX,
6780               (_("This file is invalid and cannot be played.")),
6781               ("initial atom '%" GST_FOURCC_FORMAT "' has empty length",
6782                   GST_FOURCC_ARGS (fourcc)));
6783           ret = GST_FLOW_ERROR;
6784           break;
6785         }
6786         if (fourcc == FOURCC_mdat) {
6787           gint next_entry = next_entry_size (demux);
6788           if (demux->n_streams > 0 && (next_entry != -1 || !demux->fragmented)) {
6789             /* we have the headers, start playback */
6790             demux->state = QTDEMUX_STATE_MOVIE;
6791             demux->neededbytes = next_entry;
6792             demux->mdatleft = size;
6793             demux->mdatsize = demux->mdatleft;
6794           } else {
6795             /* no headers yet, try to get them */
6796             guint bs;
6797             gboolean res;
6798             guint64 old, target;
6799
6800           buffer_data:
6801             old = demux->offset;
6802             target = old + size;
6803
6804             /* try to jump over the atom with a seek */
6805             /* only bother if it seems worth doing so,
6806              * and avoids possible upstream/server problems */
6807             if (demux->upstream_seekable &&
6808                 demux->upstream_size > 4 * (1 << 20)) {
6809               res = qtdemux_seek_offset (demux, target);
6810             } else {
6811               GST_DEBUG_OBJECT (demux, "skipping seek");
6812               res = FALSE;
6813             }
6814
6815             if (res) {
6816               GST_DEBUG_OBJECT (demux, "seek success");
6817               /* remember the offset fo the first mdat so we can seek back to it
6818                * after we have the headers */
6819               if (fourcc == FOURCC_mdat && demux->first_mdat == -1) {
6820                 demux->first_mdat = old;
6821                 GST_DEBUG_OBJECT (demux, "first mdat at %" G_GUINT64_FORMAT,
6822                     demux->first_mdat);
6823               }
6824               /* seek worked, continue reading */
6825               demux->offset = target;
6826               demux->neededbytes = 16;
6827               demux->state = QTDEMUX_STATE_INITIAL;
6828             } else {
6829               /* seek failed, need to buffer */
6830               demux->offset = old;
6831               GST_DEBUG_OBJECT (demux, "seek failed/skipped");
6832               /* there may be multiple mdat (or alike) buffers */
6833               /* sanity check */
6834               if (demux->mdatbuffer)
6835                 bs = gst_buffer_get_size (demux->mdatbuffer);
6836               else
6837                 bs = 0;
6838               if (size + bs > 10 * (1 << 20))
6839                 goto no_moov;
6840               demux->state = QTDEMUX_STATE_BUFFER_MDAT;
6841               demux->neededbytes = size;
6842               if (!demux->mdatbuffer)
6843                 demux->mdatoffset = demux->offset;
6844             }
6845           }
6846         } else if (G_UNLIKELY (size > QTDEMUX_MAX_ATOM_SIZE)) {
6847           GST_ELEMENT_ERROR (demux, STREAM, DEMUX,
6848               (_("This file is invalid and cannot be played.")),
6849               ("atom %" GST_FOURCC_FORMAT " has bogus size %" G_GUINT64_FORMAT,
6850                   GST_FOURCC_ARGS (fourcc), size));
6851           ret = GST_FLOW_ERROR;
6852           break;
6853         } else {
6854           /* this means we already started buffering and still no moov header,
6855            * let's continue buffering everything till we get moov */
6856           if (demux->mdatbuffer && !(fourcc == FOURCC_moov
6857                   || fourcc == FOURCC_moof))
6858             goto buffer_data;
6859           demux->neededbytes = size;
6860           demux->state = QTDEMUX_STATE_HEADER;
6861         }
6862         break;
6863       }
6864       case QTDEMUX_STATE_HEADER:{
6865         const guint8 *data;
6866         guint32 fourcc;
6867
6868         GST_DEBUG_OBJECT (demux, "In header");
6869
6870         data = gst_adapter_map (demux->adapter, demux->neededbytes);
6871
6872         /* parse the header */
6873         extract_initial_length_and_fourcc (data, demux->neededbytes, NULL,
6874             &fourcc);
6875         if (fourcc == FOURCC_moov) {
6876           /* in usual fragmented setup we could try to scan for more
6877            * and end up at the the moov (after mdat) again */
6878           if (demux->got_moov && demux->n_streams > 0 &&
6879               (!demux->fragmented
6880                   || demux->last_moov_offset == demux->offset)) {
6881             GST_DEBUG_OBJECT (demux,
6882                 "Skipping moov atom as we have (this) one already");
6883           } else {
6884             GST_DEBUG_OBJECT (demux, "Parsing [moov]");
6885
6886             if (demux->got_moov && demux->fragmented) {
6887               GST_DEBUG_OBJECT (demux,
6888                   "Got a second moov, clean up data from old one");
6889               if (demux->moov_node_compressed) {
6890                 g_node_destroy (demux->moov_node_compressed);
6891                 if (demux->moov_node)
6892                   g_free (demux->moov_node->data);
6893               }
6894               demux->moov_node_compressed = NULL;
6895               if (demux->moov_node)
6896                 g_node_destroy (demux->moov_node);
6897               demux->moov_node = NULL;
6898             }
6899
6900             demux->last_moov_offset = demux->offset;
6901
6902             /* Update streams with new moov */
6903             demux->old_streams =
6904                 g_list_concat (demux->old_streams, demux->active_streams);
6905             demux->active_streams = NULL;
6906
6907             qtdemux_parse_moov (demux, data, demux->neededbytes);
6908             qtdemux_node_dump (demux, demux->moov_node);
6909             qtdemux_parse_tree (demux);
6910             qtdemux_prepare_streams (demux);
6911             QTDEMUX_EXPOSE_LOCK (demux);
6912             qtdemux_expose_streams (demux);
6913             QTDEMUX_EXPOSE_UNLOCK (demux);
6914
6915             demux->got_moov = TRUE;
6916
6917             gst_qtdemux_check_send_pending_segment (demux);
6918
6919             if (demux->moov_node_compressed) {
6920               g_node_destroy (demux->moov_node_compressed);
6921               g_free (demux->moov_node->data);
6922             }
6923             demux->moov_node_compressed = NULL;
6924             g_node_destroy (demux->moov_node);
6925             demux->moov_node = NULL;
6926             GST_DEBUG_OBJECT (demux, "Finished parsing the header");
6927           }
6928         } else if (fourcc == FOURCC_moof) {
6929           if ((demux->got_moov || demux->media_caps) && demux->fragmented) {
6930             guint64 dist = 0;
6931             GstClockTime prev_pts;
6932             guint64 prev_offset;
6933             guint64 adapter_discont_offset, adapter_discont_dist;
6934
6935             GST_DEBUG_OBJECT (demux, "Parsing [moof]");
6936
6937             /*
6938              * The timestamp of the moof buffer is relevant as some scenarios
6939              * won't have the initial timestamp in the atoms. Whenever a new
6940              * buffer has started, we get that buffer's PTS and use it as a base
6941              * timestamp for the trun entries.
6942              *
6943              * To keep track of the current buffer timestamp and starting point
6944              * we use gst_adapter_prev_pts that gives us the PTS and the distance
6945              * from the beggining of the buffer, with the distance and demux->offset
6946              * we know if it is still the same buffer or not.
6947              */
6948             prev_pts = gst_adapter_prev_pts (demux->adapter, &dist);
6949             prev_offset = demux->offset - dist;
6950             if (demux->fragment_start_offset == -1
6951                 || prev_offset > demux->fragment_start_offset) {
6952               demux->fragment_start_offset = prev_offset;
6953               demux->fragment_start = prev_pts;
6954               GST_DEBUG_OBJECT (demux,
6955                   "New fragment start found at: %" G_GUINT64_FORMAT " : %"
6956                   GST_TIME_FORMAT, demux->fragment_start_offset,
6957                   GST_TIME_ARGS (demux->fragment_start));
6958             }
6959
6960             /* We can't use prev_offset() here because this would require
6961              * upstream to set consistent and correct offsets on all buffers
6962              * since the discont. Nothing ever did that in the past and we
6963              * would break backwards compatibility here then.
6964              * Instead take the offset we had at the last discont and count
6965              * the bytes from there. This works with old code as there would
6966              * be no discont between moov and moof, and also works with
6967              * adaptivedemux which correctly sets offset and will set the
6968              * DISCONT flag accordingly when needed.
6969              *
6970              * We also only do this for upstream TIME segments as otherwise
6971              * there are potential backwards compatibility problems with
6972              * seeking in PUSH mode and upstream providing inconsistent
6973              * timestamps. */
6974             adapter_discont_offset =
6975                 gst_adapter_offset_at_discont (demux->adapter);
6976             adapter_discont_dist =
6977                 gst_adapter_distance_from_discont (demux->adapter);
6978
6979             GST_DEBUG_OBJECT (demux,
6980                 "demux offset %" G_GUINT64_FORMAT " adapter offset %"
6981                 G_GUINT64_FORMAT " (+ %" G_GUINT64_FORMAT " bytes)",
6982                 demux->offset, adapter_discont_offset, adapter_discont_dist);
6983
6984             if (demux->upstream_format_is_time) {
6985               demux->moof_offset = adapter_discont_offset;
6986               if (demux->moof_offset != GST_BUFFER_OFFSET_NONE)
6987                 demux->moof_offset += adapter_discont_dist;
6988               if (demux->moof_offset == GST_BUFFER_OFFSET_NONE)
6989                 demux->moof_offset = demux->offset;
6990             } else {
6991               demux->moof_offset = demux->offset;
6992             }
6993
6994             if (!qtdemux_parse_moof (demux, data, demux->neededbytes,
6995                     demux->moof_offset, NULL)) {
6996               gst_adapter_unmap (demux->adapter);
6997               ret = GST_FLOW_ERROR;
6998               goto done;
6999             }
7000
7001             /* in MSS we need to expose the pads after the first moof as we won't get a moov */
7002             if (demux->mss_mode && !demux->exposed) {
7003               QTDEMUX_EXPOSE_LOCK (demux);
7004               qtdemux_expose_streams (demux);
7005               QTDEMUX_EXPOSE_UNLOCK (demux);
7006             }
7007
7008             gst_qtdemux_check_send_pending_segment (demux);
7009           } else {
7010             GST_DEBUG_OBJECT (demux, "Discarding [moof]");
7011           }
7012         } else if (fourcc == FOURCC_ftyp) {
7013           GST_DEBUG_OBJECT (demux, "Parsing [ftyp]");
7014           qtdemux_parse_ftyp (demux, data, demux->neededbytes);
7015         } else if (fourcc == FOURCC_uuid) {
7016           GST_DEBUG_OBJECT (demux, "Parsing [uuid]");
7017           qtdemux_parse_uuid (demux, data, demux->neededbytes);
7018         } else if (fourcc == FOURCC_sidx) {
7019           GST_DEBUG_OBJECT (demux, "Parsing [sidx]");
7020           qtdemux_parse_sidx (demux, data, demux->neededbytes);
7021         } else {
7022           switch (fourcc) {
7023             case FOURCC_styp:
7024               /* [styp] is like a [ftyp], but in fragment header. We ignore it for now
7025                * FALLTHROUGH */
7026             case FOURCC_skip:
7027             case FOURCC_free:
7028               /* [free] and [skip] are padding atoms */
7029               GST_DEBUG_OBJECT (demux,
7030                   "Skipping fourcc while parsing header : %" GST_FOURCC_FORMAT,
7031                   GST_FOURCC_ARGS (fourcc));
7032               break;
7033             default:
7034               GST_WARNING_OBJECT (demux,
7035                   "Unknown fourcc while parsing header : %" GST_FOURCC_FORMAT,
7036                   GST_FOURCC_ARGS (fourcc));
7037               /* Let's jump that one and go back to initial state */
7038               break;
7039           }
7040         }
7041         gst_adapter_unmap (demux->adapter);
7042         data = NULL;
7043
7044         if (demux->mdatbuffer && demux->n_streams) {
7045           gsize remaining_data_size = 0;
7046
7047           /* the mdat was before the header */
7048           GST_DEBUG_OBJECT (demux, "We have n_streams:%d and mdatbuffer:%p",
7049               demux->n_streams, demux->mdatbuffer);
7050           /* restore our adapter/offset view of things with upstream;
7051            * put preceding buffered data ahead of current moov data.
7052            * This should also handle evil mdat, moov, mdat cases and alike */
7053           gst_adapter_flush (demux->adapter, demux->neededbytes);
7054
7055           /* Store any remaining data after the mdat for later usage */
7056           remaining_data_size = gst_adapter_available (demux->adapter);
7057           if (remaining_data_size > 0) {
7058             g_assert (demux->restoredata_buffer == NULL);
7059             demux->restoredata_buffer =
7060                 gst_adapter_take_buffer (demux->adapter, remaining_data_size);
7061             demux->restoredata_offset = demux->offset + demux->neededbytes;
7062             GST_DEBUG_OBJECT (demux,
7063                 "Stored %" G_GSIZE_FORMAT " post mdat bytes at offset %"
7064                 G_GUINT64_FORMAT, remaining_data_size,
7065                 demux->restoredata_offset);
7066           }
7067
7068           gst_adapter_push (demux->adapter, demux->mdatbuffer);
7069           demux->mdatbuffer = NULL;
7070           demux->offset = demux->mdatoffset;
7071           demux->neededbytes = next_entry_size (demux);
7072           demux->state = QTDEMUX_STATE_MOVIE;
7073           demux->mdatleft = gst_adapter_available (demux->adapter);
7074           demux->mdatsize = demux->mdatleft;
7075         } else {
7076           GST_DEBUG_OBJECT (demux, "Carrying on normally");
7077           gst_adapter_flush (demux->adapter, demux->neededbytes);
7078
7079           /* only go back to the mdat if there are samples to play */
7080           if (demux->got_moov && demux->first_mdat != -1
7081               && has_next_entry (demux)) {
7082             gboolean res;
7083
7084             /* we need to seek back */
7085             res = qtdemux_seek_offset (demux, demux->first_mdat);
7086             if (res) {
7087               demux->offset = demux->first_mdat;
7088             } else {
7089               GST_DEBUG_OBJECT (demux, "Seek back failed");
7090             }
7091           } else {
7092             demux->offset += demux->neededbytes;
7093           }
7094           demux->neededbytes = 16;
7095           demux->state = QTDEMUX_STATE_INITIAL;
7096         }
7097
7098         break;
7099       }
7100       case QTDEMUX_STATE_BUFFER_MDAT:{
7101         GstBuffer *buf;
7102         guint8 fourcc[4];
7103
7104         GST_DEBUG_OBJECT (demux, "Got our buffer at offset %" G_GUINT64_FORMAT,
7105             demux->offset);
7106         buf = gst_adapter_take_buffer (demux->adapter, demux->neededbytes);
7107         gst_buffer_extract (buf, 0, fourcc, 4);
7108         GST_DEBUG_OBJECT (demux, "mdatbuffer starts with %" GST_FOURCC_FORMAT,
7109             GST_FOURCC_ARGS (QT_FOURCC (fourcc)));
7110         if (demux->mdatbuffer)
7111           demux->mdatbuffer = gst_buffer_append (demux->mdatbuffer, buf);
7112         else
7113           demux->mdatbuffer = buf;
7114         demux->offset += demux->neededbytes;
7115         demux->neededbytes = 16;
7116         demux->state = QTDEMUX_STATE_INITIAL;
7117         gst_qtdemux_post_progress (demux, 1, 1);
7118
7119         break;
7120       }
7121       case QTDEMUX_STATE_MOVIE:{
7122         QtDemuxStream *stream = NULL;
7123         QtDemuxSample *sample;
7124         GstClockTime dts, pts, duration;
7125         gboolean keyframe;
7126         GList *iter;
7127
7128         GST_DEBUG_OBJECT (demux,
7129             "BEGIN // in MOVIE for offset %" G_GUINT64_FORMAT, demux->offset);
7130
7131         if (demux->fragmented) {
7132           GST_DEBUG_OBJECT (demux, "mdat remaining %" G_GUINT64_FORMAT,
7133               demux->mdatleft);
7134           if (G_LIKELY (demux->todrop < demux->mdatleft)) {
7135             /* if needed data starts within this atom,
7136              * then it should not exceed this atom */
7137             if (G_UNLIKELY (demux->neededbytes > demux->mdatleft)) {
7138               GST_ELEMENT_ERROR (demux, STREAM, DEMUX,
7139                   (_("This file is invalid and cannot be played.")),
7140                   ("sample data crosses atom boundary"));
7141               ret = GST_FLOW_ERROR;
7142               break;
7143             }
7144             demux->mdatleft -= demux->neededbytes;
7145           } else {
7146             GST_DEBUG_OBJECT (demux, "data atom emptied; resuming atom scan");
7147             /* so we are dropping more than left in this atom */
7148             gst_qtdemux_drop_data (demux, demux->mdatleft);
7149             demux->mdatleft = 0;
7150
7151             /* need to resume atom parsing so we do not miss any other pieces */
7152             demux->state = QTDEMUX_STATE_INITIAL;
7153             demux->neededbytes = 16;
7154
7155             /* check if there was any stored post mdat data from previous buffers */
7156             if (demux->restoredata_buffer) {
7157               g_assert (gst_adapter_available (demux->adapter) == 0);
7158
7159               gst_adapter_push (demux->adapter, demux->restoredata_buffer);
7160               demux->restoredata_buffer = NULL;
7161               demux->offset = demux->restoredata_offset;
7162             }
7163
7164             break;
7165           }
7166         }
7167
7168         if (demux->todrop) {
7169           if (demux->cenc_aux_info_offset > 0) {
7170             GstByteReader br;
7171             const guint8 *data;
7172
7173             GST_DEBUG_OBJECT (demux, "parsing cenc auxiliary info");
7174             data = gst_adapter_map (demux->adapter, demux->todrop);
7175             gst_byte_reader_init (&br, data + 8, demux->todrop);
7176             if (!qtdemux_parse_cenc_aux_info (demux,
7177                     QTDEMUX_FIRST_STREAM (demux), &br,
7178                     demux->cenc_aux_info_sizes, demux->cenc_aux_sample_count)) {
7179               GST_ERROR_OBJECT (demux, "failed to parse cenc auxiliary info");
7180               ret = GST_FLOW_ERROR;
7181               gst_adapter_unmap (demux->adapter);
7182               g_free (demux->cenc_aux_info_sizes);
7183               demux->cenc_aux_info_sizes = NULL;
7184               goto done;
7185             }
7186             demux->cenc_aux_info_offset = 0;
7187             g_free (demux->cenc_aux_info_sizes);
7188             demux->cenc_aux_info_sizes = NULL;
7189             gst_adapter_unmap (demux->adapter);
7190           }
7191           gst_qtdemux_drop_data (demux, demux->todrop);
7192         }
7193
7194         /* first buffer? */
7195         /* initial newsegment sent here after having added pads,
7196          * possible others in sink_event */
7197         gst_qtdemux_check_send_pending_segment (demux);
7198
7199         /* Figure out which stream this packet belongs to */
7200         for (iter = demux->active_streams; iter; iter = g_list_next (iter)) {
7201           stream = QTDEMUX_STREAM (iter->data);
7202           if (stream->sample_index >= stream->n_samples) {
7203             /* reset to be checked below G_UNLIKELY (stream == NULL) */
7204             stream = NULL;
7205             continue;
7206           }
7207           GST_LOG_OBJECT (demux,
7208               "Checking track-id %u (sample_index:%d / offset:%"
7209               G_GUINT64_FORMAT " / size:%d)", stream->track_id,
7210               stream->sample_index,
7211               stream->samples[stream->sample_index].offset,
7212               stream->samples[stream->sample_index].size);
7213
7214           if (stream->samples[stream->sample_index].offset == demux->offset)
7215             break;
7216         }
7217
7218         if (G_UNLIKELY (stream == NULL))
7219           goto unknown_stream;
7220
7221         gst_qtdemux_stream_check_and_change_stsd_index (demux, stream);
7222
7223         if (stream->new_caps) {
7224           gst_qtdemux_configure_stream (demux, stream);
7225         }
7226
7227         /* Put data in a buffer, set timestamps, caps, ... */
7228         sample = &stream->samples[stream->sample_index];
7229
7230         if (G_LIKELY (!(STREAM_IS_EOS (stream)))) {
7231           GST_DEBUG_OBJECT (demux, "stream : %" GST_FOURCC_FORMAT,
7232               GST_FOURCC_ARGS (CUR_STREAM (stream)->fourcc));
7233
7234           dts = QTSAMPLE_DTS (stream, sample);
7235           pts = QTSAMPLE_PTS (stream, sample);
7236           duration = QTSAMPLE_DUR_DTS (stream, sample, dts);
7237           keyframe = QTSAMPLE_KEYFRAME (stream, sample);
7238
7239           /* check for segment end */
7240           if (G_UNLIKELY (demux->segment.stop != -1
7241                   && demux->segment.stop <= pts && stream->on_keyframe)
7242               && !(demux->upstream_format_is_time && demux->segment.rate < 0)) {
7243             GST_DEBUG_OBJECT (demux, "we reached the end of our segment.");
7244             stream->time_position = GST_CLOCK_TIME_NONE;        /* this means EOS */
7245
7246             /* skip this data, stream is EOS */
7247             gst_adapter_flush (demux->adapter, demux->neededbytes);
7248             demux->offset += demux->neededbytes;
7249
7250             /* check if all streams are eos */
7251             ret = GST_FLOW_EOS;
7252             for (iter = demux->active_streams; iter; iter = g_list_next (iter)) {
7253               if (!STREAM_IS_EOS (QTDEMUX_STREAM (iter->data))) {
7254                 ret = GST_FLOW_OK;
7255                 break;
7256               }
7257             }
7258           } else {
7259             GstBuffer *outbuf;
7260
7261             outbuf =
7262                 gst_adapter_take_buffer (demux->adapter, demux->neededbytes);
7263
7264             /* FIXME: should either be an assert or a plain check */
7265             g_return_val_if_fail (outbuf != NULL, GST_FLOW_ERROR);
7266
7267             ret = gst_qtdemux_decorate_and_push_buffer (demux, stream, outbuf,
7268                 dts, pts, duration, keyframe, dts, demux->offset);
7269           }
7270
7271           /* combine flows */
7272           ret = gst_qtdemux_combine_flows (demux, stream, ret);
7273         } else {
7274           /* skip this data, stream is EOS */
7275           gst_adapter_flush (demux->adapter, demux->neededbytes);
7276         }
7277
7278         stream->sample_index++;
7279         stream->offset_in_sample = 0;
7280
7281         /* update current offset and figure out size of next buffer */
7282         GST_LOG_OBJECT (demux, "increasing offset %" G_GUINT64_FORMAT " by %u",
7283             demux->offset, demux->neededbytes);
7284         demux->offset += demux->neededbytes;
7285         GST_LOG_OBJECT (demux, "offset is now %" G_GUINT64_FORMAT,
7286             demux->offset);
7287
7288
7289         if (ret == GST_FLOW_EOS) {
7290           GST_DEBUG_OBJECT (demux, "All streams are EOS, signal upstream");
7291           demux->neededbytes = -1;
7292           goto eos;
7293         }
7294
7295         if ((demux->neededbytes = next_entry_size (demux)) == -1) {
7296           if (demux->fragmented) {
7297             GST_DEBUG_OBJECT (demux, "(temporarily) out of fragmented samples");
7298             /* there may be more to follow, only finish this atom */
7299             demux->todrop = demux->mdatleft;
7300             demux->neededbytes = demux->todrop;
7301             break;
7302           }
7303           goto eos;
7304         }
7305         if (ret != GST_FLOW_OK && ret != GST_FLOW_NOT_LINKED) {
7306           goto non_ok_unlinked_flow;
7307         }
7308         break;
7309       }
7310       default:
7311         goto invalid_state;
7312     }
7313   }
7314
7315   /* when buffering movie data, at least show user something is happening */
7316   if (ret == GST_FLOW_OK && demux->state == QTDEMUX_STATE_BUFFER_MDAT &&
7317       gst_adapter_available (demux->adapter) <= demux->neededbytes) {
7318     gst_qtdemux_post_progress (demux, gst_adapter_available (demux->adapter),
7319         demux->neededbytes);
7320   }
7321 done:
7322
7323   return ret;
7324
7325   /* ERRORS */
7326 non_ok_unlinked_flow:
7327   {
7328     GST_DEBUG_OBJECT (demux, "Stopping, combined return flow %s",
7329         gst_flow_get_name (ret));
7330     return ret;
7331   }
7332 unknown_stream:
7333   {
7334     GST_ELEMENT_ERROR (demux, STREAM, FAILED, (NULL), ("unknown stream found"));
7335     ret = GST_FLOW_ERROR;
7336     goto done;
7337   }
7338 eos:
7339   {
7340     GST_DEBUG_OBJECT (demux, "no next entry, EOS");
7341     ret = GST_FLOW_EOS;
7342     goto done;
7343   }
7344 invalid_state:
7345   {
7346     GST_ELEMENT_ERROR (demux, STREAM, FAILED,
7347         (NULL), ("qtdemuxer invalid state %d", demux->state));
7348     ret = GST_FLOW_ERROR;
7349     goto done;
7350   }
7351 no_moov:
7352   {
7353     GST_ELEMENT_ERROR (demux, STREAM, FAILED,
7354         (NULL), ("no 'moov' atom within the first 10 MB"));
7355     ret = GST_FLOW_ERROR;
7356     goto done;
7357   }
7358 }
7359
7360 static gboolean
7361 qtdemux_sink_activate (GstPad * sinkpad, GstObject * parent)
7362 {
7363   GstQuery *query;
7364   gboolean pull_mode;
7365
7366   query = gst_query_new_scheduling ();
7367
7368   if (!gst_pad_peer_query (sinkpad, query)) {
7369     gst_query_unref (query);
7370     goto activate_push;
7371   }
7372
7373   pull_mode = gst_query_has_scheduling_mode_with_flags (query,
7374       GST_PAD_MODE_PULL, GST_SCHEDULING_FLAG_SEEKABLE);
7375   gst_query_unref (query);
7376
7377   if (!pull_mode)
7378     goto activate_push;
7379
7380   GST_DEBUG_OBJECT (sinkpad, "activating pull");
7381   return gst_pad_activate_mode (sinkpad, GST_PAD_MODE_PULL, TRUE);
7382
7383 activate_push:
7384   {
7385     GST_DEBUG_OBJECT (sinkpad, "activating push");
7386     return gst_pad_activate_mode (sinkpad, GST_PAD_MODE_PUSH, TRUE);
7387   }
7388 }
7389
7390 static gboolean
7391 qtdemux_sink_activate_mode (GstPad * sinkpad, GstObject * parent,
7392     GstPadMode mode, gboolean active)
7393 {
7394   gboolean res;
7395   GstQTDemux *demux = GST_QTDEMUX (parent);
7396
7397   switch (mode) {
7398     case GST_PAD_MODE_PUSH:
7399       demux->pullbased = FALSE;
7400       res = TRUE;
7401       break;
7402     case GST_PAD_MODE_PULL:
7403       if (active) {
7404         demux->pullbased = TRUE;
7405         res = gst_pad_start_task (sinkpad, (GstTaskFunction) gst_qtdemux_loop,
7406             sinkpad, NULL);
7407       } else {
7408         res = gst_pad_stop_task (sinkpad);
7409       }
7410       break;
7411     default:
7412       res = FALSE;
7413       break;
7414   }
7415   return res;
7416 }
7417
7418 #ifdef HAVE_ZLIB
7419 static void *
7420 qtdemux_inflate (void *z_buffer, guint z_length, guint * length)
7421 {
7422   guint8 *buffer;
7423   z_stream z;
7424   int ret;
7425
7426   memset (&z, 0, sizeof (z));
7427   z.zalloc = NULL;
7428   z.zfree = NULL;
7429   z.opaque = NULL;
7430
7431   if ((ret = inflateInit (&z)) != Z_OK) {
7432     GST_ERROR ("inflateInit() returned %d", ret);
7433     return NULL;
7434   }
7435
7436   z.next_in = z_buffer;
7437   z.avail_in = z_length;
7438
7439   buffer = (guint8 *) g_malloc (*length);
7440   z.avail_out = *length;
7441   z.next_out = (Bytef *) buffer;
7442   do {
7443     ret = inflate (&z, Z_NO_FLUSH);
7444     if (ret == Z_STREAM_END) {
7445       break;
7446     } else if (ret != Z_OK) {
7447       GST_WARNING ("inflate() returned %d", ret);
7448       break;
7449     }
7450
7451     *length += 4096;
7452     buffer = (guint8 *) g_realloc (buffer, *length);
7453     z.next_out = (Bytef *) (buffer + z.total_out);
7454     z.avail_out += 4096;
7455   } while (z.avail_in > 0);
7456
7457   if (ret != Z_STREAM_END) {
7458     g_free (buffer);
7459     buffer = NULL;
7460     *length = 0;
7461   } else {
7462     *length = z.total_out;
7463   }
7464
7465   inflateEnd (&z);
7466
7467   return buffer;
7468 }
7469 #endif /* HAVE_ZLIB */
7470
7471 static gboolean
7472 qtdemux_parse_moov (GstQTDemux * qtdemux, const guint8 * buffer, guint length)
7473 {
7474   GNode *cmov;
7475
7476   qtdemux->moov_node = g_node_new ((guint8 *) buffer);
7477
7478   /* counts as header data */
7479   qtdemux->header_size += length;
7480
7481   GST_DEBUG_OBJECT (qtdemux, "parsing 'moov' atom");
7482   qtdemux_parse_node (qtdemux, qtdemux->moov_node, buffer, length);
7483
7484   cmov = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_cmov);
7485   if (cmov) {
7486     guint32 method;
7487     GNode *dcom;
7488     GNode *cmvd;
7489     guint32 dcom_len;
7490
7491     dcom = qtdemux_tree_get_child_by_type (cmov, FOURCC_dcom);
7492     cmvd = qtdemux_tree_get_child_by_type (cmov, FOURCC_cmvd);
7493     if (dcom == NULL || cmvd == NULL)
7494       goto invalid_compression;
7495
7496     dcom_len = QT_UINT32 (dcom->data);
7497     if (dcom_len < 12)
7498       goto invalid_compression;
7499
7500     method = QT_FOURCC ((guint8 *) dcom->data + 8);
7501     switch (method) {
7502 #ifdef HAVE_ZLIB
7503       case FOURCC_zlib:{
7504         guint uncompressed_length;
7505         guint compressed_length;
7506         guint8 *buf;
7507         guint32 cmvd_len;
7508
7509         cmvd_len = QT_UINT32 ((guint8 *) cmvd->data);
7510         if (cmvd_len < 12)
7511           goto invalid_compression;
7512
7513         uncompressed_length = QT_UINT32 ((guint8 *) cmvd->data + 8);
7514         compressed_length = cmvd_len - 12;
7515         GST_LOG ("length = %u", uncompressed_length);
7516
7517         buf =
7518             (guint8 *) qtdemux_inflate ((guint8 *) cmvd->data + 12,
7519             compressed_length, &uncompressed_length);
7520
7521         if (buf) {
7522           qtdemux->moov_node_compressed = qtdemux->moov_node;
7523           qtdemux->moov_node = g_node_new (buf);
7524
7525           qtdemux_parse_node (qtdemux, qtdemux->moov_node, buf,
7526               uncompressed_length);
7527         }
7528         break;
7529       }
7530 #endif /* HAVE_ZLIB */
7531       default:
7532         GST_WARNING_OBJECT (qtdemux, "unknown or unhandled header compression "
7533             "type %" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (method));
7534         break;
7535     }
7536   }
7537   return TRUE;
7538
7539   /* ERRORS */
7540 invalid_compression:
7541   {
7542     GST_ERROR_OBJECT (qtdemux, "invalid compressed header");
7543     return FALSE;
7544   }
7545 }
7546
7547 static gboolean
7548 qtdemux_parse_container (GstQTDemux * qtdemux, GNode * node, const guint8 * buf,
7549     const guint8 * end)
7550 {
7551   while (G_UNLIKELY (buf < end)) {
7552     GNode *child;
7553     guint32 len;
7554
7555     if (G_UNLIKELY (buf + 4 > end)) {
7556       GST_LOG_OBJECT (qtdemux, "buffer overrun");
7557       break;
7558     }
7559     len = QT_UINT32 (buf);
7560     if (G_UNLIKELY (len == 0)) {
7561       GST_LOG_OBJECT (qtdemux, "empty container");
7562       break;
7563     }
7564     if (G_UNLIKELY (len < 8)) {
7565       GST_WARNING_OBJECT (qtdemux, "length too short (%d < 8)", len);
7566       break;
7567     }
7568     if (G_UNLIKELY (len > (end - buf))) {
7569       GST_WARNING_OBJECT (qtdemux, "length too long (%d > %d)", len,
7570           (gint) (end - buf));
7571       break;
7572     }
7573
7574     child = g_node_new ((guint8 *) buf);
7575     g_node_append (node, child);
7576     GST_LOG_OBJECT (qtdemux, "adding new node of len %d", len);
7577     qtdemux_parse_node (qtdemux, child, buf, len);
7578
7579     buf += len;
7580   }
7581   return TRUE;
7582 }
7583
7584 static gboolean
7585 qtdemux_parse_theora_extension (GstQTDemux * qtdemux, QtDemuxStream * stream,
7586     GNode * xdxt)
7587 {
7588   int len = QT_UINT32 (xdxt->data);
7589   guint8 *buf = xdxt->data;
7590   guint8 *end = buf + len;
7591   GstBuffer *buffer;
7592
7593   /* skip size and type */
7594   buf += 8;
7595   end -= 8;
7596
7597   while (buf < end) {
7598     gint size;
7599     guint32 type;
7600
7601     size = QT_UINT32 (buf);
7602     type = QT_FOURCC (buf + 4);
7603
7604     GST_LOG_OBJECT (qtdemux, "%p %p", buf, end);
7605
7606     if (buf + size > end || size <= 0)
7607       break;
7608
7609     buf += 8;
7610     size -= 8;
7611
7612     GST_WARNING_OBJECT (qtdemux, "have cookie %" GST_FOURCC_FORMAT,
7613         GST_FOURCC_ARGS (type));
7614
7615     switch (type) {
7616       case FOURCC_tCtH:
7617         buffer = gst_buffer_new_and_alloc (size);
7618         gst_buffer_fill (buffer, 0, buf, size);
7619         stream->buffers = g_slist_append (stream->buffers, buffer);
7620         GST_LOG_OBJECT (qtdemux, "parsing theora header");
7621         break;
7622       case FOURCC_tCt_:
7623         buffer = gst_buffer_new_and_alloc (size);
7624         gst_buffer_fill (buffer, 0, buf, size);
7625         stream->buffers = g_slist_append (stream->buffers, buffer);
7626         GST_LOG_OBJECT (qtdemux, "parsing theora comment");
7627         break;
7628       case FOURCC_tCtC:
7629         buffer = gst_buffer_new_and_alloc (size);
7630         gst_buffer_fill (buffer, 0, buf, size);
7631         stream->buffers = g_slist_append (stream->buffers, buffer);
7632         GST_LOG_OBJECT (qtdemux, "parsing theora codebook");
7633         break;
7634       default:
7635         GST_WARNING_OBJECT (qtdemux,
7636             "unknown theora cookie %" GST_FOURCC_FORMAT,
7637             GST_FOURCC_ARGS (type));
7638         break;
7639     }
7640     buf += size;
7641   }
7642   return TRUE;
7643 }
7644
7645 static gboolean
7646 qtdemux_parse_node (GstQTDemux * qtdemux, GNode * node, const guint8 * buffer,
7647     guint length)
7648 {
7649   guint32 fourcc = 0;
7650   guint32 node_length = 0;
7651   const QtNodeType *type;
7652   const guint8 *end;
7653
7654   GST_LOG_OBJECT (qtdemux, "qtdemux_parse buffer %p length %u", buffer, length);
7655
7656   if (G_UNLIKELY (length < 8))
7657     goto not_enough_data;
7658
7659   node_length = QT_UINT32 (buffer);
7660   fourcc = QT_FOURCC (buffer + 4);
7661
7662   /* ignore empty nodes */
7663   if (G_UNLIKELY (fourcc == 0 || node_length == 8))
7664     return TRUE;
7665
7666   type = qtdemux_type_get (fourcc);
7667
7668   end = buffer + length;
7669
7670   GST_LOG_OBJECT (qtdemux,
7671       "parsing '%" GST_FOURCC_FORMAT "', length=%u, name '%s'",
7672       GST_FOURCC_ARGS (fourcc), node_length, type->name);
7673
7674   if (node_length > length)
7675     goto broken_atom_size;
7676
7677   if (type->flags & QT_FLAG_CONTAINER) {
7678     qtdemux_parse_container (qtdemux, node, buffer + 8, end);
7679   } else {
7680     switch (fourcc) {
7681       case FOURCC_stsd:
7682       {
7683         if (node_length < 20) {
7684           GST_LOG_OBJECT (qtdemux, "skipping small stsd box");
7685           break;
7686         }
7687         GST_DEBUG_OBJECT (qtdemux,
7688             "parsing stsd (sample table, sample description) atom");
7689         /* Skip over 8 byte atom hdr + 1 byte version, 3 bytes flags, 4 byte num_entries */
7690         qtdemux_parse_container (qtdemux, node, buffer + 16, end);
7691         break;
7692       }
7693       case FOURCC_mp4a:
7694       case FOURCC_alac:
7695       case FOURCC_fLaC:
7696       {
7697         guint32 version;
7698         guint32 offset;
7699         guint min_size;
7700
7701         /* also read alac (or whatever) in stead of mp4a in the following,
7702          * since a similar layout is used in other cases as well */
7703         if (fourcc == FOURCC_mp4a)
7704           min_size = 20;
7705         else if (fourcc == FOURCC_fLaC)
7706           min_size = 86;
7707         else
7708           min_size = 40;
7709
7710         /* There are two things we might encounter here: a true mp4a atom, and
7711            an mp4a entry in an stsd atom. The latter is what we're interested
7712            in, and it looks like an atom, but isn't really one. The true mp4a
7713            atom is short, so we detect it based on length here. */
7714         if (length < min_size) {
7715           GST_LOG_OBJECT (qtdemux, "skipping small %" GST_FOURCC_FORMAT " box",
7716               GST_FOURCC_ARGS (fourcc));
7717           break;
7718         }
7719
7720         /* 'version' here is the sound sample description version. Types 0 and
7721            1 are documented in the QTFF reference, but type 2 is not: it's
7722            described in Apple header files instead (struct SoundDescriptionV2
7723            in Movies.h) */
7724         version = QT_UINT16 (buffer + 16);
7725
7726         GST_DEBUG_OBJECT (qtdemux, "%" GST_FOURCC_FORMAT " version 0x%08x",
7727             GST_FOURCC_ARGS (fourcc), version);
7728
7729         /* parse any esds descriptors */
7730         switch (version) {
7731           case 0:
7732             offset = 0x24;
7733             break;
7734           case 1:
7735             offset = 0x34;
7736             break;
7737           case 2:
7738             offset = 0x48;
7739             break;
7740           default:
7741             GST_WARNING_OBJECT (qtdemux,
7742                 "unhandled %" GST_FOURCC_FORMAT " version 0x%08x",
7743                 GST_FOURCC_ARGS (fourcc), version);
7744             offset = 0;
7745             break;
7746         }
7747         if (offset)
7748           qtdemux_parse_container (qtdemux, node, buffer + offset, end);
7749         break;
7750       }
7751       case FOURCC_mp4v:
7752       case FOURCC_MP4V:
7753       case FOURCC_fmp4:
7754       case FOURCC_FMP4:
7755       case FOURCC_apcs:
7756       case FOURCC_apch:
7757       case FOURCC_apcn:
7758       case FOURCC_apco:
7759       case FOURCC_ap4h:
7760       case FOURCC_xvid:
7761       case FOURCC_XVID:
7762       case FOURCC_H264:
7763       case FOURCC_avc1:
7764       case FOURCC_avc3:
7765       case FOURCC_H265:
7766       case FOURCC_hvc1:
7767       case FOURCC_hev1:
7768       case FOURCC_mjp2:
7769       case FOURCC_encv:
7770       {
7771         guint32 version;
7772         guint32 str_len;
7773
7774         /* codec_data is contained inside these atoms, which all have
7775          * the same format. */
7776         /* video sample description size is 86 bytes without extension.
7777          * node_length have to be bigger than 86 bytes because video sample
7778          * description can include extenstions such as esds, fiel, glbl, etc. */
7779         if (node_length < 86) {
7780           GST_WARNING_OBJECT (qtdemux, "%" GST_FOURCC_FORMAT
7781               " sample description length too short (%u < 86)",
7782               GST_FOURCC_ARGS (fourcc), node_length);
7783           break;
7784         }
7785
7786         GST_DEBUG_OBJECT (qtdemux, "parsing in %" GST_FOURCC_FORMAT,
7787             GST_FOURCC_ARGS (fourcc));
7788
7789         /* version (2 bytes) : this is set to 0, unless a compressor has changed
7790          *              its data format.
7791          * revision level (2 bytes) : must be set to 0. */
7792         version = QT_UINT32 (buffer + 16);
7793         GST_DEBUG_OBJECT (qtdemux, "version %08x", version);
7794
7795         /* compressor name : PASCAL string and informative purposes
7796          * first byte : the number of bytes to be displayed.
7797          *              it has to be less than 32 because it is reserved
7798          *              space of 32 bytes total including itself. */
7799         str_len = QT_UINT8 (buffer + 50);
7800         if (str_len < 32)
7801           GST_DEBUG_OBJECT (qtdemux, "compressorname = %.*s", str_len,
7802               (char *) buffer + 51);
7803         else
7804           GST_WARNING_OBJECT (qtdemux,
7805               "compressorname length too big (%u > 31)", str_len);
7806
7807         GST_MEMDUMP_OBJECT (qtdemux, "video sample description", buffer,
7808             end - buffer);
7809         qtdemux_parse_container (qtdemux, node, buffer + 86, end);
7810         break;
7811       }
7812       case FOURCC_meta:
7813       {
7814         GST_DEBUG_OBJECT (qtdemux, "parsing meta atom");
7815
7816         /* You are reading this correctly. QTFF specifies that the
7817          * metadata atom is a short atom, whereas ISO BMFF specifies
7818          * it's a full atom. But since so many people are doing things
7819          * differently, we actually peek into the atom to see which
7820          * variant it is */
7821         if (length < 16) {
7822           GST_LOG_OBJECT (qtdemux, "skipping small %" GST_FOURCC_FORMAT " box",
7823               GST_FOURCC_ARGS (fourcc));
7824           break;
7825         }
7826         if (QT_FOURCC (buffer + 12) == FOURCC_hdlr) {
7827           /* Variant 1: What QTFF specifies. 'meta' is a short header which
7828            * starts with a 'hdlr' atom */
7829           qtdemux_parse_container (qtdemux, node, buffer + 8, end);
7830         } else if (QT_UINT32 (buffer + 8) == 0x00000000) {
7831           /* Variant 2: What ISO BMFF specifies. 'meta' is a _full_ atom
7832            * with version/flags both set to zero */
7833           qtdemux_parse_container (qtdemux, node, buffer + 12, end);
7834         } else
7835           GST_WARNING_OBJECT (qtdemux, "Unknown 'meta' atom format");
7836         break;
7837       }
7838       case FOURCC_mp4s:
7839       {
7840         GST_MEMDUMP_OBJECT (qtdemux, "mp4s", buffer, end - buffer);
7841         /* Skip 8 byte header, plus 8 byte version + flags + entry_count */
7842         qtdemux_parse_container (qtdemux, node, buffer + 16, end);
7843         break;
7844       }
7845       case FOURCC_XiTh:
7846       {
7847         guint32 version;
7848         guint32 offset;
7849
7850         if (length < 16) {
7851           GST_LOG_OBJECT (qtdemux, "skipping small %" GST_FOURCC_FORMAT " box",
7852               GST_FOURCC_ARGS (fourcc));
7853           break;
7854         }
7855
7856         version = QT_UINT32 (buffer + 12);
7857         GST_DEBUG_OBJECT (qtdemux, "parsing XiTh atom version 0x%08x", version);
7858
7859         switch (version) {
7860           case 0x00000001:
7861             offset = 0x62;
7862             break;
7863           default:
7864             GST_DEBUG_OBJECT (qtdemux, "unknown version 0x%08x", version);
7865             offset = 0;
7866             break;
7867         }
7868         if (offset) {
7869           if (length < offset) {
7870             GST_WARNING_OBJECT (qtdemux,
7871                 "skipping too small %" GST_FOURCC_FORMAT " box",
7872                 GST_FOURCC_ARGS (fourcc));
7873             break;
7874           }
7875           qtdemux_parse_container (qtdemux, node, buffer + offset, end);
7876         }
7877         break;
7878       }
7879       case FOURCC_in24:
7880       {
7881         qtdemux_parse_container (qtdemux, node, buffer + 0x34, end);
7882         break;
7883       }
7884       case FOURCC_uuid:
7885       {
7886         qtdemux_parse_uuid (qtdemux, buffer, end - buffer);
7887         break;
7888       }
7889       case FOURCC_enca:
7890       {
7891         qtdemux_parse_container (qtdemux, node, buffer + 36, end);
7892         break;
7893       }
7894       default:
7895         if (!strcmp (type->name, "unknown"))
7896           GST_MEMDUMP ("Unknown tag", buffer + 4, end - buffer - 4);
7897         break;
7898     }
7899   }
7900   GST_LOG_OBJECT (qtdemux, "parsed '%" GST_FOURCC_FORMAT "'",
7901       GST_FOURCC_ARGS (fourcc));
7902   return TRUE;
7903
7904 /* ERRORS */
7905 not_enough_data:
7906   {
7907     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
7908         (_("This file is corrupt and cannot be played.")),
7909         ("Not enough data for an atom header, got only %u bytes", length));
7910     return FALSE;
7911   }
7912 broken_atom_size:
7913   {
7914     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
7915         (_("This file is corrupt and cannot be played.")),
7916         ("Atom '%" GST_FOURCC_FORMAT "' has size of %u bytes, but we have only "
7917             "%u bytes available.", GST_FOURCC_ARGS (fourcc), node_length,
7918             length));
7919     return FALSE;
7920   }
7921 }
7922
7923 static GNode *
7924 qtdemux_tree_get_child_by_type (GNode * node, guint32 fourcc)
7925 {
7926   GNode *child;
7927   guint8 *buffer;
7928   guint32 child_fourcc;
7929
7930   for (child = g_node_first_child (node); child;
7931       child = g_node_next_sibling (child)) {
7932     buffer = (guint8 *) child->data;
7933
7934     child_fourcc = QT_FOURCC (buffer + 4);
7935
7936     if (G_UNLIKELY (child_fourcc == fourcc)) {
7937       return child;
7938     }
7939   }
7940   return NULL;
7941 }
7942
7943 static GNode *
7944 qtdemux_tree_get_child_by_type_full (GNode * node, guint32 fourcc,
7945     GstByteReader * parser)
7946 {
7947   GNode *child;
7948   guint8 *buffer;
7949   guint32 child_fourcc, child_len;
7950
7951   for (child = g_node_first_child (node); child;
7952       child = g_node_next_sibling (child)) {
7953     buffer = (guint8 *) child->data;
7954
7955     child_len = QT_UINT32 (buffer);
7956     child_fourcc = QT_FOURCC (buffer + 4);
7957
7958     if (G_UNLIKELY (child_fourcc == fourcc)) {
7959       if (G_UNLIKELY (child_len < (4 + 4)))
7960         return NULL;
7961       /* FIXME: must verify if atom length < parent atom length */
7962       gst_byte_reader_init (parser, buffer + (4 + 4), child_len - (4 + 4));
7963       return child;
7964     }
7965   }
7966   return NULL;
7967 }
7968
7969 static GNode *
7970 qtdemux_tree_get_child_by_index (GNode * node, guint index)
7971 {
7972   return g_node_nth_child (node, index);
7973 }
7974
7975 static GNode *
7976 qtdemux_tree_get_sibling_by_type_full (GNode * node, guint32 fourcc,
7977     GstByteReader * parser)
7978 {
7979   GNode *child;
7980   guint8 *buffer;
7981   guint32 child_fourcc, child_len;
7982
7983   for (child = g_node_next_sibling (node); child;
7984       child = g_node_next_sibling (child)) {
7985     buffer = (guint8 *) child->data;
7986
7987     child_fourcc = QT_FOURCC (buffer + 4);
7988
7989     if (child_fourcc == fourcc) {
7990       if (parser) {
7991         child_len = QT_UINT32 (buffer);
7992         if (G_UNLIKELY (child_len < (4 + 4)))
7993           return NULL;
7994         /* FIXME: must verify if atom length < parent atom length */
7995         gst_byte_reader_init (parser, buffer + (4 + 4), child_len - (4 + 4));
7996       }
7997       return child;
7998     }
7999   }
8000   return NULL;
8001 }
8002
8003 static GNode *
8004 qtdemux_tree_get_sibling_by_type (GNode * node, guint32 fourcc)
8005 {
8006   return qtdemux_tree_get_sibling_by_type_full (node, fourcc, NULL);
8007 }
8008
8009 static void
8010 qtdemux_do_allocation (GstQTDemux * qtdemux, QtDemuxStream * stream)
8011 {
8012 /* FIXME: This can only reliably work if demuxers have a
8013  * separate streaming thread per srcpad. This should be
8014  * done in a demuxer base class, which integrates parts
8015  * of multiqueue
8016  *
8017  * https://bugzilla.gnome.org/show_bug.cgi?id=701856
8018  */
8019 #if 0
8020   GstQuery *query;
8021
8022   query = gst_query_new_allocation (stream->caps, FALSE);
8023
8024   if (!gst_pad_peer_query (stream->pad, query)) {
8025     /* not a problem, just debug a little */
8026     GST_DEBUG_OBJECT (qtdemux, "peer ALLOCATION query failed");
8027   }
8028
8029   if (stream->allocator)
8030     gst_object_unref (stream->allocator);
8031
8032   if (gst_query_get_n_allocation_params (query) > 0) {
8033     /* try the allocator */
8034     gst_query_parse_nth_allocation_param (query, 0, &stream->allocator,
8035         &stream->params);
8036     stream->use_allocator = TRUE;
8037   } else {
8038     stream->allocator = NULL;
8039     gst_allocation_params_init (&stream->params);
8040     stream->use_allocator = FALSE;
8041   }
8042   gst_query_unref (query);
8043 #endif
8044 }
8045
8046 static gboolean
8047 pad_query (const GValue * item, GValue * value, gpointer user_data)
8048 {
8049   GstPad *pad = g_value_get_object (item);
8050   GstQuery *query = user_data;
8051   gboolean res;
8052
8053   res = gst_pad_peer_query (pad, query);
8054
8055   if (res) {
8056     g_value_set_boolean (value, TRUE);
8057     return FALSE;
8058   }
8059
8060   GST_INFO_OBJECT (pad, "pad peer query failed");
8061   return TRUE;
8062 }
8063
8064 static gboolean
8065 gst_qtdemux_run_query (GstElement * element, GstQuery * query,
8066     GstPadDirection direction)
8067 {
8068   GstIterator *it;
8069   GstIteratorFoldFunction func = pad_query;
8070   GValue res = { 0, };
8071
8072   g_value_init (&res, G_TYPE_BOOLEAN);
8073   g_value_set_boolean (&res, FALSE);
8074
8075   /* Ask neighbor */
8076   if (direction == GST_PAD_SRC)
8077     it = gst_element_iterate_src_pads (element);
8078   else
8079     it = gst_element_iterate_sink_pads (element);
8080
8081   while (gst_iterator_fold (it, func, &res, query) == GST_ITERATOR_RESYNC)
8082     gst_iterator_resync (it);
8083
8084   gst_iterator_free (it);
8085
8086   return g_value_get_boolean (&res);
8087 }
8088
8089 static void
8090 gst_qtdemux_request_protection_context (GstQTDemux * qtdemux,
8091     QtDemuxStream * stream)
8092 {
8093   GstQuery *query;
8094   GstContext *ctxt;
8095   GstElement *element = GST_ELEMENT (qtdemux);
8096   GstStructure *st;
8097   gchar **filtered_sys_ids;
8098   GValue event_list = G_VALUE_INIT;
8099   GList *walk;
8100
8101   /* 1. Check if we already have the context. */
8102   if (qtdemux->preferred_protection_system_id != NULL) {
8103     GST_LOG_OBJECT (element,
8104         "already have the protection context, no need to request it again");
8105     return;
8106   }
8107
8108   g_ptr_array_add (qtdemux->protection_system_ids, NULL);
8109   filtered_sys_ids = gst_protection_filter_systems_by_available_decryptors (
8110       (const gchar **) qtdemux->protection_system_ids->pdata);
8111
8112   g_ptr_array_remove_index (qtdemux->protection_system_ids,
8113       qtdemux->protection_system_ids->len - 1);
8114   GST_TRACE_OBJECT (qtdemux, "detected %u protection systems, we have "
8115       "decryptors for %u of them, running context request",
8116       qtdemux->protection_system_ids->len,
8117       filtered_sys_ids ? g_strv_length (filtered_sys_ids) : 0);
8118
8119
8120   if (stream->protection_scheme_event_queue.length) {
8121     GST_TRACE_OBJECT (qtdemux, "using stream event queue, length %u",
8122         stream->protection_scheme_event_queue.length);
8123     walk = stream->protection_scheme_event_queue.tail;
8124   } else {
8125     GST_TRACE_OBJECT (qtdemux, "using demuxer event queue, length %u",
8126         qtdemux->protection_event_queue.length);
8127     walk = qtdemux->protection_event_queue.tail;
8128   }
8129
8130   g_value_init (&event_list, GST_TYPE_LIST);
8131   for (; walk; walk = g_list_previous (walk)) {
8132     GValue *event_value = g_new0 (GValue, 1);
8133     g_value_init (event_value, GST_TYPE_EVENT);
8134     g_value_set_boxed (event_value, walk->data);
8135     gst_value_list_append_and_take_value (&event_list, event_value);
8136   }
8137
8138   /*  2a) Query downstream with GST_QUERY_CONTEXT for the context and
8139    *      check if downstream already has a context of the specific type
8140    *  2b) Query upstream as above.
8141    */
8142   query = gst_query_new_context ("drm-preferred-decryption-system-id");
8143   st = gst_query_writable_structure (query);
8144   gst_structure_set (st, "track-id", G_TYPE_UINT, stream->track_id,
8145       "available-stream-encryption-systems", G_TYPE_STRV, filtered_sys_ids,
8146       NULL);
8147   gst_structure_set_value (st, "stream-encryption-events", &event_list);
8148   if (gst_qtdemux_run_query (element, query, GST_PAD_SRC)) {
8149     gst_query_parse_context (query, &ctxt);
8150     GST_INFO_OBJECT (element, "found context (%p) in downstream query", ctxt);
8151     gst_element_set_context (element, ctxt);
8152   } else if (gst_qtdemux_run_query (element, query, GST_PAD_SINK)) {
8153     gst_query_parse_context (query, &ctxt);
8154     GST_INFO_OBJECT (element, "found context (%p) in upstream query", ctxt);
8155     gst_element_set_context (element, ctxt);
8156   } else {
8157     /* 3) Post a GST_MESSAGE_NEED_CONTEXT message on the bus with
8158      *    the required context type and afterwards check if a
8159      *    usable context was set now as in 1). The message could
8160      *    be handled by the parent bins of the element and the
8161      *    application.
8162      */
8163     GstMessage *msg;
8164
8165     GST_INFO_OBJECT (element, "posting need context message");
8166     msg = gst_message_new_need_context (GST_OBJECT_CAST (element),
8167         "drm-preferred-decryption-system-id");
8168     st = (GstStructure *) gst_message_get_structure (msg);
8169     gst_structure_set (st, "track-id", G_TYPE_UINT, stream->track_id,
8170         "available-stream-encryption-systems", G_TYPE_STRV, filtered_sys_ids,
8171         NULL);
8172
8173     gst_structure_set_value (st, "stream-encryption-events", &event_list);
8174     gst_element_post_message (element, msg);
8175   }
8176
8177   g_strfreev (filtered_sys_ids);
8178   g_value_unset (&event_list);
8179   gst_query_unref (query);
8180 }
8181
8182 static gboolean
8183 gst_qtdemux_configure_protected_caps (GstQTDemux * qtdemux,
8184     QtDemuxStream * stream)
8185 {
8186   GstStructure *s;
8187   const gchar *selected_system = NULL;
8188
8189   g_return_val_if_fail (qtdemux != NULL, FALSE);
8190   g_return_val_if_fail (stream != NULL, FALSE);
8191   g_return_val_if_fail (gst_caps_get_size (CUR_STREAM (stream)->caps) == 1,
8192       FALSE);
8193
8194   if (stream->protection_scheme_type != FOURCC_cenc) {
8195     GST_ERROR_OBJECT (qtdemux,
8196         "unsupported protection scheme: %" GST_FOURCC_FORMAT,
8197         GST_FOURCC_ARGS (stream->protection_scheme_type));
8198     return FALSE;
8199   }
8200   if (qtdemux->protection_system_ids == NULL) {
8201     GST_ERROR_OBJECT (qtdemux, "stream is protected using cenc, but no "
8202         "cenc protection system information has been found");
8203     return FALSE;
8204   }
8205
8206   gst_qtdemux_request_protection_context (qtdemux, stream);
8207   if (qtdemux->preferred_protection_system_id != NULL) {
8208     const gchar *preferred_system_array[] =
8209         { qtdemux->preferred_protection_system_id, NULL };
8210
8211     selected_system = gst_protection_select_system (preferred_system_array);
8212
8213     if (selected_system) {
8214       GST_TRACE_OBJECT (qtdemux, "selected preferred system %s",
8215           qtdemux->preferred_protection_system_id);
8216     } else {
8217       GST_WARNING_OBJECT (qtdemux, "could not select preferred system %s "
8218           "because there is no available decryptor",
8219           qtdemux->preferred_protection_system_id);
8220     }
8221   }
8222
8223   if (!selected_system) {
8224     g_ptr_array_add (qtdemux->protection_system_ids, NULL);
8225     selected_system = gst_protection_select_system ((const gchar **)
8226         qtdemux->protection_system_ids->pdata);
8227     g_ptr_array_remove_index (qtdemux->protection_system_ids,
8228         qtdemux->protection_system_ids->len - 1);
8229   }
8230
8231   if (!selected_system) {
8232     GST_ERROR_OBJECT (qtdemux, "stream is protected, but no "
8233         "suitable decryptor element has been found");
8234     return FALSE;
8235   }
8236
8237   GST_DEBUG_OBJECT (qtdemux, "selected protection system is %s",
8238       selected_system);
8239
8240   s = gst_caps_get_structure (CUR_STREAM (stream)->caps, 0);
8241   if (!gst_structure_has_name (s, "application/x-cenc")) {
8242     gst_structure_set (s,
8243         "original-media-type", G_TYPE_STRING, gst_structure_get_name (s),
8244         GST_PROTECTION_SYSTEM_ID_CAPS_FIELD, G_TYPE_STRING, selected_system,
8245         NULL);
8246     gst_structure_set_name (s, "application/x-cenc");
8247   }
8248   return TRUE;
8249 }
8250
8251 static gboolean
8252 gst_qtdemux_configure_stream (GstQTDemux * qtdemux, QtDemuxStream * stream)
8253 {
8254   if (stream->subtype == FOURCC_vide) {
8255     /* fps is calculated base on the duration of the average framerate since
8256      * qt does not have a fixed framerate. */
8257     gboolean fps_available = TRUE;
8258     guint32 first_duration = 0;
8259
8260     if (stream->n_samples > 0)
8261       first_duration = stream->samples[0].duration;
8262
8263     if ((stream->n_samples == 1 && first_duration == 0)
8264         || (qtdemux->fragmented && stream->n_samples_moof == 1)) {
8265       /* still frame */
8266       CUR_STREAM (stream)->fps_n = 0;
8267       CUR_STREAM (stream)->fps_d = 1;
8268     } else {
8269       if (stream->duration == 0 || stream->n_samples < 2) {
8270         CUR_STREAM (stream)->fps_n = stream->timescale;
8271         CUR_STREAM (stream)->fps_d = 1;
8272         fps_available = FALSE;
8273       } else {
8274         GstClockTime avg_duration;
8275         guint64 duration;
8276         guint32 n_samples;
8277
8278         /* duration and n_samples can be updated for fragmented format
8279          * so, framerate of fragmented format is calculated using data in a moof */
8280         if (qtdemux->fragmented && stream->n_samples_moof > 0
8281             && stream->duration_moof > 0) {
8282           n_samples = stream->n_samples_moof;
8283           duration = stream->duration_moof;
8284         } else {
8285           n_samples = stream->n_samples;
8286           duration = stream->duration;
8287         }
8288
8289         /* Calculate a framerate, ignoring the first sample which is sometimes truncated */
8290         /* stream->duration is guint64, timescale, n_samples are guint32 */
8291         avg_duration =
8292             gst_util_uint64_scale_round (duration -
8293             first_duration, GST_SECOND,
8294             (guint64) (stream->timescale) * (n_samples - 1));
8295
8296         GST_LOG_OBJECT (qtdemux,
8297             "Calculating avg sample duration based on stream (or moof) duration %"
8298             G_GUINT64_FORMAT
8299             " minus first sample %u, leaving %d samples gives %"
8300             GST_TIME_FORMAT, duration, first_duration,
8301             n_samples - 1, GST_TIME_ARGS (avg_duration));
8302
8303         gst_video_guess_framerate (avg_duration, &CUR_STREAM (stream)->fps_n,
8304             &CUR_STREAM (stream)->fps_d);
8305
8306         GST_DEBUG_OBJECT (qtdemux,
8307             "Calculating framerate, timescale %u gave fps_n %d fps_d %d",
8308             stream->timescale, CUR_STREAM (stream)->fps_n,
8309             CUR_STREAM (stream)->fps_d);
8310       }
8311     }
8312
8313     if (CUR_STREAM (stream)->caps) {
8314       CUR_STREAM (stream)->caps =
8315           gst_caps_make_writable (CUR_STREAM (stream)->caps);
8316
8317       gst_caps_set_simple (CUR_STREAM (stream)->caps,
8318           "width", G_TYPE_INT, CUR_STREAM (stream)->width,
8319           "height", G_TYPE_INT, CUR_STREAM (stream)->height, NULL);
8320
8321       /* set framerate if calculated framerate is reliable */
8322       if (fps_available) {
8323         gst_caps_set_simple (CUR_STREAM (stream)->caps,
8324             "framerate", GST_TYPE_FRACTION, CUR_STREAM (stream)->fps_n,
8325             CUR_STREAM (stream)->fps_d, NULL);
8326       }
8327
8328       /* calculate pixel-aspect-ratio using display width and height */
8329       GST_DEBUG_OBJECT (qtdemux,
8330           "video size %dx%d, target display size %dx%d",
8331           CUR_STREAM (stream)->width, CUR_STREAM (stream)->height,
8332           stream->display_width, stream->display_height);
8333       /* qt file might have pasp atom */
8334       if (CUR_STREAM (stream)->par_w > 0 && CUR_STREAM (stream)->par_h > 0) {
8335         GST_DEBUG_OBJECT (qtdemux, "par %d:%d", CUR_STREAM (stream)->par_w,
8336             CUR_STREAM (stream)->par_h);
8337         gst_caps_set_simple (CUR_STREAM (stream)->caps, "pixel-aspect-ratio",
8338             GST_TYPE_FRACTION, CUR_STREAM (stream)->par_w,
8339             CUR_STREAM (stream)->par_h, NULL);
8340       } else if (stream->display_width > 0 && stream->display_height > 0
8341           && CUR_STREAM (stream)->width > 0
8342           && CUR_STREAM (stream)->height > 0) {
8343         gint n, d;
8344
8345         /* calculate the pixel aspect ratio using the display and pixel w/h */
8346         n = stream->display_width * CUR_STREAM (stream)->height;
8347         d = stream->display_height * CUR_STREAM (stream)->width;
8348         if (n == d)
8349           n = d = 1;
8350         GST_DEBUG_OBJECT (qtdemux, "setting PAR to %d/%d", n, d);
8351         CUR_STREAM (stream)->par_w = n;
8352         CUR_STREAM (stream)->par_h = d;
8353         gst_caps_set_simple (CUR_STREAM (stream)->caps, "pixel-aspect-ratio",
8354             GST_TYPE_FRACTION, CUR_STREAM (stream)->par_w,
8355             CUR_STREAM (stream)->par_h, NULL);
8356       }
8357
8358       if (CUR_STREAM (stream)->interlace_mode > 0) {
8359         if (CUR_STREAM (stream)->interlace_mode == 1) {
8360           gst_caps_set_simple (CUR_STREAM (stream)->caps, "interlace-mode",
8361               G_TYPE_STRING, "progressive", NULL);
8362         } else if (CUR_STREAM (stream)->interlace_mode == 2) {
8363           gst_caps_set_simple (CUR_STREAM (stream)->caps, "interlace-mode",
8364               G_TYPE_STRING, "interleaved", NULL);
8365           if (CUR_STREAM (stream)->field_order == 9) {
8366             gst_caps_set_simple (CUR_STREAM (stream)->caps, "field-order",
8367                 G_TYPE_STRING, "top-field-first", NULL);
8368           } else if (CUR_STREAM (stream)->field_order == 14) {
8369             gst_caps_set_simple (CUR_STREAM (stream)->caps, "field-order",
8370                 G_TYPE_STRING, "bottom-field-first", NULL);
8371           }
8372         }
8373       }
8374
8375       /* Create incomplete colorimetry here if needed */
8376       if (CUR_STREAM (stream)->colorimetry.range ||
8377           CUR_STREAM (stream)->colorimetry.matrix ||
8378           CUR_STREAM (stream)->colorimetry.transfer
8379           || CUR_STREAM (stream)->colorimetry.primaries) {
8380         gchar *colorimetry =
8381             gst_video_colorimetry_to_string (&CUR_STREAM (stream)->colorimetry);
8382         gst_caps_set_simple (CUR_STREAM (stream)->caps, "colorimetry",
8383             G_TYPE_STRING, colorimetry, NULL);
8384         g_free (colorimetry);
8385       }
8386
8387       if (stream->multiview_mode != GST_VIDEO_MULTIVIEW_MODE_NONE) {
8388         guint par_w = 1, par_h = 1;
8389
8390         if (CUR_STREAM (stream)->par_w > 0 && CUR_STREAM (stream)->par_h > 0) {
8391           par_w = CUR_STREAM (stream)->par_w;
8392           par_h = CUR_STREAM (stream)->par_h;
8393         }
8394
8395         if (gst_video_multiview_guess_half_aspect (stream->multiview_mode,
8396                 CUR_STREAM (stream)->width, CUR_STREAM (stream)->height, par_w,
8397                 par_h)) {
8398           stream->multiview_flags |= GST_VIDEO_MULTIVIEW_FLAGS_HALF_ASPECT;
8399         }
8400
8401         gst_caps_set_simple (CUR_STREAM (stream)->caps,
8402             "multiview-mode", G_TYPE_STRING,
8403             gst_video_multiview_mode_to_caps_string (stream->multiview_mode),
8404             "multiview-flags", GST_TYPE_VIDEO_MULTIVIEW_FLAGSET,
8405             stream->multiview_flags, GST_FLAG_SET_MASK_EXACT, NULL);
8406       }
8407     }
8408   }
8409
8410   else if (stream->subtype == FOURCC_soun) {
8411     if (CUR_STREAM (stream)->caps) {
8412       CUR_STREAM (stream)->caps =
8413           gst_caps_make_writable (CUR_STREAM (stream)->caps);
8414       if (CUR_STREAM (stream)->rate > 0)
8415         gst_caps_set_simple (CUR_STREAM (stream)->caps,
8416             "rate", G_TYPE_INT, (int) CUR_STREAM (stream)->rate, NULL);
8417       if (CUR_STREAM (stream)->n_channels > 0)
8418         gst_caps_set_simple (CUR_STREAM (stream)->caps,
8419             "channels", G_TYPE_INT, CUR_STREAM (stream)->n_channels, NULL);
8420       if (CUR_STREAM (stream)->n_channels > 2) {
8421         /* FIXME: Need to parse the 'chan' atom to get channel layouts
8422          * correctly; this is just the minimum we can do - assume
8423          * we don't actually have any channel positions. */
8424         gst_caps_set_simple (CUR_STREAM (stream)->caps,
8425             "channel-mask", GST_TYPE_BITMASK, G_GUINT64_CONSTANT (0), NULL);
8426       }
8427     }
8428   }
8429
8430   if (stream->pad) {
8431     GstCaps *prev_caps = NULL;
8432
8433     GST_PAD_ELEMENT_PRIVATE (stream->pad) = stream;
8434     gst_pad_set_event_function (stream->pad, gst_qtdemux_handle_src_event);
8435     gst_pad_set_query_function (stream->pad, gst_qtdemux_handle_src_query);
8436     gst_pad_set_active (stream->pad, TRUE);
8437
8438     gst_pad_use_fixed_caps (stream->pad);
8439
8440     if (stream->protected) {
8441       if (!gst_qtdemux_configure_protected_caps (qtdemux, stream)) {
8442         GST_ERROR_OBJECT (qtdemux,
8443             "Failed to configure protected stream caps.");
8444         return FALSE;
8445       }
8446     }
8447
8448     GST_DEBUG_OBJECT (qtdemux, "setting caps %" GST_PTR_FORMAT,
8449         CUR_STREAM (stream)->caps);
8450     if (stream->new_stream) {
8451       GstEvent *event;
8452       GstStreamFlags stream_flags = GST_STREAM_FLAG_NONE;
8453
8454       event =
8455           gst_pad_get_sticky_event (qtdemux->sinkpad, GST_EVENT_STREAM_START,
8456           0);
8457       if (event) {
8458         gst_event_parse_stream_flags (event, &stream_flags);
8459         if (gst_event_parse_group_id (event, &qtdemux->group_id))
8460           qtdemux->have_group_id = TRUE;
8461         else
8462           qtdemux->have_group_id = FALSE;
8463         gst_event_unref (event);
8464       } else if (!qtdemux->have_group_id) {
8465         qtdemux->have_group_id = TRUE;
8466         qtdemux->group_id = gst_util_group_id_next ();
8467       }
8468
8469       stream->new_stream = FALSE;
8470       event = gst_event_new_stream_start (stream->stream_id);
8471       if (qtdemux->have_group_id)
8472         gst_event_set_group_id (event, qtdemux->group_id);
8473       if (stream->disabled)
8474         stream_flags |= GST_STREAM_FLAG_UNSELECT;
8475       if (CUR_STREAM (stream)->sparse) {
8476         stream_flags |= GST_STREAM_FLAG_SPARSE;
8477       } else {
8478         stream_flags &= ~GST_STREAM_FLAG_SPARSE;
8479       }
8480       gst_event_set_stream_flags (event, stream_flags);
8481       gst_pad_push_event (stream->pad, event);
8482     }
8483
8484     prev_caps = gst_pad_get_current_caps (stream->pad);
8485
8486     if (CUR_STREAM (stream)->caps) {
8487       if (!prev_caps
8488           || !gst_caps_is_equal_fixed (prev_caps, CUR_STREAM (stream)->caps)) {
8489         GST_DEBUG_OBJECT (qtdemux, "setting caps %" GST_PTR_FORMAT,
8490             CUR_STREAM (stream)->caps);
8491         gst_pad_set_caps (stream->pad, CUR_STREAM (stream)->caps);
8492       } else {
8493         GST_DEBUG_OBJECT (qtdemux, "ignore duplicated caps");
8494       }
8495     } else {
8496       GST_WARNING_OBJECT (qtdemux, "stream without caps");
8497     }
8498
8499     if (prev_caps)
8500       gst_caps_unref (prev_caps);
8501     stream->new_caps = FALSE;
8502   }
8503   return TRUE;
8504 }
8505
8506 static void
8507 gst_qtdemux_stream_check_and_change_stsd_index (GstQTDemux * demux,
8508     QtDemuxStream * stream)
8509 {
8510   if (stream->cur_stsd_entry_index == stream->stsd_sample_description_id)
8511     return;
8512
8513   GST_DEBUG_OBJECT (stream->pad, "Changing stsd index from '%u' to '%u'",
8514       stream->cur_stsd_entry_index, stream->stsd_sample_description_id);
8515   if (G_UNLIKELY (stream->stsd_sample_description_id >=
8516           stream->stsd_entries_length)) {
8517     GST_ELEMENT_ERROR (demux, STREAM, DEMUX,
8518         (_("This file is invalid and cannot be played.")),
8519         ("New sample description id is out of bounds (%d >= %d)",
8520             stream->stsd_sample_description_id, stream->stsd_entries_length));
8521   } else {
8522     stream->cur_stsd_entry_index = stream->stsd_sample_description_id;
8523     stream->new_caps = TRUE;
8524   }
8525 }
8526
8527 static gboolean
8528 gst_qtdemux_add_stream (GstQTDemux * qtdemux,
8529     QtDemuxStream * stream, GstTagList * list)
8530 {
8531   gboolean ret = TRUE;
8532   /* consistent default for push based mode */
8533   gst_segment_init (&stream->segment, GST_FORMAT_TIME);
8534
8535   if (stream->subtype == FOURCC_vide) {
8536     gchar *name = g_strdup_printf ("video_%u", qtdemux->n_video_streams);
8537
8538     stream->pad =
8539         gst_pad_new_from_static_template (&gst_qtdemux_videosrc_template, name);
8540     g_free (name);
8541
8542     if (!gst_qtdemux_configure_stream (qtdemux, stream)) {
8543       gst_object_unref (stream->pad);
8544       stream->pad = NULL;
8545       ret = FALSE;
8546       goto done;
8547     }
8548
8549     qtdemux->n_video_streams++;
8550   } else if (stream->subtype == FOURCC_soun) {
8551     gchar *name = g_strdup_printf ("audio_%u", qtdemux->n_audio_streams);
8552
8553     stream->pad =
8554         gst_pad_new_from_static_template (&gst_qtdemux_audiosrc_template, name);
8555     g_free (name);
8556     if (!gst_qtdemux_configure_stream (qtdemux, stream)) {
8557       gst_object_unref (stream->pad);
8558       stream->pad = NULL;
8559       ret = FALSE;
8560       goto done;
8561     }
8562     qtdemux->n_audio_streams++;
8563   } else if (stream->subtype == FOURCC_strm) {
8564     GST_DEBUG_OBJECT (qtdemux, "stream type, not creating pad");
8565   } else if (stream->subtype == FOURCC_subp || stream->subtype == FOURCC_text
8566       || stream->subtype == FOURCC_sbtl || stream->subtype == FOURCC_subt
8567       || stream->subtype == FOURCC_clcp) {
8568     gchar *name = g_strdup_printf ("subtitle_%u", qtdemux->n_sub_streams);
8569
8570     stream->pad =
8571         gst_pad_new_from_static_template (&gst_qtdemux_subsrc_template, name);
8572     g_free (name);
8573     if (!gst_qtdemux_configure_stream (qtdemux, stream)) {
8574       gst_object_unref (stream->pad);
8575       stream->pad = NULL;
8576       ret = FALSE;
8577       goto done;
8578     }
8579     qtdemux->n_sub_streams++;
8580   } else if (CUR_STREAM (stream)->caps) {
8581     gchar *name = g_strdup_printf ("video_%u", qtdemux->n_video_streams);
8582
8583     stream->pad =
8584         gst_pad_new_from_static_template (&gst_qtdemux_videosrc_template, name);
8585     g_free (name);
8586     if (!gst_qtdemux_configure_stream (qtdemux, stream)) {
8587       gst_object_unref (stream->pad);
8588       stream->pad = NULL;
8589       ret = FALSE;
8590       goto done;
8591     }
8592     qtdemux->n_video_streams++;
8593   } else {
8594     GST_DEBUG_OBJECT (qtdemux, "unknown stream type");
8595     goto done;
8596   }
8597
8598   if (stream->pad) {
8599     GList *l;
8600
8601     GST_DEBUG_OBJECT (qtdemux, "adding pad %s %p to qtdemux %p",
8602         GST_OBJECT_NAME (stream->pad), stream->pad, qtdemux);
8603     gst_element_add_pad (GST_ELEMENT_CAST (qtdemux), stream->pad);
8604     gst_flow_combiner_add_pad (qtdemux->flowcombiner, stream->pad);
8605
8606     if (stream->stream_tags)
8607       gst_tag_list_unref (stream->stream_tags);
8608     stream->stream_tags = list;
8609     list = NULL;
8610     /* global tags go on each pad anyway */
8611     stream->send_global_tags = TRUE;
8612     /* send upstream GST_EVENT_PROTECTION events that were received before
8613        this source pad was created */
8614     for (l = qtdemux->protection_event_queue.head; l != NULL; l = l->next)
8615       gst_pad_push_event (stream->pad, gst_event_ref (l->data));
8616   }
8617 done:
8618   if (list)
8619     gst_tag_list_unref (list);
8620   return ret;
8621 }
8622
8623 /* find next atom with @fourcc starting at @offset */
8624 static GstFlowReturn
8625 qtdemux_find_atom (GstQTDemux * qtdemux, guint64 * offset,
8626     guint64 * length, guint32 fourcc)
8627 {
8628   GstFlowReturn ret;
8629   guint32 lfourcc;
8630   GstBuffer *buf;
8631
8632   GST_LOG_OBJECT (qtdemux, "finding fourcc %" GST_FOURCC_FORMAT " at offset %"
8633       G_GUINT64_FORMAT, GST_FOURCC_ARGS (fourcc), *offset);
8634
8635   while (TRUE) {
8636     GstMapInfo map;
8637
8638     buf = NULL;
8639     ret = gst_pad_pull_range (qtdemux->sinkpad, *offset, 16, &buf);
8640     if (G_UNLIKELY (ret != GST_FLOW_OK))
8641       goto locate_failed;
8642     if (G_UNLIKELY (gst_buffer_get_size (buf) != 16)) {
8643       /* likely EOF */
8644       ret = GST_FLOW_EOS;
8645       gst_buffer_unref (buf);
8646       goto locate_failed;
8647     }
8648     gst_buffer_map (buf, &map, GST_MAP_READ);
8649     extract_initial_length_and_fourcc (map.data, 16, length, &lfourcc);
8650     gst_buffer_unmap (buf, &map);
8651     gst_buffer_unref (buf);
8652
8653     if (G_UNLIKELY (*length == 0)) {
8654       GST_DEBUG_OBJECT (qtdemux, "invalid length 0");
8655       ret = GST_FLOW_ERROR;
8656       goto locate_failed;
8657     }
8658
8659     if (lfourcc == fourcc) {
8660       GST_DEBUG_OBJECT (qtdemux, "found fourcc at offset %" G_GUINT64_FORMAT,
8661           *offset);
8662       break;
8663     } else {
8664       GST_LOG_OBJECT (qtdemux,
8665           "skipping atom '%" GST_FOURCC_FORMAT "' at %" G_GUINT64_FORMAT,
8666           GST_FOURCC_ARGS (fourcc), *offset);
8667       *offset += *length;
8668     }
8669   }
8670
8671   return GST_FLOW_OK;
8672
8673 locate_failed:
8674   {
8675     /* might simply have had last one */
8676     GST_DEBUG_OBJECT (qtdemux, "fourcc not found");
8677     return ret;
8678   }
8679 }
8680
8681 /* should only do something in pull mode */
8682 /* call with OBJECT lock */
8683 static GstFlowReturn
8684 qtdemux_add_fragmented_samples (GstQTDemux * qtdemux)
8685 {
8686   guint64 length, offset;
8687   GstBuffer *buf = NULL;
8688   GstFlowReturn ret = GST_FLOW_OK;
8689   GstFlowReturn res = GST_FLOW_OK;
8690   GstMapInfo map;
8691
8692   offset = qtdemux->moof_offset;
8693   GST_DEBUG_OBJECT (qtdemux, "next moof at offset %" G_GUINT64_FORMAT, offset);
8694
8695   if (!offset) {
8696     GST_DEBUG_OBJECT (qtdemux, "no next moof");
8697     return GST_FLOW_EOS;
8698   }
8699
8700   /* best not do pull etc with lock held */
8701   GST_OBJECT_UNLOCK (qtdemux);
8702
8703   ret = qtdemux_find_atom (qtdemux, &offset, &length, FOURCC_moof);
8704   if (ret != GST_FLOW_OK)
8705     goto flow_failed;
8706
8707   ret = gst_qtdemux_pull_atom (qtdemux, offset, length, &buf);
8708   if (G_UNLIKELY (ret != GST_FLOW_OK))
8709     goto flow_failed;
8710   gst_buffer_map (buf, &map, GST_MAP_READ);
8711   if (!qtdemux_parse_moof (qtdemux, map.data, map.size, offset, NULL)) {
8712     gst_buffer_unmap (buf, &map);
8713     gst_buffer_unref (buf);
8714     buf = NULL;
8715     goto parse_failed;
8716   }
8717
8718   gst_buffer_unmap (buf, &map);
8719   gst_buffer_unref (buf);
8720   buf = NULL;
8721
8722   offset += length;
8723   /* look for next moof */
8724   ret = qtdemux_find_atom (qtdemux, &offset, &length, FOURCC_moof);
8725   if (G_UNLIKELY (ret != GST_FLOW_OK))
8726     goto flow_failed;
8727
8728 exit:
8729   GST_OBJECT_LOCK (qtdemux);
8730
8731   qtdemux->moof_offset = offset;
8732
8733   return res;
8734
8735 parse_failed:
8736   {
8737     GST_DEBUG_OBJECT (qtdemux, "failed to parse moof");
8738     offset = 0;
8739     res = GST_FLOW_ERROR;
8740     goto exit;
8741   }
8742 flow_failed:
8743   {
8744     /* maybe upstream temporarily flushing */
8745     if (ret != GST_FLOW_FLUSHING) {
8746       GST_DEBUG_OBJECT (qtdemux, "no next moof");
8747       offset = 0;
8748     } else {
8749       GST_DEBUG_OBJECT (qtdemux, "upstream WRONG_STATE");
8750       /* resume at current position next time */
8751     }
8752     res = ret;
8753     goto exit;
8754   }
8755 }
8756
8757 /* initialise bytereaders for stbl sub-atoms */
8758 static gboolean
8759 qtdemux_stbl_init (GstQTDemux * qtdemux, QtDemuxStream * stream, GNode * stbl)
8760 {
8761   stream->stbl_index = -1;      /* no samples have yet been parsed */
8762   stream->sample_index = -1;
8763
8764   /* time-to-sample atom */
8765   if (!qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stts, &stream->stts))
8766     goto corrupt_file;
8767
8768   /* copy atom data into a new buffer for later use */
8769   stream->stts.data = g_memdup (stream->stts.data, stream->stts.size);
8770
8771   /* skip version + flags */
8772   if (!gst_byte_reader_skip (&stream->stts, 1 + 3) ||
8773       !gst_byte_reader_get_uint32_be (&stream->stts, &stream->n_sample_times))
8774     goto corrupt_file;
8775   GST_LOG_OBJECT (qtdemux, "%u timestamp blocks", stream->n_sample_times);
8776
8777   /* make sure there's enough data */
8778   if (!qt_atom_parser_has_chunks (&stream->stts, stream->n_sample_times, 8)) {
8779     stream->n_sample_times = gst_byte_reader_get_remaining (&stream->stts) / 8;
8780     GST_LOG_OBJECT (qtdemux, "overriding to %u timestamp blocks",
8781         stream->n_sample_times);
8782     if (!stream->n_sample_times)
8783       goto corrupt_file;
8784   }
8785
8786   /* sync sample atom */
8787   stream->stps_present = FALSE;
8788   if ((stream->stss_present =
8789           ! !qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stss,
8790               &stream->stss) ? TRUE : FALSE) == TRUE) {
8791     /* copy atom data into a new buffer for later use */
8792     stream->stss.data = g_memdup (stream->stss.data, stream->stss.size);
8793
8794     /* skip version + flags */
8795     if (!gst_byte_reader_skip (&stream->stss, 1 + 3) ||
8796         !gst_byte_reader_get_uint32_be (&stream->stss, &stream->n_sample_syncs))
8797       goto corrupt_file;
8798
8799     if (stream->n_sample_syncs) {
8800       /* make sure there's enough data */
8801       if (!qt_atom_parser_has_chunks (&stream->stss, stream->n_sample_syncs, 4))
8802         goto corrupt_file;
8803     }
8804
8805     /* partial sync sample atom */
8806     if ((stream->stps_present =
8807             ! !qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stps,
8808                 &stream->stps) ? TRUE : FALSE) == TRUE) {
8809       /* copy atom data into a new buffer for later use */
8810       stream->stps.data = g_memdup (stream->stps.data, stream->stps.size);
8811
8812       /* skip version + flags */
8813       if (!gst_byte_reader_skip (&stream->stps, 1 + 3) ||
8814           !gst_byte_reader_get_uint32_be (&stream->stps,
8815               &stream->n_sample_partial_syncs))
8816         goto corrupt_file;
8817
8818       /* if there are no entries, the stss table contains the real
8819        * sync samples */
8820       if (stream->n_sample_partial_syncs) {
8821         /* make sure there's enough data */
8822         if (!qt_atom_parser_has_chunks (&stream->stps,
8823                 stream->n_sample_partial_syncs, 4))
8824           goto corrupt_file;
8825       }
8826     }
8827   }
8828
8829   /* sample size */
8830   if (!qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stsz, &stream->stsz))
8831     goto no_samples;
8832
8833   /* copy atom data into a new buffer for later use */
8834   stream->stsz.data = g_memdup (stream->stsz.data, stream->stsz.size);
8835
8836   /* skip version + flags */
8837   if (!gst_byte_reader_skip (&stream->stsz, 1 + 3) ||
8838       !gst_byte_reader_get_uint32_be (&stream->stsz, &stream->sample_size))
8839     goto corrupt_file;
8840
8841   if (!gst_byte_reader_get_uint32_be (&stream->stsz, &stream->n_samples))
8842     goto corrupt_file;
8843
8844   if (!stream->n_samples)
8845     goto no_samples;
8846
8847   /* sample-to-chunk atom */
8848   if (!qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stsc, &stream->stsc))
8849     goto corrupt_file;
8850
8851   /* copy atom data into a new buffer for later use */
8852   stream->stsc.data = g_memdup (stream->stsc.data, stream->stsc.size);
8853
8854   /* skip version + flags */
8855   if (!gst_byte_reader_skip (&stream->stsc, 1 + 3) ||
8856       !gst_byte_reader_get_uint32_be (&stream->stsc,
8857           &stream->n_samples_per_chunk))
8858     goto corrupt_file;
8859
8860   GST_DEBUG_OBJECT (qtdemux, "n_samples_per_chunk %u",
8861       stream->n_samples_per_chunk);
8862
8863   /* make sure there's enough data */
8864   if (!qt_atom_parser_has_chunks (&stream->stsc, stream->n_samples_per_chunk,
8865           12))
8866     goto corrupt_file;
8867
8868
8869   /* chunk offset */
8870   if (qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stco, &stream->stco))
8871     stream->co_size = sizeof (guint32);
8872   else if (qtdemux_tree_get_child_by_type_full (stbl, FOURCC_co64,
8873           &stream->stco))
8874     stream->co_size = sizeof (guint64);
8875   else
8876     goto corrupt_file;
8877
8878   /* copy atom data into a new buffer for later use */
8879   stream->stco.data = g_memdup (stream->stco.data, stream->stco.size);
8880
8881   /* skip version + flags */
8882   if (!gst_byte_reader_skip (&stream->stco, 1 + 3))
8883     goto corrupt_file;
8884
8885   /* chunks_are_samples == TRUE means treat chunks as samples */
8886   stream->chunks_are_samples = stream->sample_size
8887       && !CUR_STREAM (stream)->sampled;
8888   if (stream->chunks_are_samples) {
8889     /* treat chunks as samples */
8890     if (!gst_byte_reader_get_uint32_be (&stream->stco, &stream->n_samples))
8891       goto corrupt_file;
8892   } else {
8893     /* skip number of entries */
8894     if (!gst_byte_reader_skip (&stream->stco, 4))
8895       goto corrupt_file;
8896
8897     /* make sure there are enough data in the stsz atom */
8898     if (!stream->sample_size) {
8899       /* different sizes for each sample */
8900       if (!qt_atom_parser_has_chunks (&stream->stsz, stream->n_samples, 4))
8901         goto corrupt_file;
8902     }
8903   }
8904
8905   GST_DEBUG_OBJECT (qtdemux, "allocating n_samples %u * %u (%.2f MB)",
8906       stream->n_samples, (guint) sizeof (QtDemuxSample),
8907       stream->n_samples * sizeof (QtDemuxSample) / (1024.0 * 1024.0));
8908
8909   if (stream->n_samples >=
8910       QTDEMUX_MAX_SAMPLE_INDEX_SIZE / sizeof (QtDemuxSample)) {
8911     GST_WARNING_OBJECT (qtdemux, "not allocating index of %d samples, would "
8912         "be larger than %uMB (broken file?)", stream->n_samples,
8913         QTDEMUX_MAX_SAMPLE_INDEX_SIZE >> 20);
8914     return FALSE;
8915   }
8916
8917   g_assert (stream->samples == NULL);
8918   stream->samples = g_try_new0 (QtDemuxSample, stream->n_samples);
8919   if (!stream->samples) {
8920     GST_WARNING_OBJECT (qtdemux, "failed to allocate %d samples",
8921         stream->n_samples);
8922     return FALSE;
8923   }
8924
8925   /* composition time-to-sample */
8926   if ((stream->ctts_present =
8927           ! !qtdemux_tree_get_child_by_type_full (stbl, FOURCC_ctts,
8928               &stream->ctts) ? TRUE : FALSE) == TRUE) {
8929     GstByteReader cslg = GST_BYTE_READER_INIT (NULL, 0);
8930
8931     /* copy atom data into a new buffer for later use */
8932     stream->ctts.data = g_memdup (stream->ctts.data, stream->ctts.size);
8933
8934     /* skip version + flags */
8935     if (!gst_byte_reader_skip (&stream->ctts, 1 + 3)
8936         || !gst_byte_reader_get_uint32_be (&stream->ctts,
8937             &stream->n_composition_times))
8938       goto corrupt_file;
8939
8940     /* make sure there's enough data */
8941     if (!qt_atom_parser_has_chunks (&stream->ctts, stream->n_composition_times,
8942             4 + 4))
8943       goto corrupt_file;
8944
8945     /* This is optional, if missing we iterate the ctts */
8946     if (qtdemux_tree_get_child_by_type_full (stbl, FOURCC_cslg, &cslg)) {
8947       if (!gst_byte_reader_skip (&cslg, 1 + 3)
8948           || !gst_byte_reader_get_uint32_be (&cslg, &stream->cslg_shift)) {
8949         g_free ((gpointer) cslg.data);
8950         goto corrupt_file;
8951       }
8952     } else {
8953       gint32 cslg_least = 0;
8954       guint num_entries, pos;
8955       gint i;
8956
8957       pos = gst_byte_reader_get_pos (&stream->ctts);
8958       num_entries = stream->n_composition_times;
8959
8960       stream->cslg_shift = 0;
8961
8962       for (i = 0; i < num_entries; i++) {
8963         gint32 offset;
8964
8965         gst_byte_reader_skip_unchecked (&stream->ctts, 4);
8966         offset = gst_byte_reader_get_int32_be_unchecked (&stream->ctts);
8967
8968         if (offset < cslg_least)
8969           cslg_least = offset;
8970       }
8971
8972       if (cslg_least < 0)
8973         stream->cslg_shift = ABS (cslg_least);
8974       else
8975         stream->cslg_shift = 0;
8976
8977       /* reset the reader so we can generate sample table */
8978       gst_byte_reader_set_pos (&stream->ctts, pos);
8979     }
8980   } else {
8981     /* Ensure the cslg_shift value is consistent so we can use it
8982      * unconditionnally to produce TS and Segment */
8983     stream->cslg_shift = 0;
8984   }
8985
8986   return TRUE;
8987
8988 corrupt_file:
8989   {
8990     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
8991         (_("This file is corrupt and cannot be played.")), (NULL));
8992     return FALSE;
8993   }
8994 no_samples:
8995   {
8996     gst_qtdemux_stbl_free (stream);
8997     if (!qtdemux->fragmented) {
8998       /* not quite good */
8999       GST_WARNING_OBJECT (qtdemux, "stream has no samples");
9000       return FALSE;
9001     } else {
9002       /* may pick up samples elsewhere */
9003       return TRUE;
9004     }
9005   }
9006 }
9007
9008 /* collect samples from the next sample to be parsed up to sample @n for @stream
9009  * by reading the info from @stbl
9010  *
9011  * This code can be executed from both the streaming thread and the seeking
9012  * thread so it takes the object lock to protect itself
9013  */
9014 static gboolean
9015 qtdemux_parse_samples (GstQTDemux * qtdemux, QtDemuxStream * stream, guint32 n)
9016 {
9017   gint i, j, k;
9018   QtDemuxSample *samples, *first, *cur, *last;
9019   guint32 n_samples_per_chunk;
9020   guint32 n_samples;
9021
9022   GST_LOG_OBJECT (qtdemux, "parsing samples for stream fourcc %"
9023       GST_FOURCC_FORMAT ", pad %s",
9024       GST_FOURCC_ARGS (CUR_STREAM (stream)->fourcc),
9025       stream->pad ? GST_PAD_NAME (stream->pad) : "(NULL)");
9026
9027   n_samples = stream->n_samples;
9028
9029   if (n >= n_samples)
9030     goto out_of_samples;
9031
9032   GST_OBJECT_LOCK (qtdemux);
9033   if (n <= stream->stbl_index)
9034     goto already_parsed;
9035
9036   GST_DEBUG_OBJECT (qtdemux, "parsing up to sample %u", n);
9037
9038   if (!stream->stsz.data) {
9039     /* so we already parsed and passed all the moov samples;
9040      * onto fragmented ones */
9041     g_assert (qtdemux->fragmented);
9042     goto done;
9043   }
9044
9045   /* pointer to the sample table */
9046   samples = stream->samples;
9047
9048   /* starts from -1, moves to the next sample index to parse */
9049   stream->stbl_index++;
9050
9051   /* keep track of the first and last sample to fill */
9052   first = &samples[stream->stbl_index];
9053   last = &samples[n];
9054
9055   if (!stream->chunks_are_samples) {
9056     /* set the sample sizes */
9057     if (stream->sample_size == 0) {
9058       /* different sizes for each sample */
9059       for (cur = first; cur <= last; cur++) {
9060         cur->size = gst_byte_reader_get_uint32_be_unchecked (&stream->stsz);
9061         GST_LOG_OBJECT (qtdemux, "sample %d has size %u",
9062             (guint) (cur - samples), cur->size);
9063       }
9064     } else {
9065       /* samples have the same size */
9066       GST_LOG_OBJECT (qtdemux, "all samples have size %u", stream->sample_size);
9067       for (cur = first; cur <= last; cur++)
9068         cur->size = stream->sample_size;
9069     }
9070   }
9071
9072   n_samples_per_chunk = stream->n_samples_per_chunk;
9073   cur = first;
9074
9075   for (i = stream->stsc_index; i < n_samples_per_chunk; i++) {
9076     guint32 last_chunk;
9077
9078     if (stream->stsc_chunk_index >= stream->last_chunk
9079         || stream->stsc_chunk_index < stream->first_chunk) {
9080       stream->first_chunk =
9081           gst_byte_reader_get_uint32_be_unchecked (&stream->stsc);
9082       stream->samples_per_chunk =
9083           gst_byte_reader_get_uint32_be_unchecked (&stream->stsc);
9084       /* starts from 1 */
9085       stream->stsd_sample_description_id =
9086           gst_byte_reader_get_uint32_be_unchecked (&stream->stsc) - 1;
9087
9088       /* chunk numbers are counted from 1 it seems */
9089       if (G_UNLIKELY (stream->first_chunk == 0))
9090         goto corrupt_file;
9091
9092       --stream->first_chunk;
9093
9094       /* the last chunk of each entry is calculated by taking the first chunk
9095        * of the next entry; except if there is no next, where we fake it with
9096        * INT_MAX */
9097       if (G_UNLIKELY (i == (stream->n_samples_per_chunk - 1))) {
9098         stream->last_chunk = G_MAXUINT32;
9099       } else {
9100         stream->last_chunk =
9101             gst_byte_reader_peek_uint32_be_unchecked (&stream->stsc);
9102         if (G_UNLIKELY (stream->last_chunk == 0))
9103           goto corrupt_file;
9104
9105         --stream->last_chunk;
9106       }
9107
9108       GST_LOG_OBJECT (qtdemux,
9109           "entry %d has first_chunk %d, last_chunk %d, samples_per_chunk %d"
9110           "sample desc ID: %d", i, stream->first_chunk, stream->last_chunk,
9111           stream->samples_per_chunk, stream->stsd_sample_description_id);
9112
9113       if (G_UNLIKELY (stream->last_chunk < stream->first_chunk))
9114         goto corrupt_file;
9115
9116       if (stream->last_chunk != G_MAXUINT32) {
9117         if (!qt_atom_parser_peek_sub (&stream->stco,
9118                 stream->first_chunk * stream->co_size,
9119                 (stream->last_chunk - stream->first_chunk) * stream->co_size,
9120                 &stream->co_chunk))
9121           goto corrupt_file;
9122
9123       } else {
9124         stream->co_chunk = stream->stco;
9125         if (!gst_byte_reader_skip (&stream->co_chunk,
9126                 stream->first_chunk * stream->co_size))
9127           goto corrupt_file;
9128       }
9129
9130       stream->stsc_chunk_index = stream->first_chunk;
9131     }
9132
9133     last_chunk = stream->last_chunk;
9134
9135     if (stream->chunks_are_samples) {
9136       cur = &samples[stream->stsc_chunk_index];
9137
9138       for (j = stream->stsc_chunk_index; j < last_chunk; j++) {
9139         if (j > n) {
9140           /* save state */
9141           stream->stsc_chunk_index = j;
9142           goto done;
9143         }
9144
9145         cur->offset =
9146             qt_atom_parser_get_offset_unchecked (&stream->co_chunk,
9147             stream->co_size);
9148
9149         GST_LOG_OBJECT (qtdemux, "Created entry %d with offset "
9150             "%" G_GUINT64_FORMAT, j, cur->offset);
9151
9152         if (CUR_STREAM (stream)->samples_per_frame > 0 &&
9153             CUR_STREAM (stream)->bytes_per_frame > 0) {
9154           cur->size =
9155               (stream->samples_per_chunk * CUR_STREAM (stream)->n_channels) /
9156               CUR_STREAM (stream)->samples_per_frame *
9157               CUR_STREAM (stream)->bytes_per_frame;
9158         } else {
9159           cur->size = stream->samples_per_chunk;
9160         }
9161
9162         GST_DEBUG_OBJECT (qtdemux,
9163             "keyframe sample %d: timestamp %" GST_TIME_FORMAT ", size %u",
9164             j, GST_TIME_ARGS (QTSTREAMTIME_TO_GSTTIME (stream,
9165                     stream->stco_sample_index)), cur->size);
9166
9167         cur->timestamp = stream->stco_sample_index;
9168         cur->duration = stream->samples_per_chunk;
9169         cur->keyframe = TRUE;
9170         cur++;
9171
9172         stream->stco_sample_index += stream->samples_per_chunk;
9173       }
9174       stream->stsc_chunk_index = j;
9175     } else {
9176       for (j = stream->stsc_chunk_index; j < last_chunk; j++) {
9177         guint32 samples_per_chunk;
9178         guint64 chunk_offset;
9179
9180         if (!stream->stsc_sample_index
9181             && !qt_atom_parser_get_offset (&stream->co_chunk, stream->co_size,
9182                 &stream->chunk_offset))
9183           goto corrupt_file;
9184
9185         samples_per_chunk = stream->samples_per_chunk;
9186         chunk_offset = stream->chunk_offset;
9187
9188         for (k = stream->stsc_sample_index; k < samples_per_chunk; k++) {
9189           GST_LOG_OBJECT (qtdemux, "creating entry %d with offset %"
9190               G_GUINT64_FORMAT " and size %d",
9191               (guint) (cur - samples), chunk_offset, cur->size);
9192
9193           cur->offset = chunk_offset;
9194           chunk_offset += cur->size;
9195           cur++;
9196
9197           if (G_UNLIKELY (cur > last)) {
9198             /* save state */
9199             stream->stsc_sample_index = k + 1;
9200             stream->chunk_offset = chunk_offset;
9201             stream->stsc_chunk_index = j;
9202             goto done2;
9203           }
9204         }
9205         stream->stsc_sample_index = 0;
9206       }
9207       stream->stsc_chunk_index = j;
9208     }
9209     stream->stsc_index++;
9210   }
9211
9212   if (stream->chunks_are_samples)
9213     goto ctts;
9214 done2:
9215   {
9216     guint32 n_sample_times;
9217
9218     n_sample_times = stream->n_sample_times;
9219     cur = first;
9220
9221     for (i = stream->stts_index; i < n_sample_times; i++) {
9222       guint32 stts_samples;
9223       gint32 stts_duration;
9224       gint64 stts_time;
9225
9226       if (stream->stts_sample_index >= stream->stts_samples
9227           || !stream->stts_sample_index) {
9228
9229         stream->stts_samples =
9230             gst_byte_reader_get_uint32_be_unchecked (&stream->stts);
9231         stream->stts_duration =
9232             gst_byte_reader_get_uint32_be_unchecked (&stream->stts);
9233
9234         GST_LOG_OBJECT (qtdemux, "block %d, %u timestamps, duration %u",
9235             i, stream->stts_samples, stream->stts_duration);
9236
9237         stream->stts_sample_index = 0;
9238       }
9239
9240       stts_samples = stream->stts_samples;
9241       stts_duration = stream->stts_duration;
9242       stts_time = stream->stts_time;
9243
9244       for (j = stream->stts_sample_index; j < stts_samples; j++) {
9245         GST_DEBUG_OBJECT (qtdemux,
9246             "sample %d: index %d, timestamp %" GST_TIME_FORMAT,
9247             (guint) (cur - samples), j,
9248             GST_TIME_ARGS (QTSTREAMTIME_TO_GSTTIME (stream, stts_time)));
9249
9250         cur->timestamp = stts_time;
9251         cur->duration = stts_duration;
9252
9253         /* avoid 32-bit wrap-around,
9254          * but still mind possible 'negative' duration */
9255         stts_time += (gint64) stts_duration;
9256         cur++;
9257
9258         if (G_UNLIKELY (cur > last)) {
9259           /* save values */
9260           stream->stts_time = stts_time;
9261           stream->stts_sample_index = j + 1;
9262           if (stream->stts_sample_index >= stream->stts_samples)
9263             stream->stts_index++;
9264           goto done3;
9265         }
9266       }
9267       stream->stts_sample_index = 0;
9268       stream->stts_time = stts_time;
9269       stream->stts_index++;
9270     }
9271     /* fill up empty timestamps with the last timestamp, this can happen when
9272      * the last samples do not decode and so we don't have timestamps for them.
9273      * We however look at the last timestamp to estimate the track length so we
9274      * need something in here. */
9275     for (; cur < last; cur++) {
9276       GST_DEBUG_OBJECT (qtdemux,
9277           "fill sample %d: timestamp %" GST_TIME_FORMAT,
9278           (guint) (cur - samples),
9279           GST_TIME_ARGS (QTSTREAMTIME_TO_GSTTIME (stream, stream->stts_time)));
9280       cur->timestamp = stream->stts_time;
9281       cur->duration = -1;
9282     }
9283   }
9284 done3:
9285   {
9286     /* sample sync, can be NULL */
9287     if (stream->stss_present == TRUE) {
9288       guint32 n_sample_syncs;
9289
9290       n_sample_syncs = stream->n_sample_syncs;
9291
9292       if (!n_sample_syncs) {
9293         GST_DEBUG_OBJECT (qtdemux, "all samples are keyframes");
9294         stream->all_keyframe = TRUE;
9295       } else {
9296         for (i = stream->stss_index; i < n_sample_syncs; i++) {
9297           /* note that the first sample is index 1, not 0 */
9298           guint32 index;
9299
9300           index = gst_byte_reader_get_uint32_be_unchecked (&stream->stss);
9301
9302           if (G_LIKELY (index > 0 && index <= n_samples)) {
9303             index -= 1;
9304             samples[index].keyframe = TRUE;
9305             GST_DEBUG_OBJECT (qtdemux, "samples at %u is keyframe", index);
9306             /* and exit if we have enough samples */
9307             if (G_UNLIKELY (index >= n)) {
9308               i++;
9309               break;
9310             }
9311           }
9312         }
9313         /* save state */
9314         stream->stss_index = i;
9315       }
9316
9317       /* stps marks partial sync frames like open GOP I-Frames */
9318       if (stream->stps_present == TRUE) {
9319         guint32 n_sample_partial_syncs;
9320
9321         n_sample_partial_syncs = stream->n_sample_partial_syncs;
9322
9323         /* if there are no entries, the stss table contains the real
9324          * sync samples */
9325         if (n_sample_partial_syncs) {
9326           for (i = stream->stps_index; i < n_sample_partial_syncs; i++) {
9327             /* note that the first sample is index 1, not 0 */
9328             guint32 index;
9329
9330             index = gst_byte_reader_get_uint32_be_unchecked (&stream->stps);
9331
9332             if (G_LIKELY (index > 0 && index <= n_samples)) {
9333               index -= 1;
9334               samples[index].keyframe = TRUE;
9335               GST_DEBUG_OBJECT (qtdemux, "samples at %u is keyframe", index);
9336               /* and exit if we have enough samples */
9337               if (G_UNLIKELY (index >= n)) {
9338                 i++;
9339                 break;
9340               }
9341             }
9342           }
9343           /* save state */
9344           stream->stps_index = i;
9345         }
9346       }
9347     } else {
9348       /* no stss, all samples are keyframes */
9349       stream->all_keyframe = TRUE;
9350       GST_DEBUG_OBJECT (qtdemux, "setting all keyframes");
9351     }
9352   }
9353
9354 ctts:
9355   /* composition time to sample */
9356   if (stream->ctts_present == TRUE) {
9357     guint32 n_composition_times;
9358     guint32 ctts_count;
9359     gint32 ctts_soffset;
9360
9361     /* Fill in the pts_offsets */
9362     cur = first;
9363     n_composition_times = stream->n_composition_times;
9364
9365     for (i = stream->ctts_index; i < n_composition_times; i++) {
9366       if (stream->ctts_sample_index >= stream->ctts_count
9367           || !stream->ctts_sample_index) {
9368         stream->ctts_count =
9369             gst_byte_reader_get_uint32_be_unchecked (&stream->ctts);
9370         stream->ctts_soffset =
9371             gst_byte_reader_get_int32_be_unchecked (&stream->ctts);
9372         stream->ctts_sample_index = 0;
9373       }
9374
9375       ctts_count = stream->ctts_count;
9376       ctts_soffset = stream->ctts_soffset;
9377
9378       for (j = stream->ctts_sample_index; j < ctts_count; j++) {
9379         cur->pts_offset = ctts_soffset;
9380         cur++;
9381
9382         if (G_UNLIKELY (cur > last)) {
9383           /* save state */
9384           stream->ctts_sample_index = j + 1;
9385           goto done;
9386         }
9387       }
9388       stream->ctts_sample_index = 0;
9389       stream->ctts_index++;
9390     }
9391   }
9392 done:
9393   stream->stbl_index = n;
9394   /* if index has been completely parsed, free data that is no-longer needed */
9395   if (n + 1 == stream->n_samples) {
9396     gst_qtdemux_stbl_free (stream);
9397     GST_DEBUG_OBJECT (qtdemux, "parsed all available samples;");
9398     if (qtdemux->pullbased) {
9399       GST_DEBUG_OBJECT (qtdemux, "checking for more samples");
9400       while (n + 1 == stream->n_samples)
9401         if (qtdemux_add_fragmented_samples (qtdemux) != GST_FLOW_OK)
9402           break;
9403     }
9404   }
9405   GST_OBJECT_UNLOCK (qtdemux);
9406
9407   return TRUE;
9408
9409   /* SUCCESS */
9410 already_parsed:
9411   {
9412     GST_LOG_OBJECT (qtdemux,
9413         "Tried to parse up to sample %u but this sample has already been parsed",
9414         n);
9415     /* if fragmented, there may be more */
9416     if (qtdemux->fragmented && n == stream->stbl_index)
9417       goto done;
9418     GST_OBJECT_UNLOCK (qtdemux);
9419     return TRUE;
9420   }
9421   /* ERRORS */
9422 out_of_samples:
9423   {
9424     GST_LOG_OBJECT (qtdemux,
9425         "Tried to parse up to sample %u but there are only %u samples", n + 1,
9426         stream->n_samples);
9427     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
9428         (_("This file is corrupt and cannot be played.")), (NULL));
9429     return FALSE;
9430   }
9431 corrupt_file:
9432   {
9433     GST_OBJECT_UNLOCK (qtdemux);
9434     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
9435         (_("This file is corrupt and cannot be played.")), (NULL));
9436     return FALSE;
9437   }
9438 }
9439
9440 /* collect all segment info for @stream.
9441  */
9442 static gboolean
9443 qtdemux_parse_segments (GstQTDemux * qtdemux, QtDemuxStream * stream,
9444     GNode * trak)
9445 {
9446   GNode *edts;
9447   /* accept edts if they contain gaps at start and there is only
9448    * one media segment */
9449   gboolean allow_pushbased_edts = TRUE;
9450   gint media_segments_count = 0;
9451
9452   /* parse and prepare segment info from the edit list */
9453   GST_DEBUG_OBJECT (qtdemux, "looking for edit list container");
9454   stream->n_segments = 0;
9455   stream->segments = NULL;
9456   if ((edts = qtdemux_tree_get_child_by_type (trak, FOURCC_edts))) {
9457     GNode *elst;
9458     gint n_segments;
9459     gint segment_number, entry_size;
9460     guint64 time;
9461     GstClockTime stime;
9462     const guint8 *buffer;
9463     guint8 version;
9464     guint32 size;
9465
9466     GST_DEBUG_OBJECT (qtdemux, "looking for edit list");
9467     if (!(elst = qtdemux_tree_get_child_by_type (edts, FOURCC_elst)))
9468       goto done;
9469
9470     buffer = elst->data;
9471
9472     size = QT_UINT32 (buffer);
9473     /* version, flags, n_segments */
9474     if (size < 16) {
9475       GST_WARNING_OBJECT (qtdemux, "Invalid edit list");
9476       goto done;
9477     }
9478     version = QT_UINT8 (buffer + 8);
9479     entry_size = (version == 1) ? 20 : 12;
9480
9481     n_segments = QT_UINT32 (buffer + 12);
9482
9483     if (n_segments > 100000 || size < 16 + n_segments * entry_size) {
9484       GST_WARNING_OBJECT (qtdemux, "Invalid edit list");
9485       goto done;
9486     }
9487
9488     /* we might allocate a bit too much, at least allocate 1 segment */
9489     stream->segments = g_new (QtDemuxSegment, MAX (n_segments, 1));
9490
9491     /* segments always start from 0 */
9492     time = 0;
9493     stime = 0;
9494     buffer += 16;
9495     for (segment_number = 0; segment_number < n_segments; segment_number++) {
9496       guint64 duration;
9497       guint64 media_time;
9498       gboolean empty_edit = FALSE;
9499       QtDemuxSegment *segment;
9500       guint32 rate_int;
9501       GstClockTime media_start = GST_CLOCK_TIME_NONE;
9502
9503       if (version == 1) {
9504         media_time = QT_UINT64 (buffer + 8);
9505         duration = QT_UINT64 (buffer);
9506         if (media_time == G_MAXUINT64)
9507           empty_edit = TRUE;
9508       } else {
9509         media_time = QT_UINT32 (buffer + 4);
9510         duration = QT_UINT32 (buffer);
9511         if (media_time == G_MAXUINT32)
9512           empty_edit = TRUE;
9513       }
9514
9515       if (!empty_edit)
9516         media_start = QTSTREAMTIME_TO_GSTTIME (stream, media_time);
9517
9518       segment = &stream->segments[segment_number];
9519
9520       /* time and duration expressed in global timescale */
9521       segment->time = stime;
9522       if (duration != 0 || empty_edit) {
9523         /* edge case: empty edits with duration=zero are treated here.
9524          * (files should not have these anyway). */
9525
9526         /* add non scaled values so we don't cause roundoff errors */
9527         time += duration;
9528         stime = QTTIME_TO_GSTTIME (qtdemux, time);
9529         segment->duration = stime - segment->time;
9530       } else {
9531         /* zero duration does not imply media_start == media_stop
9532          * but, only specify media_start. The edit ends with the track. */
9533         stime = segment->duration = GST_CLOCK_TIME_NONE;
9534         /* Don't allow more edits after this one. */
9535         n_segments = segment_number + 1;
9536       }
9537       segment->stop_time = stime;
9538
9539       segment->trak_media_start = media_time;
9540       /* media_time expressed in stream timescale */
9541       if (!empty_edit) {
9542         segment->media_start = media_start;
9543         segment->media_stop = GST_CLOCK_TIME_IS_VALID (segment->duration)
9544             ? segment->media_start + segment->duration : GST_CLOCK_TIME_NONE;
9545         media_segments_count++;
9546       } else {
9547         segment->media_start = GST_CLOCK_TIME_NONE;
9548         segment->media_stop = GST_CLOCK_TIME_NONE;
9549       }
9550       rate_int = QT_UINT32 (buffer + ((version == 1) ? 16 : 8));
9551
9552       if (rate_int <= 1) {
9553         /* 0 is not allowed, some programs write 1 instead of the floating point
9554          * value */
9555         GST_WARNING_OBJECT (qtdemux, "found suspicious rate %" G_GUINT32_FORMAT,
9556             rate_int);
9557         segment->rate = 1;
9558       } else {
9559         segment->rate = rate_int / 65536.0;
9560       }
9561
9562       GST_DEBUG_OBJECT (qtdemux, "created segment %d time %" GST_TIME_FORMAT
9563           ", duration %" GST_TIME_FORMAT ", media_start %" GST_TIME_FORMAT
9564           " (%" G_GUINT64_FORMAT ") , media_stop %" GST_TIME_FORMAT
9565           " stop_time %" GST_TIME_FORMAT " rate %g, (%d) timescale %u",
9566           segment_number, GST_TIME_ARGS (segment->time),
9567           GST_TIME_ARGS (segment->duration),
9568           GST_TIME_ARGS (segment->media_start), media_time,
9569           GST_TIME_ARGS (segment->media_stop),
9570           GST_TIME_ARGS (segment->stop_time), segment->rate, rate_int,
9571           stream->timescale);
9572       if (segment->stop_time > qtdemux->segment.stop &&
9573           !qtdemux->upstream_format_is_time) {
9574         GST_WARNING_OBJECT (qtdemux, "Segment %d "
9575             " extends to %" GST_TIME_FORMAT
9576             " past the end of the declared movie duration %" GST_TIME_FORMAT
9577             " movie segment will be extended", segment_number,
9578             GST_TIME_ARGS (segment->stop_time),
9579             GST_TIME_ARGS (qtdemux->segment.stop));
9580         qtdemux->segment.stop = qtdemux->segment.duration = segment->stop_time;
9581       }
9582
9583       buffer += entry_size;
9584     }
9585     GST_DEBUG_OBJECT (qtdemux, "found %d segments", n_segments);
9586     stream->n_segments = n_segments;
9587     if (media_segments_count != 1)
9588       allow_pushbased_edts = FALSE;
9589   }
9590 done:
9591
9592   /* push based does not handle segments, so act accordingly here,
9593    * and warn if applicable */
9594   if (!qtdemux->pullbased && !allow_pushbased_edts) {
9595     GST_WARNING_OBJECT (qtdemux, "streaming; discarding edit list segments");
9596     /* remove and use default one below, we stream like it anyway */
9597     g_free (stream->segments);
9598     stream->segments = NULL;
9599     stream->n_segments = 0;
9600   }
9601
9602   /* no segments, create one to play the complete trak */
9603   if (stream->n_segments == 0) {
9604     GstClockTime stream_duration =
9605         QTSTREAMTIME_TO_GSTTIME (stream, stream->duration);
9606
9607     if (stream->segments == NULL)
9608       stream->segments = g_new (QtDemuxSegment, 1);
9609
9610     /* represent unknown our way */
9611     if (stream_duration == 0)
9612       stream_duration = GST_CLOCK_TIME_NONE;
9613
9614     stream->segments[0].time = 0;
9615     stream->segments[0].stop_time = stream_duration;
9616     stream->segments[0].duration = stream_duration;
9617     stream->segments[0].media_start = 0;
9618     stream->segments[0].media_stop = stream_duration;
9619     stream->segments[0].rate = 1.0;
9620     stream->segments[0].trak_media_start = 0;
9621
9622     GST_DEBUG_OBJECT (qtdemux, "created dummy segment %" GST_TIME_FORMAT,
9623         GST_TIME_ARGS (stream_duration));
9624     stream->n_segments = 1;
9625     stream->dummy_segment = TRUE;
9626   }
9627   GST_DEBUG_OBJECT (qtdemux, "using %d segments", stream->n_segments);
9628
9629   return TRUE;
9630 }
9631
9632 /*
9633  * Parses the stsd atom of a svq3 trak looking for
9634  * the SMI and gama atoms.
9635  */
9636 static void
9637 qtdemux_parse_svq3_stsd_data (GstQTDemux * qtdemux,
9638     const guint8 * stsd_entry_data, const guint8 ** gamma, GstBuffer ** seqh)
9639 {
9640   const guint8 *_gamma = NULL;
9641   GstBuffer *_seqh = NULL;
9642   const guint8 *stsd_data = stsd_entry_data;
9643   guint32 length = QT_UINT32 (stsd_data);
9644   guint16 version;
9645
9646   if (length < 32) {
9647     GST_WARNING_OBJECT (qtdemux, "stsd too short");
9648     goto end;
9649   }
9650
9651   stsd_data += 16;
9652   length -= 16;
9653   version = QT_UINT16 (stsd_data);
9654   if (version == 3) {
9655     if (length >= 70) {
9656       length -= 70;
9657       stsd_data += 70;
9658       while (length > 8) {
9659         guint32 fourcc, size;
9660         const guint8 *data;
9661         size = QT_UINT32 (stsd_data);
9662         fourcc = QT_FOURCC (stsd_data + 4);
9663         data = stsd_data + 8;
9664
9665         if (size == 0) {
9666           GST_WARNING_OBJECT (qtdemux, "Atom of size 0 found, aborting "
9667               "svq3 atom parsing");
9668           goto end;
9669         }
9670
9671         switch (fourcc) {
9672           case FOURCC_gama:{
9673             if (size == 12) {
9674               _gamma = data;
9675             } else {
9676               GST_WARNING_OBJECT (qtdemux, "Unexpected size %" G_GUINT32_FORMAT
9677                   " for gama atom, expected 12", size);
9678             }
9679             break;
9680           }
9681           case FOURCC_SMI_:{
9682             if (size > 16 && QT_FOURCC (data) == FOURCC_SEQH) {
9683               guint32 seqh_size;
9684               if (_seqh != NULL) {
9685                 GST_WARNING_OBJECT (qtdemux, "Unexpected second SEQH SMI atom "
9686                     " found, ignoring");
9687               } else {
9688                 seqh_size = QT_UINT32 (data + 4);
9689                 if (seqh_size > 0) {
9690                   _seqh = gst_buffer_new_and_alloc (seqh_size);
9691                   gst_buffer_fill (_seqh, 0, data + 8, seqh_size);
9692                 }
9693               }
9694             }
9695             break;
9696           }
9697           default:{
9698             GST_WARNING_OBJECT (qtdemux, "Unhandled atom %" GST_FOURCC_FORMAT
9699                 " in SVQ3 entry in stsd atom", GST_FOURCC_ARGS (fourcc));
9700           }
9701         }
9702
9703         if (size <= length) {
9704           length -= size;
9705           stsd_data += size;
9706         }
9707       }
9708     } else {
9709       GST_WARNING_OBJECT (qtdemux, "SVQ3 entry too short in stsd atom");
9710     }
9711   } else {
9712     GST_WARNING_OBJECT (qtdemux, "Unexpected version for SVQ3 entry %"
9713         G_GUINT16_FORMAT, version);
9714     goto end;
9715   }
9716
9717 end:
9718   if (gamma) {
9719     *gamma = _gamma;
9720   }
9721   if (seqh) {
9722     *seqh = _seqh;
9723   } else if (_seqh) {
9724     gst_buffer_unref (_seqh);
9725   }
9726 }
9727
9728 static gchar *
9729 qtdemux_get_rtsp_uri_from_hndl (GstQTDemux * qtdemux, GNode * minf)
9730 {
9731   GNode *dinf;
9732   GstByteReader dref;
9733   gchar *uri = NULL;
9734
9735   /*
9736    * Get 'dinf', to get its child 'dref', that might contain a 'hndl'
9737    * atom that might contain a 'data' atom with the rtsp uri.
9738    * This case was reported in bug #597497, some info about
9739    * the hndl atom can be found in TN1195
9740    */
9741   dinf = qtdemux_tree_get_child_by_type (minf, FOURCC_dinf);
9742   GST_DEBUG_OBJECT (qtdemux, "Trying to obtain rtsp URI for stream trak");
9743
9744   if (dinf) {
9745     guint32 dref_num_entries = 0;
9746     if (qtdemux_tree_get_child_by_type_full (dinf, FOURCC_dref, &dref) &&
9747         gst_byte_reader_skip (&dref, 4) &&
9748         gst_byte_reader_get_uint32_be (&dref, &dref_num_entries)) {
9749       gint i;
9750
9751       /* search dref entries for hndl atom */
9752       for (i = 0; i < dref_num_entries; i++) {
9753         guint32 size = 0, type;
9754         guint8 string_len = 0;
9755         if (gst_byte_reader_get_uint32_be (&dref, &size) &&
9756             qt_atom_parser_get_fourcc (&dref, &type)) {
9757           if (type == FOURCC_hndl) {
9758             GST_DEBUG_OBJECT (qtdemux, "Found hndl atom");
9759
9760             /* skip data reference handle bytes and the
9761              * following pascal string and some extra 4
9762              * bytes I have no idea what are */
9763             if (!gst_byte_reader_skip (&dref, 4) ||
9764                 !gst_byte_reader_get_uint8 (&dref, &string_len) ||
9765                 !gst_byte_reader_skip (&dref, string_len + 4)) {
9766               GST_WARNING_OBJECT (qtdemux, "Failed to parse hndl atom");
9767               break;
9768             }
9769
9770             /* iterate over the atoms to find the data atom */
9771             while (gst_byte_reader_get_remaining (&dref) >= 8) {
9772               guint32 atom_size;
9773               guint32 atom_type;
9774
9775               if (gst_byte_reader_get_uint32_be (&dref, &atom_size) &&
9776                   qt_atom_parser_get_fourcc (&dref, &atom_type)) {
9777                 if (atom_type == FOURCC_data) {
9778                   const guint8 *uri_aux = NULL;
9779
9780                   /* found the data atom that might contain the rtsp uri */
9781                   GST_DEBUG_OBJECT (qtdemux, "Found data atom inside "
9782                       "hndl atom, interpreting it as an URI");
9783                   if (gst_byte_reader_peek_data (&dref, atom_size - 8,
9784                           &uri_aux)) {
9785                     if (g_strstr_len ((gchar *) uri_aux, 7, "rtsp://") != NULL)
9786                       uri = g_strndup ((gchar *) uri_aux, atom_size - 8);
9787                     else
9788                       GST_WARNING_OBJECT (qtdemux, "Data atom in hndl atom "
9789                           "didn't contain a rtsp address");
9790                   } else {
9791                     GST_WARNING_OBJECT (qtdemux, "Failed to get the data "
9792                         "atom contents");
9793                   }
9794                   break;
9795                 }
9796                 /* skipping to the next entry */
9797                 if (!gst_byte_reader_skip (&dref, atom_size - 8))
9798                   break;
9799               } else {
9800                 GST_WARNING_OBJECT (qtdemux, "Failed to parse hndl child "
9801                     "atom header");
9802                 break;
9803               }
9804             }
9805             break;
9806           }
9807           /* skip to the next entry */
9808           if (!gst_byte_reader_skip (&dref, size - 8))
9809             break;
9810         } else {
9811           GST_WARNING_OBJECT (qtdemux, "Error parsing dref atom");
9812         }
9813       }
9814       GST_DEBUG_OBJECT (qtdemux, "Finished parsing dref atom");
9815     }
9816   }
9817   return uri;
9818 }
9819
9820 #define AMR_NB_ALL_MODES        0x81ff
9821 #define AMR_WB_ALL_MODES        0x83ff
9822 static guint
9823 qtdemux_parse_amr_bitrate (GstBuffer * buf, gboolean wb)
9824 {
9825   /* The 'damr' atom is of the form:
9826    *
9827    * | vendor | decoder_ver | mode_set | mode_change_period | frames/sample |
9828    *    32 b       8 b          16 b           8 b                 8 b
9829    *
9830    * The highest set bit of the first 7 (AMR-NB) or 8 (AMR-WB) bits of mode_set
9831    * represents the highest mode used in the stream (and thus the maximum
9832    * bitrate), with a couple of special cases as seen below.
9833    */
9834
9835   /* Map of frame type ID -> bitrate */
9836   static const guint nb_bitrates[] = {
9837     4750, 5150, 5900, 6700, 7400, 7950, 10200, 12200
9838   };
9839   static const guint wb_bitrates[] = {
9840     6600, 8850, 12650, 14250, 15850, 18250, 19850, 23050, 23850
9841   };
9842   GstMapInfo map;
9843   gsize max_mode;
9844   guint16 mode_set;
9845
9846   gst_buffer_map (buf, &map, GST_MAP_READ);
9847
9848   if (map.size != 0x11) {
9849     GST_DEBUG ("Atom should have size 0x11, not %" G_GSIZE_FORMAT, map.size);
9850     goto bad_data;
9851   }
9852
9853   if (QT_FOURCC (map.data + 4) != FOURCC_damr) {
9854     GST_DEBUG ("Unknown atom in %" GST_FOURCC_FORMAT,
9855         GST_FOURCC_ARGS (QT_UINT32 (map.data + 4)));
9856     goto bad_data;
9857   }
9858
9859   mode_set = QT_UINT16 (map.data + 13);
9860
9861   if (mode_set == (wb ? AMR_WB_ALL_MODES : AMR_NB_ALL_MODES))
9862     max_mode = 7 + (wb ? 1 : 0);
9863   else
9864     /* AMR-NB modes fo from 0-7, and AMR-WB modes go from 0-8 */
9865     max_mode = g_bit_nth_msf ((gulong) mode_set & (wb ? 0x1ff : 0xff), -1);
9866
9867   if (max_mode == -1) {
9868     GST_DEBUG ("No mode indication was found (mode set) = %x",
9869         (guint) mode_set);
9870     goto bad_data;
9871   }
9872
9873   gst_buffer_unmap (buf, &map);
9874   return wb ? wb_bitrates[max_mode] : nb_bitrates[max_mode];
9875
9876 bad_data:
9877   gst_buffer_unmap (buf, &map);
9878   return 0;
9879 }
9880
9881 static gboolean
9882 qtdemux_parse_transformation_matrix (GstQTDemux * qtdemux,
9883     GstByteReader * reader, guint32 * matrix, const gchar * atom)
9884 {
9885   /*
9886    * 9 values of 32 bits (fixed point 16.16, except 2 5 and 8 that are 2.30)
9887    * [0 1 2]
9888    * [3 4 5]
9889    * [6 7 8]
9890    */
9891
9892   if (gst_byte_reader_get_remaining (reader) < 36)
9893     return FALSE;
9894
9895   matrix[0] = gst_byte_reader_get_uint32_be_unchecked (reader);
9896   matrix[1] = gst_byte_reader_get_uint32_be_unchecked (reader);
9897   matrix[2] = gst_byte_reader_get_uint32_be_unchecked (reader);
9898   matrix[3] = gst_byte_reader_get_uint32_be_unchecked (reader);
9899   matrix[4] = gst_byte_reader_get_uint32_be_unchecked (reader);
9900   matrix[5] = gst_byte_reader_get_uint32_be_unchecked (reader);
9901   matrix[6] = gst_byte_reader_get_uint32_be_unchecked (reader);
9902   matrix[7] = gst_byte_reader_get_uint32_be_unchecked (reader);
9903   matrix[8] = gst_byte_reader_get_uint32_be_unchecked (reader);
9904
9905   GST_DEBUG_OBJECT (qtdemux, "Transformation matrix from atom %s", atom);
9906   GST_DEBUG_OBJECT (qtdemux, "%u.%u %u.%u %u.%u", matrix[0] >> 16,
9907       matrix[0] & 0xFFFF, matrix[1] >> 16, matrix[1] & 0xFF, matrix[2] >> 16,
9908       matrix[2] & 0xFF);
9909   GST_DEBUG_OBJECT (qtdemux, "%u.%u %u.%u %u.%u", matrix[3] >> 16,
9910       matrix[3] & 0xFFFF, matrix[4] >> 16, matrix[4] & 0xFF, matrix[5] >> 16,
9911       matrix[5] & 0xFF);
9912   GST_DEBUG_OBJECT (qtdemux, "%u.%u %u.%u %u.%u", matrix[6] >> 16,
9913       matrix[6] & 0xFFFF, matrix[7] >> 16, matrix[7] & 0xFF, matrix[8] >> 16,
9914       matrix[8] & 0xFF);
9915
9916   return TRUE;
9917 }
9918
9919 static void
9920 qtdemux_inspect_transformation_matrix (GstQTDemux * qtdemux,
9921     QtDemuxStream * stream, guint32 * matrix, GstTagList ** taglist)
9922 {
9923
9924 /* [a b c]
9925  * [d e f]
9926  * [g h i]
9927  *
9928  * This macro will only compare value abdegh, it expects cfi to have already
9929  * been checked
9930  */
9931 #define QTCHECK_MATRIX(m,a,b,d,e) ((m)[0] == (a << 16) && (m)[1] == (b << 16) && \
9932                                    (m)[3] == (d << 16) && (m)[4] == (e << 16))
9933
9934   /* only handle the cases where the last column has standard values */
9935   if (matrix[2] == 0 && matrix[5] == 0 && matrix[8] == 1 << 30) {
9936     const gchar *rotation_tag = NULL;
9937
9938     /* no rotation needed */
9939     if (QTCHECK_MATRIX (matrix, 1, 0, 0, 1)) {
9940       /* NOP */
9941     } else if (QTCHECK_MATRIX (matrix, 0, 1, G_MAXUINT16, 0)) {
9942       rotation_tag = "rotate-90";
9943     } else if (QTCHECK_MATRIX (matrix, G_MAXUINT16, 0, 0, G_MAXUINT16)) {
9944       rotation_tag = "rotate-180";
9945     } else if (QTCHECK_MATRIX (matrix, 0, G_MAXUINT16, 1, 0)) {
9946       rotation_tag = "rotate-270";
9947     } else {
9948       GST_FIXME_OBJECT (qtdemux, "Unhandled transformation matrix values");
9949     }
9950
9951     GST_DEBUG_OBJECT (qtdemux, "Transformation matrix rotation %s",
9952         rotation_tag);
9953     if (rotation_tag != NULL) {
9954       if (*taglist == NULL)
9955         *taglist = gst_tag_list_new_empty ();
9956       gst_tag_list_add (*taglist, GST_TAG_MERGE_REPLACE,
9957           GST_TAG_IMAGE_ORIENTATION, rotation_tag, NULL);
9958     }
9959   } else {
9960     GST_FIXME_OBJECT (qtdemux, "Unhandled transformation matrix values");
9961   }
9962 }
9963
9964 /* Parses the boxes defined in ISO/IEC 14496-12 that enable support for
9965  * protected streams (sinf, frma, schm and schi); if the protection scheme is
9966  * Common Encryption (cenc), the function will also parse the tenc box (defined
9967  * in ISO/IEC 23001-7). @container points to the node that contains these boxes
9968  * (typically an enc[v|a|t|s] sample entry); the function will set
9969  * @original_fmt to the fourcc of the original unencrypted stream format.
9970  * Returns TRUE if successful; FALSE otherwise. */
9971 static gboolean
9972 qtdemux_parse_protection_scheme_info (GstQTDemux * qtdemux,
9973     QtDemuxStream * stream, GNode * container, guint32 * original_fmt)
9974 {
9975   GNode *sinf;
9976   GNode *frma;
9977   GNode *schm;
9978   GNode *schi;
9979   QtDemuxCencSampleSetInfo *info;
9980   GNode *tenc;
9981   const guint8 *tenc_data;
9982
9983   g_return_val_if_fail (qtdemux != NULL, FALSE);
9984   g_return_val_if_fail (stream != NULL, FALSE);
9985   g_return_val_if_fail (container != NULL, FALSE);
9986   g_return_val_if_fail (original_fmt != NULL, FALSE);
9987
9988   sinf = qtdemux_tree_get_child_by_type (container, FOURCC_sinf);
9989   if (G_UNLIKELY (!sinf)) {
9990     if (stream->protection_scheme_type == FOURCC_cenc) {
9991       GST_ERROR_OBJECT (qtdemux, "sinf box does not contain schi box, which is "
9992           "mandatory for Common Encryption");
9993       return FALSE;
9994     }
9995     return TRUE;
9996   }
9997
9998   frma = qtdemux_tree_get_child_by_type (sinf, FOURCC_frma);
9999   if (G_UNLIKELY (!frma)) {
10000     GST_ERROR_OBJECT (qtdemux, "sinf box does not contain mandatory frma box");
10001     return FALSE;
10002   }
10003
10004   *original_fmt = QT_FOURCC ((const guint8 *) frma->data + 8);
10005   GST_DEBUG_OBJECT (qtdemux, "original stream format: '%" GST_FOURCC_FORMAT "'",
10006       GST_FOURCC_ARGS (*original_fmt));
10007
10008   schm = qtdemux_tree_get_child_by_type (sinf, FOURCC_schm);
10009   if (!schm) {
10010     GST_DEBUG_OBJECT (qtdemux, "sinf box does not contain schm box");
10011     return FALSE;
10012   }
10013   stream->protection_scheme_type = QT_FOURCC ((const guint8 *) schm->data + 12);
10014   stream->protection_scheme_version =
10015       QT_UINT32 ((const guint8 *) schm->data + 16);
10016
10017   GST_DEBUG_OBJECT (qtdemux,
10018       "protection_scheme_type: %" GST_FOURCC_FORMAT ", "
10019       "protection_scheme_version: %#010x",
10020       GST_FOURCC_ARGS (stream->protection_scheme_type),
10021       stream->protection_scheme_version);
10022
10023   schi = qtdemux_tree_get_child_by_type (sinf, FOURCC_schi);
10024   if (!schi) {
10025     GST_DEBUG_OBJECT (qtdemux, "sinf box does not contain schi box");
10026     return FALSE;
10027   }
10028   if (stream->protection_scheme_type != FOURCC_cenc &&
10029       stream->protection_scheme_type != FOURCC_piff) {
10030     GST_ERROR_OBJECT (qtdemux,
10031         "Invalid protection_scheme_type: %" GST_FOURCC_FORMAT,
10032         GST_FOURCC_ARGS (stream->protection_scheme_type));
10033     return FALSE;
10034   }
10035
10036   if (G_UNLIKELY (!stream->protection_scheme_info))
10037     stream->protection_scheme_info =
10038         g_malloc0 (sizeof (QtDemuxCencSampleSetInfo));
10039
10040   info = (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
10041
10042   if (stream->protection_scheme_type == FOURCC_cenc) {
10043     guint32 is_encrypted;
10044     guint8 iv_size;
10045     const guint8 *default_kid;
10046
10047     tenc = qtdemux_tree_get_child_by_type (schi, FOURCC_tenc);
10048     if (!tenc) {
10049       GST_ERROR_OBJECT (qtdemux, "schi box does not contain tenc box, "
10050           "which is mandatory for Common Encryption");
10051       return FALSE;
10052     }
10053     tenc_data = (const guint8 *) tenc->data + 12;
10054     is_encrypted = QT_UINT24 (tenc_data);
10055     iv_size = QT_UINT8 (tenc_data + 3);
10056     default_kid = (tenc_data + 4);
10057     qtdemux_update_default_sample_encryption_settings (qtdemux, info,
10058         is_encrypted, iv_size, default_kid);
10059   } else if (stream->protection_scheme_type == FOURCC_piff) {
10060     GstByteReader br;
10061     static const guint8 piff_track_encryption_uuid[] = {
10062       0x89, 0x74, 0xdb, 0xce, 0x7b, 0xe7, 0x4c, 0x51,
10063       0x84, 0xf9, 0x71, 0x48, 0xf9, 0x88, 0x25, 0x54
10064     };
10065
10066     tenc = qtdemux_tree_get_child_by_type (schi, FOURCC_uuid);
10067     if (!tenc) {
10068       GST_ERROR_OBJECT (qtdemux, "schi box does not contain tenc box, "
10069           "which is mandatory for Common Encryption");
10070       return FALSE;
10071     }
10072
10073     tenc_data = (const guint8 *) tenc->data + 8;
10074     if (memcmp (tenc_data, piff_track_encryption_uuid, 16) != 0) {
10075       gchar *box_uuid = qtdemux_uuid_bytes_to_string (tenc_data);
10076       GST_ERROR_OBJECT (qtdemux,
10077           "Unsupported track encryption box with uuid: %s", box_uuid);
10078       g_free (box_uuid);
10079       return FALSE;
10080     }
10081     tenc_data = (const guint8 *) tenc->data + 16 + 12;
10082     gst_byte_reader_init (&br, tenc_data, 20);
10083     if (!qtdemux_update_default_piff_encryption_settings (qtdemux, info, &br)) {
10084       GST_ERROR_OBJECT (qtdemux, "PIFF track box parsing error");
10085       return FALSE;
10086     }
10087     stream->protection_scheme_type = FOURCC_cenc;
10088   }
10089
10090   return TRUE;
10091 }
10092
10093 static gint
10094 qtdemux_track_id_compare_func (QtDemuxStream * stream1, QtDemuxStream * stream2)
10095 {
10096   return (gint) stream1->track_id - (gint) stream2->track_id;
10097 }
10098
10099 /* parse the traks.
10100  * With each track we associate a new QtDemuxStream that contains all the info
10101  * about the trak.
10102  * traks that do not decode to something (like strm traks) will not have a pad.
10103  */
10104 static gboolean
10105 qtdemux_parse_trak (GstQTDemux * qtdemux, GNode * trak)
10106 {
10107   GstByteReader tkhd;
10108   int offset;
10109   GNode *mdia;
10110   GNode *mdhd;
10111   GNode *hdlr;
10112   GNode *minf;
10113   GNode *stbl;
10114   GNode *stsd;
10115   GNode *mp4a;
10116   GNode *mp4v;
10117   GNode *esds;
10118   GNode *tref;
10119   GNode *udta;
10120   GNode *svmi;
10121
10122   QtDemuxStream *stream = NULL;
10123   const guint8 *stsd_data;
10124   const guint8 *stsd_entry_data;
10125   guint remaining_stsd_len;
10126   guint stsd_entry_count;
10127   guint stsd_index;
10128   guint16 lang_code;            /* quicktime lang code or packed iso code */
10129   guint32 version;
10130   guint32 tkhd_flags = 0;
10131   guint8 tkhd_version = 0;
10132   guint32 w = 0, h = 0;
10133   guint value_size, stsd_len, len;
10134   guint32 track_id;
10135   guint32 dummy;
10136
10137   GST_DEBUG_OBJECT (qtdemux, "parse_trak");
10138
10139   if (!qtdemux_tree_get_child_by_type_full (trak, FOURCC_tkhd, &tkhd)
10140       || !gst_byte_reader_get_uint8 (&tkhd, &tkhd_version)
10141       || !gst_byte_reader_get_uint24_be (&tkhd, &tkhd_flags))
10142     goto corrupt_file;
10143
10144   /* pick between 64 or 32 bits */
10145   value_size = tkhd_version == 1 ? 8 : 4;
10146   if (!gst_byte_reader_skip (&tkhd, value_size * 2) ||
10147       !gst_byte_reader_get_uint32_be (&tkhd, &track_id))
10148     goto corrupt_file;
10149
10150   /* Check if current moov has duplicated track_id */
10151   if (qtdemux_find_stream (qtdemux, track_id))
10152     goto existing_stream;
10153
10154   stream = _create_stream (qtdemux, track_id);
10155   stream->stream_tags = gst_tag_list_make_writable (stream->stream_tags);
10156
10157   /* need defaults for fragments */
10158   qtdemux_parse_trex (qtdemux, stream, &dummy, &dummy, &dummy);
10159
10160   if ((tkhd_flags & 1) == 0)
10161     stream->disabled = TRUE;
10162
10163   GST_LOG_OBJECT (qtdemux, "track[tkhd] version/flags/id: 0x%02x/%06x/%u",
10164       tkhd_version, tkhd_flags, stream->track_id);
10165
10166   if (!(mdia = qtdemux_tree_get_child_by_type (trak, FOURCC_mdia)))
10167     goto corrupt_file;
10168
10169   if (!(mdhd = qtdemux_tree_get_child_by_type (mdia, FOURCC_mdhd))) {
10170     /* be nice for some crooked mjp2 files that use mhdr for mdhd */
10171     if (qtdemux->major_brand != FOURCC_mjp2 ||
10172         !(mdhd = qtdemux_tree_get_child_by_type (mdia, FOURCC_mhdr)))
10173       goto corrupt_file;
10174   }
10175
10176   len = QT_UINT32 ((guint8 *) mdhd->data);
10177   version = QT_UINT32 ((guint8 *) mdhd->data + 8);
10178   GST_LOG_OBJECT (qtdemux, "track version/flags: %08x", version);
10179   if (version == 0x01000000) {
10180     if (len < 38)
10181       goto corrupt_file;
10182     stream->timescale = QT_UINT32 ((guint8 *) mdhd->data + 28);
10183     stream->duration = QT_UINT64 ((guint8 *) mdhd->data + 32);
10184     lang_code = QT_UINT16 ((guint8 *) mdhd->data + 36);
10185   } else {
10186     if (len < 30)
10187       goto corrupt_file;
10188     stream->timescale = QT_UINT32 ((guint8 *) mdhd->data + 20);
10189     stream->duration = QT_UINT32 ((guint8 *) mdhd->data + 24);
10190     lang_code = QT_UINT16 ((guint8 *) mdhd->data + 28);
10191   }
10192
10193   if (lang_code < 0x400) {
10194     qtdemux_lang_map_qt_code_to_iso (stream->lang_id, lang_code);
10195   } else if (lang_code == 0x7fff) {
10196     stream->lang_id[0] = 0;     /* unspecified */
10197   } else {
10198     stream->lang_id[0] = 0x60 + ((lang_code >> 10) & 0x1F);
10199     stream->lang_id[1] = 0x60 + ((lang_code >> 5) & 0x1F);
10200     stream->lang_id[2] = 0x60 + (lang_code & 0x1F);
10201     stream->lang_id[3] = 0;
10202   }
10203
10204   GST_LOG_OBJECT (qtdemux, "track timescale: %" G_GUINT32_FORMAT,
10205       stream->timescale);
10206   GST_LOG_OBJECT (qtdemux, "track duration: %" G_GUINT64_FORMAT,
10207       stream->duration);
10208   GST_LOG_OBJECT (qtdemux, "track language code/id: 0x%04x/%s",
10209       lang_code, stream->lang_id);
10210
10211   if (G_UNLIKELY (stream->timescale == 0 || qtdemux->timescale == 0))
10212     goto corrupt_file;
10213
10214   if ((tref = qtdemux_tree_get_child_by_type (trak, FOURCC_tref))) {
10215     /* chapters track reference */
10216     GNode *chap = qtdemux_tree_get_child_by_type (tref, FOURCC_chap);
10217     if (chap) {
10218       gsize length = GST_READ_UINT32_BE (chap->data);
10219       if (qtdemux->chapters_track_id)
10220         GST_FIXME_OBJECT (qtdemux, "Multiple CHAP tracks");
10221
10222       if (length >= 12) {
10223         qtdemux->chapters_track_id =
10224             GST_READ_UINT32_BE ((gint8 *) chap->data + 8);
10225       }
10226     }
10227   }
10228
10229   /* fragmented files may have bogus duration in moov */
10230   if (!qtdemux->fragmented &&
10231       qtdemux->duration != G_MAXINT64 && stream->duration != G_MAXINT32) {
10232     guint64 tdur1, tdur2;
10233
10234     /* don't overflow */
10235     tdur1 = stream->timescale * (guint64) qtdemux->duration;
10236     tdur2 = qtdemux->timescale * (guint64) stream->duration;
10237
10238     /* HACK:
10239      * some of those trailers, nowadays, have prologue images that are
10240      * themselves video tracks as well. I haven't really found a way to
10241      * identify those yet, except for just looking at their duration. */
10242     if (tdur1 != 0 && (tdur2 * 10 / tdur1) < 2) {
10243       GST_WARNING_OBJECT (qtdemux,
10244           "Track shorter than 20%% (%" G_GUINT64_FORMAT "/%" G_GUINT32_FORMAT
10245           " vs. %" G_GUINT64_FORMAT "/%" G_GUINT32_FORMAT ") of the stream "
10246           "found, assuming preview image or something; skipping track",
10247           stream->duration, stream->timescale, qtdemux->duration,
10248           qtdemux->timescale);
10249       gst_qtdemux_stream_free (stream);
10250       return TRUE;
10251     }
10252   }
10253
10254   if (!(hdlr = qtdemux_tree_get_child_by_type (mdia, FOURCC_hdlr)))
10255     goto corrupt_file;
10256
10257   GST_LOG_OBJECT (qtdemux, "track type: %" GST_FOURCC_FORMAT,
10258       GST_FOURCC_ARGS (QT_FOURCC ((guint8 *) hdlr->data + 12)));
10259
10260   len = QT_UINT32 ((guint8 *) hdlr->data);
10261   if (len >= 20)
10262     stream->subtype = QT_FOURCC ((guint8 *) hdlr->data + 16);
10263   GST_LOG_OBJECT (qtdemux, "track subtype: %" GST_FOURCC_FORMAT,
10264       GST_FOURCC_ARGS (stream->subtype));
10265
10266   if (!(minf = qtdemux_tree_get_child_by_type (mdia, FOURCC_minf)))
10267     goto corrupt_file;
10268
10269   if (!(stbl = qtdemux_tree_get_child_by_type (minf, FOURCC_stbl)))
10270     goto corrupt_file;
10271
10272   /*parse svmi header if existing */
10273   svmi = qtdemux_tree_get_child_by_type (stbl, FOURCC_svmi);
10274   if (svmi) {
10275     len = QT_UINT32 ((guint8 *) svmi->data);
10276     version = QT_UINT32 ((guint8 *) svmi->data + 8);
10277     if (!version) {
10278       GstVideoMultiviewMode mode = GST_VIDEO_MULTIVIEW_MODE_NONE;
10279       GstVideoMultiviewFlags flags = GST_VIDEO_MULTIVIEW_FLAGS_NONE;
10280       guint8 frame_type, frame_layout;
10281
10282       /* MPEG-A stereo video */
10283       if (qtdemux->major_brand == FOURCC_ss02)
10284         flags |= GST_VIDEO_MULTIVIEW_FLAGS_MIXED_MONO;
10285
10286       frame_type = QT_UINT8 ((guint8 *) svmi->data + 12);
10287       frame_layout = QT_UINT8 ((guint8 *) svmi->data + 13) & 0x01;
10288       switch (frame_type) {
10289         case 0:
10290           mode = GST_VIDEO_MULTIVIEW_MODE_SIDE_BY_SIDE;
10291           break;
10292         case 1:
10293           mode = GST_VIDEO_MULTIVIEW_MODE_ROW_INTERLEAVED;
10294           break;
10295         case 2:
10296           mode = GST_VIDEO_MULTIVIEW_MODE_FRAME_BY_FRAME;
10297           break;
10298         case 3:
10299           /* mode 3 is primary/secondary view sequence, ie
10300            * left/right views in separate tracks. See section 7.2
10301            * of ISO/IEC 23000-11:2009 */
10302           GST_FIXME_OBJECT (qtdemux,
10303               "Implement stereo video in separate streams");
10304       }
10305
10306       if ((frame_layout & 0x1) == 0)
10307         flags |= GST_VIDEO_MULTIVIEW_FLAGS_RIGHT_VIEW_FIRST;
10308
10309       GST_LOG_OBJECT (qtdemux,
10310           "StereoVideo: composition type: %u, is_left_first: %u",
10311           frame_type, frame_layout);
10312       stream->multiview_mode = mode;
10313       stream->multiview_flags = flags;
10314     }
10315   }
10316
10317   /* parse rest of tkhd */
10318   if (stream->subtype == FOURCC_vide) {
10319     guint32 matrix[9];
10320
10321     /* version 1 uses some 64-bit ints */
10322     if (!gst_byte_reader_skip (&tkhd, 20 + value_size))
10323       goto corrupt_file;
10324
10325     if (!qtdemux_parse_transformation_matrix (qtdemux, &tkhd, matrix, "tkhd"))
10326       goto corrupt_file;
10327
10328     if (!gst_byte_reader_get_uint32_be (&tkhd, &w)
10329         || !gst_byte_reader_get_uint32_be (&tkhd, &h))
10330       goto corrupt_file;
10331
10332     qtdemux_inspect_transformation_matrix (qtdemux, stream, matrix,
10333         &stream->stream_tags);
10334   }
10335
10336   /* parse stsd */
10337   if (!(stsd = qtdemux_tree_get_child_by_type (stbl, FOURCC_stsd)))
10338     goto corrupt_file;
10339   stsd_data = (const guint8 *) stsd->data;
10340
10341   /* stsd should at least have one entry */
10342   stsd_len = QT_UINT32 (stsd_data);
10343   if (stsd_len < 24) {
10344     /* .. but skip stream with empty stsd produced by some Vivotek cameras */
10345     if (stream->subtype == FOURCC_vivo) {
10346       gst_qtdemux_stream_free (stream);
10347       return TRUE;
10348     } else {
10349       goto corrupt_file;
10350     }
10351   }
10352
10353   stream->stsd_entries_length = stsd_entry_count = QT_UINT32 (stsd_data + 12);
10354   stream->stsd_entries = g_new0 (QtDemuxStreamStsdEntry, stsd_entry_count);
10355   GST_LOG_OBJECT (qtdemux, "stsd len:           %d", stsd_len);
10356   GST_LOG_OBJECT (qtdemux, "stsd entry count:   %u", stsd_entry_count);
10357
10358   stsd_entry_data = stsd_data + 16;
10359   remaining_stsd_len = stsd_len - 16;
10360   for (stsd_index = 0; stsd_index < stsd_entry_count; stsd_index++) {
10361     guint32 fourcc;
10362     gchar *codec = NULL;
10363     QtDemuxStreamStsdEntry *entry = &stream->stsd_entries[stsd_index];
10364
10365     /* and that entry should fit within stsd */
10366     len = QT_UINT32 (stsd_entry_data);
10367     if (len > remaining_stsd_len)
10368       goto corrupt_file;
10369
10370     entry->fourcc = fourcc = QT_FOURCC (stsd_entry_data + 4);
10371     GST_LOG_OBJECT (qtdemux, "stsd type:          %" GST_FOURCC_FORMAT,
10372         GST_FOURCC_ARGS (entry->fourcc));
10373     GST_LOG_OBJECT (qtdemux, "stsd type len:      %d", len);
10374
10375     if ((fourcc == FOURCC_drms) || (fourcc == FOURCC_drmi))
10376       goto error_encrypted;
10377
10378     if (fourcc == FOURCC_encv || fourcc == FOURCC_enca) {
10379       /* FIXME this looks wrong, there might be multiple children
10380        * with the same type */
10381       GNode *enc = qtdemux_tree_get_child_by_type (stsd, fourcc);
10382       stream->protected = TRUE;
10383       if (!qtdemux_parse_protection_scheme_info (qtdemux, stream, enc, &fourcc))
10384         GST_ERROR_OBJECT (qtdemux, "Failed to parse protection scheme info");
10385     }
10386
10387     if (stream->subtype == FOURCC_vide) {
10388       GNode *colr;
10389       GNode *fiel;
10390       GNode *pasp;
10391       gboolean gray;
10392       gint depth, palette_size, palette_count;
10393       guint32 *palette_data = NULL;
10394
10395       entry->sampled = TRUE;
10396
10397       stream->display_width = w >> 16;
10398       stream->display_height = h >> 16;
10399
10400       offset = 16;
10401       if (len < 86)             /* TODO verify */
10402         goto corrupt_file;
10403
10404       entry->width = QT_UINT16 (stsd_entry_data + offset + 16);
10405       entry->height = QT_UINT16 (stsd_entry_data + offset + 18);
10406       entry->fps_n = 0;         /* this is filled in later */
10407       entry->fps_d = 0;         /* this is filled in later */
10408       entry->bits_per_sample = QT_UINT16 (stsd_entry_data + offset + 66);
10409       entry->color_table_id = QT_UINT16 (stsd_entry_data + offset + 68);
10410
10411       /* if color_table_id is 0, ctab atom must follow; however some files
10412        * produced by TMPEGEnc have color_table_id = 0 and no ctab atom, so
10413        * if color table is not present we'll correct the value */
10414       if (entry->color_table_id == 0 &&
10415           (len < 90
10416               || QT_FOURCC (stsd_entry_data + offset + 70) != FOURCC_ctab)) {
10417         entry->color_table_id = -1;
10418       }
10419
10420       GST_LOG_OBJECT (qtdemux, "width %d, height %d, bps %d, color table id %d",
10421           entry->width, entry->height, entry->bits_per_sample,
10422           entry->color_table_id);
10423
10424       depth = entry->bits_per_sample;
10425
10426       /* more than 32 bits means grayscale */
10427       gray = (depth > 32);
10428       /* low 32 bits specify the depth  */
10429       depth &= 0x1F;
10430
10431       /* different number of palette entries is determined by depth. */
10432       palette_count = 0;
10433       if ((depth == 1) || (depth == 2) || (depth == 4) || (depth == 8))
10434         palette_count = (1 << depth);
10435       palette_size = palette_count * 4;
10436
10437       if (entry->color_table_id) {
10438         switch (palette_count) {
10439           case 0:
10440             break;
10441           case 2:
10442             palette_data = g_memdup (ff_qt_default_palette_2, palette_size);
10443             break;
10444           case 4:
10445             palette_data = g_memdup (ff_qt_default_palette_4, palette_size);
10446             break;
10447           case 16:
10448             if (gray)
10449               palette_data =
10450                   g_memdup (ff_qt_grayscale_palette_16, palette_size);
10451             else
10452               palette_data = g_memdup (ff_qt_default_palette_16, palette_size);
10453             break;
10454           case 256:
10455             if (gray)
10456               palette_data =
10457                   g_memdup (ff_qt_grayscale_palette_256, palette_size);
10458             else
10459               palette_data = g_memdup (ff_qt_default_palette_256, palette_size);
10460             break;
10461           default:
10462             GST_ELEMENT_WARNING (qtdemux, STREAM, DEMUX,
10463                 (_("The video in this file might not play correctly.")),
10464                 ("unsupported palette depth %d", depth));
10465             break;
10466         }
10467       } else {
10468         gint i, j, start, end;
10469
10470         if (len < 94)
10471           goto corrupt_file;
10472
10473         /* read table */
10474         start = QT_UINT32 (stsd_entry_data + offset + 70);
10475         palette_count = QT_UINT16 (stsd_entry_data + offset + 74);
10476         end = QT_UINT16 (stsd_entry_data + offset + 76);
10477
10478         GST_LOG_OBJECT (qtdemux, "start %d, end %d, palette_count %d",
10479             start, end, palette_count);
10480
10481         if (end > 255)
10482           end = 255;
10483         if (start > end)
10484           start = end;
10485
10486         if (len < 94 + (end - start) * 8)
10487           goto corrupt_file;
10488
10489         /* palette is always the same size */
10490         palette_data = g_malloc0 (256 * 4);
10491         palette_size = 256 * 4;
10492
10493         for (j = 0, i = start; i <= end; j++, i++) {
10494           guint32 a, r, g, b;
10495
10496           a = QT_UINT16 (stsd_entry_data + offset + 78 + (j * 8));
10497           r = QT_UINT16 (stsd_entry_data + offset + 80 + (j * 8));
10498           g = QT_UINT16 (stsd_entry_data + offset + 82 + (j * 8));
10499           b = QT_UINT16 (stsd_entry_data + offset + 84 + (j * 8));
10500
10501           palette_data[i] = ((a & 0xff00) << 16) | ((r & 0xff00) << 8) |
10502               (g & 0xff00) | (b >> 8);
10503         }
10504       }
10505
10506       if (entry->caps)
10507         gst_caps_unref (entry->caps);
10508
10509       entry->caps =
10510           qtdemux_video_caps (qtdemux, stream, entry, fourcc, stsd_entry_data,
10511           &codec);
10512       if (G_UNLIKELY (!entry->caps)) {
10513         g_free (palette_data);
10514         goto unknown_stream;
10515       }
10516
10517       if (codec) {
10518         gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
10519             GST_TAG_VIDEO_CODEC, codec, NULL);
10520         g_free (codec);
10521         codec = NULL;
10522       }
10523
10524       if (palette_data) {
10525         GstStructure *s;
10526
10527         if (entry->rgb8_palette)
10528           gst_memory_unref (entry->rgb8_palette);
10529         entry->rgb8_palette = gst_memory_new_wrapped (GST_MEMORY_FLAG_READONLY,
10530             palette_data, palette_size, 0, palette_size, palette_data, g_free);
10531
10532         s = gst_caps_get_structure (entry->caps, 0);
10533
10534         /* non-raw video has a palette_data property. raw video has the palette as
10535          * an extra plane that we append to the output buffers before we push
10536          * them*/
10537         if (!gst_structure_has_name (s, "video/x-raw")) {
10538           GstBuffer *palette;
10539
10540           palette = gst_buffer_new ();
10541           gst_buffer_append_memory (palette, entry->rgb8_palette);
10542           entry->rgb8_palette = NULL;
10543
10544           gst_caps_set_simple (entry->caps, "palette_data",
10545               GST_TYPE_BUFFER, palette, NULL);
10546           gst_buffer_unref (palette);
10547         }
10548       } else if (palette_count != 0) {
10549         GST_ELEMENT_WARNING (qtdemux, STREAM, NOT_IMPLEMENTED,
10550             (NULL), ("Unsupported palette depth %d", depth));
10551       }
10552
10553       GST_LOG_OBJECT (qtdemux, "frame count:   %u",
10554           QT_UINT16 (stsd_entry_data + offset + 32));
10555
10556       esds = NULL;
10557       pasp = NULL;
10558       colr = NULL;
10559       fiel = NULL;
10560       /* pick 'the' stsd child */
10561       mp4v = qtdemux_tree_get_child_by_index (stsd, stsd_index);
10562       if (!stream->protected) {
10563         if (QTDEMUX_TREE_NODE_FOURCC (mp4v) != fourcc) {
10564           mp4v = NULL;
10565         }
10566       } else {
10567         if (QTDEMUX_TREE_NODE_FOURCC (mp4v) != FOURCC_encv) {
10568           mp4v = NULL;
10569         }
10570       }
10571
10572       if (mp4v) {
10573         esds = qtdemux_tree_get_child_by_type (mp4v, FOURCC_esds);
10574         pasp = qtdemux_tree_get_child_by_type (mp4v, FOURCC_pasp);
10575         colr = qtdemux_tree_get_child_by_type (mp4v, FOURCC_colr);
10576         fiel = qtdemux_tree_get_child_by_type (mp4v, FOURCC_fiel);
10577       }
10578
10579       if (pasp) {
10580         const guint8 *pasp_data = (const guint8 *) pasp->data;
10581         gint len = QT_UINT32 (pasp_data);
10582
10583         if (len == 16) {
10584           CUR_STREAM (stream)->par_w = QT_UINT32 (pasp_data + 8);
10585           CUR_STREAM (stream)->par_h = QT_UINT32 (pasp_data + 12);
10586         } else {
10587           CUR_STREAM (stream)->par_w = 0;
10588           CUR_STREAM (stream)->par_h = 0;
10589         }
10590       } else {
10591         CUR_STREAM (stream)->par_w = 0;
10592         CUR_STREAM (stream)->par_h = 0;
10593       }
10594
10595       if (fiel) {
10596         const guint8 *fiel_data = (const guint8 *) fiel->data;
10597         gint len = QT_UINT32 (fiel_data);
10598
10599         if (len == 10) {
10600           CUR_STREAM (stream)->interlace_mode = GST_READ_UINT8 (fiel_data + 8);
10601           CUR_STREAM (stream)->field_order = GST_READ_UINT8 (fiel_data + 9);
10602         }
10603       }
10604
10605       if (colr) {
10606         const guint8 *colr_data = (const guint8 *) colr->data;
10607         gint len = QT_UINT32 (colr_data);
10608
10609         if (len == 19 || len == 18) {
10610           guint32 color_type = GST_READ_UINT32_LE (colr_data + 8);
10611
10612           if (color_type == FOURCC_nclx || color_type == FOURCC_nclc) {
10613             guint16 primaries = GST_READ_UINT16_BE (colr_data + 12);
10614             guint16 transfer_function = GST_READ_UINT16_BE (colr_data + 14);
10615             guint16 matrix = GST_READ_UINT16_BE (colr_data + 16);
10616             gboolean full_range = len == 19 ? colr_data[17] >> 7 : FALSE;
10617
10618             switch (primaries) {
10619               case 1:
10620                 CUR_STREAM (stream)->colorimetry.primaries =
10621                     GST_VIDEO_COLOR_PRIMARIES_BT709;
10622                 break;
10623               case 5:
10624                 CUR_STREAM (stream)->colorimetry.primaries =
10625                     GST_VIDEO_COLOR_PRIMARIES_BT470BG;
10626                 break;
10627               case 6:
10628                 CUR_STREAM (stream)->colorimetry.primaries =
10629                     GST_VIDEO_COLOR_PRIMARIES_SMPTE170M;
10630                 break;
10631               case 9:
10632                 CUR_STREAM (stream)->colorimetry.primaries =
10633                     GST_VIDEO_COLOR_PRIMARIES_BT2020;
10634                 break;
10635               default:
10636                 break;
10637             }
10638
10639             switch (transfer_function) {
10640               case 1:
10641                 CUR_STREAM (stream)->colorimetry.transfer =
10642                     GST_VIDEO_TRANSFER_BT709;
10643                 break;
10644               case 7:
10645                 CUR_STREAM (stream)->colorimetry.transfer =
10646                     GST_VIDEO_TRANSFER_SMPTE240M;
10647                 break;
10648               default:
10649                 break;
10650             }
10651
10652             switch (matrix) {
10653               case 1:
10654                 CUR_STREAM (stream)->colorimetry.matrix =
10655                     GST_VIDEO_COLOR_MATRIX_BT709;
10656                 break;
10657               case 6:
10658                 CUR_STREAM (stream)->colorimetry.matrix =
10659                     GST_VIDEO_COLOR_MATRIX_BT601;
10660                 break;
10661               case 7:
10662                 CUR_STREAM (stream)->colorimetry.matrix =
10663                     GST_VIDEO_COLOR_MATRIX_SMPTE240M;
10664                 break;
10665               case 9:
10666                 CUR_STREAM (stream)->colorimetry.matrix =
10667                     GST_VIDEO_COLOR_MATRIX_BT2020;
10668                 break;
10669               default:
10670                 break;
10671             }
10672
10673             CUR_STREAM (stream)->colorimetry.range =
10674                 full_range ? GST_VIDEO_COLOR_RANGE_0_255 :
10675                 GST_VIDEO_COLOR_RANGE_16_235;
10676           } else {
10677             GST_DEBUG_OBJECT (qtdemux, "Unsupported color type");
10678           }
10679         } else {
10680           GST_WARNING_OBJECT (qtdemux, "Invalid colr atom size");
10681         }
10682       }
10683
10684       if (esds) {
10685         gst_qtdemux_handle_esds (qtdemux, stream, entry, esds,
10686             stream->stream_tags);
10687       } else {
10688         switch (fourcc) {
10689           case FOURCC_H264:
10690           case FOURCC_avc1:
10691           case FOURCC_avc3:
10692           {
10693             gint len = QT_UINT32 (stsd_entry_data) - 0x56;
10694             const guint8 *avc_data = stsd_entry_data + 0x56;
10695
10696             /* find avcC */
10697             while (len >= 0x8) {
10698               gint size;
10699
10700               if (QT_UINT32 (avc_data) <= len)
10701                 size = QT_UINT32 (avc_data) - 0x8;
10702               else
10703                 size = len - 0x8;
10704
10705               if (size < 1)
10706                 /* No real data, so break out */
10707                 break;
10708
10709               switch (QT_FOURCC (avc_data + 0x4)) {
10710                 case FOURCC_avcC:
10711                 {
10712                   /* parse, if found */
10713                   GstBuffer *buf;
10714
10715                   GST_DEBUG_OBJECT (qtdemux, "found avcC codec_data in stsd");
10716
10717                   /* First 4 bytes are the length of the atom, the next 4 bytes
10718                    * are the fourcc, the next 1 byte is the version, and the
10719                    * subsequent bytes are profile_tier_level structure like data. */
10720                   gst_codec_utils_h264_caps_set_level_and_profile (entry->caps,
10721                       avc_data + 8 + 1, size - 1);
10722                   buf = gst_buffer_new_and_alloc (size);
10723                   gst_buffer_fill (buf, 0, avc_data + 0x8, size);
10724                   gst_caps_set_simple (entry->caps,
10725                       "codec_data", GST_TYPE_BUFFER, buf, NULL);
10726                   gst_buffer_unref (buf);
10727
10728                   break;
10729                 }
10730                 case FOURCC_strf:
10731                 {
10732                   GstBuffer *buf;
10733
10734                   GST_DEBUG_OBJECT (qtdemux, "found strf codec_data in stsd");
10735
10736                   /* First 4 bytes are the length of the atom, the next 4 bytes
10737                    * are the fourcc, next 40 bytes are BITMAPINFOHEADER,
10738                    * next 1 byte is the version, and the
10739                    * subsequent bytes are sequence parameter set like data. */
10740
10741                   size -= 40;   /* we'll be skipping BITMAPINFOHEADER */
10742                   if (size > 1) {
10743                     gst_codec_utils_h264_caps_set_level_and_profile
10744                         (entry->caps, avc_data + 8 + 40 + 1, size - 1);
10745
10746                     buf = gst_buffer_new_and_alloc (size);
10747                     gst_buffer_fill (buf, 0, avc_data + 8 + 40, size);
10748                     gst_caps_set_simple (entry->caps,
10749                         "codec_data", GST_TYPE_BUFFER, buf, NULL);
10750                     gst_buffer_unref (buf);
10751                   }
10752                   break;
10753                 }
10754                 case FOURCC_btrt:
10755                 {
10756                   guint avg_bitrate, max_bitrate;
10757
10758                   /* bufferSizeDB, maxBitrate and avgBitrate - 4 bytes each */
10759                   if (size < 12)
10760                     break;
10761
10762                   max_bitrate = QT_UINT32 (avc_data + 0xc);
10763                   avg_bitrate = QT_UINT32 (avc_data + 0x10);
10764
10765                   if (!max_bitrate && !avg_bitrate)
10766                     break;
10767
10768                   /* Some muxers seem to swap the average and maximum bitrates
10769                    * (I'm looking at you, YouTube), so we swap for sanity. */
10770                   if (max_bitrate > 0 && max_bitrate < avg_bitrate) {
10771                     guint temp = avg_bitrate;
10772
10773                     avg_bitrate = max_bitrate;
10774                     max_bitrate = temp;
10775                   }
10776
10777                   if (max_bitrate > 0 && max_bitrate < G_MAXUINT32) {
10778                     gst_tag_list_add (stream->stream_tags,
10779                         GST_TAG_MERGE_REPLACE, GST_TAG_MAXIMUM_BITRATE,
10780                         max_bitrate, NULL);
10781                   }
10782                   if (avg_bitrate > 0 && avg_bitrate < G_MAXUINT32) {
10783                     gst_tag_list_add (stream->stream_tags,
10784                         GST_TAG_MERGE_REPLACE, GST_TAG_BITRATE, avg_bitrate,
10785                         NULL);
10786                   }
10787
10788                   break;
10789                 }
10790
10791                 default:
10792                   break;
10793               }
10794
10795               len -= size + 8;
10796               avc_data += size + 8;
10797             }
10798
10799             break;
10800           }
10801           case FOURCC_H265:
10802           case FOURCC_hvc1:
10803           case FOURCC_hev1:
10804           {
10805             gint len = QT_UINT32 (stsd_entry_data) - 0x56;
10806             const guint8 *hevc_data = stsd_entry_data + 0x56;
10807
10808             /* find hevc */
10809             while (len >= 0x8) {
10810               gint size;
10811
10812               if (QT_UINT32 (hevc_data) <= len)
10813                 size = QT_UINT32 (hevc_data) - 0x8;
10814               else
10815                 size = len - 0x8;
10816
10817               if (size < 1)
10818                 /* No real data, so break out */
10819                 break;
10820
10821               switch (QT_FOURCC (hevc_data + 0x4)) {
10822                 case FOURCC_hvcC:
10823                 {
10824                   /* parse, if found */
10825                   GstBuffer *buf;
10826
10827                   GST_DEBUG_OBJECT (qtdemux, "found hvcC codec_data in stsd");
10828
10829                   /* First 4 bytes are the length of the atom, the next 4 bytes
10830                    * are the fourcc, the next 1 byte is the version, and the
10831                    * subsequent bytes are sequence parameter set like data. */
10832                   gst_codec_utils_h265_caps_set_level_tier_and_profile
10833                       (entry->caps, hevc_data + 8 + 1, size - 1);
10834
10835                   buf = gst_buffer_new_and_alloc (size);
10836                   gst_buffer_fill (buf, 0, hevc_data + 0x8, size);
10837                   gst_caps_set_simple (entry->caps,
10838                       "codec_data", GST_TYPE_BUFFER, buf, NULL);
10839                   gst_buffer_unref (buf);
10840                   break;
10841                 }
10842                 default:
10843                   break;
10844               }
10845               len -= size + 8;
10846               hevc_data += size + 8;
10847             }
10848             break;
10849           }
10850           case FOURCC_mp4v:
10851           case FOURCC_MP4V:
10852           case FOURCC_fmp4:
10853           case FOURCC_FMP4:
10854           case FOURCC_xvid:
10855           case FOURCC_XVID:
10856           {
10857             GNode *glbl;
10858
10859             GST_DEBUG_OBJECT (qtdemux, "found %" GST_FOURCC_FORMAT,
10860                 GST_FOURCC_ARGS (fourcc));
10861
10862             /* codec data might be in glbl extension atom */
10863             glbl = mp4v ?
10864                 qtdemux_tree_get_child_by_type (mp4v, FOURCC_glbl) : NULL;
10865             if (glbl) {
10866               guint8 *data;
10867               GstBuffer *buf;
10868               gint len;
10869
10870               GST_DEBUG_OBJECT (qtdemux, "found glbl data in stsd");
10871               data = glbl->data;
10872               len = QT_UINT32 (data);
10873               if (len > 0x8) {
10874                 len -= 0x8;
10875                 buf = gst_buffer_new_and_alloc (len);
10876                 gst_buffer_fill (buf, 0, data + 8, len);
10877                 gst_caps_set_simple (entry->caps,
10878                     "codec_data", GST_TYPE_BUFFER, buf, NULL);
10879                 gst_buffer_unref (buf);
10880               }
10881             }
10882             break;
10883           }
10884           case FOURCC_mjp2:
10885           {
10886             /* see annex I of the jpeg2000 spec */
10887             GNode *jp2h, *ihdr, *colr, *mjp2, *field, *prefix, *cmap, *cdef;
10888             const guint8 *data;
10889             const gchar *colorspace = NULL;
10890             gint ncomp = 0;
10891             guint32 ncomp_map = 0;
10892             gint32 *comp_map = NULL;
10893             guint32 nchan_def = 0;
10894             gint32 *chan_def = NULL;
10895
10896             GST_DEBUG_OBJECT (qtdemux, "found mjp2");
10897             /* some required atoms */
10898             mjp2 = qtdemux_tree_get_child_by_index (stsd, stsd_index);
10899             if (!mjp2)
10900               break;
10901             jp2h = qtdemux_tree_get_child_by_type (mjp2, FOURCC_jp2h);
10902             if (!jp2h)
10903               break;
10904
10905             /* number of components; redundant with info in codestream, but useful
10906                to a muxer */
10907             ihdr = qtdemux_tree_get_child_by_type (jp2h, FOURCC_ihdr);
10908             if (!ihdr || QT_UINT32 (ihdr->data) != 22)
10909               break;
10910             ncomp = QT_UINT16 (((guint8 *) ihdr->data) + 16);
10911
10912             colr = qtdemux_tree_get_child_by_type (jp2h, FOURCC_colr);
10913             if (!colr)
10914               break;
10915             GST_DEBUG_OBJECT (qtdemux, "found colr");
10916             /* extract colour space info */
10917             if (QT_UINT8 ((guint8 *) colr->data + 8) == 1) {
10918               switch (QT_UINT32 ((guint8 *) colr->data + 11)) {
10919                 case 16:
10920                   colorspace = "sRGB";
10921                   break;
10922                 case 17:
10923                   colorspace = "GRAY";
10924                   break;
10925                 case 18:
10926                   colorspace = "sYUV";
10927                   break;
10928                 default:
10929                   colorspace = NULL;
10930                   break;
10931               }
10932             }
10933             if (!colorspace)
10934               /* colr is required, and only values 16, 17, and 18 are specified,
10935                  so error if we have no colorspace */
10936               break;
10937
10938             /* extract component mapping */
10939             cmap = qtdemux_tree_get_child_by_type (jp2h, FOURCC_cmap);
10940             if (cmap) {
10941               guint32 cmap_len = 0;
10942               int i;
10943               cmap_len = QT_UINT32 (cmap->data);
10944               if (cmap_len >= 8) {
10945                 /* normal box, subtract off header */
10946                 cmap_len -= 8;
10947                 /* cmap: { u16 cmp; u8 mtyp; u8 pcol; }* */
10948                 if (cmap_len % 4 == 0) {
10949                   ncomp_map = (cmap_len / 4);
10950                   comp_map = g_new0 (gint32, ncomp_map);
10951                   for (i = 0; i < ncomp_map; i++) {
10952                     guint16 cmp;
10953                     guint8 mtyp, pcol;
10954                     cmp = QT_UINT16 (((guint8 *) cmap->data) + 8 + i * 4);
10955                     mtyp = QT_UINT8 (((guint8 *) cmap->data) + 8 + i * 4 + 2);
10956                     pcol = QT_UINT8 (((guint8 *) cmap->data) + 8 + i * 4 + 3);
10957                     comp_map[i] = (mtyp << 24) | (pcol << 16) | cmp;
10958                   }
10959                 }
10960               }
10961             }
10962             /* extract channel definitions */
10963             cdef = qtdemux_tree_get_child_by_type (jp2h, FOURCC_cdef);
10964             if (cdef) {
10965               guint32 cdef_len = 0;
10966               int i;
10967               cdef_len = QT_UINT32 (cdef->data);
10968               if (cdef_len >= 10) {
10969                 /* normal box, subtract off header and len */
10970                 cdef_len -= 10;
10971                 /* cdef: u16 n; { u16 cn; u16 typ; u16 asoc; }* */
10972                 if (cdef_len % 6 == 0) {
10973                   nchan_def = (cdef_len / 6);
10974                   chan_def = g_new0 (gint32, nchan_def);
10975                   for (i = 0; i < nchan_def; i++)
10976                     chan_def[i] = -1;
10977                   for (i = 0; i < nchan_def; i++) {
10978                     guint16 cn, typ, asoc;
10979                     cn = QT_UINT16 (((guint8 *) cdef->data) + 10 + i * 6);
10980                     typ = QT_UINT16 (((guint8 *) cdef->data) + 10 + i * 6 + 2);
10981                     asoc = QT_UINT16 (((guint8 *) cdef->data) + 10 + i * 6 + 4);
10982                     if (cn < nchan_def) {
10983                       switch (typ) {
10984                         case 0:
10985                           chan_def[cn] = asoc;
10986                           break;
10987                         case 1:
10988                           chan_def[cn] = 0;     /* alpha */
10989                           break;
10990                         default:
10991                           chan_def[cn] = -typ;
10992                       }
10993                     }
10994                   }
10995                 }
10996               }
10997             }
10998
10999             gst_caps_set_simple (entry->caps,
11000                 "num-components", G_TYPE_INT, ncomp, NULL);
11001             gst_caps_set_simple (entry->caps,
11002                 "colorspace", G_TYPE_STRING, colorspace, NULL);
11003
11004             if (comp_map) {
11005               GValue arr = { 0, };
11006               GValue elt = { 0, };
11007               int i;
11008               g_value_init (&arr, GST_TYPE_ARRAY);
11009               g_value_init (&elt, G_TYPE_INT);
11010               for (i = 0; i < ncomp_map; i++) {
11011                 g_value_set_int (&elt, comp_map[i]);
11012                 gst_value_array_append_value (&arr, &elt);
11013               }
11014               gst_structure_set_value (gst_caps_get_structure (entry->caps, 0),
11015                   "component-map", &arr);
11016               g_value_unset (&elt);
11017               g_value_unset (&arr);
11018               g_free (comp_map);
11019             }
11020
11021             if (chan_def) {
11022               GValue arr = { 0, };
11023               GValue elt = { 0, };
11024               int i;
11025               g_value_init (&arr, GST_TYPE_ARRAY);
11026               g_value_init (&elt, G_TYPE_INT);
11027               for (i = 0; i < nchan_def; i++) {
11028                 g_value_set_int (&elt, chan_def[i]);
11029                 gst_value_array_append_value (&arr, &elt);
11030               }
11031               gst_structure_set_value (gst_caps_get_structure (entry->caps, 0),
11032                   "channel-definitions", &arr);
11033               g_value_unset (&elt);
11034               g_value_unset (&arr);
11035               g_free (chan_def);
11036             }
11037
11038             /* some optional atoms */
11039             field = qtdemux_tree_get_child_by_type (mjp2, FOURCC_fiel);
11040             prefix = qtdemux_tree_get_child_by_type (mjp2, FOURCC_jp2x);
11041
11042             /* indicate possible fields in caps */
11043             if (field) {
11044               data = (guint8 *) field->data + 8;
11045               if (*data != 1)
11046                 gst_caps_set_simple (entry->caps, "fields", G_TYPE_INT,
11047                     (gint) * data, NULL);
11048             }
11049             /* add codec_data if provided */
11050             if (prefix) {
11051               GstBuffer *buf;
11052               gint len;
11053
11054               GST_DEBUG_OBJECT (qtdemux, "found prefix data in stsd");
11055               data = prefix->data;
11056               len = QT_UINT32 (data);
11057               if (len > 0x8) {
11058                 len -= 0x8;
11059                 buf = gst_buffer_new_and_alloc (len);
11060                 gst_buffer_fill (buf, 0, data + 8, len);
11061                 gst_caps_set_simple (entry->caps,
11062                     "codec_data", GST_TYPE_BUFFER, buf, NULL);
11063                 gst_buffer_unref (buf);
11064               }
11065             }
11066             break;
11067           }
11068           case FOURCC_SVQ3:
11069           case FOURCC_VP31:
11070           {
11071             GstBuffer *buf;
11072             GstBuffer *seqh = NULL;
11073             const guint8 *gamma_data = NULL;
11074             gint len = QT_UINT32 (stsd_data);   /* FIXME review - why put the whole stsd in codec data? */
11075
11076             qtdemux_parse_svq3_stsd_data (qtdemux, stsd_entry_data, &gamma_data,
11077                 &seqh);
11078             if (gamma_data) {
11079               gst_caps_set_simple (entry->caps, "applied-gamma", G_TYPE_DOUBLE,
11080                   QT_FP32 (gamma_data), NULL);
11081             }
11082             if (seqh) {
11083               /* sorry for the bad name, but we don't know what this is, other
11084                * than its own fourcc */
11085               gst_caps_set_simple (entry->caps, "seqh", GST_TYPE_BUFFER, seqh,
11086                   NULL);
11087               gst_buffer_unref (seqh);
11088             }
11089
11090             GST_DEBUG_OBJECT (qtdemux, "found codec_data in stsd");
11091             buf = gst_buffer_new_and_alloc (len);
11092             gst_buffer_fill (buf, 0, stsd_data, len);
11093             gst_caps_set_simple (entry->caps,
11094                 "codec_data", GST_TYPE_BUFFER, buf, NULL);
11095             gst_buffer_unref (buf);
11096             break;
11097           }
11098           case FOURCC_jpeg:
11099           {
11100             /* https://developer.apple.com/standards/qtff-2001.pdf,
11101              * page 92, "Video Sample Description", under table 3.1 */
11102             GstByteReader br;
11103
11104             const gint compressor_offset =
11105                 16 + 4 + 4 * 3 + 2 * 2 + 2 * 4 + 4 + 2;
11106             const gint min_size = compressor_offset + 32 + 2 + 2;
11107             GNode *jpeg;
11108             guint32 len;
11109             guint16 color_table_id = 0;
11110             gboolean ok;
11111
11112             GST_DEBUG_OBJECT (qtdemux, "found jpeg");
11113
11114             /* recover information on interlaced/progressive */
11115             jpeg = qtdemux_tree_get_child_by_type (stsd, FOURCC_jpeg);
11116             if (!jpeg)
11117               break;
11118
11119             len = QT_UINT32 (jpeg->data);
11120             GST_DEBUG_OBJECT (qtdemux, "Found jpeg: len %u, need %d", len,
11121                 min_size);
11122             if (len >= min_size) {
11123               gst_byte_reader_init (&br, jpeg->data, len);
11124
11125               gst_byte_reader_skip (&br, compressor_offset + 32 + 2);
11126               gst_byte_reader_get_uint16_le (&br, &color_table_id);
11127               if (color_table_id != 0) {
11128                 /* the spec says there can be concatenated chunks in the data, and we want
11129                  * to find one called field. Walk through them. */
11130                 gint offset = min_size;
11131                 while (offset + 8 < len) {
11132                   guint32 size = 0, tag;
11133                   ok = gst_byte_reader_get_uint32_le (&br, &size);
11134                   ok &= gst_byte_reader_get_uint32_le (&br, &tag);
11135                   if (!ok || size < 8) {
11136                     GST_WARNING_OBJECT (qtdemux,
11137                         "Failed to walk optional chunk list");
11138                     break;
11139                   }
11140                   GST_DEBUG_OBJECT (qtdemux,
11141                       "Found optional %4.4s chunk, size %u",
11142                       (const char *) &tag, size);
11143                   if (tag == FOURCC_fiel) {
11144                     guint8 n_fields = 0, ordering = 0;
11145                     gst_byte_reader_get_uint8 (&br, &n_fields);
11146                     gst_byte_reader_get_uint8 (&br, &ordering);
11147                     if (n_fields == 1 || n_fields == 2) {
11148                       GST_DEBUG_OBJECT (qtdemux,
11149                           "Found fiel tag with %u fields, ordering %u",
11150                           n_fields, ordering);
11151                       if (n_fields == 2)
11152                         gst_caps_set_simple (CUR_STREAM (stream)->caps,
11153                             "interlace-mode", G_TYPE_STRING, "interleaved",
11154                             NULL);
11155                     } else {
11156                       GST_WARNING_OBJECT (qtdemux,
11157                           "Found fiel tag with invalid fields (%u)", n_fields);
11158                     }
11159                   }
11160                   offset += size;
11161                 }
11162               } else {
11163                 GST_DEBUG_OBJECT (qtdemux,
11164                     "Color table ID is 0, not trying to get interlacedness");
11165               }
11166             } else {
11167               GST_WARNING_OBJECT (qtdemux,
11168                   "Length of jpeg chunk is too small, not trying to get interlacedness");
11169             }
11170
11171             break;
11172           }
11173           case FOURCC_rle_:
11174           case FOURCC_WRLE:
11175           {
11176             gst_caps_set_simple (entry->caps,
11177                 "depth", G_TYPE_INT, QT_UINT16 (stsd_entry_data + offset + 66),
11178                 NULL);
11179             break;
11180           }
11181           case FOURCC_XiTh:
11182           {
11183             GNode *xith, *xdxt;
11184
11185             GST_DEBUG_OBJECT (qtdemux, "found XiTh");
11186             xith = qtdemux_tree_get_child_by_index (stsd, stsd_index);
11187             if (!xith)
11188               break;
11189
11190             xdxt = qtdemux_tree_get_child_by_type (xith, FOURCC_XdxT);
11191             if (!xdxt)
11192               break;
11193
11194             GST_DEBUG_OBJECT (qtdemux, "found XdxT node");
11195             /* collect the headers and store them in a stream list so that we can
11196              * send them out first */
11197             qtdemux_parse_theora_extension (qtdemux, stream, xdxt);
11198             break;
11199           }
11200           case FOURCC_ovc1:
11201           {
11202             GNode *ovc1;
11203             guint8 *ovc1_data;
11204             guint ovc1_len;
11205             GstBuffer *buf;
11206
11207             GST_DEBUG_OBJECT (qtdemux, "parse ovc1 header");
11208             ovc1 = qtdemux_tree_get_child_by_index (stsd, stsd_index);
11209             if (!ovc1)
11210               break;
11211             ovc1_data = ovc1->data;
11212             ovc1_len = QT_UINT32 (ovc1_data);
11213             if (ovc1_len <= 198) {
11214               GST_WARNING_OBJECT (qtdemux, "Too small ovc1 header, skipping");
11215               break;
11216             }
11217             buf = gst_buffer_new_and_alloc (ovc1_len - 198);
11218             gst_buffer_fill (buf, 0, ovc1_data + 198, ovc1_len - 198);
11219             gst_caps_set_simple (entry->caps,
11220                 "codec_data", GST_TYPE_BUFFER, buf, NULL);
11221             gst_buffer_unref (buf);
11222             break;
11223           }
11224           case FOURCC_vc_1:
11225           {
11226             gint len = QT_UINT32 (stsd_entry_data) - 0x56;
11227             const guint8 *vc1_data = stsd_entry_data + 0x56;
11228
11229             /* find dvc1 */
11230             while (len >= 8) {
11231               gint size;
11232
11233               if (QT_UINT32 (vc1_data) <= len)
11234                 size = QT_UINT32 (vc1_data) - 8;
11235               else
11236                 size = len - 8;
11237
11238               if (size < 1)
11239                 /* No real data, so break out */
11240                 break;
11241
11242               switch (QT_FOURCC (vc1_data + 0x4)) {
11243                 case GST_MAKE_FOURCC ('d', 'v', 'c', '1'):
11244                 {
11245                   GstBuffer *buf;
11246
11247                   GST_DEBUG_OBJECT (qtdemux, "found dvc1 codec_data in stsd");
11248                   buf = gst_buffer_new_and_alloc (size);
11249                   gst_buffer_fill (buf, 0, vc1_data + 8, size);
11250                   gst_caps_set_simple (entry->caps,
11251                       "codec_data", GST_TYPE_BUFFER, buf, NULL);
11252                   gst_buffer_unref (buf);
11253                   break;
11254                 }
11255                 default:
11256                   break;
11257               }
11258               len -= size + 8;
11259               vc1_data += size + 8;
11260             }
11261             break;
11262           }
11263           case FOURCC_av01:
11264           {
11265             gint len = QT_UINT32 (stsd_entry_data) - 0x56;
11266             const guint8 *av1_data = stsd_entry_data + 0x56;
11267
11268             /* find av1C */
11269             while (len >= 0x8) {
11270               gint size;
11271
11272               if (QT_UINT32 (av1_data) <= len)
11273                 size = QT_UINT32 (av1_data) - 0x8;
11274               else
11275                 size = len - 0x8;
11276
11277               if (size < 1)
11278                 /* No real data, so break out */
11279                 break;
11280
11281               switch (QT_FOURCC (av1_data + 0x4)) {
11282                 case FOURCC_av1C:
11283                 {
11284                   /* parse, if found */
11285                   GstBuffer *buf;
11286                   guint8 pres_delay_field;
11287
11288                   GST_DEBUG_OBJECT (qtdemux,
11289                       "found av1C codec_data in stsd of size %d", size);
11290
11291                   /* not enough data, just ignore and hope for the best */
11292                   if (size < 5)
11293                     break;
11294
11295                   /* Content is:
11296                    * 4 bytes: atom length
11297                    * 4 bytes: fourcc
11298                    * 1 byte: version
11299                    * 3 bytes: flags
11300                    * 3 bits: reserved
11301                    * 1 bits:  initial_presentation_delay_present
11302                    * 4 bits: initial_presentation_delay (if present else reserved
11303                    * rest: OBUs.
11304                    */
11305
11306                   if (av1_data[9] != 0) {
11307                     GST_WARNING ("Unknown version %d of av1C box", av1_data[9]);
11308                     break;
11309                   }
11310
11311                   /* We skip initial_presentation_delay* for now */
11312                   pres_delay_field = *(av1_data + 12);
11313                   if (pres_delay_field & (1 << 5)) {
11314                     gst_caps_set_simple (entry->caps,
11315                         "presentation-delay", G_TYPE_INT,
11316                         (gint) (pres_delay_field & 0x0F) + 1, NULL);
11317                   }
11318                   if (size > 5) {
11319                     buf = gst_buffer_new_and_alloc (size - 5);
11320                     GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_HEADER);
11321                     gst_buffer_fill (buf, 0, av1_data + 13, size - 5);
11322                     gst_caps_set_simple (entry->caps,
11323                         "codec_data", GST_TYPE_BUFFER, buf, NULL);
11324                     gst_buffer_unref (buf);
11325                   }
11326                   break;
11327                 }
11328                 default:
11329                   break;
11330               }
11331
11332               len -= size + 8;
11333               av1_data += size + 8;
11334             }
11335
11336             break;
11337           }
11338           default:
11339             break;
11340         }
11341       }
11342
11343       GST_INFO_OBJECT (qtdemux,
11344           "type %" GST_FOURCC_FORMAT " caps %" GST_PTR_FORMAT,
11345           GST_FOURCC_ARGS (fourcc), entry->caps);
11346
11347     } else if (stream->subtype == FOURCC_soun) {
11348       GNode *wave;
11349       int version, samplesize;
11350       guint16 compression_id;
11351       gboolean amrwb = FALSE;
11352
11353       offset = 16;
11354       /* sample description entry (16) + sound sample description v0 (20) */
11355       if (len < 36)
11356         goto corrupt_file;
11357
11358       version = QT_UINT32 (stsd_entry_data + offset);
11359       entry->n_channels = QT_UINT16 (stsd_entry_data + offset + 8);
11360       samplesize = QT_UINT16 (stsd_entry_data + offset + 10);
11361       compression_id = QT_UINT16 (stsd_entry_data + offset + 12);
11362       entry->rate = QT_FP32 (stsd_entry_data + offset + 16);
11363
11364       GST_LOG_OBJECT (qtdemux, "version/rev:      %08x", version);
11365       GST_LOG_OBJECT (qtdemux, "vendor:           %08x",
11366           QT_UINT32 (stsd_entry_data + offset + 4));
11367       GST_LOG_OBJECT (qtdemux, "n_channels:       %d", entry->n_channels);
11368       GST_LOG_OBJECT (qtdemux, "sample_size:      %d", samplesize);
11369       GST_LOG_OBJECT (qtdemux, "compression_id:   %d", compression_id);
11370       GST_LOG_OBJECT (qtdemux, "packet size:      %d",
11371           QT_UINT16 (stsd_entry_data + offset + 14));
11372       GST_LOG_OBJECT (qtdemux, "sample rate:      %g", entry->rate);
11373
11374       if (compression_id == 0xfffe)
11375         entry->sampled = TRUE;
11376
11377       /* first assume uncompressed audio */
11378       entry->bytes_per_sample = samplesize / 8;
11379       entry->samples_per_frame = entry->n_channels;
11380       entry->bytes_per_frame = entry->n_channels * entry->bytes_per_sample;
11381       entry->samples_per_packet = entry->samples_per_frame;
11382       entry->bytes_per_packet = entry->bytes_per_sample;
11383
11384       offset = 36;
11385       switch (fourcc) {
11386           /* Yes, these have to be hard-coded */
11387         case FOURCC_MAC6:
11388         {
11389           entry->samples_per_packet = 6;
11390           entry->bytes_per_packet = 1;
11391           entry->bytes_per_frame = 1 * entry->n_channels;
11392           entry->bytes_per_sample = 1;
11393           entry->samples_per_frame = 6 * entry->n_channels;
11394           break;
11395         }
11396         case FOURCC_MAC3:
11397         {
11398           entry->samples_per_packet = 3;
11399           entry->bytes_per_packet = 1;
11400           entry->bytes_per_frame = 1 * entry->n_channels;
11401           entry->bytes_per_sample = 1;
11402           entry->samples_per_frame = 3 * entry->n_channels;
11403           break;
11404         }
11405         case FOURCC_ima4:
11406         {
11407           entry->samples_per_packet = 64;
11408           entry->bytes_per_packet = 34;
11409           entry->bytes_per_frame = 34 * entry->n_channels;
11410           entry->bytes_per_sample = 2;
11411           entry->samples_per_frame = 64 * entry->n_channels;
11412           break;
11413         }
11414         case FOURCC_ulaw:
11415         case FOURCC_alaw:
11416         {
11417           entry->samples_per_packet = 1;
11418           entry->bytes_per_packet = 1;
11419           entry->bytes_per_frame = 1 * entry->n_channels;
11420           entry->bytes_per_sample = 1;
11421           entry->samples_per_frame = 1 * entry->n_channels;
11422           break;
11423         }
11424         case FOURCC_agsm:
11425         {
11426           entry->samples_per_packet = 160;
11427           entry->bytes_per_packet = 33;
11428           entry->bytes_per_frame = 33 * entry->n_channels;
11429           entry->bytes_per_sample = 2;
11430           entry->samples_per_frame = 160 * entry->n_channels;
11431           break;
11432         }
11433         default:
11434           break;
11435       }
11436
11437       if (version == 0x00010000) {
11438         /* sample description entry (16) + sound sample description v1 (20+16) */
11439         if (len < 52)
11440           goto corrupt_file;
11441
11442         switch (fourcc) {
11443           case FOURCC_twos:
11444           case FOURCC_sowt:
11445           case FOURCC_raw_:
11446           case FOURCC_lpcm:
11447             break;
11448           default:
11449           {
11450             /* only parse extra decoding config for non-pcm audio */
11451             entry->samples_per_packet = QT_UINT32 (stsd_entry_data + offset);
11452             entry->bytes_per_packet = QT_UINT32 (stsd_entry_data + offset + 4);
11453             entry->bytes_per_frame = QT_UINT32 (stsd_entry_data + offset + 8);
11454             entry->bytes_per_sample = QT_UINT32 (stsd_entry_data + offset + 12);
11455
11456             GST_LOG_OBJECT (qtdemux, "samples/packet:   %d",
11457                 entry->samples_per_packet);
11458             GST_LOG_OBJECT (qtdemux, "bytes/packet:     %d",
11459                 entry->bytes_per_packet);
11460             GST_LOG_OBJECT (qtdemux, "bytes/frame:      %d",
11461                 entry->bytes_per_frame);
11462             GST_LOG_OBJECT (qtdemux, "bytes/sample:     %d",
11463                 entry->bytes_per_sample);
11464
11465             if (!entry->sampled && entry->bytes_per_packet) {
11466               entry->samples_per_frame = (entry->bytes_per_frame /
11467                   entry->bytes_per_packet) * entry->samples_per_packet;
11468               GST_LOG_OBJECT (qtdemux, "samples/frame:    %d",
11469                   entry->samples_per_frame);
11470             }
11471             break;
11472           }
11473         }
11474       } else if (version == 0x00020000) {
11475         union
11476         {
11477           gdouble fp;
11478           guint64 val;
11479         } qtfp;
11480
11481         /* sample description entry (16) + sound sample description v2 (56) */
11482         if (len < 72)
11483           goto corrupt_file;
11484
11485         qtfp.val = QT_UINT64 (stsd_entry_data + offset + 4);
11486         entry->rate = qtfp.fp;
11487         entry->n_channels = QT_UINT32 (stsd_entry_data + offset + 12);
11488
11489         GST_LOG_OBJECT (qtdemux, "Sound sample description Version 2");
11490         GST_LOG_OBJECT (qtdemux, "sample rate:        %g", entry->rate);
11491         GST_LOG_OBJECT (qtdemux, "n_channels:         %d", entry->n_channels);
11492         GST_LOG_OBJECT (qtdemux, "bits/channel:       %d",
11493             QT_UINT32 (stsd_entry_data + offset + 20));
11494         GST_LOG_OBJECT (qtdemux, "format flags:       %X",
11495             QT_UINT32 (stsd_entry_data + offset + 24));
11496         GST_LOG_OBJECT (qtdemux, "bytes/packet:       %d",
11497             QT_UINT32 (stsd_entry_data + offset + 28));
11498         GST_LOG_OBJECT (qtdemux, "LPCM frames/packet: %d",
11499             QT_UINT32 (stsd_entry_data + offset + 32));
11500       } else if (version != 0x00000) {
11501         GST_WARNING_OBJECT (qtdemux, "unknown audio STSD version %08x",
11502             version);
11503       }
11504
11505       if (entry->caps)
11506         gst_caps_unref (entry->caps);
11507
11508       entry->caps = qtdemux_audio_caps (qtdemux, stream, entry, fourcc,
11509           stsd_entry_data + 32, len - 16, &codec);
11510
11511       switch (fourcc) {
11512         case FOURCC_in24:
11513         {
11514           GNode *enda;
11515           GNode *in24;
11516
11517           in24 = qtdemux_tree_get_child_by_type (stsd, FOURCC_in24);
11518
11519           enda = qtdemux_tree_get_child_by_type (in24, FOURCC_enda);
11520           if (!enda) {
11521             wave = qtdemux_tree_get_child_by_type (in24, FOURCC_wave);
11522             if (wave)
11523               enda = qtdemux_tree_get_child_by_type (wave, FOURCC_enda);
11524           }
11525           if (enda) {
11526             int enda_value = QT_UINT16 ((guint8 *) enda->data + 8);
11527             gst_caps_set_simple (entry->caps,
11528                 "format", G_TYPE_STRING, (enda_value) ? "S24LE" : "S24BE",
11529                 NULL);
11530           }
11531           break;
11532         }
11533         case FOURCC_owma:
11534         {
11535           const guint8 *owma_data;
11536           const gchar *codec_name = NULL;
11537           guint owma_len;
11538           GstBuffer *buf;
11539           gint version = 1;
11540           /* from http://msdn.microsoft.com/en-us/library/dd757720(VS.85).aspx */
11541           /* FIXME this should also be gst_riff_strf_auds,
11542            * but the latter one is actually missing bits-per-sample :( */
11543           typedef struct
11544           {
11545             gint16 wFormatTag;
11546             gint16 nChannels;
11547             gint32 nSamplesPerSec;
11548             gint32 nAvgBytesPerSec;
11549             gint16 nBlockAlign;
11550             gint16 wBitsPerSample;
11551             gint16 cbSize;
11552           } WAVEFORMATEX;
11553           WAVEFORMATEX *wfex;
11554
11555           GST_DEBUG_OBJECT (qtdemux, "parse owma");
11556           owma_data = stsd_entry_data;
11557           owma_len = QT_UINT32 (owma_data);
11558           if (owma_len <= 54) {
11559             GST_WARNING_OBJECT (qtdemux, "Too small owma header, skipping");
11560             break;
11561           }
11562           wfex = (WAVEFORMATEX *) (owma_data + 36);
11563           buf = gst_buffer_new_and_alloc (owma_len - 54);
11564           gst_buffer_fill (buf, 0, owma_data + 54, owma_len - 54);
11565           if (wfex->wFormatTag == 0x0161) {
11566             codec_name = "Windows Media Audio";
11567             version = 2;
11568           } else if (wfex->wFormatTag == 0x0162) {
11569             codec_name = "Windows Media Audio 9 Pro";
11570             version = 3;
11571           } else if (wfex->wFormatTag == 0x0163) {
11572             codec_name = "Windows Media Audio 9 Lossless";
11573             /* is that correct? gstffmpegcodecmap.c is missing it, but
11574              * fluendo codec seems to support it */
11575             version = 4;
11576           }
11577
11578           gst_caps_set_simple (entry->caps,
11579               "codec_data", GST_TYPE_BUFFER, buf,
11580               "wmaversion", G_TYPE_INT, version,
11581               "block_align", G_TYPE_INT,
11582               GST_READ_UINT16_LE (&wfex->nBlockAlign), "bitrate", G_TYPE_INT,
11583               GST_READ_UINT32_LE (&wfex->nAvgBytesPerSec), "width", G_TYPE_INT,
11584               GST_READ_UINT16_LE (&wfex->wBitsPerSample), "depth", G_TYPE_INT,
11585               GST_READ_UINT16_LE (&wfex->wBitsPerSample), NULL);
11586           gst_buffer_unref (buf);
11587
11588           if (codec_name) {
11589             g_free (codec);
11590             codec = g_strdup (codec_name);
11591           }
11592           break;
11593         }
11594         case FOURCC_wma_:
11595         {
11596           gint len = QT_UINT32 (stsd_entry_data) - offset;
11597           const guint8 *wfex_data = stsd_entry_data + offset;
11598           const gchar *codec_name = NULL;
11599           gint version = 1;
11600           /* from http://msdn.microsoft.com/en-us/library/dd757720(VS.85).aspx */
11601           /* FIXME this should also be gst_riff_strf_auds,
11602            * but the latter one is actually missing bits-per-sample :( */
11603           typedef struct
11604           {
11605             gint16 wFormatTag;
11606             gint16 nChannels;
11607             gint32 nSamplesPerSec;
11608             gint32 nAvgBytesPerSec;
11609             gint16 nBlockAlign;
11610             gint16 wBitsPerSample;
11611             gint16 cbSize;
11612           } WAVEFORMATEX;
11613           WAVEFORMATEX wfex;
11614
11615           /* FIXME: unify with similar wavformatex parsing code above */
11616           GST_DEBUG_OBJECT (qtdemux, "parse wma, looking for wfex");
11617
11618           /* find wfex */
11619           while (len >= 8) {
11620             gint size;
11621
11622             if (QT_UINT32 (wfex_data) <= len)
11623               size = QT_UINT32 (wfex_data) - 8;
11624             else
11625               size = len - 8;
11626
11627             if (size < 1)
11628               /* No real data, so break out */
11629               break;
11630
11631             switch (QT_FOURCC (wfex_data + 4)) {
11632               case GST_MAKE_FOURCC ('w', 'f', 'e', 'x'):
11633               {
11634                 GST_DEBUG_OBJECT (qtdemux, "found wfex in stsd");
11635
11636                 if (size < 8 + 18)
11637                   break;
11638
11639                 wfex.wFormatTag = GST_READ_UINT16_LE (wfex_data + 8 + 0);
11640                 wfex.nChannels = GST_READ_UINT16_LE (wfex_data + 8 + 2);
11641                 wfex.nSamplesPerSec = GST_READ_UINT32_LE (wfex_data + 8 + 4);
11642                 wfex.nAvgBytesPerSec = GST_READ_UINT32_LE (wfex_data + 8 + 8);
11643                 wfex.nBlockAlign = GST_READ_UINT16_LE (wfex_data + 8 + 12);
11644                 wfex.wBitsPerSample = GST_READ_UINT16_LE (wfex_data + 8 + 14);
11645                 wfex.cbSize = GST_READ_UINT16_LE (wfex_data + 8 + 16);
11646
11647                 GST_LOG_OBJECT (qtdemux, "Found wfex box in stsd:");
11648                 GST_LOG_OBJECT (qtdemux, "FormatTag = 0x%04x, Channels = %u, "
11649                     "SamplesPerSec = %u, AvgBytesPerSec = %u, BlockAlign = %u, "
11650                     "BitsPerSample = %u, Size = %u", wfex.wFormatTag,
11651                     wfex.nChannels, wfex.nSamplesPerSec, wfex.nAvgBytesPerSec,
11652                     wfex.nBlockAlign, wfex.wBitsPerSample, wfex.cbSize);
11653
11654                 if (wfex.wFormatTag == 0x0161) {
11655                   codec_name = "Windows Media Audio";
11656                   version = 2;
11657                 } else if (wfex.wFormatTag == 0x0162) {
11658                   codec_name = "Windows Media Audio 9 Pro";
11659                   version = 3;
11660                 } else if (wfex.wFormatTag == 0x0163) {
11661                   codec_name = "Windows Media Audio 9 Lossless";
11662                   /* is that correct? gstffmpegcodecmap.c is missing it, but
11663                    * fluendo codec seems to support it */
11664                   version = 4;
11665                 }
11666
11667                 gst_caps_set_simple (entry->caps,
11668                     "wmaversion", G_TYPE_INT, version,
11669                     "block_align", G_TYPE_INT, wfex.nBlockAlign,
11670                     "bitrate", G_TYPE_INT, wfex.nAvgBytesPerSec,
11671                     "width", G_TYPE_INT, wfex.wBitsPerSample,
11672                     "depth", G_TYPE_INT, wfex.wBitsPerSample, NULL);
11673
11674                 if (size > wfex.cbSize) {
11675                   GstBuffer *buf;
11676
11677                   buf = gst_buffer_new_and_alloc (size - wfex.cbSize);
11678                   gst_buffer_fill (buf, 0, wfex_data + 8 + wfex.cbSize,
11679                       size - wfex.cbSize);
11680                   gst_caps_set_simple (entry->caps,
11681                       "codec_data", GST_TYPE_BUFFER, buf, NULL);
11682                   gst_buffer_unref (buf);
11683                 } else {
11684                   GST_WARNING_OBJECT (qtdemux, "no codec data");
11685                 }
11686
11687                 if (codec_name) {
11688                   g_free (codec);
11689                   codec = g_strdup (codec_name);
11690                 }
11691                 break;
11692               }
11693               default:
11694                 break;
11695             }
11696             len -= size + 8;
11697             wfex_data += size + 8;
11698           }
11699           break;
11700         }
11701         case FOURCC_opus:
11702         {
11703           const guint8 *opus_data;
11704           guint8 *channel_mapping = NULL;
11705           guint32 rate;
11706           guint8 channels;
11707           guint8 channel_mapping_family;
11708           guint8 stream_count;
11709           guint8 coupled_count;
11710           guint8 i;
11711
11712           opus_data = stsd_entry_data;
11713
11714           channels = GST_READ_UINT8 (opus_data + 45);
11715           rate = GST_READ_UINT32_LE (opus_data + 48);
11716           channel_mapping_family = GST_READ_UINT8 (opus_data + 54);
11717           stream_count = GST_READ_UINT8 (opus_data + 55);
11718           coupled_count = GST_READ_UINT8 (opus_data + 56);
11719
11720           if (channels > 0) {
11721             channel_mapping = g_malloc (channels * sizeof (guint8));
11722             for (i = 0; i < channels; i++)
11723               channel_mapping[i] = GST_READ_UINT8 (opus_data + i + 57);
11724           }
11725
11726           entry->caps = gst_codec_utils_opus_create_caps (rate, channels,
11727               channel_mapping_family, stream_count, coupled_count,
11728               channel_mapping);
11729           break;
11730         }
11731         default:
11732           break;
11733       }
11734
11735       if (codec) {
11736         GstStructure *s;
11737         gint bitrate = 0;
11738
11739         gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
11740             GST_TAG_AUDIO_CODEC, codec, NULL);
11741         g_free (codec);
11742         codec = NULL;
11743
11744         /* some bitrate info may have ended up in caps */
11745         s = gst_caps_get_structure (entry->caps, 0);
11746         gst_structure_get_int (s, "bitrate", &bitrate);
11747         if (bitrate > 0)
11748           gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
11749               GST_TAG_BITRATE, bitrate, NULL);
11750       }
11751
11752       mp4a = qtdemux_tree_get_child_by_index (stsd, stsd_index);
11753       if (!stream->protected) {
11754       } else {
11755         if (QTDEMUX_TREE_NODE_FOURCC (mp4v) != FOURCC_encv) {
11756           mp4v = NULL;
11757         }
11758       }
11759       if (stream->protected && fourcc == FOURCC_mp4a) {
11760         if (QTDEMUX_TREE_NODE_FOURCC (mp4a) != FOURCC_enca) {
11761           mp4a = NULL;
11762         }
11763       } else {
11764         if (QTDEMUX_TREE_NODE_FOURCC (mp4a) != FOURCC_mp4a) {
11765           mp4a = NULL;
11766         }
11767       }
11768
11769       wave = NULL;
11770       esds = NULL;
11771       if (mp4a) {
11772         wave = qtdemux_tree_get_child_by_type (mp4a, FOURCC_wave);
11773         if (wave)
11774           esds = qtdemux_tree_get_child_by_type (wave, FOURCC_esds);
11775         if (!esds)
11776           esds = qtdemux_tree_get_child_by_type (mp4a, FOURCC_esds);
11777       }
11778
11779
11780       /* If the fourcc's bottom 16 bits gives 'sm', then the top
11781          16 bits is a byte-swapped wave-style codec identifier,
11782          and we can find a WAVE header internally to a 'wave' atom here.
11783          This can more clearly be thought of as 'ms' as the top 16 bits, and a
11784          codec id as the bottom 16 bits - but byte-swapped to store in QT (which
11785          is big-endian).
11786        */
11787       if ((fourcc & 0xffff) == (('s' << 8) | 'm')) {
11788         if (len < offset + 20) {
11789           GST_WARNING_OBJECT (qtdemux, "No wave atom in MS-style audio");
11790         } else {
11791           guint32 datalen = QT_UINT32 (stsd_entry_data + offset + 16);
11792           const guint8 *data = stsd_entry_data + offset + 16;
11793           GNode *wavenode;
11794           GNode *waveheadernode;
11795
11796           wavenode = g_node_new ((guint8 *) data);
11797           if (qtdemux_parse_node (qtdemux, wavenode, data, datalen)) {
11798             const guint8 *waveheader;
11799             guint32 headerlen;
11800
11801             waveheadernode = qtdemux_tree_get_child_by_type (wavenode, fourcc);
11802             if (waveheadernode) {
11803               waveheader = (const guint8 *) waveheadernode->data;
11804               headerlen = QT_UINT32 (waveheader);
11805
11806               if (headerlen > 8) {
11807                 gst_riff_strf_auds *header = NULL;
11808                 GstBuffer *headerbuf;
11809                 GstBuffer *extra;
11810
11811                 waveheader += 8;
11812                 headerlen -= 8;
11813
11814                 headerbuf = gst_buffer_new_and_alloc (headerlen);
11815                 gst_buffer_fill (headerbuf, 0, waveheader, headerlen);
11816
11817                 if (gst_riff_parse_strf_auds (GST_ELEMENT_CAST (qtdemux),
11818                         headerbuf, &header, &extra)) {
11819                   gst_caps_unref (entry->caps);
11820                   /* FIXME: Need to do something with the channel reorder map */
11821                   entry->caps =
11822                       gst_riff_create_audio_caps (header->format, NULL, header,
11823                       extra, NULL, NULL, NULL);
11824
11825                   if (extra)
11826                     gst_buffer_unref (extra);
11827                   g_free (header);
11828                 }
11829               }
11830             } else
11831               GST_DEBUG ("Didn't find waveheadernode for this codec");
11832           }
11833           g_node_destroy (wavenode);
11834         }
11835       } else if (esds) {
11836         gst_qtdemux_handle_esds (qtdemux, stream, entry, esds,
11837             stream->stream_tags);
11838       } else {
11839         switch (fourcc) {
11840 #if 0
11841             /* FIXME: what is in the chunk? */
11842           case FOURCC_QDMC:
11843           {
11844             gint len = QT_UINT32 (stsd_data);
11845
11846             /* seems to be always = 116 = 0x74 */
11847             break;
11848           }
11849 #endif
11850           case FOURCC_QDM2:
11851           {
11852             gint len = QT_UINT32 (stsd_entry_data);
11853
11854             if (len > 0x3C) {
11855               GstBuffer *buf = gst_buffer_new_and_alloc (len - 0x3C);
11856
11857               gst_buffer_fill (buf, 0, stsd_entry_data + 0x3C, len - 0x3C);
11858               gst_caps_set_simple (entry->caps,
11859                   "codec_data", GST_TYPE_BUFFER, buf, NULL);
11860               gst_buffer_unref (buf);
11861             }
11862             gst_caps_set_simple (entry->caps,
11863                 "samplesize", G_TYPE_INT, samplesize, NULL);
11864             break;
11865           }
11866           case FOURCC_alac:
11867           {
11868             GNode *alac, *wave = NULL;
11869
11870             /* apparently, m4a has this atom appended directly in the stsd entry,
11871              * while mov has it in a wave atom */
11872             alac = qtdemux_tree_get_child_by_type (stsd, FOURCC_alac);
11873             if (alac) {
11874               /* alac now refers to stsd entry atom */
11875               wave = qtdemux_tree_get_child_by_type (alac, FOURCC_wave);
11876               if (wave)
11877                 alac = qtdemux_tree_get_child_by_type (wave, FOURCC_alac);
11878               else
11879                 alac = qtdemux_tree_get_child_by_type (alac, FOURCC_alac);
11880             }
11881             if (alac) {
11882               const guint8 *alac_data = alac->data;
11883               gint len = QT_UINT32 (alac->data);
11884               GstBuffer *buf;
11885
11886               if (len < 36) {
11887                 GST_DEBUG_OBJECT (qtdemux,
11888                     "discarding alac atom with unexpected len %d", len);
11889               } else {
11890                 /* codec-data contains alac atom size and prefix,
11891                  * ffmpeg likes it that way, not quite gst-ish though ...*/
11892                 buf = gst_buffer_new_and_alloc (len);
11893                 gst_buffer_fill (buf, 0, alac->data, len);
11894                 gst_caps_set_simple (entry->caps,
11895                     "codec_data", GST_TYPE_BUFFER, buf, NULL);
11896                 gst_buffer_unref (buf);
11897
11898                 entry->bytes_per_frame = QT_UINT32 (alac_data + 12);
11899                 entry->n_channels = QT_UINT8 (alac_data + 21);
11900                 entry->rate = QT_UINT32 (alac_data + 32);
11901               }
11902             }
11903             gst_caps_set_simple (entry->caps,
11904                 "samplesize", G_TYPE_INT, samplesize, NULL);
11905             break;
11906           }
11907           case FOURCC_fLaC:
11908           {
11909             /* The codingname of the sample entry is 'fLaC' */
11910             GNode *flac = qtdemux_tree_get_child_by_type (stsd, FOURCC_fLaC);
11911
11912             if (flac) {
11913               /* The 'dfLa' box is added to the sample entry to convey
11914                  initializing information for the decoder. */
11915               const GNode *dfla =
11916                   qtdemux_tree_get_child_by_type (flac, FOURCC_dfLa);
11917
11918               if (dfla) {
11919                 const guint32 len = QT_UINT32 (dfla->data);
11920
11921                 /* Must contain at least dfLa box header (12),
11922                  * METADATA_BLOCK_HEADER (4), METADATA_BLOCK_STREAMINFO (34) */
11923                 if (len < 50) {
11924                   GST_DEBUG_OBJECT (qtdemux,
11925                       "discarding dfla atom with unexpected len %d", len);
11926                 } else {
11927                   /* skip dfLa header to get the METADATA_BLOCKs */
11928                   const guint8 *metadata_blocks = (guint8 *) dfla->data + 12;
11929                   const guint32 metadata_blocks_len = len - 12;
11930
11931                   gchar *stream_marker = g_strdup ("fLaC");
11932                   GstBuffer *block = gst_buffer_new_wrapped (stream_marker,
11933                       strlen (stream_marker));
11934
11935                   guint32 index = 0;
11936                   guint32 remainder = 0;
11937                   guint32 block_size = 0;
11938                   gboolean is_last = FALSE;
11939
11940                   GValue array = G_VALUE_INIT;
11941                   GValue value = G_VALUE_INIT;
11942
11943                   g_value_init (&array, GST_TYPE_ARRAY);
11944                   g_value_init (&value, GST_TYPE_BUFFER);
11945
11946                   gst_value_set_buffer (&value, block);
11947                   gst_value_array_append_value (&array, &value);
11948                   g_value_reset (&value);
11949
11950                   gst_buffer_unref (block);
11951
11952                   /* check there's at least one METADATA_BLOCK_HEADER's worth
11953                    * of data, and we haven't already finished parsing */
11954                   while (!is_last && ((index + 3) < metadata_blocks_len)) {
11955                     remainder = metadata_blocks_len - index;
11956
11957                     /* add the METADATA_BLOCK_HEADER size to the signalled size */
11958                     block_size = 4 +
11959                         (metadata_blocks[index + 1] << 16) +
11960                         (metadata_blocks[index + 2] << 8) +
11961                         metadata_blocks[index + 3];
11962
11963                     /* be careful not to read off end of box */
11964                     if (block_size > remainder) {
11965                       break;
11966                     }
11967
11968                     is_last = metadata_blocks[index] >> 7;
11969
11970                     block = gst_buffer_new_and_alloc (block_size);
11971
11972                     gst_buffer_fill (block, 0, &metadata_blocks[index],
11973                         block_size);
11974
11975                     gst_value_set_buffer (&value, block);
11976                     gst_value_array_append_value (&array, &value);
11977                     g_value_reset (&value);
11978
11979                     gst_buffer_unref (block);
11980
11981                     index += block_size;
11982                   }
11983
11984                   /* only append the metadata if we successfully read all of it */
11985                   if (is_last) {
11986                     gst_structure_set_value (gst_caps_get_structure (CUR_STREAM
11987                             (stream)->caps, 0), "streamheader", &array);
11988                   } else {
11989                     GST_WARNING_OBJECT (qtdemux,
11990                         "discarding all METADATA_BLOCKs due to invalid "
11991                         "block_size %d at idx %d, rem %d", block_size, index,
11992                         remainder);
11993                   }
11994
11995                   g_value_unset (&value);
11996                   g_value_unset (&array);
11997
11998                   /* The sample rate obtained from the stsd may not be accurate
11999                    * since it cannot represent rates greater than 65535Hz, so
12000                    * override that value with the sample rate from the
12001                    * METADATA_BLOCK_STREAMINFO block */
12002                   CUR_STREAM (stream)->rate =
12003                       (QT_UINT32 (metadata_blocks + 14) >> 12) & 0xFFFFF;
12004                 }
12005               }
12006             }
12007             break;
12008           }
12009           case FOURCC_sawb:
12010             /* Fallthrough! */
12011             amrwb = TRUE;
12012           case FOURCC_samr:
12013           {
12014             gint len = QT_UINT32 (stsd_entry_data);
12015
12016             if (len > 0x24) {
12017               GstBuffer *buf = gst_buffer_new_and_alloc (len - 0x24);
12018               guint bitrate;
12019
12020               gst_buffer_fill (buf, 0, stsd_entry_data + 0x24, len - 0x24);
12021
12022               /* If we have enough data, let's try to get the 'damr' atom. See
12023                * the 3GPP container spec (26.244) for more details. */
12024               if ((len - 0x34) > 8 &&
12025                   (bitrate = qtdemux_parse_amr_bitrate (buf, amrwb))) {
12026                 gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
12027                     GST_TAG_MAXIMUM_BITRATE, bitrate, NULL);
12028               }
12029
12030               gst_caps_set_simple (entry->caps,
12031                   "codec_data", GST_TYPE_BUFFER, buf, NULL);
12032               gst_buffer_unref (buf);
12033             }
12034             break;
12035           }
12036           case FOURCC_mp4a:
12037           {
12038             /* mp4a atom withtout ESDS; Attempt to build codec data from atom */
12039             gint len = QT_UINT32 (stsd_entry_data);
12040
12041             if (len >= 34) {
12042               guint16 sound_version = QT_UINT16 (stsd_entry_data + 16);
12043
12044               if (sound_version == 1) {
12045                 guint16 channels = QT_UINT16 (stsd_entry_data + 24);
12046                 guint32 time_scale = QT_UINT32 (stsd_entry_data + 30);
12047                 guint8 codec_data[2];
12048                 GstBuffer *buf;
12049                 gint profile = 2;       /* FIXME: Can this be determined somehow? There doesn't seem to be anything in mp4a atom that specifis compression */
12050
12051                 gint sample_rate_index =
12052                     gst_codec_utils_aac_get_index_from_sample_rate (time_scale);
12053
12054                 /* build AAC codec data */
12055                 codec_data[0] = profile << 3;
12056                 codec_data[0] |= ((sample_rate_index >> 1) & 0x7);
12057                 codec_data[1] = (sample_rate_index & 0x01) << 7;
12058                 codec_data[1] |= (channels & 0xF) << 3;
12059
12060                 buf = gst_buffer_new_and_alloc (2);
12061                 gst_buffer_fill (buf, 0, codec_data, 2);
12062                 gst_caps_set_simple (entry->caps,
12063                     "codec_data", GST_TYPE_BUFFER, buf, NULL);
12064                 gst_buffer_unref (buf);
12065               }
12066             }
12067             break;
12068           }
12069           case FOURCC_lpcm:
12070             /* Fully handled elsewhere */
12071             break;
12072           default:
12073             GST_INFO_OBJECT (qtdemux,
12074                 "unhandled type %" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (fourcc));
12075             break;
12076         }
12077       }
12078       GST_INFO_OBJECT (qtdemux,
12079           "type %" GST_FOURCC_FORMAT " caps %" GST_PTR_FORMAT,
12080           GST_FOURCC_ARGS (fourcc), entry->caps);
12081
12082     } else if (stream->subtype == FOURCC_strm) {
12083       if (fourcc == FOURCC_rtsp) {
12084         stream->redirect_uri = qtdemux_get_rtsp_uri_from_hndl (qtdemux, minf);
12085       } else {
12086         GST_INFO_OBJECT (qtdemux, "unhandled stream type %" GST_FOURCC_FORMAT,
12087             GST_FOURCC_ARGS (fourcc));
12088         goto unknown_stream;
12089       }
12090       entry->sampled = TRUE;
12091     } else if (stream->subtype == FOURCC_subp || stream->subtype == FOURCC_text
12092         || stream->subtype == FOURCC_sbtl || stream->subtype == FOURCC_subt
12093         || stream->subtype == FOURCC_clcp) {
12094
12095       entry->sampled = TRUE;
12096       entry->sparse = TRUE;
12097
12098       entry->caps =
12099           qtdemux_sub_caps (qtdemux, stream, entry, fourcc, stsd_entry_data,
12100           &codec);
12101       if (codec) {
12102         gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
12103             GST_TAG_SUBTITLE_CODEC, codec, NULL);
12104         g_free (codec);
12105         codec = NULL;
12106       }
12107
12108       /* hunt for sort-of codec data */
12109       switch (fourcc) {
12110         case FOURCC_mp4s:
12111         {
12112           GNode *mp4s = NULL;
12113           GNode *esds = NULL;
12114
12115           /* look for palette in a stsd->mp4s->esds sub-atom */
12116           mp4s = qtdemux_tree_get_child_by_type (stsd, FOURCC_mp4s);
12117           if (mp4s)
12118             esds = qtdemux_tree_get_child_by_type (mp4s, FOURCC_esds);
12119           if (esds == NULL) {
12120             /* Invalid STSD */
12121             GST_LOG_OBJECT (qtdemux, "Skipping invalid stsd: no esds child");
12122             break;
12123           }
12124
12125           gst_qtdemux_handle_esds (qtdemux, stream, entry, esds,
12126               stream->stream_tags);
12127           break;
12128         }
12129         default:
12130           GST_INFO_OBJECT (qtdemux,
12131               "unhandled type %" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (fourcc));
12132           break;
12133       }
12134       GST_INFO_OBJECT (qtdemux,
12135           "type %" GST_FOURCC_FORMAT " caps %" GST_PTR_FORMAT,
12136           GST_FOURCC_ARGS (fourcc), entry->caps);
12137     } else {
12138       /* everything in 1 sample */
12139       entry->sampled = TRUE;
12140
12141       entry->caps =
12142           qtdemux_generic_caps (qtdemux, stream, entry, fourcc, stsd_entry_data,
12143           &codec);
12144
12145       if (entry->caps == NULL)
12146         goto unknown_stream;
12147
12148       if (codec) {
12149         gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
12150             GST_TAG_SUBTITLE_CODEC, codec, NULL);
12151         g_free (codec);
12152         codec = NULL;
12153       }
12154     }
12155
12156     /* promote to sampled format */
12157     if (entry->fourcc == FOURCC_samr) {
12158       /* force mono 8000 Hz for AMR */
12159       entry->sampled = TRUE;
12160       entry->n_channels = 1;
12161       entry->rate = 8000;
12162     } else if (entry->fourcc == FOURCC_sawb) {
12163       /* force mono 16000 Hz for AMR-WB */
12164       entry->sampled = TRUE;
12165       entry->n_channels = 1;
12166       entry->rate = 16000;
12167     } else if (entry->fourcc == FOURCC_mp4a) {
12168       entry->sampled = TRUE;
12169     }
12170
12171
12172     stsd_entry_data += len;
12173     remaining_stsd_len -= len;
12174
12175   }
12176
12177   /* collect sample information */
12178   if (!qtdemux_stbl_init (qtdemux, stream, stbl))
12179     goto samples_failed;
12180
12181   if (qtdemux->fragmented) {
12182     guint64 offset;
12183
12184     /* need all moov samples as basis; probably not many if any at all */
12185     /* prevent moof parsing taking of at this time */
12186     offset = qtdemux->moof_offset;
12187     qtdemux->moof_offset = 0;
12188     if (stream->n_samples &&
12189         !qtdemux_parse_samples (qtdemux, stream, stream->n_samples - 1)) {
12190       qtdemux->moof_offset = offset;
12191       goto samples_failed;
12192     }
12193     qtdemux->moof_offset = 0;
12194     /* movie duration more reliable in this case (e.g. mehd) */
12195     if (qtdemux->segment.duration &&
12196         GST_CLOCK_TIME_IS_VALID (qtdemux->segment.duration))
12197       stream->duration =
12198           GSTTIME_TO_QTSTREAMTIME (stream, qtdemux->segment.duration);
12199   }
12200
12201   /* configure segments */
12202   if (!qtdemux_parse_segments (qtdemux, stream, trak))
12203     goto segments_failed;
12204
12205   /* add some language tag, if useful */
12206   if (stream->lang_id[0] != '\0' && strcmp (stream->lang_id, "unk") &&
12207       strcmp (stream->lang_id, "und")) {
12208     const gchar *lang_code;
12209
12210     /* convert ISO 639-2 code to ISO 639-1 */
12211     lang_code = gst_tag_get_language_code (stream->lang_id);
12212     gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
12213         GST_TAG_LANGUAGE_CODE, (lang_code) ? lang_code : stream->lang_id, NULL);
12214   }
12215
12216   /* Check for UDTA tags */
12217   if ((udta = qtdemux_tree_get_child_by_type (trak, FOURCC_udta))) {
12218     qtdemux_parse_udta (qtdemux, stream->stream_tags, udta);
12219   }
12220
12221   /* Insert and sort new stream in track-id order.
12222    * This will help in comparing old/new streams during stream update check */
12223   qtdemux->active_streams =
12224       g_list_insert_sorted (qtdemux->active_streams, stream,
12225       (GCompareFunc) qtdemux_track_id_compare_func);
12226   qtdemux->n_streams++;
12227   GST_DEBUG_OBJECT (qtdemux, "n_streams is now %d", qtdemux->n_streams);
12228
12229   return TRUE;
12230
12231 /* ERRORS */
12232 corrupt_file:
12233   {
12234     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
12235         (_("This file is corrupt and cannot be played.")), (NULL));
12236     if (stream)
12237       gst_qtdemux_stream_free (stream);
12238     return FALSE;
12239   }
12240 error_encrypted:
12241   {
12242     GST_ELEMENT_ERROR (qtdemux, STREAM, DECRYPT, (NULL), (NULL));
12243     gst_qtdemux_stream_free (stream);
12244     return FALSE;
12245   }
12246 samples_failed:
12247 segments_failed:
12248   {
12249     /* we posted an error already */
12250     /* free stbl sub-atoms */
12251     gst_qtdemux_stbl_free (stream);
12252     gst_qtdemux_stream_free (stream);
12253     return FALSE;
12254   }
12255 existing_stream:
12256   {
12257     GST_INFO_OBJECT (qtdemux, "stream with track id %i already exists",
12258         track_id);
12259     return TRUE;
12260   }
12261 unknown_stream:
12262   {
12263     GST_INFO_OBJECT (qtdemux, "unknown subtype %" GST_FOURCC_FORMAT,
12264         GST_FOURCC_ARGS (stream->subtype));
12265     gst_qtdemux_stream_free (stream);
12266     return TRUE;
12267   }
12268 }
12269
12270 /* If we can estimate the overall bitrate, and don't have information about the
12271  * stream bitrate for exactly one stream, this guesses the stream bitrate as
12272  * the overall bitrate minus the sum of the bitrates of all other streams. This
12273  * should be useful for the common case where we have one audio and one video
12274  * stream and can estimate the bitrate of one, but not the other. */
12275 static void
12276 gst_qtdemux_guess_bitrate (GstQTDemux * qtdemux)
12277 {
12278   QtDemuxStream *stream = NULL;
12279   gint64 size, sys_bitrate, sum_bitrate = 0;
12280   GstClockTime duration;
12281   guint bitrate;
12282   GList *iter;
12283
12284   if (qtdemux->fragmented)
12285     return;
12286
12287   GST_DEBUG_OBJECT (qtdemux, "Looking for streams with unknown bitrate");
12288
12289   if (!gst_pad_peer_query_duration (qtdemux->sinkpad, GST_FORMAT_BYTES, &size)
12290       || size <= 0) {
12291     GST_DEBUG_OBJECT (qtdemux,
12292         "Size in bytes of the stream not known - bailing");
12293     return;
12294   }
12295
12296   /* Subtract the header size */
12297   GST_DEBUG_OBJECT (qtdemux, "Total size %" G_GINT64_FORMAT ", header size %u",
12298       size, qtdemux->header_size);
12299
12300   if (size < qtdemux->header_size)
12301     return;
12302
12303   size = size - qtdemux->header_size;
12304
12305   if (!gst_qtdemux_get_duration (qtdemux, &duration)) {
12306     GST_DEBUG_OBJECT (qtdemux, "Stream duration not known - bailing");
12307     return;
12308   }
12309
12310   for (iter = qtdemux->active_streams; iter; iter = g_list_next (iter)) {
12311     QtDemuxStream *str = QTDEMUX_STREAM (iter->data);
12312     switch (str->subtype) {
12313       case FOURCC_soun:
12314       case FOURCC_vide:
12315         GST_DEBUG_OBJECT (qtdemux, "checking bitrate for %" GST_PTR_FORMAT,
12316             CUR_STREAM (str)->caps);
12317         /* retrieve bitrate, prefer avg then max */
12318         bitrate = 0;
12319         if (str->stream_tags) {
12320           if (gst_tag_list_get_uint (str->stream_tags,
12321                   GST_TAG_MAXIMUM_BITRATE, &bitrate))
12322             GST_DEBUG_OBJECT (qtdemux, "max-bitrate: %u", bitrate);
12323           if (gst_tag_list_get_uint (str->stream_tags,
12324                   GST_TAG_NOMINAL_BITRATE, &bitrate))
12325             GST_DEBUG_OBJECT (qtdemux, "nominal-bitrate: %u", bitrate);
12326           if (gst_tag_list_get_uint (str->stream_tags,
12327                   GST_TAG_BITRATE, &bitrate))
12328             GST_DEBUG_OBJECT (qtdemux, "bitrate: %u", bitrate);
12329         }
12330         if (bitrate)
12331           sum_bitrate += bitrate;
12332         else {
12333           if (stream) {
12334             GST_DEBUG_OBJECT (qtdemux,
12335                 ">1 stream with unknown bitrate - bailing");
12336             return;
12337           } else
12338             stream = str;
12339         }
12340
12341       default:
12342         /* For other subtypes, we assume no significant impact on bitrate */
12343         break;
12344     }
12345   }
12346
12347   if (!stream) {
12348     GST_DEBUG_OBJECT (qtdemux, "All stream bitrates are known");
12349     return;
12350   }
12351
12352   sys_bitrate = gst_util_uint64_scale (size, GST_SECOND * 8, duration);
12353
12354   if (sys_bitrate < sum_bitrate) {
12355     /* This can happen, since sum_bitrate might be derived from maximum
12356      * bitrates and not average bitrates */
12357     GST_DEBUG_OBJECT (qtdemux,
12358         "System bitrate less than sum bitrate - bailing");
12359     return;
12360   }
12361
12362   bitrate = sys_bitrate - sum_bitrate;
12363   GST_DEBUG_OBJECT (qtdemux, "System bitrate = %" G_GINT64_FORMAT
12364       ", Stream bitrate = %u", sys_bitrate, bitrate);
12365
12366   if (!stream->stream_tags)
12367     stream->stream_tags = gst_tag_list_new_empty ();
12368   else
12369     stream->stream_tags = gst_tag_list_make_writable (stream->stream_tags);
12370
12371   gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
12372       GST_TAG_BITRATE, bitrate, NULL);
12373 }
12374
12375 static GstFlowReturn
12376 qtdemux_prepare_streams (GstQTDemux * qtdemux)
12377 {
12378   GstFlowReturn ret = GST_FLOW_OK;
12379   GList *iter, *next;
12380
12381   GST_DEBUG_OBJECT (qtdemux, "prepare streams");
12382
12383   for (iter = qtdemux->active_streams; ret == GST_FLOW_OK && iter; iter = next) {
12384     QtDemuxStream *stream = QTDEMUX_STREAM (iter->data);
12385     guint32 sample_num = 0;
12386
12387     next = iter->next;
12388
12389     GST_DEBUG_OBJECT (qtdemux, "track-id %u, fourcc %" GST_FOURCC_FORMAT,
12390         stream->track_id, GST_FOURCC_ARGS (CUR_STREAM (stream)->fourcc));
12391
12392     if (qtdemux->fragmented) {
12393       /* need all moov samples first */
12394       GST_OBJECT_LOCK (qtdemux);
12395       while (stream->n_samples == 0)
12396         if ((ret = qtdemux_add_fragmented_samples (qtdemux)) != GST_FLOW_OK)
12397           break;
12398       GST_OBJECT_UNLOCK (qtdemux);
12399     } else {
12400       /* discard any stray moof */
12401       qtdemux->moof_offset = 0;
12402     }
12403
12404     /* prepare braking */
12405     if (ret != GST_FLOW_ERROR)
12406       ret = GST_FLOW_OK;
12407
12408     /* in pull mode, we should have parsed some sample info by now;
12409      * and quite some code will not handle no samples.
12410      * in push mode, we'll just have to deal with it */
12411     if (G_UNLIKELY (qtdemux->pullbased && !stream->n_samples)) {
12412       GST_DEBUG_OBJECT (qtdemux, "no samples for stream; discarding");
12413       gst_qtdemux_remove_stream (qtdemux, stream);
12414       continue;
12415     } else if (stream->track_id == qtdemux->chapters_track_id &&
12416         (stream->subtype == FOURCC_text || stream->subtype == FOURCC_sbtl)) {
12417       /* TODO - parse chapters track and expose it as GstToc; For now just ignore it
12418          so that it doesn't look like a subtitle track */
12419       gst_qtdemux_remove_stream (qtdemux, stream);
12420       continue;
12421     }
12422
12423     /* parse the initial sample for use in setting the frame rate cap */
12424     while (sample_num == 0 && sample_num < stream->n_samples) {
12425       if (!qtdemux_parse_samples (qtdemux, stream, sample_num))
12426         break;
12427       ++sample_num;
12428     }
12429   }
12430
12431   return ret;
12432 }
12433
12434 static GList *
12435 _stream_in_list (GList * list, QtDemuxStream * stream)
12436 {
12437   GList *iter;
12438
12439   for (iter = list; iter; iter = g_list_next (iter)) {
12440     QtDemuxStream *tmp = QTDEMUX_STREAM (iter->data);
12441     if (!g_strcmp0 (tmp->stream_id, stream->stream_id))
12442       return iter;
12443   }
12444
12445   return NULL;
12446 }
12447
12448 static gboolean
12449 qtdemux_is_streams_update (GstQTDemux * qtdemux)
12450 {
12451   GList *new, *old;
12452
12453   if (!qtdemux->active_streams)
12454     return FALSE;
12455
12456   /* streams in list are sorted in track-id order */
12457   for (new = qtdemux->active_streams, old = qtdemux->old_streams; new && old;
12458       new = g_list_next (new), old = g_list_next (old)) {
12459
12460     /* Different stream-id, updated */
12461     if (g_strcmp0 (QTDEMUX_STREAM (new->data)->stream_id,
12462             QTDEMUX_STREAM (old->data)->stream_id))
12463       return TRUE;
12464   }
12465
12466   /* Different length, updated */
12467   if (new != NULL || old != NULL)
12468     return TRUE;
12469
12470   return FALSE;
12471 }
12472
12473 static gboolean
12474 qtdemux_reuse_and_configure_stream (GstQTDemux * qtdemux,
12475     QtDemuxStream * oldstream, QtDemuxStream * newstream)
12476 {
12477   /* Connect old stream's srcpad to new stream */
12478   newstream->pad = oldstream->pad;
12479   oldstream->pad = NULL;
12480
12481   /* unset new_stream to prevent stream-start event */
12482   newstream->new_stream = FALSE;
12483
12484   return gst_qtdemux_configure_stream (qtdemux, newstream);
12485 }
12486
12487 static gboolean
12488 qtdemux_update_streams (GstQTDemux * qtdemux)
12489 {
12490   GList *iter, *next;
12491   g_assert (qtdemux->streams_aware);
12492
12493   /* At below, figure out which stream in active_streams has identical stream-id
12494    * with that of in old_streams. If there is matching stream-id,
12495    * corresponding newstream will not be exposed again,
12496    * but demux will reuse srcpad of matched old stream
12497    *
12498    * active_streams : newly created streams from the latest moov
12499    * old_streams : existing streams (belong to previous moov)
12500    */
12501
12502   /* Count n_streams again */
12503   qtdemux->n_streams = 0;
12504
12505   for (iter = qtdemux->active_streams; iter; iter = next) {
12506     GList *tmp;
12507     QtDemuxStream *stream = QTDEMUX_STREAM (iter->data);
12508
12509     next = iter->next;
12510
12511     GST_DEBUG_OBJECT (qtdemux, "track-id %u, fourcc %" GST_FOURCC_FORMAT,
12512         stream->track_id, GST_FOURCC_ARGS (CUR_STREAM (stream)->fourcc));
12513
12514     qtdemux->n_streams++;
12515
12516     if ((tmp = _stream_in_list (qtdemux->old_streams, stream)) != NULL
12517         && QTDEMUX_STREAM (tmp->data)->pad) {
12518       QtDemuxStream *oldstream = QTDEMUX_STREAM (tmp->data);
12519
12520       GST_DEBUG_OBJECT (qtdemux, "Reuse track-id %d", oldstream->track_id);
12521
12522       if (!qtdemux_reuse_and_configure_stream (qtdemux, oldstream, stream))
12523         return FALSE;
12524
12525       qtdemux->old_streams = g_list_remove (qtdemux->old_streams, oldstream);
12526       gst_qtdemux_stream_free (oldstream);
12527     } else {
12528       GstTagList *list;
12529
12530       /* now we have all info and can expose */
12531       list = stream->stream_tags;
12532       stream->stream_tags = NULL;
12533       if (!gst_qtdemux_add_stream (qtdemux, stream, list))
12534         return FALSE;
12535     }
12536   }
12537
12538   return TRUE;
12539 }
12540
12541 /* Must be called with expose lock */
12542 static GstFlowReturn
12543 qtdemux_expose_streams (GstQTDemux * qtdemux)
12544 {
12545   GList *iter, *next;
12546
12547   GST_DEBUG_OBJECT (qtdemux, "exposing streams");
12548
12549   if (!qtdemux_is_streams_update (qtdemux)) {
12550     GList *new, *old;
12551
12552     GST_DEBUG_OBJECT (qtdemux, "Reuse all streams");
12553     for (new = qtdemux->active_streams, old = qtdemux->old_streams; new && old;
12554         new = g_list_next (new), old = g_list_next (old)) {
12555       if (!qtdemux_reuse_and_configure_stream (qtdemux,
12556               QTDEMUX_STREAM (old->data), QTDEMUX_STREAM (new->data)))
12557         return GST_FLOW_ERROR;
12558     }
12559
12560     g_list_free_full (qtdemux->old_streams,
12561         (GDestroyNotify) gst_qtdemux_stream_free);
12562     qtdemux->old_streams = NULL;
12563
12564     return GST_FLOW_OK;
12565   }
12566
12567   if (qtdemux->streams_aware) {
12568     if (!qtdemux_update_streams (qtdemux))
12569       return GST_FLOW_ERROR;
12570   } else {
12571     for (iter = qtdemux->active_streams; iter; iter = g_list_next (iter)) {
12572       QtDemuxStream *stream = QTDEMUX_STREAM (iter->data);
12573       GstTagList *list;
12574
12575       /* now we have all info and can expose */
12576       list = stream->stream_tags;
12577       stream->stream_tags = NULL;
12578       if (!gst_qtdemux_add_stream (qtdemux, stream, list))
12579         return GST_FLOW_ERROR;
12580
12581     }
12582   }
12583
12584   gst_qtdemux_guess_bitrate (qtdemux);
12585
12586   gst_element_no_more_pads (GST_ELEMENT_CAST (qtdemux));
12587
12588   /* If we have still old_streams, it's no more used stream */
12589   for (iter = qtdemux->old_streams; iter; iter = next) {
12590     QtDemuxStream *stream = QTDEMUX_STREAM (iter->data);
12591     next = g_list_next (iter);
12592
12593     if (stream->pad) {
12594       GstEvent *event;
12595
12596       event = gst_event_new_eos ();
12597       if (qtdemux->segment_seqnum)
12598         gst_event_set_seqnum (event, qtdemux->segment_seqnum);
12599
12600       gst_pad_push_event (stream->pad, event);
12601     }
12602
12603     qtdemux->old_streams = g_list_remove (qtdemux->old_streams, stream);
12604     gst_qtdemux_stream_free (stream);
12605   }
12606
12607   /* check if we should post a redirect in case there is a single trak
12608    * and it is a redirecting trak */
12609   if (qtdemux->n_streams == 1 &&
12610       QTDEMUX_FIRST_STREAM (qtdemux)->redirect_uri != NULL) {
12611     GstMessage *m;
12612
12613     GST_INFO_OBJECT (qtdemux, "Issuing a redirect due to a single track with "
12614         "an external content");
12615     m = gst_message_new_element (GST_OBJECT_CAST (qtdemux),
12616         gst_structure_new ("redirect",
12617             "new-location", G_TYPE_STRING,
12618             QTDEMUX_FIRST_STREAM (qtdemux)->redirect_uri, NULL));
12619     gst_element_post_message (GST_ELEMENT_CAST (qtdemux), m);
12620     qtdemux->posted_redirect = TRUE;
12621   }
12622
12623   for (iter = qtdemux->active_streams; iter; iter = g_list_next (iter)) {
12624     qtdemux_do_allocation (qtdemux, QTDEMUX_STREAM (iter->data));
12625   }
12626
12627   qtdemux->need_segment = TRUE;
12628
12629   qtdemux->exposed = TRUE;
12630   return GST_FLOW_OK;
12631 }
12632
12633 /* check if major or compatible brand is 3GP */
12634 static inline gboolean
12635 qtdemux_is_brand_3gp (GstQTDemux * qtdemux, gboolean major)
12636 {
12637   if (major) {
12638     return ((qtdemux->major_brand & GST_MAKE_FOURCC (255, 255, 0, 0)) ==
12639         FOURCC_3g__);
12640   } else if (qtdemux->comp_brands != NULL) {
12641     GstMapInfo map;
12642     guint8 *data;
12643     gsize size;
12644     gboolean res = FALSE;
12645
12646     gst_buffer_map (qtdemux->comp_brands, &map, GST_MAP_READ);
12647     data = map.data;
12648     size = map.size;
12649     while (size >= 4) {
12650       res = res || ((QT_FOURCC (data) & GST_MAKE_FOURCC (255, 255, 0, 0)) ==
12651           FOURCC_3g__);
12652       data += 4;
12653       size -= 4;
12654     }
12655     gst_buffer_unmap (qtdemux->comp_brands, &map);
12656     return res;
12657   } else {
12658     return FALSE;
12659   }
12660 }
12661
12662 /* check if tag is a spec'ed 3GP tag keyword storing a string */
12663 static inline gboolean
12664 qtdemux_is_string_tag_3gp (GstQTDemux * qtdemux, guint32 fourcc)
12665 {
12666   return fourcc == FOURCC_cprt || fourcc == FOURCC_gnre || fourcc == FOURCC_titl
12667       || fourcc == FOURCC_dscp || fourcc == FOURCC_perf || fourcc == FOURCC_auth
12668       || fourcc == FOURCC_albm;
12669 }
12670
12671 static void
12672 qtdemux_tag_add_location (GstQTDemux * qtdemux, GstTagList * taglist,
12673     const char *tag, const char *dummy, GNode * node)
12674 {
12675   const gchar *env_vars[] = { "GST_QT_TAG_ENCODING", "GST_TAG_ENCODING", NULL };
12676   int offset;
12677   char *name;
12678   gchar *data;
12679   gdouble longitude, latitude, altitude;
12680   gint len;
12681
12682   len = QT_UINT32 (node->data);
12683   if (len <= 14)
12684     goto short_read;
12685
12686   data = node->data;
12687   offset = 14;
12688
12689   /* TODO: language code skipped */
12690
12691   name = gst_tag_freeform_string_to_utf8 (data + offset, -1, env_vars);
12692
12693   if (!name) {
12694     /* do not alarm in trivial case, but bail out otherwise */
12695     if (*(data + offset) != 0) {
12696       GST_DEBUG_OBJECT (qtdemux, "failed to convert %s tag to UTF-8, "
12697           "giving up", tag);
12698     }
12699   } else {
12700     gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE,
12701         GST_TAG_GEO_LOCATION_NAME, name, NULL);
12702     offset += strlen (name);
12703     g_free (name);
12704   }
12705
12706   if (len < offset + 2 + 4 + 4 + 4)
12707     goto short_read;
12708
12709   /* +1 +1 = skip null-terminator and location role byte */
12710   offset += 1 + 1;
12711   /* table in spec says unsigned, semantics say negative has meaning ... */
12712   longitude = QT_SFP32 (data + offset);
12713
12714   offset += 4;
12715   latitude = QT_SFP32 (data + offset);
12716
12717   offset += 4;
12718   altitude = QT_SFP32 (data + offset);
12719
12720   /* one invalid means all are invalid */
12721   if (longitude >= -180.0 && longitude <= 180.0 &&
12722       latitude >= -90.0 && latitude <= 90.0) {
12723     gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE,
12724         GST_TAG_GEO_LOCATION_LATITUDE, latitude,
12725         GST_TAG_GEO_LOCATION_LONGITUDE, longitude,
12726         GST_TAG_GEO_LOCATION_ELEVATION, altitude, NULL);
12727   }
12728
12729   /* TODO: no GST_TAG_, so astronomical body and additional notes skipped */
12730
12731   return;
12732
12733   /* ERRORS */
12734 short_read:
12735   {
12736     GST_DEBUG_OBJECT (qtdemux, "short read parsing 3GP location");
12737     return;
12738   }
12739 }
12740
12741
12742 static void
12743 qtdemux_tag_add_year (GstQTDemux * qtdemux, GstTagList * taglist,
12744     const char *tag, const char *dummy, GNode * node)
12745 {
12746   guint16 y;
12747   GDate *date;
12748   gint len;
12749
12750   len = QT_UINT32 (node->data);
12751   if (len < 14)
12752     return;
12753
12754   y = QT_UINT16 ((guint8 *) node->data + 12);
12755   if (y == 0) {
12756     GST_DEBUG_OBJECT (qtdemux, "year: %u is not a valid year", y);
12757     return;
12758   }
12759   GST_DEBUG_OBJECT (qtdemux, "year: %u", y);
12760
12761   date = g_date_new_dmy (1, 1, y);
12762   gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag, date, NULL);
12763   g_date_free (date);
12764 }
12765
12766 static void
12767 qtdemux_tag_add_classification (GstQTDemux * qtdemux, GstTagList * taglist,
12768     const char *tag, const char *dummy, GNode * node)
12769 {
12770   int offset;
12771   char *tag_str = NULL;
12772   guint8 *entity;
12773   guint16 table;
12774   gint len;
12775
12776   len = QT_UINT32 (node->data);
12777   if (len <= 20)
12778     goto short_read;
12779
12780   offset = 12;
12781   entity = (guint8 *) node->data + offset;
12782   if (entity[0] == 0 || entity[1] == 0 || entity[2] == 0 || entity[3] == 0) {
12783     GST_DEBUG_OBJECT (qtdemux,
12784         "classification info: %c%c%c%c invalid classification entity",
12785         entity[0], entity[1], entity[2], entity[3]);
12786     return;
12787   }
12788
12789   offset += 4;
12790   table = QT_UINT16 ((guint8 *) node->data + offset);
12791
12792   /* Language code skipped */
12793
12794   offset += 4;
12795
12796   /* Tag format: "XXXX://Y[YYYY]/classification info string"
12797    * XXXX: classification entity, fixed length 4 chars.
12798    * Y[YYYY]: classification table, max 5 chars.
12799    */
12800   tag_str = g_strdup_printf ("----://%u/%s",
12801       table, (char *) node->data + offset);
12802
12803   /* memcpy To be sure we're preserving byte order */
12804   memcpy (tag_str, entity, 4);
12805   GST_DEBUG_OBJECT (qtdemux, "classification info: %s", tag_str);
12806
12807   gst_tag_list_add (taglist, GST_TAG_MERGE_APPEND, tag, tag_str, NULL);
12808
12809   g_free (tag_str);
12810
12811   return;
12812
12813   /* ERRORS */
12814 short_read:
12815   {
12816     GST_DEBUG_OBJECT (qtdemux, "short read parsing 3GP classification");
12817     return;
12818   }
12819 }
12820
12821 static gboolean
12822 qtdemux_tag_add_str_full (GstQTDemux * qtdemux, GstTagList * taglist,
12823     const char *tag, const char *dummy, GNode * node)
12824 {
12825   const gchar *env_vars[] = { "GST_QT_TAG_ENCODING", "GST_TAG_ENCODING", NULL };
12826   GNode *data;
12827   char *s;
12828   int len;
12829   guint32 type;
12830   int offset;
12831   gboolean ret = TRUE;
12832   const gchar *charset = NULL;
12833
12834   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
12835   if (data) {
12836     len = QT_UINT32 (data->data);
12837     type = QT_UINT32 ((guint8 *) data->data + 8);
12838     if (type == 0x00000001 && len > 16) {
12839       s = gst_tag_freeform_string_to_utf8 ((char *) data->data + 16, len - 16,
12840           env_vars);
12841       if (s) {
12842         GST_DEBUG_OBJECT (qtdemux, "adding tag %s", GST_STR_NULL (s));
12843         gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag, s, NULL);
12844         g_free (s);
12845       } else {
12846         GST_DEBUG_OBJECT (qtdemux, "failed to convert %s tag to UTF-8", tag);
12847       }
12848     }
12849   } else {
12850     len = QT_UINT32 (node->data);
12851     type = QT_UINT32 ((guint8 *) node->data + 4);
12852     if ((type >> 24) == 0xa9 && len > 8 + 4) {
12853       gint str_len;
12854       gint lang_code;
12855
12856       /* Type starts with the (C) symbol, so the next data is a list
12857        * of (string size(16), language code(16), string) */
12858
12859       str_len = QT_UINT16 ((guint8 *) node->data + 8);
12860       lang_code = QT_UINT16 ((guint8 *) node->data + 10);
12861
12862       /* the string + fourcc + size + 2 16bit fields,
12863        * means that there are more tags in this atom */
12864       if (len > str_len + 8 + 4) {
12865         /* TODO how to represent the same tag in different languages? */
12866         GST_WARNING_OBJECT (qtdemux, "Ignoring metadata entry with multiple "
12867             "text alternatives, reading only first one");
12868       }
12869
12870       offset = 12;
12871       len = MIN (len, str_len + 8 + 4); /* remove trailing strings that we don't use */
12872       GST_DEBUG_OBJECT (qtdemux, "found international text tag");
12873
12874       if (lang_code < 0x800) {  /* MAC encoded string */
12875         charset = "mac";
12876       }
12877     } else if (len > 14 && qtdemux_is_string_tag_3gp (qtdemux,
12878             QT_FOURCC ((guint8 *) node->data + 4))) {
12879       guint32 type = QT_UINT32 ((guint8 *) node->data + 8);
12880
12881       /* we go for 3GP style encoding if major brands claims so,
12882        * or if no hope for data be ok UTF-8, and compatible 3GP brand present */
12883       if (qtdemux_is_brand_3gp (qtdemux, TRUE) ||
12884           (qtdemux_is_brand_3gp (qtdemux, FALSE) &&
12885               ((type & 0x00FFFFFF) == 0x0) && (type >> 24 <= 0xF))) {
12886         offset = 14;
12887         /* 16-bit Language code is ignored here as well */
12888         GST_DEBUG_OBJECT (qtdemux, "found 3gpp text tag");
12889       } else {
12890         goto normal;
12891       }
12892     } else {
12893     normal:
12894       offset = 8;
12895       GST_DEBUG_OBJECT (qtdemux, "found normal text tag");
12896       ret = FALSE;              /* may have to fallback */
12897     }
12898     if (charset) {
12899       GError *err = NULL;
12900
12901       s = g_convert ((gchar *) node->data + offset, len - offset, "utf8",
12902           charset, NULL, NULL, &err);
12903       if (err) {
12904         GST_DEBUG_OBJECT (qtdemux, "Failed to convert string from charset %s:"
12905             " %s(%d): %s", charset, g_quark_to_string (err->domain), err->code,
12906             err->message);
12907         g_error_free (err);
12908       }
12909     } else {
12910       s = gst_tag_freeform_string_to_utf8 ((char *) node->data + offset,
12911           len - offset, env_vars);
12912     }
12913     if (s) {
12914       GST_DEBUG_OBJECT (qtdemux, "adding tag %s", GST_STR_NULL (s));
12915       gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag, s, NULL);
12916       g_free (s);
12917       ret = TRUE;
12918     } else {
12919       GST_DEBUG_OBJECT (qtdemux, "failed to convert %s tag to UTF-8", tag);
12920     }
12921   }
12922   return ret;
12923 }
12924
12925 static void
12926 qtdemux_tag_add_str (GstQTDemux * qtdemux, GstTagList * taglist,
12927     const char *tag, const char *dummy, GNode * node)
12928 {
12929   qtdemux_tag_add_str_full (qtdemux, taglist, tag, dummy, node);
12930 }
12931
12932 static void
12933 qtdemux_tag_add_keywords (GstQTDemux * qtdemux, GstTagList * taglist,
12934     const char *tag, const char *dummy, GNode * node)
12935 {
12936   const gchar *env_vars[] = { "GST_QT_TAG_ENCODING", "GST_TAG_ENCODING", NULL };
12937   guint8 *data;
12938   char *s, *t, *k = NULL;
12939   int len;
12940   int offset;
12941   int count;
12942
12943   /* first try normal string tag if major brand not 3GP */
12944   if (!qtdemux_is_brand_3gp (qtdemux, TRUE)) {
12945     if (!qtdemux_tag_add_str_full (qtdemux, taglist, tag, dummy, node)) {
12946       /* hm, that did not work, maybe 3gpp storage in non-3gpp major brand;
12947        * let's try it 3gpp way after minor safety check */
12948       data = node->data;
12949       if (QT_UINT32 (data) < 15 || !qtdemux_is_brand_3gp (qtdemux, FALSE))
12950         return;
12951     } else
12952       return;
12953   }
12954
12955   GST_DEBUG_OBJECT (qtdemux, "found 3gpp keyword tag");
12956
12957   data = node->data;
12958
12959   len = QT_UINT32 (data);
12960   if (len < 15)
12961     goto short_read;
12962
12963   count = QT_UINT8 (data + 14);
12964   offset = 15;
12965   for (; count; count--) {
12966     gint slen;
12967
12968     if (offset + 1 > len)
12969       goto short_read;
12970     slen = QT_UINT8 (data + offset);
12971     offset += 1;
12972     if (offset + slen > len)
12973       goto short_read;
12974     s = gst_tag_freeform_string_to_utf8 ((char *) node->data + offset,
12975         slen, env_vars);
12976     if (s) {
12977       GST_DEBUG_OBJECT (qtdemux, "adding keyword %s", GST_STR_NULL (s));
12978       if (k) {
12979         t = g_strjoin (",", k, s, NULL);
12980         g_free (s);
12981         g_free (k);
12982         k = t;
12983       } else {
12984         k = s;
12985       }
12986     } else {
12987       GST_DEBUG_OBJECT (qtdemux, "failed to convert keyword to UTF-8");
12988     }
12989     offset += slen;
12990   }
12991
12992 done:
12993   if (k) {
12994     GST_DEBUG_OBJECT (qtdemux, "adding tag %s", GST_STR_NULL (k));
12995     gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag, k, NULL);
12996   }
12997   g_free (k);
12998
12999   return;
13000
13001   /* ERRORS */
13002 short_read:
13003   {
13004     GST_DEBUG_OBJECT (qtdemux, "short read parsing 3GP keywords");
13005     goto done;
13006   }
13007 }
13008
13009 static void
13010 qtdemux_tag_add_num (GstQTDemux * qtdemux, GstTagList * taglist,
13011     const char *tag1, const char *tag2, GNode * node)
13012 {
13013   GNode *data;
13014   int len;
13015   int type;
13016   int n1, n2;
13017
13018   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
13019   if (data) {
13020     len = QT_UINT32 (data->data);
13021     type = QT_UINT32 ((guint8 *) data->data + 8);
13022     if (type == 0x00000000 && len >= 22) {
13023       n1 = QT_UINT16 ((guint8 *) data->data + 18);
13024       n2 = QT_UINT16 ((guint8 *) data->data + 20);
13025       if (n1 > 0) {
13026         GST_DEBUG_OBJECT (qtdemux, "adding tag %s=%d", tag1, n1);
13027         gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag1, n1, NULL);
13028       }
13029       if (n2 > 0) {
13030         GST_DEBUG_OBJECT (qtdemux, "adding tag %s=%d", tag2, n2);
13031         gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag2, n2, NULL);
13032       }
13033     }
13034   }
13035 }
13036
13037 static void
13038 qtdemux_tag_add_tmpo (GstQTDemux * qtdemux, GstTagList * taglist,
13039     const char *tag1, const char *dummy, GNode * node)
13040 {
13041   GNode *data;
13042   int len;
13043   int type;
13044   int n1;
13045
13046   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
13047   if (data) {
13048     len = QT_UINT32 (data->data);
13049     type = QT_UINT32 ((guint8 *) data->data + 8);
13050     GST_DEBUG_OBJECT (qtdemux, "have tempo tag, type=%d,len=%d", type, len);
13051     /* some files wrongly have a type 0x0f=15, but it should be 0x15 */
13052     if ((type == 0x00000015 || type == 0x0000000f) && len >= 18) {
13053       n1 = QT_UINT16 ((guint8 *) data->data + 16);
13054       if (n1) {
13055         /* do not add bpm=0 */
13056         GST_DEBUG_OBJECT (qtdemux, "adding tag %d", n1);
13057         gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag1, (gdouble) n1,
13058             NULL);
13059       }
13060     }
13061   }
13062 }
13063
13064 static void
13065 qtdemux_tag_add_uint32 (GstQTDemux * qtdemux, GstTagList * taglist,
13066     const char *tag1, const char *dummy, GNode * node)
13067 {
13068   GNode *data;
13069   int len;
13070   int type;
13071   guint32 num;
13072
13073   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
13074   if (data) {
13075     len = QT_UINT32 (data->data);
13076     type = QT_UINT32 ((guint8 *) data->data + 8);
13077     GST_DEBUG_OBJECT (qtdemux, "have %s tag, type=%d,len=%d", tag1, type, len);
13078     /* some files wrongly have a type 0x0f=15, but it should be 0x15 */
13079     if ((type == 0x00000015 || type == 0x0000000f) && len >= 20) {
13080       num = QT_UINT32 ((guint8 *) data->data + 16);
13081       if (num) {
13082         /* do not add num=0 */
13083         GST_DEBUG_OBJECT (qtdemux, "adding tag %d", num);
13084         gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag1, num, NULL);
13085       }
13086     }
13087   }
13088 }
13089
13090 static void
13091 qtdemux_tag_add_covr (GstQTDemux * qtdemux, GstTagList * taglist,
13092     const char *tag1, const char *dummy, GNode * node)
13093 {
13094   GNode *data;
13095   int len;
13096   int type;
13097   GstSample *sample;
13098
13099   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
13100   if (data) {
13101     len = QT_UINT32 (data->data);
13102     type = QT_UINT32 ((guint8 *) data->data + 8);
13103     GST_DEBUG_OBJECT (qtdemux, "have covr tag, type=%d,len=%d", type, len);
13104     if ((type == 0x0000000d || type == 0x0000000e) && len > 16) {
13105       GstTagImageType image_type;
13106
13107       if (gst_tag_list_get_tag_size (taglist, GST_TAG_IMAGE) == 0)
13108         image_type = GST_TAG_IMAGE_TYPE_FRONT_COVER;
13109       else
13110         image_type = GST_TAG_IMAGE_TYPE_NONE;
13111
13112       if ((sample =
13113               gst_tag_image_data_to_image_sample ((guint8 *) data->data + 16,
13114                   len - 16, image_type))) {
13115         GST_DEBUG_OBJECT (qtdemux, "adding tag size %d", len - 16);
13116         gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag1, sample, NULL);
13117         gst_sample_unref (sample);
13118       }
13119     }
13120   }
13121 }
13122
13123 static void
13124 qtdemux_tag_add_date (GstQTDemux * qtdemux, GstTagList * taglist,
13125     const char *tag, const char *dummy, GNode * node)
13126 {
13127   GNode *data;
13128   GstDateTime *datetime = NULL;
13129   char *s;
13130   int len;
13131   int type;
13132
13133   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
13134   if (data) {
13135     len = QT_UINT32 (data->data);
13136     type = QT_UINT32 ((guint8 *) data->data + 8);
13137     if (type == 0x00000001 && len > 16) {
13138       guint y, m = 1, d = 1;
13139       gint ret;
13140
13141       s = g_strndup ((char *) data->data + 16, len - 16);
13142       GST_DEBUG_OBJECT (qtdemux, "adding date '%s'", s);
13143       datetime = gst_date_time_new_from_iso8601_string (s);
13144       if (datetime != NULL) {
13145         gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, GST_TAG_DATE_TIME,
13146             datetime, NULL);
13147         gst_date_time_unref (datetime);
13148       }
13149
13150       ret = sscanf (s, "%u-%u-%u", &y, &m, &d);
13151       if (ret >= 1 && y > 1500 && y < 3000) {
13152         GDate *date;
13153
13154         date = g_date_new_dmy (d, m, y);
13155         gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag, date, NULL);
13156         g_date_free (date);
13157       } else {
13158         GST_DEBUG_OBJECT (qtdemux, "could not parse date string '%s'", s);
13159       }
13160       g_free (s);
13161     }
13162   }
13163 }
13164
13165 static void
13166 qtdemux_tag_add_gnre (GstQTDemux * qtdemux, GstTagList * taglist,
13167     const char *tag, const char *dummy, GNode * node)
13168 {
13169   GNode *data;
13170
13171   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
13172
13173   /* re-route to normal string tag if major brand says so
13174    * or no data atom and compatible brand suggests so */
13175   if (qtdemux_is_brand_3gp (qtdemux, TRUE) ||
13176       (qtdemux_is_brand_3gp (qtdemux, FALSE) && !data)) {
13177     qtdemux_tag_add_str (qtdemux, taglist, tag, dummy, node);
13178     return;
13179   }
13180
13181   if (data) {
13182     guint len, type, n;
13183
13184     len = QT_UINT32 (data->data);
13185     type = QT_UINT32 ((guint8 *) data->data + 8);
13186     if (type == 0x00000000 && len >= 18) {
13187       n = QT_UINT16 ((guint8 *) data->data + 16);
13188       if (n > 0) {
13189         const gchar *genre;
13190
13191         genre = gst_tag_id3_genre_get (n - 1);
13192         if (genre != NULL) {
13193           GST_DEBUG_OBJECT (qtdemux, "adding %d [%s]", n, genre);
13194           gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag, genre, NULL);
13195         }
13196       }
13197     }
13198   }
13199 }
13200
13201 static void
13202 qtdemux_add_double_tag_from_str (GstQTDemux * demux, GstTagList * taglist,
13203     const gchar * tag, guint8 * data, guint32 datasize)
13204 {
13205   gdouble value;
13206   gchar *datacopy;
13207
13208   /* make a copy to have \0 at the end */
13209   datacopy = g_strndup ((gchar *) data, datasize);
13210
13211   /* convert the str to double */
13212   if (sscanf (datacopy, "%lf", &value) == 1) {
13213     GST_DEBUG_OBJECT (demux, "adding tag: %s [%s]", tag, datacopy);
13214     gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag, value, NULL);
13215   } else {
13216     GST_WARNING_OBJECT (demux, "Failed to parse double from string: %s",
13217         datacopy);
13218   }
13219   g_free (datacopy);
13220 }
13221
13222
13223 static void
13224 qtdemux_tag_add_revdns (GstQTDemux * demux, GstTagList * taglist,
13225     const char *tag, const char *tag_bis, GNode * node)
13226 {
13227   GNode *mean;
13228   GNode *name;
13229   GNode *data;
13230   guint32 meansize;
13231   guint32 namesize;
13232   guint32 datatype;
13233   guint32 datasize;
13234   const gchar *meanstr;
13235   const gchar *namestr;
13236
13237   /* checking the whole ---- atom size for consistency */
13238   if (QT_UINT32 (node->data) <= 4 + 12 + 12 + 16) {
13239     GST_WARNING_OBJECT (demux, "Tag ---- atom is too small, ignoring");
13240     return;
13241   }
13242
13243   mean = qtdemux_tree_get_child_by_type (node, FOURCC_mean);
13244   if (!mean) {
13245     GST_WARNING_OBJECT (demux, "No 'mean' atom found");
13246     return;
13247   }
13248
13249   meansize = QT_UINT32 (mean->data);
13250   if (meansize <= 12) {
13251     GST_WARNING_OBJECT (demux, "Small mean atom, ignoring the whole tag");
13252     return;
13253   }
13254   meanstr = ((gchar *) mean->data) + 12;
13255   meansize -= 12;
13256
13257   name = qtdemux_tree_get_child_by_type (node, FOURCC_name);
13258   if (!name) {
13259     GST_WARNING_OBJECT (demux, "'name' atom not found, ignoring tag");
13260     return;
13261   }
13262
13263   namesize = QT_UINT32 (name->data);
13264   if (namesize <= 12) {
13265     GST_WARNING_OBJECT (demux, "'name' atom is too small, ignoring tag");
13266     return;
13267   }
13268   namestr = ((gchar *) name->data) + 12;
13269   namesize -= 12;
13270
13271   /*
13272    * Data atom is:
13273    * uint32 - size
13274    * uint32 - name
13275    * uint8  - version
13276    * uint24 - data type
13277    * uint32 - all 0
13278    * rest   - the data
13279    */
13280   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
13281   if (!data) {
13282     GST_WARNING_OBJECT (demux, "No data atom in this tag");
13283     return;
13284   }
13285   datasize = QT_UINT32 (data->data);
13286   if (datasize <= 16) {
13287     GST_WARNING_OBJECT (demux, "Data atom too small");
13288     return;
13289   }
13290   datatype = QT_UINT32 (((gchar *) data->data) + 8) & 0xFFFFFF;
13291
13292   if ((strncmp (meanstr, "com.apple.iTunes", meansize) == 0) ||
13293       (strncmp (meanstr, "org.hydrogenaudio.replaygain", meansize) == 0)) {
13294     static const struct
13295     {
13296       const gchar name[28];
13297       const gchar tag[28];
13298     } tags[] = {
13299       {
13300       "replaygain_track_gain", GST_TAG_TRACK_GAIN}, {
13301       "replaygain_track_peak", GST_TAG_TRACK_PEAK}, {
13302       "replaygain_album_gain", GST_TAG_ALBUM_GAIN}, {
13303       "replaygain_album_peak", GST_TAG_ALBUM_PEAK}, {
13304       "MusicBrainz Track Id", GST_TAG_MUSICBRAINZ_TRACKID}, {
13305       "MusicBrainz Artist Id", GST_TAG_MUSICBRAINZ_ARTISTID}, {
13306       "MusicBrainz Album Id", GST_TAG_MUSICBRAINZ_ALBUMID}, {
13307       "MusicBrainz Album Artist Id", GST_TAG_MUSICBRAINZ_ALBUMARTISTID}
13308     };
13309     int i;
13310
13311     for (i = 0; i < G_N_ELEMENTS (tags); ++i) {
13312       if (!g_ascii_strncasecmp (tags[i].name, namestr, namesize)) {
13313         switch (gst_tag_get_type (tags[i].tag)) {
13314           case G_TYPE_DOUBLE:
13315             qtdemux_add_double_tag_from_str (demux, taglist, tags[i].tag,
13316                 ((guint8 *) data->data) + 16, datasize - 16);
13317             break;
13318           case G_TYPE_STRING:
13319             qtdemux_tag_add_str (demux, taglist, tags[i].tag, NULL, node);
13320             break;
13321           default:
13322             /* not reached */
13323             break;
13324         }
13325         break;
13326       }
13327     }
13328     if (i == G_N_ELEMENTS (tags))
13329       goto unknown_tag;
13330   } else {
13331     goto unknown_tag;
13332   }
13333
13334   return;
13335
13336 /* errors */
13337 unknown_tag:
13338 #ifndef GST_DISABLE_GST_DEBUG
13339   {
13340     gchar *namestr_dbg;
13341     gchar *meanstr_dbg;
13342
13343     meanstr_dbg = g_strndup (meanstr, meansize);
13344     namestr_dbg = g_strndup (namestr, namesize);
13345
13346     GST_WARNING_OBJECT (demux, "This tag %s:%s type:%u is not mapped, "
13347         "file a bug at bugzilla.gnome.org", meanstr_dbg, namestr_dbg, datatype);
13348
13349     g_free (namestr_dbg);
13350     g_free (meanstr_dbg);
13351   }
13352 #endif
13353   return;
13354 }
13355
13356 static void
13357 qtdemux_tag_add_id32 (GstQTDemux * demux, GstTagList * taglist, const char *tag,
13358     const char *tag_bis, GNode * node)
13359 {
13360   guint8 *data;
13361   GstBuffer *buf;
13362   guint len;
13363   GstTagList *id32_taglist = NULL;
13364
13365   GST_LOG_OBJECT (demux, "parsing ID32");
13366
13367   data = node->data;
13368   len = GST_READ_UINT32_BE (data);
13369
13370   /* need at least full box and language tag */
13371   if (len < 12 + 2)
13372     return;
13373
13374   buf = gst_buffer_new_allocate (NULL, len - 14, NULL);
13375   gst_buffer_fill (buf, 0, data + 14, len - 14);
13376
13377   id32_taglist = gst_tag_list_from_id3v2_tag (buf);
13378   if (id32_taglist) {
13379     GST_LOG_OBJECT (demux, "parsing ok");
13380     gst_tag_list_insert (taglist, id32_taglist, GST_TAG_MERGE_KEEP);
13381     gst_tag_list_unref (id32_taglist);
13382   } else {
13383     GST_LOG_OBJECT (demux, "parsing failed");
13384   }
13385
13386   gst_buffer_unref (buf);
13387 }
13388
13389 typedef void (*GstQTDemuxAddTagFunc) (GstQTDemux * demux, GstTagList * taglist,
13390     const char *tag, const char *tag_bis, GNode * node);
13391
13392 /* unmapped tags
13393 FOURCC_pcst -> if media is a podcast -> bool
13394 FOURCC_cpil -> if media is part of a compilation -> bool
13395 FOURCC_pgap -> if media is part of a gapless context -> bool
13396 FOURCC_tven -> the tv episode id e.g. S01E23 -> str
13397 */
13398
13399 static const struct
13400 {
13401   guint32 fourcc;
13402   const gchar *gst_tag;
13403   const gchar *gst_tag_bis;
13404   const GstQTDemuxAddTagFunc func;
13405 } add_funcs[] = {
13406   {
13407   FOURCC__nam, GST_TAG_TITLE, NULL, qtdemux_tag_add_str}, {
13408   FOURCC_titl, GST_TAG_TITLE, NULL, qtdemux_tag_add_str}, {
13409   FOURCC__grp, GST_TAG_GROUPING, NULL, qtdemux_tag_add_str}, {
13410   FOURCC__wrt, GST_TAG_COMPOSER, NULL, qtdemux_tag_add_str}, {
13411   FOURCC__ART, GST_TAG_ARTIST, NULL, qtdemux_tag_add_str}, {
13412   FOURCC_aART, GST_TAG_ALBUM_ARTIST, NULL, qtdemux_tag_add_str}, {
13413   FOURCC_perf, GST_TAG_ARTIST, NULL, qtdemux_tag_add_str}, {
13414   FOURCC_auth, GST_TAG_COMPOSER, NULL, qtdemux_tag_add_str}, {
13415   FOURCC__alb, GST_TAG_ALBUM, NULL, qtdemux_tag_add_str}, {
13416   FOURCC_albm, GST_TAG_ALBUM, NULL, qtdemux_tag_add_str}, {
13417   FOURCC_cprt, GST_TAG_COPYRIGHT, NULL, qtdemux_tag_add_str}, {
13418   FOURCC__cpy, GST_TAG_COPYRIGHT, NULL, qtdemux_tag_add_str}, {
13419   FOURCC__cmt, GST_TAG_COMMENT, NULL, qtdemux_tag_add_str}, {
13420   FOURCC__des, GST_TAG_DESCRIPTION, NULL, qtdemux_tag_add_str}, {
13421   FOURCC_desc, GST_TAG_DESCRIPTION, NULL, qtdemux_tag_add_str}, {
13422   FOURCC_dscp, GST_TAG_DESCRIPTION, NULL, qtdemux_tag_add_str}, {
13423   FOURCC__lyr, GST_TAG_LYRICS, NULL, qtdemux_tag_add_str}, {
13424   FOURCC__day, GST_TAG_DATE, NULL, qtdemux_tag_add_date}, {
13425   FOURCC_yrrc, GST_TAG_DATE, NULL, qtdemux_tag_add_year}, {
13426   FOURCC__too, GST_TAG_ENCODER, NULL, qtdemux_tag_add_str}, {
13427   FOURCC__inf, GST_TAG_COMMENT, NULL, qtdemux_tag_add_str}, {
13428   FOURCC_trkn, GST_TAG_TRACK_NUMBER, GST_TAG_TRACK_COUNT, qtdemux_tag_add_num}, {
13429   FOURCC_disk, GST_TAG_ALBUM_VOLUME_NUMBER, GST_TAG_ALBUM_VOLUME_COUNT,
13430         qtdemux_tag_add_num}, {
13431   FOURCC_disc, GST_TAG_ALBUM_VOLUME_NUMBER, GST_TAG_ALBUM_VOLUME_COUNT,
13432         qtdemux_tag_add_num}, {
13433   FOURCC__gen, GST_TAG_GENRE, NULL, qtdemux_tag_add_str}, {
13434   FOURCC_gnre, GST_TAG_GENRE, NULL, qtdemux_tag_add_gnre}, {
13435   FOURCC_tmpo, GST_TAG_BEATS_PER_MINUTE, NULL, qtdemux_tag_add_tmpo}, {
13436   FOURCC_covr, GST_TAG_IMAGE, NULL, qtdemux_tag_add_covr}, {
13437   FOURCC_sonm, GST_TAG_TITLE_SORTNAME, NULL, qtdemux_tag_add_str}, {
13438   FOURCC_soal, GST_TAG_ALBUM_SORTNAME, NULL, qtdemux_tag_add_str}, {
13439   FOURCC_soar, GST_TAG_ARTIST_SORTNAME, NULL, qtdemux_tag_add_str}, {
13440   FOURCC_soaa, GST_TAG_ALBUM_ARTIST_SORTNAME, NULL, qtdemux_tag_add_str}, {
13441   FOURCC_soco, GST_TAG_COMPOSER_SORTNAME, NULL, qtdemux_tag_add_str}, {
13442   FOURCC_sosn, GST_TAG_SHOW_SORTNAME, NULL, qtdemux_tag_add_str}, {
13443   FOURCC_tvsh, GST_TAG_SHOW_NAME, NULL, qtdemux_tag_add_str}, {
13444   FOURCC_tvsn, GST_TAG_SHOW_SEASON_NUMBER, NULL, qtdemux_tag_add_uint32}, {
13445   FOURCC_tves, GST_TAG_SHOW_EPISODE_NUMBER, NULL, qtdemux_tag_add_uint32}, {
13446   FOURCC_kywd, GST_TAG_KEYWORDS, NULL, qtdemux_tag_add_keywords}, {
13447   FOURCC_keyw, GST_TAG_KEYWORDS, NULL, qtdemux_tag_add_str}, {
13448   FOURCC__enc, GST_TAG_ENCODER, NULL, qtdemux_tag_add_str}, {
13449   FOURCC_loci, GST_TAG_GEO_LOCATION_NAME, NULL, qtdemux_tag_add_location}, {
13450   FOURCC_clsf, GST_QT_DEMUX_CLASSIFICATION_TAG, NULL,
13451         qtdemux_tag_add_classification}, {
13452   FOURCC__mak, GST_TAG_DEVICE_MANUFACTURER, NULL, qtdemux_tag_add_str}, {
13453   FOURCC__mod, GST_TAG_DEVICE_MODEL, NULL, qtdemux_tag_add_str}, {
13454   FOURCC__swr, GST_TAG_APPLICATION_NAME, NULL, qtdemux_tag_add_str}, {
13455
13456     /* This is a special case, some tags are stored in this
13457      * 'reverse dns naming', according to:
13458      * http://atomicparsley.sourceforge.net/mpeg-4files.html and
13459      * bug #614471
13460      */
13461   FOURCC_____, "", NULL, qtdemux_tag_add_revdns}, {
13462     /* see http://www.mp4ra.org/specs.html for ID32 in meta box */
13463   FOURCC_ID32, "", NULL, qtdemux_tag_add_id32}
13464 };
13465
13466 struct _GstQtDemuxTagList
13467 {
13468   GstQTDemux *demux;
13469   GstTagList *taglist;
13470 };
13471 typedef struct _GstQtDemuxTagList GstQtDemuxTagList;
13472
13473 static void
13474 qtdemux_tag_add_blob (GNode * node, GstQtDemuxTagList * qtdemuxtaglist)
13475 {
13476   gint len;
13477   guint8 *data;
13478   GstBuffer *buf;
13479   gchar *media_type;
13480   const gchar *style;
13481   GstSample *sample;
13482   GstStructure *s;
13483   guint i;
13484   guint8 ndata[4];
13485   GstQTDemux *demux = qtdemuxtaglist->demux;
13486   GstTagList *taglist = qtdemuxtaglist->taglist;
13487
13488   data = node->data;
13489   len = QT_UINT32 (data);
13490   buf = gst_buffer_new_and_alloc (len);
13491   gst_buffer_fill (buf, 0, data, len);
13492
13493   /* heuristic to determine style of tag */
13494   if (QT_FOURCC (data + 4) == FOURCC_____ ||
13495       (len > 8 + 12 && QT_FOURCC (data + 12) == FOURCC_data))
13496     style = "itunes";
13497   else if (demux->major_brand == FOURCC_qt__)
13498     style = "quicktime";
13499   /* fall back to assuming iso/3gp tag style */
13500   else
13501     style = "iso";
13502
13503   /* santize the name for the caps. */
13504   for (i = 0; i < 4; i++) {
13505     guint8 d = data[4 + i];
13506     if (g_ascii_isalnum (d))
13507       ndata[i] = g_ascii_tolower (d);
13508     else
13509       ndata[i] = '_';
13510   }
13511
13512   media_type = g_strdup_printf ("application/x-gst-qt-%c%c%c%c-tag",
13513       ndata[0], ndata[1], ndata[2], ndata[3]);
13514   GST_DEBUG_OBJECT (demux, "media type %s", media_type);
13515
13516   s = gst_structure_new (media_type, "style", G_TYPE_STRING, style, NULL);
13517   sample = gst_sample_new (buf, NULL, NULL, s);
13518   gst_buffer_unref (buf);
13519   g_free (media_type);
13520
13521   GST_DEBUG_OBJECT (demux, "adding private tag; size %d, info %" GST_PTR_FORMAT,
13522       len, s);
13523
13524   gst_tag_list_add (taglist, GST_TAG_MERGE_APPEND,
13525       GST_QT_DEMUX_PRIVATE_TAG, sample, NULL);
13526
13527   gst_sample_unref (sample);
13528 }
13529
13530 static void
13531 qtdemux_parse_udta (GstQTDemux * qtdemux, GstTagList * taglist, GNode * udta)
13532 {
13533   GNode *meta;
13534   GNode *ilst;
13535   GNode *xmp_;
13536   GNode *node;
13537   gint i;
13538   GstQtDemuxTagList demuxtaglist;
13539
13540   demuxtaglist.demux = qtdemux;
13541   demuxtaglist.taglist = taglist;
13542
13543   meta = qtdemux_tree_get_child_by_type (udta, FOURCC_meta);
13544   if (meta != NULL) {
13545     ilst = qtdemux_tree_get_child_by_type (meta, FOURCC_ilst);
13546     if (ilst == NULL) {
13547       GST_LOG_OBJECT (qtdemux, "no ilst");
13548       return;
13549     }
13550   } else {
13551     ilst = udta;
13552     GST_LOG_OBJECT (qtdemux, "no meta so using udta itself");
13553   }
13554
13555   i = 0;
13556   while (i < G_N_ELEMENTS (add_funcs)) {
13557     node = qtdemux_tree_get_child_by_type (ilst, add_funcs[i].fourcc);
13558     if (node) {
13559       gint len;
13560
13561       len = QT_UINT32 (node->data);
13562       if (len < 12) {
13563         GST_DEBUG_OBJECT (qtdemux, "too small tag atom %" GST_FOURCC_FORMAT,
13564             GST_FOURCC_ARGS (add_funcs[i].fourcc));
13565       } else {
13566         add_funcs[i].func (qtdemux, taglist, add_funcs[i].gst_tag,
13567             add_funcs[i].gst_tag_bis, node);
13568       }
13569       g_node_destroy (node);
13570     } else {
13571       i++;
13572     }
13573   }
13574
13575   /* parsed nodes have been removed, pass along remainder as blob */
13576   g_node_children_foreach (ilst, G_TRAVERSE_ALL,
13577       (GNodeForeachFunc) qtdemux_tag_add_blob, &demuxtaglist);
13578
13579   /* parse up XMP_ node if existing */
13580   xmp_ = qtdemux_tree_get_child_by_type (udta, FOURCC_XMP_);
13581   if (xmp_ != NULL) {
13582     GstBuffer *buf;
13583     GstTagList *xmptaglist;
13584
13585     buf = _gst_buffer_new_wrapped (((guint8 *) xmp_->data) + 8,
13586         QT_UINT32 ((guint8 *) xmp_->data) - 8, NULL);
13587     xmptaglist = gst_tag_list_from_xmp_buffer (buf);
13588     gst_buffer_unref (buf);
13589
13590     qtdemux_handle_xmp_taglist (qtdemux, taglist, xmptaglist);
13591   } else {
13592     GST_DEBUG_OBJECT (qtdemux, "No XMP_ node found");
13593   }
13594 }
13595
13596 typedef struct
13597 {
13598   GstStructure *structure;      /* helper for sort function */
13599   gchar *location;
13600   guint min_req_bitrate;
13601   guint min_req_qt_version;
13602 } GstQtReference;
13603
13604 static gint
13605 qtdemux_redirects_sort_func (gconstpointer a, gconstpointer b)
13606 {
13607   GstQtReference *ref_a = (GstQtReference *) a;
13608   GstQtReference *ref_b = (GstQtReference *) b;
13609
13610   if (ref_b->min_req_qt_version != ref_a->min_req_qt_version)
13611     return ref_b->min_req_qt_version - ref_a->min_req_qt_version;
13612
13613   /* known bitrates go before unknown; higher bitrates go first */
13614   return ref_b->min_req_bitrate - ref_a->min_req_bitrate;
13615 }
13616
13617 /* sort the redirects and post a message for the application.
13618  */
13619 static void
13620 qtdemux_process_redirects (GstQTDemux * qtdemux, GList * references)
13621 {
13622   GstQtReference *best;
13623   GstStructure *s;
13624   GstMessage *msg;
13625   GValue list_val = { 0, };
13626   GList *l;
13627
13628   g_assert (references != NULL);
13629
13630   references = g_list_sort (references, qtdemux_redirects_sort_func);
13631
13632   best = (GstQtReference *) references->data;
13633
13634   g_value_init (&list_val, GST_TYPE_LIST);
13635
13636   for (l = references; l != NULL; l = l->next) {
13637     GstQtReference *ref = (GstQtReference *) l->data;
13638     GValue struct_val = { 0, };
13639
13640     ref->structure = gst_structure_new ("redirect",
13641         "new-location", G_TYPE_STRING, ref->location, NULL);
13642
13643     if (ref->min_req_bitrate > 0) {
13644       gst_structure_set (ref->structure, "minimum-bitrate", G_TYPE_INT,
13645           ref->min_req_bitrate, NULL);
13646     }
13647
13648     g_value_init (&struct_val, GST_TYPE_STRUCTURE);
13649     g_value_set_boxed (&struct_val, ref->structure);
13650     gst_value_list_append_value (&list_val, &struct_val);
13651     g_value_unset (&struct_val);
13652     /* don't free anything here yet, since we need best->structure below */
13653   }
13654
13655   g_assert (best != NULL);
13656   s = gst_structure_copy (best->structure);
13657
13658   if (g_list_length (references) > 1) {
13659     gst_structure_set_value (s, "locations", &list_val);
13660   }
13661
13662   g_value_unset (&list_val);
13663
13664   for (l = references; l != NULL; l = l->next) {
13665     GstQtReference *ref = (GstQtReference *) l->data;
13666
13667     gst_structure_free (ref->structure);
13668     g_free (ref->location);
13669     g_free (ref);
13670   }
13671   g_list_free (references);
13672
13673   GST_INFO_OBJECT (qtdemux, "posting redirect message: %" GST_PTR_FORMAT, s);
13674   msg = gst_message_new_element (GST_OBJECT_CAST (qtdemux), s);
13675   gst_element_post_message (GST_ELEMENT_CAST (qtdemux), msg);
13676   qtdemux->posted_redirect = TRUE;
13677 }
13678
13679 /* look for redirect nodes, collect all redirect information and
13680  * process it.
13681  */
13682 static gboolean
13683 qtdemux_parse_redirects (GstQTDemux * qtdemux)
13684 {
13685   GNode *rmra, *rmda, *rdrf;
13686
13687   rmra = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_rmra);
13688   if (rmra) {
13689     GList *redirects = NULL;
13690
13691     rmda = qtdemux_tree_get_child_by_type (rmra, FOURCC_rmda);
13692     while (rmda) {
13693       GstQtReference ref = { NULL, NULL, 0, 0 };
13694       GNode *rmdr, *rmvc;
13695
13696       if ((rmdr = qtdemux_tree_get_child_by_type (rmda, FOURCC_rmdr))) {
13697         ref.min_req_bitrate = QT_UINT32 ((guint8 *) rmdr->data + 12);
13698         GST_LOG_OBJECT (qtdemux, "data rate atom, required bitrate = %u",
13699             ref.min_req_bitrate);
13700       }
13701
13702       if ((rmvc = qtdemux_tree_get_child_by_type (rmda, FOURCC_rmvc))) {
13703         guint32 package = QT_FOURCC ((guint8 *) rmvc->data + 12);
13704         guint version = QT_UINT32 ((guint8 *) rmvc->data + 16);
13705
13706 #ifndef GST_DISABLE_GST_DEBUG
13707         guint bitmask = QT_UINT32 ((guint8 *) rmvc->data + 20);
13708 #endif
13709         guint check_type = QT_UINT16 ((guint8 *) rmvc->data + 24);
13710
13711         GST_LOG_OBJECT (qtdemux,
13712             "version check atom [%" GST_FOURCC_FORMAT "], version=0x%08x"
13713             ", mask=%08x, check_type=%u", GST_FOURCC_ARGS (package), version,
13714             bitmask, check_type);
13715         if (package == FOURCC_qtim && check_type == 0) {
13716           ref.min_req_qt_version = version;
13717         }
13718       }
13719
13720       rdrf = qtdemux_tree_get_child_by_type (rmda, FOURCC_rdrf);
13721       if (rdrf) {
13722         guint32 ref_type;
13723         guint8 *ref_data;
13724         guint ref_len;
13725
13726         ref_len = QT_UINT32 ((guint8 *) rdrf->data);
13727         if (ref_len > 20) {
13728           ref_type = QT_FOURCC ((guint8 *) rdrf->data + 12);
13729           ref_data = (guint8 *) rdrf->data + 20;
13730           if (ref_type == FOURCC_alis) {
13731             guint record_len, record_version, fn_len;
13732
13733             if (ref_len > 70) {
13734               /* MacOSX alias record, google for alias-layout.txt */
13735               record_len = QT_UINT16 (ref_data + 4);
13736               record_version = QT_UINT16 (ref_data + 4 + 2);
13737               fn_len = QT_UINT8 (ref_data + 50);
13738               if (record_len > 50 && record_version == 2 && fn_len > 0) {
13739                 ref.location = g_strndup ((gchar *) ref_data + 51, fn_len);
13740               }
13741             } else {
13742               GST_WARNING_OBJECT (qtdemux, "Invalid rdrf/alis size (%u < 70)",
13743                   ref_len);
13744             }
13745           } else if (ref_type == FOURCC_url_) {
13746             ref.location = g_strndup ((gchar *) ref_data, ref_len - 8);
13747           } else {
13748             GST_DEBUG_OBJECT (qtdemux,
13749                 "unknown rdrf reference type %" GST_FOURCC_FORMAT,
13750                 GST_FOURCC_ARGS (ref_type));
13751           }
13752           if (ref.location != NULL) {
13753             GST_INFO_OBJECT (qtdemux, "New location: %s", ref.location);
13754             redirects =
13755                 g_list_prepend (redirects, g_memdup (&ref, sizeof (ref)));
13756           } else {
13757             GST_WARNING_OBJECT (qtdemux,
13758                 "Failed to extract redirect location from rdrf atom");
13759           }
13760         } else {
13761           GST_WARNING_OBJECT (qtdemux, "Invalid rdrf size (%u < 20)", ref_len);
13762         }
13763       }
13764
13765       /* look for others */
13766       rmda = qtdemux_tree_get_sibling_by_type (rmda, FOURCC_rmda);
13767     }
13768
13769     if (redirects != NULL) {
13770       qtdemux_process_redirects (qtdemux, redirects);
13771     }
13772   }
13773   return TRUE;
13774 }
13775
13776 static GstTagList *
13777 qtdemux_add_container_format (GstQTDemux * qtdemux, GstTagList * tags)
13778 {
13779   const gchar *fmt;
13780
13781   if (tags == NULL) {
13782     tags = gst_tag_list_new_empty ();
13783     gst_tag_list_set_scope (tags, GST_TAG_SCOPE_GLOBAL);
13784   }
13785
13786   if (qtdemux->major_brand == FOURCC_mjp2)
13787     fmt = "Motion JPEG 2000";
13788   else if ((qtdemux->major_brand & 0xffff) == FOURCC_3g__)
13789     fmt = "3GP";
13790   else if (qtdemux->major_brand == FOURCC_qt__)
13791     fmt = "Quicktime";
13792   else if (qtdemux->fragmented)
13793     fmt = "ISO fMP4";
13794   else
13795     fmt = "ISO MP4/M4A";
13796
13797   GST_LOG_OBJECT (qtdemux, "mapped %" GST_FOURCC_FORMAT " to '%s'",
13798       GST_FOURCC_ARGS (qtdemux->major_brand), fmt);
13799
13800   gst_tag_list_add (tags, GST_TAG_MERGE_REPLACE, GST_TAG_CONTAINER_FORMAT,
13801       fmt, NULL);
13802
13803   return tags;
13804 }
13805
13806 /* we have read the complete moov node now.
13807  * This function parses all of the relevant info, creates the traks and
13808  * prepares all data structures for playback
13809  */
13810 static gboolean
13811 qtdemux_parse_tree (GstQTDemux * qtdemux)
13812 {
13813   GNode *mvhd;
13814   GNode *trak;
13815   GNode *udta;
13816   GNode *mvex;
13817   GNode *pssh;
13818   guint64 creation_time;
13819   GstDateTime *datetime = NULL;
13820   gint version;
13821
13822   /* make sure we have a usable taglist */
13823   qtdemux->tag_list = gst_tag_list_make_writable (qtdemux->tag_list);
13824
13825   mvhd = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_mvhd);
13826   if (mvhd == NULL) {
13827     GST_LOG_OBJECT (qtdemux, "No mvhd node found, looking for redirects.");
13828     return qtdemux_parse_redirects (qtdemux);
13829   }
13830
13831   version = QT_UINT8 ((guint8 *) mvhd->data + 8);
13832   if (version == 1) {
13833     creation_time = QT_UINT64 ((guint8 *) mvhd->data + 12);
13834     qtdemux->timescale = QT_UINT32 ((guint8 *) mvhd->data + 28);
13835     qtdemux->duration = QT_UINT64 ((guint8 *) mvhd->data + 32);
13836   } else if (version == 0) {
13837     creation_time = QT_UINT32 ((guint8 *) mvhd->data + 12);
13838     qtdemux->timescale = QT_UINT32 ((guint8 *) mvhd->data + 20);
13839     qtdemux->duration = QT_UINT32 ((guint8 *) mvhd->data + 24);
13840   } else {
13841     GST_WARNING_OBJECT (qtdemux, "Unhandled mvhd version %d", version);
13842     return FALSE;
13843   }
13844
13845   /* Moving qt creation time (secs since 1904) to unix time */
13846   if (creation_time != 0) {
13847     /* Try to use epoch first as it should be faster and more commonly found */
13848     if (creation_time >= QTDEMUX_SECONDS_FROM_1904_TO_1970) {
13849       GTimeVal now;
13850
13851       creation_time -= QTDEMUX_SECONDS_FROM_1904_TO_1970;
13852       /* some data cleansing sanity */
13853       g_get_current_time (&now);
13854       if (now.tv_sec + 24 * 3600 < creation_time) {
13855         GST_DEBUG_OBJECT (qtdemux, "discarding bogus future creation time");
13856       } else {
13857         datetime = gst_date_time_new_from_unix_epoch_utc (creation_time);
13858       }
13859     } else {
13860       GDateTime *base_dt = g_date_time_new_utc (1904, 1, 1, 0, 0, 0);
13861       GDateTime *dt, *dt_local;
13862
13863       dt = g_date_time_add_seconds (base_dt, creation_time);
13864       dt_local = g_date_time_to_local (dt);
13865       datetime = gst_date_time_new_from_g_date_time (dt_local);
13866
13867       g_date_time_unref (base_dt);
13868       g_date_time_unref (dt);
13869     }
13870   }
13871   if (datetime) {
13872     /* Use KEEP as explicit tags should have a higher priority than mvhd tag */
13873     gst_tag_list_add (qtdemux->tag_list, GST_TAG_MERGE_KEEP, GST_TAG_DATE_TIME,
13874         datetime, NULL);
13875     gst_date_time_unref (datetime);
13876   }
13877
13878   GST_INFO_OBJECT (qtdemux, "timescale: %u", qtdemux->timescale);
13879   GST_INFO_OBJECT (qtdemux, "duration: %" G_GUINT64_FORMAT, qtdemux->duration);
13880
13881   /* check for fragmented file and get some (default) data */
13882   mvex = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_mvex);
13883   if (mvex) {
13884     GNode *mehd;
13885     GstByteReader mehd_data;
13886
13887     /* let track parsing or anyone know weird stuff might happen ... */
13888     qtdemux->fragmented = TRUE;
13889
13890     /* compensate for total duration */
13891     mehd = qtdemux_tree_get_child_by_type_full (mvex, FOURCC_mehd, &mehd_data);
13892     if (mehd)
13893       qtdemux_parse_mehd (qtdemux, &mehd_data);
13894   }
13895
13896   /* Update the movie segment duration, unless it was directly given to us
13897    * by upstream. Otherwise let it as is, as we don't want to mangle the
13898    * duration provided by upstream that may come e.g. from a MPD file. */
13899   if (!qtdemux->upstream_format_is_time) {
13900     GstClockTime duration;
13901     /* set duration in the segment info */
13902     gst_qtdemux_get_duration (qtdemux, &duration);
13903     qtdemux->segment.duration = duration;
13904     /* also do not exceed duration; stop is set that way post seek anyway,
13905      * and segment activation falls back to duration,
13906      * whereas loop only checks stop, so let's align this here as well */
13907     qtdemux->segment.stop = duration;
13908   }
13909
13910   /* parse all traks */
13911   trak = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_trak);
13912   while (trak) {
13913     qtdemux_parse_trak (qtdemux, trak);
13914     /* iterate all siblings */
13915     trak = qtdemux_tree_get_sibling_by_type (trak, FOURCC_trak);
13916   }
13917
13918   qtdemux->tag_list = gst_tag_list_make_writable (qtdemux->tag_list);
13919
13920   /* find tags */
13921   udta = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_udta);
13922   if (udta) {
13923     qtdemux_parse_udta (qtdemux, qtdemux->tag_list, udta);
13924   } else {
13925     GST_LOG_OBJECT (qtdemux, "No udta node found.");
13926   }
13927
13928   /* maybe also some tags in meta box */
13929   udta = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_meta);
13930   if (udta) {
13931     GST_DEBUG_OBJECT (qtdemux, "Parsing meta box for tags.");
13932     qtdemux_parse_udta (qtdemux, qtdemux->tag_list, udta);
13933   } else {
13934     GST_LOG_OBJECT (qtdemux, "No meta node found.");
13935   }
13936
13937   /* parse any protection system info */
13938   pssh = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_pssh);
13939   while (pssh) {
13940     GST_LOG_OBJECT (qtdemux, "Parsing pssh box.");
13941     qtdemux_parse_pssh (qtdemux, pssh);
13942     pssh = qtdemux_tree_get_sibling_by_type (pssh, FOURCC_pssh);
13943   }
13944
13945   qtdemux->tag_list = qtdemux_add_container_format (qtdemux, qtdemux->tag_list);
13946
13947   return TRUE;
13948 }
13949
13950 /* taken from ffmpeg */
13951 static int
13952 read_descr_size (guint8 * ptr, guint8 * end, guint8 ** end_out)
13953 {
13954   int count = 4;
13955   int len = 0;
13956
13957   while (count--) {
13958     int c;
13959
13960     if (ptr >= end)
13961       return -1;
13962
13963     c = *ptr++;
13964     len = (len << 7) | (c & 0x7f);
13965     if (!(c & 0x80))
13966       break;
13967   }
13968   *end_out = ptr;
13969   return len;
13970 }
13971
13972 static GList *
13973 parse_xiph_stream_headers (GstQTDemux * qtdemux, gpointer codec_data,
13974     gsize codec_data_size)
13975 {
13976   GList *list = NULL;
13977   guint8 *p = codec_data;
13978   gint i, offset, num_packets;
13979   guint *length, last;
13980
13981   GST_MEMDUMP_OBJECT (qtdemux, "xiph codec data", codec_data, codec_data_size);
13982
13983   if (codec_data == NULL || codec_data_size == 0)
13984     goto error;
13985
13986   /* start of the stream and vorbis audio or theora video, need to
13987    * send the codec_priv data as first three packets */
13988   num_packets = p[0] + 1;
13989   GST_DEBUG_OBJECT (qtdemux,
13990       "%u stream headers, total length=%" G_GSIZE_FORMAT " bytes",
13991       (guint) num_packets, codec_data_size);
13992
13993   /* Let's put some limits, Don't think there even is a xiph codec
13994    * with more than 3-4 headers */
13995   if (G_UNLIKELY (num_packets > 16)) {
13996     GST_WARNING_OBJECT (qtdemux,
13997         "Unlikely number of xiph headers, most likely not valid");
13998     goto error;
13999   }
14000
14001   length = g_alloca (num_packets * sizeof (guint));
14002   last = 0;
14003   offset = 1;
14004
14005   /* first packets, read length values */
14006   for (i = 0; i < num_packets - 1; i++) {
14007     length[i] = 0;
14008     while (offset < codec_data_size) {
14009       length[i] += p[offset];
14010       if (p[offset++] != 0xff)
14011         break;
14012     }
14013     last += length[i];
14014   }
14015   if (offset + last > codec_data_size)
14016     goto error;
14017
14018   /* last packet is the remaining size */
14019   length[i] = codec_data_size - offset - last;
14020
14021   for (i = 0; i < num_packets; i++) {
14022     GstBuffer *hdr;
14023
14024     GST_DEBUG_OBJECT (qtdemux, "buffer %d: %u bytes", i, (guint) length[i]);
14025
14026     if (offset + length[i] > codec_data_size)
14027       goto error;
14028
14029     hdr = gst_buffer_new_wrapped (g_memdup (p + offset, length[i]), length[i]);
14030     list = g_list_append (list, hdr);
14031
14032     offset += length[i];
14033   }
14034
14035   return list;
14036
14037   /* ERRORS */
14038 error:
14039   {
14040     if (list != NULL)
14041       g_list_free_full (list, (GDestroyNotify) gst_buffer_unref);
14042     return NULL;
14043   }
14044
14045 }
14046
14047 /* this can change the codec originally present in @list */
14048 static void
14049 gst_qtdemux_handle_esds (GstQTDemux * qtdemux, QtDemuxStream * stream,
14050     QtDemuxStreamStsdEntry * entry, GNode * esds, GstTagList * list)
14051 {
14052   int len = QT_UINT32 (esds->data);
14053   guint8 *ptr = esds->data;
14054   guint8 *end = ptr + len;
14055   int tag;
14056   guint8 *data_ptr = NULL;
14057   int data_len = 0;
14058   guint8 object_type_id = 0;
14059   guint8 stream_type = 0;
14060   const char *codec_name = NULL;
14061   GstCaps *caps = NULL;
14062
14063   GST_MEMDUMP_OBJECT (qtdemux, "esds", ptr, len);
14064   ptr += 8;
14065   GST_DEBUG_OBJECT (qtdemux, "version/flags = %08x", QT_UINT32 (ptr));
14066   ptr += 4;
14067   while (ptr + 1 < end) {
14068     tag = QT_UINT8 (ptr);
14069     GST_DEBUG_OBJECT (qtdemux, "tag = %02x", tag);
14070     ptr++;
14071     len = read_descr_size (ptr, end, &ptr);
14072     GST_DEBUG_OBJECT (qtdemux, "len = %d", len);
14073
14074     /* Check the stated amount of data is available for reading */
14075     if (len < 0 || ptr + len > end)
14076       break;
14077
14078     switch (tag) {
14079       case ES_DESCRIPTOR_TAG:
14080         GST_DEBUG_OBJECT (qtdemux, "ID 0x%04x", QT_UINT16 (ptr));
14081         GST_DEBUG_OBJECT (qtdemux, "priority 0x%04x", QT_UINT8 (ptr + 2));
14082         ptr += 3;
14083         break;
14084       case DECODER_CONFIG_DESC_TAG:{
14085         guint max_bitrate, avg_bitrate;
14086
14087         object_type_id = QT_UINT8 (ptr);
14088         stream_type = QT_UINT8 (ptr + 1) >> 2;
14089         max_bitrate = QT_UINT32 (ptr + 5);
14090         avg_bitrate = QT_UINT32 (ptr + 9);
14091         GST_DEBUG_OBJECT (qtdemux, "object_type_id %02x", object_type_id);
14092         GST_DEBUG_OBJECT (qtdemux, "stream_type %02x", stream_type);
14093         GST_DEBUG_OBJECT (qtdemux, "buffer_size_db %02x", QT_UINT24 (ptr + 2));
14094         GST_DEBUG_OBJECT (qtdemux, "max bitrate %u", max_bitrate);
14095         GST_DEBUG_OBJECT (qtdemux, "avg bitrate %u", avg_bitrate);
14096         if (max_bitrate > 0 && max_bitrate < G_MAXUINT32) {
14097           gst_tag_list_add (list, GST_TAG_MERGE_REPLACE,
14098               GST_TAG_MAXIMUM_BITRATE, max_bitrate, NULL);
14099         }
14100         if (avg_bitrate > 0 && avg_bitrate < G_MAXUINT32) {
14101           gst_tag_list_add (list, GST_TAG_MERGE_REPLACE, GST_TAG_BITRATE,
14102               avg_bitrate, NULL);
14103         }
14104         ptr += 13;
14105         break;
14106       }
14107       case DECODER_SPECIFIC_INFO_TAG:
14108         GST_MEMDUMP_OBJECT (qtdemux, "data", ptr, len);
14109         if (object_type_id == 0xe0 && len == 0x40) {
14110           guint8 *data;
14111           GstStructure *s;
14112           guint32 clut[16];
14113           gint i;
14114
14115           GST_DEBUG_OBJECT (qtdemux,
14116               "Have VOBSUB palette. Creating palette event");
14117           /* move to decConfigDescr data and read palette */
14118           data = ptr;
14119           for (i = 0; i < 16; i++) {
14120             clut[i] = QT_UINT32 (data);
14121             data += 4;
14122           }
14123
14124           s = gst_structure_new ("application/x-gst-dvd", "event",
14125               G_TYPE_STRING, "dvd-spu-clut-change",
14126               "clut00", G_TYPE_INT, clut[0], "clut01", G_TYPE_INT, clut[1],
14127               "clut02", G_TYPE_INT, clut[2], "clut03", G_TYPE_INT, clut[3],
14128               "clut04", G_TYPE_INT, clut[4], "clut05", G_TYPE_INT, clut[5],
14129               "clut06", G_TYPE_INT, clut[6], "clut07", G_TYPE_INT, clut[7],
14130               "clut08", G_TYPE_INT, clut[8], "clut09", G_TYPE_INT, clut[9],
14131               "clut10", G_TYPE_INT, clut[10], "clut11", G_TYPE_INT, clut[11],
14132               "clut12", G_TYPE_INT, clut[12], "clut13", G_TYPE_INT, clut[13],
14133               "clut14", G_TYPE_INT, clut[14], "clut15", G_TYPE_INT, clut[15],
14134               NULL);
14135
14136           /* store event and trigger custom processing */
14137           stream->pending_event =
14138               gst_event_new_custom (GST_EVENT_CUSTOM_DOWNSTREAM, s);
14139         } else {
14140           /* Generic codec_data handler puts it on the caps */
14141           data_ptr = ptr;
14142           data_len = len;
14143         }
14144
14145         ptr += len;
14146         break;
14147       case SL_CONFIG_DESC_TAG:
14148         GST_DEBUG_OBJECT (qtdemux, "data %02x", QT_UINT8 (ptr));
14149         ptr += 1;
14150         break;
14151       default:
14152         GST_DEBUG_OBJECT (qtdemux, "Unknown/unhandled descriptor tag %02x",
14153             tag);
14154         GST_MEMDUMP_OBJECT (qtdemux, "descriptor data", ptr, len);
14155         ptr += len;
14156         break;
14157     }
14158   }
14159
14160   /* object_type_id in the esds atom in mp4a and mp4v tells us which codec is
14161    * in use, and should also be used to override some other parameters for some
14162    * codecs. */
14163   switch (object_type_id) {
14164     case 0x20:                 /* MPEG-4 */
14165       /* 4 bytes for the visual_object_sequence_start_code and 1 byte for the
14166        * profile_and_level_indication */
14167       if (data_ptr != NULL && data_len >= 5 &&
14168           GST_READ_UINT32_BE (data_ptr) == 0x000001b0) {
14169         gst_codec_utils_mpeg4video_caps_set_level_and_profile (entry->caps,
14170             data_ptr + 4, data_len - 4);
14171       }
14172       break;                    /* Nothing special needed here */
14173     case 0x21:                 /* H.264 */
14174       codec_name = "H.264 / AVC";
14175       caps = gst_caps_new_simple ("video/x-h264",
14176           "stream-format", G_TYPE_STRING, "avc",
14177           "alignment", G_TYPE_STRING, "au", NULL);
14178       break;
14179     case 0x40:                 /* AAC (any) */
14180     case 0x66:                 /* AAC Main */
14181     case 0x67:                 /* AAC LC */
14182     case 0x68:                 /* AAC SSR */
14183       /* Override channels and rate based on the codec_data, as it's often
14184        * wrong. */
14185       /* Only do so for basic setup without HE-AAC extension */
14186       if (data_ptr && data_len == 2) {
14187         guint channels, rate;
14188
14189         channels = gst_codec_utils_aac_get_channels (data_ptr, data_len);
14190         if (channels > 0)
14191           entry->n_channels = channels;
14192
14193         rate = gst_codec_utils_aac_get_sample_rate (data_ptr, data_len);
14194         if (rate > 0)
14195           entry->rate = rate;
14196       }
14197
14198       /* Set level and profile if possible */
14199       if (data_ptr != NULL && data_len >= 2) {
14200         gst_codec_utils_aac_caps_set_level_and_profile (entry->caps,
14201             data_ptr, data_len);
14202       } else {
14203         const gchar *profile_str = NULL;
14204         GstBuffer *buffer;
14205         GstMapInfo map;
14206         guint8 *codec_data;
14207         gint rate_idx, profile;
14208
14209         /* No codec_data, let's invent something.
14210          * FIXME: This is wrong for SBR! */
14211
14212         GST_WARNING_OBJECT (qtdemux, "No codec_data for AAC available");
14213
14214         buffer = gst_buffer_new_and_alloc (2);
14215         gst_buffer_map (buffer, &map, GST_MAP_WRITE);
14216         codec_data = map.data;
14217
14218         rate_idx =
14219             gst_codec_utils_aac_get_index_from_sample_rate (CUR_STREAM
14220             (stream)->rate);
14221
14222         switch (object_type_id) {
14223           case 0x66:
14224             profile_str = "main";
14225             profile = 0;
14226             break;
14227           case 0x67:
14228             profile_str = "lc";
14229             profile = 1;
14230             break;
14231           case 0x68:
14232             profile_str = "ssr";
14233             profile = 2;
14234             break;
14235           default:
14236             profile = 3;
14237             break;
14238         }
14239
14240         codec_data[0] = ((profile + 1) << 3) | ((rate_idx & 0xE) >> 1);
14241         codec_data[1] =
14242             ((rate_idx & 0x1) << 7) | (CUR_STREAM (stream)->n_channels << 3);
14243
14244         gst_buffer_unmap (buffer, &map);
14245         gst_caps_set_simple (CUR_STREAM (stream)->caps, "codec_data",
14246             GST_TYPE_BUFFER, buffer, NULL);
14247         gst_buffer_unref (buffer);
14248
14249         if (profile_str) {
14250           gst_caps_set_simple (CUR_STREAM (stream)->caps, "profile",
14251               G_TYPE_STRING, profile_str, NULL);
14252         }
14253       }
14254       break;
14255     case 0x60:                 /* MPEG-2, various profiles */
14256     case 0x61:
14257     case 0x62:
14258     case 0x63:
14259     case 0x64:
14260     case 0x65:
14261       codec_name = "MPEG-2 video";
14262       caps = gst_caps_new_simple ("video/mpeg",
14263           "mpegversion", G_TYPE_INT, 2,
14264           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
14265       break;
14266     case 0x69:                 /* MPEG-2 BC audio */
14267     case 0x6B:                 /* MPEG-1 audio */
14268       caps = gst_caps_new_simple ("audio/mpeg",
14269           "mpegversion", G_TYPE_INT, 1, NULL);
14270       codec_name = "MPEG-1 audio";
14271       break;
14272     case 0x6A:                 /* MPEG-1 */
14273       codec_name = "MPEG-1 video";
14274       caps = gst_caps_new_simple ("video/mpeg",
14275           "mpegversion", G_TYPE_INT, 1,
14276           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
14277       break;
14278     case 0x6C:                 /* MJPEG */
14279       caps =
14280           gst_caps_new_simple ("image/jpeg", "parsed", G_TYPE_BOOLEAN, TRUE,
14281           NULL);
14282       codec_name = "Motion-JPEG";
14283       break;
14284     case 0x6D:                 /* PNG */
14285       caps =
14286           gst_caps_new_simple ("image/png", "parsed", G_TYPE_BOOLEAN, TRUE,
14287           NULL);
14288       codec_name = "PNG still images";
14289       break;
14290     case 0x6E:                 /* JPEG2000 */
14291       codec_name = "JPEG-2000";
14292       caps = gst_caps_new_simple ("image/x-j2c", "fields", G_TYPE_INT, 1, NULL);
14293       break;
14294     case 0xA4:                 /* Dirac */
14295       codec_name = "Dirac";
14296       caps = gst_caps_new_empty_simple ("video/x-dirac");
14297       break;
14298     case 0xA5:                 /* AC3 */
14299       codec_name = "AC-3 audio";
14300       caps = gst_caps_new_simple ("audio/x-ac3",
14301           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
14302       break;
14303     case 0xA9:                 /* AC3 */
14304       codec_name = "DTS audio";
14305       caps = gst_caps_new_simple ("audio/x-dts",
14306           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
14307       break;
14308     case 0xDD:
14309       if (stream_type == 0x05 && data_ptr) {
14310         GList *headers =
14311             parse_xiph_stream_headers (qtdemux, data_ptr, data_len);
14312         if (headers) {
14313           GList *tmp;
14314           GValue arr_val = G_VALUE_INIT;
14315           GValue buf_val = G_VALUE_INIT;
14316           GstStructure *s;
14317
14318           /* Let's assume it's vorbis if it's an audio stream of type 0xdd and we have codec data that extracts properly */
14319           codec_name = "Vorbis";
14320           caps = gst_caps_new_empty_simple ("audio/x-vorbis");
14321           g_value_init (&arr_val, GST_TYPE_ARRAY);
14322           g_value_init (&buf_val, GST_TYPE_BUFFER);
14323           for (tmp = headers; tmp; tmp = tmp->next) {
14324             g_value_set_boxed (&buf_val, (GstBuffer *) tmp->data);
14325             gst_value_array_append_value (&arr_val, &buf_val);
14326           }
14327           s = gst_caps_get_structure (caps, 0);
14328           gst_structure_take_value (s, "streamheader", &arr_val);
14329           g_value_unset (&buf_val);
14330           g_list_free (headers);
14331
14332           data_ptr = NULL;
14333           data_len = 0;
14334         }
14335       }
14336       break;
14337     case 0xE1:                 /* QCELP */
14338       /* QCELP, the codec_data is a riff tag (little endian) with
14339        * 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). */
14340       caps = gst_caps_new_empty_simple ("audio/qcelp");
14341       codec_name = "QCELP";
14342       break;
14343     default:
14344       break;
14345   }
14346
14347   /* If we have a replacement caps, then change our caps for this stream */
14348   if (caps) {
14349     gst_caps_unref (entry->caps);
14350     entry->caps = caps;
14351   }
14352
14353   if (codec_name && list)
14354     gst_tag_list_add (list, GST_TAG_MERGE_REPLACE,
14355         GST_TAG_AUDIO_CODEC, codec_name, NULL);
14356
14357   /* Add the codec_data attribute to caps, if we have it */
14358   if (data_ptr) {
14359     GstBuffer *buffer;
14360
14361     buffer = gst_buffer_new_and_alloc (data_len);
14362     gst_buffer_fill (buffer, 0, data_ptr, data_len);
14363
14364     GST_DEBUG_OBJECT (qtdemux, "setting codec_data from esds");
14365     GST_MEMDUMP_OBJECT (qtdemux, "codec_data from esds", data_ptr, data_len);
14366
14367     gst_caps_set_simple (entry->caps, "codec_data", GST_TYPE_BUFFER,
14368         buffer, NULL);
14369     gst_buffer_unref (buffer);
14370   }
14371
14372 }
14373
14374 static inline GstCaps *
14375 _get_unknown_codec_name (const gchar * type, guint32 fourcc)
14376 {
14377   GstCaps *caps;
14378   guint i;
14379   char *s, fourstr[5];
14380
14381   g_snprintf (fourstr, 5, "%" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (fourcc));
14382   for (i = 0; i < 4; i++) {
14383     if (!g_ascii_isalnum (fourstr[i]))
14384       fourstr[i] = '_';
14385   }
14386   s = g_strdup_printf ("%s/x-gst-fourcc-%s", type, g_strstrip (fourstr));
14387   caps = gst_caps_new_empty_simple (s);
14388   g_free (s);
14389   return caps;
14390 }
14391
14392 #define _codec(name) \
14393   do { \
14394     if (codec_name) { \
14395       *codec_name = g_strdup (name); \
14396     } \
14397   } while (0)
14398
14399 static GstCaps *
14400 qtdemux_video_caps (GstQTDemux * qtdemux, QtDemuxStream * stream,
14401     QtDemuxStreamStsdEntry * entry, guint32 fourcc,
14402     const guint8 * stsd_entry_data, gchar ** codec_name)
14403 {
14404   GstCaps *caps = NULL;
14405   GstVideoFormat format = GST_VIDEO_FORMAT_UNKNOWN;
14406
14407   switch (fourcc) {
14408     case FOURCC_png:
14409       _codec ("PNG still images");
14410       caps = gst_caps_new_empty_simple ("image/png");
14411       break;
14412     case FOURCC_jpeg:
14413       _codec ("JPEG still images");
14414       caps =
14415           gst_caps_new_simple ("image/jpeg", "parsed", G_TYPE_BOOLEAN, TRUE,
14416           NULL);
14417       break;
14418     case GST_MAKE_FOURCC ('m', 'j', 'p', 'a'):
14419     case GST_MAKE_FOURCC ('A', 'V', 'D', 'J'):
14420     case GST_MAKE_FOURCC ('M', 'J', 'P', 'G'):
14421     case GST_MAKE_FOURCC ('d', 'm', 'b', '1'):
14422       _codec ("Motion-JPEG");
14423       caps =
14424           gst_caps_new_simple ("image/jpeg", "parsed", G_TYPE_BOOLEAN, TRUE,
14425           NULL);
14426       break;
14427     case GST_MAKE_FOURCC ('m', 'j', 'p', 'b'):
14428       _codec ("Motion-JPEG format B");
14429       caps = gst_caps_new_empty_simple ("video/x-mjpeg-b");
14430       break;
14431     case FOURCC_mjp2:
14432       _codec ("JPEG-2000");
14433       /* override to what it should be according to spec, avoid palette_data */
14434       entry->bits_per_sample = 24;
14435       caps = gst_caps_new_simple ("image/x-j2c", "fields", G_TYPE_INT, 1, NULL);
14436       break;
14437     case FOURCC_SVQ3:
14438       _codec ("Sorensen video v.3");
14439       caps = gst_caps_new_simple ("video/x-svq",
14440           "svqversion", G_TYPE_INT, 3, NULL);
14441       break;
14442     case GST_MAKE_FOURCC ('s', 'v', 'q', 'i'):
14443     case GST_MAKE_FOURCC ('S', 'V', 'Q', '1'):
14444       _codec ("Sorensen video v.1");
14445       caps = gst_caps_new_simple ("video/x-svq",
14446           "svqversion", G_TYPE_INT, 1, NULL);
14447       break;
14448     case GST_MAKE_FOURCC ('W', 'R', 'A', 'W'):
14449       caps = gst_caps_new_empty_simple ("video/x-raw");
14450       gst_caps_set_simple (caps, "format", G_TYPE_STRING, "RGB8P", NULL);
14451       _codec ("Windows Raw RGB");
14452       stream->alignment = 32;
14453       break;
14454     case FOURCC_raw_:
14455     {
14456       guint16 bps;
14457
14458       bps = QT_UINT16 (stsd_entry_data + 82);
14459       switch (bps) {
14460         case 15:
14461           format = GST_VIDEO_FORMAT_RGB15;
14462           break;
14463         case 16:
14464           format = GST_VIDEO_FORMAT_RGB16;
14465           break;
14466         case 24:
14467           format = GST_VIDEO_FORMAT_RGB;
14468           break;
14469         case 32:
14470           format = GST_VIDEO_FORMAT_ARGB;
14471           break;
14472         default:
14473           /* unknown */
14474           break;
14475       }
14476       break;
14477     }
14478     case GST_MAKE_FOURCC ('y', 'v', '1', '2'):
14479       format = GST_VIDEO_FORMAT_I420;
14480       break;
14481     case GST_MAKE_FOURCC ('y', 'u', 'v', '2'):
14482     case GST_MAKE_FOURCC ('Y', 'u', 'v', '2'):
14483       format = GST_VIDEO_FORMAT_I420;
14484       break;
14485     case FOURCC_2vuy:
14486     case GST_MAKE_FOURCC ('2', 'V', 'u', 'y'):
14487       format = GST_VIDEO_FORMAT_UYVY;
14488       break;
14489     case GST_MAKE_FOURCC ('v', '3', '0', '8'):
14490       format = GST_VIDEO_FORMAT_v308;
14491       break;
14492     case GST_MAKE_FOURCC ('v', '2', '1', '6'):
14493       format = GST_VIDEO_FORMAT_v216;
14494       break;
14495     case FOURCC_v210:
14496       format = GST_VIDEO_FORMAT_v210;
14497       break;
14498     case GST_MAKE_FOURCC ('r', '2', '1', '0'):
14499       format = GST_VIDEO_FORMAT_r210;
14500       break;
14501       /* Packed YUV 4:4:4 10 bit in 32 bits, complex
14502          case GST_MAKE_FOURCC ('v', '4', '1', '0'):
14503          format = GST_VIDEO_FORMAT_v410;
14504          break;
14505        */
14506       /* Packed YUV 4:4:4:4 8 bit in 32 bits
14507        * but different order than AYUV
14508        case GST_MAKE_FOURCC ('v', '4', '0', '8'):
14509        format = GST_VIDEO_FORMAT_v408;
14510        break;
14511        */
14512     case GST_MAKE_FOURCC ('m', 'p', 'e', 'g'):
14513     case GST_MAKE_FOURCC ('m', 'p', 'g', '1'):
14514       _codec ("MPEG-1 video");
14515       caps = gst_caps_new_simple ("video/mpeg", "mpegversion", G_TYPE_INT, 1,
14516           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
14517       break;
14518     case GST_MAKE_FOURCC ('h', 'd', 'v', '1'): /* HDV 720p30 */
14519     case GST_MAKE_FOURCC ('h', 'd', 'v', '2'): /* HDV 1080i60 */
14520     case GST_MAKE_FOURCC ('h', 'd', 'v', '3'): /* HDV 1080i50 */
14521     case GST_MAKE_FOURCC ('h', 'd', 'v', '4'): /* HDV 720p24 */
14522     case GST_MAKE_FOURCC ('h', 'd', 'v', '5'): /* HDV 720p25 */
14523     case GST_MAKE_FOURCC ('h', 'd', 'v', '6'): /* HDV 1080p24 */
14524     case GST_MAKE_FOURCC ('h', 'd', 'v', '7'): /* HDV 1080p25 */
14525     case GST_MAKE_FOURCC ('h', 'd', 'v', '8'): /* HDV 1080p30 */
14526     case GST_MAKE_FOURCC ('h', 'd', 'v', '9'): /* HDV 720p60 */
14527     case GST_MAKE_FOURCC ('h', 'd', 'v', 'a'): /* HDV 720p50 */
14528     case GST_MAKE_FOURCC ('m', 'x', '5', 'n'): /* MPEG2 IMX NTSC 525/60 50mb/s produced by FCP */
14529     case GST_MAKE_FOURCC ('m', 'x', '5', 'p'): /* MPEG2 IMX PAL 625/60 50mb/s produced by FCP */
14530     case GST_MAKE_FOURCC ('m', 'x', '4', 'n'): /* MPEG2 IMX NTSC 525/60 40mb/s produced by FCP */
14531     case GST_MAKE_FOURCC ('m', 'x', '4', 'p'): /* MPEG2 IMX PAL 625/60 40mb/s produced by FCP */
14532     case GST_MAKE_FOURCC ('m', 'x', '3', 'n'): /* MPEG2 IMX NTSC 525/60 30mb/s produced by FCP */
14533     case GST_MAKE_FOURCC ('m', 'x', '3', 'p'): /* MPEG2 IMX PAL 625/50 30mb/s produced by FCP */
14534     case GST_MAKE_FOURCC ('x', 'd', 'v', '1'): /* XDCAM HD 720p30 35Mb/s */
14535     case GST_MAKE_FOURCC ('x', 'd', 'v', '2'): /* XDCAM HD 1080i60 35Mb/s */
14536     case GST_MAKE_FOURCC ('x', 'd', 'v', '3'): /* XDCAM HD 1080i50 35Mb/s */
14537     case GST_MAKE_FOURCC ('x', 'd', 'v', '4'): /* XDCAM HD 720p24 35Mb/s */
14538     case GST_MAKE_FOURCC ('x', 'd', 'v', '5'): /* XDCAM HD 720p25 35Mb/s */
14539     case GST_MAKE_FOURCC ('x', 'd', 'v', '6'): /* XDCAM HD 1080p24 35Mb/s */
14540     case GST_MAKE_FOURCC ('x', 'd', 'v', '7'): /* XDCAM HD 1080p25 35Mb/s */
14541     case GST_MAKE_FOURCC ('x', 'd', 'v', '8'): /* XDCAM HD 1080p30 35Mb/s */
14542     case GST_MAKE_FOURCC ('x', 'd', 'v', '9'): /* XDCAM HD 720p60 35Mb/s */
14543     case GST_MAKE_FOURCC ('x', 'd', 'v', 'a'): /* XDCAM HD 720p50 35Mb/s */
14544     case GST_MAKE_FOURCC ('x', 'd', 'v', 'b'): /* XDCAM EX 1080i60 50Mb/s CBR */
14545     case GST_MAKE_FOURCC ('x', 'd', 'v', 'c'): /* XDCAM EX 1080i50 50Mb/s CBR */
14546     case GST_MAKE_FOURCC ('x', 'd', 'v', 'd'): /* XDCAM HD 1080p24 50Mb/s CBR */
14547     case GST_MAKE_FOURCC ('x', 'd', 'v', 'e'): /* XDCAM HD 1080p25 50Mb/s CBR */
14548     case GST_MAKE_FOURCC ('x', 'd', 'v', 'f'): /* XDCAM HD 1080p30 50Mb/s CBR */
14549     case GST_MAKE_FOURCC ('x', 'd', '5', '1'): /* XDCAM HD422 720p30 50Mb/s CBR */
14550     case GST_MAKE_FOURCC ('x', 'd', '5', '4'): /* XDCAM HD422 720p24 50Mb/s CBR */
14551     case GST_MAKE_FOURCC ('x', 'd', '5', '5'): /* XDCAM HD422 720p25 50Mb/s CBR */
14552     case GST_MAKE_FOURCC ('x', 'd', '5', '9'): /* XDCAM HD422 720p60 50Mb/s CBR */
14553     case GST_MAKE_FOURCC ('x', 'd', '5', 'a'): /* XDCAM HD422 720p50 50Mb/s CBR */
14554     case GST_MAKE_FOURCC ('x', 'd', '5', 'b'): /* XDCAM HD422 1080i50 50Mb/s CBR */
14555     case GST_MAKE_FOURCC ('x', 'd', '5', 'c'): /* XDCAM HD422 1080i50 50Mb/s CBR */
14556     case GST_MAKE_FOURCC ('x', 'd', '5', 'd'): /* XDCAM HD422 1080p24 50Mb/s CBR */
14557     case GST_MAKE_FOURCC ('x', 'd', '5', 'e'): /* XDCAM HD422 1080p25 50Mb/s CBR */
14558     case GST_MAKE_FOURCC ('x', 'd', '5', 'f'): /* XDCAM HD422 1080p30 50Mb/s CBR */
14559     case GST_MAKE_FOURCC ('x', 'd', 'h', 'd'): /* XDCAM HD 540p */
14560     case GST_MAKE_FOURCC ('x', 'd', 'h', '2'): /* XDCAM HD422 540p */
14561     case GST_MAKE_FOURCC ('A', 'V', 'm', 'p'): /* AVID IMX PAL */
14562     case GST_MAKE_FOURCC ('m', 'p', 'g', '2'): /* AVID IMX PAL */
14563     case GST_MAKE_FOURCC ('m', 'p', '2', 'v'): /* AVID IMX PAL */
14564     case GST_MAKE_FOURCC ('m', '2', 'v', '1'):
14565       _codec ("MPEG-2 video");
14566       caps = gst_caps_new_simple ("video/mpeg", "mpegversion", G_TYPE_INT, 2,
14567           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
14568       break;
14569     case GST_MAKE_FOURCC ('g', 'i', 'f', ' '):
14570       _codec ("GIF still images");
14571       caps = gst_caps_new_empty_simple ("image/gif");
14572       break;
14573     case FOURCC_h263:
14574     case GST_MAKE_FOURCC ('H', '2', '6', '3'):
14575     case FOURCC_s263:
14576     case GST_MAKE_FOURCC ('U', '2', '6', '3'):
14577       _codec ("H.263");
14578       /* ffmpeg uses the height/width props, don't know why */
14579       caps = gst_caps_new_simple ("video/x-h263",
14580           "variant", G_TYPE_STRING, "itu", NULL);
14581       break;
14582     case FOURCC_mp4v:
14583     case FOURCC_MP4V:
14584       _codec ("MPEG-4 video");
14585       caps = gst_caps_new_simple ("video/mpeg", "mpegversion", G_TYPE_INT, 4,
14586           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
14587       break;
14588     case GST_MAKE_FOURCC ('3', 'i', 'v', 'd'):
14589     case GST_MAKE_FOURCC ('3', 'I', 'V', 'D'):
14590       _codec ("Microsoft MPEG-4 4.3");  /* FIXME? */
14591       caps = gst_caps_new_simple ("video/x-msmpeg",
14592           "msmpegversion", G_TYPE_INT, 43, NULL);
14593       break;
14594     case GST_MAKE_FOURCC ('D', 'I', 'V', '3'):
14595       _codec ("DivX 3");
14596       caps = gst_caps_new_simple ("video/x-divx",
14597           "divxversion", G_TYPE_INT, 3, NULL);
14598       break;
14599     case GST_MAKE_FOURCC ('D', 'I', 'V', 'X'):
14600     case GST_MAKE_FOURCC ('d', 'i', 'v', 'x'):
14601       _codec ("DivX 4");
14602       caps = gst_caps_new_simple ("video/x-divx",
14603           "divxversion", G_TYPE_INT, 4, NULL);
14604       break;
14605     case GST_MAKE_FOURCC ('D', 'X', '5', '0'):
14606       _codec ("DivX 5");
14607       caps = gst_caps_new_simple ("video/x-divx",
14608           "divxversion", G_TYPE_INT, 5, NULL);
14609       break;
14610
14611     case GST_MAKE_FOURCC ('F', 'F', 'V', '1'):
14612       _codec ("FFV1");
14613       caps = gst_caps_new_simple ("video/x-ffv",
14614           "ffvversion", G_TYPE_INT, 1, NULL);
14615       break;
14616
14617     case GST_MAKE_FOURCC ('3', 'I', 'V', '1'):
14618     case GST_MAKE_FOURCC ('3', 'I', 'V', '2'):
14619     case FOURCC_XVID:
14620     case FOURCC_xvid:
14621     case FOURCC_FMP4:
14622     case FOURCC_fmp4:
14623     case GST_MAKE_FOURCC ('U', 'M', 'P', '4'):
14624       caps = gst_caps_new_simple ("video/mpeg", "mpegversion", G_TYPE_INT, 4,
14625           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
14626       _codec ("MPEG-4");
14627       break;
14628
14629     case GST_MAKE_FOURCC ('c', 'v', 'i', 'd'):
14630       _codec ("Cinepak");
14631       caps = gst_caps_new_empty_simple ("video/x-cinepak");
14632       break;
14633     case GST_MAKE_FOURCC ('q', 'd', 'r', 'w'):
14634       _codec ("Apple QuickDraw");
14635       caps = gst_caps_new_empty_simple ("video/x-qdrw");
14636       break;
14637     case GST_MAKE_FOURCC ('r', 'p', 'z', 'a'):
14638       _codec ("Apple video");
14639       caps = gst_caps_new_empty_simple ("video/x-apple-video");
14640       break;
14641     case FOURCC_H264:
14642     case FOURCC_avc1:
14643       _codec ("H.264 / AVC");
14644       caps = gst_caps_new_simple ("video/x-h264",
14645           "stream-format", G_TYPE_STRING, "avc",
14646           "alignment", G_TYPE_STRING, "au", NULL);
14647       break;
14648     case FOURCC_avc3:
14649       _codec ("H.264 / AVC");
14650       caps = gst_caps_new_simple ("video/x-h264",
14651           "stream-format", G_TYPE_STRING, "avc3",
14652           "alignment", G_TYPE_STRING, "au", NULL);
14653       break;
14654     case FOURCC_H265:
14655     case FOURCC_hvc1:
14656       _codec ("H.265 / HEVC");
14657       caps = gst_caps_new_simple ("video/x-h265",
14658           "stream-format", G_TYPE_STRING, "hvc1",
14659           "alignment", G_TYPE_STRING, "au", NULL);
14660       break;
14661     case FOURCC_hev1:
14662       _codec ("H.265 / HEVC");
14663       caps = gst_caps_new_simple ("video/x-h265",
14664           "stream-format", G_TYPE_STRING, "hev1",
14665           "alignment", G_TYPE_STRING, "au", NULL);
14666       break;
14667     case FOURCC_rle_:
14668       _codec ("Run-length encoding");
14669       caps = gst_caps_new_simple ("video/x-rle",
14670           "layout", G_TYPE_STRING, "quicktime", NULL);
14671       break;
14672     case FOURCC_WRLE:
14673       _codec ("Run-length encoding");
14674       caps = gst_caps_new_simple ("video/x-rle",
14675           "layout", G_TYPE_STRING, "microsoft", NULL);
14676       break;
14677     case GST_MAKE_FOURCC ('I', 'V', '3', '2'):
14678     case GST_MAKE_FOURCC ('i', 'v', '3', '2'):
14679       _codec ("Indeo Video 3");
14680       caps = gst_caps_new_simple ("video/x-indeo",
14681           "indeoversion", G_TYPE_INT, 3, NULL);
14682       break;
14683     case GST_MAKE_FOURCC ('I', 'V', '4', '1'):
14684     case GST_MAKE_FOURCC ('i', 'v', '4', '1'):
14685       _codec ("Intel Video 4");
14686       caps = gst_caps_new_simple ("video/x-indeo",
14687           "indeoversion", G_TYPE_INT, 4, NULL);
14688       break;
14689     case FOURCC_dvcp:
14690     case FOURCC_dvc_:
14691     case GST_MAKE_FOURCC ('d', 'v', 's', 'd'):
14692     case GST_MAKE_FOURCC ('D', 'V', 'S', 'D'):
14693     case GST_MAKE_FOURCC ('d', 'v', 'c', 's'):
14694     case GST_MAKE_FOURCC ('D', 'V', 'C', 'S'):
14695     case GST_MAKE_FOURCC ('d', 'v', '2', '5'):
14696     case GST_MAKE_FOURCC ('d', 'v', 'p', 'p'):
14697       _codec ("DV Video");
14698       caps = gst_caps_new_simple ("video/x-dv", "dvversion", G_TYPE_INT, 25,
14699           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
14700       break;
14701     case FOURCC_dv5n:          /* DVCPRO50 NTSC */
14702     case FOURCC_dv5p:          /* DVCPRO50 PAL */
14703       _codec ("DVCPro50 Video");
14704       caps = gst_caps_new_simple ("video/x-dv", "dvversion", G_TYPE_INT, 50,
14705           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
14706       break;
14707     case GST_MAKE_FOURCC ('d', 'v', 'h', '5'): /* DVCPRO HD 50i produced by FCP */
14708     case GST_MAKE_FOURCC ('d', 'v', 'h', '6'): /* DVCPRO HD 60i produced by FCP */
14709       _codec ("DVCProHD Video");
14710       caps = gst_caps_new_simple ("video/x-dv", "dvversion", G_TYPE_INT, 100,
14711           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
14712       break;
14713     case GST_MAKE_FOURCC ('s', 'm', 'c', ' '):
14714       _codec ("Apple Graphics (SMC)");
14715       caps = gst_caps_new_empty_simple ("video/x-smc");
14716       break;
14717     case GST_MAKE_FOURCC ('V', 'P', '3', '1'):
14718       _codec ("VP3");
14719       caps = gst_caps_new_empty_simple ("video/x-vp3");
14720       break;
14721     case GST_MAKE_FOURCC ('V', 'P', '6', 'F'):
14722       _codec ("VP6 Flash");
14723       caps = gst_caps_new_empty_simple ("video/x-vp6-flash");
14724       break;
14725     case FOURCC_XiTh:
14726       _codec ("Theora");
14727       caps = gst_caps_new_empty_simple ("video/x-theora");
14728       /* theora uses one byte of padding in the data stream because it does not
14729        * allow 0 sized packets while theora does */
14730       entry->padding = 1;
14731       break;
14732     case FOURCC_drac:
14733       _codec ("Dirac");
14734       caps = gst_caps_new_empty_simple ("video/x-dirac");
14735       break;
14736     case GST_MAKE_FOURCC ('t', 'i', 'f', 'f'):
14737       _codec ("TIFF still images");
14738       caps = gst_caps_new_empty_simple ("image/tiff");
14739       break;
14740     case GST_MAKE_FOURCC ('i', 'c', 'o', 'd'):
14741       _codec ("Apple Intermediate Codec");
14742       caps = gst_caps_from_string ("video/x-apple-intermediate-codec");
14743       break;
14744     case GST_MAKE_FOURCC ('A', 'V', 'd', 'n'):
14745       _codec ("AVID DNxHD");
14746       caps = gst_caps_from_string ("video/x-dnxhd");
14747       break;
14748     case FOURCC_VP80:
14749     case FOURCC_vp08:
14750       _codec ("On2 VP8");
14751       caps = gst_caps_from_string ("video/x-vp8");
14752       break;
14753     case FOURCC_vp09:
14754       _codec ("Google VP9");
14755       caps = gst_caps_from_string ("video/x-vp9");
14756       break;
14757     case FOURCC_apcs:
14758       _codec ("Apple ProRes LT");
14759       caps =
14760           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING, "lt",
14761           NULL);
14762       break;
14763     case FOURCC_apch:
14764       _codec ("Apple ProRes HQ");
14765       caps =
14766           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING, "hq",
14767           NULL);
14768       break;
14769     case FOURCC_apcn:
14770       _codec ("Apple ProRes");
14771       caps =
14772           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING,
14773           "standard", NULL);
14774       break;
14775     case FOURCC_apco:
14776       _codec ("Apple ProRes Proxy");
14777       caps =
14778           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING,
14779           "proxy", NULL);
14780       break;
14781     case FOURCC_ap4h:
14782       _codec ("Apple ProRes 4444");
14783       caps =
14784           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING,
14785           "4444", NULL);
14786       break;
14787     case FOURCC_ap4x:
14788       _codec ("Apple ProRes 4444 XQ");
14789       caps =
14790           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING,
14791           "4444xq", NULL);
14792       break;
14793     case FOURCC_cfhd:
14794       _codec ("GoPro CineForm");
14795       caps = gst_caps_from_string ("video/x-cineform");
14796       break;
14797     case FOURCC_vc_1:
14798     case FOURCC_ovc1:
14799       _codec ("VC-1");
14800       caps = gst_caps_new_simple ("video/x-wmv",
14801           "wmvversion", G_TYPE_INT, 3, "format", G_TYPE_STRING, "WVC1", NULL);
14802       break;
14803     case FOURCC_av01:
14804       _codec ("AV1");
14805       caps = gst_caps_new_empty_simple ("video/x-av1");
14806       break;
14807     case GST_MAKE_FOURCC ('k', 'p', 'c', 'd'):
14808     default:
14809     {
14810       caps = _get_unknown_codec_name ("video", fourcc);
14811       break;
14812     }
14813   }
14814
14815   if (format != GST_VIDEO_FORMAT_UNKNOWN) {
14816     GstVideoInfo info;
14817
14818     gst_video_info_init (&info);
14819     gst_video_info_set_format (&info, format, entry->width, entry->height);
14820
14821     caps = gst_video_info_to_caps (&info);
14822     *codec_name = gst_pb_utils_get_codec_description (caps);
14823
14824     /* enable clipping for raw video streams */
14825     stream->need_clip = TRUE;
14826     stream->alignment = 32;
14827   }
14828
14829   return caps;
14830 }
14831
14832 static guint
14833 round_up_pow2 (guint n)
14834 {
14835   n = n - 1;
14836   n = n | (n >> 1);
14837   n = n | (n >> 2);
14838   n = n | (n >> 4);
14839   n = n | (n >> 8);
14840   n = n | (n >> 16);
14841   return n + 1;
14842 }
14843
14844 static GstCaps *
14845 qtdemux_audio_caps (GstQTDemux * qtdemux, QtDemuxStream * stream,
14846     QtDemuxStreamStsdEntry * entry, guint32 fourcc, const guint8 * data,
14847     int len, gchar ** codec_name)
14848 {
14849   GstCaps *caps;
14850   const GstStructure *s;
14851   const gchar *name;
14852   gint endian = 0;
14853   GstAudioFormat format = 0;
14854   gint depth;
14855
14856   GST_DEBUG_OBJECT (qtdemux, "resolve fourcc 0x%08x", GUINT32_TO_BE (fourcc));
14857
14858   depth = entry->bytes_per_packet * 8;
14859
14860   switch (fourcc) {
14861     case GST_MAKE_FOURCC ('N', 'O', 'N', 'E'):
14862     case FOURCC_raw_:
14863       /* 8-bit audio is unsigned */
14864       if (depth == 8)
14865         format = GST_AUDIO_FORMAT_U8;
14866       /* otherwise it's signed and big-endian just like 'twos' */
14867     case FOURCC_twos:
14868       endian = G_BIG_ENDIAN;
14869       /* fall-through */
14870     case FOURCC_sowt:
14871     {
14872       gchar *str;
14873
14874       if (!endian)
14875         endian = G_LITTLE_ENDIAN;
14876
14877       if (!format)
14878         format = gst_audio_format_build_integer (TRUE, endian, depth, depth);
14879
14880       str = g_strdup_printf ("Raw %d-bit PCM audio", depth);
14881       _codec (str);
14882       g_free (str);
14883
14884       caps = gst_caps_new_simple ("audio/x-raw",
14885           "format", G_TYPE_STRING, gst_audio_format_to_string (format),
14886           "layout", G_TYPE_STRING, "interleaved", NULL);
14887       stream->alignment = GST_ROUND_UP_8 (depth);
14888       stream->alignment = round_up_pow2 (stream->alignment);
14889       break;
14890     }
14891     case GST_MAKE_FOURCC ('f', 'l', '6', '4'):
14892       _codec ("Raw 64-bit floating-point audio");
14893       caps = gst_caps_new_simple ("audio/x-raw",
14894           "format", G_TYPE_STRING, "F64BE",
14895           "layout", G_TYPE_STRING, "interleaved", NULL);
14896       stream->alignment = 8;
14897       break;
14898     case GST_MAKE_FOURCC ('f', 'l', '3', '2'):
14899       _codec ("Raw 32-bit floating-point audio");
14900       caps = gst_caps_new_simple ("audio/x-raw",
14901           "format", G_TYPE_STRING, "F32BE",
14902           "layout", G_TYPE_STRING, "interleaved", NULL);
14903       stream->alignment = 4;
14904       break;
14905     case FOURCC_in24:
14906       _codec ("Raw 24-bit PCM audio");
14907       /* we assume BIG ENDIAN, an enda box will tell us to change this to little
14908        * endian later */
14909       caps = gst_caps_new_simple ("audio/x-raw",
14910           "format", G_TYPE_STRING, "S24BE",
14911           "layout", G_TYPE_STRING, "interleaved", NULL);
14912       stream->alignment = 4;
14913       break;
14914     case GST_MAKE_FOURCC ('i', 'n', '3', '2'):
14915       _codec ("Raw 32-bit PCM audio");
14916       caps = gst_caps_new_simple ("audio/x-raw",
14917           "format", G_TYPE_STRING, "S32BE",
14918           "layout", G_TYPE_STRING, "interleaved", NULL);
14919       stream->alignment = 4;
14920       break;
14921     case GST_MAKE_FOURCC ('s', '1', '6', 'l'):
14922       _codec ("Raw 16-bit PCM audio");
14923       caps = gst_caps_new_simple ("audio/x-raw",
14924           "format", G_TYPE_STRING, "S16LE",
14925           "layout", G_TYPE_STRING, "interleaved", NULL);
14926       stream->alignment = 2;
14927       break;
14928     case FOURCC_ulaw:
14929       _codec ("Mu-law audio");
14930       caps = gst_caps_new_empty_simple ("audio/x-mulaw");
14931       break;
14932     case FOURCC_alaw:
14933       _codec ("A-law audio");
14934       caps = gst_caps_new_empty_simple ("audio/x-alaw");
14935       break;
14936     case 0x0200736d:
14937     case 0x6d730002:
14938       _codec ("Microsoft ADPCM");
14939       /* Microsoft ADPCM-ACM code 2 */
14940       caps = gst_caps_new_simple ("audio/x-adpcm",
14941           "layout", G_TYPE_STRING, "microsoft", NULL);
14942       break;
14943     case 0x1100736d:
14944     case 0x6d730011:
14945       _codec ("DVI/IMA ADPCM");
14946       caps = gst_caps_new_simple ("audio/x-adpcm",
14947           "layout", G_TYPE_STRING, "dvi", NULL);
14948       break;
14949     case 0x1700736d:
14950     case 0x6d730017:
14951       _codec ("DVI/Intel IMA ADPCM");
14952       /* FIXME DVI/Intel IMA ADPCM/ACM code 17 */
14953       caps = gst_caps_new_simple ("audio/x-adpcm",
14954           "layout", G_TYPE_STRING, "quicktime", NULL);
14955       break;
14956     case 0x5500736d:
14957     case 0x6d730055:
14958       /* MPEG layer 3, CBR only (pre QT4.1) */
14959     case FOURCC__mp3:
14960       _codec ("MPEG-1 layer 3");
14961       /* MPEG layer 3, CBR & VBR (QT4.1 and later) */
14962       caps = gst_caps_new_simple ("audio/mpeg", "layer", G_TYPE_INT, 3,
14963           "mpegversion", G_TYPE_INT, 1, NULL);
14964       break;
14965     case GST_MAKE_FOURCC ('.', 'm', 'p', '2'):
14966       _codec ("MPEG-1 layer 2");
14967       /* MPEG layer 2 */
14968       caps = gst_caps_new_simple ("audio/mpeg", "layer", G_TYPE_INT, 2,
14969           "mpegversion", G_TYPE_INT, 1, NULL);
14970       break;
14971     case 0x20736d:
14972     case GST_MAKE_FOURCC ('e', 'c', '-', '3'):
14973       _codec ("EAC-3 audio");
14974       caps = gst_caps_new_simple ("audio/x-eac3",
14975           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
14976       entry->sampled = TRUE;
14977       break;
14978     case GST_MAKE_FOURCC ('s', 'a', 'c', '3'): // Nero Recode
14979     case FOURCC_ac_3:
14980       _codec ("AC-3 audio");
14981       caps = gst_caps_new_simple ("audio/x-ac3",
14982           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
14983       entry->sampled = TRUE;
14984       break;
14985     case GST_MAKE_FOURCC ('d', 't', 's', 'c'):
14986     case GST_MAKE_FOURCC ('D', 'T', 'S', ' '):
14987       _codec ("DTS audio");
14988       caps = gst_caps_new_simple ("audio/x-dts",
14989           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
14990       entry->sampled = TRUE;
14991       break;
14992     case GST_MAKE_FOURCC ('d', 't', 's', 'h'): // DTS-HD
14993     case GST_MAKE_FOURCC ('d', 't', 's', 'l'): // DTS-HD Lossless
14994       _codec ("DTS-HD audio");
14995       caps = gst_caps_new_simple ("audio/x-dts",
14996           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
14997       entry->sampled = TRUE;
14998       break;
14999     case FOURCC_MAC3:
15000       _codec ("MACE-3");
15001       caps = gst_caps_new_simple ("audio/x-mace",
15002           "maceversion", G_TYPE_INT, 3, NULL);
15003       break;
15004     case FOURCC_MAC6:
15005       _codec ("MACE-6");
15006       caps = gst_caps_new_simple ("audio/x-mace",
15007           "maceversion", G_TYPE_INT, 6, NULL);
15008       break;
15009     case GST_MAKE_FOURCC ('O', 'g', 'g', 'V'):
15010       /* ogg/vorbis */
15011       caps = gst_caps_new_empty_simple ("application/ogg");
15012       break;
15013     case GST_MAKE_FOURCC ('d', 'v', 'c', 'a'):
15014       _codec ("DV audio");
15015       caps = gst_caps_new_empty_simple ("audio/x-dv");
15016       break;
15017     case FOURCC_mp4a:
15018       _codec ("MPEG-4 AAC audio");
15019       caps = gst_caps_new_simple ("audio/mpeg",
15020           "mpegversion", G_TYPE_INT, 4, "framed", G_TYPE_BOOLEAN, TRUE,
15021           "stream-format", G_TYPE_STRING, "raw", NULL);
15022       break;
15023     case GST_MAKE_FOURCC ('Q', 'D', 'M', 'C'):
15024       _codec ("QDesign Music");
15025       caps = gst_caps_new_empty_simple ("audio/x-qdm");
15026       break;
15027     case FOURCC_QDM2:
15028       _codec ("QDesign Music v.2");
15029       /* FIXME: QDesign music version 2 (no constant) */
15030       if (FALSE && data) {
15031         caps = gst_caps_new_simple ("audio/x-qdm2",
15032             "framesize", G_TYPE_INT, QT_UINT32 (data + 52),
15033             "bitrate", G_TYPE_INT, QT_UINT32 (data + 40),
15034             "blocksize", G_TYPE_INT, QT_UINT32 (data + 44), NULL);
15035       } else {
15036         caps = gst_caps_new_empty_simple ("audio/x-qdm2");
15037       }
15038       break;
15039     case FOURCC_agsm:
15040       _codec ("GSM audio");
15041       caps = gst_caps_new_empty_simple ("audio/x-gsm");
15042       break;
15043     case FOURCC_samr:
15044       _codec ("AMR audio");
15045       caps = gst_caps_new_empty_simple ("audio/AMR");
15046       break;
15047     case FOURCC_sawb:
15048       _codec ("AMR-WB audio");
15049       caps = gst_caps_new_empty_simple ("audio/AMR-WB");
15050       break;
15051     case FOURCC_ima4:
15052       _codec ("Quicktime IMA ADPCM");
15053       caps = gst_caps_new_simple ("audio/x-adpcm",
15054           "layout", G_TYPE_STRING, "quicktime", NULL);
15055       break;
15056     case FOURCC_alac:
15057       _codec ("Apple lossless audio");
15058       caps = gst_caps_new_empty_simple ("audio/x-alac");
15059       break;
15060     case FOURCC_fLaC:
15061       _codec ("Free Lossless Audio Codec");
15062       caps = gst_caps_new_simple ("audio/x-flac",
15063           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
15064       break;
15065     case GST_MAKE_FOURCC ('Q', 'c', 'l', 'p'):
15066       _codec ("QualComm PureVoice");
15067       caps = gst_caps_from_string ("audio/qcelp");
15068       break;
15069     case FOURCC_wma_:
15070     case FOURCC_owma:
15071       _codec ("WMA");
15072       caps = gst_caps_new_empty_simple ("audio/x-wma");
15073       break;
15074     case FOURCC_opus:
15075       _codec ("Opus");
15076       caps = gst_caps_new_empty_simple ("audio/x-opus");
15077       break;
15078     case FOURCC_lpcm:
15079     {
15080       guint32 flags = 0;
15081       guint32 depth = 0;
15082       guint32 width = 0;
15083       GstAudioFormat format;
15084       enum
15085       {
15086         FLAG_IS_FLOAT = 0x1,
15087         FLAG_IS_BIG_ENDIAN = 0x2,
15088         FLAG_IS_SIGNED = 0x4,
15089         FLAG_IS_PACKED = 0x8,
15090         FLAG_IS_ALIGNED_HIGH = 0x10,
15091         FLAG_IS_NON_INTERLEAVED = 0x20
15092       };
15093       _codec ("Raw LPCM audio");
15094
15095       if (data && len >= 36) {
15096         depth = QT_UINT32 (data + 24);
15097         flags = QT_UINT32 (data + 28);
15098         width = QT_UINT32 (data + 32) * 8 / entry->n_channels;
15099       }
15100       if ((flags & FLAG_IS_FLOAT) == 0) {
15101         if (depth == 0)
15102           depth = 16;
15103         if (width == 0)
15104           width = 16;
15105         if ((flags & FLAG_IS_ALIGNED_HIGH))
15106           depth = width;
15107
15108         format = gst_audio_format_build_integer ((flags & FLAG_IS_SIGNED) ?
15109             TRUE : FALSE, (flags & FLAG_IS_BIG_ENDIAN) ?
15110             G_BIG_ENDIAN : G_LITTLE_ENDIAN, width, depth);
15111         caps = gst_caps_new_simple ("audio/x-raw",
15112             "format", G_TYPE_STRING,
15113             format !=
15114             GST_AUDIO_FORMAT_UNKNOWN ? gst_audio_format_to_string (format) :
15115             "UNKNOWN", "layout", G_TYPE_STRING,
15116             (flags & FLAG_IS_NON_INTERLEAVED) ? "non-interleaved" :
15117             "interleaved", NULL);
15118         stream->alignment = GST_ROUND_UP_8 (depth);
15119         stream->alignment = round_up_pow2 (stream->alignment);
15120       } else {
15121         if (width == 0)
15122           width = 32;
15123         if (width == 64) {
15124           if (flags & FLAG_IS_BIG_ENDIAN)
15125             format = GST_AUDIO_FORMAT_F64BE;
15126           else
15127             format = GST_AUDIO_FORMAT_F64LE;
15128         } else {
15129           if (flags & FLAG_IS_BIG_ENDIAN)
15130             format = GST_AUDIO_FORMAT_F32BE;
15131           else
15132             format = GST_AUDIO_FORMAT_F32LE;
15133         }
15134         caps = gst_caps_new_simple ("audio/x-raw",
15135             "format", G_TYPE_STRING, gst_audio_format_to_string (format),
15136             "layout", G_TYPE_STRING, (flags & FLAG_IS_NON_INTERLEAVED) ?
15137             "non-interleaved" : "interleaved", NULL);
15138         stream->alignment = width / 8;
15139       }
15140       break;
15141     }
15142     case GST_MAKE_FOURCC ('q', 't', 'v', 'r'):
15143       /* ? */
15144     default:
15145     {
15146       caps = _get_unknown_codec_name ("audio", fourcc);
15147       break;
15148     }
15149   }
15150
15151   if (caps) {
15152     GstCaps *templ_caps =
15153         gst_static_pad_template_get_caps (&gst_qtdemux_audiosrc_template);
15154     GstCaps *intersection = gst_caps_intersect (caps, templ_caps);
15155     gst_caps_unref (caps);
15156     gst_caps_unref (templ_caps);
15157     caps = intersection;
15158   }
15159
15160   /* enable clipping for raw audio streams */
15161   s = gst_caps_get_structure (caps, 0);
15162   name = gst_structure_get_name (s);
15163   if (g_str_has_prefix (name, "audio/x-raw")) {
15164     stream->need_clip = TRUE;
15165     stream->max_buffer_size = 4096 * entry->bytes_per_frame;
15166     GST_DEBUG ("setting max buffer size to %d", stream->max_buffer_size);
15167   }
15168   return caps;
15169 }
15170
15171 static GstCaps *
15172 qtdemux_sub_caps (GstQTDemux * qtdemux, QtDemuxStream * stream,
15173     QtDemuxStreamStsdEntry * entry, guint32 fourcc,
15174     const guint8 * stsd_entry_data, gchar ** codec_name)
15175 {
15176   GstCaps *caps;
15177
15178   GST_DEBUG_OBJECT (qtdemux, "resolve fourcc 0x%08x", GUINT32_TO_BE (fourcc));
15179
15180   switch (fourcc) {
15181     case FOURCC_mp4s:
15182       _codec ("DVD subtitle");
15183       caps = gst_caps_new_empty_simple ("subpicture/x-dvd");
15184       stream->need_process = TRUE;
15185       break;
15186     case FOURCC_text:
15187       _codec ("Quicktime timed text");
15188       goto text;
15189     case FOURCC_tx3g:
15190       _codec ("3GPP timed text");
15191     text:
15192       caps = gst_caps_new_simple ("text/x-raw", "format", G_TYPE_STRING,
15193           "utf8", NULL);
15194       /* actual text piece needs to be extracted */
15195       stream->need_process = TRUE;
15196       break;
15197     case FOURCC_stpp:
15198       _codec ("XML subtitles");
15199       caps = gst_caps_new_empty_simple ("application/ttml+xml");
15200       break;
15201     case FOURCC_c608:
15202       _codec ("CEA 608 Closed Caption");
15203       caps =
15204           gst_caps_new_simple ("closedcaption/x-cea-608", "format",
15205           G_TYPE_STRING, "cc_data", NULL);
15206       stream->need_process = TRUE;
15207       break;
15208     case FOURCC_c708:
15209       _codec ("CEA 708 Closed Caption");
15210       caps =
15211           gst_caps_new_simple ("closedcaption/x-cea-708", "format",
15212           G_TYPE_STRING, "cdp", NULL);
15213       stream->need_process = TRUE;
15214       break;
15215
15216     default:
15217     {
15218       caps = _get_unknown_codec_name ("text", fourcc);
15219       break;
15220     }
15221   }
15222   return caps;
15223 }
15224
15225 static GstCaps *
15226 qtdemux_generic_caps (GstQTDemux * qtdemux, QtDemuxStream * stream,
15227     QtDemuxStreamStsdEntry * entry, guint32 fourcc,
15228     const guint8 * stsd_entry_data, gchar ** codec_name)
15229 {
15230   GstCaps *caps;
15231
15232   switch (fourcc) {
15233     case FOURCC_m1v:
15234       _codec ("MPEG 1 video");
15235       caps = gst_caps_new_simple ("video/mpeg", "mpegversion", G_TYPE_INT, 1,
15236           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
15237       break;
15238     default:
15239       caps = NULL;
15240       break;
15241   }
15242   return caps;
15243 }
15244
15245 static void
15246 gst_qtdemux_append_protection_system_id (GstQTDemux * qtdemux,
15247     const gchar * system_id)
15248 {
15249   gint i;
15250
15251   if (!qtdemux->protection_system_ids)
15252     qtdemux->protection_system_ids =
15253         g_ptr_array_new_with_free_func ((GDestroyNotify) g_free);
15254   /* Check whether we already have an entry for this system ID. */
15255   for (i = 0; i < qtdemux->protection_system_ids->len; ++i) {
15256     const gchar *id = g_ptr_array_index (qtdemux->protection_system_ids, i);
15257     if (g_ascii_strcasecmp (system_id, id) == 0) {
15258       return;
15259     }
15260   }
15261   GST_DEBUG_OBJECT (qtdemux, "Adding cenc protection system ID %s", system_id);
15262   g_ptr_array_add (qtdemux->protection_system_ids, g_ascii_strdown (system_id,
15263           -1));
15264 }