5679036e188e1848069da646f28e81b5039ec83c
[platform/upstream/gst-plugins-good.git] / gst / isomp4 / qtdemux.c
1 /* GStreamer
2  * Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu>
3  * Copyright (C) <2003> David A. Schleef <ds@schleef.org>
4  * Copyright (C) <2006> Wim Taymans <wim@fluendo.com>
5  * Copyright (C) <2007> Julien Moutte <julien@fluendo.com>
6  * Copyright (C) <2009> Tim-Philipp Müller <tim centricular net>
7  * Copyright (C) <2009> STEricsson <benjamin.gaignard@stericsson.com>
8  * Copyright (C) <2013> Sreerenj Balachandran <sreerenj.balachandran@intel.com>
9  * Copyright (C) <2013> Intel Corporation
10  * Copyright (C) <2014> Centricular Ltd
11  * Copyright (C) <2015> YouView TV Ltd.
12  * Copyright (C) <2016> British Broadcasting Corporation
13  *
14  * This library is free software; you can redistribute it and/or
15  * modify it under the terms of the GNU Library General Public
16  * License as published by the Free Software Foundation; either
17  * version 2 of the License, or (at your option) any later version.
18  *
19  * This library is distributed in the hope that it will be useful,
20  * but WITHOUT ANY WARRANTY; without even the implied warranty of
21  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
22  * Library General Public License for more details.
23  *
24  * You should have received a copy of the GNU Library General Public
25  * License along with this library; if not, write to the
26  * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
27  * Boston, MA 02110-1301, USA.
28  */
29
30 /**
31  * SECTION:element-qtdemux
32  *
33  * Demuxes a .mov file into raw or compressed audio and/or video streams.
34  *
35  * This element supports both push and pull-based scheduling, depending on the
36  * capabilities of the upstream elements.
37  *
38  * <refsect2>
39  * <title>Example launch line</title>
40  * |[
41  * gst-launch-1.0 filesrc location=test.mov ! qtdemux name=demux  demux.audio_0 ! queue ! decodebin ! audioconvert ! audioresample ! autoaudiosink   demux.video_0 ! queue ! decodebin ! videoconvert ! videoscale ! autovideosink
42  * ]| Play (parse and decode) a .mov file and try to output it to
43  * an automatically detected soundcard and videosink. If the MOV file contains
44  * compressed audio or video data, this will only work if you have the
45  * right decoder elements/plugins installed.
46  * </refsect2>
47  */
48
49 #ifdef HAVE_CONFIG_H
50 #include "config.h"
51 #endif
52
53 #include "gst/gst-i18n-plugin.h"
54
55 #include <glib/gprintf.h>
56 #include <gst/tag/tag.h>
57 #include <gst/audio/audio.h>
58 #include <gst/video/video.h>
59
60 #include "qtatomparser.h"
61 #include "qtdemux_types.h"
62 #include "qtdemux_dump.h"
63 #include "fourcc.h"
64 #include "descriptors.h"
65 #include "qtdemux_lang.h"
66 #include "qtdemux.h"
67 #include "qtpalette.h"
68
69 #include "gst/riff/riff-media.h"
70 #include "gst/riff/riff-read.h"
71
72 #include <gst/pbutils/pbutils.h>
73
74 #include <stdio.h>
75 #include <stdlib.h>
76 #include <string.h>
77
78 #include <math.h>
79 #include <gst/math-compat.h>
80
81 #ifdef HAVE_ZLIB
82 # include <zlib.h>
83 #endif
84
85 /* max. size considered 'sane' for non-mdat atoms */
86 #define QTDEMUX_MAX_ATOM_SIZE (25*1024*1024)
87
88 /* if the sample index is larger than this, something is likely wrong */
89 #define QTDEMUX_MAX_SAMPLE_INDEX_SIZE (50*1024*1024)
90
91 /* For converting qt creation times to unix epoch times */
92 #define QTDEMUX_SECONDS_PER_DAY (60 * 60 * 24)
93 #define QTDEMUX_LEAP_YEARS_FROM_1904_TO_1970 17
94 #define QTDEMUX_SECONDS_FROM_1904_TO_1970 (((1970 - 1904) * (guint64) 365 + \
95     QTDEMUX_LEAP_YEARS_FROM_1904_TO_1970) * QTDEMUX_SECONDS_PER_DAY)
96
97 #define QTDEMUX_TREE_NODE_FOURCC(n) (QT_FOURCC(((guint8 *) (n)->data) + 4))
98
99 #define STREAM_IS_EOS(s) (s->time_position == GST_CLOCK_TIME_NONE)
100
101 #define ABSDIFF(x, y) ( (x) > (y) ? ((x) - (y)) : ((y) - (x)) )
102
103 GST_DEBUG_CATEGORY (qtdemux_debug);
104
105 typedef struct _QtDemuxSegment QtDemuxSegment;
106 typedef struct _QtDemuxSample QtDemuxSample;
107
108 typedef struct _QtDemuxCencSampleSetInfo QtDemuxCencSampleSetInfo;
109
110 struct _QtDemuxSample
111 {
112   guint32 size;
113   gint32 pts_offset;            /* Add this value to timestamp to get the pts */
114   guint64 offset;
115   guint64 timestamp;            /* DTS In mov time */
116   guint32 duration;             /* In mov time */
117   gboolean keyframe;            /* TRUE when this packet is a keyframe */
118 };
119
120 /* Macros for converting to/from timescale */
121 #define QTSTREAMTIME_TO_GSTTIME(stream, value) (gst_util_uint64_scale((value), GST_SECOND, (stream)->timescale))
122 #define GSTTIME_TO_QTSTREAMTIME(stream, value) (gst_util_uint64_scale((value), (stream)->timescale, GST_SECOND))
123
124 #define QTTIME_TO_GSTTIME(qtdemux, value) (gst_util_uint64_scale((value), GST_SECOND, (qtdemux)->timescale))
125 #define GSTTIME_TO_QTTIME(qtdemux, value) (gst_util_uint64_scale((value), (qtdemux)->timescale, GST_SECOND))
126
127 /* timestamp is the DTS */
128 #define QTSAMPLE_DTS(stream,sample) (QTSTREAMTIME_TO_GSTTIME((stream), (sample)->timestamp))
129 /* timestamp + offset + cslg_shift is the outgoing PTS */
130 #define QTSAMPLE_PTS(stream,sample) (QTSTREAMTIME_TO_GSTTIME((stream), (sample)->timestamp + (stream)->cslg_shift + (sample)->pts_offset))
131 /* timestamp + offset is the PTS used for internal seek calcuations */
132 #define QTSAMPLE_PTS_NO_CSLG(stream,sample) (QTSTREAMTIME_TO_GSTTIME((stream), (sample)->timestamp + (sample)->pts_offset))
133 /* timestamp + duration - dts is the duration */
134 #define QTSAMPLE_DUR_DTS(stream, sample, dts) (QTSTREAMTIME_TO_GSTTIME ((stream), (sample)->timestamp + (sample)->duration) - (dts))
135
136 #define QTSAMPLE_KEYFRAME(stream,sample) ((stream)->all_keyframe || (sample)->keyframe)
137
138 /*
139  * Quicktime has tracks and segments. A track is a continuous piece of
140  * multimedia content. The track is not always played from start to finish but
141  * instead, pieces of the track are 'cut out' and played in sequence. This is
142  * what the segments do.
143  *
144  * Inside the track we have keyframes (K) and delta frames. The track has its
145  * own timing, which starts from 0 and extends to end. The position in the track
146  * is called the media_time.
147  *
148  * The segments now describe the pieces that should be played from this track
149  * and are basically tuples of media_time/duration/rate entries. We can have
150  * multiple segments and they are all played after one another. An example:
151  *
152  * segment 1: media_time: 1 second, duration: 1 second, rate 1
153  * segment 2: media_time: 3 second, duration: 2 second, rate 2
154  *
155  * To correctly play back this track, one must play: 1 second of media starting
156  * from media_time 1 followed by 2 seconds of media starting from media_time 3
157  * at a rate of 2.
158  *
159  * Each of the segments will be played at a specific time, the first segment at
160  * time 0, the second one after the duration of the first one, etc.. Note that
161  * the time in resulting playback is not identical to the media_time of the
162  * track anymore.
163  *
164  * Visually, assuming the track has 4 second of media_time:
165  *
166  *                (a)                   (b)          (c)              (d)
167  *         .-----------------------------------------------------------.
168  * track:  | K.....K.........K........K.......K.......K...........K... |
169  *         '-----------------------------------------------------------'
170  *         0              1              2              3              4
171  *           .------------^              ^   .----------^              ^
172  *          /              .-------------'  /       .------------------'
173  *         /              /          .-----'       /
174  *         .--------------.         .--------------.
175  *         | segment 1    |         | segment 2    |
176  *         '--------------'         '--------------'
177  *
178  * The challenge here is to cut out the right pieces of the track for each of
179  * the playback segments. This fortunately can easily be done with the SEGMENT
180  * events of GStreamer.
181  *
182  * For playback of segment 1, we need to provide the decoder with the keyframe
183  * (a), in the above figure, but we must instruct it only to output the decoded
184  * data between second 1 and 2. We do this with a SEGMENT event for 1 to 2, time
185  * position set to the time of the segment: 0.
186  *
187  * We then proceed to push data from keyframe (a) to frame (b). The decoder
188  * decodes but clips all before media_time 1.
189  *
190  * After finishing a segment, we push out a new SEGMENT event with the clipping
191  * boundaries of the new data.
192  *
193  * This is a good usecase for the GStreamer accumulated SEGMENT events.
194  */
195
196 struct _QtDemuxSegment
197 {
198   /* global time and duration, all gst time */
199   GstClockTime time;
200   GstClockTime stop_time;
201   GstClockTime duration;
202   /* media time of trak, all gst time */
203   GstClockTime media_start;
204   GstClockTime media_stop;
205   gdouble rate;
206   /* Media start time in trak timescale units */
207   guint32 trak_media_start;
208 };
209
210 #define QTSEGMENT_IS_EMPTY(s) ((s)->media_start == GST_CLOCK_TIME_NONE)
211
212 /* Used with fragmented MP4 files (mfra atom) */
213 typedef struct
214 {
215   GstClockTime ts;
216   guint64 moof_offset;
217 } QtDemuxRandomAccessEntry;
218
219 typedef struct _QtDemuxStreamStsdEntry
220 {
221   GstCaps *caps;
222   guint32 fourcc;
223   gboolean sparse;
224
225   /* video info */
226   gint width;
227   gint height;
228   gint par_w;
229   gint par_h;
230   /* Numerator/denominator framerate */
231   gint fps_n;
232   gint fps_d;
233   GstVideoColorimetry colorimetry;
234   guint16 bits_per_sample;
235   guint16 color_table_id;
236   GstMemory *rgb8_palette;
237   guint interlace_mode;
238   guint field_order;
239
240   /* audio info */
241   gdouble rate;
242   gint n_channels;
243   guint samples_per_packet;
244   guint samples_per_frame;
245   guint bytes_per_packet;
246   guint bytes_per_sample;
247   guint bytes_per_frame;
248   guint compression;
249
250   /* if we use chunks or samples */
251   gboolean sampled;
252   guint padding;
253
254 } QtDemuxStreamStsdEntry;
255
256 #define CUR_STREAM(s) (&((s)->stsd_entries[(s)->cur_stsd_entry_index]))
257
258 struct _QtDemuxStream
259 {
260   GstPad *pad;
261
262   QtDemuxStreamStsdEntry *stsd_entries;
263   guint stsd_entries_length;
264   guint cur_stsd_entry_index;
265
266   /* stream type */
267   guint32 subtype;
268
269   gboolean new_caps;            /* If TRUE, caps need to be generated (by
270                                  * calling _configure_stream()) This happens
271                                  * for MSS and fragmented streams */
272
273   gboolean new_stream;          /* signals that a stream_start is required */
274   gboolean on_keyframe;         /* if this stream last pushed buffer was a
275                                  * keyframe. This is important to identify
276                                  * where to stop pushing buffers after a
277                                  * segment stop time */
278
279   /* if the stream has a redirect URI in its headers, we store it here */
280   gchar *redirect_uri;
281
282   /* track id */
283   guint track_id;
284
285   /* duration/scale */
286   guint64 duration;             /* in timescale units */
287   guint32 timescale;
288
289   /* language */
290   gchar lang_id[4];             /* ISO 639-2T language code */
291
292   /* our samples */
293   guint32 n_samples;
294   QtDemuxSample *samples;
295   gboolean all_keyframe;        /* TRUE when all samples are keyframes (no stss) */
296   guint32 first_duration;       /* duration in timescale of first sample, used for figuring out
297                                    the framerate */
298   guint32 n_samples_moof;       /* sample count in a moof */
299   guint64 duration_moof;        /* duration in timescale of a moof, used for figure out
300                                  * the framerate of fragmented format stream */
301   guint64 duration_last_moof;
302
303   guint32 offset_in_sample;     /* Offset in the current sample, used for
304                                  * streams which have got exceedingly big
305                                  * sample size (such as 24s of raw audio).
306                                  * Only used when max_buffer_size is non-NULL */
307   guint32 max_buffer_size;      /* Maximum allowed size for output buffers.
308                                  * Currently only set for raw audio streams*/
309
310   /* video info */
311   /* aspect ratio */
312   gint display_width;
313   gint display_height;
314
315   /* allocation */
316   gboolean use_allocator;
317   GstAllocator *allocator;
318   GstAllocationParams params;
319
320   gsize alignment;
321
322   /* when a discontinuity is pending */
323   gboolean discont;
324
325   /* list of buffers to push first */
326   GSList *buffers;
327
328   /* if we need to clip this buffer. This is only needed for uncompressed
329    * data */
330   gboolean need_clip;
331
332   /* buffer needs some custom processing, e.g. subtitles */
333   gboolean need_process;
334
335   /* current position */
336   guint32 segment_index;
337   guint32 sample_index;
338   GstClockTime time_position;   /* in gst time */
339   guint64 accumulated_base;
340
341   /* the Gst segment we are processing out, used for clipping */
342   GstSegment segment;
343
344   /* quicktime segments */
345   guint32 n_segments;
346   QtDemuxSegment *segments;
347   gboolean dummy_segment;
348   guint32 from_sample;
349   guint32 to_sample;
350
351   gboolean sent_eos;
352   GstTagList *stream_tags;
353   gboolean send_global_tags;
354
355   GstEvent *pending_event;
356
357   GstByteReader stco;
358   GstByteReader stsz;
359   GstByteReader stsc;
360   GstByteReader stts;
361   GstByteReader stss;
362   GstByteReader stps;
363   GstByteReader ctts;
364
365   gboolean chunks_are_samples;  /* TRUE means treat chunks as samples */
366   gint64 stbl_index;
367   /* stco */
368   guint co_size;
369   GstByteReader co_chunk;
370   guint32 first_chunk;
371   guint32 current_chunk;
372   guint32 last_chunk;
373   guint32 samples_per_chunk;
374   guint32 stsd_sample_description_id;
375   guint32 stco_sample_index;
376   /* stsz */
377   guint32 sample_size;          /* 0 means variable sizes are stored in stsz */
378   /* stsc */
379   guint32 stsc_index;
380   guint32 n_samples_per_chunk;
381   guint32 stsc_chunk_index;
382   guint32 stsc_sample_index;
383   guint64 chunk_offset;
384   /* stts */
385   guint32 stts_index;
386   guint32 stts_samples;
387   guint32 n_sample_times;
388   guint32 stts_sample_index;
389   guint64 stts_time;
390   guint32 stts_duration;
391   /* stss */
392   gboolean stss_present;
393   guint32 n_sample_syncs;
394   guint32 stss_index;
395   /* stps */
396   gboolean stps_present;
397   guint32 n_sample_partial_syncs;
398   guint32 stps_index;
399   QtDemuxRandomAccessEntry *ra_entries;
400   guint n_ra_entries;
401
402   const QtDemuxRandomAccessEntry *pending_seek;
403
404   /* ctts */
405   gboolean ctts_present;
406   guint32 n_composition_times;
407   guint32 ctts_index;
408   guint32 ctts_sample_index;
409   guint32 ctts_count;
410   gint32 ctts_soffset;
411
412   /* cslg */
413   guint32 cslg_shift;
414
415   /* fragmented */
416   gboolean parsed_trex;
417   guint32 def_sample_description_index; /* index is 1-based */
418   guint32 def_sample_duration;
419   guint32 def_sample_size;
420   guint32 def_sample_flags;
421
422   gboolean disabled;
423
424   /* stereoscopic video streams */
425   GstVideoMultiviewMode multiview_mode;
426   GstVideoMultiviewFlags multiview_flags;
427
428   /* protected streams */
429   gboolean protected;
430   guint32 protection_scheme_type;
431   guint32 protection_scheme_version;
432   gpointer protection_scheme_info;      /* specific to the protection scheme */
433   GQueue protection_scheme_event_queue;
434 };
435
436 /* Contains properties and cryptographic info for a set of samples from a
437  * track protected using Common Encryption (cenc) */
438 struct _QtDemuxCencSampleSetInfo
439 {
440   GstStructure *default_properties;
441
442   /* @crypto_info holds one GstStructure per sample */
443   GPtrArray *crypto_info;
444 };
445
446 static const gchar *
447 qt_demux_state_string (enum QtDemuxState state)
448 {
449   switch (state) {
450     case QTDEMUX_STATE_INITIAL:
451       return "<INITIAL>";
452     case QTDEMUX_STATE_HEADER:
453       return "<HEADER>";
454     case QTDEMUX_STATE_MOVIE:
455       return "<MOVIE>";
456     case QTDEMUX_STATE_BUFFER_MDAT:
457       return "<BUFFER_MDAT>";
458     default:
459       return "<UNKNOWN>";
460   }
461 }
462
463 static GNode *qtdemux_tree_get_child_by_type (GNode * node, guint32 fourcc);
464 static GNode *qtdemux_tree_get_child_by_type_full (GNode * node,
465     guint32 fourcc, GstByteReader * parser);
466 static GNode *qtdemux_tree_get_sibling_by_type (GNode * node, guint32 fourcc);
467 static GNode *qtdemux_tree_get_sibling_by_type_full (GNode * node,
468     guint32 fourcc, GstByteReader * parser);
469
470 static GstFlowReturn qtdemux_add_fragmented_samples (GstQTDemux * qtdemux);
471
472 static GstStaticPadTemplate gst_qtdemux_sink_template =
473     GST_STATIC_PAD_TEMPLATE ("sink",
474     GST_PAD_SINK,
475     GST_PAD_ALWAYS,
476     GST_STATIC_CAPS ("video/quicktime; video/mj2; audio/x-m4a; "
477         "application/x-3gp")
478     );
479
480 static GstStaticPadTemplate gst_qtdemux_videosrc_template =
481 GST_STATIC_PAD_TEMPLATE ("video_%u",
482     GST_PAD_SRC,
483     GST_PAD_SOMETIMES,
484     GST_STATIC_CAPS_ANY);
485
486 static GstStaticPadTemplate gst_qtdemux_audiosrc_template =
487 GST_STATIC_PAD_TEMPLATE ("audio_%u",
488     GST_PAD_SRC,
489     GST_PAD_SOMETIMES,
490     GST_STATIC_CAPS_ANY);
491
492 static GstStaticPadTemplate gst_qtdemux_subsrc_template =
493 GST_STATIC_PAD_TEMPLATE ("subtitle_%u",
494     GST_PAD_SRC,
495     GST_PAD_SOMETIMES,
496     GST_STATIC_CAPS_ANY);
497
498 #define gst_qtdemux_parent_class parent_class
499 G_DEFINE_TYPE (GstQTDemux, gst_qtdemux, GST_TYPE_ELEMENT);
500
501 static void gst_qtdemux_dispose (GObject * object);
502
503 static guint32
504 gst_qtdemux_find_index_linear (GstQTDemux * qtdemux, QtDemuxStream * str,
505     GstClockTime media_time);
506 static guint32
507 gst_qtdemux_find_index_for_given_media_offset_linear (GstQTDemux * qtdemux,
508     QtDemuxStream * str, gint64 media_offset);
509
510 #if 0
511 static void gst_qtdemux_set_index (GstElement * element, GstIndex * index);
512 static GstIndex *gst_qtdemux_get_index (GstElement * element);
513 #endif
514 static GstStateChangeReturn gst_qtdemux_change_state (GstElement * element,
515     GstStateChange transition);
516 static gboolean qtdemux_sink_activate (GstPad * sinkpad, GstObject * parent);
517 static gboolean qtdemux_sink_activate_mode (GstPad * sinkpad,
518     GstObject * parent, GstPadMode mode, gboolean active);
519
520 static void gst_qtdemux_loop (GstPad * pad);
521 static GstFlowReturn gst_qtdemux_chain (GstPad * sinkpad, GstObject * parent,
522     GstBuffer * inbuf);
523 static gboolean gst_qtdemux_handle_sink_event (GstPad * pad, GstObject * parent,
524     GstEvent * event);
525 static gboolean gst_qtdemux_setcaps (GstQTDemux * qtdemux, GstCaps * caps);
526 static gboolean gst_qtdemux_configure_stream (GstQTDemux * qtdemux,
527     QtDemuxStream * stream);
528 static void gst_qtdemux_stream_check_and_change_stsd_index (GstQTDemux * demux,
529     QtDemuxStream * stream);
530 static GstFlowReturn gst_qtdemux_process_adapter (GstQTDemux * demux,
531     gboolean force);
532
533 static gboolean qtdemux_parse_moov (GstQTDemux * qtdemux,
534     const guint8 * buffer, guint length);
535 static gboolean qtdemux_parse_node (GstQTDemux * qtdemux, GNode * node,
536     const guint8 * buffer, guint length);
537 static gboolean qtdemux_parse_tree (GstQTDemux * qtdemux);
538 static void qtdemux_parse_udta (GstQTDemux * qtdemux, GstTagList * taglist,
539     GNode * udta);
540
541 static void gst_qtdemux_handle_esds (GstQTDemux * qtdemux,
542     QtDemuxStream * stream, QtDemuxStreamStsdEntry * entry, GNode * esds,
543     GstTagList * list);
544 static GstCaps *qtdemux_video_caps (GstQTDemux * qtdemux,
545     QtDemuxStream * stream, QtDemuxStreamStsdEntry * entry, guint32 fourcc,
546     const guint8 * stsd_entry_data, gchar ** codec_name);
547 static GstCaps *qtdemux_audio_caps (GstQTDemux * qtdemux,
548     QtDemuxStream * stream, QtDemuxStreamStsdEntry * entry, guint32 fourcc,
549     const guint8 * data, int len, gchar ** codec_name);
550 static GstCaps *qtdemux_sub_caps (GstQTDemux * qtdemux, QtDemuxStream * stream,
551     QtDemuxStreamStsdEntry * entry, guint32 fourcc, const guint8 * data,
552     gchar ** codec_name);
553 static GstCaps *qtdemux_generic_caps (GstQTDemux * qtdemux,
554     QtDemuxStream * stream, QtDemuxStreamStsdEntry * entry, guint32 fourcc,
555     const guint8 * stsd_entry_data, gchar ** codec_name);
556
557 static gboolean qtdemux_parse_samples (GstQTDemux * qtdemux,
558     QtDemuxStream * stream, guint32 n);
559 static GstFlowReturn qtdemux_expose_streams (GstQTDemux * qtdemux);
560 static void gst_qtdemux_stream_free (GstQTDemux * qtdemux,
561     QtDemuxStream * stream);
562 static void gst_qtdemux_stream_clear (GstQTDemux * qtdemux,
563     QtDemuxStream * stream);
564 static void gst_qtdemux_remove_stream (GstQTDemux * qtdemux, int index);
565 static GstFlowReturn qtdemux_prepare_streams (GstQTDemux * qtdemux);
566 static void qtdemux_do_allocation (GstQTDemux * qtdemux,
567     QtDemuxStream * stream);
568 static gboolean gst_qtdemux_activate_segment (GstQTDemux * qtdemux,
569     QtDemuxStream * stream, guint32 seg_idx, GstClockTime offset);
570 static gboolean gst_qtdemux_stream_update_segment (GstQTDemux * qtdemux,
571     QtDemuxStream * stream, gint seg_idx, GstClockTime offset,
572     GstClockTime * _start, GstClockTime * _stop);
573 static void gst_qtdemux_send_gap_for_segment (GstQTDemux * demux,
574     QtDemuxStream * stream, gint segment_index, GstClockTime pos);
575
576 static gboolean qtdemux_pull_mfro_mfra (GstQTDemux * qtdemux);
577 static void check_update_duration (GstQTDemux * qtdemux, GstClockTime duration);
578
579 static gchar *qtdemux_uuid_bytes_to_string (gconstpointer uuid_bytes);
580
581 static GstStructure *qtdemux_get_cenc_sample_properties (GstQTDemux * qtdemux,
582     QtDemuxStream * stream, guint sample_index);
583 static void gst_qtdemux_append_protection_system_id (GstQTDemux * qtdemux,
584     const gchar * id);
585 static void qtdemux_gst_structure_free (GstStructure * gststructure);
586
587 static void
588 gst_qtdemux_class_init (GstQTDemuxClass * klass)
589 {
590   GObjectClass *gobject_class;
591   GstElementClass *gstelement_class;
592
593   gobject_class = (GObjectClass *) klass;
594   gstelement_class = (GstElementClass *) klass;
595
596   parent_class = g_type_class_peek_parent (klass);
597
598   gobject_class->dispose = gst_qtdemux_dispose;
599
600   gstelement_class->change_state = GST_DEBUG_FUNCPTR (gst_qtdemux_change_state);
601 #if 0
602   gstelement_class->set_index = GST_DEBUG_FUNCPTR (gst_qtdemux_set_index);
603   gstelement_class->get_index = GST_DEBUG_FUNCPTR (gst_qtdemux_get_index);
604 #endif
605
606   gst_tag_register_musicbrainz_tags ();
607
608   gst_element_class_add_static_pad_template (gstelement_class,
609       &gst_qtdemux_sink_template);
610   gst_element_class_add_static_pad_template (gstelement_class,
611       &gst_qtdemux_videosrc_template);
612   gst_element_class_add_static_pad_template (gstelement_class,
613       &gst_qtdemux_audiosrc_template);
614   gst_element_class_add_static_pad_template (gstelement_class,
615       &gst_qtdemux_subsrc_template);
616   gst_element_class_set_static_metadata (gstelement_class, "QuickTime demuxer",
617       "Codec/Demuxer",
618       "Demultiplex a QuickTime file into audio and video streams",
619       "David Schleef <ds@schleef.org>, Wim Taymans <wim@fluendo.com>");
620
621   GST_DEBUG_CATEGORY_INIT (qtdemux_debug, "qtdemux", 0, "qtdemux plugin");
622
623 }
624
625 static void
626 gst_qtdemux_init (GstQTDemux * qtdemux)
627 {
628   qtdemux->sinkpad =
629       gst_pad_new_from_static_template (&gst_qtdemux_sink_template, "sink");
630   gst_pad_set_activate_function (qtdemux->sinkpad, qtdemux_sink_activate);
631   gst_pad_set_activatemode_function (qtdemux->sinkpad,
632       qtdemux_sink_activate_mode);
633   gst_pad_set_chain_function (qtdemux->sinkpad, gst_qtdemux_chain);
634   gst_pad_set_event_function (qtdemux->sinkpad, gst_qtdemux_handle_sink_event);
635   gst_element_add_pad (GST_ELEMENT_CAST (qtdemux), qtdemux->sinkpad);
636
637   qtdemux->state = QTDEMUX_STATE_INITIAL;
638   qtdemux->pullbased = FALSE;
639   qtdemux->posted_redirect = FALSE;
640   qtdemux->neededbytes = 16;
641   qtdemux->todrop = 0;
642   qtdemux->adapter = gst_adapter_new ();
643   qtdemux->offset = 0;
644   qtdemux->first_mdat = -1;
645   qtdemux->got_moov = FALSE;
646   qtdemux->mdatoffset = -1;
647   qtdemux->mdatbuffer = NULL;
648   qtdemux->restoredata_buffer = NULL;
649   qtdemux->restoredata_offset = -1;
650   qtdemux->fragment_start = -1;
651   qtdemux->fragment_start_offset = -1;
652   qtdemux->media_caps = NULL;
653   qtdemux->exposed = FALSE;
654   qtdemux->mss_mode = FALSE;
655   qtdemux->pending_newsegment = NULL;
656   qtdemux->upstream_format_is_time = FALSE;
657   qtdemux->have_group_id = FALSE;
658   qtdemux->group_id = G_MAXUINT;
659   qtdemux->cenc_aux_info_offset = 0;
660   qtdemux->cenc_aux_info_sizes = NULL;
661   qtdemux->cenc_aux_sample_count = 0;
662   qtdemux->protection_system_ids = NULL;
663   g_queue_init (&qtdemux->protection_event_queue);
664   gst_segment_init (&qtdemux->segment, GST_FORMAT_TIME);
665   qtdemux->tag_list = gst_tag_list_new_empty ();
666   gst_tag_list_set_scope (qtdemux->tag_list, GST_TAG_SCOPE_GLOBAL);
667   qtdemux->flowcombiner = gst_flow_combiner_new ();
668
669   GST_OBJECT_FLAG_SET (qtdemux, GST_ELEMENT_FLAG_INDEXABLE);
670 }
671
672 static void
673 gst_qtdemux_dispose (GObject * object)
674 {
675   GstQTDemux *qtdemux = GST_QTDEMUX (object);
676
677   if (qtdemux->adapter) {
678     g_object_unref (G_OBJECT (qtdemux->adapter));
679     qtdemux->adapter = NULL;
680   }
681   gst_tag_list_unref (qtdemux->tag_list);
682   gst_flow_combiner_free (qtdemux->flowcombiner);
683   g_queue_foreach (&qtdemux->protection_event_queue, (GFunc) gst_event_unref,
684       NULL);
685   g_queue_clear (&qtdemux->protection_event_queue);
686
687   g_free (qtdemux->cenc_aux_info_sizes);
688   qtdemux->cenc_aux_info_sizes = NULL;
689
690   G_OBJECT_CLASS (parent_class)->dispose (object);
691 }
692
693 static void
694 gst_qtdemux_post_no_playable_stream_error (GstQTDemux * qtdemux)
695 {
696   if (qtdemux->posted_redirect) {
697     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
698         (_("This file contains no playable streams.")),
699         ("no known streams found, a redirect message has been posted"));
700   } else {
701     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
702         (_("This file contains no playable streams.")),
703         ("no known streams found"));
704   }
705 }
706
707 static GstBuffer *
708 _gst_buffer_new_wrapped (gpointer mem, gsize size, GFreeFunc free_func)
709 {
710   return gst_buffer_new_wrapped_full (free_func ? 0 : GST_MEMORY_FLAG_READONLY,
711       mem, size, 0, size, mem, free_func);
712 }
713
714 static GstFlowReturn
715 gst_qtdemux_pull_atom (GstQTDemux * qtdemux, guint64 offset, guint64 size,
716     GstBuffer ** buf)
717 {
718   GstFlowReturn flow;
719   GstMapInfo map;
720   gsize bsize;
721
722   if (G_UNLIKELY (size == 0)) {
723     GstFlowReturn ret;
724     GstBuffer *tmp = NULL;
725
726     ret = gst_qtdemux_pull_atom (qtdemux, offset, sizeof (guint32), &tmp);
727     if (ret != GST_FLOW_OK)
728       return ret;
729
730     gst_buffer_map (tmp, &map, GST_MAP_READ);
731     size = QT_UINT32 (map.data);
732     GST_DEBUG_OBJECT (qtdemux, "size 0x%08" G_GINT64_MODIFIER "x", size);
733
734     gst_buffer_unmap (tmp, &map);
735     gst_buffer_unref (tmp);
736   }
737
738   /* Sanity check: catch bogus sizes (fuzzed/broken files) */
739   if (G_UNLIKELY (size > QTDEMUX_MAX_ATOM_SIZE)) {
740     if (qtdemux->state != QTDEMUX_STATE_MOVIE && qtdemux->got_moov) {
741       /* we're pulling header but already got most interesting bits,
742        * so never mind the rest (e.g. tags) (that much) */
743       GST_WARNING_OBJECT (qtdemux, "atom has bogus size %" G_GUINT64_FORMAT,
744           size);
745       return GST_FLOW_EOS;
746     } else {
747       GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
748           (_("This file is invalid and cannot be played.")),
749           ("atom has bogus size %" G_GUINT64_FORMAT, size));
750       return GST_FLOW_ERROR;
751     }
752   }
753
754   flow = gst_pad_pull_range (qtdemux->sinkpad, offset, size, buf);
755
756   if (G_UNLIKELY (flow != GST_FLOW_OK))
757     return flow;
758
759   bsize = gst_buffer_get_size (*buf);
760   /* Catch short reads - we don't want any partial atoms */
761   if (G_UNLIKELY (bsize < size)) {
762     GST_WARNING_OBJECT (qtdemux,
763         "short read: %" G_GSIZE_FORMAT " < %" G_GUINT64_FORMAT, bsize, size);
764     gst_buffer_unref (*buf);
765     *buf = NULL;
766     return GST_FLOW_EOS;
767   }
768
769   return flow;
770 }
771
772 #if 1
773 static gboolean
774 gst_qtdemux_src_convert (GstQTDemux * qtdemux, GstPad * pad,
775     GstFormat src_format, gint64 src_value, GstFormat dest_format,
776     gint64 * dest_value)
777 {
778   gboolean res = TRUE;
779   QtDemuxStream *stream = gst_pad_get_element_private (pad);
780   gint32 index;
781
782   if (stream->subtype != FOURCC_vide) {
783     res = FALSE;
784     goto done;
785   }
786
787   switch (src_format) {
788     case GST_FORMAT_TIME:
789       switch (dest_format) {
790         case GST_FORMAT_BYTES:{
791           index = gst_qtdemux_find_index_linear (qtdemux, stream, src_value);
792           if (-1 == index) {
793             res = FALSE;
794             goto done;
795           }
796
797           *dest_value = stream->samples[index].offset;
798
799           GST_DEBUG_OBJECT (qtdemux, "Format Conversion Time->Offset :%"
800               GST_TIME_FORMAT "->%" G_GUINT64_FORMAT,
801               GST_TIME_ARGS (src_value), *dest_value);
802           break;
803         }
804         default:
805           res = FALSE;
806           break;
807       }
808       break;
809     case GST_FORMAT_BYTES:
810       switch (dest_format) {
811         case GST_FORMAT_TIME:{
812           index =
813               gst_qtdemux_find_index_for_given_media_offset_linear (qtdemux,
814               stream, src_value);
815
816           if (-1 == index) {
817             res = FALSE;
818             goto done;
819           }
820
821           *dest_value =
822               QTSTREAMTIME_TO_GSTTIME (stream,
823               stream->samples[index].timestamp);
824           GST_DEBUG_OBJECT (qtdemux,
825               "Format Conversion Offset->Time :%" G_GUINT64_FORMAT "->%"
826               GST_TIME_FORMAT, src_value, GST_TIME_ARGS (*dest_value));
827           break;
828         }
829         default:
830           res = FALSE;
831           break;
832       }
833       break;
834     default:
835       res = FALSE;
836       break;
837   }
838
839 done:
840   return res;
841 }
842 #endif
843
844 static gboolean
845 gst_qtdemux_get_duration (GstQTDemux * qtdemux, GstClockTime * duration)
846 {
847   gboolean res = FALSE;
848
849   *duration = GST_CLOCK_TIME_NONE;
850
851   if (qtdemux->duration != 0 &&
852       qtdemux->duration != G_MAXINT64 && qtdemux->timescale != 0) {
853     *duration = QTTIME_TO_GSTTIME (qtdemux, qtdemux->duration);
854     res = TRUE;
855   } else {
856     *duration = GST_CLOCK_TIME_NONE;
857   }
858
859   return res;
860 }
861
862 static gboolean
863 gst_qtdemux_handle_src_query (GstPad * pad, GstObject * parent,
864     GstQuery * query)
865 {
866   gboolean res = FALSE;
867   GstQTDemux *qtdemux = GST_QTDEMUX (parent);
868
869   GST_LOG_OBJECT (pad, "%s query", GST_QUERY_TYPE_NAME (query));
870
871   switch (GST_QUERY_TYPE (query)) {
872     case GST_QUERY_POSITION:{
873       GstFormat fmt;
874
875       gst_query_parse_position (query, &fmt, NULL);
876       if (fmt == GST_FORMAT_TIME
877           && GST_CLOCK_TIME_IS_VALID (qtdemux->segment.position)) {
878         gst_query_set_position (query, GST_FORMAT_TIME,
879             qtdemux->segment.position);
880         res = TRUE;
881       }
882     }
883       break;
884     case GST_QUERY_DURATION:{
885       GstFormat fmt;
886
887       gst_query_parse_duration (query, &fmt, NULL);
888       if (fmt == GST_FORMAT_TIME) {
889         /* First try to query upstream */
890         res = gst_pad_query_default (pad, parent, query);
891         if (!res) {
892           GstClockTime duration;
893           if (gst_qtdemux_get_duration (qtdemux, &duration) && duration > 0) {
894             gst_query_set_duration (query, GST_FORMAT_TIME, duration);
895             res = TRUE;
896           }
897         }
898       }
899       break;
900     }
901     case GST_QUERY_CONVERT:{
902       GstFormat src_fmt, dest_fmt;
903       gint64 src_value, dest_value = 0;
904
905       gst_query_parse_convert (query, &src_fmt, &src_value, &dest_fmt, NULL);
906
907       res = gst_qtdemux_src_convert (qtdemux, pad,
908           src_fmt, src_value, dest_fmt, &dest_value);
909       if (res)
910         gst_query_set_convert (query, src_fmt, src_value, dest_fmt, dest_value);
911
912       break;
913     }
914     case GST_QUERY_FORMATS:
915       gst_query_set_formats (query, 2, GST_FORMAT_TIME, GST_FORMAT_BYTES);
916       res = TRUE;
917       break;
918     case GST_QUERY_SEEKING:{
919       GstFormat fmt;
920       gboolean seekable;
921
922       /* try upstream first */
923       res = gst_pad_query_default (pad, parent, query);
924
925       if (!res) {
926         gst_query_parse_seeking (query, &fmt, NULL, NULL, NULL);
927         if (fmt == GST_FORMAT_TIME) {
928           GstClockTime duration;
929
930           gst_qtdemux_get_duration (qtdemux, &duration);
931           seekable = TRUE;
932           if (!qtdemux->pullbased) {
933             GstQuery *q;
934
935             /* we might be able with help from upstream */
936             seekable = FALSE;
937             q = gst_query_new_seeking (GST_FORMAT_BYTES);
938             if (gst_pad_peer_query (qtdemux->sinkpad, q)) {
939               gst_query_parse_seeking (q, &fmt, &seekable, NULL, NULL);
940               GST_LOG_OBJECT (qtdemux, "upstream BYTE seekable %d", seekable);
941             }
942             gst_query_unref (q);
943           }
944           gst_query_set_seeking (query, GST_FORMAT_TIME, seekable, 0, duration);
945           res = TRUE;
946         }
947       }
948       break;
949     }
950     case GST_QUERY_SEGMENT:
951     {
952       GstFormat format;
953       gint64 start, stop;
954
955       format = qtdemux->segment.format;
956
957       start =
958           gst_segment_to_stream_time (&qtdemux->segment, format,
959           qtdemux->segment.start);
960       if ((stop = qtdemux->segment.stop) == -1)
961         stop = qtdemux->segment.duration;
962       else
963         stop = gst_segment_to_stream_time (&qtdemux->segment, format, stop);
964
965       gst_query_set_segment (query, qtdemux->segment.rate, format, start, stop);
966       res = TRUE;
967       break;
968     }
969     default:
970       res = gst_pad_query_default (pad, parent, query);
971       break;
972   }
973
974   return res;
975 }
976
977 static void
978 gst_qtdemux_push_tags (GstQTDemux * qtdemux, QtDemuxStream * stream)
979 {
980   if (G_LIKELY (stream->pad)) {
981     GST_DEBUG_OBJECT (qtdemux, "Checking pad %s:%s for tags",
982         GST_DEBUG_PAD_NAME (stream->pad));
983
984     if (!gst_tag_list_is_empty (stream->stream_tags)) {
985       GST_DEBUG_OBJECT (qtdemux, "Sending tags %" GST_PTR_FORMAT,
986           stream->stream_tags);
987       gst_pad_push_event (stream->pad,
988           gst_event_new_tag (gst_tag_list_ref (stream->stream_tags)));
989     }
990
991     if (G_UNLIKELY (stream->send_global_tags)) {
992       GST_DEBUG_OBJECT (qtdemux, "Sending global tags %" GST_PTR_FORMAT,
993           qtdemux->tag_list);
994       gst_pad_push_event (stream->pad,
995           gst_event_new_tag (gst_tag_list_ref (qtdemux->tag_list)));
996       stream->send_global_tags = FALSE;
997     }
998   }
999 }
1000
1001 /* push event on all source pads; takes ownership of the event */
1002 static void
1003 gst_qtdemux_push_event (GstQTDemux * qtdemux, GstEvent * event)
1004 {
1005   guint n;
1006   gboolean has_valid_stream = FALSE;
1007   GstEventType etype = GST_EVENT_TYPE (event);
1008
1009   GST_DEBUG_OBJECT (qtdemux, "pushing %s event on all source pads",
1010       GST_EVENT_TYPE_NAME (event));
1011
1012   for (n = 0; n < qtdemux->n_streams; n++) {
1013     GstPad *pad;
1014     QtDemuxStream *stream = qtdemux->streams[n];
1015     GST_DEBUG_OBJECT (qtdemux, "pushing on pad %i", n);
1016
1017     if ((pad = stream->pad)) {
1018       has_valid_stream = TRUE;
1019
1020       if (etype == GST_EVENT_EOS) {
1021         /* let's not send twice */
1022         if (stream->sent_eos)
1023           continue;
1024         stream->sent_eos = TRUE;
1025       }
1026
1027       gst_pad_push_event (pad, gst_event_ref (event));
1028     }
1029   }
1030
1031   gst_event_unref (event);
1032
1033   /* if it is EOS and there are no pads, post an error */
1034   if (!has_valid_stream && etype == GST_EVENT_EOS) {
1035     gst_qtdemux_post_no_playable_stream_error (qtdemux);
1036   }
1037 }
1038
1039 /* push a pending newsegment event, if any from the streaming thread */
1040 static void
1041 gst_qtdemux_push_pending_newsegment (GstQTDemux * qtdemux)
1042 {
1043   if (qtdemux->pending_newsegment) {
1044     gst_qtdemux_push_event (qtdemux, qtdemux->pending_newsegment);
1045     qtdemux->pending_newsegment = NULL;
1046   }
1047 }
1048
1049 typedef struct
1050 {
1051   guint64 media_time;
1052 } FindData;
1053
1054 static gint
1055 find_func (QtDemuxSample * s1, gint64 * media_time, gpointer user_data)
1056 {
1057   if ((gint64) s1->timestamp + s1->pts_offset > *media_time)
1058     return 1;
1059   if ((gint64) s1->timestamp + s1->pts_offset == *media_time)
1060     return 0;
1061
1062   return -1;
1063 }
1064
1065 /* find the index of the sample that includes the data for @media_time using a
1066  * binary search.  Only to be called in optimized cases of linear search below.
1067  *
1068  * Returns the index of the sample.
1069  */
1070 static guint32
1071 gst_qtdemux_find_index (GstQTDemux * qtdemux, QtDemuxStream * str,
1072     guint64 media_time)
1073 {
1074   QtDemuxSample *result;
1075   guint32 index;
1076
1077   /* convert media_time to mov format */
1078   media_time =
1079       gst_util_uint64_scale_ceil (media_time, str->timescale, GST_SECOND);
1080
1081   result = gst_util_array_binary_search (str->samples, str->stbl_index + 1,
1082       sizeof (QtDemuxSample), (GCompareDataFunc) find_func,
1083       GST_SEARCH_MODE_BEFORE, &media_time, NULL);
1084
1085   if (G_LIKELY (result))
1086     index = result - str->samples;
1087   else
1088     index = 0;
1089
1090   return index;
1091 }
1092
1093
1094
1095 /* find the index of the sample that includes the data for @media_offset using a
1096  * linear search
1097  *
1098  * Returns the index of the sample.
1099  */
1100 static guint32
1101 gst_qtdemux_find_index_for_given_media_offset_linear (GstQTDemux * qtdemux,
1102     QtDemuxStream * str, gint64 media_offset)
1103 {
1104   QtDemuxSample *result = str->samples;
1105   guint32 index = 0;
1106
1107   if (result == NULL || str->n_samples == 0)
1108     return -1;
1109
1110   if (media_offset == result->offset)
1111     return index;
1112
1113   result++;
1114   while (index < str->n_samples - 1) {
1115     if (!qtdemux_parse_samples (qtdemux, str, index + 1))
1116       goto parse_failed;
1117
1118     if (media_offset < result->offset)
1119       break;
1120
1121     index++;
1122     result++;
1123   }
1124   return index;
1125
1126   /* ERRORS */
1127 parse_failed:
1128   {
1129     GST_LOG_OBJECT (qtdemux, "Parsing of index %u failed!", index + 1);
1130     return -1;
1131   }
1132 }
1133
1134 /* find the index of the sample that includes the data for @media_time using a
1135  * linear search, and keeping in mind that not all samples may have been parsed
1136  * yet.  If possible, it will delegate to binary search.
1137  *
1138  * Returns the index of the sample.
1139  */
1140 static guint32
1141 gst_qtdemux_find_index_linear (GstQTDemux * qtdemux, QtDemuxStream * str,
1142     GstClockTime media_time)
1143 {
1144   guint32 index = 0;
1145   guint64 mov_time;
1146   QtDemuxSample *sample;
1147
1148   /* convert media_time to mov format */
1149   mov_time =
1150       gst_util_uint64_scale_ceil (media_time, str->timescale, GST_SECOND);
1151
1152   sample = str->samples;
1153   if (mov_time == sample->timestamp + sample->pts_offset)
1154     return index;
1155
1156   /* use faster search if requested time in already parsed range */
1157   sample = str->samples + str->stbl_index;
1158   if (str->stbl_index >= 0 &&
1159       mov_time <= (sample->timestamp + sample->pts_offset))
1160     return gst_qtdemux_find_index (qtdemux, str, media_time);
1161
1162   while (index < str->n_samples - 1) {
1163     if (!qtdemux_parse_samples (qtdemux, str, index + 1))
1164       goto parse_failed;
1165
1166     sample = str->samples + index + 1;
1167     if (mov_time < (sample->timestamp + sample->pts_offset))
1168       break;
1169
1170     index++;
1171   }
1172   return index;
1173
1174   /* ERRORS */
1175 parse_failed:
1176   {
1177     GST_LOG_OBJECT (qtdemux, "Parsing of index %u failed!", index + 1);
1178     return -1;
1179   }
1180 }
1181
1182 /* find the index of the keyframe needed to decode the sample at @index
1183  * of stream @str, or of a subsequent keyframe (depending on @next)
1184  *
1185  * Returns the index of the keyframe.
1186  */
1187 static guint32
1188 gst_qtdemux_find_keyframe (GstQTDemux * qtdemux, QtDemuxStream * str,
1189     guint32 index, gboolean next)
1190 {
1191   guint32 new_index = index;
1192
1193   if (index >= str->n_samples) {
1194     new_index = str->n_samples;
1195     goto beach;
1196   }
1197
1198   /* all keyframes, return index */
1199   if (str->all_keyframe) {
1200     new_index = index;
1201     goto beach;
1202   }
1203
1204   /* else search until we have a keyframe */
1205   while (new_index < str->n_samples) {
1206     if (next && !qtdemux_parse_samples (qtdemux, str, new_index))
1207       goto parse_failed;
1208
1209     if (str->samples[new_index].keyframe)
1210       break;
1211
1212     if (new_index == 0)
1213       break;
1214
1215     if (next)
1216       new_index++;
1217     else
1218       new_index--;
1219   }
1220
1221   if (new_index == str->n_samples) {
1222     GST_DEBUG_OBJECT (qtdemux, "no next keyframe");
1223     new_index = -1;
1224   }
1225
1226 beach:
1227   GST_DEBUG_OBJECT (qtdemux, "searching for keyframe index %s index %u "
1228       "gave %u", next ? "after" : "before", index, new_index);
1229
1230   return new_index;
1231
1232   /* ERRORS */
1233 parse_failed:
1234   {
1235     GST_LOG_OBJECT (qtdemux, "Parsing of index %u failed!", new_index);
1236     return -1;
1237   }
1238 }
1239
1240 /* find the segment for @time_position for @stream
1241  *
1242  * Returns the index of the segment containing @time_position.
1243  * Returns the last segment and sets the @eos variable to TRUE
1244  * if the time is beyond the end. @eos may be NULL
1245  */
1246 static guint32
1247 gst_qtdemux_find_segment (GstQTDemux * qtdemux, QtDemuxStream * stream,
1248     GstClockTime time_position)
1249 {
1250   gint i;
1251   guint32 seg_idx;
1252
1253   GST_LOG_OBJECT (stream->pad, "finding segment for %" GST_TIME_FORMAT,
1254       GST_TIME_ARGS (time_position));
1255
1256   seg_idx = -1;
1257   for (i = 0; i < stream->n_segments; i++) {
1258     QtDemuxSegment *segment = &stream->segments[i];
1259
1260     GST_LOG_OBJECT (stream->pad,
1261         "looking at segment %" GST_TIME_FORMAT "-%" GST_TIME_FORMAT,
1262         GST_TIME_ARGS (segment->time), GST_TIME_ARGS (segment->stop_time));
1263
1264     /* For the last segment we include stop_time in the last segment */
1265     if (i < stream->n_segments - 1) {
1266       if (segment->time <= time_position && time_position < segment->stop_time) {
1267         GST_LOG_OBJECT (stream->pad, "segment %d matches", i);
1268         seg_idx = i;
1269         break;
1270       }
1271     } else {
1272       /* Last segment always matches */
1273       seg_idx = i;
1274       break;
1275     }
1276   }
1277   return seg_idx;
1278 }
1279
1280 /* move the stream @str to the sample position @index.
1281  *
1282  * Updates @str->sample_index and marks discontinuity if needed.
1283  */
1284 static void
1285 gst_qtdemux_move_stream (GstQTDemux * qtdemux, QtDemuxStream * str,
1286     guint32 index)
1287 {
1288   /* no change needed */
1289   if (index == str->sample_index)
1290     return;
1291
1292   GST_DEBUG_OBJECT (qtdemux, "moving to sample %u of %u", index,
1293       str->n_samples);
1294
1295   /* position changed, we have a discont */
1296   str->sample_index = index;
1297   str->offset_in_sample = 0;
1298   /* Each time we move in the stream we store the position where we are
1299    * starting from */
1300   str->from_sample = index;
1301   str->discont = TRUE;
1302 }
1303
1304 static void
1305 gst_qtdemux_adjust_seek (GstQTDemux * qtdemux, gint64 desired_time,
1306     gboolean use_sparse, gboolean next, gint64 * key_time, gint64 * key_offset)
1307 {
1308   guint64 min_offset;
1309   gint64 min_byte_offset = -1;
1310   gint n;
1311
1312   min_offset = desired_time;
1313
1314   /* for each stream, find the index of the sample in the segment
1315    * and move back to the previous keyframe. */
1316   for (n = 0; n < qtdemux->n_streams; n++) {
1317     QtDemuxStream *str;
1318     guint32 index, kindex;
1319     guint32 seg_idx;
1320     GstClockTime media_start;
1321     GstClockTime media_time;
1322     GstClockTime seg_time;
1323     QtDemuxSegment *seg;
1324     gboolean empty_segment = FALSE;
1325
1326     str = qtdemux->streams[n];
1327
1328     if (CUR_STREAM (str)->sparse && !use_sparse)
1329       continue;
1330
1331     seg_idx = gst_qtdemux_find_segment (qtdemux, str, desired_time);
1332     GST_DEBUG_OBJECT (qtdemux, "align segment %d", seg_idx);
1333
1334     /* get segment and time in the segment */
1335     seg = &str->segments[seg_idx];
1336     seg_time = (desired_time - seg->time) * seg->rate;
1337
1338     while (QTSEGMENT_IS_EMPTY (seg)) {
1339       seg_time = 0;
1340       empty_segment = TRUE;
1341       GST_DEBUG_OBJECT (str->pad, "Segment %d is empty, moving to next one",
1342           seg_idx);
1343       seg_idx++;
1344       if (seg_idx == str->n_segments)
1345         break;
1346       seg = &str->segments[seg_idx];
1347     }
1348
1349     if (seg_idx == str->n_segments) {
1350       /* FIXME track shouldn't have the last segment as empty, but if it
1351        * happens we better handle it */
1352       continue;
1353     }
1354
1355     /* get the media time in the segment */
1356     media_start = seg->media_start + seg_time;
1357
1358     /* get the index of the sample with media time */
1359     index = gst_qtdemux_find_index_linear (qtdemux, str, media_start);
1360     GST_DEBUG_OBJECT (qtdemux, "sample for %" GST_TIME_FORMAT " at %u"
1361         " at offset %" G_GUINT64_FORMAT " (empty segment: %d)",
1362         GST_TIME_ARGS (media_start), index, str->samples[index].offset,
1363         empty_segment);
1364
1365     /* shift to next frame if we are looking for next keyframe */
1366     if (next && QTSAMPLE_PTS_NO_CSLG (str, &str->samples[index]) < media_start
1367         && index < str->stbl_index)
1368       index++;
1369
1370     if (!empty_segment) {
1371       /* find previous keyframe */
1372       kindex = gst_qtdemux_find_keyframe (qtdemux, str, index, next);
1373
1374       /* we will settle for one before if none found after */
1375       if (next && kindex == -1)
1376         kindex = gst_qtdemux_find_keyframe (qtdemux, str, index, FALSE);
1377
1378       /* if the keyframe is at a different position, we need to update the
1379        * requested seek time */
1380       if (index != kindex) {
1381         index = kindex;
1382
1383         /* get timestamp of keyframe */
1384         media_time = QTSAMPLE_PTS_NO_CSLG (str, &str->samples[kindex]);
1385         GST_DEBUG_OBJECT (qtdemux,
1386             "keyframe at %u with time %" GST_TIME_FORMAT " at offset %"
1387             G_GUINT64_FORMAT, kindex, GST_TIME_ARGS (media_time),
1388             str->samples[kindex].offset);
1389
1390         /* keyframes in the segment get a chance to change the
1391          * desired_offset. keyframes out of the segment are
1392          * ignored. */
1393         if (media_time >= seg->media_start) {
1394           GstClockTime seg_time;
1395
1396           /* this keyframe is inside the segment, convert back to
1397            * segment time */
1398           seg_time = (media_time - seg->media_start) + seg->time;
1399           if ((!next && (seg_time < min_offset)) ||
1400               (next && (seg_time > min_offset)))
1401             min_offset = seg_time;
1402         }
1403       }
1404     }
1405
1406     if (min_byte_offset < 0 || str->samples[index].offset < min_byte_offset)
1407       min_byte_offset = str->samples[index].offset;
1408   }
1409
1410   if (key_time)
1411     *key_time = min_offset;
1412   if (key_offset)
1413     *key_offset = min_byte_offset;
1414 }
1415
1416 static gboolean
1417 gst_qtdemux_convert_seek (GstPad * pad, GstFormat * format,
1418     GstSeekType cur_type, gint64 * cur, GstSeekType stop_type, gint64 * stop)
1419 {
1420   gboolean res;
1421
1422   g_return_val_if_fail (format != NULL, FALSE);
1423   g_return_val_if_fail (cur != NULL, FALSE);
1424   g_return_val_if_fail (stop != NULL, FALSE);
1425
1426   if (*format == GST_FORMAT_TIME)
1427     return TRUE;
1428
1429   res = TRUE;
1430   if (cur_type != GST_SEEK_TYPE_NONE)
1431     res = gst_pad_query_convert (pad, *format, *cur, GST_FORMAT_TIME, cur);
1432   if (res && stop_type != GST_SEEK_TYPE_NONE)
1433     res = gst_pad_query_convert (pad, *format, *stop, GST_FORMAT_TIME, stop);
1434
1435   if (res)
1436     *format = GST_FORMAT_TIME;
1437
1438   return res;
1439 }
1440
1441 /* perform seek in push based mode:
1442    find BYTE position to move to based on time and delegate to upstream
1443 */
1444 static gboolean
1445 gst_qtdemux_do_push_seek (GstQTDemux * qtdemux, GstPad * pad, GstEvent * event)
1446 {
1447   gdouble rate;
1448   GstFormat format;
1449   GstSeekFlags flags;
1450   GstSeekType cur_type, stop_type;
1451   gint64 cur, stop, key_cur;
1452   gboolean res;
1453   gint64 byte_cur;
1454   gint64 original_stop;
1455   guint32 seqnum;
1456
1457   GST_DEBUG_OBJECT (qtdemux, "doing push-based seek");
1458
1459   gst_event_parse_seek (event, &rate, &format, &flags,
1460       &cur_type, &cur, &stop_type, &stop);
1461   seqnum = gst_event_get_seqnum (event);
1462
1463   /* only forward streaming and seeking is possible */
1464   if (rate <= 0)
1465     goto unsupported_seek;
1466
1467   /* convert to TIME if needed and possible */
1468   if (!gst_qtdemux_convert_seek (pad, &format, cur_type, &cur,
1469           stop_type, &stop))
1470     goto no_format;
1471
1472   /* Upstream seek in bytes will have undefined stop, but qtdemux stores
1473    * the original stop position to use when upstream pushes the new segment
1474    * for this seek */
1475   original_stop = stop;
1476   stop = -1;
1477
1478   /* find reasonable corresponding BYTE position,
1479    * also try to mind about keyframes, since we can not go back a bit for them
1480    * later on */
1481   /* determining @next here based on SNAP_BEFORE/SNAP_AFTER should
1482    * mostly just work, but let's not yet boldly go there  ... */
1483   gst_qtdemux_adjust_seek (qtdemux, cur, FALSE, FALSE, &key_cur, &byte_cur);
1484
1485   if (byte_cur == -1)
1486     goto abort_seek;
1487
1488   GST_DEBUG_OBJECT (qtdemux, "Pushing BYTE seek rate %g, "
1489       "start %" G_GINT64_FORMAT ", stop %" G_GINT64_FORMAT, rate, byte_cur,
1490       stop);
1491
1492   GST_OBJECT_LOCK (qtdemux);
1493   qtdemux->seek_offset = byte_cur;
1494   if (!(flags & GST_SEEK_FLAG_KEY_UNIT)) {
1495     qtdemux->push_seek_start = cur;
1496   } else {
1497     qtdemux->push_seek_start = key_cur;
1498   }
1499
1500   if (stop_type == GST_SEEK_TYPE_NONE) {
1501     qtdemux->push_seek_stop = qtdemux->segment.stop;
1502   } else {
1503     qtdemux->push_seek_stop = original_stop;
1504   }
1505   GST_OBJECT_UNLOCK (qtdemux);
1506
1507   /* BYTE seek event */
1508   event = gst_event_new_seek (rate, GST_FORMAT_BYTES, flags, cur_type, byte_cur,
1509       stop_type, stop);
1510   gst_event_set_seqnum (event, seqnum);
1511   res = gst_pad_push_event (qtdemux->sinkpad, event);
1512
1513   return res;
1514
1515   /* ERRORS */
1516 abort_seek:
1517   {
1518     GST_DEBUG_OBJECT (qtdemux, "could not determine byte position to seek to, "
1519         "seek aborted.");
1520     return FALSE;
1521   }
1522 unsupported_seek:
1523   {
1524     GST_DEBUG_OBJECT (qtdemux, "unsupported seek, seek aborted.");
1525     return FALSE;
1526   }
1527 no_format:
1528   {
1529     GST_DEBUG_OBJECT (qtdemux, "unsupported format given, seek aborted.");
1530     return FALSE;
1531   }
1532 }
1533
1534 /* perform the seek.
1535  *
1536  * We set all segment_indexes in the streams to unknown and
1537  * adjust the time_position to the desired position. this is enough
1538  * to trigger a segment switch in the streaming thread to start
1539  * streaming from the desired position.
1540  *
1541  * Keyframe seeking is a little more complicated when dealing with
1542  * segments. Ideally we want to move to the previous keyframe in
1543  * the segment but there might not be a keyframe in the segment. In
1544  * fact, none of the segments could contain a keyframe. We take a
1545  * practical approach: seek to the previous keyframe in the segment,
1546  * if there is none, seek to the beginning of the segment.
1547  *
1548  * Called with STREAM_LOCK
1549  */
1550 static gboolean
1551 gst_qtdemux_perform_seek (GstQTDemux * qtdemux, GstSegment * segment,
1552     guint32 seqnum, GstSeekFlags flags)
1553 {
1554   gint64 desired_offset;
1555   gint n;
1556
1557   desired_offset = segment->position;
1558
1559   GST_DEBUG_OBJECT (qtdemux, "seeking to %" GST_TIME_FORMAT,
1560       GST_TIME_ARGS (desired_offset));
1561
1562   /* may not have enough fragmented info to do this adjustment,
1563    * and we can't scan (and probably should not) at this time with
1564    * possibly flushing upstream */
1565   if ((flags & GST_SEEK_FLAG_KEY_UNIT) && !qtdemux->fragmented) {
1566     gint64 min_offset;
1567     gboolean next, before, after;
1568
1569     before = ! !(flags & GST_SEEK_FLAG_SNAP_BEFORE);
1570     after = ! !(flags & GST_SEEK_FLAG_SNAP_AFTER);
1571     next = after && !before;
1572     if (segment->rate < 0)
1573       next = !next;
1574
1575     gst_qtdemux_adjust_seek (qtdemux, desired_offset, TRUE, next, &min_offset,
1576         NULL);
1577     GST_DEBUG_OBJECT (qtdemux, "keyframe seek, align to %"
1578         GST_TIME_FORMAT, GST_TIME_ARGS (min_offset));
1579     desired_offset = min_offset;
1580   }
1581
1582   /* and set all streams to the final position */
1583   gst_flow_combiner_reset (qtdemux->flowcombiner);
1584   qtdemux->segment_seqnum = seqnum;
1585   for (n = 0; n < qtdemux->n_streams; n++) {
1586     QtDemuxStream *stream = qtdemux->streams[n];
1587
1588     stream->time_position = desired_offset;
1589     stream->accumulated_base = 0;
1590     stream->sample_index = -1;
1591     stream->offset_in_sample = 0;
1592     stream->segment_index = -1;
1593     stream->sent_eos = FALSE;
1594
1595     if (segment->flags & GST_SEEK_FLAG_FLUSH)
1596       gst_segment_init (&stream->segment, GST_FORMAT_TIME);
1597   }
1598   segment->position = desired_offset;
1599   segment->time = desired_offset;
1600   if (segment->rate >= 0) {
1601     segment->start = desired_offset;
1602
1603     /* we stop at the end */
1604     if (segment->stop == -1)
1605       segment->stop = segment->duration;
1606   } else {
1607     segment->stop = desired_offset;
1608   }
1609
1610   if (qtdemux->fragmented)
1611     qtdemux->fragmented_seek_pending = TRUE;
1612
1613   return TRUE;
1614 }
1615
1616 /* do a seek in pull based mode */
1617 static gboolean
1618 gst_qtdemux_do_seek (GstQTDemux * qtdemux, GstPad * pad, GstEvent * event)
1619 {
1620   gdouble rate;
1621   GstFormat format;
1622   GstSeekFlags flags;
1623   GstSeekType cur_type, stop_type;
1624   gint64 cur, stop;
1625   gboolean flush;
1626   gboolean update;
1627   GstSegment seeksegment;
1628   guint32 seqnum = 0;
1629   GstEvent *flush_event;
1630   gboolean ret;
1631
1632   if (event) {
1633     GST_DEBUG_OBJECT (qtdemux, "doing seek with event");
1634
1635     gst_event_parse_seek (event, &rate, &format, &flags,
1636         &cur_type, &cur, &stop_type, &stop);
1637     seqnum = gst_event_get_seqnum (event);
1638
1639     /* we have to have a format as the segment format. Try to convert
1640      * if not. */
1641     if (!gst_qtdemux_convert_seek (pad, &format, cur_type, &cur,
1642             stop_type, &stop))
1643       goto no_format;
1644
1645     GST_DEBUG_OBJECT (qtdemux, "seek format %s", gst_format_get_name (format));
1646   } else {
1647     GST_DEBUG_OBJECT (qtdemux, "doing seek without event");
1648     flags = 0;
1649   }
1650
1651   flush = flags & GST_SEEK_FLAG_FLUSH;
1652
1653   /* stop streaming, either by flushing or by pausing the task */
1654   if (flush) {
1655     flush_event = gst_event_new_flush_start ();
1656     if (seqnum)
1657       gst_event_set_seqnum (flush_event, seqnum);
1658     /* unlock upstream pull_range */
1659     gst_pad_push_event (qtdemux->sinkpad, gst_event_ref (flush_event));
1660     /* make sure out loop function exits */
1661     gst_qtdemux_push_event (qtdemux, flush_event);
1662   } else {
1663     /* non flushing seek, pause the task */
1664     gst_pad_pause_task (qtdemux->sinkpad);
1665   }
1666
1667   /* wait for streaming to finish */
1668   GST_PAD_STREAM_LOCK (qtdemux->sinkpad);
1669
1670   /* copy segment, we need this because we still need the old
1671    * segment when we close the current segment. */
1672   memcpy (&seeksegment, &qtdemux->segment, sizeof (GstSegment));
1673
1674   if (event) {
1675     /* configure the segment with the seek variables */
1676     GST_DEBUG_OBJECT (qtdemux, "configuring seek");
1677     if (!gst_segment_do_seek (&seeksegment, rate, format, flags,
1678             cur_type, cur, stop_type, stop, &update)) {
1679       ret = FALSE;
1680       GST_ERROR_OBJECT (qtdemux, "inconsistent seek values, doing nothing");
1681     } else {
1682       /* now do the seek */
1683       ret = gst_qtdemux_perform_seek (qtdemux, &seeksegment, seqnum, flags);
1684     }
1685   } else {
1686     /* now do the seek */
1687     ret = gst_qtdemux_perform_seek (qtdemux, &seeksegment, seqnum, flags);
1688   }
1689
1690   /* prepare for streaming again */
1691   if (flush) {
1692     flush_event = gst_event_new_flush_stop (TRUE);
1693     if (seqnum)
1694       gst_event_set_seqnum (flush_event, seqnum);
1695
1696     gst_pad_push_event (qtdemux->sinkpad, gst_event_ref (flush_event));
1697     gst_qtdemux_push_event (qtdemux, flush_event);
1698   }
1699
1700   /* commit the new segment */
1701   memcpy (&qtdemux->segment, &seeksegment, sizeof (GstSegment));
1702
1703   if (qtdemux->segment.flags & GST_SEEK_FLAG_SEGMENT) {
1704     GstMessage *msg = gst_message_new_segment_start (GST_OBJECT_CAST (qtdemux),
1705         qtdemux->segment.format, qtdemux->segment.position);
1706     if (seqnum)
1707       gst_message_set_seqnum (msg, seqnum);
1708     gst_element_post_message (GST_ELEMENT_CAST (qtdemux), msg);
1709   }
1710
1711   /* restart streaming, NEWSEGMENT will be sent from the streaming thread. */
1712   gst_pad_start_task (qtdemux->sinkpad, (GstTaskFunction) gst_qtdemux_loop,
1713       qtdemux->sinkpad, NULL);
1714
1715   GST_PAD_STREAM_UNLOCK (qtdemux->sinkpad);
1716
1717   return ret;
1718
1719   /* ERRORS */
1720 no_format:
1721   {
1722     GST_DEBUG_OBJECT (qtdemux, "unsupported format given, seek aborted.");
1723     return FALSE;
1724   }
1725 }
1726
1727 static gboolean
1728 qtdemux_ensure_index (GstQTDemux * qtdemux)
1729 {
1730   guint i;
1731
1732   GST_DEBUG_OBJECT (qtdemux, "collecting all metadata for all streams");
1733
1734   /* Build complete index */
1735   for (i = 0; i < qtdemux->n_streams; i++) {
1736     QtDemuxStream *stream = qtdemux->streams[i];
1737
1738     if (!qtdemux_parse_samples (qtdemux, stream, stream->n_samples - 1))
1739       goto parse_error;
1740   }
1741   return TRUE;
1742
1743   /* ERRORS */
1744 parse_error:
1745   {
1746     GST_LOG_OBJECT (qtdemux,
1747         "Building complete index of stream %u for seeking failed!", i);
1748     return FALSE;
1749   }
1750 }
1751
1752 static gboolean
1753 gst_qtdemux_handle_src_event (GstPad * pad, GstObject * parent,
1754     GstEvent * event)
1755 {
1756   gboolean res = TRUE;
1757   GstQTDemux *qtdemux = GST_QTDEMUX (parent);
1758
1759   switch (GST_EVENT_TYPE (event)) {
1760     case GST_EVENT_SEEK:
1761     {
1762 #ifndef GST_DISABLE_GST_DEBUG
1763       GstClockTime ts = gst_util_get_timestamp ();
1764 #endif
1765       guint32 seqnum = gst_event_get_seqnum (event);
1766
1767       if (seqnum == qtdemux->segment_seqnum) {
1768         GST_LOG_OBJECT (pad,
1769             "Drop duplicated SEEK event seqnum %" G_GUINT32_FORMAT, seqnum);
1770         gst_event_unref (event);
1771         return TRUE;
1772       }
1773
1774       if (qtdemux->upstream_format_is_time && qtdemux->fragmented) {
1775         /* seek should be handled by upstream, we might need to re-download fragments */
1776         GST_DEBUG_OBJECT (qtdemux,
1777             "let upstream handle seek for fragmented playback");
1778         goto upstream;
1779       }
1780
1781       /* Build complete index for seeking;
1782        * if not a fragmented file at least */
1783       if (!qtdemux->fragmented)
1784         if (!qtdemux_ensure_index (qtdemux))
1785           goto index_failed;
1786 #ifndef GST_DISABLE_GST_DEBUG
1787       ts = gst_util_get_timestamp () - ts;
1788       GST_INFO_OBJECT (qtdemux,
1789           "Time taken to parse index %" GST_TIME_FORMAT, GST_TIME_ARGS (ts));
1790 #endif
1791     }
1792       if (qtdemux->pullbased) {
1793         res = gst_qtdemux_do_seek (qtdemux, pad, event);
1794       } else if (gst_pad_push_event (qtdemux->sinkpad, gst_event_ref (event))) {
1795         GST_DEBUG_OBJECT (qtdemux, "Upstream successfully seeked");
1796         res = TRUE;
1797       } else if (qtdemux->state == QTDEMUX_STATE_MOVIE && qtdemux->n_streams
1798           && !qtdemux->fragmented) {
1799         res = gst_qtdemux_do_push_seek (qtdemux, pad, event);
1800       } else {
1801         GST_DEBUG_OBJECT (qtdemux,
1802             "ignoring seek in push mode in current state");
1803         res = FALSE;
1804       }
1805       gst_event_unref (event);
1806       break;
1807     default:
1808     upstream:
1809       res = gst_pad_event_default (pad, parent, event);
1810       break;
1811   }
1812
1813 done:
1814   return res;
1815
1816   /* ERRORS */
1817 index_failed:
1818   {
1819     GST_ERROR_OBJECT (qtdemux, "Index failed");
1820     gst_event_unref (event);
1821     res = FALSE;
1822     goto done;
1823   }
1824 }
1825
1826 /* stream/index return sample that is min/max w.r.t. byte position,
1827  * time is min/max w.r.t. time of samples,
1828  * the latter need not be time of the former sample */
1829 static void
1830 gst_qtdemux_find_sample (GstQTDemux * qtdemux, gint64 byte_pos, gboolean fw,
1831     gboolean set, QtDemuxStream ** _stream, gint * _index, gint64 * _time)
1832 {
1833   gint i, n, index;
1834   gint64 time, min_time;
1835   QtDemuxStream *stream;
1836
1837   min_time = -1;
1838   stream = NULL;
1839   index = -1;
1840
1841   for (n = 0; n < qtdemux->n_streams; ++n) {
1842     QtDemuxStream *str;
1843     gint inc;
1844     gboolean set_sample;
1845
1846     str = qtdemux->streams[n];
1847     set_sample = !set;
1848
1849     if (fw) {
1850       i = 0;
1851       inc = 1;
1852     } else {
1853       i = str->n_samples - 1;
1854       inc = -1;
1855     }
1856
1857     for (; (i >= 0) && (i < str->n_samples); i += inc) {
1858       if (str->samples[i].size == 0)
1859         continue;
1860
1861       if (fw && (str->samples[i].offset < byte_pos))
1862         continue;
1863
1864       if (!fw && (str->samples[i].offset + str->samples[i].size > byte_pos))
1865         continue;
1866
1867       /* move stream to first available sample */
1868       if (set) {
1869         gst_qtdemux_move_stream (qtdemux, str, i);
1870         set_sample = TRUE;
1871       }
1872
1873       /* avoid index from sparse streams since they might be far away */
1874       if (!CUR_STREAM (str)->sparse) {
1875         /* determine min/max time */
1876         time = QTSAMPLE_PTS (str, &str->samples[i]);
1877         if (min_time == -1 || (!fw && time > min_time) ||
1878             (fw && time < min_time)) {
1879           min_time = time;
1880         }
1881
1882         /* determine stream with leading sample, to get its position */
1883         if (!stream ||
1884             (fw && (str->samples[i].offset < stream->samples[index].offset)) ||
1885             (!fw && (str->samples[i].offset > stream->samples[index].offset))) {
1886           stream = str;
1887           index = i;
1888         }
1889       }
1890       break;
1891     }
1892
1893     /* no sample for this stream, mark eos */
1894     if (!set_sample)
1895       gst_qtdemux_move_stream (qtdemux, str, str->n_samples);
1896   }
1897
1898   if (_time)
1899     *_time = min_time;
1900   if (_stream)
1901     *_stream = stream;
1902   if (_index)
1903     *_index = index;
1904 }
1905
1906 static QtDemuxStream *
1907 _create_stream (void)
1908 {
1909   QtDemuxStream *stream;
1910
1911   stream = g_new0 (QtDemuxStream, 1);
1912   /* new streams always need a discont */
1913   stream->discont = TRUE;
1914   /* we enable clipping for raw audio/video streams */
1915   stream->need_clip = FALSE;
1916   stream->need_process = FALSE;
1917   stream->segment_index = -1;
1918   stream->time_position = 0;
1919   stream->sample_index = -1;
1920   stream->offset_in_sample = 0;
1921   stream->new_stream = TRUE;
1922   stream->multiview_mode = GST_VIDEO_MULTIVIEW_MODE_NONE;
1923   stream->multiview_flags = GST_VIDEO_MULTIVIEW_FLAGS_NONE;
1924   stream->protected = FALSE;
1925   stream->protection_scheme_type = 0;
1926   stream->protection_scheme_version = 0;
1927   stream->protection_scheme_info = NULL;
1928   stream->n_samples_moof = 0;
1929   stream->duration_moof = 0;
1930   stream->duration_last_moof = 0;
1931   stream->alignment = 1;
1932   stream->stream_tags = gst_tag_list_new_empty ();
1933   gst_tag_list_set_scope (stream->stream_tags, GST_TAG_SCOPE_STREAM);
1934   g_queue_init (&stream->protection_scheme_event_queue);
1935   return stream;
1936 }
1937
1938 static gboolean
1939 gst_qtdemux_setcaps (GstQTDemux * demux, GstCaps * caps)
1940 {
1941   GstStructure *structure;
1942   const gchar *variant;
1943   const GstCaps *mediacaps = NULL;
1944
1945   GST_DEBUG_OBJECT (demux, "Sink set caps: %" GST_PTR_FORMAT, caps);
1946
1947   structure = gst_caps_get_structure (caps, 0);
1948   variant = gst_structure_get_string (structure, "variant");
1949
1950   if (variant && strcmp (variant, "mss-fragmented") == 0) {
1951     QtDemuxStream *stream;
1952     const GValue *value;
1953
1954     demux->fragmented = TRUE;
1955     demux->mss_mode = TRUE;
1956
1957     if (demux->n_streams > 1) {
1958       /* can't do this, we can only renegotiate for another mss format */
1959       return FALSE;
1960     }
1961
1962     value = gst_structure_get_value (structure, "media-caps");
1963     /* create stream */
1964     if (value) {
1965       const GValue *timescale_v;
1966
1967       /* TODO update when stream changes during playback */
1968
1969       if (demux->n_streams == 0) {
1970         stream = _create_stream ();
1971         demux->streams[demux->n_streams] = stream;
1972         demux->n_streams = 1;
1973         /* mss has no stsd/stsd entry, use id 0 as default */
1974         stream->stsd_entries_length = 1;
1975         stream->stsd_sample_description_id = stream->cur_stsd_entry_index = 0;
1976         stream->stsd_entries = g_new0 (QtDemuxStreamStsdEntry, 1);
1977       } else {
1978         stream = demux->streams[0];
1979       }
1980
1981       timescale_v = gst_structure_get_value (structure, "timescale");
1982       if (timescale_v) {
1983         stream->timescale = g_value_get_uint64 (timescale_v);
1984       } else {
1985         /* default mss timescale */
1986         stream->timescale = 10000000;
1987       }
1988       demux->timescale = stream->timescale;
1989
1990       mediacaps = gst_value_get_caps (value);
1991       if (!CUR_STREAM (stream)->caps
1992           || !gst_caps_is_equal_fixed (mediacaps, CUR_STREAM (stream)->caps)) {
1993         GST_DEBUG_OBJECT (demux, "We have a new caps %" GST_PTR_FORMAT,
1994             mediacaps);
1995         stream->new_caps = TRUE;
1996       }
1997       gst_caps_replace (&CUR_STREAM (stream)->caps, (GstCaps *) mediacaps);
1998       structure = gst_caps_get_structure (mediacaps, 0);
1999       if (g_str_has_prefix (gst_structure_get_name (structure), "video")) {
2000         stream->subtype = FOURCC_vide;
2001
2002         gst_structure_get_int (structure, "width", &CUR_STREAM (stream)->width);
2003         gst_structure_get_int (structure, "height",
2004             &CUR_STREAM (stream)->height);
2005         gst_structure_get_fraction (structure, "framerate",
2006             &CUR_STREAM (stream)->fps_n, &CUR_STREAM (stream)->fps_d);
2007       } else if (g_str_has_prefix (gst_structure_get_name (structure), "audio")) {
2008         gint rate = 0;
2009         stream->subtype = FOURCC_soun;
2010         gst_structure_get_int (structure, "channels",
2011             &CUR_STREAM (stream)->n_channels);
2012         gst_structure_get_int (structure, "rate", &rate);
2013         CUR_STREAM (stream)->rate = rate;
2014       }
2015     }
2016     gst_caps_replace (&demux->media_caps, (GstCaps *) mediacaps);
2017   } else {
2018     demux->mss_mode = FALSE;
2019   }
2020
2021   return TRUE;
2022 }
2023
2024 static void
2025 gst_qtdemux_reset (GstQTDemux * qtdemux, gboolean hard)
2026 {
2027   gint n;
2028
2029   GST_DEBUG_OBJECT (qtdemux, "Resetting demux");
2030   gst_pad_stop_task (qtdemux->sinkpad);
2031
2032   if (hard || qtdemux->upstream_format_is_time) {
2033     qtdemux->state = QTDEMUX_STATE_INITIAL;
2034     qtdemux->neededbytes = 16;
2035     qtdemux->todrop = 0;
2036     qtdemux->pullbased = FALSE;
2037     qtdemux->posted_redirect = FALSE;
2038     qtdemux->first_mdat = -1;
2039     qtdemux->header_size = 0;
2040     qtdemux->mdatoffset = -1;
2041     qtdemux->restoredata_offset = -1;
2042     if (qtdemux->mdatbuffer)
2043       gst_buffer_unref (qtdemux->mdatbuffer);
2044     if (qtdemux->restoredata_buffer)
2045       gst_buffer_unref (qtdemux->restoredata_buffer);
2046     qtdemux->mdatbuffer = NULL;
2047     qtdemux->restoredata_buffer = NULL;
2048     qtdemux->mdatleft = 0;
2049     qtdemux->mdatsize = 0;
2050     if (qtdemux->comp_brands)
2051       gst_buffer_unref (qtdemux->comp_brands);
2052     qtdemux->comp_brands = NULL;
2053     qtdemux->last_moov_offset = -1;
2054     if (qtdemux->moov_node_compressed) {
2055       g_node_destroy (qtdemux->moov_node_compressed);
2056       if (qtdemux->moov_node)
2057         g_free (qtdemux->moov_node->data);
2058     }
2059     qtdemux->moov_node_compressed = NULL;
2060     if (qtdemux->moov_node)
2061       g_node_destroy (qtdemux->moov_node);
2062     qtdemux->moov_node = NULL;
2063     if (qtdemux->tag_list)
2064       gst_mini_object_unref (GST_MINI_OBJECT_CAST (qtdemux->tag_list));
2065     qtdemux->tag_list = gst_tag_list_new_empty ();
2066     gst_tag_list_set_scope (qtdemux->tag_list, GST_TAG_SCOPE_GLOBAL);
2067 #if 0
2068     if (qtdemux->element_index)
2069       gst_object_unref (qtdemux->element_index);
2070     qtdemux->element_index = NULL;
2071 #endif
2072     qtdemux->major_brand = 0;
2073     if (qtdemux->pending_newsegment)
2074       gst_event_unref (qtdemux->pending_newsegment);
2075     qtdemux->pending_newsegment = NULL;
2076     qtdemux->upstream_format_is_time = FALSE;
2077     qtdemux->upstream_seekable = FALSE;
2078     qtdemux->upstream_size = 0;
2079
2080     qtdemux->fragment_start = -1;
2081     qtdemux->fragment_start_offset = -1;
2082     qtdemux->duration = 0;
2083     qtdemux->moof_offset = 0;
2084     qtdemux->chapters_track_id = 0;
2085     qtdemux->have_group_id = FALSE;
2086     qtdemux->group_id = G_MAXUINT;
2087
2088     g_queue_foreach (&qtdemux->protection_event_queue, (GFunc) gst_event_unref,
2089         NULL);
2090     g_queue_clear (&qtdemux->protection_event_queue);
2091   }
2092   qtdemux->offset = 0;
2093   gst_adapter_clear (qtdemux->adapter);
2094   gst_segment_init (&qtdemux->segment, GST_FORMAT_TIME);
2095   qtdemux->segment_seqnum = 0;
2096
2097   if (hard) {
2098     for (n = 0; n < qtdemux->n_streams; n++) {
2099       gst_qtdemux_stream_free (qtdemux, qtdemux->streams[n]);
2100       qtdemux->streams[n] = NULL;
2101     }
2102     qtdemux->n_streams = 0;
2103     qtdemux->n_video_streams = 0;
2104     qtdemux->n_audio_streams = 0;
2105     qtdemux->n_sub_streams = 0;
2106     qtdemux->exposed = FALSE;
2107     qtdemux->fragmented = FALSE;
2108     qtdemux->mss_mode = FALSE;
2109     gst_caps_replace (&qtdemux->media_caps, NULL);
2110     qtdemux->timescale = 0;
2111     qtdemux->got_moov = FALSE;
2112     if (qtdemux->protection_system_ids) {
2113       g_ptr_array_free (qtdemux->protection_system_ids, TRUE);
2114       qtdemux->protection_system_ids = NULL;
2115     }
2116   } else if (qtdemux->mss_mode) {
2117     gst_flow_combiner_reset (qtdemux->flowcombiner);
2118     for (n = 0; n < qtdemux->n_streams; n++)
2119       gst_qtdemux_stream_clear (qtdemux, qtdemux->streams[n]);
2120   } else {
2121     gst_flow_combiner_reset (qtdemux->flowcombiner);
2122     for (n = 0; n < qtdemux->n_streams; n++) {
2123       qtdemux->streams[n]->sent_eos = FALSE;
2124       qtdemux->streams[n]->time_position = 0;
2125       qtdemux->streams[n]->accumulated_base = 0;
2126     }
2127     if (!qtdemux->pending_newsegment) {
2128       qtdemux->pending_newsegment = gst_event_new_segment (&qtdemux->segment);
2129       if (qtdemux->segment_seqnum)
2130         gst_event_set_seqnum (qtdemux->pending_newsegment,
2131             qtdemux->segment_seqnum);
2132     }
2133   }
2134 }
2135
2136
2137 /* Maps the @segment to the qt edts internal segments and pushes
2138  * the correspnding segment event.
2139  *
2140  * If it ends up being at a empty segment, a gap will be pushed and the next
2141  * edts segment will be activated in sequence.
2142  *
2143  * To be used in push-mode only */
2144 static void
2145 gst_qtdemux_map_and_push_segments (GstQTDemux * qtdemux, GstSegment * segment)
2146 {
2147   gint n, i;
2148
2149   for (n = 0; n < qtdemux->n_streams; n++) {
2150     QtDemuxStream *stream = qtdemux->streams[n];
2151
2152     stream->time_position = segment->start;
2153
2154     /* in push mode we should be guaranteed that we will have empty segments
2155      * at the beginning and then one segment after, other scenarios are not
2156      * supported and are discarded when parsing the edts */
2157     for (i = 0; i < stream->n_segments; i++) {
2158       if (stream->segments[i].stop_time > segment->start) {
2159         gst_qtdemux_activate_segment (qtdemux, stream, i,
2160             stream->time_position);
2161         if (QTSEGMENT_IS_EMPTY (&stream->segments[i])) {
2162           /* push the empty segment and move to the next one */
2163           gst_qtdemux_send_gap_for_segment (qtdemux, stream, i,
2164               stream->time_position);
2165           continue;
2166         }
2167
2168         g_assert (i == stream->n_segments - 1);
2169       }
2170     }
2171   }
2172 }
2173
2174 static gboolean
2175 gst_qtdemux_handle_sink_event (GstPad * sinkpad, GstObject * parent,
2176     GstEvent * event)
2177 {
2178   GstQTDemux *demux = GST_QTDEMUX (parent);
2179   gboolean res = TRUE;
2180
2181   GST_LOG_OBJECT (demux, "handling %s event", GST_EVENT_TYPE_NAME (event));
2182
2183   switch (GST_EVENT_TYPE (event)) {
2184     case GST_EVENT_SEGMENT:
2185     {
2186       gint64 offset = 0;
2187       QtDemuxStream *stream;
2188       gint idx;
2189       GstSegment segment;
2190
2191       /* some debug output */
2192       gst_event_copy_segment (event, &segment);
2193       GST_DEBUG_OBJECT (demux, "received newsegment %" GST_SEGMENT_FORMAT,
2194           &segment);
2195
2196       /* erase any previously set segment */
2197       gst_event_replace (&demux->pending_newsegment, NULL);
2198
2199       if (segment.format == GST_FORMAT_TIME) {
2200         GST_DEBUG_OBJECT (demux, "new pending_newsegment");
2201         gst_event_replace (&demux->pending_newsegment, event);
2202         demux->upstream_format_is_time = TRUE;
2203       } else {
2204         GST_DEBUG_OBJECT (demux, "Not storing upstream newsegment, "
2205             "not in time format");
2206
2207         /* chain will send initial newsegment after pads have been added */
2208         if (demux->state != QTDEMUX_STATE_MOVIE || !demux->n_streams) {
2209           GST_DEBUG_OBJECT (demux, "still starting, eating event");
2210           goto exit;
2211         }
2212       }
2213
2214       /* check if this matches a time seek we received previously
2215        * FIXME for backwards compatibility reasons we use the
2216        * seek_offset here to compare. In the future we might want to
2217        * change this to use the seqnum as it uniquely should identify
2218        * the segment that corresponds to the seek. */
2219       GST_DEBUG_OBJECT (demux, "Stored seek offset: %" G_GINT64_FORMAT
2220           ", received segment offset %" G_GINT64_FORMAT,
2221           demux->seek_offset, segment.start);
2222       if (segment.format == GST_FORMAT_BYTES
2223           && demux->seek_offset == segment.start) {
2224         GST_OBJECT_LOCK (demux);
2225         offset = segment.start;
2226
2227         segment.format = GST_FORMAT_TIME;
2228         segment.start = demux->push_seek_start;
2229         segment.stop = demux->push_seek_stop;
2230         GST_DEBUG_OBJECT (demux, "Replaced segment with stored seek "
2231             "segment %" GST_TIME_FORMAT " - %" GST_TIME_FORMAT,
2232             GST_TIME_ARGS (segment.start), GST_TIME_ARGS (segment.stop));
2233         GST_OBJECT_UNLOCK (demux);
2234       }
2235
2236       /* we only expect a BYTE segment, e.g. following a seek */
2237       if (segment.format == GST_FORMAT_BYTES) {
2238         if (GST_CLOCK_TIME_IS_VALID (segment.start)) {
2239           offset = segment.start;
2240
2241           gst_qtdemux_find_sample (demux, segment.start, TRUE, FALSE, NULL,
2242               NULL, (gint64 *) & segment.start);
2243           if ((gint64) segment.start < 0)
2244             segment.start = 0;
2245         }
2246         if (GST_CLOCK_TIME_IS_VALID (segment.stop)) {
2247           gst_qtdemux_find_sample (demux, segment.stop, FALSE, FALSE, NULL,
2248               NULL, (gint64 *) & segment.stop);
2249           /* keyframe seeking should already arrange for start >= stop,
2250            * but make sure in other rare cases */
2251           segment.stop = MAX (segment.stop, segment.start);
2252         }
2253       } else if (segment.format == GST_FORMAT_TIME) {
2254         /* push all data on the adapter before starting this
2255          * new segment */
2256         gst_qtdemux_process_adapter (demux, TRUE);
2257       } else {
2258         GST_DEBUG_OBJECT (demux, "unsupported segment format, ignoring");
2259         goto exit;
2260       }
2261
2262       /* We shouldn't modify upstream driven TIME FORMAT segment */
2263       if (!demux->upstream_format_is_time) {
2264         /* accept upstream's notion of segment and distribute along */
2265         segment.format = GST_FORMAT_TIME;
2266         segment.position = segment.time = segment.start;
2267         segment.duration = demux->segment.duration;
2268         segment.base = gst_segment_to_running_time (&demux->segment,
2269             GST_FORMAT_TIME, demux->segment.position);
2270       }
2271
2272       gst_segment_copy_into (&segment, &demux->segment);
2273       GST_DEBUG_OBJECT (demux, "Pushing newseg %" GST_SEGMENT_FORMAT, &segment);
2274
2275       /* map segment to internal qt segments and push on each stream */
2276       if (demux->n_streams) {
2277         if (demux->fragmented) {
2278           GstEvent *segment_event = gst_event_new_segment (&segment);
2279
2280           gst_event_replace (&demux->pending_newsegment, NULL);
2281           gst_event_set_seqnum (segment_event, demux->segment_seqnum);
2282           gst_qtdemux_push_event (demux, segment_event);
2283         } else {
2284           gst_event_replace (&demux->pending_newsegment, NULL);
2285           gst_qtdemux_map_and_push_segments (demux, &segment);
2286         }
2287       }
2288
2289       /* clear leftover in current segment, if any */
2290       gst_adapter_clear (demux->adapter);
2291
2292       /* set up streaming thread */
2293       demux->offset = offset;
2294       if (demux->upstream_format_is_time) {
2295         GST_DEBUG_OBJECT (demux, "Upstream is driving in time format, "
2296             "set values to restart reading from a new atom");
2297         demux->neededbytes = 16;
2298         demux->todrop = 0;
2299       } else {
2300         gst_qtdemux_find_sample (demux, offset, TRUE, TRUE, &stream, &idx,
2301             NULL);
2302         if (stream) {
2303           demux->todrop = stream->samples[idx].offset - offset;
2304           demux->neededbytes = demux->todrop + stream->samples[idx].size;
2305         } else {
2306           /* set up for EOS */
2307           demux->neededbytes = -1;
2308           demux->todrop = 0;
2309         }
2310       }
2311     exit:
2312       gst_event_unref (event);
2313       res = TRUE;
2314       goto drop;
2315     }
2316     case GST_EVENT_FLUSH_START:
2317     {
2318       if (gst_event_get_seqnum (event) == demux->offset_seek_seqnum) {
2319         gst_event_unref (event);
2320         goto drop;
2321       }
2322       break;
2323     }
2324     case GST_EVENT_FLUSH_STOP:
2325     {
2326       guint64 dur;
2327
2328       dur = demux->segment.duration;
2329       gst_qtdemux_reset (demux, FALSE);
2330       demux->segment.duration = dur;
2331
2332       if (gst_event_get_seqnum (event) == demux->offset_seek_seqnum) {
2333         gst_event_unref (event);
2334         goto drop;
2335       }
2336       break;
2337     }
2338     case GST_EVENT_EOS:
2339       /* If we are in push mode, and get an EOS before we've seen any streams,
2340        * then error out - we have nowhere to send the EOS */
2341       if (!demux->pullbased) {
2342         gint i;
2343         gboolean has_valid_stream = FALSE;
2344         for (i = 0; i < demux->n_streams; i++) {
2345           if (demux->streams[i]->pad != NULL) {
2346             has_valid_stream = TRUE;
2347             break;
2348           }
2349         }
2350         if (!has_valid_stream)
2351           gst_qtdemux_post_no_playable_stream_error (demux);
2352         else {
2353           GST_DEBUG_OBJECT (demux, "Data still available after EOS: %u",
2354               (guint) gst_adapter_available (demux->adapter));
2355           if (gst_qtdemux_process_adapter (demux, TRUE) != GST_FLOW_OK) {
2356             res = FALSE;
2357           }
2358         }
2359       }
2360       break;
2361     case GST_EVENT_CAPS:{
2362       GstCaps *caps = NULL;
2363
2364       gst_event_parse_caps (event, &caps);
2365       gst_qtdemux_setcaps (demux, caps);
2366       res = TRUE;
2367       gst_event_unref (event);
2368       goto drop;
2369     }
2370     case GST_EVENT_PROTECTION:
2371     {
2372       const gchar *system_id = NULL;
2373
2374       gst_event_parse_protection (event, &system_id, NULL, NULL);
2375       GST_DEBUG_OBJECT (demux, "Received protection event for system ID %s",
2376           system_id);
2377       gst_qtdemux_append_protection_system_id (demux, system_id);
2378       /* save the event for later, for source pads that have not been created */
2379       g_queue_push_tail (&demux->protection_event_queue, gst_event_ref (event));
2380       /* send it to all pads that already exist */
2381       gst_qtdemux_push_event (demux, event);
2382       res = TRUE;
2383       goto drop;
2384     }
2385     default:
2386       break;
2387   }
2388
2389   res = gst_pad_event_default (demux->sinkpad, parent, event) & res;
2390
2391 drop:
2392   return res;
2393 }
2394
2395 #if 0
2396 static void
2397 gst_qtdemux_set_index (GstElement * element, GstIndex * index)
2398 {
2399   GstQTDemux *demux = GST_QTDEMUX (element);
2400
2401   GST_OBJECT_LOCK (demux);
2402   if (demux->element_index)
2403     gst_object_unref (demux->element_index);
2404   if (index) {
2405     demux->element_index = gst_object_ref (index);
2406   } else {
2407     demux->element_index = NULL;
2408   }
2409   GST_OBJECT_UNLOCK (demux);
2410   /* object lock might be taken again */
2411   if (index)
2412     gst_index_get_writer_id (index, GST_OBJECT (element), &demux->index_id);
2413   GST_DEBUG_OBJECT (demux, "Set index %" GST_PTR_FORMAT "for writer id %d",
2414       demux->element_index, demux->index_id);
2415 }
2416
2417 static GstIndex *
2418 gst_qtdemux_get_index (GstElement * element)
2419 {
2420   GstIndex *result = NULL;
2421   GstQTDemux *demux = GST_QTDEMUX (element);
2422
2423   GST_OBJECT_LOCK (demux);
2424   if (demux->element_index)
2425     result = gst_object_ref (demux->element_index);
2426   GST_OBJECT_UNLOCK (demux);
2427
2428   GST_DEBUG_OBJECT (demux, "Returning index %" GST_PTR_FORMAT, result);
2429
2430   return result;
2431 }
2432 #endif
2433
2434 static void
2435 gst_qtdemux_stbl_free (QtDemuxStream * stream)
2436 {
2437   g_free ((gpointer) stream->stco.data);
2438   stream->stco.data = NULL;
2439   g_free ((gpointer) stream->stsz.data);
2440   stream->stsz.data = NULL;
2441   g_free ((gpointer) stream->stsc.data);
2442   stream->stsc.data = NULL;
2443   g_free ((gpointer) stream->stts.data);
2444   stream->stts.data = NULL;
2445   g_free ((gpointer) stream->stss.data);
2446   stream->stss.data = NULL;
2447   g_free ((gpointer) stream->stps.data);
2448   stream->stps.data = NULL;
2449   g_free ((gpointer) stream->ctts.data);
2450   stream->ctts.data = NULL;
2451 }
2452
2453 static void
2454 gst_qtdemux_stream_flush_segments_data (GstQTDemux * qtdemux,
2455     QtDemuxStream * stream)
2456 {
2457   g_free (stream->segments);
2458   stream->segments = NULL;
2459   stream->segment_index = -1;
2460   stream->accumulated_base = 0;
2461 }
2462
2463 static void
2464 gst_qtdemux_stream_flush_samples_data (GstQTDemux * qtdemux,
2465     QtDemuxStream * stream)
2466 {
2467   g_free (stream->samples);
2468   stream->samples = NULL;
2469   gst_qtdemux_stbl_free (stream);
2470
2471   /* fragments */
2472   g_free (stream->ra_entries);
2473   stream->ra_entries = NULL;
2474   stream->n_ra_entries = 0;
2475
2476   stream->sample_index = -1;
2477   stream->stbl_index = -1;
2478   stream->n_samples = 0;
2479   stream->time_position = 0;
2480
2481   stream->n_samples_moof = 0;
2482   stream->duration_moof = 0;
2483   stream->duration_last_moof = 0;
2484 }
2485
2486 static void
2487 gst_qtdemux_stream_clear (GstQTDemux * qtdemux, QtDemuxStream * stream)
2488 {
2489   gint i;
2490   if (stream->allocator)
2491     gst_object_unref (stream->allocator);
2492   while (stream->buffers) {
2493     gst_buffer_unref (GST_BUFFER_CAST (stream->buffers->data));
2494     stream->buffers = g_slist_delete_link (stream->buffers, stream->buffers);
2495   }
2496   for (i = 0; i < stream->stsd_entries_length; i++) {
2497     QtDemuxStreamStsdEntry *entry = &stream->stsd_entries[i];
2498     if (entry->rgb8_palette) {
2499       gst_memory_unref (entry->rgb8_palette);
2500       entry->rgb8_palette = NULL;
2501     }
2502     entry->sparse = FALSE;
2503   }
2504
2505   gst_tag_list_unref (stream->stream_tags);
2506   stream->stream_tags = gst_tag_list_new_empty ();
2507   gst_tag_list_set_scope (stream->stream_tags, GST_TAG_SCOPE_STREAM);
2508   g_free (stream->redirect_uri);
2509   stream->redirect_uri = NULL;
2510   stream->sent_eos = FALSE;
2511   stream->protected = FALSE;
2512   if (stream->protection_scheme_info) {
2513     if (stream->protection_scheme_type == FOURCC_cenc) {
2514       QtDemuxCencSampleSetInfo *info =
2515           (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
2516       if (info->default_properties)
2517         gst_structure_free (info->default_properties);
2518       if (info->crypto_info)
2519         g_ptr_array_free (info->crypto_info, TRUE);
2520     }
2521     g_free (stream->protection_scheme_info);
2522     stream->protection_scheme_info = NULL;
2523   }
2524   stream->protection_scheme_type = 0;
2525   stream->protection_scheme_version = 0;
2526   g_queue_foreach (&stream->protection_scheme_event_queue,
2527       (GFunc) gst_event_unref, NULL);
2528   g_queue_clear (&stream->protection_scheme_event_queue);
2529   gst_qtdemux_stream_flush_segments_data (qtdemux, stream);
2530   gst_qtdemux_stream_flush_samples_data (qtdemux, stream);
2531 }
2532
2533 static void
2534 gst_qtdemux_stream_free (GstQTDemux * qtdemux, QtDemuxStream * stream)
2535 {
2536   gint i;
2537   gst_qtdemux_stream_clear (qtdemux, stream);
2538   for (i = 0; i < stream->stsd_entries_length; i++) {
2539     QtDemuxStreamStsdEntry *entry = &stream->stsd_entries[i];
2540     if (entry->caps) {
2541       gst_caps_unref (entry->caps);
2542       entry->caps = NULL;
2543     }
2544   }
2545   gst_tag_list_unref (stream->stream_tags);
2546   if (stream->pad) {
2547     gst_element_remove_pad (GST_ELEMENT_CAST (qtdemux), stream->pad);
2548     gst_flow_combiner_remove_pad (qtdemux->flowcombiner, stream->pad);
2549   }
2550   g_free (stream->stsd_entries);
2551   g_free (stream);
2552 }
2553
2554 static void
2555 gst_qtdemux_remove_stream (GstQTDemux * qtdemux, int i)
2556 {
2557   g_assert (i >= 0 && i < qtdemux->n_streams && qtdemux->streams[i] != NULL);
2558
2559   gst_qtdemux_stream_free (qtdemux, qtdemux->streams[i]);
2560   qtdemux->streams[i] = qtdemux->streams[qtdemux->n_streams - 1];
2561   qtdemux->streams[qtdemux->n_streams - 1] = NULL;
2562   qtdemux->n_streams--;
2563 }
2564
2565 static GstStateChangeReturn
2566 gst_qtdemux_change_state (GstElement * element, GstStateChange transition)
2567 {
2568   GstQTDemux *qtdemux = GST_QTDEMUX (element);
2569   GstStateChangeReturn result = GST_STATE_CHANGE_FAILURE;
2570
2571   switch (transition) {
2572     case GST_STATE_CHANGE_PAUSED_TO_READY:
2573       break;
2574     default:
2575       break;
2576   }
2577
2578   result = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
2579
2580   switch (transition) {
2581     case GST_STATE_CHANGE_PAUSED_TO_READY:{
2582       gst_qtdemux_reset (qtdemux, TRUE);
2583       break;
2584     }
2585     default:
2586       break;
2587   }
2588
2589   return result;
2590 }
2591
2592 static void
2593 qtdemux_parse_ftyp (GstQTDemux * qtdemux, const guint8 * buffer, gint length)
2594 {
2595   /* counts as header data */
2596   qtdemux->header_size += length;
2597
2598   /* only consider at least a sufficiently complete ftyp atom */
2599   if (length >= 20) {
2600     GstBuffer *buf;
2601
2602     qtdemux->major_brand = QT_FOURCC (buffer + 8);
2603     GST_DEBUG_OBJECT (qtdemux, "major brand: %" GST_FOURCC_FORMAT,
2604         GST_FOURCC_ARGS (qtdemux->major_brand));
2605     if (qtdemux->comp_brands)
2606       gst_buffer_unref (qtdemux->comp_brands);
2607     buf = qtdemux->comp_brands = gst_buffer_new_and_alloc (length - 16);
2608     gst_buffer_fill (buf, 0, buffer + 16, length - 16);
2609   }
2610 }
2611
2612 static void
2613 qtdemux_handle_xmp_taglist (GstQTDemux * qtdemux, GstTagList * taglist,
2614     GstTagList * xmptaglist)
2615 {
2616   /* Strip out bogus fields */
2617   if (xmptaglist) {
2618     if (gst_tag_list_get_scope (taglist) == GST_TAG_SCOPE_GLOBAL) {
2619       gst_tag_list_remove_tag (xmptaglist, GST_TAG_VIDEO_CODEC);
2620       gst_tag_list_remove_tag (xmptaglist, GST_TAG_AUDIO_CODEC);
2621     } else {
2622       gst_tag_list_remove_tag (xmptaglist, GST_TAG_CONTAINER_FORMAT);
2623     }
2624
2625     GST_DEBUG_OBJECT (qtdemux, "Found XMP tags %" GST_PTR_FORMAT, xmptaglist);
2626
2627     /* prioritize native tags using _KEEP mode */
2628     gst_tag_list_insert (taglist, xmptaglist, GST_TAG_MERGE_KEEP);
2629     gst_tag_list_unref (xmptaglist);
2630   }
2631 }
2632
2633 static void
2634 qtdemux_parse_piff (GstQTDemux * qtdemux, const guint8 * buffer, gint length,
2635     guint offset)
2636 {
2637   GstByteReader br;
2638   guint8 version;
2639   guint32 flags = 0;
2640   guint i;
2641   guint8 iv_size = 8;
2642   QtDemuxStream *stream;
2643   GstStructure *structure;
2644   QtDemuxCencSampleSetInfo *ss_info = NULL;
2645   const gchar *system_id;
2646   gboolean uses_sub_sample_encryption = FALSE;
2647
2648   if (qtdemux->n_streams == 0)
2649     return;
2650
2651   stream = qtdemux->streams[0];
2652
2653   structure = gst_caps_get_structure (CUR_STREAM (stream)->caps, 0);
2654   if (!gst_structure_has_name (structure, "application/x-cenc")) {
2655     GST_WARNING_OBJECT (qtdemux,
2656         "Attempting PIFF box parsing on an unencrypted stream.");
2657     return;
2658   }
2659
2660   gst_structure_get (structure, GST_PROTECTION_SYSTEM_ID_CAPS_FIELD,
2661       G_TYPE_STRING, &system_id, NULL);
2662   gst_qtdemux_append_protection_system_id (qtdemux, system_id);
2663
2664   stream->protected = TRUE;
2665   stream->protection_scheme_type = FOURCC_cenc;
2666
2667   if (!stream->protection_scheme_info)
2668     stream->protection_scheme_info = g_new0 (QtDemuxCencSampleSetInfo, 1);
2669
2670   ss_info = (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
2671
2672   if (ss_info->default_properties)
2673     gst_structure_free (ss_info->default_properties);
2674
2675   ss_info->default_properties =
2676       gst_structure_new ("application/x-cenc",
2677       "iv_size", G_TYPE_UINT, iv_size, "encrypted", G_TYPE_BOOLEAN, TRUE, NULL);
2678
2679   if (ss_info->crypto_info) {
2680     GST_LOG_OBJECT (qtdemux, "unreffing existing crypto_info");
2681     g_ptr_array_free (ss_info->crypto_info, TRUE);
2682     ss_info->crypto_info = NULL;
2683   }
2684
2685   /* skip UUID */
2686   gst_byte_reader_init (&br, buffer + offset + 16, length - offset - 16);
2687
2688   if (!gst_byte_reader_get_uint8 (&br, &version)) {
2689     GST_ERROR_OBJECT (qtdemux, "Error getting box's version field");
2690     return;
2691   }
2692
2693   if (!gst_byte_reader_get_uint24_be (&br, &flags)) {
2694     GST_ERROR_OBJECT (qtdemux, "Error getting box's flags field");
2695     return;
2696   }
2697
2698   if ((flags & 0x000001)) {
2699     guint32 algorithm_id = 0;
2700     const guint8 *kid;
2701     GstBuffer *kid_buf;
2702     gboolean is_encrypted = TRUE;
2703
2704     if (!gst_byte_reader_get_uint24_le (&br, &algorithm_id)) {
2705       GST_ERROR_OBJECT (qtdemux, "Error getting box's algorithm ID field");
2706       return;
2707     }
2708
2709     algorithm_id >>= 8;
2710     if (algorithm_id == 0) {
2711       is_encrypted = FALSE;
2712     } else if (algorithm_id == 1) {
2713       /* FIXME: maybe store this in properties? */
2714       GST_DEBUG_OBJECT (qtdemux, "AES 128-bits CTR encrypted stream");
2715     } else if (algorithm_id == 2) {
2716       /* FIXME: maybe store this in properties? */
2717       GST_DEBUG_OBJECT (qtdemux, "AES 128-bits CBC encrypted stream");
2718     }
2719
2720     if (!gst_byte_reader_get_uint8 (&br, &iv_size))
2721       return;
2722
2723     if (!gst_byte_reader_get_data (&br, 16, &kid))
2724       return;
2725
2726     kid_buf = gst_buffer_new_allocate (NULL, 16, NULL);
2727     gst_buffer_fill (kid_buf, 0, kid, 16);
2728     if (ss_info->default_properties)
2729       gst_structure_free (ss_info->default_properties);
2730     ss_info->default_properties =
2731         gst_structure_new ("application/x-cenc",
2732         "iv_size", G_TYPE_UINT, iv_size,
2733         "encrypted", G_TYPE_BOOLEAN, is_encrypted,
2734         "kid", GST_TYPE_BUFFER, kid_buf, NULL);
2735     GST_DEBUG_OBJECT (qtdemux, "default sample properties: "
2736         "is_encrypted=%u, iv_size=%u", is_encrypted, iv_size);
2737     gst_buffer_unref (kid_buf);
2738   } else if ((flags & 0x000002)) {
2739     uses_sub_sample_encryption = TRUE;
2740   }
2741
2742   if (!gst_byte_reader_get_uint32_be (&br, &qtdemux->cenc_aux_sample_count)) {
2743     GST_ERROR_OBJECT (qtdemux, "Error getting box's sample count field");
2744     return;
2745   }
2746
2747   ss_info->crypto_info =
2748       g_ptr_array_new_full (qtdemux->cenc_aux_sample_count,
2749       (GDestroyNotify) qtdemux_gst_structure_free);
2750
2751   for (i = 0; i < qtdemux->cenc_aux_sample_count; ++i) {
2752     GstStructure *properties;
2753     guint8 *data;
2754     GstBuffer *buf;
2755
2756     properties = qtdemux_get_cenc_sample_properties (qtdemux, stream, i);
2757     if (properties == NULL) {
2758       GST_ERROR_OBJECT (qtdemux, "failed to get properties for sample %u", i);
2759       return;
2760     }
2761
2762     if (!gst_byte_reader_dup_data (&br, iv_size, &data)) {
2763       GST_ERROR_OBJECT (qtdemux, "IV data not present for sample %u", i);
2764       gst_structure_free (properties);
2765       return;
2766     }
2767     buf = gst_buffer_new_wrapped (data, iv_size);
2768     gst_structure_set (properties, "iv", GST_TYPE_BUFFER, buf, NULL);
2769     gst_buffer_unref (buf);
2770
2771     if (uses_sub_sample_encryption) {
2772       guint16 n_subsamples;
2773
2774       if (!gst_byte_reader_get_uint16_be (&br, &n_subsamples)
2775           || n_subsamples == 0) {
2776         GST_ERROR_OBJECT (qtdemux,
2777             "failed to get subsample count for sample %u", i);
2778         gst_structure_free (properties);
2779         return;
2780       }
2781       GST_LOG_OBJECT (qtdemux, "subsample count: %u", n_subsamples);
2782       if (!gst_byte_reader_dup_data (&br, n_subsamples * 6, &data)) {
2783         GST_ERROR_OBJECT (qtdemux, "failed to get subsample data for sample %u",
2784             i);
2785         gst_structure_free (properties);
2786         return;
2787       }
2788       buf = gst_buffer_new_wrapped (data, n_subsamples * 6);
2789       gst_structure_set (properties,
2790           "subsample_count", G_TYPE_UINT, n_subsamples,
2791           "subsamples", GST_TYPE_BUFFER, buf, NULL);
2792       gst_buffer_unref (buf);
2793     } else {
2794       gst_structure_set (properties, "subsample_count", G_TYPE_UINT, 0, NULL);
2795     }
2796
2797     g_ptr_array_add (ss_info->crypto_info, properties);
2798   }
2799 }
2800
2801 static void
2802 qtdemux_parse_uuid (GstQTDemux * qtdemux, const guint8 * buffer, gint length)
2803 {
2804   static const guint8 xmp_uuid[] = { 0xBE, 0x7A, 0xCF, 0xCB,
2805     0x97, 0xA9, 0x42, 0xE8,
2806     0x9C, 0x71, 0x99, 0x94,
2807     0x91, 0xE3, 0xAF, 0xAC
2808   };
2809   static const guint8 playready_uuid[] = {
2810     0xd0, 0x8a, 0x4f, 0x18, 0x10, 0xf3, 0x4a, 0x82,
2811     0xb6, 0xc8, 0x32, 0xd8, 0xab, 0xa1, 0x83, 0xd3
2812   };
2813
2814   static const guint8 piff_sample_encryption_uuid[] = {
2815     0xa2, 0x39, 0x4f, 0x52, 0x5a, 0x9b, 0x4f, 0x14,
2816     0xa2, 0x44, 0x6c, 0x42, 0x7c, 0x64, 0x8d, 0xf4
2817   };
2818
2819   guint offset;
2820
2821   /* counts as header data */
2822   qtdemux->header_size += length;
2823
2824   offset = (QT_UINT32 (buffer) == 0) ? 16 : 8;
2825
2826   if (length <= offset + 16) {
2827     GST_DEBUG_OBJECT (qtdemux, "uuid atom is too short, skipping");
2828     return;
2829   }
2830
2831   if (memcmp (buffer + offset, xmp_uuid, 16) == 0) {
2832     GstBuffer *buf;
2833     GstTagList *taglist;
2834
2835     buf = _gst_buffer_new_wrapped ((guint8 *) buffer + offset + 16,
2836         length - offset - 16, NULL);
2837     taglist = gst_tag_list_from_xmp_buffer (buf);
2838     gst_buffer_unref (buf);
2839
2840     /* make sure we have a usable taglist */
2841     qtdemux->tag_list = gst_tag_list_make_writable (qtdemux->tag_list);
2842
2843     qtdemux_handle_xmp_taglist (qtdemux, qtdemux->tag_list, taglist);
2844
2845   } else if (memcmp (buffer + offset, playready_uuid, 16) == 0) {
2846     int len;
2847     const gunichar2 *s_utf16;
2848     char *contents;
2849
2850     len = GST_READ_UINT16_LE (buffer + offset + 0x30);
2851     s_utf16 = (const gunichar2 *) (buffer + offset + 0x32);
2852     contents = g_utf16_to_utf8 (s_utf16, len / 2, NULL, NULL, NULL);
2853     GST_ERROR_OBJECT (qtdemux, "contents: %s", contents);
2854
2855     g_free (contents);
2856
2857     GST_ELEMENT_ERROR (qtdemux, STREAM, DECRYPT,
2858         (_("Cannot play stream because it is encrypted with PlayReady DRM.")),
2859         (NULL));
2860   } else if (memcmp (buffer + offset, piff_sample_encryption_uuid, 16) == 0) {
2861     qtdemux_parse_piff (qtdemux, buffer, length, offset);
2862   } else {
2863     GST_DEBUG_OBJECT (qtdemux, "Ignoring unknown uuid: %08x-%08x-%08x-%08x",
2864         GST_READ_UINT32_LE (buffer + offset),
2865         GST_READ_UINT32_LE (buffer + offset + 4),
2866         GST_READ_UINT32_LE (buffer + offset + 8),
2867         GST_READ_UINT32_LE (buffer + offset + 12));
2868   }
2869 }
2870
2871 static void
2872 qtdemux_parse_sidx (GstQTDemux * qtdemux, const guint8 * buffer, gint length)
2873 {
2874   GstSidxParser sidx_parser;
2875   GstIsoffParserResult res;
2876   guint consumed;
2877
2878   gst_isoff_qt_sidx_parser_init (&sidx_parser);
2879
2880   res =
2881       gst_isoff_qt_sidx_parser_add_data (&sidx_parser, buffer, length,
2882       &consumed);
2883   GST_DEBUG_OBJECT (qtdemux, "sidx parse result: %d", res);
2884   if (res == GST_ISOFF_QT_PARSER_DONE) {
2885     check_update_duration (qtdemux, sidx_parser.cumulative_pts);
2886   }
2887   gst_isoff_qt_sidx_parser_clear (&sidx_parser);
2888 }
2889
2890 /* caller verifies at least 8 bytes in buf */
2891 static void
2892 extract_initial_length_and_fourcc (const guint8 * data, guint size,
2893     guint64 * plength, guint32 * pfourcc)
2894 {
2895   guint64 length;
2896   guint32 fourcc;
2897
2898   length = QT_UINT32 (data);
2899   GST_DEBUG ("length 0x%08" G_GINT64_MODIFIER "x", length);
2900   fourcc = QT_FOURCC (data + 4);
2901   GST_DEBUG ("atom type %" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (fourcc));
2902
2903   if (length == 0) {
2904     length = G_MAXUINT64;
2905   } else if (length == 1 && size >= 16) {
2906     /* this means we have an extended size, which is the 64 bit value of
2907      * the next 8 bytes */
2908     length = QT_UINT64 (data + 8);
2909     GST_DEBUG ("length 0x%08" G_GINT64_MODIFIER "x", length);
2910   }
2911
2912   if (plength)
2913     *plength = length;
2914   if (pfourcc)
2915     *pfourcc = fourcc;
2916 }
2917
2918 static gboolean
2919 qtdemux_parse_mehd (GstQTDemux * qtdemux, GstByteReader * br)
2920 {
2921   guint32 version = 0;
2922   GstClockTime duration = 0;
2923
2924   if (!gst_byte_reader_get_uint32_be (br, &version))
2925     goto failed;
2926
2927   version >>= 24;
2928   if (version == 1) {
2929     if (!gst_byte_reader_get_uint64_be (br, &duration))
2930       goto failed;
2931   } else {
2932     guint32 dur = 0;
2933
2934     if (!gst_byte_reader_get_uint32_be (br, &dur))
2935       goto failed;
2936     duration = dur;
2937   }
2938
2939   GST_INFO_OBJECT (qtdemux, "mehd duration: %" G_GUINT64_FORMAT, duration);
2940   qtdemux->duration = duration;
2941
2942   return TRUE;
2943
2944 failed:
2945   {
2946     GST_DEBUG_OBJECT (qtdemux, "parsing mehd failed");
2947     return FALSE;
2948   }
2949 }
2950
2951 static gboolean
2952 qtdemux_parse_trex (GstQTDemux * qtdemux, QtDemuxStream * stream,
2953     guint32 * ds_duration, guint32 * ds_size, guint32 * ds_flags)
2954 {
2955   if (!stream->parsed_trex && qtdemux->moov_node) {
2956     GNode *mvex, *trex;
2957     GstByteReader trex_data;
2958
2959     mvex = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_mvex);
2960     if (mvex) {
2961       trex = qtdemux_tree_get_child_by_type_full (mvex, FOURCC_trex,
2962           &trex_data);
2963       while (trex) {
2964         guint32 id = 0, sdi = 0, dur = 0, size = 0, flags = 0;
2965
2966         /* skip version/flags */
2967         if (!gst_byte_reader_skip (&trex_data, 4))
2968           goto next;
2969         if (!gst_byte_reader_get_uint32_be (&trex_data, &id))
2970           goto next;
2971         if (id != stream->track_id)
2972           goto next;
2973         if (!gst_byte_reader_get_uint32_be (&trex_data, &sdi))
2974           goto next;
2975         if (!gst_byte_reader_get_uint32_be (&trex_data, &dur))
2976           goto next;
2977         if (!gst_byte_reader_get_uint32_be (&trex_data, &size))
2978           goto next;
2979         if (!gst_byte_reader_get_uint32_be (&trex_data, &flags))
2980           goto next;
2981
2982         GST_DEBUG_OBJECT (qtdemux, "fragment defaults for stream %d; "
2983             "duration %d,  size %d, flags 0x%x", stream->track_id,
2984             dur, size, flags);
2985
2986         stream->parsed_trex = TRUE;
2987         stream->def_sample_description_index = sdi;
2988         stream->def_sample_duration = dur;
2989         stream->def_sample_size = size;
2990         stream->def_sample_flags = flags;
2991
2992       next:
2993         /* iterate all siblings */
2994         trex = qtdemux_tree_get_sibling_by_type_full (trex, FOURCC_trex,
2995             &trex_data);
2996       }
2997     }
2998   }
2999
3000   *ds_duration = stream->def_sample_duration;
3001   *ds_size = stream->def_sample_size;
3002   *ds_flags = stream->def_sample_flags;
3003
3004   /* even then, above values are better than random ... */
3005   if (G_UNLIKELY (!stream->parsed_trex)) {
3006     GST_WARNING_OBJECT (qtdemux,
3007         "failed to find fragment defaults for stream %d", stream->track_id);
3008     return FALSE;
3009   }
3010
3011   return TRUE;
3012 }
3013
3014 /* This method should be called whenever a more accurate duration might
3015  * have been found. It will update all relevant variables if/where needed
3016  */
3017 static void
3018 check_update_duration (GstQTDemux * qtdemux, GstClockTime duration)
3019 {
3020   guint i;
3021   guint64 movdur;
3022   GstClockTime prevdur;
3023
3024   movdur = GSTTIME_TO_QTTIME (qtdemux, duration);
3025
3026   if (movdur > qtdemux->duration) {
3027     prevdur = QTTIME_TO_GSTTIME (qtdemux, qtdemux->duration);
3028     GST_DEBUG_OBJECT (qtdemux,
3029         "Updating total duration to %" GST_TIME_FORMAT " was %" GST_TIME_FORMAT,
3030         GST_TIME_ARGS (duration), GST_TIME_ARGS (prevdur));
3031     qtdemux->duration = movdur;
3032     GST_DEBUG_OBJECT (qtdemux,
3033         "qtdemux->segment.duration: %" GST_TIME_FORMAT " .stop: %"
3034         GST_TIME_FORMAT, GST_TIME_ARGS (qtdemux->segment.duration),
3035         GST_TIME_ARGS (qtdemux->segment.stop));
3036     if (qtdemux->segment.duration == prevdur) {
3037       /* If the current segment has duration/stop identical to previous duration
3038        * update them also (because they were set at that point in time with
3039        * the wrong duration */
3040       /* We convert the value *from* the timescale version to avoid rounding errors */
3041       GstClockTime fixeddur = QTTIME_TO_GSTTIME (qtdemux, movdur);
3042       GST_DEBUG_OBJECT (qtdemux, "Updated segment.duration and segment.stop");
3043       qtdemux->segment.duration = fixeddur;
3044       qtdemux->segment.stop = fixeddur;
3045     }
3046   }
3047   for (i = 0; i < qtdemux->n_streams; i++) {
3048     QtDemuxStream *stream = qtdemux->streams[i];
3049     if (stream) {
3050       movdur = GSTTIME_TO_QTSTREAMTIME (stream, duration);
3051       if (movdur > stream->duration) {
3052         GST_DEBUG_OBJECT (qtdemux,
3053             "Updating stream #%d duration to %" GST_TIME_FORMAT, i,
3054             GST_TIME_ARGS (duration));
3055         stream->duration = movdur;
3056         if (stream->dummy_segment) {
3057           /* Update all dummy values to new duration */
3058           stream->segments[0].stop_time = duration;
3059           stream->segments[0].duration = duration;
3060           stream->segments[0].media_stop = duration;
3061
3062           /* let downstream know we possibly have a new stop time */
3063           if (stream->segment_index != -1) {
3064             GstClockTime pos;
3065
3066             if (qtdemux->segment.rate >= 0) {
3067               pos = stream->segment.start;
3068             } else {
3069               pos = stream->segment.stop;
3070             }
3071
3072             gst_qtdemux_stream_update_segment (qtdemux, stream,
3073                 stream->segment_index, pos, NULL, NULL);
3074           }
3075         }
3076       }
3077     }
3078   }
3079 }
3080
3081 static gboolean
3082 qtdemux_parse_trun (GstQTDemux * qtdemux, GstByteReader * trun,
3083     QtDemuxStream * stream, guint32 d_sample_duration, guint32 d_sample_size,
3084     guint32 d_sample_flags, gint64 moof_offset, gint64 moof_length,
3085     gint64 * base_offset, gint64 * running_offset, gint64 decode_ts,
3086     gboolean has_tfdt)
3087 {
3088   GstClockTime gst_ts = GST_CLOCK_TIME_NONE;
3089   guint64 timestamp;
3090   gint32 data_offset = 0;
3091   guint32 flags = 0, first_flags = 0, samples_count = 0;
3092   gint i;
3093   guint8 *data;
3094   guint entry_size, dur_offset, size_offset, flags_offset = 0, ct_offset = 0;
3095   QtDemuxSample *sample;
3096   gboolean ismv = FALSE;
3097   gint64 initial_offset;
3098
3099   GST_LOG_OBJECT (qtdemux, "parsing trun stream %d; "
3100       "default dur %d, size %d, flags 0x%x, base offset %" G_GINT64_FORMAT ", "
3101       "decode ts %" G_GINT64_FORMAT, stream->track_id, d_sample_duration,
3102       d_sample_size, d_sample_flags, *base_offset, decode_ts);
3103
3104   if (stream->pending_seek && moof_offset < stream->pending_seek->moof_offset) {
3105     GST_INFO_OBJECT (stream->pad, "skipping trun before seek target fragment");
3106     return TRUE;
3107   }
3108
3109   /* presence of stss or not can't really tell us much,
3110    * and flags and so on tend to be marginally reliable in these files */
3111   if (stream->subtype == FOURCC_soun) {
3112     GST_DEBUG_OBJECT (qtdemux,
3113         "sound track in fragmented file; marking all keyframes");
3114     stream->all_keyframe = TRUE;
3115   }
3116
3117   if (!gst_byte_reader_skip (trun, 1) ||
3118       !gst_byte_reader_get_uint24_be (trun, &flags))
3119     goto fail;
3120
3121   if (!gst_byte_reader_get_uint32_be (trun, &samples_count))
3122     goto fail;
3123
3124   if (flags & TR_DATA_OFFSET) {
3125     /* note this is really signed */
3126     if (!gst_byte_reader_get_int32_be (trun, &data_offset))
3127       goto fail;
3128     GST_LOG_OBJECT (qtdemux, "trun data offset %d", data_offset);
3129     /* default base offset = first byte of moof */
3130     if (*base_offset == -1) {
3131       GST_LOG_OBJECT (qtdemux, "base_offset at moof");
3132       *base_offset = moof_offset;
3133     }
3134     *running_offset = *base_offset + data_offset;
3135   } else {
3136     /* if no offset at all, that would mean data starts at moof start,
3137      * which is a bit wrong and is ismv crappy way, so compensate
3138      * assuming data is in mdat following moof */
3139     if (*base_offset == -1) {
3140       *base_offset = moof_offset + moof_length + 8;
3141       GST_LOG_OBJECT (qtdemux, "base_offset assumed in mdat after moof");
3142       ismv = TRUE;
3143     }
3144     if (*running_offset == -1)
3145       *running_offset = *base_offset;
3146   }
3147
3148   GST_LOG_OBJECT (qtdemux, "running offset now %" G_GINT64_FORMAT,
3149       *running_offset);
3150   GST_LOG_OBJECT (qtdemux, "trun offset %d, flags 0x%x, entries %d",
3151       data_offset, flags, samples_count);
3152
3153   if (flags & TR_FIRST_SAMPLE_FLAGS) {
3154     if (G_UNLIKELY (flags & TR_SAMPLE_FLAGS)) {
3155       GST_DEBUG_OBJECT (qtdemux,
3156           "invalid flags; SAMPLE and FIRST_SAMPLE present, discarding latter");
3157       flags ^= TR_FIRST_SAMPLE_FLAGS;
3158     } else {
3159       if (!gst_byte_reader_get_uint32_be (trun, &first_flags))
3160         goto fail;
3161       GST_LOG_OBJECT (qtdemux, "first flags: 0x%x", first_flags);
3162     }
3163   }
3164
3165   /* FIXME ? spec says other bits should also be checked to determine
3166    * entry size (and prefix size for that matter) */
3167   entry_size = 0;
3168   dur_offset = size_offset = 0;
3169   if (flags & TR_SAMPLE_DURATION) {
3170     GST_LOG_OBJECT (qtdemux, "entry duration present");
3171     dur_offset = entry_size;
3172     entry_size += 4;
3173   }
3174   if (flags & TR_SAMPLE_SIZE) {
3175     GST_LOG_OBJECT (qtdemux, "entry size present");
3176     size_offset = entry_size;
3177     entry_size += 4;
3178   }
3179   if (flags & TR_SAMPLE_FLAGS) {
3180     GST_LOG_OBJECT (qtdemux, "entry flags present");
3181     flags_offset = entry_size;
3182     entry_size += 4;
3183   }
3184   if (flags & TR_COMPOSITION_TIME_OFFSETS) {
3185     GST_LOG_OBJECT (qtdemux, "entry ct offset present");
3186     ct_offset = entry_size;
3187     entry_size += 4;
3188   }
3189
3190   if (!qt_atom_parser_has_chunks (trun, samples_count, entry_size))
3191     goto fail;
3192   data = (guint8 *) gst_byte_reader_peek_data_unchecked (trun);
3193
3194   if (stream->n_samples + samples_count >=
3195       QTDEMUX_MAX_SAMPLE_INDEX_SIZE / sizeof (QtDemuxSample))
3196     goto index_too_big;
3197
3198   GST_DEBUG_OBJECT (qtdemux, "allocating n_samples %u * %u (%.2f MB)",
3199       stream->n_samples + samples_count, (guint) sizeof (QtDemuxSample),
3200       (stream->n_samples + samples_count) *
3201       sizeof (QtDemuxSample) / (1024.0 * 1024.0));
3202
3203   /* create a new array of samples if it's the first sample parsed */
3204   if (stream->n_samples == 0) {
3205     g_assert (stream->samples == NULL);
3206     stream->samples = g_try_new0 (QtDemuxSample, samples_count);
3207     /* or try to reallocate it with space enough to insert the new samples */
3208   } else
3209     stream->samples = g_try_renew (QtDemuxSample, stream->samples,
3210         stream->n_samples + samples_count);
3211   if (stream->samples == NULL)
3212     goto out_of_memory;
3213
3214   if (qtdemux->fragment_start != -1) {
3215     timestamp = GSTTIME_TO_QTSTREAMTIME (stream, qtdemux->fragment_start);
3216     qtdemux->fragment_start = -1;
3217   } else {
3218     if (stream->n_samples == 0) {
3219       if (decode_ts > 0) {
3220         timestamp = decode_ts;
3221       } else if (stream->pending_seek != NULL) {
3222         /* if we don't have a timestamp from a tfdt box, we'll use the one
3223          * from the mfra seek table */
3224         GST_INFO_OBJECT (stream->pad, "pending seek ts = %" GST_TIME_FORMAT,
3225             GST_TIME_ARGS (stream->pending_seek->ts));
3226
3227         /* FIXME: this is not fully correct, the timestamp refers to the random
3228          * access sample refered to in the tfra entry, which may not necessarily
3229          * be the first sample in the tfrag/trun (but hopefully/usually is) */
3230         timestamp = GSTTIME_TO_QTSTREAMTIME (stream, stream->pending_seek->ts);
3231       } else {
3232         timestamp = 0;
3233       }
3234
3235       gst_ts = QTSTREAMTIME_TO_GSTTIME (stream, timestamp);
3236       GST_INFO_OBJECT (stream->pad, "first sample ts %" GST_TIME_FORMAT,
3237           GST_TIME_ARGS (gst_ts));
3238     } else {
3239       /* subsequent fragments extend stream */
3240       timestamp =
3241           stream->samples[stream->n_samples - 1].timestamp +
3242           stream->samples[stream->n_samples - 1].duration;
3243
3244       /* If this is a GST_FORMAT_BYTES stream and there's a significant
3245        * difference (1 sec.) between decode_ts and timestamp, prefer the
3246        * former */
3247       if (has_tfdt && !qtdemux->upstream_format_is_time
3248           && ABSDIFF (decode_ts, timestamp) >
3249           MAX (stream->duration_last_moof / 2,
3250               GSTTIME_TO_QTSTREAMTIME (stream, GST_SECOND))) {
3251         GST_INFO_OBJECT (qtdemux,
3252             "decode_ts (%" GST_TIME_FORMAT ") and timestamp (%" GST_TIME_FORMAT
3253             ") are significantly different (more than %" GST_TIME_FORMAT
3254             "), using decode_ts",
3255             GST_TIME_ARGS (QTSTREAMTIME_TO_GSTTIME (stream, decode_ts)),
3256             GST_TIME_ARGS (QTSTREAMTIME_TO_GSTTIME (stream, timestamp)),
3257             GST_TIME_ARGS (QTSTREAMTIME_TO_GSTTIME (stream,
3258                     MAX (stream->duration_last_moof / 2,
3259                         GSTTIME_TO_QTSTREAMTIME (stream, GST_SECOND)))));
3260         timestamp = decode_ts;
3261       }
3262
3263       gst_ts = QTSTREAMTIME_TO_GSTTIME (stream, timestamp);
3264       GST_INFO_OBJECT (qtdemux, "first sample ts %" GST_TIME_FORMAT
3265           " (extends previous samples)", GST_TIME_ARGS (gst_ts));
3266     }
3267   }
3268
3269   initial_offset = *running_offset;
3270
3271   sample = stream->samples + stream->n_samples;
3272   for (i = 0; i < samples_count; i++) {
3273     guint32 dur, size, sflags, ct;
3274
3275     /* first read sample data */
3276     if (flags & TR_SAMPLE_DURATION) {
3277       dur = QT_UINT32 (data + dur_offset);
3278     } else {
3279       dur = d_sample_duration;
3280     }
3281     if (flags & TR_SAMPLE_SIZE) {
3282       size = QT_UINT32 (data + size_offset);
3283     } else {
3284       size = d_sample_size;
3285     }
3286     if (flags & TR_FIRST_SAMPLE_FLAGS) {
3287       if (i == 0) {
3288         sflags = first_flags;
3289       } else {
3290         sflags = d_sample_flags;
3291       }
3292     } else if (flags & TR_SAMPLE_FLAGS) {
3293       sflags = QT_UINT32 (data + flags_offset);
3294     } else {
3295       sflags = d_sample_flags;
3296     }
3297     if (flags & TR_COMPOSITION_TIME_OFFSETS) {
3298       ct = QT_UINT32 (data + ct_offset);
3299     } else {
3300       ct = 0;
3301     }
3302     data += entry_size;
3303
3304     /* fill the sample information */
3305     sample->offset = *running_offset;
3306     sample->pts_offset = ct;
3307     sample->size = size;
3308     sample->timestamp = timestamp;
3309     sample->duration = dur;
3310     /* sample-is-difference-sample */
3311     /* ismv seems to use 0x40 for keyframe, 0xc0 for non-keyframe,
3312      * now idea how it relates to bitfield other than massive LE/BE confusion */
3313     sample->keyframe = ismv ? ((sflags & 0xff) == 0x40) : !(sflags & 0x10000);
3314     *running_offset += size;
3315     timestamp += dur;
3316     stream->duration_moof += dur;
3317     sample++;
3318   }
3319
3320   /* Update total duration if needed */
3321   check_update_duration (qtdemux, QTSTREAMTIME_TO_GSTTIME (stream, timestamp));
3322
3323   /* Pre-emptively figure out size of mdat based on trun information.
3324    * If the [mdat] atom is effectivelly read, it will be replaced by the actual
3325    * size, else we will still be able to use this when dealing with gap'ed
3326    * input */
3327   qtdemux->mdatleft = *running_offset - initial_offset;
3328   qtdemux->mdatoffset = initial_offset;
3329   qtdemux->mdatsize = qtdemux->mdatleft;
3330
3331   stream->n_samples += samples_count;
3332   stream->n_samples_moof += samples_count;
3333
3334   if (stream->pending_seek != NULL)
3335     stream->pending_seek = NULL;
3336
3337   return TRUE;
3338
3339 fail:
3340   {
3341     GST_WARNING_OBJECT (qtdemux, "failed to parse trun");
3342     return FALSE;
3343   }
3344 out_of_memory:
3345   {
3346     GST_WARNING_OBJECT (qtdemux, "failed to allocate %d samples",
3347         stream->n_samples);
3348     return FALSE;
3349   }
3350 index_too_big:
3351   {
3352     GST_WARNING_OBJECT (qtdemux, "not allocating index of %d samples, would "
3353         "be larger than %uMB (broken file?)", stream->n_samples,
3354         QTDEMUX_MAX_SAMPLE_INDEX_SIZE >> 20);
3355     return FALSE;
3356   }
3357 }
3358
3359 /* find stream with @id */
3360 static inline QtDemuxStream *
3361 qtdemux_find_stream (GstQTDemux * qtdemux, guint32 id)
3362 {
3363   QtDemuxStream *stream;
3364   gint i;
3365
3366   /* check */
3367   if (G_UNLIKELY (!id)) {
3368     GST_DEBUG_OBJECT (qtdemux, "invalid track id 0");
3369     return NULL;
3370   }
3371
3372   /* try to get it fast and simple */
3373   if (G_LIKELY (id <= qtdemux->n_streams)) {
3374     stream = qtdemux->streams[id - 1];
3375     if (G_LIKELY (stream->track_id == id))
3376       return stream;
3377   }
3378
3379   /* linear search otherwise */
3380   for (i = 0; i < qtdemux->n_streams; i++) {
3381     stream = qtdemux->streams[i];
3382     if (stream->track_id == id)
3383       return stream;
3384   }
3385   if (qtdemux->mss_mode) {
3386     /* mss should have only 1 stream anyway */
3387     return qtdemux->streams[0];
3388   }
3389
3390   return NULL;
3391 }
3392
3393 static gboolean
3394 qtdemux_parse_mfhd (GstQTDemux * qtdemux, GstByteReader * mfhd,
3395     guint32 * fragment_number)
3396 {
3397   if (!gst_byte_reader_skip (mfhd, 4))
3398     goto fail;
3399   if (!gst_byte_reader_get_uint32_be (mfhd, fragment_number))
3400     goto fail;
3401   return TRUE;
3402 fail:
3403   {
3404     GST_WARNING_OBJECT (qtdemux, "Failed to parse mfhd atom");
3405     return FALSE;
3406   }
3407 }
3408
3409 static gboolean
3410 qtdemux_parse_tfhd (GstQTDemux * qtdemux, GstByteReader * tfhd,
3411     QtDemuxStream ** stream, guint32 * default_sample_duration,
3412     guint32 * default_sample_size, guint32 * default_sample_flags,
3413     gint64 * base_offset)
3414 {
3415   guint32 flags = 0;
3416   guint32 track_id = 0;
3417
3418   if (!gst_byte_reader_skip (tfhd, 1) ||
3419       !gst_byte_reader_get_uint24_be (tfhd, &flags))
3420     goto invalid_track;
3421
3422   if (!gst_byte_reader_get_uint32_be (tfhd, &track_id))
3423     goto invalid_track;
3424
3425   *stream = qtdemux_find_stream (qtdemux, track_id);
3426   if (G_UNLIKELY (!*stream))
3427     goto unknown_stream;
3428
3429   if (flags & TF_DEFAULT_BASE_IS_MOOF)
3430     *base_offset = qtdemux->moof_offset;
3431
3432   if (flags & TF_BASE_DATA_OFFSET)
3433     if (!gst_byte_reader_get_uint64_be (tfhd, (guint64 *) base_offset))
3434       goto invalid_track;
3435
3436   /* obtain stream defaults */
3437   qtdemux_parse_trex (qtdemux, *stream,
3438       default_sample_duration, default_sample_size, default_sample_flags);
3439
3440   (*stream)->stsd_sample_description_id =
3441       (*stream)->def_sample_description_index - 1;
3442
3443   if (flags & TF_SAMPLE_DESCRIPTION_INDEX) {
3444     guint32 sample_description_index;
3445     if (!gst_byte_reader_get_uint32_be (tfhd, &sample_description_index))
3446       goto invalid_track;
3447     (*stream)->stsd_sample_description_id = sample_description_index - 1;
3448   }
3449
3450   if (qtdemux->mss_mode) {
3451     /* mss has no stsd entry */
3452     (*stream)->stsd_sample_description_id = 0;
3453   }
3454
3455   if (flags & TF_DEFAULT_SAMPLE_DURATION)
3456     if (!gst_byte_reader_get_uint32_be (tfhd, default_sample_duration))
3457       goto invalid_track;
3458
3459   if (flags & TF_DEFAULT_SAMPLE_SIZE)
3460     if (!gst_byte_reader_get_uint32_be (tfhd, default_sample_size))
3461       goto invalid_track;
3462
3463   if (flags & TF_DEFAULT_SAMPLE_FLAGS)
3464     if (!gst_byte_reader_get_uint32_be (tfhd, default_sample_flags))
3465       goto invalid_track;
3466
3467   return TRUE;
3468
3469 invalid_track:
3470   {
3471     GST_WARNING_OBJECT (qtdemux, "invalid track fragment header");
3472     return FALSE;
3473   }
3474 unknown_stream:
3475   {
3476     GST_DEBUG_OBJECT (qtdemux, "unknown stream in tfhd");
3477     return TRUE;
3478   }
3479 }
3480
3481 static gboolean
3482 qtdemux_parse_tfdt (GstQTDemux * qtdemux, GstByteReader * br,
3483     guint64 * decode_time)
3484 {
3485   guint32 version = 0;
3486
3487   if (!gst_byte_reader_get_uint32_be (br, &version))
3488     return FALSE;
3489
3490   version >>= 24;
3491   if (version == 1) {
3492     if (!gst_byte_reader_get_uint64_be (br, decode_time))
3493       goto failed;
3494   } else {
3495     guint32 dec_time = 0;
3496     if (!gst_byte_reader_get_uint32_be (br, &dec_time))
3497       goto failed;
3498     *decode_time = dec_time;
3499   }
3500
3501   GST_INFO_OBJECT (qtdemux, "Track fragment decode time: %" G_GUINT64_FORMAT,
3502       *decode_time);
3503
3504   return TRUE;
3505
3506 failed:
3507   {
3508     GST_DEBUG_OBJECT (qtdemux, "parsing tfdt failed");
3509     return FALSE;
3510   }
3511 }
3512
3513 /* Returns a pointer to a GstStructure containing the properties of
3514  * the stream sample identified by @sample_index. The caller must unref
3515  * the returned object after use. Returns NULL if unsuccessful. */
3516 static GstStructure *
3517 qtdemux_get_cenc_sample_properties (GstQTDemux * qtdemux,
3518     QtDemuxStream * stream, guint sample_index)
3519 {
3520   QtDemuxCencSampleSetInfo *info = NULL;
3521
3522   g_return_val_if_fail (stream != NULL, NULL);
3523   g_return_val_if_fail (stream->protected, NULL);
3524   g_return_val_if_fail (stream->protection_scheme_info != NULL, NULL);
3525
3526   info = (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
3527
3528   /* Currently, cenc properties for groups of samples are not supported, so
3529    * simply return a copy of the default sample properties */
3530   return gst_structure_copy (info->default_properties);
3531 }
3532
3533 /* Parses the sizes of sample auxiliary information contained within a stream,
3534  * as given in a saiz box. Returns array of sample_count guint8 size values,
3535  * or NULL on failure */
3536 static guint8 *
3537 qtdemux_parse_saiz (GstQTDemux * qtdemux, QtDemuxStream * stream,
3538     GstByteReader * br, guint32 * sample_count)
3539 {
3540   guint32 flags = 0;
3541   guint8 *info_sizes;
3542   guint8 default_info_size;
3543
3544   g_return_val_if_fail (qtdemux != NULL, NULL);
3545   g_return_val_if_fail (stream != NULL, NULL);
3546   g_return_val_if_fail (br != NULL, NULL);
3547   g_return_val_if_fail (sample_count != NULL, NULL);
3548
3549   if (!gst_byte_reader_get_uint32_be (br, &flags))
3550     return NULL;
3551
3552   if (flags & 0x1) {
3553     /* aux_info_type and aux_info_type_parameter are ignored */
3554     if (!gst_byte_reader_skip (br, 8))
3555       return NULL;
3556   }
3557
3558   if (!gst_byte_reader_get_uint8 (br, &default_info_size))
3559     return NULL;
3560   GST_DEBUG_OBJECT (qtdemux, "default_info_size: %u", default_info_size);
3561
3562   if (!gst_byte_reader_get_uint32_be (br, sample_count))
3563     return NULL;
3564   GST_DEBUG_OBJECT (qtdemux, "sample_count: %u", *sample_count);
3565
3566
3567   if (default_info_size == 0) {
3568     if (!gst_byte_reader_dup_data (br, *sample_count, &info_sizes)) {
3569       return NULL;
3570     }
3571   } else {
3572     info_sizes = g_new (guint8, *sample_count);
3573     memset (info_sizes, default_info_size, *sample_count);
3574   }
3575
3576   return info_sizes;
3577 }
3578
3579 /* Parses the offset of sample auxiliary information contained within a stream,
3580  * as given in a saio box. Returns TRUE if successful; FALSE otherwise. */
3581 static gboolean
3582 qtdemux_parse_saio (GstQTDemux * qtdemux, QtDemuxStream * stream,
3583     GstByteReader * br, guint32 * info_type, guint32 * info_type_parameter,
3584     guint64 * offset)
3585 {
3586   guint8 version = 0;
3587   guint32 flags = 0;
3588   guint32 aux_info_type = 0;
3589   guint32 aux_info_type_parameter = 0;
3590   guint32 entry_count;
3591   guint32 off_32;
3592   guint64 off_64;
3593   const guint8 *aux_info_type_data = NULL;
3594
3595   g_return_val_if_fail (qtdemux != NULL, FALSE);
3596   g_return_val_if_fail (stream != NULL, FALSE);
3597   g_return_val_if_fail (br != NULL, FALSE);
3598   g_return_val_if_fail (offset != NULL, FALSE);
3599
3600   if (!gst_byte_reader_get_uint8 (br, &version))
3601     return FALSE;
3602
3603   if (!gst_byte_reader_get_uint24_be (br, &flags))
3604     return FALSE;
3605
3606   if (flags & 0x1) {
3607
3608     if (!gst_byte_reader_get_data (br, 4, &aux_info_type_data))
3609       return FALSE;
3610     aux_info_type = QT_FOURCC (aux_info_type_data);
3611
3612     if (!gst_byte_reader_get_uint32_be (br, &aux_info_type_parameter))
3613       return FALSE;
3614   } else if (stream->protected) {
3615     aux_info_type = stream->protection_scheme_type;
3616   } else {
3617     aux_info_type = CUR_STREAM (stream)->fourcc;
3618   }
3619
3620   if (info_type)
3621     *info_type = aux_info_type;
3622   if (info_type_parameter)
3623     *info_type_parameter = aux_info_type_parameter;
3624
3625   GST_DEBUG_OBJECT (qtdemux, "aux_info_type: '%" GST_FOURCC_FORMAT "', "
3626       "aux_info_type_parameter:  %#06x",
3627       GST_FOURCC_ARGS (aux_info_type), aux_info_type_parameter);
3628
3629   if (!gst_byte_reader_get_uint32_be (br, &entry_count))
3630     return FALSE;
3631
3632   if (entry_count != 1) {
3633     GST_ERROR_OBJECT (qtdemux, "multiple offsets are not supported");
3634     return FALSE;
3635   }
3636
3637   if (version == 0) {
3638     if (!gst_byte_reader_get_uint32_be (br, &off_32))
3639       return FALSE;
3640     *offset = (guint64) off_32;
3641   } else {
3642     if (!gst_byte_reader_get_uint64_be (br, &off_64))
3643       return FALSE;
3644     *offset = off_64;
3645   }
3646
3647   GST_DEBUG_OBJECT (qtdemux, "offset: %" G_GUINT64_FORMAT, *offset);
3648   return TRUE;
3649 }
3650
3651 static void
3652 qtdemux_gst_structure_free (GstStructure * gststructure)
3653 {
3654   if (gststructure) {
3655     gst_structure_free (gststructure);
3656   }
3657 }
3658
3659 /* Parses auxiliary information relating to samples protected using Common
3660  * Encryption (cenc); the format of this information is defined in
3661  * ISO/IEC 23001-7. Returns TRUE if successful; FALSE otherwise. */
3662 static gboolean
3663 qtdemux_parse_cenc_aux_info (GstQTDemux * qtdemux, QtDemuxStream * stream,
3664     GstByteReader * br, guint8 * info_sizes, guint32 sample_count)
3665 {
3666   QtDemuxCencSampleSetInfo *ss_info = NULL;
3667   guint8 size;
3668   gint i;
3669   GPtrArray *old_crypto_info = NULL;
3670   guint old_entries = 0;
3671
3672   g_return_val_if_fail (qtdemux != NULL, FALSE);
3673   g_return_val_if_fail (stream != NULL, FALSE);
3674   g_return_val_if_fail (br != NULL, FALSE);
3675   g_return_val_if_fail (stream->protected, FALSE);
3676   g_return_val_if_fail (stream->protection_scheme_info != NULL, FALSE);
3677
3678   ss_info = (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
3679
3680   if (ss_info->crypto_info) {
3681     old_crypto_info = ss_info->crypto_info;
3682     /* Count number of non-null entries remaining at the tail end */
3683     for (i = old_crypto_info->len - 1; i >= 0; i--) {
3684       if (g_ptr_array_index (old_crypto_info, i) == NULL)
3685         break;
3686       old_entries++;
3687     }
3688   }
3689
3690   ss_info->crypto_info =
3691       g_ptr_array_new_full (sample_count + old_entries,
3692       (GDestroyNotify) qtdemux_gst_structure_free);
3693
3694   /* We preserve old entries because we parse the next moof in advance
3695    * of consuming all samples from the previous moof, and otherwise
3696    * we'd discard the corresponding crypto info for the samples
3697    * from the previous fragment. */
3698   if (old_entries) {
3699     GST_DEBUG_OBJECT (qtdemux, "Preserving %d old crypto info entries",
3700         old_entries);
3701     for (i = old_crypto_info->len - old_entries; i < old_crypto_info->len; i++) {
3702       g_ptr_array_add (ss_info->crypto_info, g_ptr_array_index (old_crypto_info,
3703               i));
3704       g_ptr_array_index (old_crypto_info, i) = NULL;
3705     }
3706   }
3707
3708   if (old_crypto_info) {
3709     /* Everything now belongs to the new array */
3710     g_ptr_array_free (old_crypto_info, TRUE);
3711   }
3712
3713   for (i = 0; i < sample_count; ++i) {
3714     GstStructure *properties;
3715     guint16 n_subsamples = 0;
3716     guint8 *data;
3717     guint iv_size;
3718     GstBuffer *buf;
3719
3720     properties = qtdemux_get_cenc_sample_properties (qtdemux, stream, i);
3721     if (properties == NULL) {
3722       GST_ERROR_OBJECT (qtdemux, "failed to get properties for sample %u", i);
3723       return FALSE;
3724     }
3725     if (!gst_structure_get_uint (properties, "iv_size", &iv_size)) {
3726       GST_ERROR_OBJECT (qtdemux, "failed to get iv_size for sample %u", i);
3727       gst_structure_free (properties);
3728       return FALSE;
3729     }
3730     if (!gst_byte_reader_dup_data (br, iv_size, &data)) {
3731       GST_ERROR_OBJECT (qtdemux, "failed to get IV for sample %u", i);
3732       gst_structure_free (properties);
3733       return FALSE;
3734     }
3735     buf = gst_buffer_new_wrapped (data, iv_size);
3736     gst_structure_set (properties, "iv", GST_TYPE_BUFFER, buf, NULL);
3737     gst_buffer_unref (buf);
3738     size = info_sizes[i];
3739     if (size > iv_size) {
3740       if (!gst_byte_reader_get_uint16_be (br, &n_subsamples)
3741           || !(n_subsamples > 0)) {
3742         gst_structure_free (properties);
3743         GST_ERROR_OBJECT (qtdemux,
3744             "failed to get subsample count for sample %u", i);
3745         return FALSE;
3746       }
3747       GST_LOG_OBJECT (qtdemux, "subsample count: %u", n_subsamples);
3748       if (!gst_byte_reader_dup_data (br, n_subsamples * 6, &data)) {
3749         GST_ERROR_OBJECT (qtdemux, "failed to get subsample data for sample %u",
3750             i);
3751         gst_structure_free (properties);
3752         return FALSE;
3753       }
3754       buf = gst_buffer_new_wrapped (data, n_subsamples * 6);
3755       if (!buf) {
3756         gst_structure_free (properties);
3757         return FALSE;
3758       }
3759       gst_structure_set (properties,
3760           "subsample_count", G_TYPE_UINT, n_subsamples,
3761           "subsamples", GST_TYPE_BUFFER, buf, NULL);
3762       gst_buffer_unref (buf);
3763     } else {
3764       gst_structure_set (properties, "subsample_count", G_TYPE_UINT, 0, NULL);
3765     }
3766     g_ptr_array_add (ss_info->crypto_info, properties);
3767   }
3768   return TRUE;
3769 }
3770
3771 /* Converts a UUID in raw byte form to a string representation, as defined in
3772  * RFC 4122. The caller takes ownership of the returned string and is
3773  * responsible for freeing it after use. */
3774 static gchar *
3775 qtdemux_uuid_bytes_to_string (gconstpointer uuid_bytes)
3776 {
3777   const guint8 *uuid = (const guint8 *) uuid_bytes;
3778
3779   return g_strdup_printf ("%02x%02x%02x%02x-%02x%02x-%02x%02x-"
3780       "%02x%02x-%02x%02x%02x%02x%02x%02x",
3781       uuid[0], uuid[1], uuid[2], uuid[3],
3782       uuid[4], uuid[5], uuid[6], uuid[7],
3783       uuid[8], uuid[9], uuid[10], uuid[11],
3784       uuid[12], uuid[13], uuid[14], uuid[15]);
3785 }
3786
3787 /* Parses a Protection System Specific Header box (pssh), as defined in the
3788  * Common Encryption (cenc) standard (ISO/IEC 23001-7), which contains
3789  * information needed by a specific content protection system in order to
3790  * decrypt cenc-protected tracks. Returns TRUE if successful; FALSE
3791  * otherwise. */
3792 static gboolean
3793 qtdemux_parse_pssh (GstQTDemux * qtdemux, GNode * node)
3794 {
3795   gchar *sysid_string;
3796   guint32 pssh_size = QT_UINT32 (node->data);
3797   GstBuffer *pssh = NULL;
3798   GstEvent *event = NULL;
3799   guint32 parent_box_type;
3800   gint i;
3801
3802   if (G_UNLIKELY (pssh_size < 32U)) {
3803     GST_ERROR_OBJECT (qtdemux, "invalid box size");
3804     return FALSE;
3805   }
3806
3807   sysid_string =
3808       qtdemux_uuid_bytes_to_string ((const guint8 *) node->data + 12);
3809
3810   gst_qtdemux_append_protection_system_id (qtdemux, sysid_string);
3811
3812   pssh = gst_buffer_new_wrapped (g_memdup (node->data, pssh_size), pssh_size);
3813   GST_LOG_OBJECT (qtdemux, "cenc pssh size: %" G_GSIZE_FORMAT,
3814       gst_buffer_get_size (pssh));
3815
3816   parent_box_type = QT_FOURCC ((const guint8 *) node->parent->data + 4);
3817
3818   /* Push an event containing the pssh box onto the queues of all streams. */
3819   event = gst_event_new_protection (sysid_string, pssh,
3820       (parent_box_type == FOURCC_moov) ? "isobmff/moov" : "isobmff/moof");
3821   for (i = 0; i < qtdemux->n_streams; ++i) {
3822     g_queue_push_tail (&qtdemux->streams[i]->protection_scheme_event_queue,
3823         gst_event_ref (event));
3824   }
3825   g_free (sysid_string);
3826   gst_event_unref (event);
3827   gst_buffer_unref (pssh);
3828   return TRUE;
3829 }
3830
3831 static gboolean
3832 qtdemux_parse_moof (GstQTDemux * qtdemux, const guint8 * buffer, guint length,
3833     guint64 moof_offset, QtDemuxStream * stream)
3834 {
3835   GNode *moof_node, *traf_node, *tfhd_node, *trun_node, *tfdt_node, *mfhd_node;
3836   GNode *uuid_node;
3837   GstByteReader mfhd_data, trun_data, tfhd_data, tfdt_data;
3838   GNode *saiz_node, *saio_node, *pssh_node;
3839   GstByteReader saiz_data, saio_data;
3840   guint32 ds_size = 0, ds_duration = 0, ds_flags = 0;
3841   gint64 base_offset, running_offset;
3842   guint32 frag_num;
3843
3844   /* NOTE @stream ignored */
3845
3846   moof_node = g_node_new ((guint8 *) buffer);
3847   qtdemux_parse_node (qtdemux, moof_node, buffer, length);
3848   qtdemux_node_dump (qtdemux, moof_node);
3849
3850   /* Get fragment number from mfhd and check it's valid */
3851   mfhd_node =
3852       qtdemux_tree_get_child_by_type_full (moof_node, FOURCC_mfhd, &mfhd_data);
3853   if (mfhd_node == NULL)
3854     goto missing_mfhd;
3855   if (!qtdemux_parse_mfhd (qtdemux, &mfhd_data, &frag_num))
3856     goto fail;
3857   GST_DEBUG_OBJECT (qtdemux, "Fragment #%d", frag_num);
3858
3859   /* unknown base_offset to start with */
3860   base_offset = running_offset = -1;
3861   traf_node = qtdemux_tree_get_child_by_type (moof_node, FOURCC_traf);
3862   while (traf_node) {
3863     guint64 decode_time = 0;
3864
3865     /* Fragment Header node */
3866     tfhd_node =
3867         qtdemux_tree_get_child_by_type_full (traf_node, FOURCC_tfhd,
3868         &tfhd_data);
3869     if (!tfhd_node)
3870       goto missing_tfhd;
3871     if (!qtdemux_parse_tfhd (qtdemux, &tfhd_data, &stream, &ds_duration,
3872             &ds_size, &ds_flags, &base_offset))
3873       goto missing_tfhd;
3874
3875     /* The following code assumes at most a single set of sample auxiliary
3876      * data in the fragment (consisting of a saiz box and a corresponding saio
3877      * box); in theory, however, there could be multiple sets of sample
3878      * auxiliary data in a fragment. */
3879     saiz_node =
3880         qtdemux_tree_get_child_by_type_full (traf_node, FOURCC_saiz,
3881         &saiz_data);
3882     if (saiz_node) {
3883       guint32 info_type = 0;
3884       guint64 offset = 0;
3885       guint32 info_type_parameter = 0;
3886
3887       g_free (qtdemux->cenc_aux_info_sizes);
3888
3889       qtdemux->cenc_aux_info_sizes =
3890           qtdemux_parse_saiz (qtdemux, stream, &saiz_data,
3891           &qtdemux->cenc_aux_sample_count);
3892       if (qtdemux->cenc_aux_info_sizes == NULL) {
3893         GST_ERROR_OBJECT (qtdemux, "failed to parse saiz box");
3894         goto fail;
3895       }
3896       saio_node =
3897           qtdemux_tree_get_child_by_type_full (traf_node, FOURCC_saio,
3898           &saio_data);
3899       if (!saio_node) {
3900         GST_ERROR_OBJECT (qtdemux, "saiz box without a corresponding saio box");
3901         g_free (qtdemux->cenc_aux_info_sizes);
3902         qtdemux->cenc_aux_info_sizes = NULL;
3903         goto fail;
3904       }
3905
3906       if (G_UNLIKELY (!qtdemux_parse_saio (qtdemux, stream, &saio_data,
3907                   &info_type, &info_type_parameter, &offset))) {
3908         GST_ERROR_OBJECT (qtdemux, "failed to parse saio box");
3909         g_free (qtdemux->cenc_aux_info_sizes);
3910         qtdemux->cenc_aux_info_sizes = NULL;
3911         goto fail;
3912       }
3913       if (base_offset > -1 && base_offset > qtdemux->moof_offset)
3914         offset += (guint64) (base_offset - qtdemux->moof_offset);
3915       if (info_type == FOURCC_cenc && info_type_parameter == 0U) {
3916         GstByteReader br;
3917         if (offset > length) {
3918           GST_DEBUG_OBJECT (qtdemux, "cenc auxiliary info stored out of moof");
3919           qtdemux->cenc_aux_info_offset = offset;
3920         } else {
3921           gst_byte_reader_init (&br, buffer + offset, length - offset);
3922           if (!qtdemux_parse_cenc_aux_info (qtdemux, stream, &br,
3923                   qtdemux->cenc_aux_info_sizes,
3924                   qtdemux->cenc_aux_sample_count)) {
3925             GST_ERROR_OBJECT (qtdemux, "failed to parse cenc auxiliary info");
3926             g_free (qtdemux->cenc_aux_info_sizes);
3927             qtdemux->cenc_aux_info_sizes = NULL;
3928             goto fail;
3929           }
3930         }
3931       }
3932     }
3933
3934     tfdt_node =
3935         qtdemux_tree_get_child_by_type_full (traf_node, FOURCC_tfdt,
3936         &tfdt_data);
3937     if (tfdt_node) {
3938       /* We'll use decode_time to interpolate timestamps
3939        * in case the input timestamps are missing */
3940       qtdemux_parse_tfdt (qtdemux, &tfdt_data, &decode_time);
3941
3942       GST_DEBUG_OBJECT (qtdemux, "decode time %" G_GINT64_FORMAT
3943           " (%" GST_TIME_FORMAT ")", decode_time,
3944           GST_TIME_ARGS (stream ? QTSTREAMTIME_TO_GSTTIME (stream,
3945                   decode_time) : GST_CLOCK_TIME_NONE));
3946
3947       /* Discard the fragment buffer timestamp info to avoid using it.
3948        * Rely on tfdt instead as it is more accurate than the timestamp
3949        * that is fetched from a manifest/playlist and is usually
3950        * less accurate. */
3951       qtdemux->fragment_start = -1;
3952     }
3953
3954     if (G_UNLIKELY (!stream)) {
3955       /* we lost track of offset, we'll need to regain it,
3956        * but can delay complaining until later or avoid doing so altogether */
3957       base_offset = -2;
3958       goto next;
3959     }
3960     if (G_UNLIKELY (base_offset < -1))
3961       goto lost_offset;
3962
3963     if (qtdemux->upstream_format_is_time)
3964       gst_qtdemux_stream_flush_samples_data (qtdemux, stream);
3965
3966     /* initialise moof sample data */
3967     stream->n_samples_moof = 0;
3968     stream->duration_last_moof = stream->duration_moof;
3969     stream->duration_moof = 0;
3970
3971     /* Track Run node */
3972     trun_node =
3973         qtdemux_tree_get_child_by_type_full (traf_node, FOURCC_trun,
3974         &trun_data);
3975     while (trun_node) {
3976       qtdemux_parse_trun (qtdemux, &trun_data, stream,
3977           ds_duration, ds_size, ds_flags, moof_offset, length, &base_offset,
3978           &running_offset, decode_time, (tfdt_node != NULL));
3979       /* iterate all siblings */
3980       trun_node = qtdemux_tree_get_sibling_by_type_full (trun_node, FOURCC_trun,
3981           &trun_data);
3982     }
3983
3984     uuid_node = qtdemux_tree_get_child_by_type (traf_node, FOURCC_uuid);
3985     if (uuid_node) {
3986       guint8 *uuid_buffer = (guint8 *) uuid_node->data;
3987       guint32 box_length = QT_UINT32 (uuid_buffer);
3988
3989       qtdemux_parse_uuid (qtdemux, uuid_buffer, box_length);
3990     }
3991
3992     /* if no new base_offset provided for next traf,
3993      * base is end of current traf */
3994     base_offset = running_offset;
3995     running_offset = -1;
3996
3997     if (stream->n_samples_moof && stream->duration_moof)
3998       stream->new_caps = TRUE;
3999
4000   next:
4001     /* iterate all siblings */
4002     traf_node = qtdemux_tree_get_sibling_by_type (traf_node, FOURCC_traf);
4003   }
4004
4005   /* parse any protection system info */
4006   pssh_node = qtdemux_tree_get_child_by_type (moof_node, FOURCC_pssh);
4007   while (pssh_node) {
4008     GST_LOG_OBJECT (qtdemux, "Parsing pssh box.");
4009     qtdemux_parse_pssh (qtdemux, pssh_node);
4010     pssh_node = qtdemux_tree_get_sibling_by_type (pssh_node, FOURCC_pssh);
4011   }
4012
4013   g_node_destroy (moof_node);
4014   return TRUE;
4015
4016 missing_tfhd:
4017   {
4018     GST_DEBUG_OBJECT (qtdemux, "missing tfhd box");
4019     goto fail;
4020   }
4021 missing_mfhd:
4022   {
4023     GST_DEBUG_OBJECT (qtdemux, "Missing mfhd box");
4024     goto fail;
4025   }
4026 lost_offset:
4027   {
4028     GST_DEBUG_OBJECT (qtdemux, "lost offset");
4029     goto fail;
4030   }
4031 fail:
4032   {
4033     g_node_destroy (moof_node);
4034     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
4035         (_("This file is corrupt and cannot be played.")), (NULL));
4036     return FALSE;
4037   }
4038 }
4039
4040 #if 0
4041 /* might be used if some day we actually use mfra & co
4042  * for random access to fragments,
4043  * but that will require quite some modifications and much less relying
4044  * on a sample array */
4045 #endif
4046
4047 static gboolean
4048 qtdemux_parse_tfra (GstQTDemux * qtdemux, GNode * tfra_node)
4049 {
4050   QtDemuxStream *stream;
4051   guint32 ver_flags, track_id, len, num_entries, i;
4052   guint value_size, traf_size, trun_size, sample_size;
4053   guint64 time = 0, moof_offset = 0;
4054 #if 0
4055   GstBuffer *buf = NULL;
4056   GstFlowReturn ret;
4057 #endif
4058   GstByteReader tfra;
4059
4060   gst_byte_reader_init (&tfra, tfra_node->data, QT_UINT32 (tfra_node->data));
4061
4062   if (!gst_byte_reader_skip (&tfra, 8))
4063     return FALSE;
4064
4065   if (!gst_byte_reader_get_uint32_be (&tfra, &ver_flags))
4066     return FALSE;
4067
4068   if (!gst_byte_reader_get_uint32_be (&tfra, &track_id)
4069       || !gst_byte_reader_get_uint32_be (&tfra, &len)
4070       || !gst_byte_reader_get_uint32_be (&tfra, &num_entries))
4071     return FALSE;
4072
4073   GST_DEBUG_OBJECT (qtdemux, "parsing tfra box for track id %u", track_id);
4074
4075   stream = qtdemux_find_stream (qtdemux, track_id);
4076   if (stream == NULL)
4077     goto unknown_trackid;
4078
4079   value_size = ((ver_flags >> 24) == 1) ? sizeof (guint64) : sizeof (guint32);
4080   sample_size = (len & 3) + 1;
4081   trun_size = ((len & 12) >> 2) + 1;
4082   traf_size = ((len & 48) >> 4) + 1;
4083
4084   GST_DEBUG_OBJECT (qtdemux, "%u entries, sizes: value %u, traf %u, trun %u, "
4085       "sample %u", num_entries, value_size, traf_size, trun_size, sample_size);
4086
4087   if (num_entries == 0)
4088     goto no_samples;
4089
4090   if (!qt_atom_parser_has_chunks (&tfra, num_entries,
4091           value_size + value_size + traf_size + trun_size + sample_size))
4092     goto corrupt_file;
4093
4094   g_free (stream->ra_entries);
4095   stream->ra_entries = g_new (QtDemuxRandomAccessEntry, num_entries);
4096   stream->n_ra_entries = num_entries;
4097
4098   for (i = 0; i < num_entries; i++) {
4099     qt_atom_parser_get_offset (&tfra, value_size, &time);
4100     qt_atom_parser_get_offset (&tfra, value_size, &moof_offset);
4101     qt_atom_parser_get_uint_with_size_unchecked (&tfra, traf_size);
4102     qt_atom_parser_get_uint_with_size_unchecked (&tfra, trun_size);
4103     qt_atom_parser_get_uint_with_size_unchecked (&tfra, sample_size);
4104
4105     time = QTSTREAMTIME_TO_GSTTIME (stream, time);
4106
4107     GST_LOG_OBJECT (qtdemux, "fragment time: %" GST_TIME_FORMAT ", "
4108         " moof_offset: %" G_GUINT64_FORMAT, GST_TIME_ARGS (time), moof_offset);
4109
4110     stream->ra_entries[i].ts = time;
4111     stream->ra_entries[i].moof_offset = moof_offset;
4112
4113     /* don't want to go through the entire file and read all moofs at startup */
4114 #if 0
4115     ret = gst_qtdemux_pull_atom (qtdemux, moof_offset, 0, &buf);
4116     if (ret != GST_FLOW_OK)
4117       goto corrupt_file;
4118     qtdemux_parse_moof (qtdemux, GST_BUFFER_DATA (buf), GST_BUFFER_SIZE (buf),
4119         moof_offset, stream);
4120     gst_buffer_unref (buf);
4121 #endif
4122   }
4123
4124   check_update_duration (qtdemux, time);
4125
4126   return TRUE;
4127
4128 /* ERRORS */
4129 unknown_trackid:
4130   {
4131     GST_WARNING_OBJECT (qtdemux, "Couldn't find stream for track %u", track_id);
4132     return FALSE;
4133   }
4134 corrupt_file:
4135   {
4136     GST_WARNING_OBJECT (qtdemux, "broken traf box, ignoring");
4137     return FALSE;
4138   }
4139 no_samples:
4140   {
4141     GST_WARNING_OBJECT (qtdemux, "stream has no samples");
4142     return FALSE;
4143   }
4144 }
4145
4146 static gboolean
4147 qtdemux_pull_mfro_mfra (GstQTDemux * qtdemux)
4148 {
4149   GstMapInfo mfro_map = GST_MAP_INFO_INIT;
4150   GstMapInfo mfra_map = GST_MAP_INFO_INIT;
4151   GstBuffer *mfro = NULL, *mfra = NULL;
4152   GstFlowReturn flow;
4153   gboolean ret = FALSE;
4154   GNode *mfra_node, *tfra_node;
4155   guint64 mfra_offset = 0;
4156   guint32 fourcc, mfra_size;
4157   gint64 len;
4158
4159   /* query upstream size in bytes */
4160   if (!gst_pad_peer_query_duration (qtdemux->sinkpad, GST_FORMAT_BYTES, &len))
4161     goto size_query_failed;
4162
4163   /* mfro box should be at the very end of the file */
4164   flow = gst_qtdemux_pull_atom (qtdemux, len - 16, 16, &mfro);
4165   if (flow != GST_FLOW_OK)
4166     goto exit;
4167
4168   gst_buffer_map (mfro, &mfro_map, GST_MAP_READ);
4169
4170   fourcc = QT_FOURCC (mfro_map.data + 4);
4171   if (fourcc != FOURCC_mfro)
4172     goto exit;
4173
4174   GST_INFO_OBJECT (qtdemux, "Found mfro box");
4175   if (mfro_map.size < 16)
4176     goto invalid_mfro_size;
4177
4178   mfra_size = QT_UINT32 (mfro_map.data + 12);
4179   if (mfra_size >= len)
4180     goto invalid_mfra_size;
4181
4182   mfra_offset = len - mfra_size;
4183
4184   GST_INFO_OBJECT (qtdemux, "mfra offset: %" G_GUINT64_FORMAT ", size %u",
4185       mfra_offset, mfra_size);
4186
4187   /* now get and parse mfra box */
4188   flow = gst_qtdemux_pull_atom (qtdemux, mfra_offset, mfra_size, &mfra);
4189   if (flow != GST_FLOW_OK)
4190     goto broken_file;
4191
4192   gst_buffer_map (mfra, &mfra_map, GST_MAP_READ);
4193
4194   mfra_node = g_node_new ((guint8 *) mfra_map.data);
4195   qtdemux_parse_node (qtdemux, mfra_node, mfra_map.data, mfra_map.size);
4196
4197   tfra_node = qtdemux_tree_get_child_by_type (mfra_node, FOURCC_tfra);
4198
4199   while (tfra_node) {
4200     qtdemux_parse_tfra (qtdemux, tfra_node);
4201     /* iterate all siblings */
4202     tfra_node = qtdemux_tree_get_sibling_by_type (tfra_node, FOURCC_tfra);
4203   }
4204   g_node_destroy (mfra_node);
4205
4206   GST_INFO_OBJECT (qtdemux, "parsed movie fragment random access box (mfra)");
4207   ret = TRUE;
4208
4209 exit:
4210
4211   if (mfro) {
4212     if (mfro_map.memory != NULL)
4213       gst_buffer_unmap (mfro, &mfro_map);
4214     gst_buffer_unref (mfro);
4215   }
4216   if (mfra) {
4217     if (mfra_map.memory != NULL)
4218       gst_buffer_unmap (mfra, &mfra_map);
4219     gst_buffer_unref (mfra);
4220   }
4221   return ret;
4222
4223 /* ERRORS */
4224 size_query_failed:
4225   {
4226     GST_WARNING_OBJECT (qtdemux, "could not query upstream size");
4227     goto exit;
4228   }
4229 invalid_mfro_size:
4230   {
4231     GST_WARNING_OBJECT (qtdemux, "mfro size is too small");
4232     goto exit;
4233   }
4234 invalid_mfra_size:
4235   {
4236     GST_WARNING_OBJECT (qtdemux, "mfra_size in mfro box is invalid");
4237     goto exit;
4238   }
4239 broken_file:
4240   {
4241     GST_WARNING_OBJECT (qtdemux, "bogus mfra offset or size, broken file");
4242     goto exit;
4243   }
4244 }
4245
4246 static guint64
4247 add_offset (guint64 offset, guint64 advance)
4248 {
4249   /* Avoid 64-bit overflow by clamping */
4250   if (offset > G_MAXUINT64 - advance)
4251     return G_MAXUINT64;
4252   return offset + advance;
4253 }
4254
4255 static GstFlowReturn
4256 gst_qtdemux_loop_state_header (GstQTDemux * qtdemux)
4257 {
4258   guint64 length = 0;
4259   guint32 fourcc = 0;
4260   GstBuffer *buf = NULL;
4261   GstFlowReturn ret = GST_FLOW_OK;
4262   guint64 cur_offset = qtdemux->offset;
4263   GstMapInfo map;
4264
4265   ret = gst_pad_pull_range (qtdemux->sinkpad, cur_offset, 16, &buf);
4266   if (G_UNLIKELY (ret != GST_FLOW_OK))
4267     goto beach;
4268   gst_buffer_map (buf, &map, GST_MAP_READ);
4269   if (G_LIKELY (map.size >= 8))
4270     extract_initial_length_and_fourcc (map.data, map.size, &length, &fourcc);
4271   gst_buffer_unmap (buf, &map);
4272   gst_buffer_unref (buf);
4273
4274   /* maybe we already got most we needed, so only consider this eof */
4275   if (G_UNLIKELY (length == 0)) {
4276     GST_ELEMENT_WARNING (qtdemux, STREAM, DEMUX,
4277         (_("Invalid atom size.")),
4278         ("Header atom '%" GST_FOURCC_FORMAT "' has empty length",
4279             GST_FOURCC_ARGS (fourcc)));
4280     ret = GST_FLOW_EOS;
4281     goto beach;
4282   }
4283
4284   switch (fourcc) {
4285     case FOURCC_moof:
4286       /* record for later parsing when needed */
4287       if (!qtdemux->moof_offset) {
4288         qtdemux->moof_offset = qtdemux->offset;
4289       }
4290       if (qtdemux_pull_mfro_mfra (qtdemux)) {
4291         /* FIXME */
4292       } else {
4293         qtdemux->offset += length;      /* skip moof and keep going */
4294       }
4295       if (qtdemux->got_moov) {
4296         GST_INFO_OBJECT (qtdemux, "moof header, got moov, done with headers");
4297         ret = GST_FLOW_EOS;
4298         goto beach;
4299       }
4300       break;
4301     case FOURCC_mdat:
4302     case FOURCC_free:
4303     case FOURCC_skip:
4304     case FOURCC_wide:
4305     case FOURCC_PICT:
4306     case FOURCC_pnot:
4307     {
4308       GST_LOG_OBJECT (qtdemux,
4309           "skipping atom '%" GST_FOURCC_FORMAT "' at %" G_GUINT64_FORMAT,
4310           GST_FOURCC_ARGS (fourcc), cur_offset);
4311       qtdemux->offset = add_offset (qtdemux->offset, length);
4312       break;
4313     }
4314     case FOURCC_moov:
4315     {
4316       GstBuffer *moov = NULL;
4317
4318       if (qtdemux->got_moov) {
4319         GST_DEBUG_OBJECT (qtdemux, "Skipping moov atom as we have one already");
4320         qtdemux->offset = add_offset (qtdemux->offset, length);
4321         goto beach;
4322       }
4323
4324       ret = gst_pad_pull_range (qtdemux->sinkpad, cur_offset, length, &moov);
4325       if (ret != GST_FLOW_OK)
4326         goto beach;
4327       gst_buffer_map (moov, &map, GST_MAP_READ);
4328
4329       if (length != map.size) {
4330         /* Some files have a 'moov' atom at the end of the file which contains
4331          * a terminal 'free' atom where the body of the atom is missing.
4332          * Check for, and permit, this special case.
4333          */
4334         if (map.size >= 8) {
4335           guint8 *final_data = map.data + (map.size - 8);
4336           guint32 final_length = QT_UINT32 (final_data);
4337           guint32 final_fourcc = QT_FOURCC (final_data + 4);
4338
4339           if (final_fourcc == FOURCC_free
4340               && map.size + final_length - 8 == length) {
4341             /* Ok, we've found that special case. Allocate a new buffer with
4342              * that free atom actually present. */
4343             GstBuffer *newmoov = gst_buffer_new_and_alloc (length);
4344             gst_buffer_fill (newmoov, 0, map.data, map.size);
4345             gst_buffer_memset (newmoov, map.size, 0, final_length - 8);
4346             gst_buffer_unmap (moov, &map);
4347             gst_buffer_unref (moov);
4348             moov = newmoov;
4349             gst_buffer_map (moov, &map, GST_MAP_READ);
4350           }
4351         }
4352       }
4353
4354       if (length != map.size) {
4355         GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
4356             (_("This file is incomplete and cannot be played.")),
4357             ("We got less than expected (received %" G_GSIZE_FORMAT
4358                 ", wanted %u, offset %" G_GUINT64_FORMAT ")", map.size,
4359                 (guint) length, cur_offset));
4360         gst_buffer_unmap (moov, &map);
4361         gst_buffer_unref (moov);
4362         ret = GST_FLOW_ERROR;
4363         goto beach;
4364       }
4365       qtdemux->offset += length;
4366
4367       qtdemux_parse_moov (qtdemux, map.data, length);
4368       qtdemux_node_dump (qtdemux, qtdemux->moov_node);
4369
4370       qtdemux_parse_tree (qtdemux);
4371       if (qtdemux->moov_node_compressed) {
4372         g_node_destroy (qtdemux->moov_node_compressed);
4373         g_free (qtdemux->moov_node->data);
4374       }
4375       qtdemux->moov_node_compressed = NULL;
4376       g_node_destroy (qtdemux->moov_node);
4377       qtdemux->moov_node = NULL;
4378       gst_buffer_unmap (moov, &map);
4379       gst_buffer_unref (moov);
4380       qtdemux->got_moov = TRUE;
4381
4382       break;
4383     }
4384     case FOURCC_ftyp:
4385     {
4386       GstBuffer *ftyp = NULL;
4387
4388       /* extract major brand; might come in handy for ISO vs QT issues */
4389       ret = gst_qtdemux_pull_atom (qtdemux, cur_offset, length, &ftyp);
4390       if (ret != GST_FLOW_OK)
4391         goto beach;
4392       qtdemux->offset += length;
4393       gst_buffer_map (ftyp, &map, GST_MAP_READ);
4394       qtdemux_parse_ftyp (qtdemux, map.data, map.size);
4395       gst_buffer_unmap (ftyp, &map);
4396       gst_buffer_unref (ftyp);
4397       break;
4398     }
4399     case FOURCC_uuid:
4400     {
4401       GstBuffer *uuid = NULL;
4402
4403       /* uuid are extension atoms */
4404       ret = gst_qtdemux_pull_atom (qtdemux, cur_offset, length, &uuid);
4405       if (ret != GST_FLOW_OK)
4406         goto beach;
4407       qtdemux->offset += length;
4408       gst_buffer_map (uuid, &map, GST_MAP_READ);
4409       qtdemux_parse_uuid (qtdemux, map.data, map.size);
4410       gst_buffer_unmap (uuid, &map);
4411       gst_buffer_unref (uuid);
4412       break;
4413     }
4414     case FOURCC_sidx:
4415     {
4416       GstBuffer *sidx = NULL;
4417       ret = gst_qtdemux_pull_atom (qtdemux, cur_offset, length, &sidx);
4418       if (ret != GST_FLOW_OK)
4419         goto beach;
4420       qtdemux->offset += length;
4421       gst_buffer_map (sidx, &map, GST_MAP_READ);
4422       qtdemux_parse_sidx (qtdemux, map.data, map.size);
4423       gst_buffer_unmap (sidx, &map);
4424       gst_buffer_unref (sidx);
4425       break;
4426     }
4427     default:
4428     {
4429       GstBuffer *unknown = NULL;
4430
4431       GST_LOG_OBJECT (qtdemux,
4432           "unknown %08x '%" GST_FOURCC_FORMAT "' of size %" G_GUINT64_FORMAT
4433           " at %" G_GUINT64_FORMAT, fourcc, GST_FOURCC_ARGS (fourcc), length,
4434           cur_offset);
4435       ret = gst_qtdemux_pull_atom (qtdemux, cur_offset, length, &unknown);
4436       if (ret != GST_FLOW_OK)
4437         goto beach;
4438       gst_buffer_map (unknown, &map, GST_MAP_READ);
4439       GST_MEMDUMP ("Unknown tag", map.data, map.size);
4440       gst_buffer_unmap (unknown, &map);
4441       gst_buffer_unref (unknown);
4442       qtdemux->offset += length;
4443       break;
4444     }
4445   }
4446
4447 beach:
4448   if (ret == GST_FLOW_EOS && (qtdemux->got_moov || qtdemux->media_caps)) {
4449     /* digested all data, show what we have */
4450     qtdemux_prepare_streams (qtdemux);
4451     ret = qtdemux_expose_streams (qtdemux);
4452
4453     qtdemux->state = QTDEMUX_STATE_MOVIE;
4454     GST_DEBUG_OBJECT (qtdemux, "switching state to STATE_MOVIE (%d)",
4455         qtdemux->state);
4456     return ret;
4457   }
4458   return ret;
4459 }
4460
4461 /* Seeks to the previous keyframe of the indexed stream and
4462  * aligns other streams with respect to the keyframe timestamp
4463  * of indexed stream. Only called in case of Reverse Playback
4464  */
4465 static GstFlowReturn
4466 gst_qtdemux_seek_to_previous_keyframe (GstQTDemux * qtdemux)
4467 {
4468   guint8 n = 0;
4469   guint32 seg_idx = 0, k_index = 0;
4470   guint32 ref_seg_idx, ref_k_index;
4471   GstClockTime k_pos = 0, last_stop = 0;
4472   QtDemuxSegment *seg = NULL;
4473   QtDemuxStream *ref_str = NULL;
4474   guint64 seg_media_start_mov;  /* segment media start time in mov format */
4475   guint64 target_ts;
4476
4477   /* Now we choose an arbitrary stream, get the previous keyframe timestamp
4478    * and finally align all the other streams on that timestamp with their
4479    * respective keyframes */
4480   for (n = 0; n < qtdemux->n_streams; n++) {
4481     QtDemuxStream *str = qtdemux->streams[n];
4482
4483     /* No candidate yet, take the first stream */
4484     if (!ref_str) {
4485       ref_str = str;
4486       continue;
4487     }
4488
4489     /* So that stream has a segment, we prefer video streams */
4490     if (str->subtype == FOURCC_vide) {
4491       ref_str = str;
4492       break;
4493     }
4494   }
4495
4496   if (G_UNLIKELY (!ref_str)) {
4497     GST_DEBUG_OBJECT (qtdemux, "couldn't find any stream");
4498     goto eos;
4499   }
4500
4501   if (G_UNLIKELY (!ref_str->from_sample)) {
4502     GST_DEBUG_OBJECT (qtdemux, "reached the beginning of the file");
4503     goto eos;
4504   }
4505
4506   /* So that stream has been playing from from_sample to to_sample. We will
4507    * get the timestamp of the previous sample and search for a keyframe before
4508    * that. For audio streams we do an arbitrary jump in the past (10 samples) */
4509   if (ref_str->subtype == FOURCC_vide) {
4510     k_index = gst_qtdemux_find_keyframe (qtdemux, ref_str,
4511         ref_str->from_sample - 1, FALSE);
4512   } else {
4513     if (ref_str->from_sample >= 10)
4514       k_index = ref_str->from_sample - 10;
4515     else
4516       k_index = 0;
4517   }
4518
4519   target_ts =
4520       ref_str->samples[k_index].timestamp +
4521       ref_str->samples[k_index].pts_offset;
4522
4523   /* get current segment for that stream */
4524   seg = &ref_str->segments[ref_str->segment_index];
4525   /* Use segment start in original timescale for comparisons */
4526   seg_media_start_mov = seg->trak_media_start;
4527
4528   GST_LOG_OBJECT (qtdemux, "keyframe index %u ts %" G_GUINT64_FORMAT
4529       " seg start %" G_GUINT64_FORMAT " %" GST_TIME_FORMAT "\n",
4530       k_index, target_ts, seg_media_start_mov,
4531       GST_TIME_ARGS (seg->media_start));
4532
4533   /* Crawl back through segments to find the one containing this I frame */
4534   while (target_ts < seg_media_start_mov) {
4535     GST_DEBUG_OBJECT (qtdemux,
4536         "keyframe position (sample %u) is out of segment %u " " target %"
4537         G_GUINT64_FORMAT " seg start %" G_GUINT64_FORMAT, k_index,
4538         ref_str->segment_index, target_ts, seg_media_start_mov);
4539
4540     if (G_UNLIKELY (!ref_str->segment_index)) {
4541       /* Reached first segment, let's consider it's EOS */
4542       goto eos;
4543     }
4544     ref_str->segment_index--;
4545     seg = &ref_str->segments[ref_str->segment_index];
4546     /* Use segment start in original timescale for comparisons */
4547     seg_media_start_mov = seg->trak_media_start;
4548   }
4549   /* Calculate time position of the keyframe and where we should stop */
4550   k_pos =
4551       QTSTREAMTIME_TO_GSTTIME (ref_str,
4552       target_ts - seg->trak_media_start) + seg->time;
4553   last_stop =
4554       QTSTREAMTIME_TO_GSTTIME (ref_str,
4555       ref_str->samples[ref_str->from_sample].timestamp -
4556       seg->trak_media_start) + seg->time;
4557
4558   GST_DEBUG_OBJECT (qtdemux, "preferred stream played from sample %u, "
4559       "now going to sample %u (pts %" GST_TIME_FORMAT ")", ref_str->from_sample,
4560       k_index, GST_TIME_ARGS (k_pos));
4561
4562   /* Set last_stop with the keyframe timestamp we pushed of that stream */
4563   qtdemux->segment.position = last_stop;
4564   GST_DEBUG_OBJECT (qtdemux, "last_stop now is %" GST_TIME_FORMAT,
4565       GST_TIME_ARGS (last_stop));
4566
4567   if (G_UNLIKELY (last_stop < qtdemux->segment.start)) {
4568     GST_DEBUG_OBJECT (qtdemux, "reached the beginning of segment");
4569     goto eos;
4570   }
4571
4572   ref_seg_idx = ref_str->segment_index;
4573   ref_k_index = k_index;
4574
4575   /* Align them all on this */
4576   for (n = 0; n < qtdemux->n_streams; n++) {
4577     guint32 index = 0;
4578     GstClockTime seg_time = 0;
4579     QtDemuxStream *str = qtdemux->streams[n];
4580
4581     /* aligning reference stream again might lead to backing up to yet another
4582      * keyframe (due to timestamp rounding issues),
4583      * potentially putting more load on downstream; so let's try to avoid */
4584     if (str == ref_str) {
4585       seg_idx = ref_seg_idx;
4586       seg = &str->segments[seg_idx];
4587       k_index = ref_k_index;
4588       GST_DEBUG_OBJECT (qtdemux, "reference stream %d segment %d, "
4589           "sample at index %d", n, ref_str->segment_index, k_index);
4590     } else {
4591       seg_idx = gst_qtdemux_find_segment (qtdemux, str, k_pos);
4592       GST_DEBUG_OBJECT (qtdemux,
4593           "stream %d align segment %d for keyframe pos %" GST_TIME_FORMAT, n,
4594           seg_idx, GST_TIME_ARGS (k_pos));
4595
4596       /* get segment and time in the segment */
4597       seg = &str->segments[seg_idx];
4598       seg_time = k_pos - seg->time;
4599
4600       /* get the media time in the segment.
4601        * No adjustment for empty "filler" segments */
4602       if (seg->media_start != GST_CLOCK_TIME_NONE)
4603         seg_time += seg->media_start;
4604
4605       /* get the index of the sample with media time */
4606       index = gst_qtdemux_find_index_linear (qtdemux, str, seg_time);
4607       GST_DEBUG_OBJECT (qtdemux,
4608           "stream %d sample for %" GST_TIME_FORMAT " at %u", n,
4609           GST_TIME_ARGS (seg_time), index);
4610
4611       /* find previous keyframe */
4612       k_index = gst_qtdemux_find_keyframe (qtdemux, str, index, FALSE);
4613     }
4614
4615     /* Remember until where we want to go */
4616     str->to_sample = str->from_sample - 1;
4617     /* Define our time position */
4618     target_ts =
4619         str->samples[k_index].timestamp + str->samples[k_index].pts_offset;
4620     str->time_position = QTSTREAMTIME_TO_GSTTIME (str, target_ts) + seg->time;
4621     if (seg->media_start != GST_CLOCK_TIME_NONE)
4622       str->time_position -= seg->media_start;
4623
4624     /* Now seek back in time */
4625     gst_qtdemux_move_stream (qtdemux, str, k_index);
4626     GST_DEBUG_OBJECT (qtdemux, "stream %d keyframe at %u, time position %"
4627         GST_TIME_FORMAT " playing from sample %u to %u", n, k_index,
4628         GST_TIME_ARGS (str->time_position), str->from_sample, str->to_sample);
4629   }
4630
4631   return GST_FLOW_OK;
4632
4633 eos:
4634   return GST_FLOW_EOS;
4635 }
4636
4637 /*
4638  * Gets the current qt segment start, stop and position for the
4639  * given time offset. This is used in update_segment()
4640  */
4641 static void
4642 gst_qtdemux_stream_segment_get_boundaries (GstQTDemux * qtdemux,
4643     QtDemuxStream * stream, GstClockTime offset,
4644     GstClockTime * _start, GstClockTime * _stop, GstClockTime * _time)
4645 {
4646   GstClockTime seg_time;
4647   GstClockTime start, stop, time;
4648   QtDemuxSegment *segment;
4649
4650   segment = &stream->segments[stream->segment_index];
4651
4652   /* get time in this segment */
4653   seg_time = (offset - segment->time) * segment->rate;
4654
4655   GST_LOG_OBJECT (stream->pad, "seg_time %" GST_TIME_FORMAT,
4656       GST_TIME_ARGS (seg_time));
4657
4658   if (G_UNLIKELY (seg_time > segment->duration)) {
4659     GST_LOG_OBJECT (stream->pad,
4660         "seg_time > segment->duration %" GST_TIME_FORMAT,
4661         GST_TIME_ARGS (segment->duration));
4662     seg_time = segment->duration;
4663   }
4664
4665   /* qtdemux->segment.stop is in outside-time-realm, whereas
4666    * segment->media_stop is in track-time-realm.
4667    *
4668    * In order to compare the two, we need to bring segment.stop
4669    * into the track-time-realm
4670    *
4671    * FIXME - does this comment still hold? Don't see any conversion here */
4672
4673   stop = qtdemux->segment.stop;
4674   if (stop == GST_CLOCK_TIME_NONE)
4675     stop = qtdemux->segment.duration;
4676   if (stop == GST_CLOCK_TIME_NONE)
4677     stop = segment->media_stop;
4678   else
4679     stop =
4680         MIN (segment->media_stop, stop - segment->time + segment->media_start);
4681
4682   if (G_UNLIKELY (QTSEGMENT_IS_EMPTY (segment))) {
4683     start = segment->time + seg_time;
4684     time = offset;
4685     stop = start - seg_time + segment->duration;
4686   } else if (qtdemux->segment.rate >= 0) {
4687     start = MIN (segment->media_start + seg_time, stop);
4688     time = offset;
4689   } else {
4690     if (segment->media_start >= qtdemux->segment.start) {
4691       time = segment->time;
4692     } else {
4693       time = segment->time + (qtdemux->segment.start - segment->media_start);
4694     }
4695
4696     start = MAX (segment->media_start, qtdemux->segment.start);
4697     stop = MIN (segment->media_start + seg_time, stop);
4698   }
4699
4700   *_start = start;
4701   *_stop = stop;
4702   *_time = time;
4703 }
4704
4705 /*
4706  * Updates the qt segment used for the stream and pushes a new segment event
4707  * downstream on this stream's pad.
4708  */
4709 static gboolean
4710 gst_qtdemux_stream_update_segment (GstQTDemux * qtdemux, QtDemuxStream * stream,
4711     gint seg_idx, GstClockTime offset, GstClockTime * _start,
4712     GstClockTime * _stop)
4713 {
4714   QtDemuxSegment *segment;
4715   GstClockTime start = 0, stop = GST_CLOCK_TIME_NONE, time = 0;
4716   gdouble rate;
4717   GstEvent *event;
4718
4719   /* update the current segment */
4720   stream->segment_index = seg_idx;
4721
4722   /* get the segment */
4723   segment = &stream->segments[seg_idx];
4724
4725   if (G_UNLIKELY (offset < segment->time)) {
4726     GST_WARNING_OBJECT (stream->pad, "offset < segment->time %" GST_TIME_FORMAT,
4727         GST_TIME_ARGS (segment->time));
4728     return FALSE;
4729   }
4730
4731   /* segment lies beyond total indicated duration */
4732   if (G_UNLIKELY (qtdemux->segment.duration != GST_CLOCK_TIME_NONE &&
4733           segment->time > qtdemux->segment.duration)) {
4734     GST_WARNING_OBJECT (stream->pad, "file duration %" GST_TIME_FORMAT
4735         " < segment->time %" GST_TIME_FORMAT,
4736         GST_TIME_ARGS (qtdemux->segment.duration),
4737         GST_TIME_ARGS (segment->time));
4738     return FALSE;
4739   }
4740
4741   gst_qtdemux_stream_segment_get_boundaries (qtdemux, stream, offset,
4742       &start, &stop, &time);
4743
4744   GST_DEBUG_OBJECT (stream->pad, "new segment %d from %" GST_TIME_FORMAT
4745       " to %" GST_TIME_FORMAT ", time %" GST_TIME_FORMAT, seg_idx,
4746       GST_TIME_ARGS (start), GST_TIME_ARGS (stop), GST_TIME_ARGS (time));
4747
4748   /* combine global rate with that of the segment */
4749   rate = segment->rate * qtdemux->segment.rate;
4750
4751   /* Copy flags from main segment */
4752   stream->segment.flags = qtdemux->segment.flags;
4753
4754   /* update the segment values used for clipping */
4755   stream->segment.offset = qtdemux->segment.offset;
4756   stream->segment.base = qtdemux->segment.base + stream->accumulated_base;
4757   stream->segment.applied_rate = qtdemux->segment.applied_rate;
4758   stream->segment.rate = rate;
4759   stream->segment.start = start + QTSTREAMTIME_TO_GSTTIME (stream,
4760       stream->cslg_shift);
4761   stream->segment.stop = stop + QTSTREAMTIME_TO_GSTTIME (stream,
4762       stream->cslg_shift);
4763   stream->segment.time = time;
4764   stream->segment.position = stream->segment.start;
4765
4766   GST_DEBUG_OBJECT (stream->pad, "New segment: %" GST_SEGMENT_FORMAT,
4767       &stream->segment);
4768
4769   /* now prepare and send the segment */
4770   if (stream->pad) {
4771     event = gst_event_new_segment (&stream->segment);
4772     if (qtdemux->segment_seqnum) {
4773       gst_event_set_seqnum (event, qtdemux->segment_seqnum);
4774     }
4775     gst_pad_push_event (stream->pad, event);
4776     /* assume we can send more data now */
4777     GST_PAD_LAST_FLOW_RETURN (stream->pad) = GST_FLOW_OK;
4778     /* clear to send tags on this pad now */
4779     gst_qtdemux_push_tags (qtdemux, stream);
4780   }
4781
4782   if (_start)
4783     *_start = start;
4784   if (_stop)
4785     *_stop = stop;
4786
4787   return TRUE;
4788 }
4789
4790 /* activate the given segment number @seg_idx of @stream at time @offset.
4791  * @offset is an absolute global position over all the segments.
4792  *
4793  * This will push out a NEWSEGMENT event with the right values and
4794  * position the stream index to the first decodable sample before
4795  * @offset.
4796  */
4797 static gboolean
4798 gst_qtdemux_activate_segment (GstQTDemux * qtdemux, QtDemuxStream * stream,
4799     guint32 seg_idx, GstClockTime offset)
4800 {
4801   QtDemuxSegment *segment;
4802   guint32 index, kf_index;
4803   GstClockTime start = 0, stop = GST_CLOCK_TIME_NONE;
4804
4805   GST_LOG_OBJECT (stream->pad, "activate segment %d, offset %" GST_TIME_FORMAT,
4806       seg_idx, GST_TIME_ARGS (offset));
4807
4808   if (!gst_qtdemux_stream_update_segment (qtdemux, stream, seg_idx, offset,
4809           &start, &stop))
4810     return FALSE;
4811
4812   segment = &stream->segments[stream->segment_index];
4813
4814   /* in the fragmented case, we pick a fragment that starts before our
4815    * desired position and rely on downstream to wait for a keyframe
4816    * (FIXME: doesn't seem to work so well with ismv and wmv, as no parser; the
4817    * tfra entries tells us which trun/sample the key unit is in, but we don't
4818    * make use of this additional information at the moment) */
4819   if (qtdemux->fragmented) {
4820     stream->to_sample = G_MAXUINT32;
4821     return TRUE;
4822   }
4823
4824   /* We don't need to look for a sample in push-based */
4825   if (!qtdemux->pullbased)
4826     return TRUE;
4827
4828   /* and move to the keyframe before the indicated media time of the
4829    * segment */
4830   if (G_LIKELY (!QTSEGMENT_IS_EMPTY (segment))) {
4831     if (qtdemux->segment.rate >= 0) {
4832       index = gst_qtdemux_find_index_linear (qtdemux, stream, start);
4833       stream->to_sample = G_MAXUINT32;
4834       GST_DEBUG_OBJECT (stream->pad,
4835           "moving data pointer to %" GST_TIME_FORMAT ", index: %u, pts %"
4836           GST_TIME_FORMAT, GST_TIME_ARGS (start), index,
4837           GST_TIME_ARGS (QTSAMPLE_PTS (stream, &stream->samples[index])));
4838     } else {
4839       index = gst_qtdemux_find_index_linear (qtdemux, stream, stop);
4840       stream->to_sample = index;
4841       GST_DEBUG_OBJECT (stream->pad,
4842           "moving data pointer to %" GST_TIME_FORMAT ", index: %u, pts %"
4843           GST_TIME_FORMAT, GST_TIME_ARGS (stop), index,
4844           GST_TIME_ARGS (QTSAMPLE_PTS (stream, &stream->samples[index])));
4845     }
4846   } else {
4847     GST_DEBUG_OBJECT (stream->pad, "No need to look for keyframe, "
4848         "this is an empty segment");
4849     return TRUE;
4850   }
4851
4852   /* gst_qtdemux_parse_sample () called from gst_qtdemux_find_index_linear ()
4853    * encountered an error and printed a message so we return appropriately */
4854   if (index == -1)
4855     return FALSE;
4856
4857   /* we're at the right spot */
4858   if (index == stream->sample_index) {
4859     GST_DEBUG_OBJECT (stream->pad, "we are at the right index");
4860     return TRUE;
4861   }
4862
4863   /* find keyframe of the target index */
4864   kf_index = gst_qtdemux_find_keyframe (qtdemux, stream, index, FALSE);
4865
4866 /* *INDENT-OFF* */
4867 /* indent does stupid stuff with stream->samples[].timestamp */
4868
4869   /* if we move forwards, we don't have to go back to the previous
4870    * keyframe since we already sent that. We can also just jump to
4871    * the keyframe right before the target index if there is one. */
4872   if (index > stream->sample_index) {
4873     /* moving forwards check if we move past a keyframe */
4874     if (kf_index > stream->sample_index) {
4875       GST_DEBUG_OBJECT (stream->pad,
4876            "moving forwards to keyframe at %u (pts %" GST_TIME_FORMAT " dts %"GST_TIME_FORMAT" )", kf_index,
4877            GST_TIME_ARGS (QTSAMPLE_PTS(stream, &stream->samples[kf_index])),
4878            GST_TIME_ARGS (QTSAMPLE_DTS(stream, &stream->samples[kf_index])));
4879       gst_qtdemux_move_stream (qtdemux, stream, kf_index);
4880     } else {
4881       GST_DEBUG_OBJECT (stream->pad,
4882           "moving forwards, keyframe at %u (pts %" GST_TIME_FORMAT " dts %"GST_TIME_FORMAT" ) already sent", kf_index,
4883           GST_TIME_ARGS (QTSAMPLE_PTS (stream, &stream->samples[kf_index])),
4884           GST_TIME_ARGS (QTSAMPLE_DTS (stream, &stream->samples[kf_index])));
4885     }
4886   } else {
4887     GST_DEBUG_OBJECT (stream->pad,
4888         "moving backwards to keyframe at %u (pts %" GST_TIME_FORMAT " dts %"GST_TIME_FORMAT" )", kf_index,
4889         GST_TIME_ARGS (QTSAMPLE_PTS(stream, &stream->samples[kf_index])),
4890         GST_TIME_ARGS (QTSAMPLE_DTS(stream, &stream->samples[kf_index])));
4891     gst_qtdemux_move_stream (qtdemux, stream, kf_index);
4892   }
4893
4894 /* *INDENT-ON* */
4895
4896   return TRUE;
4897 }
4898
4899 /* prepare to get the current sample of @stream, getting essential values.
4900  *
4901  * This function will also prepare and send the segment when needed.
4902  *
4903  * Return FALSE if the stream is EOS.
4904  *
4905  * PULL-BASED
4906  */
4907 static gboolean
4908 gst_qtdemux_prepare_current_sample (GstQTDemux * qtdemux,
4909     QtDemuxStream * stream, gboolean * empty, guint64 * offset, guint * size,
4910     GstClockTime * dts, GstClockTime * pts, GstClockTime * duration,
4911     gboolean * keyframe)
4912 {
4913   QtDemuxSample *sample;
4914   GstClockTime time_position;
4915   guint32 seg_idx;
4916
4917   g_return_val_if_fail (stream != NULL, FALSE);
4918
4919   time_position = stream->time_position;
4920   if (G_UNLIKELY (time_position == GST_CLOCK_TIME_NONE))
4921     goto eos;
4922
4923   seg_idx = stream->segment_index;
4924   if (G_UNLIKELY (seg_idx == -1)) {
4925     /* find segment corresponding to time_position if we are looking
4926      * for a segment. */
4927     seg_idx = gst_qtdemux_find_segment (qtdemux, stream, time_position);
4928   }
4929
4930   /* different segment, activate it, sample_index will be set. */
4931   if (G_UNLIKELY (stream->segment_index != seg_idx))
4932     gst_qtdemux_activate_segment (qtdemux, stream, seg_idx, time_position);
4933
4934   if (G_UNLIKELY (QTSEGMENT_IS_EMPTY (&stream->segments[stream->
4935                   segment_index]))) {
4936     QtDemuxSegment *seg = &stream->segments[stream->segment_index];
4937
4938     GST_LOG_OBJECT (qtdemux, "Empty segment activated,"
4939         " prepare empty sample");
4940
4941     *empty = TRUE;
4942     *pts = *dts = time_position;
4943     *duration = seg->duration - (time_position - seg->time);
4944
4945     return TRUE;
4946   }
4947
4948   *empty = FALSE;
4949
4950   if (stream->sample_index == -1)
4951     stream->sample_index = 0;
4952
4953   GST_LOG_OBJECT (qtdemux, "segment active, index = %u of %u",
4954       stream->sample_index, stream->n_samples);
4955
4956   if (G_UNLIKELY (stream->sample_index >= stream->n_samples)) {
4957     if (!qtdemux->fragmented)
4958       goto eos;
4959
4960     GST_INFO_OBJECT (qtdemux, "out of samples, trying to add more");
4961     do {
4962       GstFlowReturn flow;
4963
4964       GST_OBJECT_LOCK (qtdemux);
4965       flow = qtdemux_add_fragmented_samples (qtdemux);
4966       GST_OBJECT_UNLOCK (qtdemux);
4967
4968       if (flow != GST_FLOW_OK)
4969         goto eos;
4970     }
4971     while (stream->sample_index >= stream->n_samples);
4972   }
4973
4974   if (!qtdemux_parse_samples (qtdemux, stream, stream->sample_index)) {
4975     GST_LOG_OBJECT (qtdemux, "Parsing of index %u failed!",
4976         stream->sample_index);
4977     return FALSE;
4978   }
4979
4980   /* now get the info for the sample we're at */
4981   sample = &stream->samples[stream->sample_index];
4982
4983   *dts = QTSAMPLE_DTS (stream, sample);
4984   *pts = QTSAMPLE_PTS (stream, sample);
4985   *offset = sample->offset;
4986   *size = sample->size;
4987   *duration = QTSAMPLE_DUR_DTS (stream, sample, *dts);
4988   *keyframe = QTSAMPLE_KEYFRAME (stream, sample);
4989
4990   return TRUE;
4991
4992   /* special cases */
4993 eos:
4994   {
4995     stream->time_position = GST_CLOCK_TIME_NONE;
4996     return FALSE;
4997   }
4998 }
4999
5000 /* move to the next sample in @stream.
5001  *
5002  * Moves to the next segment when needed.
5003  */
5004 static void
5005 gst_qtdemux_advance_sample (GstQTDemux * qtdemux, QtDemuxStream * stream)
5006 {
5007   QtDemuxSample *sample;
5008   QtDemuxSegment *segment;
5009
5010   /* get current segment */
5011   segment = &stream->segments[stream->segment_index];
5012
5013   if (G_UNLIKELY (QTSEGMENT_IS_EMPTY (segment))) {
5014     GST_DEBUG_OBJECT (qtdemux, "Empty segment, no samples to advance");
5015     goto next_segment;
5016   }
5017
5018   if (G_UNLIKELY (stream->sample_index >= stream->to_sample)) {
5019     /* Mark the stream as EOS */
5020     GST_DEBUG_OBJECT (qtdemux,
5021         "reached max allowed sample %u, mark EOS", stream->to_sample);
5022     stream->time_position = GST_CLOCK_TIME_NONE;
5023     return;
5024   }
5025
5026   /* move to next sample */
5027   stream->sample_index++;
5028   stream->offset_in_sample = 0;
5029
5030   /* reached the last sample, we need the next segment */
5031   if (G_UNLIKELY (stream->sample_index >= stream->n_samples))
5032     goto next_segment;
5033
5034   if (!qtdemux_parse_samples (qtdemux, stream, stream->sample_index)) {
5035     GST_LOG_OBJECT (qtdemux, "Parsing of index %u failed!",
5036         stream->sample_index);
5037     return;
5038   }
5039
5040   /* get next sample */
5041   sample = &stream->samples[stream->sample_index];
5042
5043   /* see if we are past the segment */
5044   if (G_UNLIKELY (QTSAMPLE_DTS (stream, sample) >= segment->media_stop))
5045     goto next_segment;
5046
5047   if (QTSAMPLE_DTS (stream, sample) >= segment->media_start) {
5048     /* inside the segment, update time_position, looks very familiar to
5049      * GStreamer segments, doesn't it? */
5050     stream->time_position =
5051         QTSAMPLE_DTS (stream, sample) - segment->media_start + segment->time;
5052   } else {
5053     /* not yet in segment, time does not yet increment. This means
5054      * that we are still prerolling keyframes to the decoder so it can
5055      * decode the first sample of the segment. */
5056     stream->time_position = segment->time;
5057   }
5058   return;
5059
5060   /* move to the next segment */
5061 next_segment:
5062   {
5063     GST_DEBUG_OBJECT (qtdemux, "segment %d ended ", stream->segment_index);
5064
5065     if (stream->segment_index == stream->n_segments - 1) {
5066       /* are we at the end of the last segment, we're EOS */
5067       stream->time_position = GST_CLOCK_TIME_NONE;
5068     } else {
5069       /* else we're only at the end of the current segment */
5070       stream->time_position = segment->stop_time;
5071     }
5072     /* make sure we select a new segment */
5073
5074     /* accumulate previous segments */
5075     if (GST_CLOCK_TIME_IS_VALID (stream->segment.stop))
5076       stream->accumulated_base +=
5077           (stream->segment.stop -
5078           stream->segment.start) / ABS (stream->segment.rate);
5079
5080     stream->segment_index = -1;
5081   }
5082 }
5083
5084 static void
5085 gst_qtdemux_sync_streams (GstQTDemux * demux)
5086 {
5087   gint i;
5088
5089   if (demux->n_streams <= 1)
5090     return;
5091
5092   for (i = 0; i < demux->n_streams; i++) {
5093     QtDemuxStream *stream;
5094     GstClockTime end_time;
5095
5096     stream = demux->streams[i];
5097
5098     if (!stream->pad)
5099       continue;
5100
5101     /* TODO advance time on subtitle streams here, if any some day */
5102
5103     /* some clips/trailers may have unbalanced streams at the end,
5104      * so send EOS on shorter stream to prevent stalling others */
5105
5106     /* do not mess with EOS if SEGMENT seeking */
5107     if (demux->segment.flags & GST_SEEK_FLAG_SEGMENT)
5108       continue;
5109
5110     if (demux->pullbased) {
5111       /* loop mode is sample time based */
5112       if (!STREAM_IS_EOS (stream))
5113         continue;
5114     } else {
5115       /* push mode is byte position based */
5116       if (stream->n_samples &&
5117           stream->samples[stream->n_samples - 1].offset >= demux->offset)
5118         continue;
5119     }
5120
5121     if (stream->sent_eos)
5122       continue;
5123
5124     /* only act if some gap */
5125     end_time = stream->segments[stream->n_segments - 1].stop_time;
5126     GST_LOG_OBJECT (demux, "current position: %" GST_TIME_FORMAT
5127         ", stream end: %" GST_TIME_FORMAT,
5128         GST_TIME_ARGS (demux->segment.position), GST_TIME_ARGS (end_time));
5129     if (GST_CLOCK_TIME_IS_VALID (end_time)
5130         && (end_time + 2 * GST_SECOND < demux->segment.position)) {
5131       GstEvent *event;
5132
5133       GST_DEBUG_OBJECT (demux, "sending EOS for stream %s",
5134           GST_PAD_NAME (stream->pad));
5135       stream->sent_eos = TRUE;
5136       event = gst_event_new_eos ();
5137       if (demux->segment_seqnum)
5138         gst_event_set_seqnum (event, demux->segment_seqnum);
5139       gst_pad_push_event (stream->pad, event);
5140     }
5141   }
5142 }
5143
5144 /* EOS and NOT_LINKED need to be combined. This means that we return:
5145  *
5146  *  GST_FLOW_NOT_LINKED: when all pads NOT_LINKED.
5147  *  GST_FLOW_EOS: when all pads EOS or NOT_LINKED.
5148  */
5149 static GstFlowReturn
5150 gst_qtdemux_combine_flows (GstQTDemux * demux, QtDemuxStream * stream,
5151     GstFlowReturn ret)
5152 {
5153   GST_LOG_OBJECT (demux, "flow return: %s", gst_flow_get_name (ret));
5154
5155   if (stream->pad)
5156     ret = gst_flow_combiner_update_pad_flow (demux->flowcombiner, stream->pad,
5157         ret);
5158   else
5159     ret = gst_flow_combiner_update_flow (demux->flowcombiner, ret);
5160
5161   GST_LOG_OBJECT (demux, "combined flow return: %s", gst_flow_get_name (ret));
5162   return ret;
5163 }
5164
5165 /* the input buffer metadata must be writable. Returns NULL when the buffer is
5166  * completely clipped
5167  *
5168  * Should be used only with raw buffers */
5169 static GstBuffer *
5170 gst_qtdemux_clip_buffer (GstQTDemux * qtdemux, QtDemuxStream * stream,
5171     GstBuffer * buf)
5172 {
5173   guint64 start, stop, cstart, cstop, diff;
5174   GstClockTime pts, duration;
5175   gsize size, osize;
5176   gint num_rate, denom_rate;
5177   gint frame_size;
5178   gboolean clip_data;
5179   guint offset;
5180
5181   osize = size = gst_buffer_get_size (buf);
5182   offset = 0;
5183
5184   /* depending on the type, setup the clip parameters */
5185   if (stream->subtype == FOURCC_soun) {
5186     frame_size = CUR_STREAM (stream)->bytes_per_frame;
5187     num_rate = GST_SECOND;
5188     denom_rate = (gint) CUR_STREAM (stream)->rate;
5189     clip_data = TRUE;
5190   } else if (stream->subtype == FOURCC_vide) {
5191     frame_size = size;
5192     num_rate = CUR_STREAM (stream)->fps_n;
5193     denom_rate = CUR_STREAM (stream)->fps_d;
5194     clip_data = FALSE;
5195   } else
5196     goto wrong_type;
5197
5198   if (frame_size <= 0)
5199     goto bad_frame_size;
5200
5201   /* we can only clip if we have a valid pts */
5202   pts = GST_BUFFER_PTS (buf);
5203   if (G_UNLIKELY (!GST_CLOCK_TIME_IS_VALID (pts)))
5204     goto no_pts;
5205
5206   duration = GST_BUFFER_DURATION (buf);
5207
5208   if (G_UNLIKELY (!GST_CLOCK_TIME_IS_VALID (duration))) {
5209     duration =
5210         gst_util_uint64_scale_int (size / frame_size, num_rate, denom_rate);
5211   }
5212
5213   start = pts;
5214   stop = start + duration;
5215
5216   if (G_UNLIKELY (!gst_segment_clip (&stream->segment,
5217               GST_FORMAT_TIME, start, stop, &cstart, &cstop)))
5218     goto clipped;
5219
5220   /* see if some clipping happened */
5221   diff = cstart - start;
5222   if (diff > 0) {
5223     pts += diff;
5224     duration -= diff;
5225
5226     if (clip_data) {
5227       /* bring clipped time to samples and to bytes */
5228       diff = gst_util_uint64_scale_int (diff, denom_rate, num_rate);
5229       diff *= frame_size;
5230
5231       GST_DEBUG_OBJECT (qtdemux,
5232           "clipping start to %" GST_TIME_FORMAT " %"
5233           G_GUINT64_FORMAT " bytes", GST_TIME_ARGS (cstart), diff);
5234
5235       offset = diff;
5236       size -= diff;
5237     }
5238   }
5239   diff = stop - cstop;
5240   if (diff > 0) {
5241     duration -= diff;
5242
5243     if (clip_data) {
5244       /* bring clipped time to samples and then to bytes */
5245       diff = gst_util_uint64_scale_int (diff, denom_rate, num_rate);
5246       diff *= frame_size;
5247       GST_DEBUG_OBJECT (qtdemux,
5248           "clipping stop to %" GST_TIME_FORMAT " %" G_GUINT64_FORMAT
5249           " bytes", GST_TIME_ARGS (cstop), diff);
5250       size -= diff;
5251     }
5252   }
5253
5254   if (offset != 0 || size != osize)
5255     gst_buffer_resize (buf, offset, size);
5256
5257   GST_BUFFER_DTS (buf) = GST_CLOCK_TIME_NONE;
5258   GST_BUFFER_PTS (buf) = pts;
5259   GST_BUFFER_DURATION (buf) = duration;
5260
5261   return buf;
5262
5263   /* dropped buffer */
5264 wrong_type:
5265   {
5266     GST_DEBUG_OBJECT (qtdemux, "unknown stream type");
5267     return buf;
5268   }
5269 bad_frame_size:
5270   {
5271     GST_DEBUG_OBJECT (qtdemux, "bad frame size");
5272     return buf;
5273   }
5274 no_pts:
5275   {
5276     GST_DEBUG_OBJECT (qtdemux, "no pts on buffer");
5277     return buf;
5278   }
5279 clipped:
5280   {
5281     GST_DEBUG_OBJECT (qtdemux, "clipped buffer");
5282     gst_buffer_unref (buf);
5283     return NULL;
5284   }
5285 }
5286
5287 static GstBuffer *
5288 gst_qtdemux_align_buffer (GstQTDemux * demux,
5289     GstBuffer * buffer, gsize alignment)
5290 {
5291   GstMapInfo map;
5292
5293   gst_buffer_map (buffer, &map, GST_MAP_READ);
5294
5295   if (map.size < sizeof (guintptr)) {
5296     gst_buffer_unmap (buffer, &map);
5297     return buffer;
5298   }
5299
5300   if (((guintptr) map.data) & (alignment - 1)) {
5301     GstBuffer *new_buffer;
5302     GstAllocationParams params = { 0, alignment - 1, 0, 0, };
5303
5304     new_buffer = gst_buffer_new_allocate (NULL,
5305         gst_buffer_get_size (buffer), &params);
5306
5307     /* Copy data "by hand", so ensure alignment is kept: */
5308     gst_buffer_fill (new_buffer, 0, map.data, map.size);
5309
5310     gst_buffer_copy_into (new_buffer, buffer, GST_BUFFER_COPY_METADATA, 0, -1);
5311     GST_DEBUG_OBJECT (demux,
5312         "We want output aligned on %" G_GSIZE_FORMAT ", reallocated",
5313         alignment);
5314
5315     gst_buffer_unmap (buffer, &map);
5316     gst_buffer_unref (buffer);
5317
5318     return new_buffer;
5319   }
5320
5321   gst_buffer_unmap (buffer, &map);
5322   return buffer;
5323 }
5324
5325 /* the input buffer metadata must be writable,
5326  * but time/duration etc not yet set and need not be preserved */
5327 static GstBuffer *
5328 gst_qtdemux_process_buffer (GstQTDemux * qtdemux, QtDemuxStream * stream,
5329     GstBuffer * buf)
5330 {
5331   GstMapInfo map;
5332   guint nsize = 0;
5333   gchar *str;
5334
5335   /* not many cases for now */
5336   if (G_UNLIKELY (CUR_STREAM (stream)->fourcc == FOURCC_mp4s)) {
5337     /* send a one time dvd clut event */
5338     if (stream->pending_event && stream->pad)
5339       gst_pad_push_event (stream->pad, stream->pending_event);
5340     stream->pending_event = NULL;
5341   }
5342
5343   if (G_UNLIKELY (stream->subtype != FOURCC_text
5344           && stream->subtype != FOURCC_sbtl &&
5345           stream->subtype != FOURCC_subp)) {
5346     return buf;
5347   }
5348
5349   gst_buffer_map (buf, &map, GST_MAP_READ);
5350
5351   /* empty buffer is sent to terminate previous subtitle */
5352   if (map.size <= 2) {
5353     gst_buffer_unmap (buf, &map);
5354     gst_buffer_unref (buf);
5355     return NULL;
5356   }
5357   if (stream->subtype == FOURCC_subp) {
5358     /* That's all the processing needed for subpictures */
5359     gst_buffer_unmap (buf, &map);
5360     return buf;
5361   }
5362
5363   nsize = GST_READ_UINT16_BE (map.data);
5364   nsize = MIN (nsize, map.size - 2);
5365
5366   GST_LOG_OBJECT (qtdemux, "3GPP timed text subtitle: %d/%" G_GSIZE_FORMAT "",
5367       nsize, map.size);
5368
5369   /* takes care of UTF-8 validation or UTF-16 recognition,
5370    * no other encoding expected */
5371   str = gst_tag_freeform_string_to_utf8 ((gchar *) map.data + 2, nsize, NULL);
5372   gst_buffer_unmap (buf, &map);
5373   if (str) {
5374     gst_buffer_unref (buf);
5375     buf = _gst_buffer_new_wrapped (str, strlen (str), g_free);
5376   } else {
5377     /* this should not really happen unless the subtitle is corrupted */
5378     gst_buffer_unref (buf);
5379     buf = NULL;
5380   }
5381
5382   /* FIXME ? convert optional subsequent style info to markup */
5383
5384   return buf;
5385 }
5386
5387 /* Sets a buffer's attributes properly and pushes it downstream.
5388  * Also checks for additional actions and custom processing that may
5389  * need to be done first.
5390  */
5391 static GstFlowReturn
5392 gst_qtdemux_decorate_and_push_buffer (GstQTDemux * qtdemux,
5393     QtDemuxStream * stream, GstBuffer * buf,
5394     GstClockTime dts, GstClockTime pts, GstClockTime duration,
5395     gboolean keyframe, GstClockTime position, guint64 byte_position)
5396 {
5397   GstFlowReturn ret = GST_FLOW_OK;
5398
5399   /* offset the timestamps according to the edit list */
5400
5401   if (G_UNLIKELY (CUR_STREAM (stream)->fourcc == FOURCC_rtsp)) {
5402     gchar *url;
5403     GstMapInfo map;
5404
5405     gst_buffer_map (buf, &map, GST_MAP_READ);
5406     url = g_strndup ((gchar *) map.data, map.size);
5407     gst_buffer_unmap (buf, &map);
5408     if (url != NULL && strlen (url) != 0) {
5409       /* we have RTSP redirect now */
5410       gst_element_post_message (GST_ELEMENT_CAST (qtdemux),
5411           gst_message_new_element (GST_OBJECT_CAST (qtdemux),
5412               gst_structure_new ("redirect",
5413                   "new-location", G_TYPE_STRING, url, NULL)));
5414       qtdemux->posted_redirect = TRUE;
5415     } else {
5416       GST_WARNING_OBJECT (qtdemux, "Redirect URI of stream is empty, not "
5417           "posting");
5418     }
5419     g_free (url);
5420   }
5421
5422   /* position reporting */
5423   if (qtdemux->segment.rate >= 0) {
5424     qtdemux->segment.position = position;
5425     gst_qtdemux_sync_streams (qtdemux);
5426   }
5427
5428   if (G_UNLIKELY (!stream->pad)) {
5429     GST_DEBUG_OBJECT (qtdemux, "No output pad for stream, ignoring");
5430     gst_buffer_unref (buf);
5431     goto exit;
5432   }
5433
5434   /* send out pending buffers */
5435   while (stream->buffers) {
5436     GstBuffer *buffer = (GstBuffer *) stream->buffers->data;
5437
5438     if (G_UNLIKELY (stream->discont)) {
5439       GST_LOG_OBJECT (qtdemux, "marking discont buffer");
5440       GST_BUFFER_FLAG_SET (buffer, GST_BUFFER_FLAG_DISCONT);
5441       stream->discont = FALSE;
5442     } else {
5443       GST_BUFFER_FLAG_UNSET (buf, GST_BUFFER_FLAG_DISCONT);
5444     }
5445
5446     if (stream->alignment > 1)
5447       buffer = gst_qtdemux_align_buffer (qtdemux, buffer, stream->alignment);
5448     gst_pad_push (stream->pad, buffer);
5449
5450     stream->buffers = g_slist_delete_link (stream->buffers, stream->buffers);
5451   }
5452
5453   /* we're going to modify the metadata */
5454   buf = gst_buffer_make_writable (buf);
5455
5456   if (G_UNLIKELY (stream->need_process))
5457     buf = gst_qtdemux_process_buffer (qtdemux, stream, buf);
5458
5459   if (!buf) {
5460     goto exit;
5461   }
5462
5463   GST_BUFFER_DTS (buf) = dts;
5464   GST_BUFFER_PTS (buf) = pts;
5465   GST_BUFFER_DURATION (buf) = duration;
5466   GST_BUFFER_OFFSET (buf) = -1;
5467   GST_BUFFER_OFFSET_END (buf) = -1;
5468
5469   if (G_UNLIKELY (CUR_STREAM (stream)->rgb8_palette))
5470     gst_buffer_append_memory (buf,
5471         gst_memory_ref (CUR_STREAM (stream)->rgb8_palette));
5472
5473   if (G_UNLIKELY (CUR_STREAM (stream)->padding)) {
5474     gst_buffer_resize (buf, CUR_STREAM (stream)->padding, -1);
5475   }
5476 #if 0
5477   if (G_UNLIKELY (qtdemux->element_index)) {
5478     GstClockTime stream_time;
5479
5480     stream_time =
5481         gst_segment_to_stream_time (&stream->segment, GST_FORMAT_TIME,
5482         timestamp);
5483     if (GST_CLOCK_TIME_IS_VALID (stream_time)) {
5484       GST_LOG_OBJECT (qtdemux,
5485           "adding association %" GST_TIME_FORMAT "-> %"
5486           G_GUINT64_FORMAT, GST_TIME_ARGS (stream_time), byte_position);
5487       gst_index_add_association (qtdemux->element_index,
5488           qtdemux->index_id,
5489           keyframe ? GST_ASSOCIATION_FLAG_KEY_UNIT :
5490           GST_ASSOCIATION_FLAG_DELTA_UNIT, GST_FORMAT_TIME, stream_time,
5491           GST_FORMAT_BYTES, byte_position, NULL);
5492     }
5493   }
5494 #endif
5495
5496   if (stream->need_clip)
5497     buf = gst_qtdemux_clip_buffer (qtdemux, stream, buf);
5498
5499   if (G_UNLIKELY (buf == NULL))
5500     goto exit;
5501
5502   if (G_UNLIKELY (stream->discont)) {
5503     GST_LOG_OBJECT (qtdemux, "marking discont buffer");
5504     GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_DISCONT);
5505     stream->discont = FALSE;
5506   } else {
5507     GST_BUFFER_FLAG_UNSET (buf, GST_BUFFER_FLAG_DISCONT);
5508   }
5509
5510   if (!keyframe) {
5511     GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_DELTA_UNIT);
5512     stream->on_keyframe = FALSE;
5513   } else {
5514     stream->on_keyframe = TRUE;
5515   }
5516
5517
5518   GST_LOG_OBJECT (qtdemux,
5519       "Pushing buffer with dts %" GST_TIME_FORMAT ", pts %" GST_TIME_FORMAT
5520       ", duration %" GST_TIME_FORMAT " on pad %s", GST_TIME_ARGS (dts),
5521       GST_TIME_ARGS (pts), GST_TIME_ARGS (duration),
5522       GST_PAD_NAME (stream->pad));
5523
5524   if (stream->protected && stream->protection_scheme_type == FOURCC_cenc) {
5525     GstStructure *crypto_info;
5526     QtDemuxCencSampleSetInfo *info =
5527         (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
5528     gint index;
5529     GstEvent *event;
5530
5531     while ((event = g_queue_pop_head (&stream->protection_scheme_event_queue))) {
5532       gst_pad_push_event (stream->pad, event);
5533     }
5534
5535     if (info->crypto_info == NULL) {
5536       GST_DEBUG_OBJECT (qtdemux, "cenc metadata hasn't been parsed yet");
5537       gst_buffer_unref (buf);
5538       goto exit;
5539     }
5540
5541     /* The end of the crypto_info array matches our n_samples position,
5542      * so count backward from there */
5543     index = stream->sample_index - stream->n_samples + info->crypto_info->len;
5544     if (G_LIKELY (index >= 0 && index < info->crypto_info->len)) {
5545       /* steal structure from array */
5546       crypto_info = g_ptr_array_index (info->crypto_info, index);
5547       g_ptr_array_index (info->crypto_info, index) = NULL;
5548       GST_LOG_OBJECT (qtdemux, "attaching cenc metadata [%u/%u]", index,
5549           info->crypto_info->len);
5550       if (!crypto_info || !gst_buffer_add_protection_meta (buf, crypto_info))
5551         GST_ERROR_OBJECT (qtdemux, "failed to attach cenc metadata to buffer");
5552     } else {
5553       GST_INFO_OBJECT (qtdemux, "No crypto info with index %d and sample %d",
5554           index, stream->sample_index);
5555     }
5556   }
5557
5558   if (stream->alignment > 1)
5559     buf = gst_qtdemux_align_buffer (qtdemux, buf, stream->alignment);
5560
5561   ret = gst_pad_push (stream->pad, buf);
5562
5563   if (GST_CLOCK_TIME_IS_VALID (pts) && GST_CLOCK_TIME_IS_VALID (duration)) {
5564     /* mark position in stream, we'll need this to know when to send GAP event */
5565     stream->segment.position = pts + duration;
5566   }
5567
5568 exit:
5569   return ret;
5570 }
5571
5572 static const QtDemuxRandomAccessEntry *
5573 gst_qtdemux_stream_seek_fragment (GstQTDemux * qtdemux, QtDemuxStream * stream,
5574     GstClockTime pos, gboolean after)
5575 {
5576   QtDemuxRandomAccessEntry *entries = stream->ra_entries;
5577   guint n_entries = stream->n_ra_entries;
5578   guint i;
5579
5580   /* we assume the table is sorted */
5581   for (i = 0; i < n_entries; ++i) {
5582     if (entries[i].ts > pos)
5583       break;
5584   }
5585
5586   /* FIXME: maybe save first moof_offset somewhere instead, but for now it's
5587    * probably okay to assume that the index lists the very first fragment */
5588   if (i == 0)
5589     return &entries[0];
5590
5591   if (after)
5592     return &entries[i];
5593   else
5594     return &entries[i - 1];
5595 }
5596
5597 static gboolean
5598 gst_qtdemux_do_fragmented_seek (GstQTDemux * qtdemux)
5599 {
5600   const QtDemuxRandomAccessEntry *best_entry = NULL;
5601   guint i;
5602
5603   GST_OBJECT_LOCK (qtdemux);
5604
5605   g_assert (qtdemux->n_streams > 0);
5606
5607   for (i = 0; i < qtdemux->n_streams; i++) {
5608     const QtDemuxRandomAccessEntry *entry;
5609     QtDemuxStream *stream;
5610     gboolean is_audio_or_video;
5611
5612     stream = qtdemux->streams[i];
5613
5614     g_free (stream->samples);
5615     stream->samples = NULL;
5616     stream->n_samples = 0;
5617     stream->stbl_index = -1;    /* no samples have yet been parsed */
5618     stream->sample_index = -1;
5619
5620     if (stream->protection_scheme_info) {
5621       /* Clear out any old cenc crypto info entries as we'll move to a new moof */
5622       if (stream->protection_scheme_type == FOURCC_cenc) {
5623         QtDemuxCencSampleSetInfo *info =
5624             (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
5625         if (info->crypto_info) {
5626           g_ptr_array_free (info->crypto_info, TRUE);
5627           info->crypto_info = NULL;
5628         }
5629       }
5630     }
5631
5632     if (stream->ra_entries == NULL)
5633       continue;
5634
5635     if (stream->subtype == FOURCC_vide || stream->subtype == FOURCC_soun)
5636       is_audio_or_video = TRUE;
5637     else
5638       is_audio_or_video = FALSE;
5639
5640     entry =
5641         gst_qtdemux_stream_seek_fragment (qtdemux, stream,
5642         stream->time_position, !is_audio_or_video);
5643
5644     GST_INFO_OBJECT (stream->pad, "%" GST_TIME_FORMAT " at offset "
5645         "%" G_GUINT64_FORMAT, GST_TIME_ARGS (entry->ts), entry->moof_offset);
5646
5647     stream->pending_seek = entry;
5648
5649     /* decide position to jump to just based on audio/video tracks, not subs */
5650     if (!is_audio_or_video)
5651       continue;
5652
5653     if (best_entry == NULL || entry->moof_offset < best_entry->moof_offset)
5654       best_entry = entry;
5655   }
5656
5657   if (best_entry == NULL) {
5658     GST_OBJECT_UNLOCK (qtdemux);
5659     return FALSE;
5660   }
5661
5662   GST_INFO_OBJECT (qtdemux, "seek to %" GST_TIME_FORMAT ", best fragment "
5663       "moof offset: %" G_GUINT64_FORMAT ", ts %" GST_TIME_FORMAT,
5664       GST_TIME_ARGS (qtdemux->streams[0]->time_position),
5665       best_entry->moof_offset, GST_TIME_ARGS (best_entry->ts));
5666
5667   qtdemux->moof_offset = best_entry->moof_offset;
5668
5669   qtdemux_add_fragmented_samples (qtdemux);
5670
5671   GST_OBJECT_UNLOCK (qtdemux);
5672   return TRUE;
5673 }
5674
5675 static GstFlowReturn
5676 gst_qtdemux_loop_state_movie (GstQTDemux * qtdemux)
5677 {
5678   GstFlowReturn ret = GST_FLOW_OK;
5679   GstBuffer *buf = NULL;
5680   QtDemuxStream *stream;
5681   GstClockTime min_time;
5682   guint64 offset = 0;
5683   GstClockTime dts = GST_CLOCK_TIME_NONE;
5684   GstClockTime pts = GST_CLOCK_TIME_NONE;
5685   GstClockTime duration = 0;
5686   gboolean keyframe = FALSE;
5687   guint sample_size = 0;
5688   gboolean empty = 0;
5689   guint size;
5690   gint index;
5691   gint i;
5692
5693   gst_qtdemux_push_pending_newsegment (qtdemux);
5694
5695   if (qtdemux->fragmented_seek_pending) {
5696     GST_INFO_OBJECT (qtdemux, "pending fragmented seek");
5697     gst_qtdemux_do_fragmented_seek (qtdemux);
5698     GST_INFO_OBJECT (qtdemux, "fragmented seek done!");
5699     qtdemux->fragmented_seek_pending = FALSE;
5700   }
5701
5702   /* Figure out the next stream sample to output, min_time is expressed in
5703    * global time and runs over the edit list segments. */
5704   min_time = G_MAXUINT64;
5705   index = -1;
5706   for (i = 0; i < qtdemux->n_streams; i++) {
5707     GstClockTime position;
5708
5709     stream = qtdemux->streams[i];
5710     position = stream->time_position;
5711
5712     /* position of -1 is EOS */
5713     if (position != GST_CLOCK_TIME_NONE && position < min_time) {
5714       min_time = position;
5715       index = i;
5716     }
5717   }
5718   /* all are EOS */
5719   if (G_UNLIKELY (index == -1)) {
5720     GST_DEBUG_OBJECT (qtdemux, "all streams are EOS");
5721     goto eos;
5722   }
5723
5724   /* check for segment end */
5725   if (G_UNLIKELY (qtdemux->segment.stop != -1
5726           && ((qtdemux->segment.rate >= 0 && qtdemux->segment.stop <= min_time)
5727               || (qtdemux->segment.rate < 0
5728                   && qtdemux->segment.start > min_time))
5729           && qtdemux->streams[index]->on_keyframe)) {
5730     GST_DEBUG_OBJECT (qtdemux, "we reached the end of our segment.");
5731     qtdemux->streams[index]->time_position = GST_CLOCK_TIME_NONE;
5732     goto eos_stream;
5733   }
5734
5735   /* gap events for subtitle streams */
5736   for (i = 0; i < qtdemux->n_streams; i++) {
5737     stream = qtdemux->streams[i];
5738     if (stream->pad && (stream->subtype == FOURCC_subp
5739             || stream->subtype == FOURCC_text
5740             || stream->subtype == FOURCC_sbtl)) {
5741       /* send one second gap events until the stream catches up */
5742       /* gaps can only be sent after segment is activated (segment.stop is no longer -1) */
5743       while (GST_CLOCK_TIME_IS_VALID (stream->segment.stop) &&
5744           GST_CLOCK_TIME_IS_VALID (stream->segment.position) &&
5745           stream->segment.position + GST_SECOND < min_time) {
5746         GstEvent *gap =
5747             gst_event_new_gap (stream->segment.position, GST_SECOND);
5748         gst_pad_push_event (stream->pad, gap);
5749         stream->segment.position += GST_SECOND;
5750       }
5751     }
5752   }
5753
5754   stream = qtdemux->streams[index];
5755   /* fetch info for the current sample of this stream */
5756   if (G_UNLIKELY (!gst_qtdemux_prepare_current_sample (qtdemux, stream, &empty,
5757               &offset, &sample_size, &dts, &pts, &duration, &keyframe)))
5758     goto eos_stream;
5759
5760   gst_qtdemux_stream_check_and_change_stsd_index (qtdemux, stream);
5761   if (stream->new_caps) {
5762     gst_qtdemux_configure_stream (qtdemux, stream);
5763     qtdemux_do_allocation (qtdemux, stream);
5764   }
5765
5766   /* If we're doing a keyframe-only trickmode, only push keyframes on video streams */
5767   if (G_UNLIKELY (qtdemux->
5768           segment.flags & GST_SEGMENT_FLAG_TRICKMODE_KEY_UNITS)) {
5769     if (stream->subtype == FOURCC_vide && !keyframe) {
5770       GST_LOG_OBJECT (qtdemux, "Skipping non-keyframe on stream %d", index);
5771       goto next;
5772     }
5773   }
5774
5775   GST_DEBUG_OBJECT (qtdemux,
5776       "pushing from stream %d, empty %d offset %" G_GUINT64_FORMAT
5777       ", size %d, dts=%" GST_TIME_FORMAT ", pts=%" GST_TIME_FORMAT
5778       ", duration %" GST_TIME_FORMAT, index, empty, offset, sample_size,
5779       GST_TIME_ARGS (dts), GST_TIME_ARGS (pts), GST_TIME_ARGS (duration));
5780
5781   if (G_UNLIKELY (empty)) {
5782     /* empty segment, push a gap and move to the next one */
5783     gst_pad_push_event (stream->pad, gst_event_new_gap (pts, duration));
5784     stream->segment.position = pts + duration;
5785     goto next;
5786   }
5787
5788   /* hmm, empty sample, skip and move to next sample */
5789   if (G_UNLIKELY (sample_size <= 0))
5790     goto next;
5791
5792   /* last pushed sample was out of boundary, goto next sample */
5793   if (G_UNLIKELY (GST_PAD_LAST_FLOW_RETURN (stream->pad) == GST_FLOW_EOS))
5794     goto next;
5795
5796   if (stream->max_buffer_size == 0 || sample_size <= stream->max_buffer_size) {
5797     size = sample_size;
5798   } else {
5799     GST_DEBUG_OBJECT (qtdemux,
5800         "size %d larger than stream max_buffer_size %d, trimming",
5801         sample_size, stream->max_buffer_size);
5802     size =
5803         MIN (sample_size - stream->offset_in_sample, stream->max_buffer_size);
5804   }
5805
5806   if (qtdemux->cenc_aux_info_offset > 0) {
5807     GstMapInfo map;
5808     GstByteReader br;
5809     GstBuffer *aux_info = NULL;
5810
5811     /* pull the data stored before the sample */
5812     ret =
5813         gst_qtdemux_pull_atom (qtdemux, qtdemux->offset,
5814         offset + stream->offset_in_sample - qtdemux->offset, &aux_info);
5815     if (G_UNLIKELY (ret != GST_FLOW_OK))
5816       goto beach;
5817     gst_buffer_map (aux_info, &map, GST_MAP_READ);
5818     GST_DEBUG_OBJECT (qtdemux, "parsing cenc auxiliary info");
5819     gst_byte_reader_init (&br, map.data + 8, map.size);
5820     if (!qtdemux_parse_cenc_aux_info (qtdemux, stream, &br,
5821             qtdemux->cenc_aux_info_sizes, qtdemux->cenc_aux_sample_count)) {
5822       GST_ERROR_OBJECT (qtdemux, "failed to parse cenc auxiliary info");
5823       gst_buffer_unmap (aux_info, &map);
5824       gst_buffer_unref (aux_info);
5825       ret = GST_FLOW_ERROR;
5826       goto beach;
5827     }
5828     gst_buffer_unmap (aux_info, &map);
5829     gst_buffer_unref (aux_info);
5830   }
5831
5832   GST_LOG_OBJECT (qtdemux, "reading %d bytes @ %" G_GUINT64_FORMAT, size,
5833       offset);
5834
5835   if (stream->use_allocator) {
5836     /* if we have a per-stream allocator, use it */
5837     buf = gst_buffer_new_allocate (stream->allocator, size, &stream->params);
5838   }
5839
5840   ret = gst_qtdemux_pull_atom (qtdemux, offset + stream->offset_in_sample,
5841       size, &buf);
5842   if (G_UNLIKELY (ret != GST_FLOW_OK))
5843     goto beach;
5844
5845   if (size != sample_size) {
5846     pts += gst_util_uint64_scale_int (GST_SECOND,
5847         stream->offset_in_sample / CUR_STREAM (stream)->bytes_per_frame,
5848         stream->timescale);
5849     dts +=
5850         gst_util_uint64_scale_int (GST_SECOND,
5851         stream->offset_in_sample / CUR_STREAM (stream)->bytes_per_frame,
5852         stream->timescale);
5853     duration =
5854         gst_util_uint64_scale_int (GST_SECOND,
5855         size / CUR_STREAM (stream)->bytes_per_frame, stream->timescale);
5856   }
5857
5858   ret = gst_qtdemux_decorate_and_push_buffer (qtdemux, stream, buf,
5859       dts, pts, duration, keyframe, min_time, offset);
5860
5861   if (size != sample_size) {
5862     QtDemuxSample *sample = &stream->samples[stream->sample_index];
5863     QtDemuxSegment *segment = &stream->segments[stream->segment_index];
5864
5865     GstClockTime time_position = QTSTREAMTIME_TO_GSTTIME (stream,
5866         sample->timestamp +
5867         stream->offset_in_sample / CUR_STREAM (stream)->bytes_per_frame);
5868     if (time_position >= segment->media_start) {
5869       /* inside the segment, update time_position, looks very familiar to
5870        * GStreamer segments, doesn't it? */
5871       stream->time_position = (time_position - segment->media_start) +
5872           segment->time;
5873     } else {
5874       /* not yet in segment, time does not yet increment. This means
5875        * that we are still prerolling keyframes to the decoder so it can
5876        * decode the first sample of the segment. */
5877       stream->time_position = segment->time;
5878     }
5879   }
5880
5881   /* combine flows */
5882   ret = gst_qtdemux_combine_flows (qtdemux, stream, ret);
5883   /* ignore unlinked, we will not push on the pad anymore and we will EOS when
5884    * we have no more data for the pad to push */
5885   if (ret == GST_FLOW_EOS)
5886     ret = GST_FLOW_OK;
5887
5888   stream->offset_in_sample += size;
5889   if (stream->offset_in_sample >= sample_size) {
5890     gst_qtdemux_advance_sample (qtdemux, stream);
5891   }
5892   goto beach;
5893
5894 next:
5895   gst_qtdemux_advance_sample (qtdemux, stream);
5896
5897 beach:
5898   return ret;
5899
5900   /* special cases */
5901 eos:
5902   {
5903     GST_DEBUG_OBJECT (qtdemux, "No samples left for any streams - EOS");
5904     ret = GST_FLOW_EOS;
5905     goto beach;
5906   }
5907 eos_stream:
5908   {
5909     GST_DEBUG_OBJECT (qtdemux, "No samples left for stream");
5910     /* EOS will be raised if all are EOS */
5911     ret = GST_FLOW_OK;
5912     goto beach;
5913   }
5914 }
5915
5916 static void
5917 gst_qtdemux_loop (GstPad * pad)
5918 {
5919   GstQTDemux *qtdemux;
5920   guint64 cur_offset;
5921   GstFlowReturn ret;
5922
5923   qtdemux = GST_QTDEMUX (gst_pad_get_parent (pad));
5924
5925   cur_offset = qtdemux->offset;
5926   GST_LOG_OBJECT (qtdemux, "loop at position %" G_GUINT64_FORMAT ", state %s",
5927       cur_offset, qt_demux_state_string (qtdemux->state));
5928
5929   switch (qtdemux->state) {
5930     case QTDEMUX_STATE_INITIAL:
5931     case QTDEMUX_STATE_HEADER:
5932       ret = gst_qtdemux_loop_state_header (qtdemux);
5933       break;
5934     case QTDEMUX_STATE_MOVIE:
5935       ret = gst_qtdemux_loop_state_movie (qtdemux);
5936       if (qtdemux->segment.rate < 0 && ret == GST_FLOW_EOS) {
5937         ret = gst_qtdemux_seek_to_previous_keyframe (qtdemux);
5938       }
5939       break;
5940     default:
5941       /* ouch */
5942       goto invalid_state;
5943   }
5944
5945   /* if something went wrong, pause */
5946   if (ret != GST_FLOW_OK)
5947     goto pause;
5948
5949 done:
5950   gst_object_unref (qtdemux);
5951   return;
5952
5953   /* ERRORS */
5954 invalid_state:
5955   {
5956     GST_ELEMENT_ERROR (qtdemux, STREAM, FAILED,
5957         (NULL), ("streaming stopped, invalid state"));
5958     gst_pad_pause_task (pad);
5959     gst_qtdemux_push_event (qtdemux, gst_event_new_eos ());
5960     goto done;
5961   }
5962 pause:
5963   {
5964     const gchar *reason = gst_flow_get_name (ret);
5965
5966     GST_LOG_OBJECT (qtdemux, "pausing task, reason %s", reason);
5967
5968     gst_pad_pause_task (pad);
5969
5970     /* fatal errors need special actions */
5971     /* check EOS */
5972     if (ret == GST_FLOW_EOS) {
5973       if (qtdemux->n_streams == 0) {
5974         /* we have no streams, post an error */
5975         gst_qtdemux_post_no_playable_stream_error (qtdemux);
5976       }
5977       if (qtdemux->segment.flags & GST_SEEK_FLAG_SEGMENT) {
5978         gint64 stop;
5979
5980         if ((stop = qtdemux->segment.stop) == -1)
5981           stop = qtdemux->segment.duration;
5982
5983         if (qtdemux->segment.rate >= 0) {
5984           GstMessage *message;
5985           GstEvent *event;
5986
5987           GST_LOG_OBJECT (qtdemux, "Sending segment done, at end of segment");
5988           message = gst_message_new_segment_done (GST_OBJECT_CAST (qtdemux),
5989               GST_FORMAT_TIME, stop);
5990           event = gst_event_new_segment_done (GST_FORMAT_TIME, stop);
5991           if (qtdemux->segment_seqnum) {
5992             gst_message_set_seqnum (message, qtdemux->segment_seqnum);
5993             gst_event_set_seqnum (event, qtdemux->segment_seqnum);
5994           }
5995           gst_element_post_message (GST_ELEMENT_CAST (qtdemux), message);
5996           gst_qtdemux_push_event (qtdemux, event);
5997         } else {
5998           GstMessage *message;
5999           GstEvent *event;
6000
6001           /*  For Reverse Playback */
6002           GST_LOG_OBJECT (qtdemux, "Sending segment done, at start of segment");
6003           message = gst_message_new_segment_done (GST_OBJECT_CAST (qtdemux),
6004               GST_FORMAT_TIME, qtdemux->segment.start);
6005           event = gst_event_new_segment_done (GST_FORMAT_TIME,
6006               qtdemux->segment.start);
6007           if (qtdemux->segment_seqnum) {
6008             gst_message_set_seqnum (message, qtdemux->segment_seqnum);
6009             gst_event_set_seqnum (event, qtdemux->segment_seqnum);
6010           }
6011           gst_element_post_message (GST_ELEMENT_CAST (qtdemux), message);
6012           gst_qtdemux_push_event (qtdemux, event);
6013         }
6014       } else {
6015         GstEvent *event;
6016
6017         GST_LOG_OBJECT (qtdemux, "Sending EOS at end of segment");
6018         event = gst_event_new_eos ();
6019         if (qtdemux->segment_seqnum)
6020           gst_event_set_seqnum (event, qtdemux->segment_seqnum);
6021         gst_qtdemux_push_event (qtdemux, event);
6022       }
6023     } else if (ret == GST_FLOW_NOT_LINKED || ret < GST_FLOW_EOS) {
6024       GST_ELEMENT_FLOW_ERROR (qtdemux, ret);
6025       gst_qtdemux_push_event (qtdemux, gst_event_new_eos ());
6026     }
6027     goto done;
6028   }
6029 }
6030
6031 /*
6032  * has_next_entry
6033  *
6034  * Returns if there are samples to be played.
6035  */
6036 static gboolean
6037 has_next_entry (GstQTDemux * demux)
6038 {
6039   QtDemuxStream *stream;
6040   int i;
6041
6042   GST_DEBUG_OBJECT (demux, "Checking if there are samples not played yet");
6043
6044   for (i = 0; i < demux->n_streams; i++) {
6045     stream = demux->streams[i];
6046
6047     if (stream->sample_index == -1) {
6048       stream->sample_index = 0;
6049       stream->offset_in_sample = 0;
6050     }
6051
6052     if (stream->sample_index >= stream->n_samples) {
6053       GST_LOG_OBJECT (demux, "stream %d samples exhausted", i);
6054       continue;
6055     }
6056     GST_DEBUG_OBJECT (demux, "Found a sample");
6057     return TRUE;
6058   }
6059
6060   GST_DEBUG_OBJECT (demux, "There wasn't any next sample");
6061   return FALSE;
6062 }
6063
6064 /*
6065  * next_entry_size
6066  *
6067  * Returns the size of the first entry at the current offset.
6068  * If -1, there are none (which means EOS or empty file).
6069  */
6070 static guint64
6071 next_entry_size (GstQTDemux * demux)
6072 {
6073   QtDemuxStream *stream;
6074   int i;
6075   int smallidx = -1;
6076   guint64 smalloffs = (guint64) - 1;
6077   QtDemuxSample *sample;
6078
6079   GST_LOG_OBJECT (demux, "Finding entry at offset %" G_GUINT64_FORMAT,
6080       demux->offset);
6081
6082   for (i = 0; i < demux->n_streams; i++) {
6083     stream = demux->streams[i];
6084
6085     if (stream->sample_index == -1) {
6086       stream->sample_index = 0;
6087       stream->offset_in_sample = 0;
6088     }
6089
6090     if (stream->sample_index >= stream->n_samples) {
6091       GST_LOG_OBJECT (demux, "stream %d samples exhausted", i);
6092       continue;
6093     }
6094
6095     if (!qtdemux_parse_samples (demux, stream, stream->sample_index)) {
6096       GST_LOG_OBJECT (demux, "Parsing of index %u from stbl atom failed!",
6097           stream->sample_index);
6098       return -1;
6099     }
6100
6101     sample = &stream->samples[stream->sample_index];
6102
6103     GST_LOG_OBJECT (demux,
6104         "Checking Stream %d (sample_index:%d / offset:%" G_GUINT64_FORMAT
6105         " / size:%" G_GUINT32_FORMAT ")", i, stream->sample_index,
6106         sample->offset, sample->size);
6107
6108     if (((smalloffs == -1)
6109             || (sample->offset < smalloffs)) && (sample->size)) {
6110       smallidx = i;
6111       smalloffs = sample->offset;
6112     }
6113   }
6114
6115   GST_LOG_OBJECT (demux,
6116       "stream %d offset %" G_GUINT64_FORMAT " demux->offset :%"
6117       G_GUINT64_FORMAT, smallidx, smalloffs, demux->offset);
6118
6119   if (smallidx == -1)
6120     return -1;
6121
6122   stream = demux->streams[smallidx];
6123   sample = &stream->samples[stream->sample_index];
6124
6125   if (sample->offset >= demux->offset) {
6126     demux->todrop = sample->offset - demux->offset;
6127     return sample->size + demux->todrop;
6128   }
6129
6130   GST_DEBUG_OBJECT (demux,
6131       "There wasn't any entry at offset %" G_GUINT64_FORMAT, demux->offset);
6132   return -1;
6133 }
6134
6135 static void
6136 gst_qtdemux_post_progress (GstQTDemux * demux, gint num, gint denom)
6137 {
6138   gint perc = (gint) ((gdouble) num * 100.0 / (gdouble) denom);
6139
6140   gst_element_post_message (GST_ELEMENT_CAST (demux),
6141       gst_message_new_element (GST_OBJECT_CAST (demux),
6142           gst_structure_new ("progress", "percent", G_TYPE_INT, perc, NULL)));
6143 }
6144
6145 static gboolean
6146 qtdemux_seek_offset (GstQTDemux * demux, guint64 offset)
6147 {
6148   GstEvent *event;
6149   gboolean res = 0;
6150
6151   GST_DEBUG_OBJECT (demux, "Seeking to %" G_GUINT64_FORMAT, offset);
6152
6153   event =
6154       gst_event_new_seek (1.0, GST_FORMAT_BYTES,
6155       GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_ACCURATE, GST_SEEK_TYPE_SET, offset,
6156       GST_SEEK_TYPE_NONE, -1);
6157
6158   /* store seqnum to drop flush events, they don't need to reach downstream */
6159   demux->offset_seek_seqnum = gst_event_get_seqnum (event);
6160   res = gst_pad_push_event (demux->sinkpad, event);
6161   demux->offset_seek_seqnum = 0;
6162
6163   return res;
6164 }
6165
6166 /* check for seekable upstream, above and beyond a mere query */
6167 static void
6168 gst_qtdemux_check_seekability (GstQTDemux * demux)
6169 {
6170   GstQuery *query;
6171   gboolean seekable = FALSE;
6172   gint64 start = -1, stop = -1;
6173
6174   if (demux->upstream_size)
6175     return;
6176
6177   if (demux->upstream_format_is_time)
6178     return;
6179
6180   query = gst_query_new_seeking (GST_FORMAT_BYTES);
6181   if (!gst_pad_peer_query (demux->sinkpad, query)) {
6182     GST_DEBUG_OBJECT (demux, "seeking query failed");
6183     goto done;
6184   }
6185
6186   gst_query_parse_seeking (query, NULL, &seekable, &start, &stop);
6187
6188   /* try harder to query upstream size if we didn't get it the first time */
6189   if (seekable && stop == -1) {
6190     GST_DEBUG_OBJECT (demux, "doing duration query to fix up unset stop");
6191     gst_pad_peer_query_duration (demux->sinkpad, GST_FORMAT_BYTES, &stop);
6192   }
6193
6194   /* if upstream doesn't know the size, it's likely that it's not seekable in
6195    * practice even if it technically may be seekable */
6196   if (seekable && (start != 0 || stop <= start)) {
6197     GST_DEBUG_OBJECT (demux, "seekable but unknown start/stop -> disable");
6198     seekable = FALSE;
6199   }
6200
6201 done:
6202   gst_query_unref (query);
6203
6204   GST_DEBUG_OBJECT (demux, "seekable: %d (%" G_GUINT64_FORMAT " - %"
6205       G_GUINT64_FORMAT ")", seekable, start, stop);
6206   demux->upstream_seekable = seekable;
6207   demux->upstream_size = seekable ? stop : -1;
6208 }
6209
6210 static void
6211 gst_qtdemux_drop_data (GstQTDemux * demux, gint bytes)
6212 {
6213   g_return_if_fail (bytes <= demux->todrop);
6214
6215   GST_LOG_OBJECT (demux, "Dropping %d bytes", bytes);
6216   gst_adapter_flush (demux->adapter, bytes);
6217   demux->neededbytes -= bytes;
6218   demux->offset += bytes;
6219   demux->todrop -= bytes;
6220 }
6221
6222 static void
6223 gst_qtdemux_check_send_pending_segment (GstQTDemux * demux)
6224 {
6225   if (G_UNLIKELY (demux->pending_newsegment)) {
6226     gint i;
6227
6228     gst_qtdemux_push_pending_newsegment (demux);
6229     /* clear to send tags on all streams */
6230     for (i = 0; i < demux->n_streams; i++) {
6231       QtDemuxStream *stream;
6232       stream = demux->streams[i];
6233       gst_qtdemux_push_tags (demux, stream);
6234       if (CUR_STREAM (stream)->sparse) {
6235         GST_INFO_OBJECT (demux, "Sending gap event on stream %d", i);
6236         gst_pad_push_event (stream->pad,
6237             gst_event_new_gap (stream->segment.position, GST_CLOCK_TIME_NONE));
6238       }
6239     }
6240   }
6241 }
6242
6243 static void
6244 gst_qtdemux_send_gap_for_segment (GstQTDemux * demux,
6245     QtDemuxStream * stream, gint segment_index, GstClockTime pos)
6246 {
6247   GstClockTime ts, dur;
6248   GstEvent *gap;
6249
6250   ts = pos;
6251   dur =
6252       stream->segments[segment_index].duration - (pos -
6253       stream->segments[segment_index].time);
6254   gap = gst_event_new_gap (ts, dur);
6255   stream->time_position += dur;
6256
6257   GST_DEBUG_OBJECT (stream->pad, "Pushing gap for empty "
6258       "segment: %" GST_PTR_FORMAT, gap);
6259   gst_pad_push_event (stream->pad, gap);
6260 }
6261
6262 static void
6263 gst_qtdemux_stream_send_initial_gap_segments (GstQTDemux * demux,
6264     QtDemuxStream * stream)
6265 {
6266   gint i;
6267
6268   /* Push any initial gap segments before proceeding to the
6269    * 'real' data */
6270   for (i = 0; i < stream->n_segments; i++) {
6271     gst_qtdemux_activate_segment (demux, stream, i, stream->time_position);
6272
6273     if (QTSEGMENT_IS_EMPTY (&stream->segments[i])) {
6274       gst_qtdemux_send_gap_for_segment (demux, stream, i,
6275           stream->time_position);
6276     } else {
6277       /* Only support empty segment at the beginning followed by
6278        * one non-empty segment, this was checked when parsing the
6279        * edts atom, arriving here is unexpected */
6280       g_assert (i + 1 == stream->n_segments);
6281       break;
6282     }
6283   }
6284 }
6285
6286 static GstFlowReturn
6287 gst_qtdemux_chain (GstPad * sinkpad, GstObject * parent, GstBuffer * inbuf)
6288 {
6289   GstQTDemux *demux;
6290
6291   demux = GST_QTDEMUX (parent);
6292
6293   GST_DEBUG_OBJECT (demux,
6294       "Received buffer pts:%" GST_TIME_FORMAT " dts:%" GST_TIME_FORMAT
6295       " offset:%" G_GUINT64_FORMAT " size:%" G_GSIZE_FORMAT " demux offset:%"
6296       G_GUINT64_FORMAT, GST_TIME_ARGS (GST_BUFFER_PTS (inbuf)),
6297       GST_TIME_ARGS (GST_BUFFER_DTS (inbuf)), GST_BUFFER_OFFSET (inbuf),
6298       gst_buffer_get_size (inbuf), demux->offset);
6299
6300   if (GST_BUFFER_FLAG_IS_SET (inbuf, GST_BUFFER_FLAG_DISCONT)) {
6301     gboolean is_gap_input = FALSE;
6302     gint i;
6303
6304     GST_DEBUG_OBJECT (demux, "Got DISCONT, marking all streams as DISCONT");
6305
6306     for (i = 0; i < demux->n_streams; i++) {
6307       demux->streams[i]->discont = TRUE;
6308     }
6309
6310     /* Check if we can land back on our feet in the case where upstream is
6311      * handling the seeking/pushing of samples with gaps in between (like
6312      * in the case of trick-mode DASH for example) */
6313     if (demux->upstream_format_is_time
6314         && GST_BUFFER_OFFSET (inbuf) != GST_BUFFER_OFFSET_NONE) {
6315       gint i;
6316       for (i = 0; i < demux->n_streams; i++) {
6317         guint32 res;
6318         GST_LOG_OBJECT (demux,
6319             "Stream #%d , checking if offset %" G_GUINT64_FORMAT
6320             " is a sample start", i, GST_BUFFER_OFFSET (inbuf));
6321         res =
6322             gst_qtdemux_find_index_for_given_media_offset_linear (demux,
6323             demux->streams[i], GST_BUFFER_OFFSET (inbuf));
6324         if (res != -1) {
6325           QtDemuxSample *sample = &demux->streams[i]->samples[res];
6326           GST_LOG_OBJECT (demux,
6327               "Checking if sample %d from stream %d is valid (offset:%"
6328               G_GUINT64_FORMAT " size:%" G_GUINT32_FORMAT ")", res, i,
6329               sample->offset, sample->size);
6330           if (sample->offset == GST_BUFFER_OFFSET (inbuf)) {
6331             GST_LOG_OBJECT (demux,
6332                 "new buffer corresponds to a valid sample : %" G_GUINT32_FORMAT,
6333                 res);
6334             is_gap_input = TRUE;
6335             /* We can go back to standard playback mode */
6336             demux->state = QTDEMUX_STATE_MOVIE;
6337             /* Remember which sample this stream is at */
6338             demux->streams[i]->sample_index = res;
6339             /* Finally update all push-based values to the expected values */
6340             demux->neededbytes = demux->streams[i]->samples[res].size;
6341             demux->offset = GST_BUFFER_OFFSET (inbuf);
6342             demux->mdatleft =
6343                 demux->mdatsize - demux->offset + demux->mdatoffset;
6344             demux->todrop = 0;
6345           }
6346         }
6347       }
6348       if (!is_gap_input) {
6349         GST_DEBUG_OBJECT (demux, "Resetting, actual DISCONT");
6350         /* Reset state if it's a real discont */
6351         demux->neededbytes = 16;
6352         demux->state = QTDEMUX_STATE_INITIAL;
6353         demux->offset = GST_BUFFER_OFFSET (inbuf);
6354         gst_adapter_clear (demux->adapter);
6355       }
6356     }
6357     /* Reverse fragmented playback, need to flush all we have before
6358      * consuming a new fragment.
6359      * The samples array have the timestamps calculated by accumulating the
6360      * durations but this won't work for reverse playback of fragments as
6361      * the timestamps of a subsequent fragment should be smaller than the
6362      * previously received one. */
6363     if (!is_gap_input && demux->fragmented && demux->segment.rate < 0) {
6364       gst_qtdemux_process_adapter (demux, TRUE);
6365       for (i = 0; i < demux->n_streams; i++)
6366         gst_qtdemux_stream_flush_samples_data (demux, demux->streams[i]);
6367     }
6368   }
6369
6370   gst_adapter_push (demux->adapter, inbuf);
6371
6372   GST_DEBUG_OBJECT (demux,
6373       "pushing in inbuf %p, neededbytes:%u, available:%" G_GSIZE_FORMAT, inbuf,
6374       demux->neededbytes, gst_adapter_available (demux->adapter));
6375
6376   return gst_qtdemux_process_adapter (demux, FALSE);
6377 }
6378
6379 static GstFlowReturn
6380 gst_qtdemux_process_adapter (GstQTDemux * demux, gboolean force)
6381 {
6382   GstFlowReturn ret = GST_FLOW_OK;
6383
6384   /* we never really mean to buffer that much */
6385   if (demux->neededbytes == -1) {
6386     goto eos;
6387   }
6388
6389   while (((gst_adapter_available (demux->adapter)) >= demux->neededbytes) &&
6390       (ret == GST_FLOW_OK || (ret == GST_FLOW_NOT_LINKED && force))) {
6391
6392 #ifndef GST_DISABLE_GST_DEBUG
6393     {
6394       guint64 discont_offset, distance_from_discont;
6395
6396       discont_offset = gst_adapter_offset_at_discont (demux->adapter);
6397       distance_from_discont =
6398           gst_adapter_distance_from_discont (demux->adapter);
6399
6400       GST_DEBUG_OBJECT (demux,
6401           "state:%s , demux->neededbytes:%d, demux->offset:%" G_GUINT64_FORMAT
6402           " adapter offset :%" G_GUINT64_FORMAT " (+ %" G_GUINT64_FORMAT
6403           " bytes)", qt_demux_state_string (demux->state), demux->neededbytes,
6404           demux->offset, discont_offset, distance_from_discont);
6405     }
6406 #endif
6407
6408     switch (demux->state) {
6409       case QTDEMUX_STATE_INITIAL:{
6410         const guint8 *data;
6411         guint32 fourcc;
6412         guint64 size;
6413
6414         gst_qtdemux_check_seekability (demux);
6415
6416         data = gst_adapter_map (demux->adapter, demux->neededbytes);
6417
6418         /* get fourcc/length, set neededbytes */
6419         extract_initial_length_and_fourcc ((guint8 *) data, demux->neededbytes,
6420             &size, &fourcc);
6421         gst_adapter_unmap (demux->adapter);
6422         data = NULL;
6423         GST_DEBUG_OBJECT (demux, "Peeking found [%" GST_FOURCC_FORMAT "] "
6424             "size: %" G_GUINT64_FORMAT, GST_FOURCC_ARGS (fourcc), size);
6425         if (size == 0) {
6426           GST_ELEMENT_ERROR (demux, STREAM, DEMUX,
6427               (_("This file is invalid and cannot be played.")),
6428               ("initial atom '%" GST_FOURCC_FORMAT "' has empty length",
6429                   GST_FOURCC_ARGS (fourcc)));
6430           ret = GST_FLOW_ERROR;
6431           break;
6432         }
6433         if (fourcc == FOURCC_mdat) {
6434           gint next_entry = next_entry_size (demux);
6435           if (demux->n_streams > 0 && (next_entry != -1 || !demux->fragmented)) {
6436             /* we have the headers, start playback */
6437             demux->state = QTDEMUX_STATE_MOVIE;
6438             demux->neededbytes = next_entry;
6439             demux->mdatleft = size;
6440             demux->mdatsize = demux->mdatleft;
6441           } else {
6442             /* no headers yet, try to get them */
6443             guint bs;
6444             gboolean res;
6445             guint64 old, target;
6446
6447           buffer_data:
6448             old = demux->offset;
6449             target = old + size;
6450
6451             /* try to jump over the atom with a seek */
6452             /* only bother if it seems worth doing so,
6453              * and avoids possible upstream/server problems */
6454             if (demux->upstream_seekable &&
6455                 demux->upstream_size > 4 * (1 << 20)) {
6456               res = qtdemux_seek_offset (demux, target);
6457             } else {
6458               GST_DEBUG_OBJECT (demux, "skipping seek");
6459               res = FALSE;
6460             }
6461
6462             if (res) {
6463               GST_DEBUG_OBJECT (demux, "seek success");
6464               /* remember the offset fo the first mdat so we can seek back to it
6465                * after we have the headers */
6466               if (fourcc == FOURCC_mdat && demux->first_mdat == -1) {
6467                 demux->first_mdat = old;
6468                 GST_DEBUG_OBJECT (demux, "first mdat at %" G_GUINT64_FORMAT,
6469                     demux->first_mdat);
6470               }
6471               /* seek worked, continue reading */
6472               demux->offset = target;
6473               demux->neededbytes = 16;
6474               demux->state = QTDEMUX_STATE_INITIAL;
6475             } else {
6476               /* seek failed, need to buffer */
6477               demux->offset = old;
6478               GST_DEBUG_OBJECT (demux, "seek failed/skipped");
6479               /* there may be multiple mdat (or alike) buffers */
6480               /* sanity check */
6481               if (demux->mdatbuffer)
6482                 bs = gst_buffer_get_size (demux->mdatbuffer);
6483               else
6484                 bs = 0;
6485               if (size + bs > 10 * (1 << 20))
6486                 goto no_moov;
6487               demux->state = QTDEMUX_STATE_BUFFER_MDAT;
6488               demux->neededbytes = size;
6489               if (!demux->mdatbuffer)
6490                 demux->mdatoffset = demux->offset;
6491             }
6492           }
6493         } else if (G_UNLIKELY (size > QTDEMUX_MAX_ATOM_SIZE)) {
6494           GST_ELEMENT_ERROR (demux, STREAM, DEMUX,
6495               (_("This file is invalid and cannot be played.")),
6496               ("atom %" GST_FOURCC_FORMAT " has bogus size %" G_GUINT64_FORMAT,
6497                   GST_FOURCC_ARGS (fourcc), size));
6498           ret = GST_FLOW_ERROR;
6499           break;
6500         } else {
6501           /* this means we already started buffering and still no moov header,
6502            * let's continue buffering everything till we get moov */
6503           if (demux->mdatbuffer && !(fourcc == FOURCC_moov
6504                   || fourcc == FOURCC_moof))
6505             goto buffer_data;
6506           demux->neededbytes = size;
6507           demux->state = QTDEMUX_STATE_HEADER;
6508         }
6509         break;
6510       }
6511       case QTDEMUX_STATE_HEADER:{
6512         const guint8 *data;
6513         guint32 fourcc;
6514
6515         GST_DEBUG_OBJECT (demux, "In header");
6516
6517         data = gst_adapter_map (demux->adapter, demux->neededbytes);
6518
6519         /* parse the header */
6520         extract_initial_length_and_fourcc (data, demux->neededbytes, NULL,
6521             &fourcc);
6522         if (fourcc == FOURCC_moov) {
6523           gint n;
6524
6525           /* in usual fragmented setup we could try to scan for more
6526            * and end up at the the moov (after mdat) again */
6527           if (demux->got_moov && demux->n_streams > 0 &&
6528               (!demux->fragmented
6529                   || demux->last_moov_offset == demux->offset)) {
6530             GST_DEBUG_OBJECT (demux,
6531                 "Skipping moov atom as we have (this) one already");
6532           } else {
6533             GST_DEBUG_OBJECT (demux, "Parsing [moov]");
6534
6535             if (demux->got_moov && demux->fragmented) {
6536               GST_DEBUG_OBJECT (demux,
6537                   "Got a second moov, clean up data from old one");
6538               if (demux->moov_node_compressed) {
6539                 g_node_destroy (demux->moov_node_compressed);
6540                 if (demux->moov_node)
6541                   g_free (demux->moov_node->data);
6542               }
6543               demux->moov_node_compressed = NULL;
6544               if (demux->moov_node)
6545                 g_node_destroy (demux->moov_node);
6546               demux->moov_node = NULL;
6547             } else {
6548               /* prepare newsegment to send when streaming actually starts */
6549               if (!demux->pending_newsegment) {
6550                 demux->pending_newsegment =
6551                     gst_event_new_segment (&demux->segment);
6552                 if (demux->segment_seqnum)
6553                   gst_event_set_seqnum (demux->pending_newsegment,
6554                       demux->segment_seqnum);
6555               }
6556             }
6557
6558             demux->last_moov_offset = demux->offset;
6559
6560             qtdemux_parse_moov (demux, data, demux->neededbytes);
6561             qtdemux_node_dump (demux, demux->moov_node);
6562             qtdemux_parse_tree (demux);
6563             qtdemux_prepare_streams (demux);
6564             if (!demux->got_moov)
6565               qtdemux_expose_streams (demux);
6566             else {
6567
6568               for (n = 0; n < demux->n_streams; n++) {
6569                 QtDemuxStream *stream = demux->streams[n];
6570
6571                 gst_qtdemux_configure_stream (demux, stream);
6572               }
6573             }
6574
6575             demux->got_moov = TRUE;
6576             gst_qtdemux_check_send_pending_segment (demux);
6577
6578             /* fragmented streams headers shouldn't contain edts atoms */
6579             if (!demux->fragmented) {
6580               for (n = 0; n < demux->n_streams; n++) {
6581                 gst_qtdemux_stream_send_initial_gap_segments (demux,
6582                     demux->streams[n]);
6583               }
6584             }
6585
6586             if (demux->moov_node_compressed) {
6587               g_node_destroy (demux->moov_node_compressed);
6588               g_free (demux->moov_node->data);
6589             }
6590             demux->moov_node_compressed = NULL;
6591             g_node_destroy (demux->moov_node);
6592             demux->moov_node = NULL;
6593             GST_DEBUG_OBJECT (demux, "Finished parsing the header");
6594           }
6595         } else if (fourcc == FOURCC_moof) {
6596           if ((demux->got_moov || demux->media_caps) && demux->fragmented) {
6597             guint64 dist = 0;
6598             GstClockTime prev_pts;
6599             guint64 prev_offset;
6600             guint64 adapter_discont_offset, adapter_discont_dist;
6601
6602             GST_DEBUG_OBJECT (demux, "Parsing [moof]");
6603
6604             /*
6605              * The timestamp of the moof buffer is relevant as some scenarios
6606              * won't have the initial timestamp in the atoms. Whenever a new
6607              * buffer has started, we get that buffer's PTS and use it as a base
6608              * timestamp for the trun entries.
6609              *
6610              * To keep track of the current buffer timestamp and starting point
6611              * we use gst_adapter_prev_pts that gives us the PTS and the distance
6612              * from the beggining of the buffer, with the distance and demux->offset
6613              * we know if it is still the same buffer or not.
6614              */
6615             prev_pts = gst_adapter_prev_pts (demux->adapter, &dist);
6616             prev_offset = demux->offset - dist;
6617             if (demux->fragment_start_offset == -1
6618                 || prev_offset > demux->fragment_start_offset) {
6619               demux->fragment_start_offset = prev_offset;
6620               demux->fragment_start = prev_pts;
6621               GST_DEBUG_OBJECT (demux,
6622                   "New fragment start found at: %" G_GUINT64_FORMAT " : %"
6623                   GST_TIME_FORMAT, demux->fragment_start_offset,
6624                   GST_TIME_ARGS (demux->fragment_start));
6625             }
6626
6627             /* We can't use prev_offset() here because this would require
6628              * upstream to set consistent and correct offsets on all buffers
6629              * since the discont. Nothing ever did that in the past and we
6630              * would break backwards compatibility here then.
6631              * Instead take the offset we had at the last discont and count
6632              * the bytes from there. This works with old code as there would
6633              * be no discont between moov and moof, and also works with
6634              * adaptivedemux which correctly sets offset and will set the
6635              * DISCONT flag accordingly when needed.
6636              *
6637              * We also only do this for upstream TIME segments as otherwise
6638              * there are potential backwards compatibility problems with
6639              * seeking in PUSH mode and upstream providing inconsistent
6640              * timestamps. */
6641             adapter_discont_offset =
6642                 gst_adapter_offset_at_discont (demux->adapter);
6643             adapter_discont_dist =
6644                 gst_adapter_distance_from_discont (demux->adapter);
6645
6646             GST_DEBUG_OBJECT (demux,
6647                 "demux offset %" G_GUINT64_FORMAT " adapter offset %"
6648                 G_GUINT64_FORMAT " (+ %" G_GUINT64_FORMAT " bytes)",
6649                 demux->offset, adapter_discont_offset, adapter_discont_dist);
6650
6651             if (demux->upstream_format_is_time) {
6652               demux->moof_offset = adapter_discont_offset;
6653               if (demux->moof_offset != GST_BUFFER_OFFSET_NONE)
6654                 demux->moof_offset += adapter_discont_dist;
6655               if (demux->moof_offset == GST_BUFFER_OFFSET_NONE)
6656                 demux->moof_offset = demux->offset;
6657             } else {
6658               demux->moof_offset = demux->offset;
6659             }
6660
6661             if (!qtdemux_parse_moof (demux, data, demux->neededbytes,
6662                     demux->moof_offset, NULL)) {
6663               gst_adapter_unmap (demux->adapter);
6664               ret = GST_FLOW_ERROR;
6665               goto done;
6666             }
6667             /* in MSS we need to expose the pads after the first moof as we won't get a moov */
6668             if (demux->mss_mode && !demux->exposed) {
6669               if (!demux->pending_newsegment) {
6670                 GST_DEBUG_OBJECT (demux, "new pending_newsegment");
6671                 demux->pending_newsegment =
6672                     gst_event_new_segment (&demux->segment);
6673                 if (demux->segment_seqnum)
6674                   gst_event_set_seqnum (demux->pending_newsegment,
6675                       demux->segment_seqnum);
6676               }
6677               qtdemux_expose_streams (demux);
6678             }
6679           } else {
6680             GST_DEBUG_OBJECT (demux, "Discarding [moof]");
6681           }
6682         } else if (fourcc == FOURCC_ftyp) {
6683           GST_DEBUG_OBJECT (demux, "Parsing [ftyp]");
6684           qtdemux_parse_ftyp (demux, data, demux->neededbytes);
6685         } else if (fourcc == FOURCC_uuid) {
6686           GST_DEBUG_OBJECT (demux, "Parsing [uuid]");
6687           qtdemux_parse_uuid (demux, data, demux->neededbytes);
6688         } else if (fourcc == FOURCC_sidx) {
6689           GST_DEBUG_OBJECT (demux, "Parsing [sidx]");
6690           qtdemux_parse_sidx (demux, data, demux->neededbytes);
6691         } else {
6692           switch (fourcc) {
6693             case FOURCC_styp:
6694               /* [styp] is like a [ftyp], but in fragment header. We ignore it for now
6695                * FALLTHROUGH */
6696             case FOURCC_skip:
6697             case FOURCC_free:
6698               /* [free] and [skip] are padding atoms */
6699               GST_DEBUG_OBJECT (demux,
6700                   "Skipping fourcc while parsing header : %" GST_FOURCC_FORMAT,
6701                   GST_FOURCC_ARGS (fourcc));
6702               break;
6703             default:
6704               GST_WARNING_OBJECT (demux,
6705                   "Unknown fourcc while parsing header : %" GST_FOURCC_FORMAT,
6706                   GST_FOURCC_ARGS (fourcc));
6707               /* Let's jump that one and go back to initial state */
6708               break;
6709           }
6710         }
6711         gst_adapter_unmap (demux->adapter);
6712         data = NULL;
6713
6714         if (demux->mdatbuffer && demux->n_streams) {
6715           gsize remaining_data_size = 0;
6716
6717           /* the mdat was before the header */
6718           GST_DEBUG_OBJECT (demux, "We have n_streams:%d and mdatbuffer:%p",
6719               demux->n_streams, demux->mdatbuffer);
6720           /* restore our adapter/offset view of things with upstream;
6721            * put preceding buffered data ahead of current moov data.
6722            * This should also handle evil mdat, moov, mdat cases and alike */
6723           gst_adapter_flush (demux->adapter, demux->neededbytes);
6724
6725           /* Store any remaining data after the mdat for later usage */
6726           remaining_data_size = gst_adapter_available (demux->adapter);
6727           if (remaining_data_size > 0) {
6728             g_assert (demux->restoredata_buffer == NULL);
6729             demux->restoredata_buffer =
6730                 gst_adapter_take_buffer (demux->adapter, remaining_data_size);
6731             demux->restoredata_offset = demux->offset + demux->neededbytes;
6732             GST_DEBUG_OBJECT (demux,
6733                 "Stored %" G_GSIZE_FORMAT " post mdat bytes at offset %"
6734                 G_GUINT64_FORMAT, remaining_data_size,
6735                 demux->restoredata_offset);
6736           }
6737
6738           gst_adapter_push (demux->adapter, demux->mdatbuffer);
6739           demux->mdatbuffer = NULL;
6740           demux->offset = demux->mdatoffset;
6741           demux->neededbytes = next_entry_size (demux);
6742           demux->state = QTDEMUX_STATE_MOVIE;
6743           demux->mdatleft = gst_adapter_available (demux->adapter);
6744           demux->mdatsize = demux->mdatleft;
6745         } else {
6746           GST_DEBUG_OBJECT (demux, "Carrying on normally");
6747           gst_adapter_flush (demux->adapter, demux->neededbytes);
6748
6749           /* only go back to the mdat if there are samples to play */
6750           if (demux->got_moov && demux->first_mdat != -1
6751               && has_next_entry (demux)) {
6752             gboolean res;
6753
6754             /* we need to seek back */
6755             res = qtdemux_seek_offset (demux, demux->first_mdat);
6756             if (res) {
6757               demux->offset = demux->first_mdat;
6758             } else {
6759               GST_DEBUG_OBJECT (demux, "Seek back failed");
6760             }
6761           } else {
6762             demux->offset += demux->neededbytes;
6763           }
6764           demux->neededbytes = 16;
6765           demux->state = QTDEMUX_STATE_INITIAL;
6766         }
6767
6768         break;
6769       }
6770       case QTDEMUX_STATE_BUFFER_MDAT:{
6771         GstBuffer *buf;
6772         guint8 fourcc[4];
6773
6774         GST_DEBUG_OBJECT (demux, "Got our buffer at offset %" G_GUINT64_FORMAT,
6775             demux->offset);
6776         buf = gst_adapter_take_buffer (demux->adapter, demux->neededbytes);
6777         gst_buffer_extract (buf, 0, fourcc, 4);
6778         GST_DEBUG_OBJECT (demux, "mdatbuffer starts with %" GST_FOURCC_FORMAT,
6779             GST_FOURCC_ARGS (QT_FOURCC (fourcc)));
6780         if (demux->mdatbuffer)
6781           demux->mdatbuffer = gst_buffer_append (demux->mdatbuffer, buf);
6782         else
6783           demux->mdatbuffer = buf;
6784         demux->offset += demux->neededbytes;
6785         demux->neededbytes = 16;
6786         demux->state = QTDEMUX_STATE_INITIAL;
6787         gst_qtdemux_post_progress (demux, 1, 1);
6788
6789         break;
6790       }
6791       case QTDEMUX_STATE_MOVIE:{
6792         QtDemuxStream *stream = NULL;
6793         QtDemuxSample *sample;
6794         int i = -1;
6795         GstClockTime dts, pts, duration;
6796         gboolean keyframe;
6797
6798         GST_DEBUG_OBJECT (demux,
6799             "BEGIN // in MOVIE for offset %" G_GUINT64_FORMAT, demux->offset);
6800
6801         if (demux->fragmented) {
6802           GST_DEBUG_OBJECT (demux, "mdat remaining %" G_GUINT64_FORMAT,
6803               demux->mdatleft);
6804           if (G_LIKELY (demux->todrop < demux->mdatleft)) {
6805             /* if needed data starts within this atom,
6806              * then it should not exceed this atom */
6807             if (G_UNLIKELY (demux->neededbytes > demux->mdatleft)) {
6808               GST_ELEMENT_ERROR (demux, STREAM, DEMUX,
6809                   (_("This file is invalid and cannot be played.")),
6810                   ("sample data crosses atom boundary"));
6811               ret = GST_FLOW_ERROR;
6812               break;
6813             }
6814             demux->mdatleft -= demux->neededbytes;
6815           } else {
6816             GST_DEBUG_OBJECT (demux, "data atom emptied; resuming atom scan");
6817             /* so we are dropping more than left in this atom */
6818             gst_qtdemux_drop_data (demux, demux->mdatleft);
6819             demux->mdatleft = 0;
6820
6821             /* need to resume atom parsing so we do not miss any other pieces */
6822             demux->state = QTDEMUX_STATE_INITIAL;
6823             demux->neededbytes = 16;
6824
6825             /* check if there was any stored post mdat data from previous buffers */
6826             if (demux->restoredata_buffer) {
6827               g_assert (gst_adapter_available (demux->adapter) == 0);
6828
6829               gst_adapter_push (demux->adapter, demux->restoredata_buffer);
6830               demux->restoredata_buffer = NULL;
6831               demux->offset = demux->restoredata_offset;
6832             }
6833
6834             break;
6835           }
6836         }
6837
6838         if (demux->todrop) {
6839           if (demux->cenc_aux_info_offset > 0) {
6840             GstByteReader br;
6841             const guint8 *data;
6842
6843             GST_DEBUG_OBJECT (demux, "parsing cenc auxiliary info");
6844             data = gst_adapter_map (demux->adapter, demux->todrop);
6845             gst_byte_reader_init (&br, data + 8, demux->todrop);
6846             if (!qtdemux_parse_cenc_aux_info (demux, demux->streams[0], &br,
6847                     demux->cenc_aux_info_sizes, demux->cenc_aux_sample_count)) {
6848               GST_ERROR_OBJECT (demux, "failed to parse cenc auxiliary info");
6849               ret = GST_FLOW_ERROR;
6850               gst_adapter_unmap (demux->adapter);
6851               g_free (demux->cenc_aux_info_sizes);
6852               demux->cenc_aux_info_sizes = NULL;
6853               goto done;
6854             }
6855             demux->cenc_aux_info_offset = 0;
6856             g_free (demux->cenc_aux_info_sizes);
6857             demux->cenc_aux_info_sizes = NULL;
6858             gst_adapter_unmap (demux->adapter);
6859           }
6860           gst_qtdemux_drop_data (demux, demux->todrop);
6861         }
6862
6863         /* first buffer? */
6864         /* initial newsegment sent here after having added pads,
6865          * possible others in sink_event */
6866         gst_qtdemux_check_send_pending_segment (demux);
6867
6868         /* Figure out which stream this packet belongs to */
6869         for (i = 0; i < demux->n_streams; i++) {
6870           stream = demux->streams[i];
6871           if (stream->sample_index >= stream->n_samples)
6872             continue;
6873           GST_LOG_OBJECT (demux,
6874               "Checking stream %d (sample_index:%d / offset:%" G_GUINT64_FORMAT
6875               " / size:%d)", i, stream->sample_index,
6876               stream->samples[stream->sample_index].offset,
6877               stream->samples[stream->sample_index].size);
6878
6879           if (stream->samples[stream->sample_index].offset == demux->offset)
6880             break;
6881         }
6882
6883         if (G_UNLIKELY (stream == NULL || i == demux->n_streams))
6884           goto unknown_stream;
6885
6886         gst_qtdemux_stream_check_and_change_stsd_index (demux, stream);
6887
6888         if (stream->new_caps) {
6889           gst_qtdemux_configure_stream (demux, stream);
6890         }
6891
6892         /* Put data in a buffer, set timestamps, caps, ... */
6893         sample = &stream->samples[stream->sample_index];
6894
6895         if (G_LIKELY (!(STREAM_IS_EOS (stream)))) {
6896           GST_DEBUG_OBJECT (demux, "stream : %" GST_FOURCC_FORMAT,
6897               GST_FOURCC_ARGS (CUR_STREAM (stream)->fourcc));
6898
6899           dts = QTSAMPLE_DTS (stream, sample);
6900           pts = QTSAMPLE_PTS (stream, sample);
6901           duration = QTSAMPLE_DUR_DTS (stream, sample, dts);
6902           keyframe = QTSAMPLE_KEYFRAME (stream, sample);
6903
6904           /* check for segment end */
6905           if (G_UNLIKELY (demux->segment.stop != -1
6906                   && demux->segment.stop <= pts && stream->on_keyframe)) {
6907             GST_DEBUG_OBJECT (demux, "we reached the end of our segment.");
6908             stream->time_position = GST_CLOCK_TIME_NONE;        /* this means EOS */
6909
6910             /* skip this data, stream is EOS */
6911             gst_adapter_flush (demux->adapter, demux->neededbytes);
6912             demux->offset += demux->neededbytes;
6913
6914             /* check if all streams are eos */
6915             ret = GST_FLOW_EOS;
6916             for (i = 0; i < demux->n_streams; i++) {
6917               if (!STREAM_IS_EOS (demux->streams[i])) {
6918                 ret = GST_FLOW_OK;
6919                 break;
6920               }
6921             }
6922           } else {
6923             GstBuffer *outbuf;
6924
6925             outbuf =
6926                 gst_adapter_take_buffer (demux->adapter, demux->neededbytes);
6927
6928             /* FIXME: should either be an assert or a plain check */
6929             g_return_val_if_fail (outbuf != NULL, GST_FLOW_ERROR);
6930
6931             ret = gst_qtdemux_decorate_and_push_buffer (demux, stream, outbuf,
6932                 dts, pts, duration, keyframe, dts, demux->offset);
6933           }
6934
6935           /* combine flows */
6936           ret = gst_qtdemux_combine_flows (demux, stream, ret);
6937         } else {
6938           /* skip this data, stream is EOS */
6939           gst_adapter_flush (demux->adapter, demux->neededbytes);
6940         }
6941
6942         stream->sample_index++;
6943         stream->offset_in_sample = 0;
6944
6945         /* update current offset and figure out size of next buffer */
6946         GST_LOG_OBJECT (demux, "increasing offset %" G_GUINT64_FORMAT " by %u",
6947             demux->offset, demux->neededbytes);
6948         demux->offset += demux->neededbytes;
6949         GST_LOG_OBJECT (demux, "offset is now %" G_GUINT64_FORMAT,
6950             demux->offset);
6951
6952
6953         if (ret == GST_FLOW_EOS) {
6954           GST_DEBUG_OBJECT (demux, "All streams are EOS, signal upstream");
6955           demux->neededbytes = -1;
6956           goto eos;
6957         }
6958
6959         if ((demux->neededbytes = next_entry_size (demux)) == -1) {
6960           if (demux->fragmented) {
6961             GST_DEBUG_OBJECT (demux, "(temporarily) out of fragmented samples");
6962             /* there may be more to follow, only finish this atom */
6963             demux->todrop = demux->mdatleft;
6964             demux->neededbytes = demux->todrop;
6965             break;
6966           }
6967           goto eos;
6968         }
6969         if (ret != GST_FLOW_OK && ret != GST_FLOW_NOT_LINKED) {
6970           goto non_ok_unlinked_flow;
6971         }
6972         break;
6973       }
6974       default:
6975         goto invalid_state;
6976     }
6977   }
6978
6979   /* when buffering movie data, at least show user something is happening */
6980   if (ret == GST_FLOW_OK && demux->state == QTDEMUX_STATE_BUFFER_MDAT &&
6981       gst_adapter_available (demux->adapter) <= demux->neededbytes) {
6982     gst_qtdemux_post_progress (demux, gst_adapter_available (demux->adapter),
6983         demux->neededbytes);
6984   }
6985 done:
6986
6987   return ret;
6988
6989   /* ERRORS */
6990 non_ok_unlinked_flow:
6991   {
6992     GST_DEBUG_OBJECT (demux, "Stopping, combined return flow %s",
6993         gst_flow_get_name (ret));
6994     return ret;
6995   }
6996 unknown_stream:
6997   {
6998     GST_ELEMENT_ERROR (demux, STREAM, FAILED, (NULL), ("unknown stream found"));
6999     ret = GST_FLOW_ERROR;
7000     goto done;
7001   }
7002 eos:
7003   {
7004     GST_DEBUG_OBJECT (demux, "no next entry, EOS");
7005     ret = GST_FLOW_EOS;
7006     goto done;
7007   }
7008 invalid_state:
7009   {
7010     GST_ELEMENT_ERROR (demux, STREAM, FAILED,
7011         (NULL), ("qtdemuxer invalid state %d", demux->state));
7012     ret = GST_FLOW_ERROR;
7013     goto done;
7014   }
7015 no_moov:
7016   {
7017     GST_ELEMENT_ERROR (demux, STREAM, FAILED,
7018         (NULL), ("no 'moov' atom within the first 10 MB"));
7019     ret = GST_FLOW_ERROR;
7020     goto done;
7021   }
7022 }
7023
7024 static gboolean
7025 qtdemux_sink_activate (GstPad * sinkpad, GstObject * parent)
7026 {
7027   GstQuery *query;
7028   gboolean pull_mode;
7029
7030   query = gst_query_new_scheduling ();
7031
7032   if (!gst_pad_peer_query (sinkpad, query)) {
7033     gst_query_unref (query);
7034     goto activate_push;
7035   }
7036
7037   pull_mode = gst_query_has_scheduling_mode_with_flags (query,
7038       GST_PAD_MODE_PULL, GST_SCHEDULING_FLAG_SEEKABLE);
7039   gst_query_unref (query);
7040
7041   if (!pull_mode)
7042     goto activate_push;
7043
7044   GST_DEBUG_OBJECT (sinkpad, "activating pull");
7045   return gst_pad_activate_mode (sinkpad, GST_PAD_MODE_PULL, TRUE);
7046
7047 activate_push:
7048   {
7049     GST_DEBUG_OBJECT (sinkpad, "activating push");
7050     return gst_pad_activate_mode (sinkpad, GST_PAD_MODE_PUSH, TRUE);
7051   }
7052 }
7053
7054 static gboolean
7055 qtdemux_sink_activate_mode (GstPad * sinkpad, GstObject * parent,
7056     GstPadMode mode, gboolean active)
7057 {
7058   gboolean res;
7059   GstQTDemux *demux = GST_QTDEMUX (parent);
7060
7061   switch (mode) {
7062     case GST_PAD_MODE_PUSH:
7063       demux->pullbased = FALSE;
7064       res = TRUE;
7065       break;
7066     case GST_PAD_MODE_PULL:
7067       if (active) {
7068         demux->pullbased = TRUE;
7069         res = gst_pad_start_task (sinkpad, (GstTaskFunction) gst_qtdemux_loop,
7070             sinkpad, NULL);
7071       } else {
7072         res = gst_pad_stop_task (sinkpad);
7073       }
7074       break;
7075     default:
7076       res = FALSE;
7077       break;
7078   }
7079   return res;
7080 }
7081
7082 #ifdef HAVE_ZLIB
7083 static void *
7084 qtdemux_inflate (void *z_buffer, guint z_length, guint * length)
7085 {
7086   guint8 *buffer;
7087   z_stream z;
7088   int ret;
7089
7090   memset (&z, 0, sizeof (z));
7091   z.zalloc = NULL;
7092   z.zfree = NULL;
7093   z.opaque = NULL;
7094
7095   if ((ret = inflateInit (&z)) != Z_OK) {
7096     GST_ERROR ("inflateInit() returned %d", ret);
7097     return NULL;
7098   }
7099
7100   z.next_in = z_buffer;
7101   z.avail_in = z_length;
7102
7103   buffer = (guint8 *) g_malloc (*length);
7104   z.avail_out = *length;
7105   z.next_out = (Bytef *) buffer;
7106   do {
7107     ret = inflate (&z, Z_NO_FLUSH);
7108     if (ret == Z_STREAM_END) {
7109       break;
7110     } else if (ret != Z_OK) {
7111       GST_WARNING ("inflate() returned %d", ret);
7112       break;
7113     }
7114
7115     *length += 4096;
7116     buffer = (guint8 *) g_realloc (buffer, *length);
7117     z.next_out = (Bytef *) (buffer + z.total_out);
7118     z.avail_out += 4096;
7119   } while (z.avail_in > 0);
7120
7121   if (ret != Z_STREAM_END) {
7122     g_free (buffer);
7123     buffer = NULL;
7124     *length = 0;
7125   } else {
7126     *length = z.total_out;
7127   }
7128
7129   inflateEnd (&z);
7130
7131   return buffer;
7132 }
7133 #endif /* HAVE_ZLIB */
7134
7135 static gboolean
7136 qtdemux_parse_moov (GstQTDemux * qtdemux, const guint8 * buffer, guint length)
7137 {
7138   GNode *cmov;
7139
7140   qtdemux->moov_node = g_node_new ((guint8 *) buffer);
7141
7142   /* counts as header data */
7143   qtdemux->header_size += length;
7144
7145   GST_DEBUG_OBJECT (qtdemux, "parsing 'moov' atom");
7146   qtdemux_parse_node (qtdemux, qtdemux->moov_node, buffer, length);
7147
7148   cmov = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_cmov);
7149   if (cmov) {
7150     guint32 method;
7151     GNode *dcom;
7152     GNode *cmvd;
7153     guint32 dcom_len;
7154
7155     dcom = qtdemux_tree_get_child_by_type (cmov, FOURCC_dcom);
7156     cmvd = qtdemux_tree_get_child_by_type (cmov, FOURCC_cmvd);
7157     if (dcom == NULL || cmvd == NULL)
7158       goto invalid_compression;
7159
7160     dcom_len = QT_UINT32 (dcom->data);
7161     if (dcom_len < 12)
7162       goto invalid_compression;
7163
7164     method = QT_FOURCC ((guint8 *) dcom->data + 8);
7165     switch (method) {
7166 #ifdef HAVE_ZLIB
7167       case FOURCC_zlib:{
7168         guint uncompressed_length;
7169         guint compressed_length;
7170         guint8 *buf;
7171         guint32 cmvd_len;
7172
7173         cmvd_len = QT_UINT32 ((guint8 *) cmvd->data);
7174         if (cmvd_len < 12)
7175           goto invalid_compression;
7176
7177         uncompressed_length = QT_UINT32 ((guint8 *) cmvd->data + 8);
7178         compressed_length = cmvd_len - 12;
7179         GST_LOG ("length = %u", uncompressed_length);
7180
7181         buf =
7182             (guint8 *) qtdemux_inflate ((guint8 *) cmvd->data + 12,
7183             compressed_length, &uncompressed_length);
7184
7185         if (buf) {
7186           qtdemux->moov_node_compressed = qtdemux->moov_node;
7187           qtdemux->moov_node = g_node_new (buf);
7188
7189           qtdemux_parse_node (qtdemux, qtdemux->moov_node, buf,
7190               uncompressed_length);
7191         }
7192         break;
7193       }
7194 #endif /* HAVE_ZLIB */
7195       default:
7196         GST_WARNING_OBJECT (qtdemux, "unknown or unhandled header compression "
7197             "type %" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (method));
7198         break;
7199     }
7200   }
7201   return TRUE;
7202
7203   /* ERRORS */
7204 invalid_compression:
7205   {
7206     GST_ERROR_OBJECT (qtdemux, "invalid compressed header");
7207     return FALSE;
7208   }
7209 }
7210
7211 static gboolean
7212 qtdemux_parse_container (GstQTDemux * qtdemux, GNode * node, const guint8 * buf,
7213     const guint8 * end)
7214 {
7215   while (G_UNLIKELY (buf < end)) {
7216     GNode *child;
7217     guint32 len;
7218
7219     if (G_UNLIKELY (buf + 4 > end)) {
7220       GST_LOG_OBJECT (qtdemux, "buffer overrun");
7221       break;
7222     }
7223     len = QT_UINT32 (buf);
7224     if (G_UNLIKELY (len == 0)) {
7225       GST_LOG_OBJECT (qtdemux, "empty container");
7226       break;
7227     }
7228     if (G_UNLIKELY (len < 8)) {
7229       GST_WARNING_OBJECT (qtdemux, "length too short (%d < 8)", len);
7230       break;
7231     }
7232     if (G_UNLIKELY (len > (end - buf))) {
7233       GST_WARNING_OBJECT (qtdemux, "length too long (%d > %d)", len,
7234           (gint) (end - buf));
7235       break;
7236     }
7237
7238     child = g_node_new ((guint8 *) buf);
7239     g_node_append (node, child);
7240     GST_LOG_OBJECT (qtdemux, "adding new node of len %d", len);
7241     qtdemux_parse_node (qtdemux, child, buf, len);
7242
7243     buf += len;
7244   }
7245   return TRUE;
7246 }
7247
7248 static gboolean
7249 qtdemux_parse_theora_extension (GstQTDemux * qtdemux, QtDemuxStream * stream,
7250     GNode * xdxt)
7251 {
7252   int len = QT_UINT32 (xdxt->data);
7253   guint8 *buf = xdxt->data;
7254   guint8 *end = buf + len;
7255   GstBuffer *buffer;
7256
7257   /* skip size and type */
7258   buf += 8;
7259   end -= 8;
7260
7261   while (buf < end) {
7262     gint size;
7263     guint32 type;
7264
7265     size = QT_UINT32 (buf);
7266     type = QT_FOURCC (buf + 4);
7267
7268     GST_LOG_OBJECT (qtdemux, "%p %p", buf, end);
7269
7270     if (buf + size > end || size <= 0)
7271       break;
7272
7273     buf += 8;
7274     size -= 8;
7275
7276     GST_WARNING_OBJECT (qtdemux, "have cookie %" GST_FOURCC_FORMAT,
7277         GST_FOURCC_ARGS (type));
7278
7279     switch (type) {
7280       case FOURCC_tCtH:
7281         buffer = gst_buffer_new_and_alloc (size);
7282         gst_buffer_fill (buffer, 0, buf, size);
7283         stream->buffers = g_slist_append (stream->buffers, buffer);
7284         GST_LOG_OBJECT (qtdemux, "parsing theora header");
7285         break;
7286       case FOURCC_tCt_:
7287         buffer = gst_buffer_new_and_alloc (size);
7288         gst_buffer_fill (buffer, 0, buf, size);
7289         stream->buffers = g_slist_append (stream->buffers, buffer);
7290         GST_LOG_OBJECT (qtdemux, "parsing theora comment");
7291         break;
7292       case FOURCC_tCtC:
7293         buffer = gst_buffer_new_and_alloc (size);
7294         gst_buffer_fill (buffer, 0, buf, size);
7295         stream->buffers = g_slist_append (stream->buffers, buffer);
7296         GST_LOG_OBJECT (qtdemux, "parsing theora codebook");
7297         break;
7298       default:
7299         GST_WARNING_OBJECT (qtdemux,
7300             "unknown theora cookie %" GST_FOURCC_FORMAT,
7301             GST_FOURCC_ARGS (type));
7302         break;
7303     }
7304     buf += size;
7305   }
7306   return TRUE;
7307 }
7308
7309 static gboolean
7310 qtdemux_parse_node (GstQTDemux * qtdemux, GNode * node, const guint8 * buffer,
7311     guint length)
7312 {
7313   guint32 fourcc = 0;
7314   guint32 node_length = 0;
7315   const QtNodeType *type;
7316   const guint8 *end;
7317
7318   GST_LOG_OBJECT (qtdemux, "qtdemux_parse buffer %p length %u", buffer, length);
7319
7320   if (G_UNLIKELY (length < 8))
7321     goto not_enough_data;
7322
7323   node_length = QT_UINT32 (buffer);
7324   fourcc = QT_FOURCC (buffer + 4);
7325
7326   /* ignore empty nodes */
7327   if (G_UNLIKELY (fourcc == 0 || node_length == 8))
7328     return TRUE;
7329
7330   type = qtdemux_type_get (fourcc);
7331
7332   end = buffer + length;
7333
7334   GST_LOG_OBJECT (qtdemux,
7335       "parsing '%" GST_FOURCC_FORMAT "', length=%u, name '%s'",
7336       GST_FOURCC_ARGS (fourcc), node_length, type->name);
7337
7338   if (node_length > length)
7339     goto broken_atom_size;
7340
7341   if (type->flags & QT_FLAG_CONTAINER) {
7342     qtdemux_parse_container (qtdemux, node, buffer + 8, end);
7343   } else {
7344     switch (fourcc) {
7345       case FOURCC_stsd:
7346       {
7347         if (node_length < 20) {
7348           GST_LOG_OBJECT (qtdemux, "skipping small stsd box");
7349           break;
7350         }
7351         GST_DEBUG_OBJECT (qtdemux,
7352             "parsing stsd (sample table, sample description) atom");
7353         /* Skip over 8 byte atom hdr + 1 byte version, 3 bytes flags, 4 byte num_entries */
7354         qtdemux_parse_container (qtdemux, node, buffer + 16, end);
7355         break;
7356       }
7357       case FOURCC_mp4a:
7358       case FOURCC_alac:
7359       case FOURCC_fLaC:
7360       {
7361         guint32 version;
7362         guint32 offset;
7363         guint min_size;
7364
7365         /* also read alac (or whatever) in stead of mp4a in the following,
7366          * since a similar layout is used in other cases as well */
7367         if (fourcc == FOURCC_mp4a)
7368           min_size = 20;
7369         else if (fourcc == FOURCC_fLaC)
7370           min_size = 86;
7371         else
7372           min_size = 40;
7373
7374         /* There are two things we might encounter here: a true mp4a atom, and
7375            an mp4a entry in an stsd atom. The latter is what we're interested
7376            in, and it looks like an atom, but isn't really one. The true mp4a
7377            atom is short, so we detect it based on length here. */
7378         if (length < min_size) {
7379           GST_LOG_OBJECT (qtdemux, "skipping small %" GST_FOURCC_FORMAT " box",
7380               GST_FOURCC_ARGS (fourcc));
7381           break;
7382         }
7383
7384         /* 'version' here is the sound sample description version. Types 0 and
7385            1 are documented in the QTFF reference, but type 2 is not: it's
7386            described in Apple header files instead (struct SoundDescriptionV2
7387            in Movies.h) */
7388         version = QT_UINT16 (buffer + 16);
7389
7390         GST_DEBUG_OBJECT (qtdemux, "%" GST_FOURCC_FORMAT " version 0x%08x",
7391             GST_FOURCC_ARGS (fourcc), version);
7392
7393         /* parse any esds descriptors */
7394         switch (version) {
7395           case 0:
7396             offset = 0x24;
7397             break;
7398           case 1:
7399             offset = 0x34;
7400             break;
7401           case 2:
7402             offset = 0x48;
7403             break;
7404           default:
7405             GST_WARNING_OBJECT (qtdemux,
7406                 "unhandled %" GST_FOURCC_FORMAT " version 0x%08x",
7407                 GST_FOURCC_ARGS (fourcc), version);
7408             offset = 0;
7409             break;
7410         }
7411         if (offset)
7412           qtdemux_parse_container (qtdemux, node, buffer + offset, end);
7413         break;
7414       }
7415       case FOURCC_mp4v:
7416       case FOURCC_MP4V:
7417       case FOURCC_fmp4:
7418       case FOURCC_FMP4:
7419       case FOURCC_apcs:
7420       case FOURCC_apch:
7421       case FOURCC_apcn:
7422       case FOURCC_apco:
7423       case FOURCC_ap4h:
7424       case FOURCC_xvid:
7425       case FOURCC_XVID:
7426       case FOURCC_H264:
7427       case FOURCC_avc1:
7428       case FOURCC_avc3:
7429       case FOURCC_H265:
7430       case FOURCC_hvc1:
7431       case FOURCC_hev1:
7432       case FOURCC_mjp2:
7433       case FOURCC_encv:
7434       {
7435         guint32 version;
7436         guint32 str_len;
7437
7438         /* codec_data is contained inside these atoms, which all have
7439          * the same format. */
7440         /* video sample description size is 86 bytes without extension.
7441          * node_length have to be bigger than 86 bytes because video sample
7442          * description can include extenstions such as esds, fiel, glbl, etc. */
7443         if (node_length < 86) {
7444           GST_WARNING_OBJECT (qtdemux, "%" GST_FOURCC_FORMAT
7445               " sample description length too short (%u < 86)",
7446               GST_FOURCC_ARGS (fourcc), node_length);
7447           break;
7448         }
7449
7450         GST_DEBUG_OBJECT (qtdemux, "parsing in %" GST_FOURCC_FORMAT,
7451             GST_FOURCC_ARGS (fourcc));
7452
7453         /* version (2 bytes) : this is set to 0, unless a compressor has changed
7454          *              its data format.
7455          * revision level (2 bytes) : must be set to 0. */
7456         version = QT_UINT32 (buffer + 16);
7457         GST_DEBUG_OBJECT (qtdemux, "version %08x", version);
7458
7459         /* compressor name : PASCAL string and informative purposes
7460          * first byte : the number of bytes to be displayed.
7461          *              it has to be less than 32 because it is reserved
7462          *              space of 32 bytes total including itself. */
7463         str_len = QT_UINT8 (buffer + 50);
7464         if (str_len < 32)
7465           GST_DEBUG_OBJECT (qtdemux, "compressorname = %.*s", str_len,
7466               (char *) buffer + 51);
7467         else
7468           GST_WARNING_OBJECT (qtdemux,
7469               "compressorname length too big (%u > 31)", str_len);
7470
7471         GST_MEMDUMP_OBJECT (qtdemux, "video sample description", buffer,
7472             end - buffer);
7473         qtdemux_parse_container (qtdemux, node, buffer + 86, end);
7474         break;
7475       }
7476       case FOURCC_meta:
7477       {
7478         GST_DEBUG_OBJECT (qtdemux, "parsing meta atom");
7479         qtdemux_parse_container (qtdemux, node, buffer + 12, end);
7480         break;
7481       }
7482       case FOURCC_mp4s:
7483       {
7484         GST_MEMDUMP_OBJECT (qtdemux, "mp4s", buffer, end - buffer);
7485         /* Skip 8 byte header, plus 8 byte version + flags + entry_count */
7486         qtdemux_parse_container (qtdemux, node, buffer + 16, end);
7487         break;
7488       }
7489       case FOURCC_XiTh:
7490       {
7491         guint32 version;
7492         guint32 offset;
7493
7494         if (length < 16) {
7495           GST_LOG_OBJECT (qtdemux, "skipping small %" GST_FOURCC_FORMAT " box",
7496               GST_FOURCC_ARGS (fourcc));
7497           break;
7498         }
7499
7500         version = QT_UINT32 (buffer + 12);
7501         GST_DEBUG_OBJECT (qtdemux, "parsing XiTh atom version 0x%08x", version);
7502
7503         switch (version) {
7504           case 0x00000001:
7505             offset = 0x62;
7506             break;
7507           default:
7508             GST_DEBUG_OBJECT (qtdemux, "unknown version 0x%08x", version);
7509             offset = 0;
7510             break;
7511         }
7512         if (offset) {
7513           if (length < offset) {
7514             GST_WARNING_OBJECT (qtdemux,
7515                 "skipping too small %" GST_FOURCC_FORMAT " box",
7516                 GST_FOURCC_ARGS (fourcc));
7517             break;
7518           }
7519           qtdemux_parse_container (qtdemux, node, buffer + offset, end);
7520         }
7521         break;
7522       }
7523       case FOURCC_in24:
7524       {
7525         qtdemux_parse_container (qtdemux, node, buffer + 0x34, end);
7526         break;
7527       }
7528       case FOURCC_uuid:
7529       {
7530         qtdemux_parse_uuid (qtdemux, buffer, end - buffer);
7531         break;
7532       }
7533       case FOURCC_enca:
7534       {
7535         qtdemux_parse_container (qtdemux, node, buffer + 36, end);
7536         break;
7537       }
7538       default:
7539         if (!strcmp (type->name, "unknown"))
7540           GST_MEMDUMP ("Unknown tag", buffer + 4, end - buffer - 4);
7541         break;
7542     }
7543   }
7544   GST_LOG_OBJECT (qtdemux, "parsed '%" GST_FOURCC_FORMAT "'",
7545       GST_FOURCC_ARGS (fourcc));
7546   return TRUE;
7547
7548 /* ERRORS */
7549 not_enough_data:
7550   {
7551     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
7552         (_("This file is corrupt and cannot be played.")),
7553         ("Not enough data for an atom header, got only %u bytes", length));
7554     return FALSE;
7555   }
7556 broken_atom_size:
7557   {
7558     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
7559         (_("This file is corrupt and cannot be played.")),
7560         ("Atom '%" GST_FOURCC_FORMAT "' has size of %u bytes, but we have only "
7561             "%u bytes available.", GST_FOURCC_ARGS (fourcc), node_length,
7562             length));
7563     return FALSE;
7564   }
7565 }
7566
7567 static GNode *
7568 qtdemux_tree_get_child_by_type (GNode * node, guint32 fourcc)
7569 {
7570   GNode *child;
7571   guint8 *buffer;
7572   guint32 child_fourcc;
7573
7574   for (child = g_node_first_child (node); child;
7575       child = g_node_next_sibling (child)) {
7576     buffer = (guint8 *) child->data;
7577
7578     child_fourcc = QT_FOURCC (buffer + 4);
7579
7580     if (G_UNLIKELY (child_fourcc == fourcc)) {
7581       return child;
7582     }
7583   }
7584   return NULL;
7585 }
7586
7587 static GNode *
7588 qtdemux_tree_get_child_by_type_full (GNode * node, guint32 fourcc,
7589     GstByteReader * parser)
7590 {
7591   GNode *child;
7592   guint8 *buffer;
7593   guint32 child_fourcc, child_len;
7594
7595   for (child = g_node_first_child (node); child;
7596       child = g_node_next_sibling (child)) {
7597     buffer = (guint8 *) child->data;
7598
7599     child_len = QT_UINT32 (buffer);
7600     child_fourcc = QT_FOURCC (buffer + 4);
7601
7602     if (G_UNLIKELY (child_fourcc == fourcc)) {
7603       if (G_UNLIKELY (child_len < (4 + 4)))
7604         return NULL;
7605       /* FIXME: must verify if atom length < parent atom length */
7606       gst_byte_reader_init (parser, buffer + (4 + 4), child_len - (4 + 4));
7607       return child;
7608     }
7609   }
7610   return NULL;
7611 }
7612
7613 static GNode *
7614 qtdemux_tree_get_child_by_index (GNode * node, guint index)
7615 {
7616   return g_node_nth_child (node, index);
7617 }
7618
7619 static GNode *
7620 qtdemux_tree_get_sibling_by_type_full (GNode * node, guint32 fourcc,
7621     GstByteReader * parser)
7622 {
7623   GNode *child;
7624   guint8 *buffer;
7625   guint32 child_fourcc, child_len;
7626
7627   for (child = g_node_next_sibling (node); child;
7628       child = g_node_next_sibling (child)) {
7629     buffer = (guint8 *) child->data;
7630
7631     child_fourcc = QT_FOURCC (buffer + 4);
7632
7633     if (child_fourcc == fourcc) {
7634       if (parser) {
7635         child_len = QT_UINT32 (buffer);
7636         if (G_UNLIKELY (child_len < (4 + 4)))
7637           return NULL;
7638         /* FIXME: must verify if atom length < parent atom length */
7639         gst_byte_reader_init (parser, buffer + (4 + 4), child_len - (4 + 4));
7640       }
7641       return child;
7642     }
7643   }
7644   return NULL;
7645 }
7646
7647 static GNode *
7648 qtdemux_tree_get_sibling_by_type (GNode * node, guint32 fourcc)
7649 {
7650   return qtdemux_tree_get_sibling_by_type_full (node, fourcc, NULL);
7651 }
7652
7653 static void
7654 qtdemux_do_allocation (GstQTDemux * qtdemux, QtDemuxStream * stream)
7655 {
7656 /* FIXME: This can only reliably work if demuxers have a
7657  * separate streaming thread per srcpad. This should be
7658  * done in a demuxer base class, which integrates parts
7659  * of multiqueue
7660  *
7661  * https://bugzilla.gnome.org/show_bug.cgi?id=701856
7662  */
7663 #if 0
7664   GstQuery *query;
7665
7666   query = gst_query_new_allocation (stream->caps, FALSE);
7667
7668   if (!gst_pad_peer_query (stream->pad, query)) {
7669     /* not a problem, just debug a little */
7670     GST_DEBUG_OBJECT (qtdemux, "peer ALLOCATION query failed");
7671   }
7672
7673   if (stream->allocator)
7674     gst_object_unref (stream->allocator);
7675
7676   if (gst_query_get_n_allocation_params (query) > 0) {
7677     /* try the allocator */
7678     gst_query_parse_nth_allocation_param (query, 0, &stream->allocator,
7679         &stream->params);
7680     stream->use_allocator = TRUE;
7681   } else {
7682     stream->allocator = NULL;
7683     gst_allocation_params_init (&stream->params);
7684     stream->use_allocator = FALSE;
7685   }
7686   gst_query_unref (query);
7687 #endif
7688 }
7689
7690 static gboolean
7691 gst_qtdemux_configure_protected_caps (GstQTDemux * qtdemux,
7692     QtDemuxStream * stream)
7693 {
7694   GstStructure *s;
7695   const gchar *selected_system;
7696
7697   g_return_val_if_fail (qtdemux != NULL, FALSE);
7698   g_return_val_if_fail (stream != NULL, FALSE);
7699   g_return_val_if_fail (gst_caps_get_size (CUR_STREAM (stream)->caps) == 1,
7700       FALSE);
7701
7702   if (stream->protection_scheme_type != FOURCC_cenc) {
7703     GST_ERROR_OBJECT (qtdemux, "unsupported protection scheme");
7704     return FALSE;
7705   }
7706   if (qtdemux->protection_system_ids == NULL) {
7707     GST_ERROR_OBJECT (qtdemux, "stream is protected using cenc, but no "
7708         "cenc protection system information has been found");
7709     return FALSE;
7710   }
7711   g_ptr_array_add (qtdemux->protection_system_ids, NULL);
7712   selected_system = gst_protection_select_system ((const gchar **)
7713       qtdemux->protection_system_ids->pdata);
7714   g_ptr_array_remove_index (qtdemux->protection_system_ids,
7715       qtdemux->protection_system_ids->len - 1);
7716   if (!selected_system) {
7717     GST_ERROR_OBJECT (qtdemux, "stream is protected, but no "
7718         "suitable decryptor element has been found");
7719     return FALSE;
7720   }
7721
7722   s = gst_caps_get_structure (CUR_STREAM (stream)->caps, 0);
7723   if (!gst_structure_has_name (s, "application/x-cenc")) {
7724     gst_structure_set (s,
7725         "original-media-type", G_TYPE_STRING, gst_structure_get_name (s),
7726         GST_PROTECTION_SYSTEM_ID_CAPS_FIELD, G_TYPE_STRING, selected_system,
7727         NULL);
7728     gst_structure_set_name (s, "application/x-cenc");
7729   }
7730   return TRUE;
7731 }
7732
7733 static gboolean
7734 gst_qtdemux_configure_stream (GstQTDemux * qtdemux, QtDemuxStream * stream)
7735 {
7736   if (stream->subtype == FOURCC_vide) {
7737     /* fps is calculated base on the duration of the average framerate since
7738      * qt does not have a fixed framerate. */
7739     gboolean fps_available = TRUE;
7740
7741     if ((stream->n_samples == 1) && (stream->first_duration == 0)) {
7742       /* still frame */
7743       CUR_STREAM (stream)->fps_n = 0;
7744       CUR_STREAM (stream)->fps_d = 1;
7745     } else {
7746       if (stream->duration == 0 || stream->n_samples < 2) {
7747         CUR_STREAM (stream)->fps_n = stream->timescale;
7748         CUR_STREAM (stream)->fps_d = 1;
7749         fps_available = FALSE;
7750       } else {
7751         GstClockTime avg_duration;
7752         guint64 duration;
7753         guint32 n_samples;
7754
7755         /* duration and n_samples can be updated for fragmented format
7756          * so, framerate of fragmented format is calculated using data in a moof */
7757         if (qtdemux->fragmented && stream->n_samples_moof > 0
7758             && stream->duration_moof > 0) {
7759           n_samples = stream->n_samples_moof;
7760           duration = stream->duration_moof;
7761         } else {
7762           n_samples = stream->n_samples;
7763           duration = stream->duration;
7764         }
7765
7766         /* Calculate a framerate, ignoring the first sample which is sometimes truncated */
7767         /* stream->duration is guint64, timescale, n_samples are guint32 */
7768         avg_duration =
7769             gst_util_uint64_scale_round (duration -
7770             stream->first_duration, GST_SECOND,
7771             (guint64) (stream->timescale) * (n_samples - 1));
7772
7773         GST_LOG_OBJECT (qtdemux,
7774             "Calculating avg sample duration based on stream (or moof) duration %"
7775             G_GUINT64_FORMAT
7776             " minus first sample %u, leaving %d samples gives %"
7777             GST_TIME_FORMAT, duration, stream->first_duration,
7778             n_samples - 1, GST_TIME_ARGS (avg_duration));
7779
7780         gst_video_guess_framerate (avg_duration, &CUR_STREAM (stream)->fps_n,
7781             &CUR_STREAM (stream)->fps_d);
7782
7783         GST_DEBUG_OBJECT (qtdemux,
7784             "Calculating framerate, timescale %u gave fps_n %d fps_d %d",
7785             stream->timescale, CUR_STREAM (stream)->fps_n,
7786             CUR_STREAM (stream)->fps_d);
7787       }
7788     }
7789
7790     if (CUR_STREAM (stream)->caps) {
7791       CUR_STREAM (stream)->caps =
7792           gst_caps_make_writable (CUR_STREAM (stream)->caps);
7793
7794       gst_caps_set_simple (CUR_STREAM (stream)->caps,
7795           "width", G_TYPE_INT, CUR_STREAM (stream)->width,
7796           "height", G_TYPE_INT, CUR_STREAM (stream)->height, NULL);
7797
7798       /* set framerate if calculated framerate is reliable */
7799       if (fps_available) {
7800         gst_caps_set_simple (CUR_STREAM (stream)->caps,
7801             "framerate", GST_TYPE_FRACTION, CUR_STREAM (stream)->fps_n,
7802             CUR_STREAM (stream)->fps_d, NULL);
7803       }
7804
7805       /* calculate pixel-aspect-ratio using display width and height */
7806       GST_DEBUG_OBJECT (qtdemux,
7807           "video size %dx%d, target display size %dx%d",
7808           CUR_STREAM (stream)->width, CUR_STREAM (stream)->height,
7809           stream->display_width, stream->display_height);
7810       /* qt file might have pasp atom */
7811       if (CUR_STREAM (stream)->par_w > 0 && CUR_STREAM (stream)->par_h > 0) {
7812         GST_DEBUG_OBJECT (qtdemux, "par %d:%d", CUR_STREAM (stream)->par_w,
7813             CUR_STREAM (stream)->par_h);
7814         gst_caps_set_simple (CUR_STREAM (stream)->caps, "pixel-aspect-ratio",
7815             GST_TYPE_FRACTION, CUR_STREAM (stream)->par_w,
7816             CUR_STREAM (stream)->par_h, NULL);
7817       } else if (stream->display_width > 0 && stream->display_height > 0
7818           && CUR_STREAM (stream)->width > 0
7819           && CUR_STREAM (stream)->height > 0) {
7820         gint n, d;
7821
7822         /* calculate the pixel aspect ratio using the display and pixel w/h */
7823         n = stream->display_width * CUR_STREAM (stream)->height;
7824         d = stream->display_height * CUR_STREAM (stream)->width;
7825         if (n == d)
7826           n = d = 1;
7827         GST_DEBUG_OBJECT (qtdemux, "setting PAR to %d/%d", n, d);
7828         CUR_STREAM (stream)->par_w = n;
7829         CUR_STREAM (stream)->par_h = d;
7830         gst_caps_set_simple (CUR_STREAM (stream)->caps, "pixel-aspect-ratio",
7831             GST_TYPE_FRACTION, CUR_STREAM (stream)->par_w,
7832             CUR_STREAM (stream)->par_h, NULL);
7833       }
7834
7835       if (CUR_STREAM (stream)->interlace_mode > 0) {
7836         if (CUR_STREAM (stream)->interlace_mode == 1) {
7837           gst_caps_set_simple (CUR_STREAM (stream)->caps, "interlace-mode",
7838               G_TYPE_STRING, "progressive", NULL);
7839         } else if (CUR_STREAM (stream)->interlace_mode == 2) {
7840           gst_caps_set_simple (CUR_STREAM (stream)->caps, "interlace-mode",
7841               G_TYPE_STRING, "interleaved", NULL);
7842           if (CUR_STREAM (stream)->field_order == 9) {
7843             gst_caps_set_simple (CUR_STREAM (stream)->caps, "field-order",
7844                 G_TYPE_STRING, "top-field-first", NULL);
7845           } else if (CUR_STREAM (stream)->field_order == 14) {
7846             gst_caps_set_simple (CUR_STREAM (stream)->caps, "field-order",
7847                 G_TYPE_STRING, "bottom-field-first", NULL);
7848           }
7849         }
7850       }
7851
7852       /* Create incomplete colorimetry here if needed */
7853       if (CUR_STREAM (stream)->colorimetry.range ||
7854           CUR_STREAM (stream)->colorimetry.matrix ||
7855           CUR_STREAM (stream)->colorimetry.transfer
7856           || CUR_STREAM (stream)->colorimetry.primaries) {
7857         gchar *colorimetry =
7858             gst_video_colorimetry_to_string (&CUR_STREAM (stream)->colorimetry);
7859         gst_caps_set_simple (CUR_STREAM (stream)->caps, "colorimetry",
7860             G_TYPE_STRING, colorimetry, NULL);
7861         g_free (colorimetry);
7862       }
7863
7864       if (stream->multiview_mode != GST_VIDEO_MULTIVIEW_MODE_NONE) {
7865         guint par_w = 1, par_h = 1;
7866
7867         if (CUR_STREAM (stream)->par_w > 0 && CUR_STREAM (stream)->par_h > 0) {
7868           par_w = CUR_STREAM (stream)->par_w;
7869           par_h = CUR_STREAM (stream)->par_h;
7870         }
7871
7872         if (gst_video_multiview_guess_half_aspect (stream->multiview_mode,
7873                 CUR_STREAM (stream)->width, CUR_STREAM (stream)->height, par_w,
7874                 par_h)) {
7875           stream->multiview_flags |= GST_VIDEO_MULTIVIEW_FLAGS_HALF_ASPECT;
7876         }
7877
7878         gst_caps_set_simple (CUR_STREAM (stream)->caps,
7879             "multiview-mode", G_TYPE_STRING,
7880             gst_video_multiview_mode_to_caps_string (stream->multiview_mode),
7881             "multiview-flags", GST_TYPE_VIDEO_MULTIVIEW_FLAGSET,
7882             stream->multiview_flags, GST_FLAG_SET_MASK_EXACT, NULL);
7883       }
7884     }
7885   }
7886
7887   else if (stream->subtype == FOURCC_soun) {
7888     if (CUR_STREAM (stream)->caps) {
7889       CUR_STREAM (stream)->caps =
7890           gst_caps_make_writable (CUR_STREAM (stream)->caps);
7891       if (CUR_STREAM (stream)->rate > 0)
7892         gst_caps_set_simple (CUR_STREAM (stream)->caps,
7893             "rate", G_TYPE_INT, (int) CUR_STREAM (stream)->rate, NULL);
7894       if (CUR_STREAM (stream)->n_channels > 0)
7895         gst_caps_set_simple (CUR_STREAM (stream)->caps,
7896             "channels", G_TYPE_INT, CUR_STREAM (stream)->n_channels, NULL);
7897       if (CUR_STREAM (stream)->n_channels > 2) {
7898         /* FIXME: Need to parse the 'chan' atom to get channel layouts
7899          * correctly; this is just the minimum we can do - assume
7900          * we don't actually have any channel positions. */
7901         gst_caps_set_simple (CUR_STREAM (stream)->caps,
7902             "channel-mask", GST_TYPE_BITMASK, G_GUINT64_CONSTANT (0), NULL);
7903       }
7904     }
7905   }
7906
7907   if (stream->pad) {
7908     GstCaps *prev_caps = NULL;
7909
7910     GST_PAD_ELEMENT_PRIVATE (stream->pad) = stream;
7911     gst_pad_set_event_function (stream->pad, gst_qtdemux_handle_src_event);
7912     gst_pad_set_query_function (stream->pad, gst_qtdemux_handle_src_query);
7913     gst_pad_set_active (stream->pad, TRUE);
7914
7915     gst_pad_use_fixed_caps (stream->pad);
7916
7917     if (stream->protected) {
7918       if (!gst_qtdemux_configure_protected_caps (qtdemux, stream)) {
7919         GST_ERROR_OBJECT (qtdemux,
7920             "Failed to configure protected stream caps.");
7921         return FALSE;
7922       }
7923     }
7924
7925     GST_DEBUG_OBJECT (qtdemux, "setting caps %" GST_PTR_FORMAT,
7926         CUR_STREAM (stream)->caps);
7927     if (stream->new_stream) {
7928       gchar *stream_id;
7929       GstEvent *event;
7930       GstStreamFlags stream_flags = GST_STREAM_FLAG_NONE;
7931
7932       event =
7933           gst_pad_get_sticky_event (qtdemux->sinkpad, GST_EVENT_STREAM_START,
7934           0);
7935       if (event) {
7936         gst_event_parse_stream_flags (event, &stream_flags);
7937         if (gst_event_parse_group_id (event, &qtdemux->group_id))
7938           qtdemux->have_group_id = TRUE;
7939         else
7940           qtdemux->have_group_id = FALSE;
7941         gst_event_unref (event);
7942       } else if (!qtdemux->have_group_id) {
7943         qtdemux->have_group_id = TRUE;
7944         qtdemux->group_id = gst_util_group_id_next ();
7945       }
7946
7947       stream->new_stream = FALSE;
7948       stream_id =
7949           gst_pad_create_stream_id_printf (stream->pad,
7950           GST_ELEMENT_CAST (qtdemux), "%03u", stream->track_id);
7951       event = gst_event_new_stream_start (stream_id);
7952       if (qtdemux->have_group_id)
7953         gst_event_set_group_id (event, qtdemux->group_id);
7954       if (stream->disabled)
7955         stream_flags |= GST_STREAM_FLAG_UNSELECT;
7956       if (CUR_STREAM (stream)->sparse) {
7957         stream_flags |= GST_STREAM_FLAG_SPARSE;
7958       } else {
7959         stream_flags &= ~GST_STREAM_FLAG_SPARSE;
7960       }
7961       gst_event_set_stream_flags (event, stream_flags);
7962       gst_pad_push_event (stream->pad, event);
7963       g_free (stream_id);
7964     }
7965
7966     prev_caps = gst_pad_get_current_caps (stream->pad);
7967
7968     if (CUR_STREAM (stream)->caps) {
7969       if (!prev_caps
7970           || !gst_caps_is_equal_fixed (prev_caps, CUR_STREAM (stream)->caps)) {
7971         GST_DEBUG_OBJECT (qtdemux, "setting caps %" GST_PTR_FORMAT,
7972             CUR_STREAM (stream)->caps);
7973         gst_pad_set_caps (stream->pad, CUR_STREAM (stream)->caps);
7974       } else {
7975         GST_DEBUG_OBJECT (qtdemux, "ignore duplicated caps");
7976       }
7977     } else {
7978       GST_WARNING_OBJECT (qtdemux, "stream without caps");
7979     }
7980
7981     if (prev_caps)
7982       gst_caps_unref (prev_caps);
7983     stream->new_caps = FALSE;
7984   }
7985   return TRUE;
7986 }
7987
7988 static void
7989 gst_qtdemux_stream_check_and_change_stsd_index (GstQTDemux * demux,
7990     QtDemuxStream * stream)
7991 {
7992   if (stream->cur_stsd_entry_index == stream->stsd_sample_description_id)
7993     return;
7994
7995   GST_DEBUG_OBJECT (stream->pad, "Changing stsd index from '%u' to '%u'",
7996       stream->cur_stsd_entry_index, stream->stsd_sample_description_id);
7997   if (G_UNLIKELY (stream->stsd_sample_description_id >=
7998           stream->stsd_entries_length)) {
7999     GST_ELEMENT_ERROR (demux, STREAM, DEMUX,
8000         (_("This file is invalid and cannot be played.")),
8001         ("New sample description id is out of bounds (%d >= %d)",
8002             stream->stsd_sample_description_id, stream->stsd_entries_length));
8003   } else {
8004     stream->cur_stsd_entry_index = stream->stsd_sample_description_id;
8005     stream->new_caps = TRUE;
8006   }
8007 }
8008
8009 static gboolean
8010 gst_qtdemux_add_stream (GstQTDemux * qtdemux,
8011     QtDemuxStream * stream, GstTagList * list)
8012 {
8013   gboolean ret = TRUE;
8014   /* consistent default for push based mode */
8015   gst_segment_init (&stream->segment, GST_FORMAT_TIME);
8016
8017   if (stream->subtype == FOURCC_vide) {
8018     gchar *name = g_strdup_printf ("video_%u", qtdemux->n_video_streams);
8019
8020     stream->pad =
8021         gst_pad_new_from_static_template (&gst_qtdemux_videosrc_template, name);
8022     g_free (name);
8023
8024     if (!gst_qtdemux_configure_stream (qtdemux, stream)) {
8025       gst_object_unref (stream->pad);
8026       stream->pad = NULL;
8027       ret = FALSE;
8028       goto done;
8029     }
8030
8031     qtdemux->n_video_streams++;
8032   } else if (stream->subtype == FOURCC_soun) {
8033     gchar *name = g_strdup_printf ("audio_%u", qtdemux->n_audio_streams);
8034
8035     stream->pad =
8036         gst_pad_new_from_static_template (&gst_qtdemux_audiosrc_template, name);
8037     g_free (name);
8038     if (!gst_qtdemux_configure_stream (qtdemux, stream)) {
8039       gst_object_unref (stream->pad);
8040       stream->pad = NULL;
8041       ret = FALSE;
8042       goto done;
8043     }
8044     qtdemux->n_audio_streams++;
8045   } else if (stream->subtype == FOURCC_strm) {
8046     GST_DEBUG_OBJECT (qtdemux, "stream type, not creating pad");
8047   } else if (stream->subtype == FOURCC_subp || stream->subtype == FOURCC_text
8048       || stream->subtype == FOURCC_sbtl || stream->subtype == FOURCC_subt) {
8049     gchar *name = g_strdup_printf ("subtitle_%u", qtdemux->n_sub_streams);
8050
8051     stream->pad =
8052         gst_pad_new_from_static_template (&gst_qtdemux_subsrc_template, name);
8053     g_free (name);
8054     if (!gst_qtdemux_configure_stream (qtdemux, stream)) {
8055       gst_object_unref (stream->pad);
8056       stream->pad = NULL;
8057       ret = FALSE;
8058       goto done;
8059     }
8060     qtdemux->n_sub_streams++;
8061   } else if (CUR_STREAM (stream)->caps) {
8062     gchar *name = g_strdup_printf ("video_%u", qtdemux->n_video_streams);
8063
8064     stream->pad =
8065         gst_pad_new_from_static_template (&gst_qtdemux_videosrc_template, name);
8066     g_free (name);
8067     if (!gst_qtdemux_configure_stream (qtdemux, stream)) {
8068       gst_object_unref (stream->pad);
8069       stream->pad = NULL;
8070       ret = FALSE;
8071       goto done;
8072     }
8073     qtdemux->n_video_streams++;
8074   } else {
8075     GST_DEBUG_OBJECT (qtdemux, "unknown stream type");
8076     goto done;
8077   }
8078
8079   if (stream->pad) {
8080     GList *l;
8081
8082     GST_DEBUG_OBJECT (qtdemux, "adding pad %s %p to qtdemux %p",
8083         GST_OBJECT_NAME (stream->pad), stream->pad, qtdemux);
8084     gst_element_add_pad (GST_ELEMENT_CAST (qtdemux), stream->pad);
8085     gst_flow_combiner_add_pad (qtdemux->flowcombiner, stream->pad);
8086
8087     if (stream->stream_tags)
8088       gst_tag_list_unref (stream->stream_tags);
8089     stream->stream_tags = list;
8090     list = NULL;
8091     /* global tags go on each pad anyway */
8092     stream->send_global_tags = TRUE;
8093     /* send upstream GST_EVENT_PROTECTION events that were received before
8094        this source pad was created */
8095     for (l = qtdemux->protection_event_queue.head; l != NULL; l = l->next)
8096       gst_pad_push_event (stream->pad, gst_event_ref (l->data));
8097   }
8098 done:
8099   if (list)
8100     gst_tag_list_unref (list);
8101   return ret;
8102 }
8103
8104 /* find next atom with @fourcc starting at @offset */
8105 static GstFlowReturn
8106 qtdemux_find_atom (GstQTDemux * qtdemux, guint64 * offset,
8107     guint64 * length, guint32 fourcc)
8108 {
8109   GstFlowReturn ret;
8110   guint32 lfourcc;
8111   GstBuffer *buf;
8112
8113   GST_LOG_OBJECT (qtdemux, "finding fourcc %" GST_FOURCC_FORMAT " at offset %"
8114       G_GUINT64_FORMAT, GST_FOURCC_ARGS (fourcc), *offset);
8115
8116   while (TRUE) {
8117     GstMapInfo map;
8118
8119     buf = NULL;
8120     ret = gst_pad_pull_range (qtdemux->sinkpad, *offset, 16, &buf);
8121     if (G_UNLIKELY (ret != GST_FLOW_OK))
8122       goto locate_failed;
8123     if (G_UNLIKELY (gst_buffer_get_size (buf) != 16)) {
8124       /* likely EOF */
8125       ret = GST_FLOW_EOS;
8126       gst_buffer_unref (buf);
8127       goto locate_failed;
8128     }
8129     gst_buffer_map (buf, &map, GST_MAP_READ);
8130     extract_initial_length_and_fourcc (map.data, 16, length, &lfourcc);
8131     gst_buffer_unmap (buf, &map);
8132     gst_buffer_unref (buf);
8133
8134     if (G_UNLIKELY (*length == 0)) {
8135       GST_DEBUG_OBJECT (qtdemux, "invalid length 0");
8136       ret = GST_FLOW_ERROR;
8137       goto locate_failed;
8138     }
8139
8140     if (lfourcc == fourcc) {
8141       GST_DEBUG_OBJECT (qtdemux, "found fourcc at offset %" G_GUINT64_FORMAT,
8142           *offset);
8143       break;
8144     } else {
8145       GST_LOG_OBJECT (qtdemux,
8146           "skipping atom '%" GST_FOURCC_FORMAT "' at %" G_GUINT64_FORMAT,
8147           GST_FOURCC_ARGS (fourcc), *offset);
8148       *offset += *length;
8149     }
8150   }
8151
8152   return GST_FLOW_OK;
8153
8154 locate_failed:
8155   {
8156     /* might simply have had last one */
8157     GST_DEBUG_OBJECT (qtdemux, "fourcc not found");
8158     return ret;
8159   }
8160 }
8161
8162 /* should only do something in pull mode */
8163 /* call with OBJECT lock */
8164 static GstFlowReturn
8165 qtdemux_add_fragmented_samples (GstQTDemux * qtdemux)
8166 {
8167   guint64 length, offset;
8168   GstBuffer *buf = NULL;
8169   GstFlowReturn ret = GST_FLOW_OK;
8170   GstFlowReturn res = GST_FLOW_OK;
8171   GstMapInfo map;
8172
8173   offset = qtdemux->moof_offset;
8174   GST_DEBUG_OBJECT (qtdemux, "next moof at offset %" G_GUINT64_FORMAT, offset);
8175
8176   if (!offset) {
8177     GST_DEBUG_OBJECT (qtdemux, "no next moof");
8178     return GST_FLOW_EOS;
8179   }
8180
8181   /* best not do pull etc with lock held */
8182   GST_OBJECT_UNLOCK (qtdemux);
8183
8184   ret = qtdemux_find_atom (qtdemux, &offset, &length, FOURCC_moof);
8185   if (ret != GST_FLOW_OK)
8186     goto flow_failed;
8187
8188   ret = gst_qtdemux_pull_atom (qtdemux, offset, length, &buf);
8189   if (G_UNLIKELY (ret != GST_FLOW_OK))
8190     goto flow_failed;
8191   gst_buffer_map (buf, &map, GST_MAP_READ);
8192   if (!qtdemux_parse_moof (qtdemux, map.data, map.size, offset, NULL)) {
8193     gst_buffer_unmap (buf, &map);
8194     gst_buffer_unref (buf);
8195     buf = NULL;
8196     goto parse_failed;
8197   }
8198
8199   gst_buffer_unmap (buf, &map);
8200   gst_buffer_unref (buf);
8201   buf = NULL;
8202
8203   offset += length;
8204   /* look for next moof */
8205   ret = qtdemux_find_atom (qtdemux, &offset, &length, FOURCC_moof);
8206   if (G_UNLIKELY (ret != GST_FLOW_OK))
8207     goto flow_failed;
8208
8209 exit:
8210   GST_OBJECT_LOCK (qtdemux);
8211
8212   qtdemux->moof_offset = offset;
8213
8214   return res;
8215
8216 parse_failed:
8217   {
8218     GST_DEBUG_OBJECT (qtdemux, "failed to parse moof");
8219     offset = 0;
8220     res = GST_FLOW_ERROR;
8221     goto exit;
8222   }
8223 flow_failed:
8224   {
8225     /* maybe upstream temporarily flushing */
8226     if (ret != GST_FLOW_FLUSHING) {
8227       GST_DEBUG_OBJECT (qtdemux, "no next moof");
8228       offset = 0;
8229     } else {
8230       GST_DEBUG_OBJECT (qtdemux, "upstream WRONG_STATE");
8231       /* resume at current position next time */
8232     }
8233     res = ret;
8234     goto exit;
8235   }
8236 }
8237
8238 /* initialise bytereaders for stbl sub-atoms */
8239 static gboolean
8240 qtdemux_stbl_init (GstQTDemux * qtdemux, QtDemuxStream * stream, GNode * stbl)
8241 {
8242   stream->stbl_index = -1;      /* no samples have yet been parsed */
8243   stream->sample_index = -1;
8244
8245   /* time-to-sample atom */
8246   if (!qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stts, &stream->stts))
8247     goto corrupt_file;
8248
8249   /* copy atom data into a new buffer for later use */
8250   stream->stts.data = g_memdup (stream->stts.data, stream->stts.size);
8251
8252   /* skip version + flags */
8253   if (!gst_byte_reader_skip (&stream->stts, 1 + 3) ||
8254       !gst_byte_reader_get_uint32_be (&stream->stts, &stream->n_sample_times))
8255     goto corrupt_file;
8256   GST_LOG_OBJECT (qtdemux, "%u timestamp blocks", stream->n_sample_times);
8257
8258   /* make sure there's enough data */
8259   if (!qt_atom_parser_has_chunks (&stream->stts, stream->n_sample_times, 8)) {
8260     stream->n_sample_times = gst_byte_reader_get_remaining (&stream->stts) / 8;
8261     GST_LOG_OBJECT (qtdemux, "overriding to %u timestamp blocks",
8262         stream->n_sample_times);
8263     if (!stream->n_sample_times)
8264       goto corrupt_file;
8265   }
8266
8267   /* sync sample atom */
8268   stream->stps_present = FALSE;
8269   if ((stream->stss_present =
8270           ! !qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stss,
8271               &stream->stss) ? TRUE : FALSE) == TRUE) {
8272     /* copy atom data into a new buffer for later use */
8273     stream->stss.data = g_memdup (stream->stss.data, stream->stss.size);
8274
8275     /* skip version + flags */
8276     if (!gst_byte_reader_skip (&stream->stss, 1 + 3) ||
8277         !gst_byte_reader_get_uint32_be (&stream->stss, &stream->n_sample_syncs))
8278       goto corrupt_file;
8279
8280     if (stream->n_sample_syncs) {
8281       /* make sure there's enough data */
8282       if (!qt_atom_parser_has_chunks (&stream->stss, stream->n_sample_syncs, 4))
8283         goto corrupt_file;
8284     }
8285
8286     /* partial sync sample atom */
8287     if ((stream->stps_present =
8288             ! !qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stps,
8289                 &stream->stps) ? TRUE : FALSE) == TRUE) {
8290       /* copy atom data into a new buffer for later use */
8291       stream->stps.data = g_memdup (stream->stps.data, stream->stps.size);
8292
8293       /* skip version + flags */
8294       if (!gst_byte_reader_skip (&stream->stps, 1 + 3) ||
8295           !gst_byte_reader_get_uint32_be (&stream->stps,
8296               &stream->n_sample_partial_syncs))
8297         goto corrupt_file;
8298
8299       /* if there are no entries, the stss table contains the real
8300        * sync samples */
8301       if (stream->n_sample_partial_syncs) {
8302         /* make sure there's enough data */
8303         if (!qt_atom_parser_has_chunks (&stream->stps,
8304                 stream->n_sample_partial_syncs, 4))
8305           goto corrupt_file;
8306       }
8307     }
8308   }
8309
8310   /* sample size */
8311   if (!qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stsz, &stream->stsz))
8312     goto no_samples;
8313
8314   /* copy atom data into a new buffer for later use */
8315   stream->stsz.data = g_memdup (stream->stsz.data, stream->stsz.size);
8316
8317   /* skip version + flags */
8318   if (!gst_byte_reader_skip (&stream->stsz, 1 + 3) ||
8319       !gst_byte_reader_get_uint32_be (&stream->stsz, &stream->sample_size))
8320     goto corrupt_file;
8321
8322   if (!gst_byte_reader_get_uint32_be (&stream->stsz, &stream->n_samples))
8323     goto corrupt_file;
8324
8325   if (!stream->n_samples)
8326     goto no_samples;
8327
8328   /* sample-to-chunk atom */
8329   if (!qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stsc, &stream->stsc))
8330     goto corrupt_file;
8331
8332   /* copy atom data into a new buffer for later use */
8333   stream->stsc.data = g_memdup (stream->stsc.data, stream->stsc.size);
8334
8335   /* skip version + flags */
8336   if (!gst_byte_reader_skip (&stream->stsc, 1 + 3) ||
8337       !gst_byte_reader_get_uint32_be (&stream->stsc,
8338           &stream->n_samples_per_chunk))
8339     goto corrupt_file;
8340
8341   GST_DEBUG_OBJECT (qtdemux, "n_samples_per_chunk %u",
8342       stream->n_samples_per_chunk);
8343
8344   /* make sure there's enough data */
8345   if (!qt_atom_parser_has_chunks (&stream->stsc, stream->n_samples_per_chunk,
8346           12))
8347     goto corrupt_file;
8348
8349
8350   /* chunk offset */
8351   if (qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stco, &stream->stco))
8352     stream->co_size = sizeof (guint32);
8353   else if (qtdemux_tree_get_child_by_type_full (stbl, FOURCC_co64,
8354           &stream->stco))
8355     stream->co_size = sizeof (guint64);
8356   else
8357     goto corrupt_file;
8358
8359   /* copy atom data into a new buffer for later use */
8360   stream->stco.data = g_memdup (stream->stco.data, stream->stco.size);
8361
8362   /* skip version + flags */
8363   if (!gst_byte_reader_skip (&stream->stco, 1 + 3))
8364     goto corrupt_file;
8365
8366   /* chunks_are_samples == TRUE means treat chunks as samples */
8367   stream->chunks_are_samples = stream->sample_size
8368       && !CUR_STREAM (stream)->sampled;
8369   if (stream->chunks_are_samples) {
8370     /* treat chunks as samples */
8371     if (!gst_byte_reader_get_uint32_be (&stream->stco, &stream->n_samples))
8372       goto corrupt_file;
8373   } else {
8374     /* skip number of entries */
8375     if (!gst_byte_reader_skip (&stream->stco, 4))
8376       goto corrupt_file;
8377
8378     /* make sure there are enough data in the stsz atom */
8379     if (!stream->sample_size) {
8380       /* different sizes for each sample */
8381       if (!qt_atom_parser_has_chunks (&stream->stsz, stream->n_samples, 4))
8382         goto corrupt_file;
8383     }
8384   }
8385
8386   GST_DEBUG_OBJECT (qtdemux, "allocating n_samples %u * %u (%.2f MB)",
8387       stream->n_samples, (guint) sizeof (QtDemuxSample),
8388       stream->n_samples * sizeof (QtDemuxSample) / (1024.0 * 1024.0));
8389
8390   if (stream->n_samples >=
8391       QTDEMUX_MAX_SAMPLE_INDEX_SIZE / sizeof (QtDemuxSample)) {
8392     GST_WARNING_OBJECT (qtdemux, "not allocating index of %d samples, would "
8393         "be larger than %uMB (broken file?)", stream->n_samples,
8394         QTDEMUX_MAX_SAMPLE_INDEX_SIZE >> 20);
8395     return FALSE;
8396   }
8397
8398   g_assert (stream->samples == NULL);
8399   stream->samples = g_try_new0 (QtDemuxSample, stream->n_samples);
8400   if (!stream->samples) {
8401     GST_WARNING_OBJECT (qtdemux, "failed to allocate %d samples",
8402         stream->n_samples);
8403     return FALSE;
8404   }
8405
8406   /* composition time-to-sample */
8407   if ((stream->ctts_present =
8408           ! !qtdemux_tree_get_child_by_type_full (stbl, FOURCC_ctts,
8409               &stream->ctts) ? TRUE : FALSE) == TRUE) {
8410     GstByteReader cslg = GST_BYTE_READER_INIT (NULL, 0);
8411
8412     /* copy atom data into a new buffer for later use */
8413     stream->ctts.data = g_memdup (stream->ctts.data, stream->ctts.size);
8414
8415     /* skip version + flags */
8416     if (!gst_byte_reader_skip (&stream->ctts, 1 + 3)
8417         || !gst_byte_reader_get_uint32_be (&stream->ctts,
8418             &stream->n_composition_times))
8419       goto corrupt_file;
8420
8421     /* make sure there's enough data */
8422     if (!qt_atom_parser_has_chunks (&stream->ctts, stream->n_composition_times,
8423             4 + 4))
8424       goto corrupt_file;
8425
8426     /* This is optional, if missing we iterate the ctts */
8427     if (qtdemux_tree_get_child_by_type_full (stbl, FOURCC_cslg, &cslg)) {
8428       if (!gst_byte_reader_skip (&cslg, 1 + 3)
8429           || !gst_byte_reader_get_uint32_be (&cslg, &stream->cslg_shift)) {
8430         g_free ((gpointer) cslg.data);
8431         goto corrupt_file;
8432       }
8433     } else {
8434       gint32 cslg_least = 0;
8435       guint num_entries, pos;
8436       gint i;
8437
8438       pos = gst_byte_reader_get_pos (&stream->ctts);
8439       num_entries = stream->n_composition_times;
8440
8441       stream->cslg_shift = 0;
8442
8443       for (i = 0; i < num_entries; i++) {
8444         gint32 offset;
8445
8446         gst_byte_reader_skip_unchecked (&stream->ctts, 4);
8447         offset = gst_byte_reader_get_int32_be_unchecked (&stream->ctts);
8448
8449         if (offset < cslg_least)
8450           cslg_least = offset;
8451       }
8452
8453       if (cslg_least < 0)
8454         stream->cslg_shift = ABS (cslg_least);
8455       else
8456         stream->cslg_shift = 0;
8457
8458       /* reset the reader so we can generate sample table */
8459       gst_byte_reader_set_pos (&stream->ctts, pos);
8460     }
8461   } else {
8462     /* Ensure the cslg_shift value is consistent so we can use it
8463      * unconditionnally to produce TS and Segment */
8464     stream->cslg_shift = 0;
8465   }
8466
8467   return TRUE;
8468
8469 corrupt_file:
8470   {
8471     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
8472         (_("This file is corrupt and cannot be played.")), (NULL));
8473     return FALSE;
8474   }
8475 no_samples:
8476   {
8477     gst_qtdemux_stbl_free (stream);
8478     if (!qtdemux->fragmented) {
8479       /* not quite good */
8480       GST_WARNING_OBJECT (qtdemux, "stream has no samples");
8481       return FALSE;
8482     } else {
8483       /* may pick up samples elsewhere */
8484       return TRUE;
8485     }
8486   }
8487 }
8488
8489 /* collect samples from the next sample to be parsed up to sample @n for @stream
8490  * by reading the info from @stbl
8491  *
8492  * This code can be executed from both the streaming thread and the seeking
8493  * thread so it takes the object lock to protect itself
8494  */
8495 static gboolean
8496 qtdemux_parse_samples (GstQTDemux * qtdemux, QtDemuxStream * stream, guint32 n)
8497 {
8498   gint i, j, k;
8499   QtDemuxSample *samples, *first, *cur, *last;
8500   guint32 n_samples_per_chunk;
8501   guint32 n_samples;
8502
8503   GST_LOG_OBJECT (qtdemux, "parsing samples for stream fourcc %"
8504       GST_FOURCC_FORMAT ", pad %s",
8505       GST_FOURCC_ARGS (CUR_STREAM (stream)->fourcc),
8506       stream->pad ? GST_PAD_NAME (stream->pad) : "(NULL)");
8507
8508   n_samples = stream->n_samples;
8509
8510   if (n >= n_samples)
8511     goto out_of_samples;
8512
8513   GST_OBJECT_LOCK (qtdemux);
8514   if (n <= stream->stbl_index)
8515     goto already_parsed;
8516
8517   GST_DEBUG_OBJECT (qtdemux, "parsing up to sample %u", n);
8518
8519   if (!stream->stsz.data) {
8520     /* so we already parsed and passed all the moov samples;
8521      * onto fragmented ones */
8522     g_assert (qtdemux->fragmented);
8523     goto done;
8524   }
8525
8526   /* pointer to the sample table */
8527   samples = stream->samples;
8528
8529   /* starts from -1, moves to the next sample index to parse */
8530   stream->stbl_index++;
8531
8532   /* keep track of the first and last sample to fill */
8533   first = &samples[stream->stbl_index];
8534   last = &samples[n];
8535
8536   if (!stream->chunks_are_samples) {
8537     /* set the sample sizes */
8538     if (stream->sample_size == 0) {
8539       /* different sizes for each sample */
8540       for (cur = first; cur <= last; cur++) {
8541         cur->size = gst_byte_reader_get_uint32_be_unchecked (&stream->stsz);
8542         GST_LOG_OBJECT (qtdemux, "sample %d has size %u",
8543             (guint) (cur - samples), cur->size);
8544       }
8545     } else {
8546       /* samples have the same size */
8547       GST_LOG_OBJECT (qtdemux, "all samples have size %u", stream->sample_size);
8548       for (cur = first; cur <= last; cur++)
8549         cur->size = stream->sample_size;
8550     }
8551   }
8552
8553   n_samples_per_chunk = stream->n_samples_per_chunk;
8554   cur = first;
8555
8556   for (i = stream->stsc_index; i < n_samples_per_chunk; i++) {
8557     guint32 last_chunk;
8558
8559     if (stream->stsc_chunk_index >= stream->last_chunk
8560         || stream->stsc_chunk_index < stream->first_chunk) {
8561       stream->first_chunk =
8562           gst_byte_reader_get_uint32_be_unchecked (&stream->stsc);
8563       stream->samples_per_chunk =
8564           gst_byte_reader_get_uint32_be_unchecked (&stream->stsc);
8565       /* starts from 1 */
8566       stream->stsd_sample_description_id =
8567           gst_byte_reader_get_uint32_be_unchecked (&stream->stsc) - 1;
8568
8569       /* chunk numbers are counted from 1 it seems */
8570       if (G_UNLIKELY (stream->first_chunk == 0))
8571         goto corrupt_file;
8572
8573       --stream->first_chunk;
8574
8575       /* the last chunk of each entry is calculated by taking the first chunk
8576        * of the next entry; except if there is no next, where we fake it with
8577        * INT_MAX */
8578       if (G_UNLIKELY (i == (stream->n_samples_per_chunk - 1))) {
8579         stream->last_chunk = G_MAXUINT32;
8580       } else {
8581         stream->last_chunk =
8582             gst_byte_reader_peek_uint32_be_unchecked (&stream->stsc);
8583         if (G_UNLIKELY (stream->last_chunk == 0))
8584           goto corrupt_file;
8585
8586         --stream->last_chunk;
8587       }
8588
8589       GST_LOG_OBJECT (qtdemux,
8590           "entry %d has first_chunk %d, last_chunk %d, samples_per_chunk %d"
8591           "sample desc ID: %d", i, stream->first_chunk, stream->last_chunk,
8592           stream->samples_per_chunk, stream->stsd_sample_description_id);
8593
8594       if (G_UNLIKELY (stream->last_chunk < stream->first_chunk))
8595         goto corrupt_file;
8596
8597       if (stream->last_chunk != G_MAXUINT32) {
8598         if (!qt_atom_parser_peek_sub (&stream->stco,
8599                 stream->first_chunk * stream->co_size,
8600                 (stream->last_chunk - stream->first_chunk) * stream->co_size,
8601                 &stream->co_chunk))
8602           goto corrupt_file;
8603
8604       } else {
8605         stream->co_chunk = stream->stco;
8606         if (!gst_byte_reader_skip (&stream->co_chunk,
8607                 stream->first_chunk * stream->co_size))
8608           goto corrupt_file;
8609       }
8610
8611       stream->stsc_chunk_index = stream->first_chunk;
8612     }
8613
8614     last_chunk = stream->last_chunk;
8615
8616     if (stream->chunks_are_samples) {
8617       cur = &samples[stream->stsc_chunk_index];
8618
8619       for (j = stream->stsc_chunk_index; j < last_chunk; j++) {
8620         if (j > n) {
8621           /* save state */
8622           stream->stsc_chunk_index = j;
8623           goto done;
8624         }
8625
8626         cur->offset =
8627             qt_atom_parser_get_offset_unchecked (&stream->co_chunk,
8628             stream->co_size);
8629
8630         GST_LOG_OBJECT (qtdemux, "Created entry %d with offset "
8631             "%" G_GUINT64_FORMAT, j, cur->offset);
8632
8633         if (CUR_STREAM (stream)->samples_per_frame > 0 &&
8634             CUR_STREAM (stream)->bytes_per_frame > 0) {
8635           cur->size =
8636               (stream->samples_per_chunk * CUR_STREAM (stream)->n_channels) /
8637               CUR_STREAM (stream)->samples_per_frame *
8638               CUR_STREAM (stream)->bytes_per_frame;
8639         } else {
8640           cur->size = stream->samples_per_chunk;
8641         }
8642
8643         GST_DEBUG_OBJECT (qtdemux,
8644             "keyframe sample %d: timestamp %" GST_TIME_FORMAT ", size %u",
8645             j, GST_TIME_ARGS (QTSTREAMTIME_TO_GSTTIME (stream,
8646                     stream->stco_sample_index)), cur->size);
8647
8648         cur->timestamp = stream->stco_sample_index;
8649         cur->duration = stream->samples_per_chunk;
8650         cur->keyframe = TRUE;
8651         cur++;
8652
8653         stream->stco_sample_index += stream->samples_per_chunk;
8654       }
8655       stream->stsc_chunk_index = j;
8656     } else {
8657       for (j = stream->stsc_chunk_index; j < last_chunk; j++) {
8658         guint32 samples_per_chunk;
8659         guint64 chunk_offset;
8660
8661         if (!stream->stsc_sample_index
8662             && !qt_atom_parser_get_offset (&stream->co_chunk, stream->co_size,
8663                 &stream->chunk_offset))
8664           goto corrupt_file;
8665
8666         samples_per_chunk = stream->samples_per_chunk;
8667         chunk_offset = stream->chunk_offset;
8668
8669         for (k = stream->stsc_sample_index; k < samples_per_chunk; k++) {
8670           GST_LOG_OBJECT (qtdemux, "creating entry %d with offset %"
8671               G_GUINT64_FORMAT " and size %d",
8672               (guint) (cur - samples), chunk_offset, cur->size);
8673
8674           cur->offset = chunk_offset;
8675           chunk_offset += cur->size;
8676           cur++;
8677
8678           if (G_UNLIKELY (cur > last)) {
8679             /* save state */
8680             stream->stsc_sample_index = k + 1;
8681             stream->chunk_offset = chunk_offset;
8682             stream->stsc_chunk_index = j;
8683             goto done2;
8684           }
8685         }
8686         stream->stsc_sample_index = 0;
8687       }
8688       stream->stsc_chunk_index = j;
8689     }
8690     stream->stsc_index++;
8691   }
8692
8693   if (stream->chunks_are_samples)
8694     goto ctts;
8695 done2:
8696   {
8697     guint32 n_sample_times;
8698
8699     n_sample_times = stream->n_sample_times;
8700     cur = first;
8701
8702     for (i = stream->stts_index; i < n_sample_times; i++) {
8703       guint32 stts_samples;
8704       gint32 stts_duration;
8705       gint64 stts_time;
8706
8707       if (stream->stts_sample_index >= stream->stts_samples
8708           || !stream->stts_sample_index) {
8709
8710         stream->stts_samples =
8711             gst_byte_reader_get_uint32_be_unchecked (&stream->stts);
8712         stream->stts_duration =
8713             gst_byte_reader_get_uint32_be_unchecked (&stream->stts);
8714
8715         GST_LOG_OBJECT (qtdemux, "block %d, %u timestamps, duration %u",
8716             i, stream->stts_samples, stream->stts_duration);
8717
8718         stream->stts_sample_index = 0;
8719       }
8720
8721       stts_samples = stream->stts_samples;
8722       stts_duration = stream->stts_duration;
8723       stts_time = stream->stts_time;
8724
8725       for (j = stream->stts_sample_index; j < stts_samples; j++) {
8726         GST_DEBUG_OBJECT (qtdemux,
8727             "sample %d: index %d, timestamp %" GST_TIME_FORMAT,
8728             (guint) (cur - samples), j,
8729             GST_TIME_ARGS (QTSTREAMTIME_TO_GSTTIME (stream, stts_time)));
8730
8731         cur->timestamp = stts_time;
8732         cur->duration = stts_duration;
8733
8734         /* avoid 32-bit wrap-around,
8735          * but still mind possible 'negative' duration */
8736         stts_time += (gint64) stts_duration;
8737         cur++;
8738
8739         if (G_UNLIKELY (cur > last)) {
8740           /* save values */
8741           stream->stts_time = stts_time;
8742           stream->stts_sample_index = j + 1;
8743           if (stream->stts_sample_index >= stream->stts_samples)
8744             stream->stts_index++;
8745           goto done3;
8746         }
8747       }
8748       stream->stts_sample_index = 0;
8749       stream->stts_time = stts_time;
8750       stream->stts_index++;
8751     }
8752     /* fill up empty timestamps with the last timestamp, this can happen when
8753      * the last samples do not decode and so we don't have timestamps for them.
8754      * We however look at the last timestamp to estimate the track length so we
8755      * need something in here. */
8756     for (; cur < last; cur++) {
8757       GST_DEBUG_OBJECT (qtdemux,
8758           "fill sample %d: timestamp %" GST_TIME_FORMAT,
8759           (guint) (cur - samples),
8760           GST_TIME_ARGS (QTSTREAMTIME_TO_GSTTIME (stream, stream->stts_time)));
8761       cur->timestamp = stream->stts_time;
8762       cur->duration = -1;
8763     }
8764   }
8765 done3:
8766   {
8767     /* sample sync, can be NULL */
8768     if (stream->stss_present == TRUE) {
8769       guint32 n_sample_syncs;
8770
8771       n_sample_syncs = stream->n_sample_syncs;
8772
8773       if (!n_sample_syncs) {
8774         GST_DEBUG_OBJECT (qtdemux, "all samples are keyframes");
8775         stream->all_keyframe = TRUE;
8776       } else {
8777         for (i = stream->stss_index; i < n_sample_syncs; i++) {
8778           /* note that the first sample is index 1, not 0 */
8779           guint32 index;
8780
8781           index = gst_byte_reader_get_uint32_be_unchecked (&stream->stss);
8782
8783           if (G_LIKELY (index > 0 && index <= n_samples)) {
8784             index -= 1;
8785             samples[index].keyframe = TRUE;
8786             GST_DEBUG_OBJECT (qtdemux, "samples at %u is keyframe", index);
8787             /* and exit if we have enough samples */
8788             if (G_UNLIKELY (index >= n)) {
8789               i++;
8790               break;
8791             }
8792           }
8793         }
8794         /* save state */
8795         stream->stss_index = i;
8796       }
8797
8798       /* stps marks partial sync frames like open GOP I-Frames */
8799       if (stream->stps_present == TRUE) {
8800         guint32 n_sample_partial_syncs;
8801
8802         n_sample_partial_syncs = stream->n_sample_partial_syncs;
8803
8804         /* if there are no entries, the stss table contains the real
8805          * sync samples */
8806         if (n_sample_partial_syncs) {
8807           for (i = stream->stps_index; i < n_sample_partial_syncs; i++) {
8808             /* note that the first sample is index 1, not 0 */
8809             guint32 index;
8810
8811             index = gst_byte_reader_get_uint32_be_unchecked (&stream->stps);
8812
8813             if (G_LIKELY (index > 0 && index <= n_samples)) {
8814               index -= 1;
8815               samples[index].keyframe = TRUE;
8816               GST_DEBUG_OBJECT (qtdemux, "samples at %u is keyframe", index);
8817               /* and exit if we have enough samples */
8818               if (G_UNLIKELY (index >= n)) {
8819                 i++;
8820                 break;
8821               }
8822             }
8823           }
8824           /* save state */
8825           stream->stps_index = i;
8826         }
8827       }
8828     } else {
8829       /* no stss, all samples are keyframes */
8830       stream->all_keyframe = TRUE;
8831       GST_DEBUG_OBJECT (qtdemux, "setting all keyframes");
8832     }
8833   }
8834
8835 ctts:
8836   /* composition time to sample */
8837   if (stream->ctts_present == TRUE) {
8838     guint32 n_composition_times;
8839     guint32 ctts_count;
8840     gint32 ctts_soffset;
8841
8842     /* Fill in the pts_offsets */
8843     cur = first;
8844     n_composition_times = stream->n_composition_times;
8845
8846     for (i = stream->ctts_index; i < n_composition_times; i++) {
8847       if (stream->ctts_sample_index >= stream->ctts_count
8848           || !stream->ctts_sample_index) {
8849         stream->ctts_count =
8850             gst_byte_reader_get_uint32_be_unchecked (&stream->ctts);
8851         stream->ctts_soffset =
8852             gst_byte_reader_get_int32_be_unchecked (&stream->ctts);
8853         stream->ctts_sample_index = 0;
8854       }
8855
8856       ctts_count = stream->ctts_count;
8857       ctts_soffset = stream->ctts_soffset;
8858
8859       for (j = stream->ctts_sample_index; j < ctts_count; j++) {
8860         cur->pts_offset = ctts_soffset;
8861         cur++;
8862
8863         if (G_UNLIKELY (cur > last)) {
8864           /* save state */
8865           stream->ctts_sample_index = j + 1;
8866           goto done;
8867         }
8868       }
8869       stream->ctts_sample_index = 0;
8870       stream->ctts_index++;
8871     }
8872   }
8873 done:
8874   stream->stbl_index = n;
8875   /* if index has been completely parsed, free data that is no-longer needed */
8876   if (n + 1 == stream->n_samples) {
8877     gst_qtdemux_stbl_free (stream);
8878     GST_DEBUG_OBJECT (qtdemux, "parsed all available samples;");
8879     if (qtdemux->pullbased) {
8880       GST_DEBUG_OBJECT (qtdemux, "checking for more samples");
8881       while (n + 1 == stream->n_samples)
8882         if (qtdemux_add_fragmented_samples (qtdemux) != GST_FLOW_OK)
8883           break;
8884     }
8885   }
8886   GST_OBJECT_UNLOCK (qtdemux);
8887
8888   return TRUE;
8889
8890   /* SUCCESS */
8891 already_parsed:
8892   {
8893     GST_LOG_OBJECT (qtdemux,
8894         "Tried to parse up to sample %u but this sample has already been parsed",
8895         n);
8896     /* if fragmented, there may be more */
8897     if (qtdemux->fragmented && n == stream->stbl_index)
8898       goto done;
8899     GST_OBJECT_UNLOCK (qtdemux);
8900     return TRUE;
8901   }
8902   /* ERRORS */
8903 out_of_samples:
8904   {
8905     GST_LOG_OBJECT (qtdemux,
8906         "Tried to parse up to sample %u but there are only %u samples", n + 1,
8907         stream->n_samples);
8908     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
8909         (_("This file is corrupt and cannot be played.")), (NULL));
8910     return FALSE;
8911   }
8912 corrupt_file:
8913   {
8914     GST_OBJECT_UNLOCK (qtdemux);
8915     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
8916         (_("This file is corrupt and cannot be played.")), (NULL));
8917     return FALSE;
8918   }
8919 }
8920
8921 /* collect all segment info for @stream.
8922  */
8923 static gboolean
8924 qtdemux_parse_segments (GstQTDemux * qtdemux, QtDemuxStream * stream,
8925     GNode * trak)
8926 {
8927   GNode *edts;
8928   /* accept edts if they contain gaps at start and there is only
8929    * one media segment */
8930   gboolean allow_pushbased_edts = TRUE;
8931   gint media_segments_count = 0;
8932
8933   /* parse and prepare segment info from the edit list */
8934   GST_DEBUG_OBJECT (qtdemux, "looking for edit list container");
8935   stream->n_segments = 0;
8936   stream->segments = NULL;
8937   if ((edts = qtdemux_tree_get_child_by_type (trak, FOURCC_edts))) {
8938     GNode *elst;
8939     gint n_segments;
8940     gint i, count, entry_size;
8941     guint64 time;
8942     GstClockTime stime;
8943     const guint8 *buffer;
8944     guint8 version;
8945     guint32 size;
8946
8947     GST_DEBUG_OBJECT (qtdemux, "looking for edit list");
8948     if (!(elst = qtdemux_tree_get_child_by_type (edts, FOURCC_elst)))
8949       goto done;
8950
8951     buffer = elst->data;
8952
8953     size = QT_UINT32 (buffer);
8954     /* version, flags, n_segments */
8955     if (size < 16) {
8956       GST_WARNING_OBJECT (qtdemux, "Invalid edit list");
8957       goto done;
8958     }
8959     version = QT_UINT8 (buffer + 8);
8960     entry_size = (version == 1) ? 20 : 12;
8961
8962     n_segments = QT_UINT32 (buffer + 12);
8963
8964     if (n_segments > 100000 || size < 16 + n_segments * entry_size) {
8965       GST_WARNING_OBJECT (qtdemux, "Invalid edit list");
8966       goto done;
8967     }
8968
8969     /* we might allocate a bit too much, at least allocate 1 segment */
8970     stream->segments = g_new (QtDemuxSegment, MAX (n_segments, 1));
8971
8972     /* segments always start from 0 */
8973     time = 0;
8974     stime = 0;
8975     count = 0;
8976     buffer += 16;
8977     for (i = 0; i < n_segments; i++) {
8978       guint64 duration;
8979       guint64 media_time;
8980       gboolean time_valid = TRUE;
8981       QtDemuxSegment *segment;
8982       guint32 rate_int;
8983       GstClockTime media_start = GST_CLOCK_TIME_NONE;
8984
8985       if (version == 1) {
8986         media_time = QT_UINT64 (buffer + 8);
8987         duration = QT_UINT64 (buffer);
8988         if (media_time == G_MAXUINT64)
8989           time_valid = FALSE;
8990       } else {
8991         media_time = QT_UINT32 (buffer + 4);
8992         duration = QT_UINT32 (buffer);
8993         if (media_time == G_MAXUINT32)
8994           time_valid = FALSE;
8995       }
8996
8997       if (time_valid)
8998         media_start = QTSTREAMTIME_TO_GSTTIME (stream, media_time);
8999
9000       segment = &stream->segments[count++];
9001
9002       /* time and duration expressed in global timescale */
9003       segment->time = stime;
9004       /* add non scaled values so we don't cause roundoff errors */
9005       if (duration || media_start == GST_CLOCK_TIME_NONE) {
9006         time += duration;
9007         stime = QTTIME_TO_GSTTIME (qtdemux, time);
9008         segment->duration = stime - segment->time;
9009       } else {
9010         /* zero duration does not imply media_start == media_stop
9011          * but, only specify media_start.*/
9012         stime = QTTIME_TO_GSTTIME (qtdemux, qtdemux->duration);
9013         if (GST_CLOCK_TIME_IS_VALID (stime) && time_valid
9014             && stime >= media_start) {
9015           segment->duration = stime - media_start;
9016         } else {
9017           segment->duration = GST_CLOCK_TIME_NONE;
9018         }
9019       }
9020       segment->stop_time = stime;
9021
9022       segment->trak_media_start = media_time;
9023       /* media_time expressed in stream timescale */
9024       if (time_valid) {
9025         segment->media_start = media_start;
9026         segment->media_stop = segment->media_start + segment->duration;
9027         media_segments_count++;
9028       } else {
9029         segment->media_start = GST_CLOCK_TIME_NONE;
9030         segment->media_stop = GST_CLOCK_TIME_NONE;
9031       }
9032       rate_int = QT_UINT32 (buffer + ((version == 1) ? 16 : 8));
9033
9034       if (rate_int <= 1) {
9035         /* 0 is not allowed, some programs write 1 instead of the floating point
9036          * value */
9037         GST_WARNING_OBJECT (qtdemux, "found suspicious rate %" G_GUINT32_FORMAT,
9038             rate_int);
9039         segment->rate = 1;
9040       } else {
9041         segment->rate = rate_int / 65536.0;
9042       }
9043
9044       GST_DEBUG_OBJECT (qtdemux, "created segment %d time %" GST_TIME_FORMAT
9045           ", duration %" GST_TIME_FORMAT ", media_start %" GST_TIME_FORMAT
9046           " (%" G_GUINT64_FORMAT ") , media_stop %" GST_TIME_FORMAT
9047           " stop_time %" GST_TIME_FORMAT " rate %g, (%d) timescale %u",
9048           i, GST_TIME_ARGS (segment->time),
9049           GST_TIME_ARGS (segment->duration),
9050           GST_TIME_ARGS (segment->media_start), media_time,
9051           GST_TIME_ARGS (segment->media_stop),
9052           GST_TIME_ARGS (segment->stop_time), segment->rate, rate_int,
9053           stream->timescale);
9054       if (segment->stop_time > qtdemux->segment.stop) {
9055         GST_WARNING_OBJECT (qtdemux, "Segment %d "
9056             " extends to %" GST_TIME_FORMAT
9057             " past the end of the file duration %" GST_TIME_FORMAT
9058             " it will be truncated", i, GST_TIME_ARGS (segment->stop_time),
9059             GST_TIME_ARGS (qtdemux->segment.stop));
9060         qtdemux->segment.stop = segment->stop_time;
9061       }
9062
9063       buffer += entry_size;
9064     }
9065     GST_DEBUG_OBJECT (qtdemux, "found %d segments", count);
9066     stream->n_segments = count;
9067     if (media_segments_count != 1)
9068       allow_pushbased_edts = FALSE;
9069   }
9070 done:
9071
9072   /* push based does not handle segments, so act accordingly here,
9073    * and warn if applicable */
9074   if (!qtdemux->pullbased && !allow_pushbased_edts) {
9075     GST_WARNING_OBJECT (qtdemux, "streaming; discarding edit list segments");
9076     /* remove and use default one below, we stream like it anyway */
9077     g_free (stream->segments);
9078     stream->segments = NULL;
9079     stream->n_segments = 0;
9080   }
9081
9082   /* no segments, create one to play the complete trak */
9083   if (stream->n_segments == 0) {
9084     GstClockTime stream_duration =
9085         QTSTREAMTIME_TO_GSTTIME (stream, stream->duration);
9086
9087     if (stream->segments == NULL)
9088       stream->segments = g_new (QtDemuxSegment, 1);
9089
9090     /* represent unknown our way */
9091     if (stream_duration == 0)
9092       stream_duration = GST_CLOCK_TIME_NONE;
9093
9094     stream->segments[0].time = 0;
9095     stream->segments[0].stop_time = stream_duration;
9096     stream->segments[0].duration = stream_duration;
9097     stream->segments[0].media_start = 0;
9098     stream->segments[0].media_stop = stream_duration;
9099     stream->segments[0].rate = 1.0;
9100     stream->segments[0].trak_media_start = 0;
9101
9102     GST_DEBUG_OBJECT (qtdemux, "created dummy segment %" GST_TIME_FORMAT,
9103         GST_TIME_ARGS (stream_duration));
9104     stream->n_segments = 1;
9105     stream->dummy_segment = TRUE;
9106   }
9107   GST_DEBUG_OBJECT (qtdemux, "using %d segments", stream->n_segments);
9108
9109   return TRUE;
9110 }
9111
9112 /*
9113  * Parses the stsd atom of a svq3 trak looking for
9114  * the SMI and gama atoms.
9115  */
9116 static void
9117 qtdemux_parse_svq3_stsd_data (GstQTDemux * qtdemux,
9118     const guint8 * stsd_entry_data, const guint8 ** gamma, GstBuffer ** seqh)
9119 {
9120   const guint8 *_gamma = NULL;
9121   GstBuffer *_seqh = NULL;
9122   const guint8 *stsd_data = stsd_entry_data;
9123   guint32 length = QT_UINT32 (stsd_data);
9124   guint16 version;
9125
9126   if (length < 32) {
9127     GST_WARNING_OBJECT (qtdemux, "stsd too short");
9128     goto end;
9129   }
9130
9131   stsd_data += 16;
9132   length -= 16;
9133   version = QT_UINT16 (stsd_data);
9134   if (version == 3) {
9135     if (length >= 70) {
9136       length -= 70;
9137       stsd_data += 70;
9138       while (length > 8) {
9139         guint32 fourcc, size;
9140         const guint8 *data;
9141         size = QT_UINT32 (stsd_data);
9142         fourcc = QT_FOURCC (stsd_data + 4);
9143         data = stsd_data + 8;
9144
9145         if (size == 0) {
9146           GST_WARNING_OBJECT (qtdemux, "Atom of size 0 found, aborting "
9147               "svq3 atom parsing");
9148           goto end;
9149         }
9150
9151         switch (fourcc) {
9152           case FOURCC_gama:{
9153             if (size == 12) {
9154               _gamma = data;
9155             } else {
9156               GST_WARNING_OBJECT (qtdemux, "Unexpected size %" G_GUINT32_FORMAT
9157                   " for gama atom, expected 12", size);
9158             }
9159             break;
9160           }
9161           case FOURCC_SMI_:{
9162             if (size > 16 && QT_FOURCC (data) == FOURCC_SEQH) {
9163               guint32 seqh_size;
9164               if (_seqh != NULL) {
9165                 GST_WARNING_OBJECT (qtdemux, "Unexpected second SEQH SMI atom "
9166                     " found, ignoring");
9167               } else {
9168                 seqh_size = QT_UINT32 (data + 4);
9169                 if (seqh_size > 0) {
9170                   _seqh = gst_buffer_new_and_alloc (seqh_size);
9171                   gst_buffer_fill (_seqh, 0, data + 8, seqh_size);
9172                 }
9173               }
9174             }
9175             break;
9176           }
9177           default:{
9178             GST_WARNING_OBJECT (qtdemux, "Unhandled atom %" GST_FOURCC_FORMAT
9179                 " in SVQ3 entry in stsd atom", GST_FOURCC_ARGS (fourcc));
9180           }
9181         }
9182
9183         if (size <= length) {
9184           length -= size;
9185           stsd_data += size;
9186         }
9187       }
9188     } else {
9189       GST_WARNING_OBJECT (qtdemux, "SVQ3 entry too short in stsd atom");
9190     }
9191   } else {
9192     GST_WARNING_OBJECT (qtdemux, "Unexpected version for SVQ3 entry %"
9193         G_GUINT16_FORMAT, version);
9194     goto end;
9195   }
9196
9197 end:
9198   if (gamma) {
9199     *gamma = _gamma;
9200   }
9201   if (seqh) {
9202     *seqh = _seqh;
9203   } else if (_seqh) {
9204     gst_buffer_unref (_seqh);
9205   }
9206 }
9207
9208 static gchar *
9209 qtdemux_get_rtsp_uri_from_hndl (GstQTDemux * qtdemux, GNode * minf)
9210 {
9211   GNode *dinf;
9212   GstByteReader dref;
9213   gchar *uri = NULL;
9214
9215   /*
9216    * Get 'dinf', to get its child 'dref', that might contain a 'hndl'
9217    * atom that might contain a 'data' atom with the rtsp uri.
9218    * This case was reported in bug #597497, some info about
9219    * the hndl atom can be found in TN1195
9220    */
9221   dinf = qtdemux_tree_get_child_by_type (minf, FOURCC_dinf);
9222   GST_DEBUG_OBJECT (qtdemux, "Trying to obtain rtsp URI for stream trak");
9223
9224   if (dinf) {
9225     guint32 dref_num_entries = 0;
9226     if (qtdemux_tree_get_child_by_type_full (dinf, FOURCC_dref, &dref) &&
9227         gst_byte_reader_skip (&dref, 4) &&
9228         gst_byte_reader_get_uint32_be (&dref, &dref_num_entries)) {
9229       gint i;
9230
9231       /* search dref entries for hndl atom */
9232       for (i = 0; i < dref_num_entries; i++) {
9233         guint32 size = 0, type;
9234         guint8 string_len = 0;
9235         if (gst_byte_reader_get_uint32_be (&dref, &size) &&
9236             qt_atom_parser_get_fourcc (&dref, &type)) {
9237           if (type == FOURCC_hndl) {
9238             GST_DEBUG_OBJECT (qtdemux, "Found hndl atom");
9239
9240             /* skip data reference handle bytes and the
9241              * following pascal string and some extra 4
9242              * bytes I have no idea what are */
9243             if (!gst_byte_reader_skip (&dref, 4) ||
9244                 !gst_byte_reader_get_uint8 (&dref, &string_len) ||
9245                 !gst_byte_reader_skip (&dref, string_len + 4)) {
9246               GST_WARNING_OBJECT (qtdemux, "Failed to parse hndl atom");
9247               break;
9248             }
9249
9250             /* iterate over the atoms to find the data atom */
9251             while (gst_byte_reader_get_remaining (&dref) >= 8) {
9252               guint32 atom_size;
9253               guint32 atom_type;
9254
9255               if (gst_byte_reader_get_uint32_be (&dref, &atom_size) &&
9256                   qt_atom_parser_get_fourcc (&dref, &atom_type)) {
9257                 if (atom_type == FOURCC_data) {
9258                   const guint8 *uri_aux = NULL;
9259
9260                   /* found the data atom that might contain the rtsp uri */
9261                   GST_DEBUG_OBJECT (qtdemux, "Found data atom inside "
9262                       "hndl atom, interpreting it as an URI");
9263                   if (gst_byte_reader_peek_data (&dref, atom_size - 8,
9264                           &uri_aux)) {
9265                     if (g_strstr_len ((gchar *) uri_aux, 7, "rtsp://") != NULL)
9266                       uri = g_strndup ((gchar *) uri_aux, atom_size - 8);
9267                     else
9268                       GST_WARNING_OBJECT (qtdemux, "Data atom in hndl atom "
9269                           "didn't contain a rtsp address");
9270                   } else {
9271                     GST_WARNING_OBJECT (qtdemux, "Failed to get the data "
9272                         "atom contents");
9273                   }
9274                   break;
9275                 }
9276                 /* skipping to the next entry */
9277                 if (!gst_byte_reader_skip (&dref, atom_size - 8))
9278                   break;
9279               } else {
9280                 GST_WARNING_OBJECT (qtdemux, "Failed to parse hndl child "
9281                     "atom header");
9282                 break;
9283               }
9284             }
9285             break;
9286           }
9287           /* skip to the next entry */
9288           if (!gst_byte_reader_skip (&dref, size - 8))
9289             break;
9290         } else {
9291           GST_WARNING_OBJECT (qtdemux, "Error parsing dref atom");
9292         }
9293       }
9294       GST_DEBUG_OBJECT (qtdemux, "Finished parsing dref atom");
9295     }
9296   }
9297   return uri;
9298 }
9299
9300 #define AMR_NB_ALL_MODES        0x81ff
9301 #define AMR_WB_ALL_MODES        0x83ff
9302 static guint
9303 qtdemux_parse_amr_bitrate (GstBuffer * buf, gboolean wb)
9304 {
9305   /* The 'damr' atom is of the form:
9306    *
9307    * | vendor | decoder_ver | mode_set | mode_change_period | frames/sample |
9308    *    32 b       8 b          16 b           8 b                 8 b
9309    *
9310    * The highest set bit of the first 7 (AMR-NB) or 8 (AMR-WB) bits of mode_set
9311    * represents the highest mode used in the stream (and thus the maximum
9312    * bitrate), with a couple of special cases as seen below.
9313    */
9314
9315   /* Map of frame type ID -> bitrate */
9316   static const guint nb_bitrates[] = {
9317     4750, 5150, 5900, 6700, 7400, 7950, 10200, 12200
9318   };
9319   static const guint wb_bitrates[] = {
9320     6600, 8850, 12650, 14250, 15850, 18250, 19850, 23050, 23850
9321   };
9322   GstMapInfo map;
9323   gsize max_mode;
9324   guint16 mode_set;
9325
9326   gst_buffer_map (buf, &map, GST_MAP_READ);
9327
9328   if (map.size != 0x11) {
9329     GST_DEBUG ("Atom should have size 0x11, not %" G_GSIZE_FORMAT, map.size);
9330     goto bad_data;
9331   }
9332
9333   if (QT_FOURCC (map.data + 4) != FOURCC_damr) {
9334     GST_DEBUG ("Unknown atom in %" GST_FOURCC_FORMAT,
9335         GST_FOURCC_ARGS (QT_UINT32 (map.data + 4)));
9336     goto bad_data;
9337   }
9338
9339   mode_set = QT_UINT16 (map.data + 13);
9340
9341   if (mode_set == (wb ? AMR_WB_ALL_MODES : AMR_NB_ALL_MODES))
9342     max_mode = 7 + (wb ? 1 : 0);
9343   else
9344     /* AMR-NB modes fo from 0-7, and AMR-WB modes go from 0-8 */
9345     max_mode = g_bit_nth_msf ((gulong) mode_set & (wb ? 0x1ff : 0xff), -1);
9346
9347   if (max_mode == -1) {
9348     GST_DEBUG ("No mode indication was found (mode set) = %x",
9349         (guint) mode_set);
9350     goto bad_data;
9351   }
9352
9353   gst_buffer_unmap (buf, &map);
9354   return wb ? wb_bitrates[max_mode] : nb_bitrates[max_mode];
9355
9356 bad_data:
9357   gst_buffer_unmap (buf, &map);
9358   return 0;
9359 }
9360
9361 static gboolean
9362 qtdemux_parse_transformation_matrix (GstQTDemux * qtdemux,
9363     GstByteReader * reader, guint32 * matrix, const gchar * atom)
9364 {
9365   /*
9366    * 9 values of 32 bits (fixed point 16.16, except 2 5 and 8 that are 2.30)
9367    * [0 1 2]
9368    * [3 4 5]
9369    * [6 7 8]
9370    */
9371
9372   if (gst_byte_reader_get_remaining (reader) < 36)
9373     return FALSE;
9374
9375   matrix[0] = gst_byte_reader_get_uint32_be_unchecked (reader);
9376   matrix[1] = gst_byte_reader_get_uint32_be_unchecked (reader);
9377   matrix[2] = gst_byte_reader_get_uint32_be_unchecked (reader);
9378   matrix[3] = gst_byte_reader_get_uint32_be_unchecked (reader);
9379   matrix[4] = gst_byte_reader_get_uint32_be_unchecked (reader);
9380   matrix[5] = gst_byte_reader_get_uint32_be_unchecked (reader);
9381   matrix[6] = gst_byte_reader_get_uint32_be_unchecked (reader);
9382   matrix[7] = gst_byte_reader_get_uint32_be_unchecked (reader);
9383   matrix[8] = gst_byte_reader_get_uint32_be_unchecked (reader);
9384
9385   GST_DEBUG_OBJECT (qtdemux, "Transformation matrix from atom %s", atom);
9386   GST_DEBUG_OBJECT (qtdemux, "%u.%u %u.%u %u.%u", matrix[0] >> 16,
9387       matrix[0] & 0xFFFF, matrix[1] >> 16, matrix[1] & 0xFF, matrix[2] >> 16,
9388       matrix[2] & 0xFF);
9389   GST_DEBUG_OBJECT (qtdemux, "%u.%u %u.%u %u.%u", matrix[3] >> 16,
9390       matrix[3] & 0xFFFF, matrix[4] >> 16, matrix[4] & 0xFF, matrix[5] >> 16,
9391       matrix[5] & 0xFF);
9392   GST_DEBUG_OBJECT (qtdemux, "%u.%u %u.%u %u.%u", matrix[6] >> 16,
9393       matrix[6] & 0xFFFF, matrix[7] >> 16, matrix[7] & 0xFF, matrix[8] >> 16,
9394       matrix[8] & 0xFF);
9395
9396   return TRUE;
9397 }
9398
9399 static void
9400 qtdemux_inspect_transformation_matrix (GstQTDemux * qtdemux,
9401     QtDemuxStream * stream, guint32 * matrix, GstTagList ** taglist)
9402 {
9403
9404 /* [a b c]
9405  * [d e f]
9406  * [g h i]
9407  *
9408  * This macro will only compare value abdegh, it expects cfi to have already
9409  * been checked
9410  */
9411 #define QTCHECK_MATRIX(m,a,b,d,e) ((m)[0] == (a << 16) && (m)[1] == (b << 16) && \
9412                                    (m)[3] == (d << 16) && (m)[4] == (e << 16))
9413
9414   /* only handle the cases where the last column has standard values */
9415   if (matrix[2] == 0 && matrix[5] == 0 && matrix[8] == 1 << 30) {
9416     const gchar *rotation_tag = NULL;
9417
9418     /* no rotation needed */
9419     if (QTCHECK_MATRIX (matrix, 1, 0, 0, 1)) {
9420       /* NOP */
9421     } else if (QTCHECK_MATRIX (matrix, 0, 1, G_MAXUINT16, 0)) {
9422       rotation_tag = "rotate-90";
9423     } else if (QTCHECK_MATRIX (matrix, G_MAXUINT16, 0, 0, G_MAXUINT16)) {
9424       rotation_tag = "rotate-180";
9425     } else if (QTCHECK_MATRIX (matrix, 0, G_MAXUINT16, 1, 0)) {
9426       rotation_tag = "rotate-270";
9427     } else {
9428       GST_FIXME_OBJECT (qtdemux, "Unhandled transformation matrix values");
9429     }
9430
9431     GST_DEBUG_OBJECT (qtdemux, "Transformation matrix rotation %s",
9432         rotation_tag);
9433     if (rotation_tag != NULL) {
9434       if (*taglist == NULL)
9435         *taglist = gst_tag_list_new_empty ();
9436       gst_tag_list_add (*taglist, GST_TAG_MERGE_REPLACE,
9437           GST_TAG_IMAGE_ORIENTATION, rotation_tag, NULL);
9438     }
9439   } else {
9440     GST_FIXME_OBJECT (qtdemux, "Unhandled transformation matrix values");
9441   }
9442 }
9443
9444 /* Parses the boxes defined in ISO/IEC 14496-12 that enable support for
9445  * protected streams (sinf, frma, schm and schi); if the protection scheme is
9446  * Common Encryption (cenc), the function will also parse the tenc box (defined
9447  * in ISO/IEC 23001-7). @container points to the node that contains these boxes
9448  * (typically an enc[v|a|t|s] sample entry); the function will set
9449  * @original_fmt to the fourcc of the original unencrypted stream format.
9450  * Returns TRUE if successful; FALSE otherwise. */
9451 static gboolean
9452 qtdemux_parse_protection_scheme_info (GstQTDemux * qtdemux,
9453     QtDemuxStream * stream, GNode * container, guint32 * original_fmt)
9454 {
9455   GNode *sinf;
9456   GNode *frma;
9457   GNode *schm;
9458   GNode *schi;
9459
9460   g_return_val_if_fail (qtdemux != NULL, FALSE);
9461   g_return_val_if_fail (stream != NULL, FALSE);
9462   g_return_val_if_fail (container != NULL, FALSE);
9463   g_return_val_if_fail (original_fmt != NULL, FALSE);
9464
9465   sinf = qtdemux_tree_get_child_by_type (container, FOURCC_sinf);
9466   if (G_UNLIKELY (!sinf)) {
9467     if (stream->protection_scheme_type == FOURCC_cenc) {
9468       GST_ERROR_OBJECT (qtdemux, "sinf box does not contain schi box, which is "
9469           "mandatory for Common Encryption");
9470       return FALSE;
9471     }
9472     return TRUE;
9473   }
9474
9475   frma = qtdemux_tree_get_child_by_type (sinf, FOURCC_frma);
9476   if (G_UNLIKELY (!frma)) {
9477     GST_ERROR_OBJECT (qtdemux, "sinf box does not contain mandatory frma box");
9478     return FALSE;
9479   }
9480
9481   *original_fmt = QT_FOURCC ((const guint8 *) frma->data + 8);
9482   GST_DEBUG_OBJECT (qtdemux, "original stream format: '%" GST_FOURCC_FORMAT "'",
9483       GST_FOURCC_ARGS (*original_fmt));
9484
9485   schm = qtdemux_tree_get_child_by_type (sinf, FOURCC_schm);
9486   if (!schm) {
9487     GST_DEBUG_OBJECT (qtdemux, "sinf box does not contain schm box");
9488     return FALSE;
9489   }
9490   stream->protection_scheme_type = QT_FOURCC ((const guint8 *) schm->data + 12);
9491   stream->protection_scheme_version =
9492       QT_UINT32 ((const guint8 *) schm->data + 16);
9493
9494   GST_DEBUG_OBJECT (qtdemux,
9495       "protection_scheme_type: %" GST_FOURCC_FORMAT ", "
9496       "protection_scheme_version: %#010x",
9497       GST_FOURCC_ARGS (stream->protection_scheme_type),
9498       stream->protection_scheme_version);
9499
9500   schi = qtdemux_tree_get_child_by_type (sinf, FOURCC_schi);
9501   if (!schi) {
9502     GST_DEBUG_OBJECT (qtdemux, "sinf box does not contain schi box");
9503     return FALSE;
9504   }
9505   if (stream->protection_scheme_type == FOURCC_cenc) {
9506     QtDemuxCencSampleSetInfo *info;
9507     GNode *tenc;
9508     const guint8 *tenc_data;
9509     guint32 isEncrypted;
9510     guint8 iv_size;
9511     const guint8 *default_kid;
9512     GstBuffer *kid_buf;
9513
9514     if (G_UNLIKELY (!stream->protection_scheme_info))
9515       stream->protection_scheme_info =
9516           g_malloc0 (sizeof (QtDemuxCencSampleSetInfo));
9517
9518     info = (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
9519
9520     tenc = qtdemux_tree_get_child_by_type (schi, FOURCC_tenc);
9521     if (!tenc) {
9522       GST_ERROR_OBJECT (qtdemux, "schi box does not contain tenc box, "
9523           "which is mandatory for Common Encryption");
9524       return FALSE;
9525     }
9526     tenc_data = (const guint8 *) tenc->data + 12;
9527     isEncrypted = QT_UINT24 (tenc_data);
9528     iv_size = QT_UINT8 (tenc_data + 3);
9529     default_kid = (tenc_data + 4);
9530     kid_buf = gst_buffer_new_allocate (NULL, 16, NULL);
9531     gst_buffer_fill (kid_buf, 0, default_kid, 16);
9532     if (info->default_properties)
9533       gst_structure_free (info->default_properties);
9534     info->default_properties =
9535         gst_structure_new ("application/x-cenc",
9536         "iv_size", G_TYPE_UINT, iv_size,
9537         "encrypted", G_TYPE_BOOLEAN, (isEncrypted == 1),
9538         "kid", GST_TYPE_BUFFER, kid_buf, NULL);
9539     GST_DEBUG_OBJECT (qtdemux, "default sample properties: "
9540         "is_encrypted=%u, iv_size=%u", isEncrypted, iv_size);
9541     gst_buffer_unref (kid_buf);
9542   }
9543   return TRUE;
9544 }
9545
9546 /* parse the traks.
9547  * With each track we associate a new QtDemuxStream that contains all the info
9548  * about the trak.
9549  * traks that do not decode to something (like strm traks) will not have a pad.
9550  */
9551 static gboolean
9552 qtdemux_parse_trak (GstQTDemux * qtdemux, GNode * trak)
9553 {
9554   GstByteReader tkhd;
9555   int offset;
9556   GNode *mdia;
9557   GNode *mdhd;
9558   GNode *hdlr;
9559   GNode *minf;
9560   GNode *stbl;
9561   GNode *stsd;
9562   GNode *mp4a;
9563   GNode *mp4v;
9564   GNode *wave;
9565   GNode *esds;
9566   GNode *pasp;
9567   GNode *colr;
9568   GNode *tref;
9569   GNode *udta;
9570   GNode *svmi;
9571   GNode *fiel;
9572
9573   QtDemuxStream *stream = NULL;
9574   gboolean new_stream = FALSE;
9575   gchar *codec = NULL;
9576   const guint8 *stsd_data;
9577   const guint8 *stsd_entry_data;
9578   guint remaining_stsd_len;
9579   guint stsd_entry_count;
9580   guint stsd_index;
9581   guint16 lang_code;            /* quicktime lang code or packed iso code */
9582   guint32 version;
9583   guint32 tkhd_flags = 0;
9584   guint8 tkhd_version = 0;
9585   guint32 w = 0, h = 0;
9586   guint32 fourcc;
9587   guint value_size, stsd_len, len;
9588   guint32 track_id;
9589   guint32 dummy;
9590
9591   GST_DEBUG_OBJECT (qtdemux, "parse_trak");
9592
9593   if (!qtdemux_tree_get_child_by_type_full (trak, FOURCC_tkhd, &tkhd)
9594       || !gst_byte_reader_get_uint8 (&tkhd, &tkhd_version)
9595       || !gst_byte_reader_get_uint24_be (&tkhd, &tkhd_flags))
9596     goto corrupt_file;
9597
9598   /* pick between 64 or 32 bits */
9599   value_size = tkhd_version == 1 ? 8 : 4;
9600   if (!gst_byte_reader_skip (&tkhd, value_size * 2) ||
9601       !gst_byte_reader_get_uint32_be (&tkhd, &track_id))
9602     goto corrupt_file;
9603
9604   if (!qtdemux->got_moov) {
9605     if (qtdemux_find_stream (qtdemux, track_id))
9606       goto existing_stream;
9607     stream = _create_stream ();
9608     stream->track_id = track_id;
9609     new_stream = TRUE;
9610   } else {
9611     stream = qtdemux_find_stream (qtdemux, track_id);
9612     if (!stream) {
9613       GST_WARNING_OBJECT (qtdemux, "Stream not found, going to ignore it");
9614       goto skip_track;
9615     }
9616
9617     stream->stream_tags = gst_tag_list_make_writable (stream->stream_tags);
9618
9619     /* flush samples data from this track from previous moov */
9620     gst_qtdemux_stream_flush_segments_data (qtdemux, stream);
9621     gst_qtdemux_stream_flush_samples_data (qtdemux, stream);
9622   }
9623   /* need defaults for fragments */
9624   qtdemux_parse_trex (qtdemux, stream, &dummy, &dummy, &dummy);
9625
9626   if ((tkhd_flags & 1) == 0)
9627     stream->disabled = TRUE;
9628
9629   GST_LOG_OBJECT (qtdemux, "track[tkhd] version/flags/id: 0x%02x/%06x/%u",
9630       tkhd_version, tkhd_flags, stream->track_id);
9631
9632   if (!(mdia = qtdemux_tree_get_child_by_type (trak, FOURCC_mdia)))
9633     goto corrupt_file;
9634
9635   if (!(mdhd = qtdemux_tree_get_child_by_type (mdia, FOURCC_mdhd))) {
9636     /* be nice for some crooked mjp2 files that use mhdr for mdhd */
9637     if (qtdemux->major_brand != FOURCC_mjp2 ||
9638         !(mdhd = qtdemux_tree_get_child_by_type (mdia, FOURCC_mhdr)))
9639       goto corrupt_file;
9640   }
9641
9642   len = QT_UINT32 ((guint8 *) mdhd->data);
9643   version = QT_UINT32 ((guint8 *) mdhd->data + 8);
9644   GST_LOG_OBJECT (qtdemux, "track version/flags: %08x", version);
9645   if (version == 0x01000000) {
9646     if (len < 38)
9647       goto corrupt_file;
9648     stream->timescale = QT_UINT32 ((guint8 *) mdhd->data + 28);
9649     stream->duration = QT_UINT64 ((guint8 *) mdhd->data + 32);
9650     lang_code = QT_UINT16 ((guint8 *) mdhd->data + 36);
9651   } else {
9652     if (len < 30)
9653       goto corrupt_file;
9654     stream->timescale = QT_UINT32 ((guint8 *) mdhd->data + 20);
9655     stream->duration = QT_UINT32 ((guint8 *) mdhd->data + 24);
9656     lang_code = QT_UINT16 ((guint8 *) mdhd->data + 28);
9657   }
9658
9659   if (lang_code < 0x400) {
9660     qtdemux_lang_map_qt_code_to_iso (stream->lang_id, lang_code);
9661   } else if (lang_code == 0x7fff) {
9662     stream->lang_id[0] = 0;     /* unspecified */
9663   } else {
9664     stream->lang_id[0] = 0x60 + ((lang_code >> 10) & 0x1F);
9665     stream->lang_id[1] = 0x60 + ((lang_code >> 5) & 0x1F);
9666     stream->lang_id[2] = 0x60 + (lang_code & 0x1F);
9667     stream->lang_id[3] = 0;
9668   }
9669
9670   GST_LOG_OBJECT (qtdemux, "track timescale: %" G_GUINT32_FORMAT,
9671       stream->timescale);
9672   GST_LOG_OBJECT (qtdemux, "track duration: %" G_GUINT64_FORMAT,
9673       stream->duration);
9674   GST_LOG_OBJECT (qtdemux, "track language code/id: 0x%04x/%s",
9675       lang_code, stream->lang_id);
9676
9677   if (G_UNLIKELY (stream->timescale == 0 || qtdemux->timescale == 0))
9678     goto corrupt_file;
9679
9680   if ((tref = qtdemux_tree_get_child_by_type (trak, FOURCC_tref))) {
9681     /* chapters track reference */
9682     GNode *chap = qtdemux_tree_get_child_by_type (tref, FOURCC_chap);
9683     if (chap) {
9684       gsize length = GST_READ_UINT32_BE (chap->data);
9685       if (qtdemux->chapters_track_id)
9686         GST_FIXME_OBJECT (qtdemux, "Multiple CHAP tracks");
9687
9688       if (length >= 12) {
9689         qtdemux->chapters_track_id =
9690             GST_READ_UINT32_BE ((gint8 *) chap->data + 8);
9691       }
9692     }
9693   }
9694
9695   /* fragmented files may have bogus duration in moov */
9696   if (!qtdemux->fragmented &&
9697       qtdemux->duration != G_MAXINT64 && stream->duration != G_MAXINT32) {
9698     guint64 tdur1, tdur2;
9699
9700     /* don't overflow */
9701     tdur1 = stream->timescale * (guint64) qtdemux->duration;
9702     tdur2 = qtdemux->timescale * (guint64) stream->duration;
9703
9704     /* HACK:
9705      * some of those trailers, nowadays, have prologue images that are
9706      * themselves video tracks as well. I haven't really found a way to
9707      * identify those yet, except for just looking at their duration. */
9708     if (tdur1 != 0 && (tdur2 * 10 / tdur1) < 2) {
9709       GST_WARNING_OBJECT (qtdemux,
9710           "Track shorter than 20%% (%" G_GUINT64_FORMAT "/%" G_GUINT32_FORMAT
9711           " vs. %" G_GUINT64_FORMAT "/%" G_GUINT32_FORMAT ") of the stream "
9712           "found, assuming preview image or something; skipping track",
9713           stream->duration, stream->timescale, qtdemux->duration,
9714           qtdemux->timescale);
9715       if (new_stream)
9716         gst_qtdemux_stream_free (qtdemux, stream);
9717       return TRUE;
9718     }
9719   }
9720
9721   if (!(hdlr = qtdemux_tree_get_child_by_type (mdia, FOURCC_hdlr)))
9722     goto corrupt_file;
9723
9724   GST_LOG_OBJECT (qtdemux, "track type: %" GST_FOURCC_FORMAT,
9725       GST_FOURCC_ARGS (QT_FOURCC ((guint8 *) hdlr->data + 12)));
9726
9727   len = QT_UINT32 ((guint8 *) hdlr->data);
9728   if (len >= 20)
9729     stream->subtype = QT_FOURCC ((guint8 *) hdlr->data + 16);
9730   GST_LOG_OBJECT (qtdemux, "track subtype: %" GST_FOURCC_FORMAT,
9731       GST_FOURCC_ARGS (stream->subtype));
9732
9733   if (!(minf = qtdemux_tree_get_child_by_type (mdia, FOURCC_minf)))
9734     goto corrupt_file;
9735
9736   if (!(stbl = qtdemux_tree_get_child_by_type (minf, FOURCC_stbl)))
9737     goto corrupt_file;
9738
9739   /*parse svmi header if existing */
9740   svmi = qtdemux_tree_get_child_by_type (stbl, FOURCC_svmi);
9741   if (svmi) {
9742     len = QT_UINT32 ((guint8 *) svmi->data);
9743     version = QT_UINT32 ((guint8 *) svmi->data + 8);
9744     if (!version) {
9745       GstVideoMultiviewMode mode = GST_VIDEO_MULTIVIEW_MODE_NONE;
9746       GstVideoMultiviewFlags flags = GST_VIDEO_MULTIVIEW_FLAGS_NONE;
9747       guint8 frame_type, frame_layout;
9748
9749       /* MPEG-A stereo video */
9750       if (qtdemux->major_brand == FOURCC_ss02)
9751         flags |= GST_VIDEO_MULTIVIEW_FLAGS_MIXED_MONO;
9752
9753       frame_type = QT_UINT8 ((guint8 *) svmi->data + 12);
9754       frame_layout = QT_UINT8 ((guint8 *) svmi->data + 13) & 0x01;
9755       switch (frame_type) {
9756         case 0:
9757           mode = GST_VIDEO_MULTIVIEW_MODE_SIDE_BY_SIDE;
9758           break;
9759         case 1:
9760           mode = GST_VIDEO_MULTIVIEW_MODE_ROW_INTERLEAVED;
9761           break;
9762         case 2:
9763           mode = GST_VIDEO_MULTIVIEW_MODE_FRAME_BY_FRAME;
9764           break;
9765         case 3:
9766           /* mode 3 is primary/secondary view sequence, ie
9767            * left/right views in separate tracks. See section 7.2
9768            * of ISO/IEC 23000-11:2009 */
9769           GST_FIXME_OBJECT (qtdemux,
9770               "Implement stereo video in separate streams");
9771       }
9772
9773       if ((frame_layout & 0x1) == 0)
9774         flags |= GST_VIDEO_MULTIVIEW_FLAGS_RIGHT_VIEW_FIRST;
9775
9776       GST_LOG_OBJECT (qtdemux,
9777           "StereoVideo: composition type: %u, is_left_first: %u",
9778           frame_type, frame_layout);
9779       stream->multiview_mode = mode;
9780       stream->multiview_flags = flags;
9781     }
9782   }
9783
9784   /* parse rest of tkhd */
9785   if (stream->subtype == FOURCC_vide) {
9786     guint32 matrix[9];
9787
9788     /* version 1 uses some 64-bit ints */
9789     if (!gst_byte_reader_skip (&tkhd, 20 + value_size))
9790       goto corrupt_file;
9791
9792     if (!qtdemux_parse_transformation_matrix (qtdemux, &tkhd, matrix, "tkhd"))
9793       goto corrupt_file;
9794
9795     if (!gst_byte_reader_get_uint32_be (&tkhd, &w)
9796         || !gst_byte_reader_get_uint32_be (&tkhd, &h))
9797       goto corrupt_file;
9798
9799     qtdemux_inspect_transformation_matrix (qtdemux, stream, matrix,
9800         &stream->stream_tags);
9801   }
9802
9803   /* parse stsd */
9804   if (!(stsd = qtdemux_tree_get_child_by_type (stbl, FOURCC_stsd)))
9805     goto corrupt_file;
9806   stsd_data = (const guint8 *) stsd->data;
9807
9808   /* stsd should at least have one entry */
9809   stsd_len = QT_UINT32 (stsd_data);
9810   if (stsd_len < 24) {
9811     /* .. but skip stream with empty stsd produced by some Vivotek cameras */
9812     if (stream->subtype == FOURCC_vivo) {
9813       if (new_stream)
9814         gst_qtdemux_stream_free (qtdemux, stream);
9815       return TRUE;
9816     } else {
9817       goto corrupt_file;
9818     }
9819   }
9820
9821   stream->stsd_entries_length = stsd_entry_count = QT_UINT32 (stsd_data + 12);
9822   stream->stsd_entries = g_new0 (QtDemuxStreamStsdEntry, stsd_entry_count);
9823   GST_LOG_OBJECT (qtdemux, "stsd len:           %d", stsd_len);
9824   GST_LOG_OBJECT (qtdemux, "stsd entry count:   %u", stsd_entry_count);
9825
9826   stsd_entry_data = stsd_data + 16;
9827   remaining_stsd_len = stsd_len - 16;
9828   for (stsd_index = 0; stsd_index < stsd_entry_count; stsd_index++) {
9829     QtDemuxStreamStsdEntry *entry = &stream->stsd_entries[stsd_index];
9830
9831     /* and that entry should fit within stsd */
9832     len = QT_UINT32 (stsd_entry_data);
9833     if (len > remaining_stsd_len)
9834       goto corrupt_file;
9835
9836     entry->fourcc = fourcc = QT_FOURCC (stsd_entry_data + 4);
9837     GST_LOG_OBJECT (qtdemux, "stsd type:          %" GST_FOURCC_FORMAT,
9838         GST_FOURCC_ARGS (entry->fourcc));
9839     GST_LOG_OBJECT (qtdemux, "stsd type len:      %d", len);
9840
9841     if ((fourcc == FOURCC_drms) || (fourcc == FOURCC_drmi))
9842       goto error_encrypted;
9843
9844     if (fourcc == FOURCC_encv || fourcc == FOURCC_enca) {
9845       /* FIXME this looks wrong, there might be multiple children
9846        * with the same type */
9847       GNode *enc = qtdemux_tree_get_child_by_type (stsd, fourcc);
9848       stream->protected = TRUE;
9849       if (!qtdemux_parse_protection_scheme_info (qtdemux, stream, enc, &fourcc))
9850         GST_ERROR_OBJECT (qtdemux, "Failed to parse protection scheme info");
9851     }
9852
9853     if (stream->subtype == FOURCC_vide) {
9854       gboolean gray;
9855       gint depth, palette_size, palette_count;
9856       guint32 *palette_data = NULL;
9857
9858       entry->sampled = TRUE;
9859
9860       stream->display_width = w >> 16;
9861       stream->display_height = h >> 16;
9862
9863       offset = 16;
9864       if (len < 86)             /* TODO verify */
9865         goto corrupt_file;
9866
9867       entry->width = QT_UINT16 (stsd_entry_data + offset + 16);
9868       entry->height = QT_UINT16 (stsd_entry_data + offset + 18);
9869       entry->fps_n = 0;         /* this is filled in later */
9870       entry->fps_d = 0;         /* this is filled in later */
9871       entry->bits_per_sample = QT_UINT16 (stsd_entry_data + offset + 66);
9872       entry->color_table_id = QT_UINT16 (stsd_entry_data + offset + 68);
9873
9874       /* if color_table_id is 0, ctab atom must follow; however some files
9875        * produced by TMPEGEnc have color_table_id = 0 and no ctab atom, so
9876        * if color table is not present we'll correct the value */
9877       if (entry->color_table_id == 0 &&
9878           (len < 90
9879               || QT_FOURCC (stsd_entry_data + offset + 70) != FOURCC_ctab)) {
9880         entry->color_table_id = -1;
9881       }
9882
9883       GST_LOG_OBJECT (qtdemux, "width %d, height %d, bps %d, color table id %d",
9884           entry->width, entry->height, entry->bits_per_sample,
9885           entry->color_table_id);
9886
9887       depth = entry->bits_per_sample;
9888
9889       /* more than 32 bits means grayscale */
9890       gray = (depth > 32);
9891       /* low 32 bits specify the depth  */
9892       depth &= 0x1F;
9893
9894       /* different number of palette entries is determined by depth. */
9895       palette_count = 0;
9896       if ((depth == 1) || (depth == 2) || (depth == 4) || (depth == 8))
9897         palette_count = (1 << depth);
9898       palette_size = palette_count * 4;
9899
9900       if (entry->color_table_id) {
9901         switch (palette_count) {
9902           case 0:
9903             break;
9904           case 2:
9905             palette_data = g_memdup (ff_qt_default_palette_2, palette_size);
9906             break;
9907           case 4:
9908             palette_data = g_memdup (ff_qt_default_palette_4, palette_size);
9909             break;
9910           case 16:
9911             if (gray)
9912               palette_data =
9913                   g_memdup (ff_qt_grayscale_palette_16, palette_size);
9914             else
9915               palette_data = g_memdup (ff_qt_default_palette_16, palette_size);
9916             break;
9917           case 256:
9918             if (gray)
9919               palette_data =
9920                   g_memdup (ff_qt_grayscale_palette_256, palette_size);
9921             else
9922               palette_data = g_memdup (ff_qt_default_palette_256, palette_size);
9923             break;
9924           default:
9925             GST_ELEMENT_WARNING (qtdemux, STREAM, DEMUX,
9926                 (_("The video in this file might not play correctly.")),
9927                 ("unsupported palette depth %d", depth));
9928             break;
9929         }
9930       } else {
9931         gint i, j, start, end;
9932
9933         if (len < 94)
9934           goto corrupt_file;
9935
9936         /* read table */
9937         start = QT_UINT32 (stsd_entry_data + offset + 70);
9938         palette_count = QT_UINT16 (stsd_entry_data + offset + 74);
9939         end = QT_UINT16 (stsd_entry_data + offset + 76);
9940
9941         GST_LOG_OBJECT (qtdemux, "start %d, end %d, palette_count %d",
9942             start, end, palette_count);
9943
9944         if (end > 255)
9945           end = 255;
9946         if (start > end)
9947           start = end;
9948
9949         if (len < 94 + (end - start) * 8)
9950           goto corrupt_file;
9951
9952         /* palette is always the same size */
9953         palette_data = g_malloc0 (256 * 4);
9954         palette_size = 256 * 4;
9955
9956         for (j = 0, i = start; i <= end; j++, i++) {
9957           guint32 a, r, g, b;
9958
9959           a = QT_UINT16 (stsd_entry_data + offset + 78 + (j * 8));
9960           r = QT_UINT16 (stsd_entry_data + offset + 80 + (j * 8));
9961           g = QT_UINT16 (stsd_entry_data + offset + 82 + (j * 8));
9962           b = QT_UINT16 (stsd_entry_data + offset + 84 + (j * 8));
9963
9964           palette_data[i] = ((a & 0xff00) << 16) | ((r & 0xff00) << 8) |
9965               (g & 0xff00) | (b >> 8);
9966         }
9967       }
9968
9969       if (entry->caps)
9970         gst_caps_unref (entry->caps);
9971
9972       entry->caps =
9973           qtdemux_video_caps (qtdemux, stream, entry, fourcc, stsd_entry_data,
9974           &codec);
9975       if (G_UNLIKELY (!entry->caps)) {
9976         g_free (palette_data);
9977         goto unknown_stream;
9978       }
9979
9980       if (codec) {
9981         gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
9982             GST_TAG_VIDEO_CODEC, codec, NULL);
9983         g_free (codec);
9984         codec = NULL;
9985       }
9986
9987       if (palette_data) {
9988         GstStructure *s;
9989
9990         if (entry->rgb8_palette)
9991           gst_memory_unref (entry->rgb8_palette);
9992         entry->rgb8_palette = gst_memory_new_wrapped (GST_MEMORY_FLAG_READONLY,
9993             palette_data, palette_size, 0, palette_size, palette_data, g_free);
9994
9995         s = gst_caps_get_structure (entry->caps, 0);
9996
9997         /* non-raw video has a palette_data property. raw video has the palette as
9998          * an extra plane that we append to the output buffers before we push
9999          * them*/
10000         if (!gst_structure_has_name (s, "video/x-raw")) {
10001           GstBuffer *palette;
10002
10003           palette = gst_buffer_new ();
10004           gst_buffer_append_memory (palette, entry->rgb8_palette);
10005           entry->rgb8_palette = NULL;
10006
10007           gst_caps_set_simple (entry->caps, "palette_data",
10008               GST_TYPE_BUFFER, palette, NULL);
10009           gst_buffer_unref (palette);
10010         }
10011       } else if (palette_count != 0) {
10012         GST_ELEMENT_WARNING (qtdemux, STREAM, NOT_IMPLEMENTED,
10013             (NULL), ("Unsupported palette depth %d", depth));
10014       }
10015
10016       GST_LOG_OBJECT (qtdemux, "frame count:   %u",
10017           QT_UINT16 (stsd_entry_data + offset + 32));
10018
10019       esds = NULL;
10020       pasp = NULL;
10021       colr = NULL;
10022       fiel = NULL;
10023       /* pick 'the' stsd child */
10024       mp4v = qtdemux_tree_get_child_by_index (stsd, stsd_index);
10025       if (!stream->protected) {
10026         if (QTDEMUX_TREE_NODE_FOURCC (mp4v) != fourcc) {
10027           mp4v = NULL;
10028         }
10029       } else {
10030         if (QTDEMUX_TREE_NODE_FOURCC (mp4v) != FOURCC_encv) {
10031           mp4v = NULL;
10032         }
10033       }
10034
10035       if (mp4v) {
10036         esds = qtdemux_tree_get_child_by_type (mp4v, FOURCC_esds);
10037         pasp = qtdemux_tree_get_child_by_type (mp4v, FOURCC_pasp);
10038         colr = qtdemux_tree_get_child_by_type (mp4v, FOURCC_colr);
10039         fiel = qtdemux_tree_get_child_by_type (mp4v, FOURCC_fiel);
10040       }
10041
10042       if (pasp) {
10043         const guint8 *pasp_data = (const guint8 *) pasp->data;
10044         gint len = QT_UINT32 (pasp_data);
10045
10046         if (len == 16) {
10047           CUR_STREAM (stream)->par_w = QT_UINT32 (pasp_data + 8);
10048           CUR_STREAM (stream)->par_h = QT_UINT32 (pasp_data + 12);
10049         } else {
10050           CUR_STREAM (stream)->par_w = 0;
10051           CUR_STREAM (stream)->par_h = 0;
10052         }
10053       } else {
10054         CUR_STREAM (stream)->par_w = 0;
10055         CUR_STREAM (stream)->par_h = 0;
10056       }
10057
10058       if (fiel) {
10059         const guint8 *fiel_data = (const guint8 *) fiel->data;
10060         gint len = QT_UINT32 (fiel_data);
10061
10062         if (len == 10) {
10063           CUR_STREAM (stream)->interlace_mode = GST_READ_UINT8 (fiel_data + 8);
10064           CUR_STREAM (stream)->field_order = GST_READ_UINT8 (fiel_data + 9);
10065         }
10066       }
10067
10068       if (colr) {
10069         const guint8 *colr_data = (const guint8 *) colr->data;
10070         gint len = QT_UINT32 (colr_data);
10071
10072         if (len == 19 || len == 18) {
10073           guint32 color_type = GST_READ_UINT32_LE (colr_data + 8);
10074
10075           if (color_type == FOURCC_nclx || color_type == FOURCC_nclc) {
10076             guint16 primaries = GST_READ_UINT16_BE (colr_data + 12);
10077             guint16 transfer_function = GST_READ_UINT16_BE (colr_data + 14);
10078             guint16 matrix = GST_READ_UINT16_BE (colr_data + 16);
10079             gboolean full_range = len == 19 ? colr_data[17] >> 7 : FALSE;
10080
10081             switch (primaries) {
10082               case 1:
10083                 CUR_STREAM (stream)->colorimetry.primaries =
10084                     GST_VIDEO_COLOR_PRIMARIES_BT709;
10085                 break;
10086               case 5:
10087                 CUR_STREAM (stream)->colorimetry.primaries =
10088                     GST_VIDEO_COLOR_PRIMARIES_BT470BG;
10089                 break;
10090               case 6:
10091                 CUR_STREAM (stream)->colorimetry.primaries =
10092                     GST_VIDEO_COLOR_PRIMARIES_SMPTE170M;
10093                 break;
10094               case 9:
10095                 CUR_STREAM (stream)->colorimetry.primaries =
10096                     GST_VIDEO_COLOR_PRIMARIES_BT2020;
10097                 break;
10098               default:
10099                 break;
10100             }
10101
10102             switch (transfer_function) {
10103               case 1:
10104                 CUR_STREAM (stream)->colorimetry.transfer =
10105                     GST_VIDEO_TRANSFER_BT709;
10106                 break;
10107               case 7:
10108                 CUR_STREAM (stream)->colorimetry.transfer =
10109                     GST_VIDEO_TRANSFER_SMPTE240M;
10110                 break;
10111               default:
10112                 break;
10113             }
10114
10115             switch (matrix) {
10116               case 1:
10117                 CUR_STREAM (stream)->colorimetry.matrix =
10118                     GST_VIDEO_COLOR_MATRIX_BT709;
10119                 break;
10120               case 6:
10121                 CUR_STREAM (stream)->colorimetry.matrix =
10122                     GST_VIDEO_COLOR_MATRIX_BT601;
10123                 break;
10124               case 7:
10125                 CUR_STREAM (stream)->colorimetry.matrix =
10126                     GST_VIDEO_COLOR_MATRIX_SMPTE240M;
10127                 break;
10128               case 9:
10129                 CUR_STREAM (stream)->colorimetry.matrix =
10130                     GST_VIDEO_COLOR_MATRIX_BT2020;
10131                 break;
10132               default:
10133                 break;
10134             }
10135
10136             CUR_STREAM (stream)->colorimetry.range =
10137                 full_range ? GST_VIDEO_COLOR_RANGE_0_255 :
10138                 GST_VIDEO_COLOR_RANGE_16_235;
10139           } else {
10140             GST_DEBUG_OBJECT (qtdemux, "Unsupported color type");
10141           }
10142         } else {
10143           GST_WARNING_OBJECT (qtdemux, "Invalid colr atom size");
10144         }
10145       }
10146
10147       if (esds) {
10148         gst_qtdemux_handle_esds (qtdemux, stream, entry, esds,
10149             stream->stream_tags);
10150       } else {
10151         switch (fourcc) {
10152           case FOURCC_H264:
10153           case FOURCC_avc1:
10154           case FOURCC_avc3:
10155           {
10156             gint len = QT_UINT32 (stsd_entry_data) - 0x56;
10157             const guint8 *avc_data = stsd_entry_data + 0x56;
10158
10159             /* find avcC */
10160             while (len >= 0x8) {
10161               gint size;
10162
10163               if (QT_UINT32 (avc_data) <= len)
10164                 size = QT_UINT32 (avc_data) - 0x8;
10165               else
10166                 size = len - 0x8;
10167
10168               if (size < 1)
10169                 /* No real data, so break out */
10170                 break;
10171
10172               switch (QT_FOURCC (avc_data + 0x4)) {
10173                 case FOURCC_avcC:
10174                 {
10175                   /* parse, if found */
10176                   GstBuffer *buf;
10177
10178                   GST_DEBUG_OBJECT (qtdemux, "found avcC codec_data in stsd");
10179
10180                   /* First 4 bytes are the length of the atom, the next 4 bytes
10181                    * are the fourcc, the next 1 byte is the version, and the
10182                    * subsequent bytes are profile_tier_level structure like data. */
10183                   gst_codec_utils_h264_caps_set_level_and_profile (entry->caps,
10184                       avc_data + 8 + 1, size - 1);
10185                   buf = gst_buffer_new_and_alloc (size);
10186                   gst_buffer_fill (buf, 0, avc_data + 0x8, size);
10187                   gst_caps_set_simple (entry->caps,
10188                       "codec_data", GST_TYPE_BUFFER, buf, NULL);
10189                   gst_buffer_unref (buf);
10190
10191                   break;
10192                 }
10193                 case FOURCC_strf:
10194                 {
10195                   GstBuffer *buf;
10196
10197                   GST_DEBUG_OBJECT (qtdemux, "found strf codec_data in stsd");
10198
10199                   /* First 4 bytes are the length of the atom, the next 4 bytes
10200                    * are the fourcc, next 40 bytes are BITMAPINFOHEADER,
10201                    * next 1 byte is the version, and the
10202                    * subsequent bytes are sequence parameter set like data. */
10203
10204                   size -= 40;   /* we'll be skipping BITMAPINFOHEADER */
10205                   if (size > 1) {
10206                     gst_codec_utils_h264_caps_set_level_and_profile
10207                         (entry->caps, avc_data + 8 + 40 + 1, size - 1);
10208
10209                     buf = gst_buffer_new_and_alloc (size);
10210                     gst_buffer_fill (buf, 0, avc_data + 8 + 40, size);
10211                     gst_caps_set_simple (entry->caps,
10212                         "codec_data", GST_TYPE_BUFFER, buf, NULL);
10213                     gst_buffer_unref (buf);
10214                   }
10215                   break;
10216                 }
10217                 case FOURCC_btrt:
10218                 {
10219                   guint avg_bitrate, max_bitrate;
10220
10221                   /* bufferSizeDB, maxBitrate and avgBitrate - 4 bytes each */
10222                   if (size < 12)
10223                     break;
10224
10225                   max_bitrate = QT_UINT32 (avc_data + 0xc);
10226                   avg_bitrate = QT_UINT32 (avc_data + 0x10);
10227
10228                   if (!max_bitrate && !avg_bitrate)
10229                     break;
10230
10231                   /* Some muxers seem to swap the average and maximum bitrates
10232                    * (I'm looking at you, YouTube), so we swap for sanity. */
10233                   if (max_bitrate > 0 && max_bitrate < avg_bitrate) {
10234                     guint temp = avg_bitrate;
10235
10236                     avg_bitrate = max_bitrate;
10237                     max_bitrate = temp;
10238                   }
10239
10240                   if (max_bitrate > 0 && max_bitrate < G_MAXUINT32) {
10241                     gst_tag_list_add (stream->stream_tags,
10242                         GST_TAG_MERGE_REPLACE, GST_TAG_MAXIMUM_BITRATE,
10243                         max_bitrate, NULL);
10244                   }
10245                   if (avg_bitrate > 0 && avg_bitrate < G_MAXUINT32) {
10246                     gst_tag_list_add (stream->stream_tags,
10247                         GST_TAG_MERGE_REPLACE, GST_TAG_BITRATE, avg_bitrate,
10248                         NULL);
10249                   }
10250
10251                   break;
10252                 }
10253
10254                 default:
10255                   break;
10256               }
10257
10258               len -= size + 8;
10259               avc_data += size + 8;
10260             }
10261
10262             break;
10263           }
10264           case FOURCC_H265:
10265           case FOURCC_hvc1:
10266           case FOURCC_hev1:
10267           {
10268             gint len = QT_UINT32 (stsd_entry_data) - 0x56;
10269             const guint8 *hevc_data = stsd_entry_data + 0x56;
10270
10271             /* find hevc */
10272             while (len >= 0x8) {
10273               gint size;
10274
10275               if (QT_UINT32 (hevc_data) <= len)
10276                 size = QT_UINT32 (hevc_data) - 0x8;
10277               else
10278                 size = len - 0x8;
10279
10280               if (size < 1)
10281                 /* No real data, so break out */
10282                 break;
10283
10284               switch (QT_FOURCC (hevc_data + 0x4)) {
10285                 case FOURCC_hvcC:
10286                 {
10287                   /* parse, if found */
10288                   GstBuffer *buf;
10289
10290                   GST_DEBUG_OBJECT (qtdemux, "found avcC codec_data in stsd");
10291
10292                   /* First 4 bytes are the length of the atom, the next 4 bytes
10293                    * are the fourcc, the next 1 byte is the version, and the
10294                    * subsequent bytes are sequence parameter set like data. */
10295                   gst_codec_utils_h265_caps_set_level_tier_and_profile
10296                       (entry->caps, hevc_data + 8 + 1, size - 1);
10297
10298                   buf = gst_buffer_new_and_alloc (size);
10299                   gst_buffer_fill (buf, 0, hevc_data + 0x8, size);
10300                   gst_caps_set_simple (entry->caps,
10301                       "codec_data", GST_TYPE_BUFFER, buf, NULL);
10302                   gst_buffer_unref (buf);
10303                   break;
10304                 }
10305                 default:
10306                   break;
10307               }
10308               len -= size + 8;
10309               hevc_data += size + 8;
10310             }
10311             break;
10312           }
10313           case FOURCC_mp4v:
10314           case FOURCC_MP4V:
10315           case FOURCC_fmp4:
10316           case FOURCC_FMP4:
10317           case FOURCC_xvid:
10318           case FOURCC_XVID:
10319           {
10320             GNode *glbl;
10321
10322             GST_DEBUG_OBJECT (qtdemux, "found %" GST_FOURCC_FORMAT,
10323                 GST_FOURCC_ARGS (fourcc));
10324
10325             /* codec data might be in glbl extension atom */
10326             glbl = mp4v ?
10327                 qtdemux_tree_get_child_by_type (mp4v, FOURCC_glbl) : NULL;
10328             if (glbl) {
10329               guint8 *data;
10330               GstBuffer *buf;
10331               gint len;
10332
10333               GST_DEBUG_OBJECT (qtdemux, "found glbl data in stsd");
10334               data = glbl->data;
10335               len = QT_UINT32 (data);
10336               if (len > 0x8) {
10337                 len -= 0x8;
10338                 buf = gst_buffer_new_and_alloc (len);
10339                 gst_buffer_fill (buf, 0, data + 8, len);
10340                 gst_caps_set_simple (entry->caps,
10341                     "codec_data", GST_TYPE_BUFFER, buf, NULL);
10342                 gst_buffer_unref (buf);
10343               }
10344             }
10345             break;
10346           }
10347           case FOURCC_mjp2:
10348           {
10349             /* see annex I of the jpeg2000 spec */
10350             GNode *jp2h, *ihdr, *colr, *mjp2, *field, *prefix, *cmap, *cdef;
10351             const guint8 *data;
10352             const gchar *colorspace = NULL;
10353             gint ncomp = 0;
10354             guint32 ncomp_map = 0;
10355             gint32 *comp_map = NULL;
10356             guint32 nchan_def = 0;
10357             gint32 *chan_def = NULL;
10358
10359             GST_DEBUG_OBJECT (qtdemux, "found mjp2");
10360             /* some required atoms */
10361             mjp2 = qtdemux_tree_get_child_by_index (stsd, stsd_index);
10362             if (!mjp2)
10363               break;
10364             jp2h = qtdemux_tree_get_child_by_type (mjp2, FOURCC_jp2h);
10365             if (!jp2h)
10366               break;
10367
10368             /* number of components; redundant with info in codestream, but useful
10369                to a muxer */
10370             ihdr = qtdemux_tree_get_child_by_type (jp2h, FOURCC_ihdr);
10371             if (!ihdr || QT_UINT32 (ihdr->data) != 22)
10372               break;
10373             ncomp = QT_UINT16 (((guint8 *) ihdr->data) + 16);
10374
10375             colr = qtdemux_tree_get_child_by_type (jp2h, FOURCC_colr);
10376             if (!colr)
10377               break;
10378             GST_DEBUG_OBJECT (qtdemux, "found colr");
10379             /* extract colour space info */
10380             if (QT_UINT8 ((guint8 *) colr->data + 8) == 1) {
10381               switch (QT_UINT32 ((guint8 *) colr->data + 11)) {
10382                 case 16:
10383                   colorspace = "sRGB";
10384                   break;
10385                 case 17:
10386                   colorspace = "GRAY";
10387                   break;
10388                 case 18:
10389                   colorspace = "sYUV";
10390                   break;
10391                 default:
10392                   colorspace = NULL;
10393                   break;
10394               }
10395             }
10396             if (!colorspace)
10397               /* colr is required, and only values 16, 17, and 18 are specified,
10398                  so error if we have no colorspace */
10399               break;
10400
10401             /* extract component mapping */
10402             cmap = qtdemux_tree_get_child_by_type (jp2h, FOURCC_cmap);
10403             if (cmap) {
10404               guint32 cmap_len = 0;
10405               int i;
10406               cmap_len = QT_UINT32 (cmap->data);
10407               if (cmap_len >= 8) {
10408                 /* normal box, subtract off header */
10409                 cmap_len -= 8;
10410                 /* cmap: { u16 cmp; u8 mtyp; u8 pcol; }* */
10411                 if (cmap_len % 4 == 0) {
10412                   ncomp_map = (cmap_len / 4);
10413                   comp_map = g_new0 (gint32, ncomp_map);
10414                   for (i = 0; i < ncomp_map; i++) {
10415                     guint16 cmp;
10416                     guint8 mtyp, pcol;
10417                     cmp = QT_UINT16 (((guint8 *) cmap->data) + 8 + i * 4);
10418                     mtyp = QT_UINT8 (((guint8 *) cmap->data) + 8 + i * 4 + 2);
10419                     pcol = QT_UINT8 (((guint8 *) cmap->data) + 8 + i * 4 + 3);
10420                     comp_map[i] = (mtyp << 24) | (pcol << 16) | cmp;
10421                   }
10422                 }
10423               }
10424             }
10425             /* extract channel definitions */
10426             cdef = qtdemux_tree_get_child_by_type (jp2h, FOURCC_cdef);
10427             if (cdef) {
10428               guint32 cdef_len = 0;
10429               int i;
10430               cdef_len = QT_UINT32 (cdef->data);
10431               if (cdef_len >= 10) {
10432                 /* normal box, subtract off header and len */
10433                 cdef_len -= 10;
10434                 /* cdef: u16 n; { u16 cn; u16 typ; u16 asoc; }* */
10435                 if (cdef_len % 6 == 0) {
10436                   nchan_def = (cdef_len / 6);
10437                   chan_def = g_new0 (gint32, nchan_def);
10438                   for (i = 0; i < nchan_def; i++)
10439                     chan_def[i] = -1;
10440                   for (i = 0; i < nchan_def; i++) {
10441                     guint16 cn, typ, asoc;
10442                     cn = QT_UINT16 (((guint8 *) cdef->data) + 10 + i * 6);
10443                     typ = QT_UINT16 (((guint8 *) cdef->data) + 10 + i * 6 + 2);
10444                     asoc = QT_UINT16 (((guint8 *) cdef->data) + 10 + i * 6 + 4);
10445                     if (cn < nchan_def) {
10446                       switch (typ) {
10447                         case 0:
10448                           chan_def[cn] = asoc;
10449                           break;
10450                         case 1:
10451                           chan_def[cn] = 0;     /* alpha */
10452                           break;
10453                         default:
10454                           chan_def[cn] = -typ;
10455                       }
10456                     }
10457                   }
10458                 }
10459               }
10460             }
10461
10462             gst_caps_set_simple (entry->caps,
10463                 "num-components", G_TYPE_INT, ncomp, NULL);
10464             gst_caps_set_simple (entry->caps,
10465                 "colorspace", G_TYPE_STRING, colorspace, NULL);
10466
10467             if (comp_map) {
10468               GValue arr = { 0, };
10469               GValue elt = { 0, };
10470               int i;
10471               g_value_init (&arr, GST_TYPE_ARRAY);
10472               g_value_init (&elt, G_TYPE_INT);
10473               for (i = 0; i < ncomp_map; i++) {
10474                 g_value_set_int (&elt, comp_map[i]);
10475                 gst_value_array_append_value (&arr, &elt);
10476               }
10477               gst_structure_set_value (gst_caps_get_structure (entry->caps, 0),
10478                   "component-map", &arr);
10479               g_value_unset (&elt);
10480               g_value_unset (&arr);
10481               g_free (comp_map);
10482             }
10483
10484             if (chan_def) {
10485               GValue arr = { 0, };
10486               GValue elt = { 0, };
10487               int i;
10488               g_value_init (&arr, GST_TYPE_ARRAY);
10489               g_value_init (&elt, G_TYPE_INT);
10490               for (i = 0; i < nchan_def; i++) {
10491                 g_value_set_int (&elt, chan_def[i]);
10492                 gst_value_array_append_value (&arr, &elt);
10493               }
10494               gst_structure_set_value (gst_caps_get_structure (entry->caps, 0),
10495                   "channel-definitions", &arr);
10496               g_value_unset (&elt);
10497               g_value_unset (&arr);
10498               g_free (chan_def);
10499             }
10500
10501             /* some optional atoms */
10502             field = qtdemux_tree_get_child_by_type (mjp2, FOURCC_fiel);
10503             prefix = qtdemux_tree_get_child_by_type (mjp2, FOURCC_jp2x);
10504
10505             /* indicate possible fields in caps */
10506             if (field) {
10507               data = (guint8 *) field->data + 8;
10508               if (*data != 1)
10509                 gst_caps_set_simple (entry->caps, "fields", G_TYPE_INT,
10510                     (gint) * data, NULL);
10511             }
10512             /* add codec_data if provided */
10513             if (prefix) {
10514               GstBuffer *buf;
10515               gint len;
10516
10517               GST_DEBUG_OBJECT (qtdemux, "found prefix data in stsd");
10518               data = prefix->data;
10519               len = QT_UINT32 (data);
10520               if (len > 0x8) {
10521                 len -= 0x8;
10522                 buf = gst_buffer_new_and_alloc (len);
10523                 gst_buffer_fill (buf, 0, data + 8, len);
10524                 gst_caps_set_simple (entry->caps,
10525                     "codec_data", GST_TYPE_BUFFER, buf, NULL);
10526                 gst_buffer_unref (buf);
10527               }
10528             }
10529             break;
10530           }
10531           case FOURCC_SVQ3:
10532           case FOURCC_VP31:
10533           {
10534             GstBuffer *buf;
10535             GstBuffer *seqh = NULL;
10536             const guint8 *gamma_data = NULL;
10537             gint len = QT_UINT32 (stsd_data);   /* FIXME review - why put the whole stsd in codec data? */
10538
10539             qtdemux_parse_svq3_stsd_data (qtdemux, stsd_entry_data, &gamma_data,
10540                 &seqh);
10541             if (gamma_data) {
10542               gst_caps_set_simple (entry->caps, "applied-gamma", G_TYPE_DOUBLE,
10543                   QT_FP32 (gamma_data), NULL);
10544             }
10545             if (seqh) {
10546               /* sorry for the bad name, but we don't know what this is, other
10547                * than its own fourcc */
10548               gst_caps_set_simple (entry->caps, "seqh", GST_TYPE_BUFFER, seqh,
10549                   NULL);
10550               gst_buffer_unref (seqh);
10551             }
10552
10553             GST_DEBUG_OBJECT (qtdemux, "found codec_data in stsd");
10554             buf = gst_buffer_new_and_alloc (len);
10555             gst_buffer_fill (buf, 0, stsd_data, len);
10556             gst_caps_set_simple (entry->caps,
10557                 "codec_data", GST_TYPE_BUFFER, buf, NULL);
10558             gst_buffer_unref (buf);
10559             break;
10560           }
10561           case FOURCC_jpeg:
10562           {
10563             /* https://developer.apple.com/standards/qtff-2001.pdf,
10564              * page 92, "Video Sample Description", under table 3.1 */
10565             GstByteReader br;
10566
10567             const gint compressor_offset =
10568                 16 + 4 + 4 * 3 + 2 * 2 + 2 * 4 + 4 + 2;
10569             const gint min_size = compressor_offset + 32 + 2 + 2;
10570             GNode *jpeg;
10571             guint32 len;
10572             guint16 color_table_id = 0;
10573             gboolean ok;
10574
10575             GST_DEBUG_OBJECT (qtdemux, "found jpeg");
10576
10577             /* recover information on interlaced/progressive */
10578             jpeg = qtdemux_tree_get_child_by_type (stsd, FOURCC_jpeg);
10579             if (!jpeg)
10580               break;
10581
10582             len = QT_UINT32 (jpeg->data);
10583             GST_DEBUG_OBJECT (qtdemux, "Found jpeg: len %u, need %d", len,
10584                 min_size);
10585             if (len >= min_size) {
10586               gst_byte_reader_init (&br, jpeg->data, len);
10587
10588               gst_byte_reader_skip (&br, compressor_offset + 32 + 2);
10589               gst_byte_reader_get_uint16_le (&br, &color_table_id);
10590               if (color_table_id != 0) {
10591                 /* the spec says there can be concatenated chunks in the data, and we want
10592                  * to find one called field. Walk through them. */
10593                 gint offset = min_size;
10594                 while (offset + 8 < len) {
10595                   guint32 size = 0, tag;
10596                   ok = gst_byte_reader_get_uint32_le (&br, &size);
10597                   ok &= gst_byte_reader_get_uint32_le (&br, &tag);
10598                   if (!ok || size < 8) {
10599                     GST_WARNING_OBJECT (qtdemux,
10600                         "Failed to walk optional chunk list");
10601                     break;
10602                   }
10603                   GST_DEBUG_OBJECT (qtdemux,
10604                       "Found optional %4.4s chunk, size %u",
10605                       (const char *) &tag, size);
10606                   if (tag == FOURCC_fiel) {
10607                     guint8 n_fields = 0, ordering = 0;
10608                     gst_byte_reader_get_uint8 (&br, &n_fields);
10609                     gst_byte_reader_get_uint8 (&br, &ordering);
10610                     if (n_fields == 1 || n_fields == 2) {
10611                       GST_DEBUG_OBJECT (qtdemux,
10612                           "Found fiel tag with %u fields, ordering %u",
10613                           n_fields, ordering);
10614                       if (n_fields == 2)
10615                         gst_caps_set_simple (CUR_STREAM (stream)->caps,
10616                             "interlace-mode", G_TYPE_STRING, "interleaved",
10617                             NULL);
10618                     } else {
10619                       GST_WARNING_OBJECT (qtdemux,
10620                           "Found fiel tag with invalid fields (%u)", n_fields);
10621                     }
10622                   }
10623                   offset += size;
10624                 }
10625               } else {
10626                 GST_DEBUG_OBJECT (qtdemux,
10627                     "Color table ID is 0, not trying to get interlacedness");
10628               }
10629             } else {
10630               GST_WARNING_OBJECT (qtdemux,
10631                   "Length of jpeg chunk is too small, not trying to get interlacedness");
10632             }
10633
10634             break;
10635           }
10636           case FOURCC_rle_:
10637           case FOURCC_WRLE:
10638           {
10639             gst_caps_set_simple (entry->caps,
10640                 "depth", G_TYPE_INT, QT_UINT16 (stsd_entry_data + offset + 66),
10641                 NULL);
10642             break;
10643           }
10644           case FOURCC_XiTh:
10645           {
10646             GNode *xith, *xdxt;
10647
10648             GST_DEBUG_OBJECT (qtdemux, "found XiTh");
10649             xith = qtdemux_tree_get_child_by_index (stsd, stsd_index);
10650             if (!xith)
10651               break;
10652
10653             xdxt = qtdemux_tree_get_child_by_type (xith, FOURCC_XdxT);
10654             if (!xdxt)
10655               break;
10656
10657             GST_DEBUG_OBJECT (qtdemux, "found XdxT node");
10658             /* collect the headers and store them in a stream list so that we can
10659              * send them out first */
10660             qtdemux_parse_theora_extension (qtdemux, stream, xdxt);
10661             break;
10662           }
10663           case FOURCC_ovc1:
10664           {
10665             GNode *ovc1;
10666             guint8 *ovc1_data;
10667             guint ovc1_len;
10668             GstBuffer *buf;
10669
10670             GST_DEBUG_OBJECT (qtdemux, "parse ovc1 header");
10671             ovc1 = qtdemux_tree_get_child_by_index (stsd, stsd_index);
10672             if (!ovc1)
10673               break;
10674             ovc1_data = ovc1->data;
10675             ovc1_len = QT_UINT32 (ovc1_data);
10676             if (ovc1_len <= 198) {
10677               GST_WARNING_OBJECT (qtdemux, "Too small ovc1 header, skipping");
10678               break;
10679             }
10680             buf = gst_buffer_new_and_alloc (ovc1_len - 198);
10681             gst_buffer_fill (buf, 0, ovc1_data + 198, ovc1_len - 198);
10682             gst_caps_set_simple (entry->caps,
10683                 "codec_data", GST_TYPE_BUFFER, buf, NULL);
10684             gst_buffer_unref (buf);
10685             break;
10686           }
10687           case FOURCC_vc_1:
10688           {
10689             gint len = QT_UINT32 (stsd_entry_data) - 0x56;
10690             const guint8 *vc1_data = stsd_entry_data + 0x56;
10691
10692             /* find dvc1 */
10693             while (len >= 8) {
10694               gint size;
10695
10696               if (QT_UINT32 (vc1_data) <= len)
10697                 size = QT_UINT32 (vc1_data) - 8;
10698               else
10699                 size = len - 8;
10700
10701               if (size < 1)
10702                 /* No real data, so break out */
10703                 break;
10704
10705               switch (QT_FOURCC (vc1_data + 0x4)) {
10706                 case GST_MAKE_FOURCC ('d', 'v', 'c', '1'):
10707                 {
10708                   GstBuffer *buf;
10709
10710                   GST_DEBUG_OBJECT (qtdemux, "found dvc1 codec_data in stsd");
10711                   buf = gst_buffer_new_and_alloc (size);
10712                   gst_buffer_fill (buf, 0, vc1_data + 8, size);
10713                   gst_caps_set_simple (entry->caps,
10714                       "codec_data", GST_TYPE_BUFFER, buf, NULL);
10715                   gst_buffer_unref (buf);
10716                   break;
10717                 }
10718                 default:
10719                   break;
10720               }
10721               len -= size + 8;
10722               vc1_data += size + 8;
10723             }
10724             break;
10725           }
10726           default:
10727             break;
10728         }
10729       }
10730
10731       GST_INFO_OBJECT (qtdemux,
10732           "type %" GST_FOURCC_FORMAT " caps %" GST_PTR_FORMAT,
10733           GST_FOURCC_ARGS (fourcc), entry->caps);
10734
10735     } else if (stream->subtype == FOURCC_soun) {
10736       int version, samplesize;
10737       guint16 compression_id;
10738       gboolean amrwb = FALSE;
10739
10740       offset = 16;
10741       /* sample description entry (16) + sound sample description v0 (20) */
10742       if (len < 36)
10743         goto corrupt_file;
10744
10745       version = QT_UINT32 (stsd_entry_data + offset);
10746       entry->n_channels = QT_UINT16 (stsd_entry_data + offset + 8);
10747       samplesize = QT_UINT16 (stsd_entry_data + offset + 10);
10748       compression_id = QT_UINT16 (stsd_entry_data + offset + 12);
10749       entry->rate = QT_FP32 (stsd_entry_data + offset + 16);
10750
10751       GST_LOG_OBJECT (qtdemux, "version/rev:      %08x", version);
10752       GST_LOG_OBJECT (qtdemux, "vendor:           %08x",
10753           QT_UINT32 (stsd_entry_data + offset + 4));
10754       GST_LOG_OBJECT (qtdemux, "n_channels:       %d", entry->n_channels);
10755       GST_LOG_OBJECT (qtdemux, "sample_size:      %d", samplesize);
10756       GST_LOG_OBJECT (qtdemux, "compression_id:   %d", compression_id);
10757       GST_LOG_OBJECT (qtdemux, "packet size:      %d",
10758           QT_UINT16 (stsd_entry_data + offset + 14));
10759       GST_LOG_OBJECT (qtdemux, "sample rate:      %g", entry->rate);
10760
10761       if (compression_id == 0xfffe)
10762         entry->sampled = TRUE;
10763
10764       /* first assume uncompressed audio */
10765       entry->bytes_per_sample = samplesize / 8;
10766       entry->samples_per_frame = entry->n_channels;
10767       entry->bytes_per_frame = entry->n_channels * entry->bytes_per_sample;
10768       entry->samples_per_packet = entry->samples_per_frame;
10769       entry->bytes_per_packet = entry->bytes_per_sample;
10770
10771       offset = 36;
10772       switch (fourcc) {
10773           /* Yes, these have to be hard-coded */
10774         case FOURCC_MAC6:
10775         {
10776           entry->samples_per_packet = 6;
10777           entry->bytes_per_packet = 1;
10778           entry->bytes_per_frame = 1 * entry->n_channels;
10779           entry->bytes_per_sample = 1;
10780           entry->samples_per_frame = 6 * entry->n_channels;
10781           break;
10782         }
10783         case FOURCC_MAC3:
10784         {
10785           entry->samples_per_packet = 3;
10786           entry->bytes_per_packet = 1;
10787           entry->bytes_per_frame = 1 * entry->n_channels;
10788           entry->bytes_per_sample = 1;
10789           entry->samples_per_frame = 3 * entry->n_channels;
10790           break;
10791         }
10792         case FOURCC_ima4:
10793         {
10794           entry->samples_per_packet = 64;
10795           entry->bytes_per_packet = 34;
10796           entry->bytes_per_frame = 34 * entry->n_channels;
10797           entry->bytes_per_sample = 2;
10798           entry->samples_per_frame = 64 * entry->n_channels;
10799           break;
10800         }
10801         case FOURCC_ulaw:
10802         case FOURCC_alaw:
10803         {
10804           entry->samples_per_packet = 1;
10805           entry->bytes_per_packet = 1;
10806           entry->bytes_per_frame = 1 * entry->n_channels;
10807           entry->bytes_per_sample = 1;
10808           entry->samples_per_frame = 1 * entry->n_channels;
10809           break;
10810         }
10811         case FOURCC_agsm:
10812         {
10813           entry->samples_per_packet = 160;
10814           entry->bytes_per_packet = 33;
10815           entry->bytes_per_frame = 33 * entry->n_channels;
10816           entry->bytes_per_sample = 2;
10817           entry->samples_per_frame = 160 * entry->n_channels;
10818           break;
10819         }
10820         default:
10821           break;
10822       }
10823
10824       if (version == 0x00010000) {
10825         /* sample description entry (16) + sound sample description v1 (20+16) */
10826         if (len < 52)
10827           goto corrupt_file;
10828
10829         switch (fourcc) {
10830           case FOURCC_twos:
10831           case FOURCC_sowt:
10832           case FOURCC_raw_:
10833             break;
10834           default:
10835           {
10836             /* only parse extra decoding config for non-pcm audio */
10837             entry->samples_per_packet = QT_UINT32 (stsd_entry_data + offset);
10838             entry->bytes_per_packet = QT_UINT32 (stsd_entry_data + offset + 4);
10839             entry->bytes_per_frame = QT_UINT32 (stsd_entry_data + offset + 8);
10840             entry->bytes_per_sample = QT_UINT32 (stsd_entry_data + offset + 12);
10841
10842             GST_LOG_OBJECT (qtdemux, "samples/packet:   %d",
10843                 entry->samples_per_packet);
10844             GST_LOG_OBJECT (qtdemux, "bytes/packet:     %d",
10845                 entry->bytes_per_packet);
10846             GST_LOG_OBJECT (qtdemux, "bytes/frame:      %d",
10847                 entry->bytes_per_frame);
10848             GST_LOG_OBJECT (qtdemux, "bytes/sample:     %d",
10849                 entry->bytes_per_sample);
10850
10851             if (!entry->sampled && entry->bytes_per_packet) {
10852               entry->samples_per_frame = (entry->bytes_per_frame /
10853                   entry->bytes_per_packet) * entry->samples_per_packet;
10854               GST_LOG_OBJECT (qtdemux, "samples/frame:    %d",
10855                   entry->samples_per_frame);
10856             }
10857             break;
10858           }
10859         }
10860       } else if (version == 0x00020000) {
10861         union
10862         {
10863           gdouble fp;
10864           guint64 val;
10865         } qtfp;
10866
10867         /* sample description entry (16) + sound sample description v2 (56) */
10868         if (len < 72)
10869           goto corrupt_file;
10870
10871         qtfp.val = QT_UINT64 (stsd_entry_data + offset + 4);
10872         entry->rate = qtfp.fp;
10873         entry->n_channels = QT_UINT32 (stsd_entry_data + offset + 12);
10874
10875         GST_LOG_OBJECT (qtdemux, "Sound sample description Version 2");
10876         GST_LOG_OBJECT (qtdemux, "sample rate:        %g", entry->rate);
10877         GST_LOG_OBJECT (qtdemux, "n_channels:         %d", entry->n_channels);
10878         GST_LOG_OBJECT (qtdemux, "bits/channel:       %d",
10879             QT_UINT32 (stsd_entry_data + offset + 20));
10880         GST_LOG_OBJECT (qtdemux, "format flags:       %X",
10881             QT_UINT32 (stsd_entry_data + offset + 24));
10882         GST_LOG_OBJECT (qtdemux, "bytes/packet:       %d",
10883             QT_UINT32 (stsd_entry_data + offset + 28));
10884         GST_LOG_OBJECT (qtdemux, "LPCM frames/packet: %d",
10885             QT_UINT32 (stsd_entry_data + offset + 32));
10886       } else if (version != 0x00000) {
10887         GST_WARNING_OBJECT (qtdemux, "unknown audio STSD version %08x",
10888             version);
10889       }
10890
10891       if (entry->caps)
10892         gst_caps_unref (entry->caps);
10893
10894       entry->caps = qtdemux_audio_caps (qtdemux, stream, entry, fourcc,
10895           stsd_entry_data + 32, len - 16, &codec);
10896
10897       switch (fourcc) {
10898         case FOURCC_in24:
10899         {
10900           GNode *enda;
10901           GNode *in24;
10902
10903           in24 = qtdemux_tree_get_child_by_type (stsd, FOURCC_in24);
10904
10905           enda = qtdemux_tree_get_child_by_type (in24, FOURCC_enda);
10906           if (!enda) {
10907             wave = qtdemux_tree_get_child_by_type (in24, FOURCC_wave);
10908             if (wave)
10909               enda = qtdemux_tree_get_child_by_type (wave, FOURCC_enda);
10910           }
10911           if (enda) {
10912             int enda_value = QT_UINT16 ((guint8 *) enda->data + 8);
10913             gst_caps_set_simple (entry->caps,
10914                 "format", G_TYPE_STRING, (enda_value) ? "S24LE" : "S24BE",
10915                 NULL);
10916           }
10917           break;
10918         }
10919         case FOURCC_owma:
10920         {
10921           const guint8 *owma_data;
10922           const gchar *codec_name = NULL;
10923           guint owma_len;
10924           GstBuffer *buf;
10925           gint version = 1;
10926           /* from http://msdn.microsoft.com/en-us/library/dd757720(VS.85).aspx */
10927           /* FIXME this should also be gst_riff_strf_auds,
10928            * but the latter one is actually missing bits-per-sample :( */
10929           typedef struct
10930           {
10931             gint16 wFormatTag;
10932             gint16 nChannels;
10933             gint32 nSamplesPerSec;
10934             gint32 nAvgBytesPerSec;
10935             gint16 nBlockAlign;
10936             gint16 wBitsPerSample;
10937             gint16 cbSize;
10938           } WAVEFORMATEX;
10939           WAVEFORMATEX *wfex;
10940
10941           GST_DEBUG_OBJECT (qtdemux, "parse owma");
10942           owma_data = stsd_entry_data;
10943           owma_len = QT_UINT32 (owma_data);
10944           if (owma_len <= 54) {
10945             GST_WARNING_OBJECT (qtdemux, "Too small owma header, skipping");
10946             break;
10947           }
10948           wfex = (WAVEFORMATEX *) (owma_data + 36);
10949           buf = gst_buffer_new_and_alloc (owma_len - 54);
10950           gst_buffer_fill (buf, 0, owma_data + 54, owma_len - 54);
10951           if (wfex->wFormatTag == 0x0161) {
10952             codec_name = "Windows Media Audio";
10953             version = 2;
10954           } else if (wfex->wFormatTag == 0x0162) {
10955             codec_name = "Windows Media Audio 9 Pro";
10956             version = 3;
10957           } else if (wfex->wFormatTag == 0x0163) {
10958             codec_name = "Windows Media Audio 9 Lossless";
10959             /* is that correct? gstffmpegcodecmap.c is missing it, but
10960              * fluendo codec seems to support it */
10961             version = 4;
10962           }
10963
10964           gst_caps_set_simple (entry->caps,
10965               "codec_data", GST_TYPE_BUFFER, buf,
10966               "wmaversion", G_TYPE_INT, version,
10967               "block_align", G_TYPE_INT,
10968               GST_READ_UINT16_LE (&wfex->nBlockAlign), "bitrate", G_TYPE_INT,
10969               GST_READ_UINT32_LE (&wfex->nAvgBytesPerSec), "width", G_TYPE_INT,
10970               GST_READ_UINT16_LE (&wfex->wBitsPerSample), "depth", G_TYPE_INT,
10971               GST_READ_UINT16_LE (&wfex->wBitsPerSample), NULL);
10972           gst_buffer_unref (buf);
10973
10974           if (codec_name) {
10975             g_free (codec);
10976             codec = g_strdup (codec_name);
10977           }
10978           break;
10979         }
10980         case FOURCC_wma_:
10981         {
10982           gint len = QT_UINT32 (stsd_entry_data) - offset;
10983           const guint8 *wfex_data = stsd_entry_data + offset;
10984           const gchar *codec_name = NULL;
10985           gint version = 1;
10986           /* from http://msdn.microsoft.com/en-us/library/dd757720(VS.85).aspx */
10987           /* FIXME this should also be gst_riff_strf_auds,
10988            * but the latter one is actually missing bits-per-sample :( */
10989           typedef struct
10990           {
10991             gint16 wFormatTag;
10992             gint16 nChannels;
10993             gint32 nSamplesPerSec;
10994             gint32 nAvgBytesPerSec;
10995             gint16 nBlockAlign;
10996             gint16 wBitsPerSample;
10997             gint16 cbSize;
10998           } WAVEFORMATEX;
10999           WAVEFORMATEX wfex;
11000
11001           /* FIXME: unify with similar wavformatex parsing code above */
11002           GST_DEBUG_OBJECT (qtdemux, "parse wma, looking for wfex");
11003
11004           /* find wfex */
11005           while (len >= 8) {
11006             gint size;
11007
11008             if (QT_UINT32 (wfex_data) <= len)
11009               size = QT_UINT32 (wfex_data) - 8;
11010             else
11011               size = len - 8;
11012
11013             if (size < 1)
11014               /* No real data, so break out */
11015               break;
11016
11017             switch (QT_FOURCC (wfex_data + 4)) {
11018               case GST_MAKE_FOURCC ('w', 'f', 'e', 'x'):
11019               {
11020                 GST_DEBUG_OBJECT (qtdemux, "found wfex in stsd");
11021
11022                 if (size < 8 + 18)
11023                   break;
11024
11025                 wfex.wFormatTag = GST_READ_UINT16_LE (wfex_data + 8 + 0);
11026                 wfex.nChannels = GST_READ_UINT16_LE (wfex_data + 8 + 2);
11027                 wfex.nSamplesPerSec = GST_READ_UINT32_LE (wfex_data + 8 + 4);
11028                 wfex.nAvgBytesPerSec = GST_READ_UINT32_LE (wfex_data + 8 + 8);
11029                 wfex.nBlockAlign = GST_READ_UINT16_LE (wfex_data + 8 + 12);
11030                 wfex.wBitsPerSample = GST_READ_UINT16_LE (wfex_data + 8 + 14);
11031                 wfex.cbSize = GST_READ_UINT16_LE (wfex_data + 8 + 16);
11032
11033                 GST_LOG_OBJECT (qtdemux, "Found wfex box in stsd:");
11034                 GST_LOG_OBJECT (qtdemux, "FormatTag = 0x%04x, Channels = %u, "
11035                     "SamplesPerSec = %u, AvgBytesPerSec = %u, BlockAlign = %u, "
11036                     "BitsPerSample = %u, Size = %u", wfex.wFormatTag,
11037                     wfex.nChannels, wfex.nSamplesPerSec, wfex.nAvgBytesPerSec,
11038                     wfex.nBlockAlign, wfex.wBitsPerSample, wfex.cbSize);
11039
11040                 if (wfex.wFormatTag == 0x0161) {
11041                   codec_name = "Windows Media Audio";
11042                   version = 2;
11043                 } else if (wfex.wFormatTag == 0x0162) {
11044                   codec_name = "Windows Media Audio 9 Pro";
11045                   version = 3;
11046                 } else if (wfex.wFormatTag == 0x0163) {
11047                   codec_name = "Windows Media Audio 9 Lossless";
11048                   /* is that correct? gstffmpegcodecmap.c is missing it, but
11049                    * fluendo codec seems to support it */
11050                   version = 4;
11051                 }
11052
11053                 gst_caps_set_simple (entry->caps,
11054                     "wmaversion", G_TYPE_INT, version,
11055                     "block_align", G_TYPE_INT, wfex.nBlockAlign,
11056                     "bitrate", G_TYPE_INT, wfex.nAvgBytesPerSec,
11057                     "width", G_TYPE_INT, wfex.wBitsPerSample,
11058                     "depth", G_TYPE_INT, wfex.wBitsPerSample, NULL);
11059
11060                 if (size > wfex.cbSize) {
11061                   GstBuffer *buf;
11062
11063                   buf = gst_buffer_new_and_alloc (size - wfex.cbSize);
11064                   gst_buffer_fill (buf, 0, wfex_data + 8 + wfex.cbSize,
11065                       size - wfex.cbSize);
11066                   gst_caps_set_simple (entry->caps,
11067                       "codec_data", GST_TYPE_BUFFER, buf, NULL);
11068                   gst_buffer_unref (buf);
11069                 } else {
11070                   GST_WARNING_OBJECT (qtdemux, "no codec data");
11071                 }
11072
11073                 if (codec_name) {
11074                   g_free (codec);
11075                   codec = g_strdup (codec_name);
11076                 }
11077                 break;
11078               }
11079               default:
11080                 break;
11081             }
11082             len -= size + 8;
11083             wfex_data += size + 8;
11084           }
11085           break;
11086         }
11087         case FOURCC_opus:
11088         {
11089           const guint8 *opus_data;
11090           guint8 *channel_mapping = NULL;
11091           guint32 rate;
11092           guint8 channels;
11093           guint8 channel_mapping_family;
11094           guint8 stream_count;
11095           guint8 coupled_count;
11096           guint8 i;
11097
11098           opus_data = stsd_entry_data;
11099
11100           channels = GST_READ_UINT8 (opus_data + 45);
11101           rate = GST_READ_UINT32_LE (opus_data + 48);
11102           channel_mapping_family = GST_READ_UINT8 (opus_data + 54);
11103           stream_count = GST_READ_UINT8 (opus_data + 55);
11104           coupled_count = GST_READ_UINT8 (opus_data + 56);
11105
11106           if (channels > 0) {
11107             channel_mapping = g_malloc (channels * sizeof (guint8));
11108             for (i = 0; i < channels; i++)
11109               channel_mapping[i] = GST_READ_UINT8 (opus_data + i + 57);
11110           }
11111
11112           entry->caps = gst_codec_utils_opus_create_caps (rate, channels,
11113               channel_mapping_family, stream_count, coupled_count,
11114               channel_mapping);
11115           break;
11116         }
11117         default:
11118           break;
11119       }
11120
11121       if (codec) {
11122         GstStructure *s;
11123         gint bitrate = 0;
11124
11125         gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
11126             GST_TAG_AUDIO_CODEC, codec, NULL);
11127         g_free (codec);
11128         codec = NULL;
11129
11130         /* some bitrate info may have ended up in caps */
11131         s = gst_caps_get_structure (entry->caps, 0);
11132         gst_structure_get_int (s, "bitrate", &bitrate);
11133         if (bitrate > 0)
11134           gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
11135               GST_TAG_BITRATE, bitrate, NULL);
11136       }
11137
11138       mp4a = qtdemux_tree_get_child_by_index (stsd, stsd_index);
11139       if (!stream->protected) {
11140       } else {
11141         if (QTDEMUX_TREE_NODE_FOURCC (mp4v) != FOURCC_encv) {
11142           mp4v = NULL;
11143         }
11144       }
11145       if (stream->protected && fourcc == FOURCC_mp4a) {
11146         if (QTDEMUX_TREE_NODE_FOURCC (mp4a) != FOURCC_enca) {
11147           mp4a = NULL;
11148         }
11149       } else {
11150         if (QTDEMUX_TREE_NODE_FOURCC (mp4a) != FOURCC_mp4a) {
11151           mp4a = NULL;
11152         }
11153       }
11154
11155       wave = NULL;
11156       esds = NULL;
11157       if (mp4a) {
11158         wave = qtdemux_tree_get_child_by_type (mp4a, FOURCC_wave);
11159         if (wave)
11160           esds = qtdemux_tree_get_child_by_type (wave, FOURCC_esds);
11161         if (!esds)
11162           esds = qtdemux_tree_get_child_by_type (mp4a, FOURCC_esds);
11163       }
11164
11165
11166       /* If the fourcc's bottom 16 bits gives 'sm', then the top
11167          16 bits is a byte-swapped wave-style codec identifier,
11168          and we can find a WAVE header internally to a 'wave' atom here.
11169          This can more clearly be thought of as 'ms' as the top 16 bits, and a
11170          codec id as the bottom 16 bits - but byte-swapped to store in QT (which
11171          is big-endian).
11172        */
11173       if ((fourcc & 0xffff) == (('s' << 8) | 'm')) {
11174         if (len < offset + 20) {
11175           GST_WARNING_OBJECT (qtdemux, "No wave atom in MS-style audio");
11176         } else {
11177           guint32 datalen = QT_UINT32 (stsd_entry_data + offset + 16);
11178           const guint8 *data = stsd_entry_data + offset + 16;
11179           GNode *wavenode;
11180           GNode *waveheadernode;
11181
11182           wavenode = g_node_new ((guint8 *) data);
11183           if (qtdemux_parse_node (qtdemux, wavenode, data, datalen)) {
11184             const guint8 *waveheader;
11185             guint32 headerlen;
11186
11187             waveheadernode = qtdemux_tree_get_child_by_type (wavenode, fourcc);
11188             if (waveheadernode) {
11189               waveheader = (const guint8 *) waveheadernode->data;
11190               headerlen = QT_UINT32 (waveheader);
11191
11192               if (headerlen > 8) {
11193                 gst_riff_strf_auds *header = NULL;
11194                 GstBuffer *headerbuf;
11195                 GstBuffer *extra;
11196
11197                 waveheader += 8;
11198                 headerlen -= 8;
11199
11200                 headerbuf = gst_buffer_new_and_alloc (headerlen);
11201                 gst_buffer_fill (headerbuf, 0, waveheader, headerlen);
11202
11203                 if (gst_riff_parse_strf_auds (GST_ELEMENT_CAST (qtdemux),
11204                         headerbuf, &header, &extra)) {
11205                   gst_caps_unref (entry->caps);
11206                   /* FIXME: Need to do something with the channel reorder map */
11207                   entry->caps =
11208                       gst_riff_create_audio_caps (header->format, NULL, header,
11209                       extra, NULL, NULL, NULL);
11210
11211                   if (extra)
11212                     gst_buffer_unref (extra);
11213                   g_free (header);
11214                 }
11215               }
11216             } else
11217               GST_DEBUG ("Didn't find waveheadernode for this codec");
11218           }
11219           g_node_destroy (wavenode);
11220         }
11221       } else if (esds) {
11222         gst_qtdemux_handle_esds (qtdemux, stream, entry, esds,
11223             stream->stream_tags);
11224       } else {
11225         switch (fourcc) {
11226 #if 0
11227             /* FIXME: what is in the chunk? */
11228           case FOURCC_QDMC:
11229           {
11230             gint len = QT_UINT32 (stsd_data);
11231
11232             /* seems to be always = 116 = 0x74 */
11233             break;
11234           }
11235 #endif
11236           case FOURCC_QDM2:
11237           {
11238             gint len = QT_UINT32 (stsd_entry_data);
11239
11240             if (len > 0x3C) {
11241               GstBuffer *buf = gst_buffer_new_and_alloc (len - 0x3C);
11242
11243               gst_buffer_fill (buf, 0, stsd_entry_data + 0x3C, len - 0x3C);
11244               gst_caps_set_simple (entry->caps,
11245                   "codec_data", GST_TYPE_BUFFER, buf, NULL);
11246               gst_buffer_unref (buf);
11247             }
11248             gst_caps_set_simple (entry->caps,
11249                 "samplesize", G_TYPE_INT, samplesize, NULL);
11250             break;
11251           }
11252           case FOURCC_alac:
11253           {
11254             GNode *alac, *wave = NULL;
11255
11256             /* apparently, m4a has this atom appended directly in the stsd entry,
11257              * while mov has it in a wave atom */
11258             alac = qtdemux_tree_get_child_by_type (stsd, FOURCC_alac);
11259             if (alac) {
11260               /* alac now refers to stsd entry atom */
11261               wave = qtdemux_tree_get_child_by_type (alac, FOURCC_wave);
11262               if (wave)
11263                 alac = qtdemux_tree_get_child_by_type (wave, FOURCC_alac);
11264               else
11265                 alac = qtdemux_tree_get_child_by_type (alac, FOURCC_alac);
11266             }
11267             if (alac) {
11268               const guint8 *alac_data = alac->data;
11269               gint len = QT_UINT32 (alac->data);
11270               GstBuffer *buf;
11271
11272               if (len < 36) {
11273                 GST_DEBUG_OBJECT (qtdemux,
11274                     "discarding alac atom with unexpected len %d", len);
11275               } else {
11276                 /* codec-data contains alac atom size and prefix,
11277                  * ffmpeg likes it that way, not quite gst-ish though ...*/
11278                 buf = gst_buffer_new_and_alloc (len);
11279                 gst_buffer_fill (buf, 0, alac->data, len);
11280                 gst_caps_set_simple (entry->caps,
11281                     "codec_data", GST_TYPE_BUFFER, buf, NULL);
11282                 gst_buffer_unref (buf);
11283
11284                 entry->bytes_per_frame = QT_UINT32 (alac_data + 12);
11285                 entry->n_channels = QT_UINT8 (alac_data + 21);
11286                 entry->rate = QT_UINT32 (alac_data + 32);
11287               }
11288             }
11289             gst_caps_set_simple (entry->caps,
11290                 "samplesize", G_TYPE_INT, samplesize, NULL);
11291             break;
11292           }
11293           case FOURCC_fLaC:
11294           {
11295             /* The codingname of the sample entry is 'fLaC' */
11296             GNode *flac = qtdemux_tree_get_child_by_type (stsd, FOURCC_fLaC);
11297
11298             if (flac) {
11299               /* The 'dfLa' box is added to the sample entry to convey
11300                  initializing information for the decoder. */
11301               const GNode *dfla =
11302                   qtdemux_tree_get_child_by_type (flac, FOURCC_dfLa);
11303
11304               if (dfla) {
11305                 const guint32 len = QT_UINT32 (dfla->data);
11306
11307                 /* Must contain at least dfLa box header (12),
11308                  * METADATA_BLOCK_HEADER (4), METADATA_BLOCK_STREAMINFO (34) */
11309                 if (len < 50) {
11310                   GST_DEBUG_OBJECT (qtdemux,
11311                       "discarding dfla atom with unexpected len %d", len);
11312                 } else {
11313                   /* skip dfLa header to get the METADATA_BLOCKs */
11314                   const guint8 *metadata_blocks = (guint8 *) dfla->data + 12;
11315                   const guint32 metadata_blocks_len = len - 12;
11316
11317                   gchar *stream_marker = g_strdup ("fLaC");
11318                   GstBuffer *block = gst_buffer_new_wrapped (stream_marker,
11319                       strlen (stream_marker));
11320
11321                   guint32 index = 0;
11322                   guint32 remainder = 0;
11323                   guint32 block_size = 0;
11324                   gboolean is_last = FALSE;
11325
11326                   GValue array = G_VALUE_INIT;
11327                   GValue value = G_VALUE_INIT;
11328
11329                   g_value_init (&array, GST_TYPE_ARRAY);
11330                   g_value_init (&value, GST_TYPE_BUFFER);
11331
11332                   gst_value_set_buffer (&value, block);
11333                   gst_value_array_append_value (&array, &value);
11334                   g_value_reset (&value);
11335
11336                   gst_buffer_unref (block);
11337
11338                   /* check there's at least one METADATA_BLOCK_HEADER's worth
11339                    * of data, and we haven't already finished parsing */
11340                   while (!is_last && ((index + 3) < metadata_blocks_len)) {
11341                     remainder = metadata_blocks_len - index;
11342
11343                     /* add the METADATA_BLOCK_HEADER size to the signalled size */
11344                     block_size = 4 +
11345                         (metadata_blocks[index + 1] << 16) +
11346                         (metadata_blocks[index + 2] << 8) +
11347                         metadata_blocks[index + 3];
11348
11349                     /* be careful not to read off end of box */
11350                     if (block_size > remainder) {
11351                       break;
11352                     }
11353
11354                     is_last = metadata_blocks[index] >> 7;
11355
11356                     block = gst_buffer_new_and_alloc (block_size);
11357
11358                     gst_buffer_fill (block, 0, &metadata_blocks[index],
11359                         block_size);
11360
11361                     gst_value_set_buffer (&value, block);
11362                     gst_value_array_append_value (&array, &value);
11363                     g_value_reset (&value);
11364
11365                     gst_buffer_unref (block);
11366
11367                     index += block_size;
11368                   }
11369
11370                   /* only append the metadata if we successfully read all of it */
11371                   if (is_last) {
11372                     gst_structure_set_value (gst_caps_get_structure (CUR_STREAM
11373                             (stream)->caps, 0), "streamheader", &array);
11374                   } else {
11375                     GST_WARNING_OBJECT (qtdemux,
11376                         "discarding all METADATA_BLOCKs due to invalid "
11377                         "block_size %d at idx %d, rem %d", block_size, index,
11378                         remainder);
11379                   }
11380
11381                   g_value_unset (&value);
11382                   g_value_unset (&array);
11383
11384                   /* The sample rate obtained from the stsd may not be accurate
11385                    * since it cannot represent rates greater than 65535Hz, so
11386                    * override that value with the sample rate from the
11387                    * METADATA_BLOCK_STREAMINFO block */
11388                   CUR_STREAM (stream)->rate =
11389                       (QT_UINT32 (metadata_blocks + 14) >> 12) & 0xFFFFF;
11390                 }
11391               }
11392             }
11393             break;
11394           }
11395           case FOURCC_sawb:
11396             /* Fallthrough! */
11397             amrwb = TRUE;
11398           case FOURCC_samr:
11399           {
11400             gint len = QT_UINT32 (stsd_entry_data);
11401
11402             if (len > 0x24) {
11403               GstBuffer *buf = gst_buffer_new_and_alloc (len - 0x24);
11404               guint bitrate;
11405
11406               gst_buffer_fill (buf, 0, stsd_entry_data + 0x24, len - 0x24);
11407
11408               /* If we have enough data, let's try to get the 'damr' atom. See
11409                * the 3GPP container spec (26.244) for more details. */
11410               if ((len - 0x34) > 8 &&
11411                   (bitrate = qtdemux_parse_amr_bitrate (buf, amrwb))) {
11412                 gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
11413                     GST_TAG_MAXIMUM_BITRATE, bitrate, NULL);
11414               }
11415
11416               gst_caps_set_simple (entry->caps,
11417                   "codec_data", GST_TYPE_BUFFER, buf, NULL);
11418               gst_buffer_unref (buf);
11419             }
11420             break;
11421           }
11422           case FOURCC_mp4a:
11423           {
11424             /* mp4a atom withtout ESDS; Attempt to build codec data from atom */
11425             gint len = QT_UINT32 (stsd_entry_data);
11426
11427             if (len >= 34) {
11428               guint16 sound_version = QT_UINT16 (stsd_entry_data + 16);
11429
11430               if (sound_version == 1) {
11431                 guint16 channels = QT_UINT16 (stsd_entry_data + 24);
11432                 guint32 time_scale = QT_UINT32 (stsd_entry_data + 30);
11433                 guint8 codec_data[2];
11434                 GstBuffer *buf;
11435                 gint profile = 2;       /* FIXME: Can this be determined somehow? There doesn't seem to be anything in mp4a atom that specifis compression */
11436
11437                 gint sample_rate_index =
11438                     gst_codec_utils_aac_get_index_from_sample_rate (time_scale);
11439
11440                 /* build AAC codec data */
11441                 codec_data[0] = profile << 3;
11442                 codec_data[0] |= ((sample_rate_index >> 1) & 0x7);
11443                 codec_data[1] = (sample_rate_index & 0x01) << 7;
11444                 codec_data[1] |= (channels & 0xF) << 3;
11445
11446                 buf = gst_buffer_new_and_alloc (2);
11447                 gst_buffer_fill (buf, 0, codec_data, 2);
11448                 gst_caps_set_simple (entry->caps,
11449                     "codec_data", GST_TYPE_BUFFER, buf, NULL);
11450                 gst_buffer_unref (buf);
11451               }
11452             }
11453             break;
11454           }
11455           default:
11456             GST_INFO_OBJECT (qtdemux,
11457                 "unhandled type %" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (fourcc));
11458             break;
11459         }
11460       }
11461       GST_INFO_OBJECT (qtdemux,
11462           "type %" GST_FOURCC_FORMAT " caps %" GST_PTR_FORMAT,
11463           GST_FOURCC_ARGS (fourcc), entry->caps);
11464
11465     } else if (stream->subtype == FOURCC_strm) {
11466       if (fourcc == FOURCC_rtsp) {
11467         stream->redirect_uri = qtdemux_get_rtsp_uri_from_hndl (qtdemux, minf);
11468       } else {
11469         GST_INFO_OBJECT (qtdemux, "unhandled stream type %" GST_FOURCC_FORMAT,
11470             GST_FOURCC_ARGS (fourcc));
11471         goto unknown_stream;
11472       }
11473       entry->sampled = TRUE;
11474     } else if (stream->subtype == FOURCC_subp || stream->subtype == FOURCC_text
11475         || stream->subtype == FOURCC_sbtl || stream->subtype == FOURCC_subt) {
11476
11477       entry->sampled = TRUE;
11478       entry->sparse = TRUE;
11479
11480       entry->caps =
11481           qtdemux_sub_caps (qtdemux, stream, entry, fourcc, stsd_entry_data,
11482           &codec);
11483       if (codec) {
11484         gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
11485             GST_TAG_SUBTITLE_CODEC, codec, NULL);
11486         g_free (codec);
11487         codec = NULL;
11488       }
11489
11490       /* hunt for sort-of codec data */
11491       switch (fourcc) {
11492         case FOURCC_mp4s:
11493         {
11494           GNode *mp4s = NULL;
11495           GNode *esds = NULL;
11496
11497           /* look for palette in a stsd->mp4s->esds sub-atom */
11498           mp4s = qtdemux_tree_get_child_by_type (stsd, FOURCC_mp4s);
11499           if (mp4s)
11500             esds = qtdemux_tree_get_child_by_type (mp4s, FOURCC_esds);
11501           if (esds == NULL) {
11502             /* Invalid STSD */
11503             GST_LOG_OBJECT (qtdemux, "Skipping invalid stsd: no esds child");
11504             break;
11505           }
11506
11507           gst_qtdemux_handle_esds (qtdemux, stream, entry, esds,
11508               stream->stream_tags);
11509           break;
11510         }
11511         default:
11512           GST_INFO_OBJECT (qtdemux,
11513               "unhandled type %" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (fourcc));
11514           break;
11515       }
11516       GST_INFO_OBJECT (qtdemux,
11517           "type %" GST_FOURCC_FORMAT " caps %" GST_PTR_FORMAT,
11518           GST_FOURCC_ARGS (fourcc), entry->caps);
11519     } else {
11520       /* everything in 1 sample */
11521       entry->sampled = TRUE;
11522
11523       entry->caps =
11524           qtdemux_generic_caps (qtdemux, stream, entry, fourcc, stsd_entry_data,
11525           &codec);
11526
11527       if (entry->caps == NULL)
11528         goto unknown_stream;
11529
11530       if (codec) {
11531         gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
11532             GST_TAG_SUBTITLE_CODEC, codec, NULL);
11533         g_free (codec);
11534         codec = NULL;
11535       }
11536     }
11537
11538     /* promote to sampled format */
11539     if (entry->fourcc == FOURCC_samr) {
11540       /* force mono 8000 Hz for AMR */
11541       entry->sampled = TRUE;
11542       entry->n_channels = 1;
11543       entry->rate = 8000;
11544     } else if (entry->fourcc == FOURCC_sawb) {
11545       /* force mono 16000 Hz for AMR-WB */
11546       entry->sampled = TRUE;
11547       entry->n_channels = 1;
11548       entry->rate = 16000;
11549     } else if (entry->fourcc == FOURCC_mp4a) {
11550       entry->sampled = TRUE;
11551     }
11552
11553
11554     stsd_entry_data += len;
11555     remaining_stsd_len -= len;
11556
11557   }
11558
11559   /* collect sample information */
11560   if (!qtdemux_stbl_init (qtdemux, stream, stbl))
11561     goto samples_failed;
11562
11563   if (qtdemux->fragmented) {
11564     guint64 offset;
11565
11566     /* need all moov samples as basis; probably not many if any at all */
11567     /* prevent moof parsing taking of at this time */
11568     offset = qtdemux->moof_offset;
11569     qtdemux->moof_offset = 0;
11570     if (stream->n_samples &&
11571         !qtdemux_parse_samples (qtdemux, stream, stream->n_samples - 1)) {
11572       qtdemux->moof_offset = offset;
11573       goto samples_failed;
11574     }
11575     qtdemux->moof_offset = 0;
11576     /* movie duration more reliable in this case (e.g. mehd) */
11577     if (qtdemux->segment.duration &&
11578         GST_CLOCK_TIME_IS_VALID (qtdemux->segment.duration))
11579       stream->duration =
11580           GSTTIME_TO_QTSTREAMTIME (stream, qtdemux->segment.duration);
11581   }
11582
11583   /* configure segments */
11584   if (!qtdemux_parse_segments (qtdemux, stream, trak))
11585     goto segments_failed;
11586
11587   /* add some language tag, if useful */
11588   if (stream->lang_id[0] != '\0' && strcmp (stream->lang_id, "unk") &&
11589       strcmp (stream->lang_id, "und")) {
11590     const gchar *lang_code;
11591
11592     /* convert ISO 639-2 code to ISO 639-1 */
11593     lang_code = gst_tag_get_language_code (stream->lang_id);
11594     gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
11595         GST_TAG_LANGUAGE_CODE, (lang_code) ? lang_code : stream->lang_id, NULL);
11596   }
11597
11598   /* Check for UDTA tags */
11599   if ((udta = qtdemux_tree_get_child_by_type (trak, FOURCC_udta))) {
11600     qtdemux_parse_udta (qtdemux, stream->stream_tags, udta);
11601   }
11602
11603   /* now we are ready to add the stream */
11604   if (qtdemux->n_streams >= GST_QTDEMUX_MAX_STREAMS)
11605     goto too_many_streams;
11606
11607   if (!qtdemux->got_moov) {
11608     qtdemux->streams[qtdemux->n_streams] = stream;
11609     qtdemux->n_streams++;
11610     GST_DEBUG_OBJECT (qtdemux, "n_streams is now %d", qtdemux->n_streams);
11611   }
11612
11613   return TRUE;
11614
11615 /* ERRORS */
11616 skip_track:
11617   {
11618     GST_INFO_OBJECT (qtdemux, "skip disabled track");
11619     if (new_stream)
11620       gst_qtdemux_stream_free (qtdemux, stream);
11621     return TRUE;
11622   }
11623 corrupt_file:
11624   {
11625     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
11626         (_("This file is corrupt and cannot be played.")), (NULL));
11627     if (new_stream)
11628       gst_qtdemux_stream_free (qtdemux, stream);
11629     return FALSE;
11630   }
11631 error_encrypted:
11632   {
11633     GST_ELEMENT_ERROR (qtdemux, STREAM, DECRYPT, (NULL), (NULL));
11634     if (new_stream)
11635       gst_qtdemux_stream_free (qtdemux, stream);
11636     return FALSE;
11637   }
11638 samples_failed:
11639 segments_failed:
11640   {
11641     /* we posted an error already */
11642     /* free stbl sub-atoms */
11643     gst_qtdemux_stbl_free (stream);
11644     if (new_stream)
11645       gst_qtdemux_stream_free (qtdemux, stream);
11646     return FALSE;
11647   }
11648 existing_stream:
11649   {
11650     GST_INFO_OBJECT (qtdemux, "stream with track id %i already exists",
11651         track_id);
11652     if (new_stream)
11653       gst_qtdemux_stream_free (qtdemux, stream);
11654     return TRUE;
11655   }
11656 unknown_stream:
11657   {
11658     GST_INFO_OBJECT (qtdemux, "unknown subtype %" GST_FOURCC_FORMAT,
11659         GST_FOURCC_ARGS (stream->subtype));
11660     if (new_stream)
11661       gst_qtdemux_stream_free (qtdemux, stream);
11662     return TRUE;
11663   }
11664 too_many_streams:
11665   {
11666     GST_ELEMENT_WARNING (qtdemux, STREAM, DEMUX,
11667         (_("This file contains too many streams. Only playing first %d"),
11668             GST_QTDEMUX_MAX_STREAMS), (NULL));
11669     return TRUE;
11670   }
11671 }
11672
11673 /* If we can estimate the overall bitrate, and don't have information about the
11674  * stream bitrate for exactly one stream, this guesses the stream bitrate as
11675  * the overall bitrate minus the sum of the bitrates of all other streams. This
11676  * should be useful for the common case where we have one audio and one video
11677  * stream and can estimate the bitrate of one, but not the other. */
11678 static void
11679 gst_qtdemux_guess_bitrate (GstQTDemux * qtdemux)
11680 {
11681   QtDemuxStream *stream = NULL;
11682   gint64 size, sys_bitrate, sum_bitrate = 0;
11683   GstClockTime duration;
11684   gint i;
11685   guint bitrate;
11686
11687   if (qtdemux->fragmented)
11688     return;
11689
11690   GST_DEBUG_OBJECT (qtdemux, "Looking for streams with unknown bitrate");
11691
11692   if (!gst_pad_peer_query_duration (qtdemux->sinkpad, GST_FORMAT_BYTES, &size)
11693       || size <= 0) {
11694     GST_DEBUG_OBJECT (qtdemux,
11695         "Size in bytes of the stream not known - bailing");
11696     return;
11697   }
11698
11699   /* Subtract the header size */
11700   GST_DEBUG_OBJECT (qtdemux, "Total size %" G_GINT64_FORMAT ", header size %u",
11701       size, qtdemux->header_size);
11702
11703   if (size < qtdemux->header_size)
11704     return;
11705
11706   size = size - qtdemux->header_size;
11707
11708   if (!gst_qtdemux_get_duration (qtdemux, &duration)) {
11709     GST_DEBUG_OBJECT (qtdemux, "Stream duration not known - bailing");
11710     return;
11711   }
11712
11713   for (i = 0; i < qtdemux->n_streams; i++) {
11714     switch (qtdemux->streams[i]->subtype) {
11715       case FOURCC_soun:
11716       case FOURCC_vide:
11717         GST_DEBUG_OBJECT (qtdemux, "checking bitrate for %" GST_PTR_FORMAT,
11718             CUR_STREAM (qtdemux->streams[i])->caps);
11719         /* retrieve bitrate, prefer avg then max */
11720         bitrate = 0;
11721         if (qtdemux->streams[i]->stream_tags) {
11722           gst_tag_list_get_uint (qtdemux->streams[i]->stream_tags,
11723               GST_TAG_MAXIMUM_BITRATE, &bitrate);
11724           GST_DEBUG_OBJECT (qtdemux, "max-bitrate: %u", bitrate);
11725           gst_tag_list_get_uint (qtdemux->streams[i]->stream_tags,
11726               GST_TAG_NOMINAL_BITRATE, &bitrate);
11727           GST_DEBUG_OBJECT (qtdemux, "nominal-bitrate: %u", bitrate);
11728           gst_tag_list_get_uint (qtdemux->streams[i]->stream_tags,
11729               GST_TAG_BITRATE, &bitrate);
11730           GST_DEBUG_OBJECT (qtdemux, "bitrate: %u", bitrate);
11731         }
11732         if (bitrate)
11733           sum_bitrate += bitrate;
11734         else {
11735           if (stream) {
11736             GST_DEBUG_OBJECT (qtdemux,
11737                 ">1 stream with unknown bitrate - bailing");
11738             return;
11739           } else
11740             stream = qtdemux->streams[i];
11741         }
11742
11743       default:
11744         /* For other subtypes, we assume no significant impact on bitrate */
11745         break;
11746     }
11747   }
11748
11749   if (!stream) {
11750     GST_DEBUG_OBJECT (qtdemux, "All stream bitrates are known");
11751     return;
11752   }
11753
11754   sys_bitrate = gst_util_uint64_scale (size, GST_SECOND * 8, duration);
11755
11756   if (sys_bitrate < sum_bitrate) {
11757     /* This can happen, since sum_bitrate might be derived from maximum
11758      * bitrates and not average bitrates */
11759     GST_DEBUG_OBJECT (qtdemux,
11760         "System bitrate less than sum bitrate - bailing");
11761     return;
11762   }
11763
11764   bitrate = sys_bitrate - sum_bitrate;
11765   GST_DEBUG_OBJECT (qtdemux, "System bitrate = %" G_GINT64_FORMAT
11766       ", Stream bitrate = %u", sys_bitrate, bitrate);
11767
11768   if (!stream->stream_tags)
11769     stream->stream_tags = gst_tag_list_new_empty ();
11770   else
11771     stream->stream_tags = gst_tag_list_make_writable (stream->stream_tags);
11772
11773   gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
11774       GST_TAG_BITRATE, bitrate, NULL);
11775 }
11776
11777 static GstFlowReturn
11778 qtdemux_prepare_streams (GstQTDemux * qtdemux)
11779 {
11780   gint i;
11781   GstFlowReturn ret = GST_FLOW_OK;
11782
11783   GST_DEBUG_OBJECT (qtdemux, "prepare streams");
11784
11785   for (i = 0; ret == GST_FLOW_OK && i < qtdemux->n_streams; i++) {
11786     QtDemuxStream *stream = qtdemux->streams[i];
11787     guint32 sample_num = 0;
11788
11789     GST_DEBUG_OBJECT (qtdemux, "stream %d, id %d, fourcc %" GST_FOURCC_FORMAT,
11790         i, stream->track_id, GST_FOURCC_ARGS (CUR_STREAM (stream)->fourcc));
11791
11792     if (qtdemux->fragmented) {
11793       /* need all moov samples first */
11794       GST_OBJECT_LOCK (qtdemux);
11795       while (stream->n_samples == 0)
11796         if ((ret = qtdemux_add_fragmented_samples (qtdemux)) != GST_FLOW_OK)
11797           break;
11798       GST_OBJECT_UNLOCK (qtdemux);
11799     } else {
11800       /* discard any stray moof */
11801       qtdemux->moof_offset = 0;
11802     }
11803
11804     /* prepare braking */
11805     if (ret != GST_FLOW_ERROR)
11806       ret = GST_FLOW_OK;
11807
11808     /* in pull mode, we should have parsed some sample info by now;
11809      * and quite some code will not handle no samples.
11810      * in push mode, we'll just have to deal with it */
11811     if (G_UNLIKELY (qtdemux->pullbased && !stream->n_samples)) {
11812       GST_DEBUG_OBJECT (qtdemux, "no samples for stream; discarding");
11813       gst_qtdemux_remove_stream (qtdemux, i);
11814       i--;
11815       continue;
11816     }
11817
11818     /* parse the initial sample for use in setting the frame rate cap */
11819     while (sample_num == 0 && sample_num < stream->n_samples) {
11820       if (!qtdemux_parse_samples (qtdemux, stream, sample_num))
11821         break;
11822       ++sample_num;
11823     }
11824     if (stream->n_samples > 0 && stream->stbl_index >= 0) {
11825       stream->first_duration = stream->samples[0].duration;
11826       GST_LOG_OBJECT (qtdemux, "stream %d first duration %u",
11827           stream->track_id, stream->first_duration);
11828     }
11829   }
11830
11831   return ret;
11832 }
11833
11834 static GstFlowReturn
11835 qtdemux_expose_streams (GstQTDemux * qtdemux)
11836 {
11837   gint i;
11838   GSList *oldpads = NULL;
11839   GSList *iter;
11840
11841   GST_DEBUG_OBJECT (qtdemux, "exposing streams");
11842
11843   for (i = 0; i < qtdemux->n_streams; i++) {
11844     QtDemuxStream *stream = qtdemux->streams[i];
11845     GstPad *oldpad = stream->pad;
11846     GstTagList *list;
11847
11848     GST_DEBUG_OBJECT (qtdemux, "stream %d, id %d, fourcc %" GST_FOURCC_FORMAT,
11849         i, stream->track_id, GST_FOURCC_ARGS (CUR_STREAM (stream)->fourcc));
11850
11851     if ((stream->subtype == FOURCC_text || stream->subtype == FOURCC_sbtl) &&
11852         stream->track_id == qtdemux->chapters_track_id) {
11853       /* TODO - parse chapters track and expose it as GstToc; For now just ignore it
11854          so that it doesn't look like a subtitle track */
11855       gst_qtdemux_remove_stream (qtdemux, i);
11856       i--;
11857       continue;
11858     }
11859
11860     /* now we have all info and can expose */
11861     list = stream->stream_tags;
11862     stream->stream_tags = NULL;
11863     if (oldpad)
11864       oldpads = g_slist_prepend (oldpads, oldpad);
11865     if (!gst_qtdemux_add_stream (qtdemux, stream, list))
11866       return GST_FLOW_ERROR;
11867   }
11868
11869   gst_qtdemux_guess_bitrate (qtdemux);
11870
11871   gst_element_no_more_pads (GST_ELEMENT_CAST (qtdemux));
11872
11873   for (iter = oldpads; iter; iter = g_slist_next (iter)) {
11874     GstPad *oldpad = iter->data;
11875     GstEvent *event;
11876
11877     event = gst_event_new_eos ();
11878     if (qtdemux->segment_seqnum)
11879       gst_event_set_seqnum (event, qtdemux->segment_seqnum);
11880
11881     gst_pad_push_event (oldpad, event);
11882     gst_pad_set_active (oldpad, FALSE);
11883     gst_element_remove_pad (GST_ELEMENT (qtdemux), oldpad);
11884     gst_flow_combiner_remove_pad (qtdemux->flowcombiner, oldpad);
11885     gst_object_unref (oldpad);
11886   }
11887
11888   /* check if we should post a redirect in case there is a single trak
11889    * and it is a redirecting trak */
11890   if (qtdemux->n_streams == 1 && qtdemux->streams[0]->redirect_uri != NULL) {
11891     GstMessage *m;
11892
11893     GST_INFO_OBJECT (qtdemux, "Issuing a redirect due to a single track with "
11894         "an external content");
11895     m = gst_message_new_element (GST_OBJECT_CAST (qtdemux),
11896         gst_structure_new ("redirect",
11897             "new-location", G_TYPE_STRING, qtdemux->streams[0]->redirect_uri,
11898             NULL));
11899     gst_element_post_message (GST_ELEMENT_CAST (qtdemux), m);
11900     qtdemux->posted_redirect = TRUE;
11901   }
11902
11903   for (i = 0; i < qtdemux->n_streams; i++) {
11904     QtDemuxStream *stream = qtdemux->streams[i];
11905
11906     qtdemux_do_allocation (qtdemux, stream);
11907   }
11908
11909   qtdemux->exposed = TRUE;
11910   return GST_FLOW_OK;
11911 }
11912
11913 /* check if major or compatible brand is 3GP */
11914 static inline gboolean
11915 qtdemux_is_brand_3gp (GstQTDemux * qtdemux, gboolean major)
11916 {
11917   if (major) {
11918     return ((qtdemux->major_brand & GST_MAKE_FOURCC (255, 255, 0, 0)) ==
11919         FOURCC_3g__);
11920   } else if (qtdemux->comp_brands != NULL) {
11921     GstMapInfo map;
11922     guint8 *data;
11923     gsize size;
11924     gboolean res = FALSE;
11925
11926     gst_buffer_map (qtdemux->comp_brands, &map, GST_MAP_READ);
11927     data = map.data;
11928     size = map.size;
11929     while (size >= 4) {
11930       res = res || ((QT_FOURCC (data) & GST_MAKE_FOURCC (255, 255, 0, 0)) ==
11931           FOURCC_3g__);
11932       data += 4;
11933       size -= 4;
11934     }
11935     gst_buffer_unmap (qtdemux->comp_brands, &map);
11936     return res;
11937   } else {
11938     return FALSE;
11939   }
11940 }
11941
11942 /* check if tag is a spec'ed 3GP tag keyword storing a string */
11943 static inline gboolean
11944 qtdemux_is_string_tag_3gp (GstQTDemux * qtdemux, guint32 fourcc)
11945 {
11946   return fourcc == FOURCC_cprt || fourcc == FOURCC_gnre || fourcc == FOURCC_titl
11947       || fourcc == FOURCC_dscp || fourcc == FOURCC_perf || fourcc == FOURCC_auth
11948       || fourcc == FOURCC_albm;
11949 }
11950
11951 static void
11952 qtdemux_tag_add_location (GstQTDemux * qtdemux, GstTagList * taglist,
11953     const char *tag, const char *dummy, GNode * node)
11954 {
11955   const gchar *env_vars[] = { "GST_QT_TAG_ENCODING", "GST_TAG_ENCODING", NULL };
11956   int offset;
11957   char *name;
11958   gchar *data;
11959   gdouble longitude, latitude, altitude;
11960   gint len;
11961
11962   len = QT_UINT32 (node->data);
11963   if (len <= 14)
11964     goto short_read;
11965
11966   data = node->data;
11967   offset = 14;
11968
11969   /* TODO: language code skipped */
11970
11971   name = gst_tag_freeform_string_to_utf8 (data + offset, -1, env_vars);
11972
11973   if (!name) {
11974     /* do not alarm in trivial case, but bail out otherwise */
11975     if (*(data + offset) != 0) {
11976       GST_DEBUG_OBJECT (qtdemux, "failed to convert %s tag to UTF-8, "
11977           "giving up", tag);
11978     }
11979   } else {
11980     gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE,
11981         GST_TAG_GEO_LOCATION_NAME, name, NULL);
11982     offset += strlen (name);
11983     g_free (name);
11984   }
11985
11986   if (len < offset + 2 + 4 + 4 + 4)
11987     goto short_read;
11988
11989   /* +1 +1 = skip null-terminator and location role byte */
11990   offset += 1 + 1;
11991   /* table in spec says unsigned, semantics say negative has meaning ... */
11992   longitude = QT_SFP32 (data + offset);
11993
11994   offset += 4;
11995   latitude = QT_SFP32 (data + offset);
11996
11997   offset += 4;
11998   altitude = QT_SFP32 (data + offset);
11999
12000   /* one invalid means all are invalid */
12001   if (longitude >= -180.0 && longitude <= 180.0 &&
12002       latitude >= -90.0 && latitude <= 90.0) {
12003     gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE,
12004         GST_TAG_GEO_LOCATION_LATITUDE, latitude,
12005         GST_TAG_GEO_LOCATION_LONGITUDE, longitude,
12006         GST_TAG_GEO_LOCATION_ELEVATION, altitude, NULL);
12007   }
12008
12009   /* TODO: no GST_TAG_, so astronomical body and additional notes skipped */
12010
12011   return;
12012
12013   /* ERRORS */
12014 short_read:
12015   {
12016     GST_DEBUG_OBJECT (qtdemux, "short read parsing 3GP location");
12017     return;
12018   }
12019 }
12020
12021
12022 static void
12023 qtdemux_tag_add_year (GstQTDemux * qtdemux, GstTagList * taglist,
12024     const char *tag, const char *dummy, GNode * node)
12025 {
12026   guint16 y;
12027   GDate *date;
12028   gint len;
12029
12030   len = QT_UINT32 (node->data);
12031   if (len < 14)
12032     return;
12033
12034   y = QT_UINT16 ((guint8 *) node->data + 12);
12035   if (y == 0) {
12036     GST_DEBUG_OBJECT (qtdemux, "year: %u is not a valid year", y);
12037     return;
12038   }
12039   GST_DEBUG_OBJECT (qtdemux, "year: %u", y);
12040
12041   date = g_date_new_dmy (1, 1, y);
12042   gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag, date, NULL);
12043   g_date_free (date);
12044 }
12045
12046 static void
12047 qtdemux_tag_add_classification (GstQTDemux * qtdemux, GstTagList * taglist,
12048     const char *tag, const char *dummy, GNode * node)
12049 {
12050   int offset;
12051   char *tag_str = NULL;
12052   guint8 *entity;
12053   guint16 table;
12054   gint len;
12055
12056   len = QT_UINT32 (node->data);
12057   if (len <= 20)
12058     goto short_read;
12059
12060   offset = 12;
12061   entity = (guint8 *) node->data + offset;
12062   if (entity[0] == 0 || entity[1] == 0 || entity[2] == 0 || entity[3] == 0) {
12063     GST_DEBUG_OBJECT (qtdemux,
12064         "classification info: %c%c%c%c invalid classification entity",
12065         entity[0], entity[1], entity[2], entity[3]);
12066     return;
12067   }
12068
12069   offset += 4;
12070   table = QT_UINT16 ((guint8 *) node->data + offset);
12071
12072   /* Language code skipped */
12073
12074   offset += 4;
12075
12076   /* Tag format: "XXXX://Y[YYYY]/classification info string"
12077    * XXXX: classification entity, fixed length 4 chars.
12078    * Y[YYYY]: classification table, max 5 chars.
12079    */
12080   tag_str = g_strdup_printf ("----://%u/%s",
12081       table, (char *) node->data + offset);
12082
12083   /* memcpy To be sure we're preserving byte order */
12084   memcpy (tag_str, entity, 4);
12085   GST_DEBUG_OBJECT (qtdemux, "classification info: %s", tag_str);
12086
12087   gst_tag_list_add (taglist, GST_TAG_MERGE_APPEND, tag, tag_str, NULL);
12088
12089   g_free (tag_str);
12090
12091   return;
12092
12093   /* ERRORS */
12094 short_read:
12095   {
12096     GST_DEBUG_OBJECT (qtdemux, "short read parsing 3GP classification");
12097     return;
12098   }
12099 }
12100
12101 static gboolean
12102 qtdemux_tag_add_str_full (GstQTDemux * qtdemux, GstTagList * taglist,
12103     const char *tag, const char *dummy, GNode * node)
12104 {
12105   const gchar *env_vars[] = { "GST_QT_TAG_ENCODING", "GST_TAG_ENCODING", NULL };
12106   GNode *data;
12107   char *s;
12108   int len;
12109   guint32 type;
12110   int offset;
12111   gboolean ret = TRUE;
12112   const gchar *charset = NULL;
12113
12114   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
12115   if (data) {
12116     len = QT_UINT32 (data->data);
12117     type = QT_UINT32 ((guint8 *) data->data + 8);
12118     if (type == 0x00000001 && len > 16) {
12119       s = gst_tag_freeform_string_to_utf8 ((char *) data->data + 16, len - 16,
12120           env_vars);
12121       if (s) {
12122         GST_DEBUG_OBJECT (qtdemux, "adding tag %s", GST_STR_NULL (s));
12123         gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag, s, NULL);
12124         g_free (s);
12125       } else {
12126         GST_DEBUG_OBJECT (qtdemux, "failed to convert %s tag to UTF-8", tag);
12127       }
12128     }
12129   } else {
12130     len = QT_UINT32 (node->data);
12131     type = QT_UINT32 ((guint8 *) node->data + 4);
12132     if ((type >> 24) == 0xa9 && len > 8 + 4) {
12133       gint str_len;
12134       gint lang_code;
12135
12136       /* Type starts with the (C) symbol, so the next data is a list
12137        * of (string size(16), language code(16), string) */
12138
12139       str_len = QT_UINT16 ((guint8 *) node->data + 8);
12140       lang_code = QT_UINT16 ((guint8 *) node->data + 10);
12141
12142       /* the string + fourcc + size + 2 16bit fields,
12143        * means that there are more tags in this atom */
12144       if (len > str_len + 8 + 4) {
12145         /* TODO how to represent the same tag in different languages? */
12146         GST_WARNING_OBJECT (qtdemux, "Ignoring metadata entry with multiple "
12147             "text alternatives, reading only first one");
12148       }
12149
12150       offset = 12;
12151       len = MIN (len, str_len + 8 + 4); /* remove trailing strings that we don't use */
12152       GST_DEBUG_OBJECT (qtdemux, "found international text tag");
12153
12154       if (lang_code < 0x800) {  /* MAC encoded string */
12155         charset = "mac";
12156       }
12157     } else if (len > 14 && qtdemux_is_string_tag_3gp (qtdemux,
12158             QT_FOURCC ((guint8 *) node->data + 4))) {
12159       guint32 type = QT_UINT32 ((guint8 *) node->data + 8);
12160
12161       /* we go for 3GP style encoding if major brands claims so,
12162        * or if no hope for data be ok UTF-8, and compatible 3GP brand present */
12163       if (qtdemux_is_brand_3gp (qtdemux, TRUE) ||
12164           (qtdemux_is_brand_3gp (qtdemux, FALSE) &&
12165               ((type & 0x00FFFFFF) == 0x0) && (type >> 24 <= 0xF))) {
12166         offset = 14;
12167         /* 16-bit Language code is ignored here as well */
12168         GST_DEBUG_OBJECT (qtdemux, "found 3gpp text tag");
12169       } else {
12170         goto normal;
12171       }
12172     } else {
12173     normal:
12174       offset = 8;
12175       GST_DEBUG_OBJECT (qtdemux, "found normal text tag");
12176       ret = FALSE;              /* may have to fallback */
12177     }
12178     if (charset) {
12179       GError *err = NULL;
12180
12181       s = g_convert ((gchar *) node->data + offset, len - offset, "utf8",
12182           charset, NULL, NULL, &err);
12183       if (err) {
12184         GST_DEBUG_OBJECT (qtdemux, "Failed to convert string from charset %s:"
12185             " %s(%d): %s", charset, g_quark_to_string (err->domain), err->code,
12186             err->message);
12187         g_error_free (err);
12188       }
12189     } else {
12190       s = gst_tag_freeform_string_to_utf8 ((char *) node->data + offset,
12191           len - offset, env_vars);
12192     }
12193     if (s) {
12194       GST_DEBUG_OBJECT (qtdemux, "adding tag %s", GST_STR_NULL (s));
12195       gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag, s, NULL);
12196       g_free (s);
12197       ret = TRUE;
12198     } else {
12199       GST_DEBUG_OBJECT (qtdemux, "failed to convert %s tag to UTF-8", tag);
12200     }
12201   }
12202   return ret;
12203 }
12204
12205 static void
12206 qtdemux_tag_add_str (GstQTDemux * qtdemux, GstTagList * taglist,
12207     const char *tag, const char *dummy, GNode * node)
12208 {
12209   qtdemux_tag_add_str_full (qtdemux, taglist, tag, dummy, node);
12210 }
12211
12212 static void
12213 qtdemux_tag_add_keywords (GstQTDemux * qtdemux, GstTagList * taglist,
12214     const char *tag, const char *dummy, GNode * node)
12215 {
12216   const gchar *env_vars[] = { "GST_QT_TAG_ENCODING", "GST_TAG_ENCODING", NULL };
12217   guint8 *data;
12218   char *s, *t, *k = NULL;
12219   int len;
12220   int offset;
12221   int count;
12222
12223   /* first try normal string tag if major brand not 3GP */
12224   if (!qtdemux_is_brand_3gp (qtdemux, TRUE)) {
12225     if (!qtdemux_tag_add_str_full (qtdemux, taglist, tag, dummy, node)) {
12226       /* hm, that did not work, maybe 3gpp storage in non-3gpp major brand;
12227        * let's try it 3gpp way after minor safety check */
12228       data = node->data;
12229       if (QT_UINT32 (data) < 15 || !qtdemux_is_brand_3gp (qtdemux, FALSE))
12230         return;
12231     } else
12232       return;
12233   }
12234
12235   GST_DEBUG_OBJECT (qtdemux, "found 3gpp keyword tag");
12236
12237   data = node->data;
12238
12239   len = QT_UINT32 (data);
12240   if (len < 15)
12241     goto short_read;
12242
12243   count = QT_UINT8 (data + 14);
12244   offset = 15;
12245   for (; count; count--) {
12246     gint slen;
12247
12248     if (offset + 1 > len)
12249       goto short_read;
12250     slen = QT_UINT8 (data + offset);
12251     offset += 1;
12252     if (offset + slen > len)
12253       goto short_read;
12254     s = gst_tag_freeform_string_to_utf8 ((char *) node->data + offset,
12255         slen, env_vars);
12256     if (s) {
12257       GST_DEBUG_OBJECT (qtdemux, "adding keyword %s", GST_STR_NULL (s));
12258       if (k) {
12259         t = g_strjoin (",", k, s, NULL);
12260         g_free (s);
12261         g_free (k);
12262         k = t;
12263       } else {
12264         k = s;
12265       }
12266     } else {
12267       GST_DEBUG_OBJECT (qtdemux, "failed to convert keyword to UTF-8");
12268     }
12269     offset += slen;
12270   }
12271
12272 done:
12273   if (k) {
12274     GST_DEBUG_OBJECT (qtdemux, "adding tag %s", GST_STR_NULL (k));
12275     gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag, k, NULL);
12276   }
12277   g_free (k);
12278
12279   return;
12280
12281   /* ERRORS */
12282 short_read:
12283   {
12284     GST_DEBUG_OBJECT (qtdemux, "short read parsing 3GP keywords");
12285     goto done;
12286   }
12287 }
12288
12289 static void
12290 qtdemux_tag_add_num (GstQTDemux * qtdemux, GstTagList * taglist,
12291     const char *tag1, const char *tag2, GNode * node)
12292 {
12293   GNode *data;
12294   int len;
12295   int type;
12296   int n1, n2;
12297
12298   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
12299   if (data) {
12300     len = QT_UINT32 (data->data);
12301     type = QT_UINT32 ((guint8 *) data->data + 8);
12302     if (type == 0x00000000 && len >= 22) {
12303       n1 = QT_UINT16 ((guint8 *) data->data + 18);
12304       n2 = QT_UINT16 ((guint8 *) data->data + 20);
12305       if (n1 > 0) {
12306         GST_DEBUG_OBJECT (qtdemux, "adding tag %s=%d", tag1, n1);
12307         gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag1, n1, NULL);
12308       }
12309       if (n2 > 0) {
12310         GST_DEBUG_OBJECT (qtdemux, "adding tag %s=%d", tag2, n2);
12311         gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag2, n2, NULL);
12312       }
12313     }
12314   }
12315 }
12316
12317 static void
12318 qtdemux_tag_add_tmpo (GstQTDemux * qtdemux, GstTagList * taglist,
12319     const char *tag1, const char *dummy, GNode * node)
12320 {
12321   GNode *data;
12322   int len;
12323   int type;
12324   int n1;
12325
12326   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
12327   if (data) {
12328     len = QT_UINT32 (data->data);
12329     type = QT_UINT32 ((guint8 *) data->data + 8);
12330     GST_DEBUG_OBJECT (qtdemux, "have tempo tag, type=%d,len=%d", type, len);
12331     /* some files wrongly have a type 0x0f=15, but it should be 0x15 */
12332     if ((type == 0x00000015 || type == 0x0000000f) && len >= 18) {
12333       n1 = QT_UINT16 ((guint8 *) data->data + 16);
12334       if (n1) {
12335         /* do not add bpm=0 */
12336         GST_DEBUG_OBJECT (qtdemux, "adding tag %d", n1);
12337         gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag1, (gdouble) n1,
12338             NULL);
12339       }
12340     }
12341   }
12342 }
12343
12344 static void
12345 qtdemux_tag_add_uint32 (GstQTDemux * qtdemux, GstTagList * taglist,
12346     const char *tag1, const char *dummy, GNode * node)
12347 {
12348   GNode *data;
12349   int len;
12350   int type;
12351   guint32 num;
12352
12353   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
12354   if (data) {
12355     len = QT_UINT32 (data->data);
12356     type = QT_UINT32 ((guint8 *) data->data + 8);
12357     GST_DEBUG_OBJECT (qtdemux, "have %s tag, type=%d,len=%d", tag1, type, len);
12358     /* some files wrongly have a type 0x0f=15, but it should be 0x15 */
12359     if ((type == 0x00000015 || type == 0x0000000f) && len >= 20) {
12360       num = QT_UINT32 ((guint8 *) data->data + 16);
12361       if (num) {
12362         /* do not add num=0 */
12363         GST_DEBUG_OBJECT (qtdemux, "adding tag %d", num);
12364         gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag1, num, NULL);
12365       }
12366     }
12367   }
12368 }
12369
12370 static void
12371 qtdemux_tag_add_covr (GstQTDemux * qtdemux, GstTagList * taglist,
12372     const char *tag1, const char *dummy, GNode * node)
12373 {
12374   GNode *data;
12375   int len;
12376   int type;
12377   GstSample *sample;
12378
12379   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
12380   if (data) {
12381     len = QT_UINT32 (data->data);
12382     type = QT_UINT32 ((guint8 *) data->data + 8);
12383     GST_DEBUG_OBJECT (qtdemux, "have covr tag, type=%d,len=%d", type, len);
12384     if ((type == 0x0000000d || type == 0x0000000e) && len > 16) {
12385       GstTagImageType image_type;
12386
12387       if (gst_tag_list_get_tag_size (taglist, GST_TAG_IMAGE) == 0)
12388         image_type = GST_TAG_IMAGE_TYPE_FRONT_COVER;
12389       else
12390         image_type = GST_TAG_IMAGE_TYPE_NONE;
12391
12392       if ((sample =
12393               gst_tag_image_data_to_image_sample ((guint8 *) data->data + 16,
12394                   len - 16, image_type))) {
12395         GST_DEBUG_OBJECT (qtdemux, "adding tag size %d", len - 16);
12396         gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag1, sample, NULL);
12397         gst_sample_unref (sample);
12398       }
12399     }
12400   }
12401 }
12402
12403 static void
12404 qtdemux_tag_add_date (GstQTDemux * qtdemux, GstTagList * taglist,
12405     const char *tag, const char *dummy, GNode * node)
12406 {
12407   GNode *data;
12408   char *s;
12409   int len;
12410   int type;
12411
12412   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
12413   if (data) {
12414     len = QT_UINT32 (data->data);
12415     type = QT_UINT32 ((guint8 *) data->data + 8);
12416     if (type == 0x00000001 && len > 16) {
12417       guint y, m = 1, d = 1;
12418       gint ret;
12419
12420       s = g_strndup ((char *) data->data + 16, len - 16);
12421       GST_DEBUG_OBJECT (qtdemux, "adding date '%s'", s);
12422       ret = sscanf (s, "%u-%u-%u", &y, &m, &d);
12423       if (ret >= 1 && y > 1500 && y < 3000) {
12424         GDate *date;
12425
12426         date = g_date_new_dmy (d, m, y);
12427         gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag, date, NULL);
12428         g_date_free (date);
12429       } else {
12430         GST_DEBUG_OBJECT (qtdemux, "could not parse date string '%s'", s);
12431       }
12432       g_free (s);
12433     }
12434   }
12435 }
12436
12437 static void
12438 qtdemux_tag_add_gnre (GstQTDemux * qtdemux, GstTagList * taglist,
12439     const char *tag, const char *dummy, GNode * node)
12440 {
12441   GNode *data;
12442
12443   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
12444
12445   /* re-route to normal string tag if major brand says so
12446    * or no data atom and compatible brand suggests so */
12447   if (qtdemux_is_brand_3gp (qtdemux, TRUE) ||
12448       (qtdemux_is_brand_3gp (qtdemux, FALSE) && !data)) {
12449     qtdemux_tag_add_str (qtdemux, taglist, tag, dummy, node);
12450     return;
12451   }
12452
12453   if (data) {
12454     guint len, type, n;
12455
12456     len = QT_UINT32 (data->data);
12457     type = QT_UINT32 ((guint8 *) data->data + 8);
12458     if (type == 0x00000000 && len >= 18) {
12459       n = QT_UINT16 ((guint8 *) data->data + 16);
12460       if (n > 0) {
12461         const gchar *genre;
12462
12463         genre = gst_tag_id3_genre_get (n - 1);
12464         if (genre != NULL) {
12465           GST_DEBUG_OBJECT (qtdemux, "adding %d [%s]", n, genre);
12466           gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag, genre, NULL);
12467         }
12468       }
12469     }
12470   }
12471 }
12472
12473 static void
12474 qtdemux_add_double_tag_from_str (GstQTDemux * demux, GstTagList * taglist,
12475     const gchar * tag, guint8 * data, guint32 datasize)
12476 {
12477   gdouble value;
12478   gchar *datacopy;
12479
12480   /* make a copy to have \0 at the end */
12481   datacopy = g_strndup ((gchar *) data, datasize);
12482
12483   /* convert the str to double */
12484   if (sscanf (datacopy, "%lf", &value) == 1) {
12485     GST_DEBUG_OBJECT (demux, "adding tag: %s [%s]", tag, datacopy);
12486     gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag, value, NULL);
12487   } else {
12488     GST_WARNING_OBJECT (demux, "Failed to parse double from string: %s",
12489         datacopy);
12490   }
12491   g_free (datacopy);
12492 }
12493
12494
12495 static void
12496 qtdemux_tag_add_revdns (GstQTDemux * demux, GstTagList * taglist,
12497     const char *tag, const char *tag_bis, GNode * node)
12498 {
12499   GNode *mean;
12500   GNode *name;
12501   GNode *data;
12502   guint32 meansize;
12503   guint32 namesize;
12504   guint32 datatype;
12505   guint32 datasize;
12506   const gchar *meanstr;
12507   const gchar *namestr;
12508
12509   /* checking the whole ---- atom size for consistency */
12510   if (QT_UINT32 (node->data) <= 4 + 12 + 12 + 16) {
12511     GST_WARNING_OBJECT (demux, "Tag ---- atom is too small, ignoring");
12512     return;
12513   }
12514
12515   mean = qtdemux_tree_get_child_by_type (node, FOURCC_mean);
12516   if (!mean) {
12517     GST_WARNING_OBJECT (demux, "No 'mean' atom found");
12518     return;
12519   }
12520
12521   meansize = QT_UINT32 (mean->data);
12522   if (meansize <= 12) {
12523     GST_WARNING_OBJECT (demux, "Small mean atom, ignoring the whole tag");
12524     return;
12525   }
12526   meanstr = ((gchar *) mean->data) + 12;
12527   meansize -= 12;
12528
12529   name = qtdemux_tree_get_child_by_type (node, FOURCC_name);
12530   if (!name) {
12531     GST_WARNING_OBJECT (demux, "'name' atom not found, ignoring tag");
12532     return;
12533   }
12534
12535   namesize = QT_UINT32 (name->data);
12536   if (namesize <= 12) {
12537     GST_WARNING_OBJECT (demux, "'name' atom is too small, ignoring tag");
12538     return;
12539   }
12540   namestr = ((gchar *) name->data) + 12;
12541   namesize -= 12;
12542
12543   /*
12544    * Data atom is:
12545    * uint32 - size
12546    * uint32 - name
12547    * uint8  - version
12548    * uint24 - data type
12549    * uint32 - all 0
12550    * rest   - the data
12551    */
12552   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
12553   if (!data) {
12554     GST_WARNING_OBJECT (demux, "No data atom in this tag");
12555     return;
12556   }
12557   datasize = QT_UINT32 (data->data);
12558   if (datasize <= 16) {
12559     GST_WARNING_OBJECT (demux, "Data atom too small");
12560     return;
12561   }
12562   datatype = QT_UINT32 (((gchar *) data->data) + 8) & 0xFFFFFF;
12563
12564   if ((strncmp (meanstr, "com.apple.iTunes", meansize) == 0) ||
12565       (strncmp (meanstr, "org.hydrogenaudio.replaygain", meansize) == 0)) {
12566     static const struct
12567     {
12568       const gchar name[28];
12569       const gchar tag[28];
12570     } tags[] = {
12571       {
12572       "replaygain_track_gain", GST_TAG_TRACK_GAIN}, {
12573       "replaygain_track_peak", GST_TAG_TRACK_PEAK}, {
12574       "replaygain_album_gain", GST_TAG_ALBUM_GAIN}, {
12575       "replaygain_album_peak", GST_TAG_ALBUM_PEAK}, {
12576       "MusicBrainz Track Id", GST_TAG_MUSICBRAINZ_TRACKID}, {
12577       "MusicBrainz Artist Id", GST_TAG_MUSICBRAINZ_ARTISTID}, {
12578       "MusicBrainz Album Id", GST_TAG_MUSICBRAINZ_ALBUMID}, {
12579       "MusicBrainz Album Artist Id", GST_TAG_MUSICBRAINZ_ALBUMARTISTID}
12580     };
12581     int i;
12582
12583     for (i = 0; i < G_N_ELEMENTS (tags); ++i) {
12584       if (!g_ascii_strncasecmp (tags[i].name, namestr, namesize)) {
12585         switch (gst_tag_get_type (tags[i].tag)) {
12586           case G_TYPE_DOUBLE:
12587             qtdemux_add_double_tag_from_str (demux, taglist, tags[i].tag,
12588                 ((guint8 *) data->data) + 16, datasize - 16);
12589             break;
12590           case G_TYPE_STRING:
12591             qtdemux_tag_add_str (demux, taglist, tags[i].tag, NULL, node);
12592             break;
12593           default:
12594             /* not reached */
12595             break;
12596         }
12597         break;
12598       }
12599     }
12600     if (i == G_N_ELEMENTS (tags))
12601       goto unknown_tag;
12602   } else {
12603     goto unknown_tag;
12604   }
12605
12606   return;
12607
12608 /* errors */
12609 unknown_tag:
12610 #ifndef GST_DISABLE_GST_DEBUG
12611   {
12612     gchar *namestr_dbg;
12613     gchar *meanstr_dbg;
12614
12615     meanstr_dbg = g_strndup (meanstr, meansize);
12616     namestr_dbg = g_strndup (namestr, namesize);
12617
12618     GST_WARNING_OBJECT (demux, "This tag %s:%s type:%u is not mapped, "
12619         "file a bug at bugzilla.gnome.org", meanstr_dbg, namestr_dbg, datatype);
12620
12621     g_free (namestr_dbg);
12622     g_free (meanstr_dbg);
12623   }
12624 #endif
12625   return;
12626 }
12627
12628 static void
12629 qtdemux_tag_add_id32 (GstQTDemux * demux, GstTagList * taglist, const char *tag,
12630     const char *tag_bis, GNode * node)
12631 {
12632   guint8 *data;
12633   GstBuffer *buf;
12634   guint len;
12635   GstTagList *id32_taglist = NULL;
12636
12637   GST_LOG_OBJECT (demux, "parsing ID32");
12638
12639   data = node->data;
12640   len = GST_READ_UINT32_BE (data);
12641
12642   /* need at least full box and language tag */
12643   if (len < 12 + 2)
12644     return;
12645
12646   buf = gst_buffer_new_allocate (NULL, len - 14, NULL);
12647   gst_buffer_fill (buf, 0, data + 14, len - 14);
12648
12649   id32_taglist = gst_tag_list_from_id3v2_tag (buf);
12650   if (id32_taglist) {
12651     GST_LOG_OBJECT (demux, "parsing ok");
12652     gst_tag_list_insert (taglist, id32_taglist, GST_TAG_MERGE_KEEP);
12653     gst_tag_list_unref (id32_taglist);
12654   } else {
12655     GST_LOG_OBJECT (demux, "parsing failed");
12656   }
12657
12658   gst_buffer_unref (buf);
12659 }
12660
12661 typedef void (*GstQTDemuxAddTagFunc) (GstQTDemux * demux, GstTagList * taglist,
12662     const char *tag, const char *tag_bis, GNode * node);
12663
12664 /* unmapped tags
12665 FOURCC_pcst -> if media is a podcast -> bool
12666 FOURCC_cpil -> if media is part of a compilation -> bool
12667 FOURCC_pgap -> if media is part of a gapless context -> bool
12668 FOURCC_tven -> the tv episode id e.g. S01E23 -> str
12669 */
12670
12671 static const struct
12672 {
12673   guint32 fourcc;
12674   const gchar *gst_tag;
12675   const gchar *gst_tag_bis;
12676   const GstQTDemuxAddTagFunc func;
12677 } add_funcs[] = {
12678   {
12679   FOURCC__nam, GST_TAG_TITLE, NULL, qtdemux_tag_add_str}, {
12680   FOURCC_titl, GST_TAG_TITLE, NULL, qtdemux_tag_add_str}, {
12681   FOURCC__grp, GST_TAG_GROUPING, NULL, qtdemux_tag_add_str}, {
12682   FOURCC__wrt, GST_TAG_COMPOSER, NULL, qtdemux_tag_add_str}, {
12683   FOURCC__ART, GST_TAG_ARTIST, NULL, qtdemux_tag_add_str}, {
12684   FOURCC_aART, GST_TAG_ALBUM_ARTIST, NULL, qtdemux_tag_add_str}, {
12685   FOURCC_perf, GST_TAG_ARTIST, NULL, qtdemux_tag_add_str}, {
12686   FOURCC_auth, GST_TAG_COMPOSER, NULL, qtdemux_tag_add_str}, {
12687   FOURCC__alb, GST_TAG_ALBUM, NULL, qtdemux_tag_add_str}, {
12688   FOURCC_albm, GST_TAG_ALBUM, NULL, qtdemux_tag_add_str}, {
12689   FOURCC_cprt, GST_TAG_COPYRIGHT, NULL, qtdemux_tag_add_str}, {
12690   FOURCC__cpy, GST_TAG_COPYRIGHT, NULL, qtdemux_tag_add_str}, {
12691   FOURCC__cmt, GST_TAG_COMMENT, NULL, qtdemux_tag_add_str}, {
12692   FOURCC__des, GST_TAG_DESCRIPTION, NULL, qtdemux_tag_add_str}, {
12693   FOURCC_desc, GST_TAG_DESCRIPTION, NULL, qtdemux_tag_add_str}, {
12694   FOURCC_dscp, GST_TAG_DESCRIPTION, NULL, qtdemux_tag_add_str}, {
12695   FOURCC__lyr, GST_TAG_LYRICS, NULL, qtdemux_tag_add_str}, {
12696   FOURCC__day, GST_TAG_DATE, NULL, qtdemux_tag_add_date}, {
12697   FOURCC_yrrc, GST_TAG_DATE, NULL, qtdemux_tag_add_year}, {
12698   FOURCC__too, GST_TAG_ENCODER, NULL, qtdemux_tag_add_str}, {
12699   FOURCC__inf, GST_TAG_COMMENT, NULL, qtdemux_tag_add_str}, {
12700   FOURCC_trkn, GST_TAG_TRACK_NUMBER, GST_TAG_TRACK_COUNT, qtdemux_tag_add_num}, {
12701   FOURCC_disk, GST_TAG_ALBUM_VOLUME_NUMBER, GST_TAG_ALBUM_VOLUME_COUNT,
12702         qtdemux_tag_add_num}, {
12703   FOURCC_disc, GST_TAG_ALBUM_VOLUME_NUMBER, GST_TAG_ALBUM_VOLUME_COUNT,
12704         qtdemux_tag_add_num}, {
12705   FOURCC__gen, GST_TAG_GENRE, NULL, qtdemux_tag_add_str}, {
12706   FOURCC_gnre, GST_TAG_GENRE, NULL, qtdemux_tag_add_gnre}, {
12707   FOURCC_tmpo, GST_TAG_BEATS_PER_MINUTE, NULL, qtdemux_tag_add_tmpo}, {
12708   FOURCC_covr, GST_TAG_IMAGE, NULL, qtdemux_tag_add_covr}, {
12709   FOURCC_sonm, GST_TAG_TITLE_SORTNAME, NULL, qtdemux_tag_add_str}, {
12710   FOURCC_soal, GST_TAG_ALBUM_SORTNAME, NULL, qtdemux_tag_add_str}, {
12711   FOURCC_soar, GST_TAG_ARTIST_SORTNAME, NULL, qtdemux_tag_add_str}, {
12712   FOURCC_soaa, GST_TAG_ALBUM_ARTIST_SORTNAME, NULL, qtdemux_tag_add_str}, {
12713   FOURCC_soco, GST_TAG_COMPOSER_SORTNAME, NULL, qtdemux_tag_add_str}, {
12714   FOURCC_sosn, GST_TAG_SHOW_SORTNAME, NULL, qtdemux_tag_add_str}, {
12715   FOURCC_tvsh, GST_TAG_SHOW_NAME, NULL, qtdemux_tag_add_str}, {
12716   FOURCC_tvsn, GST_TAG_SHOW_SEASON_NUMBER, NULL, qtdemux_tag_add_uint32}, {
12717   FOURCC_tves, GST_TAG_SHOW_EPISODE_NUMBER, NULL, qtdemux_tag_add_uint32}, {
12718   FOURCC_kywd, GST_TAG_KEYWORDS, NULL, qtdemux_tag_add_keywords}, {
12719   FOURCC_keyw, GST_TAG_KEYWORDS, NULL, qtdemux_tag_add_str}, {
12720   FOURCC__enc, GST_TAG_ENCODER, NULL, qtdemux_tag_add_str}, {
12721   FOURCC_loci, GST_TAG_GEO_LOCATION_NAME, NULL, qtdemux_tag_add_location}, {
12722   FOURCC_clsf, GST_QT_DEMUX_CLASSIFICATION_TAG, NULL,
12723         qtdemux_tag_add_classification}, {
12724   FOURCC__mak, GST_TAG_DEVICE_MANUFACTURER, NULL, qtdemux_tag_add_str}, {
12725   FOURCC__mod, GST_TAG_DEVICE_MODEL, NULL, qtdemux_tag_add_str}, {
12726   FOURCC__swr, GST_TAG_APPLICATION_NAME, NULL, qtdemux_tag_add_str}, {
12727
12728     /* This is a special case, some tags are stored in this
12729      * 'reverse dns naming', according to:
12730      * http://atomicparsley.sourceforge.net/mpeg-4files.html and
12731      * bug #614471
12732      */
12733   FOURCC_____, "", NULL, qtdemux_tag_add_revdns}, {
12734     /* see http://www.mp4ra.org/specs.html for ID32 in meta box */
12735   FOURCC_ID32, "", NULL, qtdemux_tag_add_id32}
12736 };
12737
12738 struct _GstQtDemuxTagList
12739 {
12740   GstQTDemux *demux;
12741   GstTagList *taglist;
12742 };
12743 typedef struct _GstQtDemuxTagList GstQtDemuxTagList;
12744
12745 static void
12746 qtdemux_tag_add_blob (GNode * node, GstQtDemuxTagList * qtdemuxtaglist)
12747 {
12748   gint len;
12749   guint8 *data;
12750   GstBuffer *buf;
12751   gchar *media_type;
12752   const gchar *style;
12753   GstSample *sample;
12754   GstStructure *s;
12755   guint i;
12756   guint8 ndata[4];
12757   GstQTDemux *demux = qtdemuxtaglist->demux;
12758   GstTagList *taglist = qtdemuxtaglist->taglist;
12759
12760   data = node->data;
12761   len = QT_UINT32 (data);
12762   buf = gst_buffer_new_and_alloc (len);
12763   gst_buffer_fill (buf, 0, data, len);
12764
12765   /* heuristic to determine style of tag */
12766   if (QT_FOURCC (data + 4) == FOURCC_____ ||
12767       (len > 8 + 12 && QT_FOURCC (data + 12) == FOURCC_data))
12768     style = "itunes";
12769   else if (demux->major_brand == FOURCC_qt__)
12770     style = "quicktime";
12771   /* fall back to assuming iso/3gp tag style */
12772   else
12773     style = "iso";
12774
12775   /* santize the name for the caps. */
12776   for (i = 0; i < 4; i++) {
12777     guint8 d = data[4 + i];
12778     if (g_ascii_isalnum (d))
12779       ndata[i] = g_ascii_tolower (d);
12780     else
12781       ndata[i] = '_';
12782   }
12783
12784   media_type = g_strdup_printf ("application/x-gst-qt-%c%c%c%c-tag",
12785       ndata[0], ndata[1], ndata[2], ndata[3]);
12786   GST_DEBUG_OBJECT (demux, "media type %s", media_type);
12787
12788   s = gst_structure_new (media_type, "style", G_TYPE_STRING, style, NULL);
12789   sample = gst_sample_new (buf, NULL, NULL, s);
12790   gst_buffer_unref (buf);
12791   g_free (media_type);
12792
12793   GST_DEBUG_OBJECT (demux, "adding private tag; size %d, info %" GST_PTR_FORMAT,
12794       len, s);
12795
12796   gst_tag_list_add (taglist, GST_TAG_MERGE_APPEND,
12797       GST_QT_DEMUX_PRIVATE_TAG, sample, NULL);
12798
12799   gst_sample_unref (sample);
12800 }
12801
12802 static void
12803 qtdemux_parse_udta (GstQTDemux * qtdemux, GstTagList * taglist, GNode * udta)
12804 {
12805   GNode *meta;
12806   GNode *ilst;
12807   GNode *xmp_;
12808   GNode *node;
12809   gint i;
12810   GstQtDemuxTagList demuxtaglist;
12811
12812   demuxtaglist.demux = qtdemux;
12813   demuxtaglist.taglist = taglist;
12814
12815   meta = qtdemux_tree_get_child_by_type (udta, FOURCC_meta);
12816   if (meta != NULL) {
12817     ilst = qtdemux_tree_get_child_by_type (meta, FOURCC_ilst);
12818     if (ilst == NULL) {
12819       GST_LOG_OBJECT (qtdemux, "no ilst");
12820       return;
12821     }
12822   } else {
12823     ilst = udta;
12824     GST_LOG_OBJECT (qtdemux, "no meta so using udta itself");
12825   }
12826
12827   i = 0;
12828   while (i < G_N_ELEMENTS (add_funcs)) {
12829     node = qtdemux_tree_get_child_by_type (ilst, add_funcs[i].fourcc);
12830     if (node) {
12831       gint len;
12832
12833       len = QT_UINT32 (node->data);
12834       if (len < 12) {
12835         GST_DEBUG_OBJECT (qtdemux, "too small tag atom %" GST_FOURCC_FORMAT,
12836             GST_FOURCC_ARGS (add_funcs[i].fourcc));
12837       } else {
12838         add_funcs[i].func (qtdemux, taglist, add_funcs[i].gst_tag,
12839             add_funcs[i].gst_tag_bis, node);
12840       }
12841       g_node_destroy (node);
12842     } else {
12843       i++;
12844     }
12845   }
12846
12847   /* parsed nodes have been removed, pass along remainder as blob */
12848   g_node_children_foreach (ilst, G_TRAVERSE_ALL,
12849       (GNodeForeachFunc) qtdemux_tag_add_blob, &demuxtaglist);
12850
12851   /* parse up XMP_ node if existing */
12852   xmp_ = qtdemux_tree_get_child_by_type (udta, FOURCC_XMP_);
12853   if (xmp_ != NULL) {
12854     GstBuffer *buf;
12855     GstTagList *xmptaglist;
12856
12857     buf = _gst_buffer_new_wrapped (((guint8 *) xmp_->data) + 8,
12858         QT_UINT32 ((guint8 *) xmp_->data) - 8, NULL);
12859     xmptaglist = gst_tag_list_from_xmp_buffer (buf);
12860     gst_buffer_unref (buf);
12861
12862     qtdemux_handle_xmp_taglist (qtdemux, taglist, xmptaglist);
12863   } else {
12864     GST_DEBUG_OBJECT (qtdemux, "No XMP_ node found");
12865   }
12866 }
12867
12868 typedef struct
12869 {
12870   GstStructure *structure;      /* helper for sort function */
12871   gchar *location;
12872   guint min_req_bitrate;
12873   guint min_req_qt_version;
12874 } GstQtReference;
12875
12876 static gint
12877 qtdemux_redirects_sort_func (gconstpointer a, gconstpointer b)
12878 {
12879   GstQtReference *ref_a = (GstQtReference *) a;
12880   GstQtReference *ref_b = (GstQtReference *) b;
12881
12882   if (ref_b->min_req_qt_version != ref_a->min_req_qt_version)
12883     return ref_b->min_req_qt_version - ref_a->min_req_qt_version;
12884
12885   /* known bitrates go before unknown; higher bitrates go first */
12886   return ref_b->min_req_bitrate - ref_a->min_req_bitrate;
12887 }
12888
12889 /* sort the redirects and post a message for the application.
12890  */
12891 static void
12892 qtdemux_process_redirects (GstQTDemux * qtdemux, GList * references)
12893 {
12894   GstQtReference *best;
12895   GstStructure *s;
12896   GstMessage *msg;
12897   GValue list_val = { 0, };
12898   GList *l;
12899
12900   g_assert (references != NULL);
12901
12902   references = g_list_sort (references, qtdemux_redirects_sort_func);
12903
12904   best = (GstQtReference *) references->data;
12905
12906   g_value_init (&list_val, GST_TYPE_LIST);
12907
12908   for (l = references; l != NULL; l = l->next) {
12909     GstQtReference *ref = (GstQtReference *) l->data;
12910     GValue struct_val = { 0, };
12911
12912     ref->structure = gst_structure_new ("redirect",
12913         "new-location", G_TYPE_STRING, ref->location, NULL);
12914
12915     if (ref->min_req_bitrate > 0) {
12916       gst_structure_set (ref->structure, "minimum-bitrate", G_TYPE_INT,
12917           ref->min_req_bitrate, NULL);
12918     }
12919
12920     g_value_init (&struct_val, GST_TYPE_STRUCTURE);
12921     g_value_set_boxed (&struct_val, ref->structure);
12922     gst_value_list_append_value (&list_val, &struct_val);
12923     g_value_unset (&struct_val);
12924     /* don't free anything here yet, since we need best->structure below */
12925   }
12926
12927   g_assert (best != NULL);
12928   s = gst_structure_copy (best->structure);
12929
12930   if (g_list_length (references) > 1) {
12931     gst_structure_set_value (s, "locations", &list_val);
12932   }
12933
12934   g_value_unset (&list_val);
12935
12936   for (l = references; l != NULL; l = l->next) {
12937     GstQtReference *ref = (GstQtReference *) l->data;
12938
12939     gst_structure_free (ref->structure);
12940     g_free (ref->location);
12941     g_free (ref);
12942   }
12943   g_list_free (references);
12944
12945   GST_INFO_OBJECT (qtdemux, "posting redirect message: %" GST_PTR_FORMAT, s);
12946   msg = gst_message_new_element (GST_OBJECT_CAST (qtdemux), s);
12947   gst_element_post_message (GST_ELEMENT_CAST (qtdemux), msg);
12948   qtdemux->posted_redirect = TRUE;
12949 }
12950
12951 /* look for redirect nodes, collect all redirect information and
12952  * process it.
12953  */
12954 static gboolean
12955 qtdemux_parse_redirects (GstQTDemux * qtdemux)
12956 {
12957   GNode *rmra, *rmda, *rdrf;
12958
12959   rmra = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_rmra);
12960   if (rmra) {
12961     GList *redirects = NULL;
12962
12963     rmda = qtdemux_tree_get_child_by_type (rmra, FOURCC_rmda);
12964     while (rmda) {
12965       GstQtReference ref = { NULL, NULL, 0, 0 };
12966       GNode *rmdr, *rmvc;
12967
12968       if ((rmdr = qtdemux_tree_get_child_by_type (rmda, FOURCC_rmdr))) {
12969         ref.min_req_bitrate = QT_UINT32 ((guint8 *) rmdr->data + 12);
12970         GST_LOG_OBJECT (qtdemux, "data rate atom, required bitrate = %u",
12971             ref.min_req_bitrate);
12972       }
12973
12974       if ((rmvc = qtdemux_tree_get_child_by_type (rmda, FOURCC_rmvc))) {
12975         guint32 package = QT_FOURCC ((guint8 *) rmvc->data + 12);
12976         guint version = QT_UINT32 ((guint8 *) rmvc->data + 16);
12977
12978 #ifndef GST_DISABLE_GST_DEBUG
12979         guint bitmask = QT_UINT32 ((guint8 *) rmvc->data + 20);
12980 #endif
12981         guint check_type = QT_UINT16 ((guint8 *) rmvc->data + 24);
12982
12983         GST_LOG_OBJECT (qtdemux,
12984             "version check atom [%" GST_FOURCC_FORMAT "], version=0x%08x"
12985             ", mask=%08x, check_type=%u", GST_FOURCC_ARGS (package), version,
12986             bitmask, check_type);
12987         if (package == FOURCC_qtim && check_type == 0) {
12988           ref.min_req_qt_version = version;
12989         }
12990       }
12991
12992       rdrf = qtdemux_tree_get_child_by_type (rmda, FOURCC_rdrf);
12993       if (rdrf) {
12994         guint32 ref_type;
12995         guint8 *ref_data;
12996         guint ref_len;
12997
12998         ref_len = QT_UINT32 ((guint8 *) rdrf->data);
12999         if (ref_len > 20) {
13000           ref_type = QT_FOURCC ((guint8 *) rdrf->data + 12);
13001           ref_data = (guint8 *) rdrf->data + 20;
13002           if (ref_type == FOURCC_alis) {
13003             guint record_len, record_version, fn_len;
13004
13005             if (ref_len > 70) {
13006               /* MacOSX alias record, google for alias-layout.txt */
13007               record_len = QT_UINT16 (ref_data + 4);
13008               record_version = QT_UINT16 (ref_data + 4 + 2);
13009               fn_len = QT_UINT8 (ref_data + 50);
13010               if (record_len > 50 && record_version == 2 && fn_len > 0) {
13011                 ref.location = g_strndup ((gchar *) ref_data + 51, fn_len);
13012               }
13013             } else {
13014               GST_WARNING_OBJECT (qtdemux, "Invalid rdrf/alis size (%u < 70)",
13015                   ref_len);
13016             }
13017           } else if (ref_type == FOURCC_url_) {
13018             ref.location = g_strndup ((gchar *) ref_data, ref_len - 8);
13019           } else {
13020             GST_DEBUG_OBJECT (qtdemux,
13021                 "unknown rdrf reference type %" GST_FOURCC_FORMAT,
13022                 GST_FOURCC_ARGS (ref_type));
13023           }
13024           if (ref.location != NULL) {
13025             GST_INFO_OBJECT (qtdemux, "New location: %s", ref.location);
13026             redirects =
13027                 g_list_prepend (redirects, g_memdup (&ref, sizeof (ref)));
13028           } else {
13029             GST_WARNING_OBJECT (qtdemux,
13030                 "Failed to extract redirect location from rdrf atom");
13031           }
13032         } else {
13033           GST_WARNING_OBJECT (qtdemux, "Invalid rdrf size (%u < 20)", ref_len);
13034         }
13035       }
13036
13037       /* look for others */
13038       rmda = qtdemux_tree_get_sibling_by_type (rmda, FOURCC_rmda);
13039     }
13040
13041     if (redirects != NULL) {
13042       qtdemux_process_redirects (qtdemux, redirects);
13043     }
13044   }
13045   return TRUE;
13046 }
13047
13048 static GstTagList *
13049 qtdemux_add_container_format (GstQTDemux * qtdemux, GstTagList * tags)
13050 {
13051   const gchar *fmt;
13052
13053   if (tags == NULL) {
13054     tags = gst_tag_list_new_empty ();
13055     gst_tag_list_set_scope (tags, GST_TAG_SCOPE_GLOBAL);
13056   }
13057
13058   if (qtdemux->major_brand == FOURCC_mjp2)
13059     fmt = "Motion JPEG 2000";
13060   else if ((qtdemux->major_brand & 0xffff) == FOURCC_3g__)
13061     fmt = "3GP";
13062   else if (qtdemux->major_brand == FOURCC_qt__)
13063     fmt = "Quicktime";
13064   else if (qtdemux->fragmented)
13065     fmt = "ISO fMP4";
13066   else
13067     fmt = "ISO MP4/M4A";
13068
13069   GST_LOG_OBJECT (qtdemux, "mapped %" GST_FOURCC_FORMAT " to '%s'",
13070       GST_FOURCC_ARGS (qtdemux->major_brand), fmt);
13071
13072   gst_tag_list_add (tags, GST_TAG_MERGE_REPLACE, GST_TAG_CONTAINER_FORMAT,
13073       fmt, NULL);
13074
13075   return tags;
13076 }
13077
13078 /* we have read the complete moov node now.
13079  * This function parses all of the relevant info, creates the traks and
13080  * prepares all data structures for playback
13081  */
13082 static gboolean
13083 qtdemux_parse_tree (GstQTDemux * qtdemux)
13084 {
13085   GNode *mvhd;
13086   GNode *trak;
13087   GNode *udta;
13088   GNode *mvex;
13089   GstClockTime duration;
13090   GNode *pssh;
13091   guint64 creation_time;
13092   GstDateTime *datetime = NULL;
13093   gint version;
13094
13095   /* make sure we have a usable taglist */
13096   qtdemux->tag_list = gst_tag_list_make_writable (qtdemux->tag_list);
13097
13098   mvhd = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_mvhd);
13099   if (mvhd == NULL) {
13100     GST_LOG_OBJECT (qtdemux, "No mvhd node found, looking for redirects.");
13101     return qtdemux_parse_redirects (qtdemux);
13102   }
13103
13104   version = QT_UINT8 ((guint8 *) mvhd->data + 8);
13105   if (version == 1) {
13106     creation_time = QT_UINT64 ((guint8 *) mvhd->data + 12);
13107     qtdemux->timescale = QT_UINT32 ((guint8 *) mvhd->data + 28);
13108     qtdemux->duration = QT_UINT64 ((guint8 *) mvhd->data + 32);
13109   } else if (version == 0) {
13110     creation_time = QT_UINT32 ((guint8 *) mvhd->data + 12);
13111     qtdemux->timescale = QT_UINT32 ((guint8 *) mvhd->data + 20);
13112     qtdemux->duration = QT_UINT32 ((guint8 *) mvhd->data + 24);
13113   } else {
13114     GST_WARNING_OBJECT (qtdemux, "Unhandled mvhd version %d", version);
13115     return FALSE;
13116   }
13117
13118   /* Moving qt creation time (secs since 1904) to unix time */
13119   if (creation_time != 0) {
13120     /* Try to use epoch first as it should be faster and more commonly found */
13121     if (creation_time >= QTDEMUX_SECONDS_FROM_1904_TO_1970) {
13122       GTimeVal now;
13123
13124       creation_time -= QTDEMUX_SECONDS_FROM_1904_TO_1970;
13125       /* some data cleansing sanity */
13126       g_get_current_time (&now);
13127       if (now.tv_sec + 24 * 3600 < creation_time) {
13128         GST_DEBUG_OBJECT (qtdemux, "discarding bogus future creation time");
13129       } else {
13130         datetime = gst_date_time_new_from_unix_epoch_utc (creation_time);
13131       }
13132     } else {
13133       GDateTime *base_dt = g_date_time_new_utc (1904, 1, 1, 0, 0, 0);
13134       GDateTime *dt, *dt_local;
13135
13136       dt = g_date_time_add_seconds (base_dt, creation_time);
13137       dt_local = g_date_time_to_local (dt);
13138       datetime = gst_date_time_new_from_g_date_time (dt_local);
13139
13140       g_date_time_unref (base_dt);
13141       g_date_time_unref (dt);
13142     }
13143   }
13144   if (datetime) {
13145     /* Use KEEP as explicit tags should have a higher priority than mvhd tag */
13146     gst_tag_list_add (qtdemux->tag_list, GST_TAG_MERGE_KEEP, GST_TAG_DATE_TIME,
13147         datetime, NULL);
13148     gst_date_time_unref (datetime);
13149   }
13150
13151   GST_INFO_OBJECT (qtdemux, "timescale: %u", qtdemux->timescale);
13152   GST_INFO_OBJECT (qtdemux, "duration: %" G_GUINT64_FORMAT, qtdemux->duration);
13153
13154   /* check for fragmented file and get some (default) data */
13155   mvex = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_mvex);
13156   if (mvex) {
13157     GNode *mehd;
13158     GstByteReader mehd_data;
13159
13160     /* let track parsing or anyone know weird stuff might happen ... */
13161     qtdemux->fragmented = TRUE;
13162
13163     /* compensate for total duration */
13164     mehd = qtdemux_tree_get_child_by_type_full (mvex, FOURCC_mehd, &mehd_data);
13165     if (mehd)
13166       qtdemux_parse_mehd (qtdemux, &mehd_data);
13167   }
13168
13169   /* set duration in the segment info */
13170   gst_qtdemux_get_duration (qtdemux, &duration);
13171   if (duration) {
13172     qtdemux->segment.duration = duration;
13173     /* also do not exceed duration; stop is set that way post seek anyway,
13174      * and segment activation falls back to duration,
13175      * whereas loop only checks stop, so let's align this here as well */
13176     qtdemux->segment.stop = duration;
13177   }
13178
13179   /* parse all traks */
13180   trak = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_trak);
13181   while (trak) {
13182     qtdemux_parse_trak (qtdemux, trak);
13183     /* iterate all siblings */
13184     trak = qtdemux_tree_get_sibling_by_type (trak, FOURCC_trak);
13185   }
13186
13187   qtdemux->tag_list = gst_tag_list_make_writable (qtdemux->tag_list);
13188
13189   /* find tags */
13190   udta = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_udta);
13191   if (udta) {
13192     qtdemux_parse_udta (qtdemux, qtdemux->tag_list, udta);
13193   } else {
13194     GST_LOG_OBJECT (qtdemux, "No udta node found.");
13195   }
13196
13197   /* maybe also some tags in meta box */
13198   udta = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_meta);
13199   if (udta) {
13200     GST_DEBUG_OBJECT (qtdemux, "Parsing meta box for tags.");
13201     qtdemux_parse_udta (qtdemux, qtdemux->tag_list, udta);
13202   } else {
13203     GST_LOG_OBJECT (qtdemux, "No meta node found.");
13204   }
13205
13206   /* parse any protection system info */
13207   pssh = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_pssh);
13208   while (pssh) {
13209     GST_LOG_OBJECT (qtdemux, "Parsing pssh box.");
13210     qtdemux_parse_pssh (qtdemux, pssh);
13211     pssh = qtdemux_tree_get_sibling_by_type (pssh, FOURCC_pssh);
13212   }
13213
13214   qtdemux->tag_list = qtdemux_add_container_format (qtdemux, qtdemux->tag_list);
13215
13216   return TRUE;
13217 }
13218
13219 /* taken from ffmpeg */
13220 static int
13221 read_descr_size (guint8 * ptr, guint8 * end, guint8 ** end_out)
13222 {
13223   int count = 4;
13224   int len = 0;
13225
13226   while (count--) {
13227     int c;
13228
13229     if (ptr >= end)
13230       return -1;
13231
13232     c = *ptr++;
13233     len = (len << 7) | (c & 0x7f);
13234     if (!(c & 0x80))
13235       break;
13236   }
13237   *end_out = ptr;
13238   return len;
13239 }
13240
13241 /* this can change the codec originally present in @list */
13242 static void
13243 gst_qtdemux_handle_esds (GstQTDemux * qtdemux, QtDemuxStream * stream,
13244     QtDemuxStreamStsdEntry * entry, GNode * esds, GstTagList * list)
13245 {
13246   int len = QT_UINT32 (esds->data);
13247   guint8 *ptr = esds->data;
13248   guint8 *end = ptr + len;
13249   int tag;
13250   guint8 *data_ptr = NULL;
13251   int data_len = 0;
13252   guint8 object_type_id = 0;
13253   const char *codec_name = NULL;
13254   GstCaps *caps = NULL;
13255
13256   GST_MEMDUMP_OBJECT (qtdemux, "esds", ptr, len);
13257   ptr += 8;
13258   GST_DEBUG_OBJECT (qtdemux, "version/flags = %08x", QT_UINT32 (ptr));
13259   ptr += 4;
13260   while (ptr + 1 < end) {
13261     tag = QT_UINT8 (ptr);
13262     GST_DEBUG_OBJECT (qtdemux, "tag = %02x", tag);
13263     ptr++;
13264     len = read_descr_size (ptr, end, &ptr);
13265     GST_DEBUG_OBJECT (qtdemux, "len = %d", len);
13266
13267     /* Check the stated amount of data is available for reading */
13268     if (len < 0 || ptr + len > end)
13269       break;
13270
13271     switch (tag) {
13272       case ES_DESCRIPTOR_TAG:
13273         GST_DEBUG_OBJECT (qtdemux, "ID %04x", QT_UINT16 (ptr));
13274         GST_DEBUG_OBJECT (qtdemux, "priority %04x", QT_UINT8 (ptr + 2));
13275         ptr += 3;
13276         break;
13277       case DECODER_CONFIG_DESC_TAG:{
13278         guint max_bitrate, avg_bitrate;
13279
13280         object_type_id = QT_UINT8 (ptr);
13281         max_bitrate = QT_UINT32 (ptr + 5);
13282         avg_bitrate = QT_UINT32 (ptr + 9);
13283         GST_DEBUG_OBJECT (qtdemux, "object_type_id %02x", object_type_id);
13284         GST_DEBUG_OBJECT (qtdemux, "stream_type %02x", QT_UINT8 (ptr + 1));
13285         GST_DEBUG_OBJECT (qtdemux, "buffer_size_db %02x", QT_UINT24 (ptr + 2));
13286         GST_DEBUG_OBJECT (qtdemux, "max bitrate %u", max_bitrate);
13287         GST_DEBUG_OBJECT (qtdemux, "avg bitrate %u", avg_bitrate);
13288         if (max_bitrate > 0 && max_bitrate < G_MAXUINT32) {
13289           gst_tag_list_add (list, GST_TAG_MERGE_REPLACE,
13290               GST_TAG_MAXIMUM_BITRATE, max_bitrate, NULL);
13291         }
13292         if (avg_bitrate > 0 && avg_bitrate < G_MAXUINT32) {
13293           gst_tag_list_add (list, GST_TAG_MERGE_REPLACE, GST_TAG_BITRATE,
13294               avg_bitrate, NULL);
13295         }
13296         ptr += 13;
13297         break;
13298       }
13299       case DECODER_SPECIFIC_INFO_TAG:
13300         GST_MEMDUMP_OBJECT (qtdemux, "data", ptr, len);
13301         if (object_type_id == 0xe0 && len == 0x40) {
13302           guint8 *data;
13303           GstStructure *s;
13304           guint32 clut[16];
13305           gint i;
13306
13307           GST_DEBUG_OBJECT (qtdemux,
13308               "Have VOBSUB palette. Creating palette event");
13309           /* move to decConfigDescr data and read palette */
13310           data = ptr;
13311           for (i = 0; i < 16; i++) {
13312             clut[i] = QT_UINT32 (data);
13313             data += 4;
13314           }
13315
13316           s = gst_structure_new ("application/x-gst-dvd", "event",
13317               G_TYPE_STRING, "dvd-spu-clut-change",
13318               "clut00", G_TYPE_INT, clut[0], "clut01", G_TYPE_INT, clut[1],
13319               "clut02", G_TYPE_INT, clut[2], "clut03", G_TYPE_INT, clut[3],
13320               "clut04", G_TYPE_INT, clut[4], "clut05", G_TYPE_INT, clut[5],
13321               "clut06", G_TYPE_INT, clut[6], "clut07", G_TYPE_INT, clut[7],
13322               "clut08", G_TYPE_INT, clut[8], "clut09", G_TYPE_INT, clut[9],
13323               "clut10", G_TYPE_INT, clut[10], "clut11", G_TYPE_INT, clut[11],
13324               "clut12", G_TYPE_INT, clut[12], "clut13", G_TYPE_INT, clut[13],
13325               "clut14", G_TYPE_INT, clut[14], "clut15", G_TYPE_INT, clut[15],
13326               NULL);
13327
13328           /* store event and trigger custom processing */
13329           stream->pending_event =
13330               gst_event_new_custom (GST_EVENT_CUSTOM_DOWNSTREAM, s);
13331         } else {
13332           /* Generic codec_data handler puts it on the caps */
13333           data_ptr = ptr;
13334           data_len = len;
13335         }
13336
13337         ptr += len;
13338         break;
13339       case SL_CONFIG_DESC_TAG:
13340         GST_DEBUG_OBJECT (qtdemux, "data %02x", QT_UINT8 (ptr));
13341         ptr += 1;
13342         break;
13343       default:
13344         GST_DEBUG_OBJECT (qtdemux, "Unknown/unhandled descriptor tag %02x",
13345             tag);
13346         GST_MEMDUMP_OBJECT (qtdemux, "descriptor data", ptr, len);
13347         ptr += len;
13348         break;
13349     }
13350   }
13351
13352   /* object_type_id in the esds atom in mp4a and mp4v tells us which codec is
13353    * in use, and should also be used to override some other parameters for some
13354    * codecs. */
13355   switch (object_type_id) {
13356     case 0x20:                 /* MPEG-4 */
13357       /* 4 bytes for the visual_object_sequence_start_code and 1 byte for the
13358        * profile_and_level_indication */
13359       if (data_ptr != NULL && data_len >= 5 &&
13360           GST_READ_UINT32_BE (data_ptr) == 0x000001b0) {
13361         gst_codec_utils_mpeg4video_caps_set_level_and_profile (entry->caps,
13362             data_ptr + 4, data_len - 4);
13363       }
13364       break;                    /* Nothing special needed here */
13365     case 0x21:                 /* H.264 */
13366       codec_name = "H.264 / AVC";
13367       caps = gst_caps_new_simple ("video/x-h264",
13368           "stream-format", G_TYPE_STRING, "avc",
13369           "alignment", G_TYPE_STRING, "au", NULL);
13370       break;
13371     case 0x40:                 /* AAC (any) */
13372     case 0x66:                 /* AAC Main */
13373     case 0x67:                 /* AAC LC */
13374     case 0x68:                 /* AAC SSR */
13375       /* Override channels and rate based on the codec_data, as it's often
13376        * wrong. */
13377       /* Only do so for basic setup without HE-AAC extension */
13378       if (data_ptr && data_len == 2) {
13379         guint channels, rate;
13380
13381         channels = gst_codec_utils_aac_get_channels (data_ptr, data_len);
13382         if (channels > 0)
13383           entry->n_channels = channels;
13384
13385         rate = gst_codec_utils_aac_get_sample_rate (data_ptr, data_len);
13386         if (rate > 0)
13387           entry->rate = rate;
13388       }
13389
13390       /* Set level and profile if possible */
13391       if (data_ptr != NULL && data_len >= 2) {
13392         gst_codec_utils_aac_caps_set_level_and_profile (entry->caps,
13393             data_ptr, data_len);
13394       } else {
13395         const gchar *profile_str = NULL;
13396         GstBuffer *buffer;
13397         GstMapInfo map;
13398         guint8 *codec_data;
13399         gint rate_idx, profile;
13400
13401         /* No codec_data, let's invent something.
13402          * FIXME: This is wrong for SBR! */
13403
13404         GST_WARNING_OBJECT (qtdemux, "No codec_data for AAC available");
13405
13406         buffer = gst_buffer_new_and_alloc (2);
13407         gst_buffer_map (buffer, &map, GST_MAP_WRITE);
13408         codec_data = map.data;
13409
13410         rate_idx =
13411             gst_codec_utils_aac_get_index_from_sample_rate (CUR_STREAM
13412             (stream)->rate);
13413
13414         switch (object_type_id) {
13415           case 0x66:
13416             profile_str = "main";
13417             profile = 0;
13418             break;
13419           case 0x67:
13420             profile_str = "lc";
13421             profile = 1;
13422             break;
13423           case 0x68:
13424             profile_str = "ssr";
13425             profile = 2;
13426             break;
13427           default:
13428             profile = 3;
13429             break;
13430         }
13431
13432         codec_data[0] = ((profile + 1) << 3) | ((rate_idx & 0xE) >> 1);
13433         codec_data[1] =
13434             ((rate_idx & 0x1) << 7) | (CUR_STREAM (stream)->n_channels << 3);
13435
13436         gst_buffer_unmap (buffer, &map);
13437         gst_caps_set_simple (CUR_STREAM (stream)->caps, "codec_data",
13438             GST_TYPE_BUFFER, buffer, NULL);
13439         gst_buffer_unref (buffer);
13440
13441         if (profile_str) {
13442           gst_caps_set_simple (CUR_STREAM (stream)->caps, "profile",
13443               G_TYPE_STRING, profile_str, NULL);
13444         }
13445       }
13446       break;
13447     case 0x60:                 /* MPEG-2, various profiles */
13448     case 0x61:
13449     case 0x62:
13450     case 0x63:
13451     case 0x64:
13452     case 0x65:
13453       codec_name = "MPEG-2 video";
13454       caps = gst_caps_new_simple ("video/mpeg",
13455           "mpegversion", G_TYPE_INT, 2,
13456           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
13457       break;
13458     case 0x69:                 /* MPEG-2 BC audio */
13459     case 0x6B:                 /* MPEG-1 audio */
13460       caps = gst_caps_new_simple ("audio/mpeg",
13461           "mpegversion", G_TYPE_INT, 1, "parsed", G_TYPE_BOOLEAN, TRUE, NULL);
13462       codec_name = "MPEG-1 audio";
13463       break;
13464     case 0x6A:                 /* MPEG-1 */
13465       codec_name = "MPEG-1 video";
13466       caps = gst_caps_new_simple ("video/mpeg",
13467           "mpegversion", G_TYPE_INT, 1,
13468           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
13469       break;
13470     case 0x6C:                 /* MJPEG */
13471       caps =
13472           gst_caps_new_simple ("image/jpeg", "parsed", G_TYPE_BOOLEAN, TRUE,
13473           NULL);
13474       codec_name = "Motion-JPEG";
13475       break;
13476     case 0x6D:                 /* PNG */
13477       caps =
13478           gst_caps_new_simple ("image/png", "parsed", G_TYPE_BOOLEAN, TRUE,
13479           NULL);
13480       codec_name = "PNG still images";
13481       break;
13482     case 0x6E:                 /* JPEG2000 */
13483       codec_name = "JPEG-2000";
13484       caps = gst_caps_new_simple ("image/x-j2c", "fields", G_TYPE_INT, 1, NULL);
13485       break;
13486     case 0xA4:                 /* Dirac */
13487       codec_name = "Dirac";
13488       caps = gst_caps_new_empty_simple ("video/x-dirac");
13489       break;
13490     case 0xA5:                 /* AC3 */
13491       codec_name = "AC-3 audio";
13492       caps = gst_caps_new_simple ("audio/x-ac3",
13493           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
13494       break;
13495     case 0xA9:                 /* AC3 */
13496       codec_name = "DTS audio";
13497       caps = gst_caps_new_simple ("audio/x-dts",
13498           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
13499       break;
13500     case 0xE1:                 /* QCELP */
13501       /* QCELP, the codec_data is a riff tag (little endian) with
13502        * 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). */
13503       caps = gst_caps_new_empty_simple ("audio/qcelp");
13504       codec_name = "QCELP";
13505       break;
13506     default:
13507       break;
13508   }
13509
13510   /* If we have a replacement caps, then change our caps for this stream */
13511   if (caps) {
13512     gst_caps_unref (entry->caps);
13513     entry->caps = caps;
13514   }
13515
13516   if (codec_name && list)
13517     gst_tag_list_add (list, GST_TAG_MERGE_REPLACE,
13518         GST_TAG_AUDIO_CODEC, codec_name, NULL);
13519
13520   /* Add the codec_data attribute to caps, if we have it */
13521   if (data_ptr) {
13522     GstBuffer *buffer;
13523
13524     buffer = gst_buffer_new_and_alloc (data_len);
13525     gst_buffer_fill (buffer, 0, data_ptr, data_len);
13526
13527     GST_DEBUG_OBJECT (qtdemux, "setting codec_data from esds");
13528     GST_MEMDUMP_OBJECT (qtdemux, "codec_data from esds", data_ptr, data_len);
13529
13530     gst_caps_set_simple (entry->caps, "codec_data", GST_TYPE_BUFFER,
13531         buffer, NULL);
13532     gst_buffer_unref (buffer);
13533   }
13534
13535 }
13536
13537 static inline GstCaps *
13538 _get_unknown_codec_name (const gchar * type, guint32 fourcc)
13539 {
13540   GstCaps *caps;
13541   guint i;
13542   char *s, fourstr[5];
13543
13544   g_snprintf (fourstr, 5, "%" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (fourcc));
13545   for (i = 0; i < 4; i++) {
13546     if (!g_ascii_isalnum (fourstr[i]))
13547       fourstr[i] = '_';
13548   }
13549   s = g_strdup_printf ("%s/x-gst-fourcc-%s", type, g_strstrip (fourstr));
13550   caps = gst_caps_new_empty_simple (s);
13551   g_free (s);
13552   return caps;
13553 }
13554
13555 #define _codec(name) \
13556   do { \
13557     if (codec_name) { \
13558       *codec_name = g_strdup (name); \
13559     } \
13560   } while (0)
13561
13562 static GstCaps *
13563 qtdemux_video_caps (GstQTDemux * qtdemux, QtDemuxStream * stream,
13564     QtDemuxStreamStsdEntry * entry, guint32 fourcc,
13565     const guint8 * stsd_entry_data, gchar ** codec_name)
13566 {
13567   GstCaps *caps = NULL;
13568   GstVideoFormat format = GST_VIDEO_FORMAT_UNKNOWN;
13569
13570   switch (fourcc) {
13571     case FOURCC_png:
13572       _codec ("PNG still images");
13573       caps = gst_caps_new_empty_simple ("image/png");
13574       break;
13575     case FOURCC_jpeg:
13576       _codec ("JPEG still images");
13577       caps =
13578           gst_caps_new_simple ("image/jpeg", "parsed", G_TYPE_BOOLEAN, TRUE,
13579           NULL);
13580       break;
13581     case GST_MAKE_FOURCC ('m', 'j', 'p', 'a'):
13582     case GST_MAKE_FOURCC ('A', 'V', 'D', 'J'):
13583     case GST_MAKE_FOURCC ('M', 'J', 'P', 'G'):
13584     case GST_MAKE_FOURCC ('d', 'm', 'b', '1'):
13585       _codec ("Motion-JPEG");
13586       caps =
13587           gst_caps_new_simple ("image/jpeg", "parsed", G_TYPE_BOOLEAN, TRUE,
13588           NULL);
13589       break;
13590     case GST_MAKE_FOURCC ('m', 'j', 'p', 'b'):
13591       _codec ("Motion-JPEG format B");
13592       caps = gst_caps_new_empty_simple ("video/x-mjpeg-b");
13593       break;
13594     case FOURCC_mjp2:
13595       _codec ("JPEG-2000");
13596       /* override to what it should be according to spec, avoid palette_data */
13597       entry->bits_per_sample = 24;
13598       caps = gst_caps_new_simple ("image/x-j2c", "fields", G_TYPE_INT, 1, NULL);
13599       break;
13600     case FOURCC_SVQ3:
13601       _codec ("Sorensen video v.3");
13602       caps = gst_caps_new_simple ("video/x-svq",
13603           "svqversion", G_TYPE_INT, 3, NULL);
13604       break;
13605     case GST_MAKE_FOURCC ('s', 'v', 'q', 'i'):
13606     case GST_MAKE_FOURCC ('S', 'V', 'Q', '1'):
13607       _codec ("Sorensen video v.1");
13608       caps = gst_caps_new_simple ("video/x-svq",
13609           "svqversion", G_TYPE_INT, 1, NULL);
13610       break;
13611     case GST_MAKE_FOURCC ('W', 'R', 'A', 'W'):
13612       caps = gst_caps_new_empty_simple ("video/x-raw");
13613       gst_caps_set_simple (caps, "format", G_TYPE_STRING, "RGB8P", NULL);
13614       _codec ("Windows Raw RGB");
13615       stream->alignment = 32;
13616       break;
13617     case FOURCC_raw_:
13618     {
13619       guint16 bps;
13620
13621       bps = QT_UINT16 (stsd_entry_data + 82);
13622       switch (bps) {
13623         case 15:
13624           format = GST_VIDEO_FORMAT_RGB15;
13625           break;
13626         case 16:
13627           format = GST_VIDEO_FORMAT_RGB16;
13628           break;
13629         case 24:
13630           format = GST_VIDEO_FORMAT_RGB;
13631           break;
13632         case 32:
13633           format = GST_VIDEO_FORMAT_ARGB;
13634           break;
13635         default:
13636           /* unknown */
13637           break;
13638       }
13639       break;
13640     }
13641     case GST_MAKE_FOURCC ('y', 'v', '1', '2'):
13642       format = GST_VIDEO_FORMAT_I420;
13643       break;
13644     case GST_MAKE_FOURCC ('y', 'u', 'v', '2'):
13645     case GST_MAKE_FOURCC ('Y', 'u', 'v', '2'):
13646       format = GST_VIDEO_FORMAT_I420;
13647       break;
13648     case FOURCC_2vuy:
13649     case GST_MAKE_FOURCC ('2', 'V', 'u', 'y'):
13650       format = GST_VIDEO_FORMAT_UYVY;
13651       break;
13652     case GST_MAKE_FOURCC ('v', '3', '0', '8'):
13653       format = GST_VIDEO_FORMAT_v308;
13654       break;
13655     case GST_MAKE_FOURCC ('v', '2', '1', '6'):
13656       format = GST_VIDEO_FORMAT_v216;
13657       break;
13658     case FOURCC_v210:
13659       format = GST_VIDEO_FORMAT_v210;
13660       break;
13661     case GST_MAKE_FOURCC ('r', '2', '1', '0'):
13662       format = GST_VIDEO_FORMAT_r210;
13663       break;
13664       /* Packed YUV 4:4:4 10 bit in 32 bits, complex
13665          case GST_MAKE_FOURCC ('v', '4', '1', '0'):
13666          format = GST_VIDEO_FORMAT_v410;
13667          break;
13668        */
13669       /* Packed YUV 4:4:4:4 8 bit in 32 bits
13670        * but different order than AYUV
13671        case GST_MAKE_FOURCC ('v', '4', '0', '8'):
13672        format = GST_VIDEO_FORMAT_v408;
13673        break;
13674        */
13675     case GST_MAKE_FOURCC ('m', 'p', 'e', 'g'):
13676     case GST_MAKE_FOURCC ('m', 'p', 'g', '1'):
13677       _codec ("MPEG-1 video");
13678       caps = gst_caps_new_simple ("video/mpeg", "mpegversion", G_TYPE_INT, 1,
13679           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
13680       break;
13681     case GST_MAKE_FOURCC ('h', 'd', 'v', '1'): /* HDV 720p30 */
13682     case GST_MAKE_FOURCC ('h', 'd', 'v', '2'): /* HDV 1080i60 */
13683     case GST_MAKE_FOURCC ('h', 'd', 'v', '3'): /* HDV 1080i50 */
13684     case GST_MAKE_FOURCC ('h', 'd', 'v', '4'): /* HDV 720p24 */
13685     case GST_MAKE_FOURCC ('h', 'd', 'v', '5'): /* HDV 720p25 */
13686     case GST_MAKE_FOURCC ('h', 'd', 'v', '6'): /* HDV 1080p24 */
13687     case GST_MAKE_FOURCC ('h', 'd', 'v', '7'): /* HDV 1080p25 */
13688     case GST_MAKE_FOURCC ('h', 'd', 'v', '8'): /* HDV 1080p30 */
13689     case GST_MAKE_FOURCC ('h', 'd', 'v', '9'): /* HDV 720p60 */
13690     case GST_MAKE_FOURCC ('h', 'd', 'v', 'a'): /* HDV 720p50 */
13691     case GST_MAKE_FOURCC ('m', 'x', '5', 'n'): /* MPEG2 IMX NTSC 525/60 50mb/s produced by FCP */
13692     case GST_MAKE_FOURCC ('m', 'x', '5', 'p'): /* MPEG2 IMX PAL 625/60 50mb/s produced by FCP */
13693     case GST_MAKE_FOURCC ('m', 'x', '4', 'n'): /* MPEG2 IMX NTSC 525/60 40mb/s produced by FCP */
13694     case GST_MAKE_FOURCC ('m', 'x', '4', 'p'): /* MPEG2 IMX PAL 625/60 40mb/s produced by FCP */
13695     case GST_MAKE_FOURCC ('m', 'x', '3', 'n'): /* MPEG2 IMX NTSC 525/60 30mb/s produced by FCP */
13696     case GST_MAKE_FOURCC ('m', 'x', '3', 'p'): /* MPEG2 IMX PAL 625/50 30mb/s produced by FCP */
13697     case GST_MAKE_FOURCC ('x', 'd', 'v', '1'): /* XDCAM HD 720p30 35Mb/s */
13698     case GST_MAKE_FOURCC ('x', 'd', 'v', '2'): /* XDCAM HD 1080i60 35Mb/s */
13699     case GST_MAKE_FOURCC ('x', 'd', 'v', '3'): /* XDCAM HD 1080i50 35Mb/s */
13700     case GST_MAKE_FOURCC ('x', 'd', 'v', '4'): /* XDCAM HD 720p24 35Mb/s */
13701     case GST_MAKE_FOURCC ('x', 'd', 'v', '5'): /* XDCAM HD 720p25 35Mb/s */
13702     case GST_MAKE_FOURCC ('x', 'd', 'v', '6'): /* XDCAM HD 1080p24 35Mb/s */
13703     case GST_MAKE_FOURCC ('x', 'd', 'v', '7'): /* XDCAM HD 1080p25 35Mb/s */
13704     case GST_MAKE_FOURCC ('x', 'd', 'v', '8'): /* XDCAM HD 1080p30 35Mb/s */
13705     case GST_MAKE_FOURCC ('x', 'd', 'v', '9'): /* XDCAM HD 720p60 35Mb/s */
13706     case GST_MAKE_FOURCC ('x', 'd', 'v', 'a'): /* XDCAM HD 720p50 35Mb/s */
13707     case GST_MAKE_FOURCC ('x', 'd', 'v', 'b'): /* XDCAM EX 1080i60 50Mb/s CBR */
13708     case GST_MAKE_FOURCC ('x', 'd', 'v', 'c'): /* XDCAM EX 1080i50 50Mb/s CBR */
13709     case GST_MAKE_FOURCC ('x', 'd', 'v', 'd'): /* XDCAM HD 1080p24 50Mb/s CBR */
13710     case GST_MAKE_FOURCC ('x', 'd', 'v', 'e'): /* XDCAM HD 1080p25 50Mb/s CBR */
13711     case GST_MAKE_FOURCC ('x', 'd', 'v', 'f'): /* XDCAM HD 1080p30 50Mb/s CBR */
13712     case GST_MAKE_FOURCC ('x', 'd', '5', '1'): /* XDCAM HD422 720p30 50Mb/s CBR */
13713     case GST_MAKE_FOURCC ('x', 'd', '5', '4'): /* XDCAM HD422 720p24 50Mb/s CBR */
13714     case GST_MAKE_FOURCC ('x', 'd', '5', '5'): /* XDCAM HD422 720p25 50Mb/s CBR */
13715     case GST_MAKE_FOURCC ('x', 'd', '5', '9'): /* XDCAM HD422 720p60 50Mb/s CBR */
13716     case GST_MAKE_FOURCC ('x', 'd', '5', 'a'): /* XDCAM HD422 720p50 50Mb/s CBR */
13717     case GST_MAKE_FOURCC ('x', 'd', '5', 'b'): /* XDCAM HD422 1080i50 50Mb/s CBR */
13718     case GST_MAKE_FOURCC ('x', 'd', '5', 'c'): /* XDCAM HD422 1080i50 50Mb/s CBR */
13719     case GST_MAKE_FOURCC ('x', 'd', '5', 'd'): /* XDCAM HD422 1080p24 50Mb/s CBR */
13720     case GST_MAKE_FOURCC ('x', 'd', '5', 'e'): /* XDCAM HD422 1080p25 50Mb/s CBR */
13721     case GST_MAKE_FOURCC ('x', 'd', '5', 'f'): /* XDCAM HD422 1080p30 50Mb/s CBR */
13722     case GST_MAKE_FOURCC ('x', 'd', 'h', 'd'): /* XDCAM HD 540p */
13723     case GST_MAKE_FOURCC ('x', 'd', 'h', '2'): /* XDCAM HD422 540p */
13724     case GST_MAKE_FOURCC ('A', 'V', 'm', 'p'): /* AVID IMX PAL */
13725     case GST_MAKE_FOURCC ('m', 'p', 'g', '2'): /* AVID IMX PAL */
13726     case GST_MAKE_FOURCC ('m', 'p', '2', 'v'): /* AVID IMX PAL */
13727     case GST_MAKE_FOURCC ('m', '2', 'v', '1'):
13728       _codec ("MPEG-2 video");
13729       caps = gst_caps_new_simple ("video/mpeg", "mpegversion", G_TYPE_INT, 2,
13730           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
13731       break;
13732     case GST_MAKE_FOURCC ('g', 'i', 'f', ' '):
13733       _codec ("GIF still images");
13734       caps = gst_caps_new_empty_simple ("image/gif");
13735       break;
13736     case FOURCC_h263:
13737     case GST_MAKE_FOURCC ('H', '2', '6', '3'):
13738     case FOURCC_s263:
13739     case GST_MAKE_FOURCC ('U', '2', '6', '3'):
13740       _codec ("H.263");
13741       /* ffmpeg uses the height/width props, don't know why */
13742       caps = gst_caps_new_simple ("video/x-h263",
13743           "variant", G_TYPE_STRING, "itu", NULL);
13744       break;
13745     case FOURCC_mp4v:
13746     case FOURCC_MP4V:
13747       _codec ("MPEG-4 video");
13748       caps = gst_caps_new_simple ("video/mpeg", "mpegversion", G_TYPE_INT, 4,
13749           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
13750       break;
13751     case GST_MAKE_FOURCC ('3', 'i', 'v', 'd'):
13752     case GST_MAKE_FOURCC ('3', 'I', 'V', 'D'):
13753       _codec ("Microsoft MPEG-4 4.3");  /* FIXME? */
13754       caps = gst_caps_new_simple ("video/x-msmpeg",
13755           "msmpegversion", G_TYPE_INT, 43, NULL);
13756       break;
13757     case GST_MAKE_FOURCC ('D', 'I', 'V', '3'):
13758       _codec ("DivX 3");
13759       caps = gst_caps_new_simple ("video/x-divx",
13760           "divxversion", G_TYPE_INT, 3, NULL);
13761       break;
13762     case GST_MAKE_FOURCC ('D', 'I', 'V', 'X'):
13763     case GST_MAKE_FOURCC ('d', 'i', 'v', 'x'):
13764       _codec ("DivX 4");
13765       caps = gst_caps_new_simple ("video/x-divx",
13766           "divxversion", G_TYPE_INT, 4, NULL);
13767       break;
13768     case GST_MAKE_FOURCC ('D', 'X', '5', '0'):
13769       _codec ("DivX 5");
13770       caps = gst_caps_new_simple ("video/x-divx",
13771           "divxversion", G_TYPE_INT, 5, NULL);
13772       break;
13773
13774     case GST_MAKE_FOURCC ('F', 'F', 'V', '1'):
13775       _codec ("FFV1");
13776       caps = gst_caps_new_simple ("video/x-ffv",
13777           "ffvversion", G_TYPE_INT, 1, NULL);
13778       break;
13779
13780     case GST_MAKE_FOURCC ('3', 'I', 'V', '1'):
13781     case GST_MAKE_FOURCC ('3', 'I', 'V', '2'):
13782     case FOURCC_XVID:
13783     case FOURCC_xvid:
13784     case FOURCC_FMP4:
13785     case FOURCC_fmp4:
13786     case GST_MAKE_FOURCC ('U', 'M', 'P', '4'):
13787       caps = gst_caps_new_simple ("video/mpeg", "mpegversion", G_TYPE_INT, 4,
13788           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
13789       _codec ("MPEG-4");
13790       break;
13791
13792     case GST_MAKE_FOURCC ('c', 'v', 'i', 'd'):
13793       _codec ("Cinepak");
13794       caps = gst_caps_new_empty_simple ("video/x-cinepak");
13795       break;
13796     case GST_MAKE_FOURCC ('q', 'd', 'r', 'w'):
13797       _codec ("Apple QuickDraw");
13798       caps = gst_caps_new_empty_simple ("video/x-qdrw");
13799       break;
13800     case GST_MAKE_FOURCC ('r', 'p', 'z', 'a'):
13801       _codec ("Apple video");
13802       caps = gst_caps_new_empty_simple ("video/x-apple-video");
13803       break;
13804     case FOURCC_H264:
13805     case FOURCC_avc1:
13806       _codec ("H.264 / AVC");
13807       caps = gst_caps_new_simple ("video/x-h264",
13808           "stream-format", G_TYPE_STRING, "avc",
13809           "alignment", G_TYPE_STRING, "au", NULL);
13810       break;
13811     case FOURCC_avc3:
13812       _codec ("H.264 / AVC");
13813       caps = gst_caps_new_simple ("video/x-h264",
13814           "stream-format", G_TYPE_STRING, "avc3",
13815           "alignment", G_TYPE_STRING, "au", NULL);
13816       break;
13817     case FOURCC_H265:
13818     case FOURCC_hvc1:
13819       _codec ("H.265 / HEVC");
13820       caps = gst_caps_new_simple ("video/x-h265",
13821           "stream-format", G_TYPE_STRING, "hvc1",
13822           "alignment", G_TYPE_STRING, "au", NULL);
13823       break;
13824     case FOURCC_hev1:
13825       _codec ("H.265 / HEVC");
13826       caps = gst_caps_new_simple ("video/x-h265",
13827           "stream-format", G_TYPE_STRING, "hev1",
13828           "alignment", G_TYPE_STRING, "au", NULL);
13829       break;
13830     case FOURCC_rle_:
13831       _codec ("Run-length encoding");
13832       caps = gst_caps_new_simple ("video/x-rle",
13833           "layout", G_TYPE_STRING, "quicktime", NULL);
13834       break;
13835     case FOURCC_WRLE:
13836       _codec ("Run-length encoding");
13837       caps = gst_caps_new_simple ("video/x-rle",
13838           "layout", G_TYPE_STRING, "microsoft", NULL);
13839       break;
13840     case GST_MAKE_FOURCC ('I', 'V', '3', '2'):
13841     case GST_MAKE_FOURCC ('i', 'v', '3', '2'):
13842       _codec ("Indeo Video 3");
13843       caps = gst_caps_new_simple ("video/x-indeo",
13844           "indeoversion", G_TYPE_INT, 3, NULL);
13845       break;
13846     case GST_MAKE_FOURCC ('I', 'V', '4', '1'):
13847     case GST_MAKE_FOURCC ('i', 'v', '4', '1'):
13848       _codec ("Intel Video 4");
13849       caps = gst_caps_new_simple ("video/x-indeo",
13850           "indeoversion", G_TYPE_INT, 4, NULL);
13851       break;
13852     case FOURCC_dvcp:
13853     case FOURCC_dvc_:
13854     case GST_MAKE_FOURCC ('d', 'v', 's', 'd'):
13855     case GST_MAKE_FOURCC ('D', 'V', 'S', 'D'):
13856     case GST_MAKE_FOURCC ('d', 'v', 'c', 's'):
13857     case GST_MAKE_FOURCC ('D', 'V', 'C', 'S'):
13858     case GST_MAKE_FOURCC ('d', 'v', '2', '5'):
13859     case GST_MAKE_FOURCC ('d', 'v', 'p', 'p'):
13860       _codec ("DV Video");
13861       caps = gst_caps_new_simple ("video/x-dv", "dvversion", G_TYPE_INT, 25,
13862           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
13863       break;
13864     case FOURCC_dv5n:          /* DVCPRO50 NTSC */
13865     case FOURCC_dv5p:          /* DVCPRO50 PAL */
13866       _codec ("DVCPro50 Video");
13867       caps = gst_caps_new_simple ("video/x-dv", "dvversion", G_TYPE_INT, 50,
13868           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
13869       break;
13870     case GST_MAKE_FOURCC ('d', 'v', 'h', '5'): /* DVCPRO HD 50i produced by FCP */
13871     case GST_MAKE_FOURCC ('d', 'v', 'h', '6'): /* DVCPRO HD 60i produced by FCP */
13872       _codec ("DVCProHD Video");
13873       caps = gst_caps_new_simple ("video/x-dv", "dvversion", G_TYPE_INT, 100,
13874           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
13875       break;
13876     case GST_MAKE_FOURCC ('s', 'm', 'c', ' '):
13877       _codec ("Apple Graphics (SMC)");
13878       caps = gst_caps_new_empty_simple ("video/x-smc");
13879       break;
13880     case GST_MAKE_FOURCC ('V', 'P', '3', '1'):
13881       _codec ("VP3");
13882       caps = gst_caps_new_empty_simple ("video/x-vp3");
13883       break;
13884     case GST_MAKE_FOURCC ('V', 'P', '6', 'F'):
13885       _codec ("VP6 Flash");
13886       caps = gst_caps_new_empty_simple ("video/x-vp6-flash");
13887       break;
13888     case FOURCC_XiTh:
13889       _codec ("Theora");
13890       caps = gst_caps_new_empty_simple ("video/x-theora");
13891       /* theora uses one byte of padding in the data stream because it does not
13892        * allow 0 sized packets while theora does */
13893       entry->padding = 1;
13894       break;
13895     case FOURCC_drac:
13896       _codec ("Dirac");
13897       caps = gst_caps_new_empty_simple ("video/x-dirac");
13898       break;
13899     case GST_MAKE_FOURCC ('t', 'i', 'f', 'f'):
13900       _codec ("TIFF still images");
13901       caps = gst_caps_new_empty_simple ("image/tiff");
13902       break;
13903     case GST_MAKE_FOURCC ('i', 'c', 'o', 'd'):
13904       _codec ("Apple Intermediate Codec");
13905       caps = gst_caps_from_string ("video/x-apple-intermediate-codec");
13906       break;
13907     case GST_MAKE_FOURCC ('A', 'V', 'd', 'n'):
13908       _codec ("AVID DNxHD");
13909       caps = gst_caps_from_string ("video/x-dnxhd");
13910       break;
13911     case FOURCC_VP80:
13912       _codec ("On2 VP8");
13913       caps = gst_caps_from_string ("video/x-vp8");
13914       break;
13915     case FOURCC_apcs:
13916       _codec ("Apple ProRes LT");
13917       caps =
13918           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING, "lt",
13919           NULL);
13920       break;
13921     case FOURCC_apch:
13922       _codec ("Apple ProRes HQ");
13923       caps =
13924           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING, "hq",
13925           NULL);
13926       break;
13927     case FOURCC_apcn:
13928       _codec ("Apple ProRes");
13929       caps =
13930           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING,
13931           "standard", NULL);
13932       break;
13933     case FOURCC_apco:
13934       _codec ("Apple ProRes Proxy");
13935       caps =
13936           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING,
13937           "proxy", NULL);
13938       break;
13939     case FOURCC_ap4h:
13940       _codec ("Apple ProRes 4444");
13941       caps =
13942           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING,
13943           "4444", NULL);
13944       break;
13945     case FOURCC_ap4x:
13946       _codec ("Apple ProRes 4444 XQ");
13947       caps =
13948           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING,
13949           "4444xq", NULL);
13950       break;
13951     case FOURCC_cfhd:
13952       _codec ("GoPro CineForm");
13953       caps = gst_caps_from_string ("video/x-cineform");
13954       break;
13955     case FOURCC_vc_1:
13956     case FOURCC_ovc1:
13957       _codec ("VC-1");
13958       caps = gst_caps_new_simple ("video/x-wmv",
13959           "wmvversion", G_TYPE_INT, 3, "format", G_TYPE_STRING, "WVC1", NULL);
13960       break;
13961     case GST_MAKE_FOURCC ('k', 'p', 'c', 'd'):
13962     default:
13963     {
13964       caps = _get_unknown_codec_name ("video", fourcc);
13965       break;
13966     }
13967   }
13968
13969   if (format != GST_VIDEO_FORMAT_UNKNOWN) {
13970     GstVideoInfo info;
13971
13972     gst_video_info_init (&info);
13973     gst_video_info_set_format (&info, format, entry->width, entry->height);
13974
13975     caps = gst_video_info_to_caps (&info);
13976     *codec_name = gst_pb_utils_get_codec_description (caps);
13977
13978     /* enable clipping for raw video streams */
13979     stream->need_clip = TRUE;
13980     stream->alignment = 32;
13981   }
13982
13983   return caps;
13984 }
13985
13986 static guint
13987 round_up_pow2 (guint n)
13988 {
13989   n = n - 1;
13990   n = n | (n >> 1);
13991   n = n | (n >> 2);
13992   n = n | (n >> 4);
13993   n = n | (n >> 8);
13994   n = n | (n >> 16);
13995   return n + 1;
13996 }
13997
13998 static GstCaps *
13999 qtdemux_audio_caps (GstQTDemux * qtdemux, QtDemuxStream * stream,
14000     QtDemuxStreamStsdEntry * entry, guint32 fourcc, const guint8 * data,
14001     int len, gchar ** codec_name)
14002 {
14003   GstCaps *caps;
14004   const GstStructure *s;
14005   const gchar *name;
14006   gint endian = 0;
14007   GstAudioFormat format = 0;
14008   gint depth;
14009
14010   GST_DEBUG_OBJECT (qtdemux, "resolve fourcc 0x%08x", GUINT32_TO_BE (fourcc));
14011
14012   depth = entry->bytes_per_packet * 8;
14013
14014   switch (fourcc) {
14015     case GST_MAKE_FOURCC ('N', 'O', 'N', 'E'):
14016     case FOURCC_raw_:
14017       /* 8-bit audio is unsigned */
14018       if (depth == 8)
14019         format = GST_AUDIO_FORMAT_U8;
14020       /* otherwise it's signed and big-endian just like 'twos' */
14021     case FOURCC_twos:
14022       endian = G_BIG_ENDIAN;
14023       /* fall-through */
14024     case FOURCC_sowt:
14025     {
14026       gchar *str;
14027
14028       if (!endian)
14029         endian = G_LITTLE_ENDIAN;
14030
14031       if (!format)
14032         format = gst_audio_format_build_integer (TRUE, endian, depth, depth);
14033
14034       str = g_strdup_printf ("Raw %d-bit PCM audio", depth);
14035       _codec (str);
14036       g_free (str);
14037
14038       caps = gst_caps_new_simple ("audio/x-raw",
14039           "format", G_TYPE_STRING, gst_audio_format_to_string (format),
14040           "layout", G_TYPE_STRING, "interleaved", NULL);
14041       stream->alignment = GST_ROUND_UP_8 (depth);
14042       stream->alignment = round_up_pow2 (stream->alignment);
14043       break;
14044     }
14045     case GST_MAKE_FOURCC ('f', 'l', '6', '4'):
14046       _codec ("Raw 64-bit floating-point audio");
14047       caps = gst_caps_new_simple ("audio/x-raw",
14048           "format", G_TYPE_STRING, "F64BE",
14049           "layout", G_TYPE_STRING, "interleaved", NULL);
14050       stream->alignment = 8;
14051       break;
14052     case GST_MAKE_FOURCC ('f', 'l', '3', '2'):
14053       _codec ("Raw 32-bit floating-point audio");
14054       caps = gst_caps_new_simple ("audio/x-raw",
14055           "format", G_TYPE_STRING, "F32BE",
14056           "layout", G_TYPE_STRING, "interleaved", NULL);
14057       stream->alignment = 4;
14058       break;
14059     case FOURCC_in24:
14060       _codec ("Raw 24-bit PCM audio");
14061       /* we assume BIG ENDIAN, an enda box will tell us to change this to little
14062        * endian later */
14063       caps = gst_caps_new_simple ("audio/x-raw",
14064           "format", G_TYPE_STRING, "S24BE",
14065           "layout", G_TYPE_STRING, "interleaved", NULL);
14066       stream->alignment = 4;
14067       break;
14068     case GST_MAKE_FOURCC ('i', 'n', '3', '2'):
14069       _codec ("Raw 32-bit PCM audio");
14070       caps = gst_caps_new_simple ("audio/x-raw",
14071           "format", G_TYPE_STRING, "S32BE",
14072           "layout", G_TYPE_STRING, "interleaved", NULL);
14073       stream->alignment = 4;
14074       break;
14075     case GST_MAKE_FOURCC ('s', '1', '6', 'l'):
14076       _codec ("Raw 16-bit PCM audio");
14077       caps = gst_caps_new_simple ("audio/x-raw",
14078           "format", G_TYPE_STRING, "S16LE",
14079           "layout", G_TYPE_STRING, "interleaved", NULL);
14080       stream->alignment = 2;
14081       break;
14082     case FOURCC_ulaw:
14083       _codec ("Mu-law audio");
14084       caps = gst_caps_new_empty_simple ("audio/x-mulaw");
14085       break;
14086     case FOURCC_alaw:
14087       _codec ("A-law audio");
14088       caps = gst_caps_new_empty_simple ("audio/x-alaw");
14089       break;
14090     case 0x0200736d:
14091     case 0x6d730002:
14092       _codec ("Microsoft ADPCM");
14093       /* Microsoft ADPCM-ACM code 2 */
14094       caps = gst_caps_new_simple ("audio/x-adpcm",
14095           "layout", G_TYPE_STRING, "microsoft", NULL);
14096       break;
14097     case 0x1100736d:
14098     case 0x6d730011:
14099       _codec ("DVI/IMA ADPCM");
14100       caps = gst_caps_new_simple ("audio/x-adpcm",
14101           "layout", G_TYPE_STRING, "dvi", NULL);
14102       break;
14103     case 0x1700736d:
14104     case 0x6d730017:
14105       _codec ("DVI/Intel IMA ADPCM");
14106       /* FIXME DVI/Intel IMA ADPCM/ACM code 17 */
14107       caps = gst_caps_new_simple ("audio/x-adpcm",
14108           "layout", G_TYPE_STRING, "quicktime", NULL);
14109       break;
14110     case 0x5500736d:
14111     case 0x6d730055:
14112       /* MPEG layer 3, CBR only (pre QT4.1) */
14113     case FOURCC__mp3:
14114       _codec ("MPEG-1 layer 3");
14115       /* MPEG layer 3, CBR & VBR (QT4.1 and later) */
14116       caps = gst_caps_new_simple ("audio/mpeg", "layer", G_TYPE_INT, 3,
14117           "mpegversion", G_TYPE_INT, 1, NULL);
14118       break;
14119     case GST_MAKE_FOURCC ('.', 'm', 'p', '2'):
14120       _codec ("MPEG-1 layer 2");
14121       /* MPEG layer 2 */
14122       caps = gst_caps_new_simple ("audio/mpeg", "layer", G_TYPE_INT, 2,
14123           "mpegversion", G_TYPE_INT, 1, NULL);
14124       break;
14125     case 0x20736d:
14126     case GST_MAKE_FOURCC ('e', 'c', '-', '3'):
14127       _codec ("EAC-3 audio");
14128       caps = gst_caps_new_simple ("audio/x-eac3",
14129           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
14130       entry->sampled = TRUE;
14131       break;
14132     case GST_MAKE_FOURCC ('s', 'a', 'c', '3'): // Nero Recode
14133     case FOURCC_ac_3:
14134       _codec ("AC-3 audio");
14135       caps = gst_caps_new_simple ("audio/x-ac3",
14136           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
14137       entry->sampled = TRUE;
14138       break;
14139     case GST_MAKE_FOURCC ('d', 't', 's', 'c'):
14140     case GST_MAKE_FOURCC ('D', 'T', 'S', ' '):
14141       _codec ("DTS audio");
14142       caps = gst_caps_new_simple ("audio/x-dts",
14143           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
14144       entry->sampled = TRUE;
14145       break;
14146     case GST_MAKE_FOURCC ('d', 't', 's', 'h'): // DTS-HD
14147     case GST_MAKE_FOURCC ('d', 't', 's', 'l'): // DTS-HD Lossless
14148       _codec ("DTS-HD audio");
14149       caps = gst_caps_new_simple ("audio/x-dts",
14150           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
14151       entry->sampled = TRUE;
14152       break;
14153     case FOURCC_MAC3:
14154       _codec ("MACE-3");
14155       caps = gst_caps_new_simple ("audio/x-mace",
14156           "maceversion", G_TYPE_INT, 3, NULL);
14157       break;
14158     case FOURCC_MAC6:
14159       _codec ("MACE-6");
14160       caps = gst_caps_new_simple ("audio/x-mace",
14161           "maceversion", G_TYPE_INT, 6, NULL);
14162       break;
14163     case GST_MAKE_FOURCC ('O', 'g', 'g', 'V'):
14164       /* ogg/vorbis */
14165       caps = gst_caps_new_empty_simple ("application/ogg");
14166       break;
14167     case GST_MAKE_FOURCC ('d', 'v', 'c', 'a'):
14168       _codec ("DV audio");
14169       caps = gst_caps_new_empty_simple ("audio/x-dv");
14170       break;
14171     case FOURCC_mp4a:
14172       _codec ("MPEG-4 AAC audio");
14173       caps = gst_caps_new_simple ("audio/mpeg",
14174           "mpegversion", G_TYPE_INT, 4, "framed", G_TYPE_BOOLEAN, TRUE,
14175           "stream-format", G_TYPE_STRING, "raw", NULL);
14176       break;
14177     case GST_MAKE_FOURCC ('Q', 'D', 'M', 'C'):
14178       _codec ("QDesign Music");
14179       caps = gst_caps_new_empty_simple ("audio/x-qdm");
14180       break;
14181     case FOURCC_QDM2:
14182       _codec ("QDesign Music v.2");
14183       /* FIXME: QDesign music version 2 (no constant) */
14184       if (FALSE && data) {
14185         caps = gst_caps_new_simple ("audio/x-qdm2",
14186             "framesize", G_TYPE_INT, QT_UINT32 (data + 52),
14187             "bitrate", G_TYPE_INT, QT_UINT32 (data + 40),
14188             "blocksize", G_TYPE_INT, QT_UINT32 (data + 44), NULL);
14189       } else {
14190         caps = gst_caps_new_empty_simple ("audio/x-qdm2");
14191       }
14192       break;
14193     case FOURCC_agsm:
14194       _codec ("GSM audio");
14195       caps = gst_caps_new_empty_simple ("audio/x-gsm");
14196       break;
14197     case FOURCC_samr:
14198       _codec ("AMR audio");
14199       caps = gst_caps_new_empty_simple ("audio/AMR");
14200       break;
14201     case FOURCC_sawb:
14202       _codec ("AMR-WB audio");
14203       caps = gst_caps_new_empty_simple ("audio/AMR-WB");
14204       break;
14205     case FOURCC_ima4:
14206       _codec ("Quicktime IMA ADPCM");
14207       caps = gst_caps_new_simple ("audio/x-adpcm",
14208           "layout", G_TYPE_STRING, "quicktime", NULL);
14209       break;
14210     case FOURCC_alac:
14211       _codec ("Apple lossless audio");
14212       caps = gst_caps_new_empty_simple ("audio/x-alac");
14213       break;
14214     case FOURCC_fLaC:
14215       _codec ("Free Lossless Audio Codec");
14216       caps = gst_caps_new_simple ("audio/x-flac",
14217           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
14218       break;
14219     case GST_MAKE_FOURCC ('Q', 'c', 'l', 'p'):
14220       _codec ("QualComm PureVoice");
14221       caps = gst_caps_from_string ("audio/qcelp");
14222       break;
14223     case FOURCC_wma_:
14224     case FOURCC_owma:
14225       _codec ("WMA");
14226       caps = gst_caps_new_empty_simple ("audio/x-wma");
14227       break;
14228     case FOURCC_opus:
14229       _codec ("Opus");
14230       caps = gst_caps_new_empty_simple ("audio/x-opus");
14231       break;
14232     case GST_MAKE_FOURCC ('l', 'p', 'c', 'm'):
14233     {
14234       guint32 flags = 0;
14235       guint32 depth = 0;
14236       guint32 width = 0;
14237       GstAudioFormat format;
14238       enum
14239       {
14240         FLAG_IS_FLOAT = 0x1,
14241         FLAG_IS_BIG_ENDIAN = 0x2,
14242         FLAG_IS_SIGNED = 0x4,
14243         FLAG_IS_PACKED = 0x8,
14244         FLAG_IS_ALIGNED_HIGH = 0x10,
14245         FLAG_IS_NON_INTERLEAVED = 0x20
14246       };
14247       _codec ("Raw LPCM audio");
14248
14249       if (data && len >= 56) {
14250         depth = QT_UINT32 (data + 40);
14251         flags = QT_UINT32 (data + 44);
14252         width = QT_UINT32 (data + 48) * 8 / entry->n_channels;
14253       }
14254       if ((flags & FLAG_IS_FLOAT) == 0) {
14255         if (depth == 0)
14256           depth = 16;
14257         if (width == 0)
14258           width = 16;
14259         format = gst_audio_format_build_integer ((flags & FLAG_IS_SIGNED) ?
14260             TRUE : FALSE, (flags & FLAG_IS_BIG_ENDIAN) ?
14261             G_BIG_ENDIAN : G_LITTLE_ENDIAN, width, depth);
14262         caps = gst_caps_new_simple ("audio/x-raw",
14263             "format", G_TYPE_STRING, gst_audio_format_to_string (format),
14264             "layout", G_TYPE_STRING, (flags & FLAG_IS_NON_INTERLEAVED) ?
14265             "non-interleaved" : "interleaved", NULL);
14266         stream->alignment = GST_ROUND_UP_8 (depth);
14267         stream->alignment = round_up_pow2 (stream->alignment);
14268       } else {
14269         if (width == 0)
14270           width = 32;
14271         if (width == 64) {
14272           if (flags & FLAG_IS_BIG_ENDIAN)
14273             format = GST_AUDIO_FORMAT_F64BE;
14274           else
14275             format = GST_AUDIO_FORMAT_F64LE;
14276         } else {
14277           if (flags & FLAG_IS_BIG_ENDIAN)
14278             format = GST_AUDIO_FORMAT_F32BE;
14279           else
14280             format = GST_AUDIO_FORMAT_F32LE;
14281         }
14282         caps = gst_caps_new_simple ("audio/x-raw",
14283             "format", G_TYPE_STRING, gst_audio_format_to_string (format),
14284             "layout", G_TYPE_STRING, (flags & FLAG_IS_NON_INTERLEAVED) ?
14285             "non-interleaved" : "interleaved", NULL);
14286         stream->alignment = width / 8;
14287       }
14288       break;
14289     }
14290     case GST_MAKE_FOURCC ('q', 't', 'v', 'r'):
14291       /* ? */
14292     default:
14293     {
14294       caps = _get_unknown_codec_name ("audio", fourcc);
14295       break;
14296     }
14297   }
14298
14299   if (caps) {
14300     GstCaps *templ_caps =
14301         gst_static_pad_template_get_caps (&gst_qtdemux_audiosrc_template);
14302     GstCaps *intersection = gst_caps_intersect (caps, templ_caps);
14303     gst_caps_unref (caps);
14304     gst_caps_unref (templ_caps);
14305     caps = intersection;
14306   }
14307
14308   /* enable clipping for raw audio streams */
14309   s = gst_caps_get_structure (caps, 0);
14310   name = gst_structure_get_name (s);
14311   if (g_str_has_prefix (name, "audio/x-raw")) {
14312     stream->need_clip = TRUE;
14313     stream->max_buffer_size = 4096 * entry->bytes_per_frame;
14314     GST_DEBUG ("setting max buffer size to %d", stream->max_buffer_size);
14315   }
14316   return caps;
14317 }
14318
14319 static GstCaps *
14320 qtdemux_sub_caps (GstQTDemux * qtdemux, QtDemuxStream * stream,
14321     QtDemuxStreamStsdEntry * entry, guint32 fourcc,
14322     const guint8 * stsd_entry_data, gchar ** codec_name)
14323 {
14324   GstCaps *caps;
14325
14326   GST_DEBUG_OBJECT (qtdemux, "resolve fourcc 0x%08x", GUINT32_TO_BE (fourcc));
14327
14328   switch (fourcc) {
14329     case FOURCC_mp4s:
14330       _codec ("DVD subtitle");
14331       caps = gst_caps_new_empty_simple ("subpicture/x-dvd");
14332       stream->need_process = TRUE;
14333       break;
14334     case FOURCC_text:
14335       _codec ("Quicktime timed text");
14336       goto text;
14337     case FOURCC_tx3g:
14338       _codec ("3GPP timed text");
14339     text:
14340       caps = gst_caps_new_simple ("text/x-raw", "format", G_TYPE_STRING,
14341           "utf8", NULL);
14342       /* actual text piece needs to be extracted */
14343       stream->need_process = TRUE;
14344       break;
14345     case FOURCC_stpp:
14346       _codec ("XML subtitles");
14347       caps = gst_caps_new_empty_simple ("application/ttml+xml");
14348       break;
14349     default:
14350     {
14351       caps = _get_unknown_codec_name ("text", fourcc);
14352       break;
14353     }
14354   }
14355   return caps;
14356 }
14357
14358 static GstCaps *
14359 qtdemux_generic_caps (GstQTDemux * qtdemux, QtDemuxStream * stream,
14360     QtDemuxStreamStsdEntry * entry, guint32 fourcc,
14361     const guint8 * stsd_entry_data, gchar ** codec_name)
14362 {
14363   GstCaps *caps;
14364
14365   switch (fourcc) {
14366     case FOURCC_m1v:
14367       _codec ("MPEG 1 video");
14368       caps = gst_caps_new_simple ("video/mpeg", "mpegversion", G_TYPE_INT, 1,
14369           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
14370       break;
14371     default:
14372       caps = NULL;
14373       break;
14374   }
14375   return caps;
14376 }
14377
14378 static void
14379 gst_qtdemux_append_protection_system_id (GstQTDemux * qtdemux,
14380     const gchar * system_id)
14381 {
14382   gint i;
14383
14384   if (!qtdemux->protection_system_ids)
14385     qtdemux->protection_system_ids =
14386         g_ptr_array_new_with_free_func ((GDestroyNotify) g_free);
14387   /* Check whether we already have an entry for this system ID. */
14388   for (i = 0; i < qtdemux->protection_system_ids->len; ++i) {
14389     const gchar *id = g_ptr_array_index (qtdemux->protection_system_ids, i);
14390     if (g_ascii_strcasecmp (system_id, id) == 0) {
14391       return;
14392     }
14393   }
14394   GST_DEBUG_OBJECT (qtdemux, "Adding cenc protection system ID %s", system_id);
14395   g_ptr_array_add (qtdemux->protection_system_ids, g_ascii_strdown (system_id,
14396           -1));
14397 }