406c6c8f95fdcc2082ecc6833eea4ff9c42dad9a
[platform/upstream/gst-plugins-good.git] / gst / isomp4 / qtdemux.c
1 /* GStreamer
2  * Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu>
3  * Copyright (C) <2003> David A. Schleef <ds@schleef.org>
4  * Copyright (C) <2006> Wim Taymans <wim@fluendo.com>
5  * Copyright (C) <2007> Julien Moutte <julien@fluendo.com>
6  * Copyright (C) <2009> Tim-Philipp Müller <tim centricular net>
7  * Copyright (C) <2009> STEricsson <benjamin.gaignard@stericsson.com>
8  * Copyright (C) <2013> Sreerenj Balachandran <sreerenj.balachandran@intel.com>
9  * Copyright (C) <2013> Intel Corporation
10  * Copyright (C) <2014> Centricular Ltd
11  * Copyright (C) <2015> YouView TV Ltd.
12  * Copyright (C) <2016> British Broadcasting Corporation
13  *
14  * This library is free software; you can redistribute it and/or
15  * modify it under the terms of the GNU Library General Public
16  * License as published by the Free Software Foundation; either
17  * version 2 of the License, or (at your option) any later version.
18  *
19  * This library is distributed in the hope that it will be useful,
20  * but WITHOUT ANY WARRANTY; without even the implied warranty of
21  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
22  * Library General Public License for more details.
23  *
24  * You should have received a copy of the GNU Library General Public
25  * License along with this library; if not, write to the
26  * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
27  * Boston, MA 02110-1301, USA.
28  */
29
30 /**
31  * SECTION:element-qtdemux
32  *
33  * Demuxes a .mov file into raw or compressed audio and/or video streams.
34  *
35  * This element supports both push and pull-based scheduling, depending on the
36  * capabilities of the upstream elements.
37  *
38  * <refsect2>
39  * <title>Example launch line</title>
40  * |[
41  * gst-launch-1.0 filesrc location=test.mov ! qtdemux name=demux  demux.audio_0 ! queue ! decodebin ! audioconvert ! audioresample ! autoaudiosink   demux.video_0 ! queue ! decodebin ! videoconvert ! videoscale ! autovideosink
42  * ]| Play (parse and decode) a .mov file and try to output it to
43  * an automatically detected soundcard and videosink. If the MOV file contains
44  * compressed audio or video data, this will only work if you have the
45  * right decoder elements/plugins installed.
46  * </refsect2>
47  */
48
49 #ifdef HAVE_CONFIG_H
50 #include "config.h"
51 #endif
52
53 #include "gst/gst-i18n-plugin.h"
54
55 #include <glib/gprintf.h>
56 #include <gst/tag/tag.h>
57 #include <gst/audio/audio.h>
58 #include <gst/video/video.h>
59 #include <gst/riff/riff.h>
60 #include <gst/pbutils/pbutils.h>
61
62 #include "qtatomparser.h"
63 #include "qtdemux_types.h"
64 #include "qtdemux_dump.h"
65 #include "fourcc.h"
66 #include "descriptors.h"
67 #include "qtdemux_lang.h"
68 #include "qtdemux.h"
69 #include "qtpalette.h"
70
71 #include <stdio.h>
72 #include <stdlib.h>
73 #include <string.h>
74
75 #include <math.h>
76 #include <gst/math-compat.h>
77
78 #ifdef HAVE_ZLIB
79 # include <zlib.h>
80 #endif
81
82 /* max. size considered 'sane' for non-mdat atoms */
83 #define QTDEMUX_MAX_ATOM_SIZE (25*1024*1024)
84
85 /* if the sample index is larger than this, something is likely wrong */
86 #define QTDEMUX_MAX_SAMPLE_INDEX_SIZE (200*1024*1024)
87
88 /* For converting qt creation times to unix epoch times */
89 #define QTDEMUX_SECONDS_PER_DAY (60 * 60 * 24)
90 #define QTDEMUX_LEAP_YEARS_FROM_1904_TO_1970 17
91 #define QTDEMUX_SECONDS_FROM_1904_TO_1970 (((1970 - 1904) * (guint64) 365 + \
92     QTDEMUX_LEAP_YEARS_FROM_1904_TO_1970) * QTDEMUX_SECONDS_PER_DAY)
93
94 #define QTDEMUX_TREE_NODE_FOURCC(n) (QT_FOURCC(((guint8 *) (n)->data) + 4))
95
96 #define STREAM_IS_EOS(s) ((s)->time_position == GST_CLOCK_TIME_NONE)
97
98 #define ABSDIFF(x, y) ( (x) > (y) ? ((x) - (y)) : ((y) - (x)) )
99
100 #define QTDEMUX_FIRST_STREAM(demux) ((QtDemuxStream *)(demux)->active_streams \
101   ? (QtDemuxStream *)(demux)->active_streams->data : NULL)
102 #define QTDEMUX_STREAM(s) ((QtDemuxStream *)(s))
103
104 GST_DEBUG_CATEGORY (qtdemux_debug);
105 #define GST_CAT_DEFAULT qtdemux_debug
106
107 typedef struct _QtDemuxSegment QtDemuxSegment;
108 typedef struct _QtDemuxSample QtDemuxSample;
109
110 typedef struct _QtDemuxCencSampleSetInfo QtDemuxCencSampleSetInfo;
111
112 struct _QtDemuxSample
113 {
114   guint32 size;
115   gint32 pts_offset;            /* Add this value to timestamp to get the pts */
116   guint64 offset;
117   guint64 timestamp;            /* DTS In mov time */
118   guint32 duration;             /* In mov time */
119   gboolean keyframe;            /* TRUE when this packet is a keyframe */
120 };
121
122 /* Macros for converting to/from timescale */
123 #define QTSTREAMTIME_TO_GSTTIME(stream, value) (gst_util_uint64_scale((value), GST_SECOND, (stream)->timescale))
124 #define GSTTIME_TO_QTSTREAMTIME(stream, value) (gst_util_uint64_scale((value), (stream)->timescale, GST_SECOND))
125
126 #define QTTIME_TO_GSTTIME(qtdemux, value) (gst_util_uint64_scale((value), GST_SECOND, (qtdemux)->timescale))
127 #define GSTTIME_TO_QTTIME(qtdemux, value) (gst_util_uint64_scale((value), (qtdemux)->timescale, GST_SECOND))
128
129 /* timestamp is the DTS */
130 #define QTSAMPLE_DTS(stream,sample) (QTSTREAMTIME_TO_GSTTIME((stream), (sample)->timestamp))
131 /* timestamp + offset + cslg_shift is the outgoing PTS */
132 #define QTSAMPLE_PTS(stream,sample) (QTSTREAMTIME_TO_GSTTIME((stream), (sample)->timestamp + (stream)->cslg_shift + (sample)->pts_offset))
133 /* timestamp + offset is the PTS used for internal seek calcuations */
134 #define QTSAMPLE_PTS_NO_CSLG(stream,sample) (QTSTREAMTIME_TO_GSTTIME((stream), (sample)->timestamp + (sample)->pts_offset))
135 /* timestamp + duration - dts is the duration */
136 #define QTSAMPLE_DUR_DTS(stream, sample, dts) (QTSTREAMTIME_TO_GSTTIME ((stream), (sample)->timestamp + (sample)->duration) - (dts))
137
138 #define QTSAMPLE_KEYFRAME(stream,sample) ((stream)->all_keyframe || (sample)->keyframe)
139
140 #define QTDEMUX_EXPOSE_GET_LOCK(demux) (&((demux)->expose_lock))
141 #define QTDEMUX_EXPOSE_LOCK(demux) G_STMT_START { \
142     GST_TRACE("Locking from thread %p", g_thread_self()); \
143     g_mutex_lock (QTDEMUX_EXPOSE_GET_LOCK (demux)); \
144     GST_TRACE("Locked from thread %p", g_thread_self()); \
145  } G_STMT_END
146
147 #define QTDEMUX_EXPOSE_UNLOCK(demux) G_STMT_START { \
148     GST_TRACE("Unlocking from thread %p", g_thread_self()); \
149     g_mutex_unlock (QTDEMUX_EXPOSE_GET_LOCK (demux)); \
150  } G_STMT_END
151
152 /*
153  * Quicktime has tracks and segments. A track is a continuous piece of
154  * multimedia content. The track is not always played from start to finish but
155  * instead, pieces of the track are 'cut out' and played in sequence. This is
156  * what the segments do.
157  *
158  * Inside the track we have keyframes (K) and delta frames. The track has its
159  * own timing, which starts from 0 and extends to end. The position in the track
160  * is called the media_time.
161  *
162  * The segments now describe the pieces that should be played from this track
163  * and are basically tuples of media_time/duration/rate entries. We can have
164  * multiple segments and they are all played after one another. An example:
165  *
166  * segment 1: media_time: 1 second, duration: 1 second, rate 1
167  * segment 2: media_time: 3 second, duration: 2 second, rate 2
168  *
169  * To correctly play back this track, one must play: 1 second of media starting
170  * from media_time 1 followed by 2 seconds of media starting from media_time 3
171  * at a rate of 2.
172  *
173  * Each of the segments will be played at a specific time, the first segment at
174  * time 0, the second one after the duration of the first one, etc.. Note that
175  * the time in resulting playback is not identical to the media_time of the
176  * track anymore.
177  *
178  * Visually, assuming the track has 4 second of media_time:
179  *
180  *                (a)                   (b)          (c)              (d)
181  *         .-----------------------------------------------------------.
182  * track:  | K.....K.........K........K.......K.......K...........K... |
183  *         '-----------------------------------------------------------'
184  *         0              1              2              3              4
185  *           .------------^              ^   .----------^              ^
186  *          /              .-------------'  /       .------------------'
187  *         /              /          .-----'       /
188  *         .--------------.         .--------------.
189  *         | segment 1    |         | segment 2    |
190  *         '--------------'         '--------------'
191  *
192  * The challenge here is to cut out the right pieces of the track for each of
193  * the playback segments. This fortunately can easily be done with the SEGMENT
194  * events of GStreamer.
195  *
196  * For playback of segment 1, we need to provide the decoder with the keyframe
197  * (a), in the above figure, but we must instruct it only to output the decoded
198  * data between second 1 and 2. We do this with a SEGMENT event for 1 to 2, time
199  * position set to the time of the segment: 0.
200  *
201  * We then proceed to push data from keyframe (a) to frame (b). The decoder
202  * decodes but clips all before media_time 1.
203  *
204  * After finishing a segment, we push out a new SEGMENT event with the clipping
205  * boundaries of the new data.
206  *
207  * This is a good usecase for the GStreamer accumulated SEGMENT events.
208  */
209
210 struct _QtDemuxSegment
211 {
212   /* global time and duration, all gst time */
213   GstClockTime time;
214   GstClockTime stop_time;
215   GstClockTime duration;
216   /* media time of trak, all gst time */
217   GstClockTime media_start;
218   GstClockTime media_stop;
219   gdouble rate;
220   /* Media start time in trak timescale units */
221   guint32 trak_media_start;
222 };
223
224 #define QTSEGMENT_IS_EMPTY(s) ((s)->media_start == GST_CLOCK_TIME_NONE)
225
226 /* Used with fragmented MP4 files (mfra atom) */
227 typedef struct
228 {
229   GstClockTime ts;
230   guint64 moof_offset;
231 } QtDemuxRandomAccessEntry;
232
233 typedef struct _QtDemuxStreamStsdEntry
234 {
235   GstCaps *caps;
236   guint32 fourcc;
237   gboolean sparse;
238
239   /* video info */
240   gint width;
241   gint height;
242   gint par_w;
243   gint par_h;
244   /* Numerator/denominator framerate */
245   gint fps_n;
246   gint fps_d;
247   GstVideoColorimetry colorimetry;
248   guint16 bits_per_sample;
249   guint16 color_table_id;
250   GstMemory *rgb8_palette;
251   guint interlace_mode;
252   guint field_order;
253
254   /* audio info */
255   gdouble rate;
256   gint n_channels;
257   guint samples_per_packet;
258   guint samples_per_frame;
259   guint bytes_per_packet;
260   guint bytes_per_sample;
261   guint bytes_per_frame;
262   guint compression;
263
264   /* if we use chunks or samples */
265   gboolean sampled;
266   guint padding;
267
268 } QtDemuxStreamStsdEntry;
269
270 #define CUR_STREAM(s) (&((s)->stsd_entries[(s)->cur_stsd_entry_index]))
271
272 struct _QtDemuxStream
273 {
274   GstPad *pad;
275
276   GstQTDemux *demux;
277   gchar *stream_id;
278
279   QtDemuxStreamStsdEntry *stsd_entries;
280   guint stsd_entries_length;
281   guint cur_stsd_entry_index;
282
283   /* stream type */
284   guint32 subtype;
285
286   gboolean new_caps;            /* If TRUE, caps need to be generated (by
287                                  * calling _configure_stream()) This happens
288                                  * for MSS and fragmented streams */
289
290   gboolean new_stream;          /* signals that a stream_start is required */
291   gboolean on_keyframe;         /* if this stream last pushed buffer was a
292                                  * keyframe. This is important to identify
293                                  * where to stop pushing buffers after a
294                                  * segment stop time */
295
296   /* if the stream has a redirect URI in its headers, we store it here */
297   gchar *redirect_uri;
298
299   /* track id */
300   guint track_id;
301
302   /* duration/scale */
303   guint64 duration;             /* in timescale units */
304   guint32 timescale;
305
306   /* language */
307   gchar lang_id[4];             /* ISO 639-2T language code */
308
309   /* our samples */
310   guint32 n_samples;
311   QtDemuxSample *samples;
312   gboolean all_keyframe;        /* TRUE when all samples are keyframes (no stss) */
313   guint32 n_samples_moof;       /* sample count in a moof */
314   guint64 duration_moof;        /* duration in timescale of a moof, used for figure out
315                                  * the framerate of fragmented format stream */
316   guint64 duration_last_moof;
317
318   guint32 offset_in_sample;     /* Offset in the current sample, used for
319                                  * streams which have got exceedingly big
320                                  * sample size (such as 24s of raw audio).
321                                  * Only used when max_buffer_size is non-NULL */
322   guint32 max_buffer_size;      /* Maximum allowed size for output buffers.
323                                  * Currently only set for raw audio streams*/
324
325   /* video info */
326   /* aspect ratio */
327   gint display_width;
328   gint display_height;
329
330   /* allocation */
331   gboolean use_allocator;
332   GstAllocator *allocator;
333   GstAllocationParams params;
334
335   gsize alignment;
336
337   /* when a discontinuity is pending */
338   gboolean discont;
339
340   /* list of buffers to push first */
341   GSList *buffers;
342
343   /* if we need to clip this buffer. This is only needed for uncompressed
344    * data */
345   gboolean need_clip;
346
347   /* buffer needs some custom processing, e.g. subtitles */
348   gboolean need_process;
349
350   /* current position */
351   guint32 segment_index;
352   guint32 sample_index;
353   GstClockTime time_position;   /* in gst time */
354   guint64 accumulated_base;
355
356   /* the Gst segment we are processing out, used for clipping */
357   GstSegment segment;
358
359   /* quicktime segments */
360   guint32 n_segments;
361   QtDemuxSegment *segments;
362   gboolean dummy_segment;
363   guint32 from_sample;
364   guint32 to_sample;
365
366   gboolean sent_eos;
367   GstTagList *stream_tags;
368   gboolean send_global_tags;
369
370   GstEvent *pending_event;
371
372   GstByteReader stco;
373   GstByteReader stsz;
374   GstByteReader stsc;
375   GstByteReader stts;
376   GstByteReader stss;
377   GstByteReader stps;
378   GstByteReader ctts;
379
380   gboolean chunks_are_samples;  /* TRUE means treat chunks as samples */
381   gint64 stbl_index;
382   /* stco */
383   guint co_size;
384   GstByteReader co_chunk;
385   guint32 first_chunk;
386   guint32 current_chunk;
387   guint32 last_chunk;
388   guint32 samples_per_chunk;
389   guint32 stsd_sample_description_id;
390   guint32 stco_sample_index;
391   /* stsz */
392   guint32 sample_size;          /* 0 means variable sizes are stored in stsz */
393   /* stsc */
394   guint32 stsc_index;
395   guint32 n_samples_per_chunk;
396   guint32 stsc_chunk_index;
397   guint32 stsc_sample_index;
398   guint64 chunk_offset;
399   /* stts */
400   guint32 stts_index;
401   guint32 stts_samples;
402   guint32 n_sample_times;
403   guint32 stts_sample_index;
404   guint64 stts_time;
405   guint32 stts_duration;
406   /* stss */
407   gboolean stss_present;
408   guint32 n_sample_syncs;
409   guint32 stss_index;
410   /* stps */
411   gboolean stps_present;
412   guint32 n_sample_partial_syncs;
413   guint32 stps_index;
414   QtDemuxRandomAccessEntry *ra_entries;
415   guint n_ra_entries;
416
417   const QtDemuxRandomAccessEntry *pending_seek;
418
419   /* ctts */
420   gboolean ctts_present;
421   guint32 n_composition_times;
422   guint32 ctts_index;
423   guint32 ctts_sample_index;
424   guint32 ctts_count;
425   gint32 ctts_soffset;
426
427   /* cslg */
428   guint32 cslg_shift;
429
430   /* fragmented */
431   gboolean parsed_trex;
432   guint32 def_sample_description_index; /* index is 1-based */
433   guint32 def_sample_duration;
434   guint32 def_sample_size;
435   guint32 def_sample_flags;
436
437   gboolean disabled;
438
439   /* stereoscopic video streams */
440   GstVideoMultiviewMode multiview_mode;
441   GstVideoMultiviewFlags multiview_flags;
442
443   /* protected streams */
444   gboolean protected;
445   guint32 protection_scheme_type;
446   guint32 protection_scheme_version;
447   gpointer protection_scheme_info;      /* specific to the protection scheme */
448   GQueue protection_scheme_event_queue;
449 };
450
451 /* Contains properties and cryptographic info for a set of samples from a
452  * track protected using Common Encryption (cenc) */
453 struct _QtDemuxCencSampleSetInfo
454 {
455   GstStructure *default_properties;
456
457   /* @crypto_info holds one GstStructure per sample */
458   GPtrArray *crypto_info;
459 };
460
461 static const gchar *
462 qt_demux_state_string (enum QtDemuxState state)
463 {
464   switch (state) {
465     case QTDEMUX_STATE_INITIAL:
466       return "<INITIAL>";
467     case QTDEMUX_STATE_HEADER:
468       return "<HEADER>";
469     case QTDEMUX_STATE_MOVIE:
470       return "<MOVIE>";
471     case QTDEMUX_STATE_BUFFER_MDAT:
472       return "<BUFFER_MDAT>";
473     default:
474       return "<UNKNOWN>";
475   }
476 }
477
478 static GNode *qtdemux_tree_get_child_by_type (GNode * node, guint32 fourcc);
479 static GNode *qtdemux_tree_get_child_by_type_full (GNode * node,
480     guint32 fourcc, GstByteReader * parser);
481 static GNode *qtdemux_tree_get_sibling_by_type (GNode * node, guint32 fourcc);
482 static GNode *qtdemux_tree_get_sibling_by_type_full (GNode * node,
483     guint32 fourcc, GstByteReader * parser);
484
485 static GstFlowReturn qtdemux_add_fragmented_samples (GstQTDemux * qtdemux);
486
487 static void gst_qtdemux_check_send_pending_segment (GstQTDemux * demux);
488
489 static GstStaticPadTemplate gst_qtdemux_sink_template =
490     GST_STATIC_PAD_TEMPLATE ("sink",
491     GST_PAD_SINK,
492     GST_PAD_ALWAYS,
493     GST_STATIC_CAPS ("video/quicktime; video/mj2; audio/x-m4a; "
494         "application/x-3gp")
495     );
496
497 static GstStaticPadTemplate gst_qtdemux_videosrc_template =
498 GST_STATIC_PAD_TEMPLATE ("video_%u",
499     GST_PAD_SRC,
500     GST_PAD_SOMETIMES,
501     GST_STATIC_CAPS_ANY);
502
503 static GstStaticPadTemplate gst_qtdemux_audiosrc_template =
504 GST_STATIC_PAD_TEMPLATE ("audio_%u",
505     GST_PAD_SRC,
506     GST_PAD_SOMETIMES,
507     GST_STATIC_CAPS_ANY);
508
509 static GstStaticPadTemplate gst_qtdemux_subsrc_template =
510 GST_STATIC_PAD_TEMPLATE ("subtitle_%u",
511     GST_PAD_SRC,
512     GST_PAD_SOMETIMES,
513     GST_STATIC_CAPS_ANY);
514
515 #define gst_qtdemux_parent_class parent_class
516 G_DEFINE_TYPE (GstQTDemux, gst_qtdemux, GST_TYPE_ELEMENT);
517
518 static void gst_qtdemux_dispose (GObject * object);
519
520 static guint32
521 gst_qtdemux_find_index_linear (GstQTDemux * qtdemux, QtDemuxStream * str,
522     GstClockTime media_time);
523 static guint32
524 gst_qtdemux_find_index_for_given_media_offset_linear (GstQTDemux * qtdemux,
525     QtDemuxStream * str, gint64 media_offset);
526
527 #if 0
528 static void gst_qtdemux_set_index (GstElement * element, GstIndex * index);
529 static GstIndex *gst_qtdemux_get_index (GstElement * element);
530 #endif
531 static GstStateChangeReturn gst_qtdemux_change_state (GstElement * element,
532     GstStateChange transition);
533 static void gst_qtdemux_set_context (GstElement * element,
534     GstContext * context);
535 static gboolean qtdemux_sink_activate (GstPad * sinkpad, GstObject * parent);
536 static gboolean qtdemux_sink_activate_mode (GstPad * sinkpad,
537     GstObject * parent, GstPadMode mode, gboolean active);
538
539 static void gst_qtdemux_loop (GstPad * pad);
540 static GstFlowReturn gst_qtdemux_chain (GstPad * sinkpad, GstObject * parent,
541     GstBuffer * inbuf);
542 static gboolean gst_qtdemux_handle_sink_event (GstPad * pad, GstObject * parent,
543     GstEvent * event);
544 static gboolean gst_qtdemux_setcaps (GstQTDemux * qtdemux, GstCaps * caps);
545 static gboolean gst_qtdemux_configure_stream (GstQTDemux * qtdemux,
546     QtDemuxStream * stream);
547 static void gst_qtdemux_stream_check_and_change_stsd_index (GstQTDemux * demux,
548     QtDemuxStream * stream);
549 static GstFlowReturn gst_qtdemux_process_adapter (GstQTDemux * demux,
550     gboolean force);
551
552 static gboolean qtdemux_parse_moov (GstQTDemux * qtdemux,
553     const guint8 * buffer, guint length);
554 static gboolean qtdemux_parse_node (GstQTDemux * qtdemux, GNode * node,
555     const guint8 * buffer, guint length);
556 static gboolean qtdemux_parse_tree (GstQTDemux * qtdemux);
557 static void qtdemux_parse_udta (GstQTDemux * qtdemux, GstTagList * taglist,
558     GNode * udta);
559
560 static void gst_qtdemux_handle_esds (GstQTDemux * qtdemux,
561     QtDemuxStream * stream, QtDemuxStreamStsdEntry * entry, GNode * esds,
562     GstTagList * list);
563 static GstCaps *qtdemux_video_caps (GstQTDemux * qtdemux,
564     QtDemuxStream * stream, QtDemuxStreamStsdEntry * entry, guint32 fourcc,
565     const guint8 * stsd_entry_data, gchar ** codec_name);
566 static GstCaps *qtdemux_audio_caps (GstQTDemux * qtdemux,
567     QtDemuxStream * stream, QtDemuxStreamStsdEntry * entry, guint32 fourcc,
568     const guint8 * data, int len, gchar ** codec_name);
569 static GstCaps *qtdemux_sub_caps (GstQTDemux * qtdemux, QtDemuxStream * stream,
570     QtDemuxStreamStsdEntry * entry, guint32 fourcc, const guint8 * data,
571     gchar ** codec_name);
572 static GstCaps *qtdemux_generic_caps (GstQTDemux * qtdemux,
573     QtDemuxStream * stream, QtDemuxStreamStsdEntry * entry, guint32 fourcc,
574     const guint8 * stsd_entry_data, gchar ** codec_name);
575
576 static gboolean qtdemux_parse_samples (GstQTDemux * qtdemux,
577     QtDemuxStream * stream, guint32 n);
578 static GstFlowReturn qtdemux_expose_streams (GstQTDemux * qtdemux);
579 static void gst_qtdemux_stream_free (QtDemuxStream * stream);
580 static void gst_qtdemux_stream_clear (QtDemuxStream * stream);
581 static void gst_qtdemux_remove_stream (GstQTDemux * qtdemux,
582     QtDemuxStream * stream);
583 static GstFlowReturn qtdemux_prepare_streams (GstQTDemux * qtdemux);
584 static void qtdemux_do_allocation (GstQTDemux * qtdemux,
585     QtDemuxStream * stream);
586 static gboolean gst_qtdemux_activate_segment (GstQTDemux * qtdemux,
587     QtDemuxStream * stream, guint32 seg_idx, GstClockTime offset);
588 static gboolean gst_qtdemux_stream_update_segment (GstQTDemux * qtdemux,
589     QtDemuxStream * stream, gint seg_idx, GstClockTime offset,
590     GstClockTime * _start, GstClockTime * _stop);
591 static void gst_qtdemux_send_gap_for_segment (GstQTDemux * demux,
592     QtDemuxStream * stream, gint segment_index, GstClockTime pos);
593
594 static gboolean qtdemux_pull_mfro_mfra (GstQTDemux * qtdemux);
595 static void check_update_duration (GstQTDemux * qtdemux, GstClockTime duration);
596
597 static gchar *qtdemux_uuid_bytes_to_string (gconstpointer uuid_bytes);
598
599 static GstStructure *qtdemux_get_cenc_sample_properties (GstQTDemux * qtdemux,
600     QtDemuxStream * stream, guint sample_index);
601 static void gst_qtdemux_append_protection_system_id (GstQTDemux * qtdemux,
602     const gchar * id);
603 static void qtdemux_gst_structure_free (GstStructure * gststructure);
604 static void gst_qtdemux_reset (GstQTDemux * qtdemux, gboolean hard);
605
606 static void
607 gst_qtdemux_class_init (GstQTDemuxClass * klass)
608 {
609   GObjectClass *gobject_class;
610   GstElementClass *gstelement_class;
611
612   gobject_class = (GObjectClass *) klass;
613   gstelement_class = (GstElementClass *) klass;
614
615   parent_class = g_type_class_peek_parent (klass);
616
617   gobject_class->dispose = gst_qtdemux_dispose;
618
619   gstelement_class->change_state = GST_DEBUG_FUNCPTR (gst_qtdemux_change_state);
620 #if 0
621   gstelement_class->set_index = GST_DEBUG_FUNCPTR (gst_qtdemux_set_index);
622   gstelement_class->get_index = GST_DEBUG_FUNCPTR (gst_qtdemux_get_index);
623 #endif
624   gstelement_class->set_context = GST_DEBUG_FUNCPTR (gst_qtdemux_set_context);
625
626   gst_tag_register_musicbrainz_tags ();
627
628   gst_element_class_add_static_pad_template (gstelement_class,
629       &gst_qtdemux_sink_template);
630   gst_element_class_add_static_pad_template (gstelement_class,
631       &gst_qtdemux_videosrc_template);
632   gst_element_class_add_static_pad_template (gstelement_class,
633       &gst_qtdemux_audiosrc_template);
634   gst_element_class_add_static_pad_template (gstelement_class,
635       &gst_qtdemux_subsrc_template);
636   gst_element_class_set_static_metadata (gstelement_class, "QuickTime demuxer",
637       "Codec/Demuxer",
638       "Demultiplex a QuickTime file into audio and video streams",
639       "David Schleef <ds@schleef.org>, Wim Taymans <wim@fluendo.com>");
640
641   GST_DEBUG_CATEGORY_INIT (qtdemux_debug, "qtdemux", 0, "qtdemux plugin");
642   gst_riff_init ();
643 }
644
645 static void
646 gst_qtdemux_init (GstQTDemux * qtdemux)
647 {
648   qtdemux->sinkpad =
649       gst_pad_new_from_static_template (&gst_qtdemux_sink_template, "sink");
650   gst_pad_set_activate_function (qtdemux->sinkpad, qtdemux_sink_activate);
651   gst_pad_set_activatemode_function (qtdemux->sinkpad,
652       qtdemux_sink_activate_mode);
653   gst_pad_set_chain_function (qtdemux->sinkpad, gst_qtdemux_chain);
654   gst_pad_set_event_function (qtdemux->sinkpad, gst_qtdemux_handle_sink_event);
655   gst_element_add_pad (GST_ELEMENT_CAST (qtdemux), qtdemux->sinkpad);
656
657   qtdemux->adapter = gst_adapter_new ();
658   g_queue_init (&qtdemux->protection_event_queue);
659   qtdemux->flowcombiner = gst_flow_combiner_new ();
660   g_mutex_init (&qtdemux->expose_lock);
661
662   GST_OBJECT_FLAG_SET (qtdemux, GST_ELEMENT_FLAG_INDEXABLE);
663
664   gst_qtdemux_reset (qtdemux, TRUE);
665 }
666
667 static void
668 gst_qtdemux_dispose (GObject * object)
669 {
670   GstQTDemux *qtdemux = GST_QTDEMUX (object);
671
672   if (qtdemux->adapter) {
673     g_object_unref (G_OBJECT (qtdemux->adapter));
674     qtdemux->adapter = NULL;
675   }
676   gst_tag_list_unref (qtdemux->tag_list);
677   gst_flow_combiner_free (qtdemux->flowcombiner);
678   g_queue_foreach (&qtdemux->protection_event_queue, (GFunc) gst_event_unref,
679       NULL);
680   g_queue_clear (&qtdemux->protection_event_queue);
681
682   g_free (qtdemux->cenc_aux_info_sizes);
683   qtdemux->cenc_aux_info_sizes = NULL;
684   g_mutex_clear (&qtdemux->expose_lock);
685
686   G_OBJECT_CLASS (parent_class)->dispose (object);
687 }
688
689 static void
690 gst_qtdemux_post_no_playable_stream_error (GstQTDemux * qtdemux)
691 {
692   if (qtdemux->posted_redirect) {
693     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
694         (_("This file contains no playable streams.")),
695         ("no known streams found, a redirect message has been posted"));
696   } else {
697     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
698         (_("This file contains no playable streams.")),
699         ("no known streams found"));
700   }
701 }
702
703 static GstBuffer *
704 _gst_buffer_new_wrapped (gpointer mem, gsize size, GFreeFunc free_func)
705 {
706   return gst_buffer_new_wrapped_full (free_func ? 0 : GST_MEMORY_FLAG_READONLY,
707       mem, size, 0, size, mem, free_func);
708 }
709
710 static GstFlowReturn
711 gst_qtdemux_pull_atom (GstQTDemux * qtdemux, guint64 offset, guint64 size,
712     GstBuffer ** buf)
713 {
714   GstFlowReturn flow;
715   GstMapInfo map;
716   gsize bsize;
717
718   if (G_UNLIKELY (size == 0)) {
719     GstFlowReturn ret;
720     GstBuffer *tmp = NULL;
721
722     ret = gst_qtdemux_pull_atom (qtdemux, offset, sizeof (guint32), &tmp);
723     if (ret != GST_FLOW_OK)
724       return ret;
725
726     gst_buffer_map (tmp, &map, GST_MAP_READ);
727     size = QT_UINT32 (map.data);
728     GST_DEBUG_OBJECT (qtdemux, "size 0x%08" G_GINT64_MODIFIER "x", size);
729
730     gst_buffer_unmap (tmp, &map);
731     gst_buffer_unref (tmp);
732   }
733
734   /* Sanity check: catch bogus sizes (fuzzed/broken files) */
735   if (G_UNLIKELY (size > QTDEMUX_MAX_ATOM_SIZE)) {
736     if (qtdemux->state != QTDEMUX_STATE_MOVIE && qtdemux->got_moov) {
737       /* we're pulling header but already got most interesting bits,
738        * so never mind the rest (e.g. tags) (that much) */
739       GST_WARNING_OBJECT (qtdemux, "atom has bogus size %" G_GUINT64_FORMAT,
740           size);
741       return GST_FLOW_EOS;
742     } else {
743       GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
744           (_("This file is invalid and cannot be played.")),
745           ("atom has bogus size %" G_GUINT64_FORMAT, size));
746       return GST_FLOW_ERROR;
747     }
748   }
749
750   flow = gst_pad_pull_range (qtdemux->sinkpad, offset, size, buf);
751
752   if (G_UNLIKELY (flow != GST_FLOW_OK))
753     return flow;
754
755   bsize = gst_buffer_get_size (*buf);
756   /* Catch short reads - we don't want any partial atoms */
757   if (G_UNLIKELY (bsize < size)) {
758     GST_WARNING_OBJECT (qtdemux,
759         "short read: %" G_GSIZE_FORMAT " < %" G_GUINT64_FORMAT, bsize, size);
760     gst_buffer_unref (*buf);
761     *buf = NULL;
762     return GST_FLOW_EOS;
763   }
764
765   return flow;
766 }
767
768 #if 1
769 static gboolean
770 gst_qtdemux_src_convert (GstQTDemux * qtdemux, GstPad * pad,
771     GstFormat src_format, gint64 src_value, GstFormat dest_format,
772     gint64 * dest_value)
773 {
774   gboolean res = TRUE;
775   QtDemuxStream *stream = gst_pad_get_element_private (pad);
776   gint32 index;
777
778   if (stream->subtype != FOURCC_vide) {
779     res = FALSE;
780     goto done;
781   }
782
783   switch (src_format) {
784     case GST_FORMAT_TIME:
785       switch (dest_format) {
786         case GST_FORMAT_BYTES:{
787           index = gst_qtdemux_find_index_linear (qtdemux, stream, src_value);
788           if (-1 == index) {
789             res = FALSE;
790             goto done;
791           }
792
793           *dest_value = stream->samples[index].offset;
794
795           GST_DEBUG_OBJECT (qtdemux, "Format Conversion Time->Offset :%"
796               GST_TIME_FORMAT "->%" G_GUINT64_FORMAT,
797               GST_TIME_ARGS (src_value), *dest_value);
798           break;
799         }
800         default:
801           res = FALSE;
802           break;
803       }
804       break;
805     case GST_FORMAT_BYTES:
806       switch (dest_format) {
807         case GST_FORMAT_TIME:{
808           index =
809               gst_qtdemux_find_index_for_given_media_offset_linear (qtdemux,
810               stream, src_value);
811
812           if (-1 == index) {
813             res = FALSE;
814             goto done;
815           }
816
817           *dest_value =
818               QTSTREAMTIME_TO_GSTTIME (stream,
819               stream->samples[index].timestamp);
820           GST_DEBUG_OBJECT (qtdemux,
821               "Format Conversion Offset->Time :%" G_GUINT64_FORMAT "->%"
822               GST_TIME_FORMAT, src_value, GST_TIME_ARGS (*dest_value));
823           break;
824         }
825         default:
826           res = FALSE;
827           break;
828       }
829       break;
830     default:
831       res = FALSE;
832       break;
833   }
834
835 done:
836   return res;
837 }
838 #endif
839
840 static gboolean
841 gst_qtdemux_get_duration (GstQTDemux * qtdemux, GstClockTime * duration)
842 {
843   gboolean res = FALSE;
844
845   *duration = GST_CLOCK_TIME_NONE;
846
847   if (qtdemux->duration != 0 &&
848       qtdemux->duration != G_MAXINT64 && qtdemux->timescale != 0) {
849     *duration = QTTIME_TO_GSTTIME (qtdemux, qtdemux->duration);
850     res = TRUE;
851   } else {
852     *duration = GST_CLOCK_TIME_NONE;
853   }
854
855   return res;
856 }
857
858 static gboolean
859 gst_qtdemux_handle_src_query (GstPad * pad, GstObject * parent,
860     GstQuery * query)
861 {
862   gboolean res = FALSE;
863   GstQTDemux *qtdemux = GST_QTDEMUX (parent);
864
865   GST_LOG_OBJECT (pad, "%s query", GST_QUERY_TYPE_NAME (query));
866
867   switch (GST_QUERY_TYPE (query)) {
868     case GST_QUERY_POSITION:{
869       GstFormat fmt;
870
871       gst_query_parse_position (query, &fmt, NULL);
872       if (fmt == GST_FORMAT_TIME
873           && GST_CLOCK_TIME_IS_VALID (qtdemux->segment.position)) {
874         gst_query_set_position (query, GST_FORMAT_TIME,
875             qtdemux->segment.position);
876         res = TRUE;
877       }
878     }
879       break;
880     case GST_QUERY_DURATION:{
881       GstFormat fmt;
882
883       gst_query_parse_duration (query, &fmt, NULL);
884       if (fmt == GST_FORMAT_TIME) {
885         /* First try to query upstream */
886         res = gst_pad_query_default (pad, parent, query);
887         if (!res) {
888           GstClockTime duration;
889           if (gst_qtdemux_get_duration (qtdemux, &duration) && duration > 0) {
890             gst_query_set_duration (query, GST_FORMAT_TIME, duration);
891             res = TRUE;
892           }
893         }
894       }
895       break;
896     }
897     case GST_QUERY_CONVERT:{
898       GstFormat src_fmt, dest_fmt;
899       gint64 src_value, dest_value = 0;
900
901       gst_query_parse_convert (query, &src_fmt, &src_value, &dest_fmt, NULL);
902
903       res = gst_qtdemux_src_convert (qtdemux, pad,
904           src_fmt, src_value, dest_fmt, &dest_value);
905       if (res)
906         gst_query_set_convert (query, src_fmt, src_value, dest_fmt, dest_value);
907
908       break;
909     }
910     case GST_QUERY_FORMATS:
911       gst_query_set_formats (query, 2, GST_FORMAT_TIME, GST_FORMAT_BYTES);
912       res = TRUE;
913       break;
914     case GST_QUERY_SEEKING:{
915       GstFormat fmt;
916       gboolean seekable;
917
918       /* try upstream first */
919       res = gst_pad_query_default (pad, parent, query);
920
921       if (!res) {
922         gst_query_parse_seeking (query, &fmt, NULL, NULL, NULL);
923         if (fmt == GST_FORMAT_TIME) {
924           GstClockTime duration;
925
926           gst_qtdemux_get_duration (qtdemux, &duration);
927           seekable = TRUE;
928           if (!qtdemux->pullbased) {
929             GstQuery *q;
930
931             /* we might be able with help from upstream */
932             seekable = FALSE;
933             q = gst_query_new_seeking (GST_FORMAT_BYTES);
934             if (gst_pad_peer_query (qtdemux->sinkpad, q)) {
935               gst_query_parse_seeking (q, &fmt, &seekable, NULL, NULL);
936               GST_LOG_OBJECT (qtdemux, "upstream BYTE seekable %d", seekable);
937             }
938             gst_query_unref (q);
939           }
940           gst_query_set_seeking (query, GST_FORMAT_TIME, seekable, 0, duration);
941           res = TRUE;
942         }
943       }
944       break;
945     }
946     case GST_QUERY_SEGMENT:
947     {
948       GstFormat format;
949       gint64 start, stop;
950
951       format = qtdemux->segment.format;
952
953       start =
954           gst_segment_to_stream_time (&qtdemux->segment, format,
955           qtdemux->segment.start);
956       if ((stop = qtdemux->segment.stop) == -1)
957         stop = qtdemux->segment.duration;
958       else
959         stop = gst_segment_to_stream_time (&qtdemux->segment, format, stop);
960
961       gst_query_set_segment (query, qtdemux->segment.rate, format, start, stop);
962       res = TRUE;
963       break;
964     }
965     default:
966       res = gst_pad_query_default (pad, parent, query);
967       break;
968   }
969
970   return res;
971 }
972
973 static void
974 gst_qtdemux_push_tags (GstQTDemux * qtdemux, QtDemuxStream * stream)
975 {
976   if (G_LIKELY (stream->pad)) {
977     GST_DEBUG_OBJECT (qtdemux, "Checking pad %s:%s for tags",
978         GST_DEBUG_PAD_NAME (stream->pad));
979
980     if (!gst_tag_list_is_empty (stream->stream_tags)) {
981       GST_DEBUG_OBJECT (qtdemux, "Sending tags %" GST_PTR_FORMAT,
982           stream->stream_tags);
983       gst_pad_push_event (stream->pad,
984           gst_event_new_tag (gst_tag_list_ref (stream->stream_tags)));
985     }
986
987     if (G_UNLIKELY (stream->send_global_tags)) {
988       GST_DEBUG_OBJECT (qtdemux, "Sending global tags %" GST_PTR_FORMAT,
989           qtdemux->tag_list);
990       gst_pad_push_event (stream->pad,
991           gst_event_new_tag (gst_tag_list_ref (qtdemux->tag_list)));
992       stream->send_global_tags = FALSE;
993     }
994   }
995 }
996
997 /* push event on all source pads; takes ownership of the event */
998 static void
999 gst_qtdemux_push_event (GstQTDemux * qtdemux, GstEvent * event)
1000 {
1001   gboolean has_valid_stream = FALSE;
1002   GstEventType etype = GST_EVENT_TYPE (event);
1003   GList *iter;
1004
1005   GST_DEBUG_OBJECT (qtdemux, "pushing %s event on all source pads",
1006       GST_EVENT_TYPE_NAME (event));
1007
1008   for (iter = qtdemux->active_streams; iter; iter = g_list_next (iter)) {
1009     GstPad *pad;
1010     QtDemuxStream *stream = QTDEMUX_STREAM (iter->data);
1011     GST_DEBUG_OBJECT (qtdemux, "pushing on track-id %u", stream->track_id);
1012
1013     if ((pad = stream->pad)) {
1014       has_valid_stream = TRUE;
1015
1016       if (etype == GST_EVENT_EOS) {
1017         /* let's not send twice */
1018         if (stream->sent_eos)
1019           continue;
1020         stream->sent_eos = TRUE;
1021       }
1022
1023       gst_pad_push_event (pad, gst_event_ref (event));
1024     }
1025   }
1026
1027   gst_event_unref (event);
1028
1029   /* if it is EOS and there are no pads, post an error */
1030   if (!has_valid_stream && etype == GST_EVENT_EOS) {
1031     gst_qtdemux_post_no_playable_stream_error (qtdemux);
1032   }
1033 }
1034
1035 typedef struct
1036 {
1037   guint64 media_time;
1038 } FindData;
1039
1040 static gint
1041 find_func (QtDemuxSample * s1, gint64 * media_time, gpointer user_data)
1042 {
1043   if ((gint64) s1->timestamp > *media_time)
1044     return 1;
1045   if ((gint64) s1->timestamp == *media_time)
1046     return 0;
1047
1048   return -1;
1049 }
1050
1051 /* find the index of the sample that includes the data for @media_time using a
1052  * binary search.  Only to be called in optimized cases of linear search below.
1053  *
1054  * Returns the index of the sample with the corresponding *DTS*.
1055  */
1056 static guint32
1057 gst_qtdemux_find_index (GstQTDemux * qtdemux, QtDemuxStream * str,
1058     guint64 media_time)
1059 {
1060   QtDemuxSample *result;
1061   guint32 index;
1062
1063   /* convert media_time to mov format */
1064   media_time =
1065       gst_util_uint64_scale_ceil (media_time, str->timescale, GST_SECOND);
1066
1067   result = gst_util_array_binary_search (str->samples, str->stbl_index + 1,
1068       sizeof (QtDemuxSample), (GCompareDataFunc) find_func,
1069       GST_SEARCH_MODE_BEFORE, &media_time, NULL);
1070
1071   if (G_LIKELY (result))
1072     index = result - str->samples;
1073   else
1074     index = 0;
1075
1076   return index;
1077 }
1078
1079
1080
1081 /* find the index of the sample that includes the data for @media_offset using a
1082  * linear search
1083  *
1084  * Returns the index of the sample.
1085  */
1086 static guint32
1087 gst_qtdemux_find_index_for_given_media_offset_linear (GstQTDemux * qtdemux,
1088     QtDemuxStream * str, gint64 media_offset)
1089 {
1090   QtDemuxSample *result = str->samples;
1091   guint32 index = 0;
1092
1093   if (result == NULL || str->n_samples == 0)
1094     return -1;
1095
1096   if (media_offset == result->offset)
1097     return index;
1098
1099   result++;
1100   while (index < str->n_samples - 1) {
1101     if (!qtdemux_parse_samples (qtdemux, str, index + 1))
1102       goto parse_failed;
1103
1104     if (media_offset < result->offset)
1105       break;
1106
1107     index++;
1108     result++;
1109   }
1110   return index;
1111
1112   /* ERRORS */
1113 parse_failed:
1114   {
1115     GST_LOG_OBJECT (qtdemux, "Parsing of index %u failed!", index + 1);
1116     return -1;
1117   }
1118 }
1119
1120 /* find the index of the sample that includes the data for @media_time using a
1121  * linear search, and keeping in mind that not all samples may have been parsed
1122  * yet.  If possible, it will delegate to binary search.
1123  *
1124  * Returns the index of the sample.
1125  */
1126 static guint32
1127 gst_qtdemux_find_index_linear (GstQTDemux * qtdemux, QtDemuxStream * str,
1128     GstClockTime media_time)
1129 {
1130   guint32 index = 0;
1131   guint64 mov_time;
1132   QtDemuxSample *sample;
1133
1134   /* convert media_time to mov format */
1135   mov_time =
1136       gst_util_uint64_scale_ceil (media_time, str->timescale, GST_SECOND);
1137
1138   sample = str->samples;
1139   if (mov_time == sample->timestamp + sample->pts_offset)
1140     return index;
1141
1142   /* use faster search if requested time in already parsed range */
1143   sample = str->samples + str->stbl_index;
1144   if (str->stbl_index >= 0 && mov_time <= sample->timestamp) {
1145     index = gst_qtdemux_find_index (qtdemux, str, media_time);
1146     sample = str->samples + index;
1147   } else {
1148     while (index < str->n_samples - 1) {
1149       if (!qtdemux_parse_samples (qtdemux, str, index + 1))
1150         goto parse_failed;
1151
1152       sample = str->samples + index + 1;
1153       if (mov_time < sample->timestamp) {
1154         sample = str->samples + index;
1155         break;
1156       }
1157
1158       index++;
1159     }
1160   }
1161
1162   /* sample->timestamp is now <= media_time, need to find the corresponding
1163    * PTS now by looking backwards */
1164   while (index > 0 && sample->timestamp + sample->pts_offset > mov_time) {
1165     index--;
1166     sample = str->samples + index;
1167   }
1168
1169   return index;
1170
1171   /* ERRORS */
1172 parse_failed:
1173   {
1174     GST_LOG_OBJECT (qtdemux, "Parsing of index %u failed!", index + 1);
1175     return -1;
1176   }
1177 }
1178
1179 /* find the index of the keyframe needed to decode the sample at @index
1180  * of stream @str, or of a subsequent keyframe (depending on @next)
1181  *
1182  * Returns the index of the keyframe.
1183  */
1184 static guint32
1185 gst_qtdemux_find_keyframe (GstQTDemux * qtdemux, QtDemuxStream * str,
1186     guint32 index, gboolean next)
1187 {
1188   guint32 new_index = index;
1189
1190   if (index >= str->n_samples) {
1191     new_index = str->n_samples;
1192     goto beach;
1193   }
1194
1195   /* all keyframes, return index */
1196   if (str->all_keyframe) {
1197     new_index = index;
1198     goto beach;
1199   }
1200
1201   /* else search until we have a keyframe */
1202   while (new_index < str->n_samples) {
1203     if (next && !qtdemux_parse_samples (qtdemux, str, new_index))
1204       goto parse_failed;
1205
1206     if (str->samples[new_index].keyframe)
1207       break;
1208
1209     if (new_index == 0)
1210       break;
1211
1212     if (next)
1213       new_index++;
1214     else
1215       new_index--;
1216   }
1217
1218   if (new_index == str->n_samples) {
1219     GST_DEBUG_OBJECT (qtdemux, "no next keyframe");
1220     new_index = -1;
1221   }
1222
1223 beach:
1224   GST_DEBUG_OBJECT (qtdemux, "searching for keyframe index %s index %u "
1225       "gave %u", next ? "after" : "before", index, new_index);
1226
1227   return new_index;
1228
1229   /* ERRORS */
1230 parse_failed:
1231   {
1232     GST_LOG_OBJECT (qtdemux, "Parsing of index %u failed!", new_index);
1233     return -1;
1234   }
1235 }
1236
1237 /* find the segment for @time_position for @stream
1238  *
1239  * Returns the index of the segment containing @time_position.
1240  * Returns the last segment and sets the @eos variable to TRUE
1241  * if the time is beyond the end. @eos may be NULL
1242  */
1243 static guint32
1244 gst_qtdemux_find_segment (GstQTDemux * qtdemux, QtDemuxStream * stream,
1245     GstClockTime time_position)
1246 {
1247   gint i;
1248   guint32 seg_idx;
1249
1250   GST_LOG_OBJECT (stream->pad, "finding segment for %" GST_TIME_FORMAT,
1251       GST_TIME_ARGS (time_position));
1252
1253   seg_idx = -1;
1254   for (i = 0; i < stream->n_segments; i++) {
1255     QtDemuxSegment *segment = &stream->segments[i];
1256
1257     GST_LOG_OBJECT (stream->pad,
1258         "looking at segment %" GST_TIME_FORMAT "-%" GST_TIME_FORMAT,
1259         GST_TIME_ARGS (segment->time), GST_TIME_ARGS (segment->stop_time));
1260
1261     /* For the last segment we include stop_time in the last segment */
1262     if (i < stream->n_segments - 1) {
1263       if (segment->time <= time_position && time_position < segment->stop_time) {
1264         GST_LOG_OBJECT (stream->pad, "segment %d matches", i);
1265         seg_idx = i;
1266         break;
1267       }
1268     } else {
1269       /* Last segment always matches */
1270       seg_idx = i;
1271       break;
1272     }
1273   }
1274   return seg_idx;
1275 }
1276
1277 /* move the stream @str to the sample position @index.
1278  *
1279  * Updates @str->sample_index and marks discontinuity if needed.
1280  */
1281 static void
1282 gst_qtdemux_move_stream (GstQTDemux * qtdemux, QtDemuxStream * str,
1283     guint32 index)
1284 {
1285   /* no change needed */
1286   if (index == str->sample_index)
1287     return;
1288
1289   GST_DEBUG_OBJECT (qtdemux, "moving to sample %u of %u", index,
1290       str->n_samples);
1291
1292   /* position changed, we have a discont */
1293   str->sample_index = index;
1294   str->offset_in_sample = 0;
1295   /* Each time we move in the stream we store the position where we are
1296    * starting from */
1297   str->from_sample = index;
1298   str->discont = TRUE;
1299 }
1300
1301 static void
1302 gst_qtdemux_adjust_seek (GstQTDemux * qtdemux, gint64 desired_time,
1303     gboolean use_sparse, gboolean next, gint64 * key_time, gint64 * key_offset)
1304 {
1305   guint64 min_offset;
1306   gint64 min_byte_offset = -1;
1307   GList *iter;
1308
1309   min_offset = desired_time;
1310
1311   /* for each stream, find the index of the sample in the segment
1312    * and move back to the previous keyframe. */
1313   for (iter = qtdemux->active_streams; iter; iter = g_list_next (iter)) {
1314     QtDemuxStream *str;
1315     guint32 index, kindex;
1316     guint32 seg_idx;
1317     GstClockTime media_start;
1318     GstClockTime media_time;
1319     GstClockTime seg_time;
1320     QtDemuxSegment *seg;
1321     gboolean empty_segment = FALSE;
1322
1323     str = QTDEMUX_STREAM (iter->data);
1324
1325     if (CUR_STREAM (str)->sparse && !use_sparse)
1326       continue;
1327
1328     seg_idx = gst_qtdemux_find_segment (qtdemux, str, desired_time);
1329     GST_DEBUG_OBJECT (qtdemux, "align segment %d", seg_idx);
1330
1331     /* get segment and time in the segment */
1332     seg = &str->segments[seg_idx];
1333     seg_time = (desired_time - seg->time) * seg->rate;
1334
1335     while (QTSEGMENT_IS_EMPTY (seg)) {
1336       seg_time = 0;
1337       empty_segment = TRUE;
1338       GST_DEBUG_OBJECT (str->pad, "Segment %d is empty, moving to next one",
1339           seg_idx);
1340       seg_idx++;
1341       if (seg_idx == str->n_segments)
1342         break;
1343       seg = &str->segments[seg_idx];
1344     }
1345
1346     if (seg_idx == str->n_segments) {
1347       /* FIXME track shouldn't have the last segment as empty, but if it
1348        * happens we better handle it */
1349       continue;
1350     }
1351
1352     /* get the media time in the segment */
1353     media_start = seg->media_start + seg_time;
1354
1355     /* get the index of the sample with media time */
1356     index = gst_qtdemux_find_index_linear (qtdemux, str, media_start);
1357     GST_DEBUG_OBJECT (qtdemux, "sample for %" GST_TIME_FORMAT " at %u"
1358         " at offset %" G_GUINT64_FORMAT " (empty segment: %d)",
1359         GST_TIME_ARGS (media_start), index, str->samples[index].offset,
1360         empty_segment);
1361
1362     /* shift to next frame if we are looking for next keyframe */
1363     if (next && QTSAMPLE_PTS_NO_CSLG (str, &str->samples[index]) < media_start
1364         && index < str->stbl_index)
1365       index++;
1366
1367     if (!empty_segment) {
1368       /* find previous keyframe */
1369       kindex = gst_qtdemux_find_keyframe (qtdemux, str, index, next);
1370
1371       /* we will settle for one before if none found after */
1372       if (next && kindex == -1)
1373         kindex = gst_qtdemux_find_keyframe (qtdemux, str, index, FALSE);
1374
1375       /* if the keyframe is at a different position, we need to update the
1376        * requested seek time */
1377       if (index != kindex) {
1378         index = kindex;
1379
1380         /* get timestamp of keyframe */
1381         media_time = QTSAMPLE_PTS_NO_CSLG (str, &str->samples[kindex]);
1382         GST_DEBUG_OBJECT (qtdemux,
1383             "keyframe at %u with time %" GST_TIME_FORMAT " at offset %"
1384             G_GUINT64_FORMAT, kindex, GST_TIME_ARGS (media_time),
1385             str->samples[kindex].offset);
1386
1387         /* keyframes in the segment get a chance to change the
1388          * desired_offset. keyframes out of the segment are
1389          * ignored. */
1390         if (media_time >= seg->media_start) {
1391           GstClockTime seg_time;
1392
1393           /* this keyframe is inside the segment, convert back to
1394            * segment time */
1395           seg_time = (media_time - seg->media_start) + seg->time;
1396           if ((!next && (seg_time < min_offset)) ||
1397               (next && (seg_time > min_offset)))
1398             min_offset = seg_time;
1399         }
1400       }
1401     }
1402
1403     if (min_byte_offset < 0 || str->samples[index].offset < min_byte_offset)
1404       min_byte_offset = str->samples[index].offset;
1405   }
1406
1407   if (key_time)
1408     *key_time = min_offset;
1409   if (key_offset)
1410     *key_offset = min_byte_offset;
1411 }
1412
1413 static gboolean
1414 gst_qtdemux_convert_seek (GstPad * pad, GstFormat * format,
1415     GstSeekType cur_type, gint64 * cur, GstSeekType stop_type, gint64 * stop)
1416 {
1417   gboolean res;
1418
1419   g_return_val_if_fail (format != NULL, FALSE);
1420   g_return_val_if_fail (cur != NULL, FALSE);
1421   g_return_val_if_fail (stop != NULL, FALSE);
1422
1423   if (*format == GST_FORMAT_TIME)
1424     return TRUE;
1425
1426   res = TRUE;
1427   if (cur_type != GST_SEEK_TYPE_NONE)
1428     res = gst_pad_query_convert (pad, *format, *cur, GST_FORMAT_TIME, cur);
1429   if (res && stop_type != GST_SEEK_TYPE_NONE)
1430     res = gst_pad_query_convert (pad, *format, *stop, GST_FORMAT_TIME, stop);
1431
1432   if (res)
1433     *format = GST_FORMAT_TIME;
1434
1435   return res;
1436 }
1437
1438 /* perform seek in push based mode:
1439    find BYTE position to move to based on time and delegate to upstream
1440 */
1441 static gboolean
1442 gst_qtdemux_do_push_seek (GstQTDemux * qtdemux, GstPad * pad, GstEvent * event)
1443 {
1444   gdouble rate;
1445   GstFormat format;
1446   GstSeekFlags flags;
1447   GstSeekType cur_type, stop_type;
1448   gint64 cur, stop, key_cur;
1449   gboolean res;
1450   gint64 byte_cur;
1451   gint64 original_stop;
1452   guint32 seqnum;
1453
1454   GST_DEBUG_OBJECT (qtdemux, "doing push-based seek");
1455
1456   gst_event_parse_seek (event, &rate, &format, &flags,
1457       &cur_type, &cur, &stop_type, &stop);
1458   seqnum = gst_event_get_seqnum (event);
1459
1460   /* only forward streaming and seeking is possible */
1461   if (rate <= 0)
1462     goto unsupported_seek;
1463
1464   /* convert to TIME if needed and possible */
1465   if (!gst_qtdemux_convert_seek (pad, &format, cur_type, &cur,
1466           stop_type, &stop))
1467     goto no_format;
1468
1469   /* Upstream seek in bytes will have undefined stop, but qtdemux stores
1470    * the original stop position to use when upstream pushes the new segment
1471    * for this seek */
1472   original_stop = stop;
1473   stop = -1;
1474
1475   /* find reasonable corresponding BYTE position,
1476    * also try to mind about keyframes, since we can not go back a bit for them
1477    * later on */
1478   /* determining @next here based on SNAP_BEFORE/SNAP_AFTER should
1479    * mostly just work, but let's not yet boldly go there  ... */
1480   gst_qtdemux_adjust_seek (qtdemux, cur, FALSE, FALSE, &key_cur, &byte_cur);
1481
1482   if (byte_cur == -1)
1483     goto abort_seek;
1484
1485   GST_DEBUG_OBJECT (qtdemux, "Pushing BYTE seek rate %g, "
1486       "start %" G_GINT64_FORMAT ", stop %" G_GINT64_FORMAT, rate, byte_cur,
1487       stop);
1488
1489   GST_OBJECT_LOCK (qtdemux);
1490   qtdemux->seek_offset = byte_cur;
1491   if (!(flags & GST_SEEK_FLAG_KEY_UNIT)) {
1492     qtdemux->push_seek_start = cur;
1493   } else {
1494     qtdemux->push_seek_start = key_cur;
1495   }
1496
1497   if (stop_type == GST_SEEK_TYPE_NONE) {
1498     qtdemux->push_seek_stop = qtdemux->segment.stop;
1499   } else {
1500     qtdemux->push_seek_stop = original_stop;
1501   }
1502   GST_OBJECT_UNLOCK (qtdemux);
1503
1504   qtdemux->segment_seqnum = seqnum;
1505   /* BYTE seek event */
1506   event = gst_event_new_seek (rate, GST_FORMAT_BYTES, flags, cur_type, byte_cur,
1507       stop_type, stop);
1508   gst_event_set_seqnum (event, seqnum);
1509   res = gst_pad_push_event (qtdemux->sinkpad, event);
1510
1511   return res;
1512
1513   /* ERRORS */
1514 abort_seek:
1515   {
1516     GST_DEBUG_OBJECT (qtdemux, "could not determine byte position to seek to, "
1517         "seek aborted.");
1518     return FALSE;
1519   }
1520 unsupported_seek:
1521   {
1522     GST_DEBUG_OBJECT (qtdemux, "unsupported seek, seek aborted.");
1523     return FALSE;
1524   }
1525 no_format:
1526   {
1527     GST_DEBUG_OBJECT (qtdemux, "unsupported format given, seek aborted.");
1528     return FALSE;
1529   }
1530 }
1531
1532 /* perform the seek.
1533  *
1534  * We set all segment_indexes in the streams to unknown and
1535  * adjust the time_position to the desired position. this is enough
1536  * to trigger a segment switch in the streaming thread to start
1537  * streaming from the desired position.
1538  *
1539  * Keyframe seeking is a little more complicated when dealing with
1540  * segments. Ideally we want to move to the previous keyframe in
1541  * the segment but there might not be a keyframe in the segment. In
1542  * fact, none of the segments could contain a keyframe. We take a
1543  * practical approach: seek to the previous keyframe in the segment,
1544  * if there is none, seek to the beginning of the segment.
1545  *
1546  * Called with STREAM_LOCK
1547  */
1548 static gboolean
1549 gst_qtdemux_perform_seek (GstQTDemux * qtdemux, GstSegment * segment,
1550     guint32 seqnum, GstSeekFlags flags)
1551 {
1552   gint64 desired_offset;
1553   GList *iter;
1554
1555   desired_offset = segment->position;
1556
1557   GST_DEBUG_OBJECT (qtdemux, "seeking to %" GST_TIME_FORMAT,
1558       GST_TIME_ARGS (desired_offset));
1559
1560   /* may not have enough fragmented info to do this adjustment,
1561    * and we can't scan (and probably should not) at this time with
1562    * possibly flushing upstream */
1563   if ((flags & GST_SEEK_FLAG_KEY_UNIT) && !qtdemux->fragmented) {
1564     gint64 min_offset;
1565     gboolean next, before, after;
1566
1567     before = ! !(flags & GST_SEEK_FLAG_SNAP_BEFORE);
1568     after = ! !(flags & GST_SEEK_FLAG_SNAP_AFTER);
1569     next = after && !before;
1570     if (segment->rate < 0)
1571       next = !next;
1572
1573     gst_qtdemux_adjust_seek (qtdemux, desired_offset, TRUE, next, &min_offset,
1574         NULL);
1575     GST_DEBUG_OBJECT (qtdemux, "keyframe seek, align to %"
1576         GST_TIME_FORMAT, GST_TIME_ARGS (min_offset));
1577     desired_offset = min_offset;
1578   }
1579
1580   /* and set all streams to the final position */
1581   gst_flow_combiner_reset (qtdemux->flowcombiner);
1582   qtdemux->segment_seqnum = seqnum;
1583   for (iter = qtdemux->active_streams; iter; iter = g_list_next (iter)) {
1584     QtDemuxStream *stream = QTDEMUX_STREAM (iter->data);
1585
1586     stream->time_position = desired_offset;
1587     stream->accumulated_base = 0;
1588     stream->sample_index = -1;
1589     stream->offset_in_sample = 0;
1590     stream->segment_index = -1;
1591     stream->sent_eos = FALSE;
1592
1593     if (segment->flags & GST_SEEK_FLAG_FLUSH)
1594       gst_segment_init (&stream->segment, GST_FORMAT_TIME);
1595   }
1596   segment->position = desired_offset;
1597   segment->time = desired_offset;
1598   if (segment->rate >= 0) {
1599     segment->start = desired_offset;
1600
1601     /* we stop at the end */
1602     if (segment->stop == -1)
1603       segment->stop = segment->duration;
1604   } else {
1605     segment->stop = desired_offset;
1606   }
1607
1608   if (qtdemux->fragmented)
1609     qtdemux->fragmented_seek_pending = TRUE;
1610
1611   return TRUE;
1612 }
1613
1614 /* do a seek in pull based mode */
1615 static gboolean
1616 gst_qtdemux_do_seek (GstQTDemux * qtdemux, GstPad * pad, GstEvent * event)
1617 {
1618   gdouble rate;
1619   GstFormat format;
1620   GstSeekFlags flags;
1621   GstSeekType cur_type, stop_type;
1622   gint64 cur, stop;
1623   gboolean flush;
1624   gboolean update;
1625   GstSegment seeksegment;
1626   guint32 seqnum = GST_SEQNUM_INVALID;
1627   GstEvent *flush_event;
1628   gboolean ret;
1629
1630   if (event) {
1631     GST_DEBUG_OBJECT (qtdemux, "doing seek with event");
1632
1633     gst_event_parse_seek (event, &rate, &format, &flags,
1634         &cur_type, &cur, &stop_type, &stop);
1635     seqnum = gst_event_get_seqnum (event);
1636
1637     /* we have to have a format as the segment format. Try to convert
1638      * if not. */
1639     if (!gst_qtdemux_convert_seek (pad, &format, cur_type, &cur,
1640             stop_type, &stop))
1641       goto no_format;
1642
1643     GST_DEBUG_OBJECT (qtdemux, "seek format %s", gst_format_get_name (format));
1644   } else {
1645     GST_DEBUG_OBJECT (qtdemux, "doing seek without event");
1646     flags = 0;
1647   }
1648
1649   flush = flags & GST_SEEK_FLAG_FLUSH;
1650
1651   /* stop streaming, either by flushing or by pausing the task */
1652   if (flush) {
1653     flush_event = gst_event_new_flush_start ();
1654     if (seqnum != GST_SEQNUM_INVALID)
1655       gst_event_set_seqnum (flush_event, seqnum);
1656     /* unlock upstream pull_range */
1657     gst_pad_push_event (qtdemux->sinkpad, gst_event_ref (flush_event));
1658     /* make sure out loop function exits */
1659     gst_qtdemux_push_event (qtdemux, flush_event);
1660   } else {
1661     /* non flushing seek, pause the task */
1662     gst_pad_pause_task (qtdemux->sinkpad);
1663   }
1664
1665   /* wait for streaming to finish */
1666   GST_PAD_STREAM_LOCK (qtdemux->sinkpad);
1667
1668   /* copy segment, we need this because we still need the old
1669    * segment when we close the current segment. */
1670   memcpy (&seeksegment, &qtdemux->segment, sizeof (GstSegment));
1671
1672   if (event) {
1673     /* configure the segment with the seek variables */
1674     GST_DEBUG_OBJECT (qtdemux, "configuring seek");
1675     if (!gst_segment_do_seek (&seeksegment, rate, format, flags,
1676             cur_type, cur, stop_type, stop, &update)) {
1677       ret = FALSE;
1678       GST_ERROR_OBJECT (qtdemux, "inconsistent seek values, doing nothing");
1679     } else {
1680       /* now do the seek */
1681       ret = gst_qtdemux_perform_seek (qtdemux, &seeksegment, seqnum, flags);
1682     }
1683   } else {
1684     /* now do the seek */
1685     ret = gst_qtdemux_perform_seek (qtdemux, &seeksegment, seqnum, flags);
1686   }
1687
1688   /* prepare for streaming again */
1689   if (flush) {
1690     flush_event = gst_event_new_flush_stop (TRUE);
1691     if (seqnum != GST_SEQNUM_INVALID)
1692       gst_event_set_seqnum (flush_event, seqnum);
1693
1694     gst_pad_push_event (qtdemux->sinkpad, gst_event_ref (flush_event));
1695     gst_qtdemux_push_event (qtdemux, flush_event);
1696   }
1697
1698   /* commit the new segment */
1699   memcpy (&qtdemux->segment, &seeksegment, sizeof (GstSegment));
1700
1701   if (qtdemux->segment.flags & GST_SEEK_FLAG_SEGMENT) {
1702     GstMessage *msg = gst_message_new_segment_start (GST_OBJECT_CAST (qtdemux),
1703         qtdemux->segment.format, qtdemux->segment.position);
1704     if (seqnum != GST_SEQNUM_INVALID)
1705       gst_message_set_seqnum (msg, seqnum);
1706     gst_element_post_message (GST_ELEMENT_CAST (qtdemux), msg);
1707   }
1708
1709   /* restart streaming, NEWSEGMENT will be sent from the streaming thread. */
1710   gst_pad_start_task (qtdemux->sinkpad, (GstTaskFunction) gst_qtdemux_loop,
1711       qtdemux->sinkpad, NULL);
1712
1713   GST_PAD_STREAM_UNLOCK (qtdemux->sinkpad);
1714
1715   return ret;
1716
1717   /* ERRORS */
1718 no_format:
1719   {
1720     GST_DEBUG_OBJECT (qtdemux, "unsupported format given, seek aborted.");
1721     return FALSE;
1722   }
1723 }
1724
1725 static gboolean
1726 qtdemux_ensure_index (GstQTDemux * qtdemux)
1727 {
1728   GList *iter;
1729
1730   GST_DEBUG_OBJECT (qtdemux, "collecting all metadata for all streams");
1731
1732   /* Build complete index */
1733   for (iter = qtdemux->active_streams; iter; iter = g_list_next (iter)) {
1734     QtDemuxStream *stream = QTDEMUX_STREAM (iter->data);
1735
1736     if (!qtdemux_parse_samples (qtdemux, stream, stream->n_samples - 1)) {
1737       GST_LOG_OBJECT (qtdemux,
1738           "Building complete index of track-id %u for seeking failed!",
1739           stream->track_id);
1740       return FALSE;
1741     }
1742   }
1743
1744   return TRUE;
1745 }
1746
1747 static gboolean
1748 gst_qtdemux_handle_src_event (GstPad * pad, GstObject * parent,
1749     GstEvent * event)
1750 {
1751   gboolean res = TRUE;
1752   GstQTDemux *qtdemux = GST_QTDEMUX (parent);
1753
1754   switch (GST_EVENT_TYPE (event)) {
1755     case GST_EVENT_SEEK:
1756     {
1757 #ifndef GST_DISABLE_GST_DEBUG
1758       GstClockTime ts = gst_util_get_timestamp ();
1759 #endif
1760       guint32 seqnum = gst_event_get_seqnum (event);
1761
1762       qtdemux->received_seek = TRUE;
1763
1764       if (seqnum == qtdemux->segment_seqnum) {
1765         GST_LOG_OBJECT (pad,
1766             "Drop duplicated SEEK event seqnum %" G_GUINT32_FORMAT, seqnum);
1767         gst_event_unref (event);
1768         return TRUE;
1769       }
1770
1771       if (qtdemux->upstream_format_is_time && qtdemux->fragmented) {
1772         /* seek should be handled by upstream, we might need to re-download fragments */
1773         GST_DEBUG_OBJECT (qtdemux,
1774             "let upstream handle seek for fragmented playback");
1775         goto upstream;
1776       }
1777
1778       /* Build complete index for seeking;
1779        * if not a fragmented file at least */
1780       if (!qtdemux->fragmented)
1781         if (!qtdemux_ensure_index (qtdemux))
1782           goto index_failed;
1783 #ifndef GST_DISABLE_GST_DEBUG
1784       ts = gst_util_get_timestamp () - ts;
1785       GST_INFO_OBJECT (qtdemux,
1786           "Time taken to parse index %" GST_TIME_FORMAT, GST_TIME_ARGS (ts));
1787 #endif
1788     }
1789       if (qtdemux->pullbased) {
1790         res = gst_qtdemux_do_seek (qtdemux, pad, event);
1791       } else if (gst_pad_push_event (qtdemux->sinkpad, gst_event_ref (event))) {
1792         GST_DEBUG_OBJECT (qtdemux, "Upstream successfully seeked");
1793         res = TRUE;
1794       } else if (qtdemux->state == QTDEMUX_STATE_MOVIE && qtdemux->n_streams
1795           && !qtdemux->fragmented) {
1796         res = gst_qtdemux_do_push_seek (qtdemux, pad, event);
1797       } else {
1798         GST_DEBUG_OBJECT (qtdemux,
1799             "ignoring seek in push mode in current state");
1800         res = FALSE;
1801       }
1802       gst_event_unref (event);
1803       break;
1804     default:
1805     upstream:
1806       res = gst_pad_event_default (pad, parent, event);
1807       break;
1808   }
1809
1810 done:
1811   return res;
1812
1813   /* ERRORS */
1814 index_failed:
1815   {
1816     GST_ERROR_OBJECT (qtdemux, "Index failed");
1817     gst_event_unref (event);
1818     res = FALSE;
1819     goto done;
1820   }
1821 }
1822
1823 /* Find, for each track, the first sample in coding order that has a file offset >= @byte_pos.
1824  *
1825  * If @fw is false, the coding order is explored backwards.
1826  *
1827  * If @set is true, each stream will be moved to its matched sample, or EOS if no matching
1828  * sample is found for that track.
1829  *
1830  * The stream and sample index of the sample with the minimum offset in the direction explored
1831  * (see @fw) is returned in the output parameters @_stream and @_index respectively.
1832  *
1833  * @_time is set to the QTSAMPLE_PTS of the matched sample with the minimum QTSAMPLE_PTS in the
1834  * direction explored, which may not always match the QTSAMPLE_PTS of the sample returned in
1835  * @_stream and @_index. */
1836 static void
1837 gst_qtdemux_find_sample (GstQTDemux * qtdemux, gint64 byte_pos, gboolean fw,
1838     gboolean set, QtDemuxStream ** _stream, gint * _index, gint64 * _time)
1839 {
1840   gint i, index;
1841   gint64 time, min_time;
1842   QtDemuxStream *stream;
1843   GList *iter;
1844
1845   min_time = -1;
1846   stream = NULL;
1847   index = -1;
1848
1849   for (iter = qtdemux->active_streams; iter; iter = g_list_next (iter)) {
1850     QtDemuxStream *str;
1851     gint inc;
1852     gboolean set_sample;
1853
1854     str = QTDEMUX_STREAM (iter->data);
1855     set_sample = !set;
1856
1857     if (fw) {
1858       i = 0;
1859       inc = 1;
1860     } else {
1861       i = str->n_samples - 1;
1862       inc = -1;
1863     }
1864
1865     for (; (i >= 0) && (i < str->n_samples); i += inc) {
1866       if (str->samples[i].size == 0)
1867         continue;
1868
1869       if (fw && (str->samples[i].offset < byte_pos))
1870         continue;
1871
1872       if (!fw && (str->samples[i].offset + str->samples[i].size > byte_pos))
1873         continue;
1874
1875       /* move stream to first available sample */
1876       if (set) {
1877         gst_qtdemux_move_stream (qtdemux, str, i);
1878         set_sample = TRUE;
1879       }
1880
1881       /* avoid index from sparse streams since they might be far away */
1882       if (!CUR_STREAM (str)->sparse) {
1883         /* determine min/max time */
1884         time = QTSAMPLE_PTS (str, &str->samples[i]);
1885         if (min_time == -1 || (!fw && time > min_time) ||
1886             (fw && time < min_time)) {
1887           min_time = time;
1888         }
1889
1890         /* determine stream with leading sample, to get its position */
1891         if (!stream ||
1892             (fw && (str->samples[i].offset < stream->samples[index].offset)) ||
1893             (!fw && (str->samples[i].offset > stream->samples[index].offset))) {
1894           stream = str;
1895           index = i;
1896         }
1897       }
1898       break;
1899     }
1900
1901     /* no sample for this stream, mark eos */
1902     if (!set_sample)
1903       gst_qtdemux_move_stream (qtdemux, str, str->n_samples);
1904   }
1905
1906   if (_time)
1907     *_time = min_time;
1908   if (_stream)
1909     *_stream = stream;
1910   if (_index)
1911     *_index = index;
1912 }
1913
1914 /* Copied from mpegtsbase code */
1915 /* FIXME: replace this function when we add new util function for stream-id creation */
1916 static gchar *
1917 _get_upstream_id (GstQTDemux * demux)
1918 {
1919   gchar *upstream_id = gst_pad_get_stream_id (demux->sinkpad);
1920
1921   if (!upstream_id) {
1922     /* Try to create one from the upstream URI, else use a randome number */
1923     GstQuery *query;
1924     gchar *uri = NULL;
1925
1926     /* Try to generate one from the URI query and
1927      * if it fails take a random number instead */
1928     query = gst_query_new_uri ();
1929     if (gst_element_query (GST_ELEMENT_CAST (demux), query)) {
1930       gst_query_parse_uri (query, &uri);
1931     }
1932
1933     if (uri) {
1934       GChecksum *cs;
1935
1936       /* And then generate an SHA256 sum of the URI */
1937       cs = g_checksum_new (G_CHECKSUM_SHA256);
1938       g_checksum_update (cs, (const guchar *) uri, strlen (uri));
1939       g_free (uri);
1940       upstream_id = g_strdup (g_checksum_get_string (cs));
1941       g_checksum_free (cs);
1942     } else {
1943       /* Just get some random number if the URI query fails */
1944       GST_FIXME_OBJECT (demux, "Creating random stream-id, consider "
1945           "implementing a deterministic way of creating a stream-id");
1946       upstream_id =
1947           g_strdup_printf ("%08x%08x%08x%08x", g_random_int (), g_random_int (),
1948           g_random_int (), g_random_int ());
1949     }
1950
1951     gst_query_unref (query);
1952   }
1953   return upstream_id;
1954 }
1955
1956 static QtDemuxStream *
1957 _create_stream (GstQTDemux * demux, guint32 track_id)
1958 {
1959   QtDemuxStream *stream;
1960   gchar *upstream_id;
1961
1962   stream = g_new0 (QtDemuxStream, 1);
1963   stream->demux = demux;
1964   stream->track_id = track_id;
1965   upstream_id = _get_upstream_id (demux);
1966   stream->stream_id = g_strdup_printf ("%s/%03u", upstream_id, track_id);
1967   g_free (upstream_id);
1968   /* new streams always need a discont */
1969   stream->discont = TRUE;
1970   /* we enable clipping for raw audio/video streams */
1971   stream->need_clip = FALSE;
1972   stream->need_process = FALSE;
1973   stream->segment_index = -1;
1974   stream->time_position = 0;
1975   stream->sample_index = -1;
1976   stream->offset_in_sample = 0;
1977   stream->new_stream = TRUE;
1978   stream->multiview_mode = GST_VIDEO_MULTIVIEW_MODE_NONE;
1979   stream->multiview_flags = GST_VIDEO_MULTIVIEW_FLAGS_NONE;
1980   stream->protected = FALSE;
1981   stream->protection_scheme_type = 0;
1982   stream->protection_scheme_version = 0;
1983   stream->protection_scheme_info = NULL;
1984   stream->n_samples_moof = 0;
1985   stream->duration_moof = 0;
1986   stream->duration_last_moof = 0;
1987   stream->alignment = 1;
1988   stream->stream_tags = gst_tag_list_new_empty ();
1989   gst_tag_list_set_scope (stream->stream_tags, GST_TAG_SCOPE_STREAM);
1990   g_queue_init (&stream->protection_scheme_event_queue);
1991   return stream;
1992 }
1993
1994 static gboolean
1995 gst_qtdemux_setcaps (GstQTDemux * demux, GstCaps * caps)
1996 {
1997   GstStructure *structure;
1998   const gchar *variant;
1999   const GstCaps *mediacaps = NULL;
2000
2001   GST_DEBUG_OBJECT (demux, "Sink set caps: %" GST_PTR_FORMAT, caps);
2002
2003   structure = gst_caps_get_structure (caps, 0);
2004   variant = gst_structure_get_string (structure, "variant");
2005
2006   if (variant && strcmp (variant, "mss-fragmented") == 0) {
2007     QtDemuxStream *stream;
2008     const GValue *value;
2009
2010     demux->fragmented = TRUE;
2011     demux->mss_mode = TRUE;
2012
2013     if (demux->n_streams > 1) {
2014       /* can't do this, we can only renegotiate for another mss format */
2015       return FALSE;
2016     }
2017
2018     value = gst_structure_get_value (structure, "media-caps");
2019     /* create stream */
2020     if (value) {
2021       const GValue *timescale_v;
2022
2023       /* TODO update when stream changes during playback */
2024
2025       if (demux->n_streams == 0) {
2026         stream = _create_stream (demux, 1);
2027         demux->active_streams = g_list_append (demux->active_streams, stream);
2028         demux->n_streams = 1;
2029         /* mss has no stsd/stsd entry, use id 0 as default */
2030         stream->stsd_entries_length = 1;
2031         stream->stsd_sample_description_id = stream->cur_stsd_entry_index = 0;
2032         stream->stsd_entries = g_new0 (QtDemuxStreamStsdEntry, 1);
2033       } else {
2034         stream = QTDEMUX_FIRST_STREAM (demux);
2035       }
2036
2037       timescale_v = gst_structure_get_value (structure, "timescale");
2038       if (timescale_v) {
2039         stream->timescale = g_value_get_uint64 (timescale_v);
2040       } else {
2041         /* default mss timescale */
2042         stream->timescale = 10000000;
2043       }
2044       demux->timescale = stream->timescale;
2045
2046       mediacaps = gst_value_get_caps (value);
2047       if (!CUR_STREAM (stream)->caps
2048           || !gst_caps_is_equal_fixed (mediacaps, CUR_STREAM (stream)->caps)) {
2049         GST_DEBUG_OBJECT (demux, "We have a new caps %" GST_PTR_FORMAT,
2050             mediacaps);
2051         stream->new_caps = TRUE;
2052       }
2053       gst_caps_replace (&CUR_STREAM (stream)->caps, (GstCaps *) mediacaps);
2054       structure = gst_caps_get_structure (mediacaps, 0);
2055       if (g_str_has_prefix (gst_structure_get_name (structure), "video")) {
2056         stream->subtype = FOURCC_vide;
2057
2058         gst_structure_get_int (structure, "width", &CUR_STREAM (stream)->width);
2059         gst_structure_get_int (structure, "height",
2060             &CUR_STREAM (stream)->height);
2061         gst_structure_get_fraction (structure, "framerate",
2062             &CUR_STREAM (stream)->fps_n, &CUR_STREAM (stream)->fps_d);
2063       } else if (g_str_has_prefix (gst_structure_get_name (structure), "audio")) {
2064         gint rate = 0;
2065         stream->subtype = FOURCC_soun;
2066         gst_structure_get_int (structure, "channels",
2067             &CUR_STREAM (stream)->n_channels);
2068         gst_structure_get_int (structure, "rate", &rate);
2069         CUR_STREAM (stream)->rate = rate;
2070       }
2071     }
2072     gst_caps_replace (&demux->media_caps, (GstCaps *) mediacaps);
2073   } else {
2074     demux->mss_mode = FALSE;
2075   }
2076
2077   return TRUE;
2078 }
2079
2080 static void
2081 gst_qtdemux_reset (GstQTDemux * qtdemux, gboolean hard)
2082 {
2083   GList *iter;
2084
2085   GST_DEBUG_OBJECT (qtdemux, "Resetting demux");
2086   gst_pad_stop_task (qtdemux->sinkpad);
2087
2088   if (hard || qtdemux->upstream_format_is_time) {
2089     qtdemux->state = QTDEMUX_STATE_INITIAL;
2090     qtdemux->neededbytes = 16;
2091     qtdemux->todrop = 0;
2092     qtdemux->pullbased = FALSE;
2093     qtdemux->posted_redirect = FALSE;
2094     qtdemux->first_mdat = -1;
2095     qtdemux->header_size = 0;
2096     qtdemux->mdatoffset = -1;
2097     qtdemux->restoredata_offset = -1;
2098     if (qtdemux->mdatbuffer)
2099       gst_buffer_unref (qtdemux->mdatbuffer);
2100     if (qtdemux->restoredata_buffer)
2101       gst_buffer_unref (qtdemux->restoredata_buffer);
2102     qtdemux->mdatbuffer = NULL;
2103     qtdemux->restoredata_buffer = NULL;
2104     qtdemux->mdatleft = 0;
2105     qtdemux->mdatsize = 0;
2106     if (qtdemux->comp_brands)
2107       gst_buffer_unref (qtdemux->comp_brands);
2108     qtdemux->comp_brands = NULL;
2109     qtdemux->last_moov_offset = -1;
2110     if (qtdemux->moov_node_compressed) {
2111       g_node_destroy (qtdemux->moov_node_compressed);
2112       if (qtdemux->moov_node)
2113         g_free (qtdemux->moov_node->data);
2114     }
2115     qtdemux->moov_node_compressed = NULL;
2116     if (qtdemux->moov_node)
2117       g_node_destroy (qtdemux->moov_node);
2118     qtdemux->moov_node = NULL;
2119     if (qtdemux->tag_list)
2120       gst_mini_object_unref (GST_MINI_OBJECT_CAST (qtdemux->tag_list));
2121     qtdemux->tag_list = gst_tag_list_new_empty ();
2122     gst_tag_list_set_scope (qtdemux->tag_list, GST_TAG_SCOPE_GLOBAL);
2123 #if 0
2124     if (qtdemux->element_index)
2125       gst_object_unref (qtdemux->element_index);
2126     qtdemux->element_index = NULL;
2127 #endif
2128     qtdemux->major_brand = 0;
2129     qtdemux->upstream_format_is_time = FALSE;
2130     qtdemux->upstream_seekable = FALSE;
2131     qtdemux->upstream_size = 0;
2132
2133     qtdemux->fragment_start = -1;
2134     qtdemux->fragment_start_offset = -1;
2135     qtdemux->duration = 0;
2136     qtdemux->moof_offset = 0;
2137     qtdemux->chapters_track_id = 0;
2138     qtdemux->have_group_id = FALSE;
2139     qtdemux->group_id = G_MAXUINT;
2140
2141     g_queue_foreach (&qtdemux->protection_event_queue, (GFunc) gst_event_unref,
2142         NULL);
2143     g_queue_clear (&qtdemux->protection_event_queue);
2144
2145     qtdemux->received_seek = FALSE;
2146     qtdemux->first_moof_already_parsed = FALSE;
2147   }
2148   qtdemux->offset = 0;
2149   gst_adapter_clear (qtdemux->adapter);
2150   gst_segment_init (&qtdemux->segment, GST_FORMAT_TIME);
2151   qtdemux->need_segment = TRUE;
2152
2153   if (hard) {
2154     qtdemux->segment_seqnum = GST_SEQNUM_INVALID;
2155     g_list_free_full (qtdemux->active_streams,
2156         (GDestroyNotify) gst_qtdemux_stream_free);
2157     g_list_free_full (qtdemux->old_streams,
2158         (GDestroyNotify) gst_qtdemux_stream_free);
2159     qtdemux->active_streams = NULL;
2160     qtdemux->old_streams = NULL;
2161     qtdemux->n_streams = 0;
2162     qtdemux->n_video_streams = 0;
2163     qtdemux->n_audio_streams = 0;
2164     qtdemux->n_sub_streams = 0;
2165     qtdemux->exposed = FALSE;
2166     qtdemux->fragmented = FALSE;
2167     qtdemux->mss_mode = FALSE;
2168     gst_caps_replace (&qtdemux->media_caps, NULL);
2169     qtdemux->timescale = 0;
2170     qtdemux->got_moov = FALSE;
2171     qtdemux->cenc_aux_info_offset = 0;
2172     qtdemux->cenc_aux_info_sizes = NULL;
2173     qtdemux->cenc_aux_sample_count = 0;
2174     if (qtdemux->protection_system_ids) {
2175       g_ptr_array_free (qtdemux->protection_system_ids, TRUE);
2176       qtdemux->protection_system_ids = NULL;
2177     }
2178     qtdemux->streams_aware = GST_OBJECT_PARENT (qtdemux)
2179         && GST_OBJECT_FLAG_IS_SET (GST_OBJECT_PARENT (qtdemux),
2180         GST_BIN_FLAG_STREAMS_AWARE);
2181
2182     if (qtdemux->preferred_protection_system_id) {
2183       g_free (qtdemux->preferred_protection_system_id);
2184       qtdemux->preferred_protection_system_id = NULL;
2185     }
2186   } else if (qtdemux->mss_mode) {
2187     gst_flow_combiner_reset (qtdemux->flowcombiner);
2188     g_list_foreach (qtdemux->active_streams,
2189         (GFunc) gst_qtdemux_stream_clear, NULL);
2190   } else {
2191     gst_flow_combiner_reset (qtdemux->flowcombiner);
2192     for (iter = qtdemux->active_streams; iter; iter = g_list_next (iter)) {
2193       QtDemuxStream *stream = QTDEMUX_STREAM (iter->data);
2194       stream->sent_eos = FALSE;
2195       stream->time_position = 0;
2196       stream->accumulated_base = 0;
2197     }
2198   }
2199 }
2200
2201
2202 /* Maps the @segment to the qt edts internal segments and pushes
2203  * the correspnding segment event.
2204  *
2205  * If it ends up being at a empty segment, a gap will be pushed and the next
2206  * edts segment will be activated in sequence.
2207  *
2208  * To be used in push-mode only */
2209 static void
2210 gst_qtdemux_map_and_push_segments (GstQTDemux * qtdemux, GstSegment * segment)
2211 {
2212   gint i;
2213   GList *iter;
2214
2215   for (iter = qtdemux->active_streams; iter; iter = g_list_next (iter)) {
2216     QtDemuxStream *stream = QTDEMUX_STREAM (iter->data);
2217
2218     stream->time_position = segment->start;
2219
2220     /* in push mode we should be guaranteed that we will have empty segments
2221      * at the beginning and then one segment after, other scenarios are not
2222      * supported and are discarded when parsing the edts */
2223     for (i = 0; i < stream->n_segments; i++) {
2224       if (stream->segments[i].stop_time > segment->start) {
2225         /* push the empty segment and move to the next one */
2226         gst_qtdemux_activate_segment (qtdemux, stream, i,
2227             stream->time_position);
2228         if (QTSEGMENT_IS_EMPTY (&stream->segments[i])) {
2229           gst_qtdemux_send_gap_for_segment (qtdemux, stream, i,
2230               stream->time_position);
2231
2232           /* accumulate previous segments */
2233           if (GST_CLOCK_TIME_IS_VALID (stream->segment.stop))
2234             stream->accumulated_base +=
2235                 (stream->segment.stop -
2236                 stream->segment.start) / ABS (stream->segment.rate);
2237           continue;
2238         }
2239
2240         g_assert (i == stream->n_segments - 1);
2241       }
2242     }
2243   }
2244 }
2245
2246 static gboolean
2247 gst_qtdemux_handle_sink_event (GstPad * sinkpad, GstObject * parent,
2248     GstEvent * event)
2249 {
2250   GstQTDemux *demux = GST_QTDEMUX (parent);
2251   gboolean res = TRUE;
2252
2253   GST_LOG_OBJECT (demux, "handling %s event", GST_EVENT_TYPE_NAME (event));
2254
2255   switch (GST_EVENT_TYPE (event)) {
2256     case GST_EVENT_SEGMENT:
2257     {
2258       gint64 offset = 0;
2259       QtDemuxStream *stream;
2260       gint idx;
2261       GstSegment segment;
2262
2263       /* some debug output */
2264       gst_event_copy_segment (event, &segment);
2265       GST_DEBUG_OBJECT (demux, "received newsegment %" GST_SEGMENT_FORMAT,
2266           &segment);
2267
2268       if (segment.format == GST_FORMAT_TIME) {
2269         demux->upstream_format_is_time = TRUE;
2270         demux->segment_seqnum = gst_event_get_seqnum (event);
2271       } else {
2272         GST_DEBUG_OBJECT (demux, "Not storing upstream newsegment, "
2273             "not in time format");
2274
2275         /* chain will send initial newsegment after pads have been added */
2276         if (demux->state != QTDEMUX_STATE_MOVIE || !demux->n_streams) {
2277           GST_DEBUG_OBJECT (demux, "still starting, eating event");
2278           goto exit;
2279         }
2280       }
2281
2282       /* check if this matches a time seek we received previously
2283        * FIXME for backwards compatibility reasons we use the
2284        * seek_offset here to compare. In the future we might want to
2285        * change this to use the seqnum as it uniquely should identify
2286        * the segment that corresponds to the seek. */
2287       GST_DEBUG_OBJECT (demux, "Stored seek offset: %" G_GINT64_FORMAT
2288           ", received segment offset %" G_GINT64_FORMAT,
2289           demux->seek_offset, segment.start);
2290       if (segment.format == GST_FORMAT_BYTES
2291           && demux->seek_offset == segment.start) {
2292         GST_OBJECT_LOCK (demux);
2293         offset = segment.start;
2294
2295         segment.format = GST_FORMAT_TIME;
2296         segment.start = demux->push_seek_start;
2297         segment.stop = demux->push_seek_stop;
2298         GST_DEBUG_OBJECT (demux, "Replaced segment with stored seek "
2299             "segment %" GST_TIME_FORMAT " - %" GST_TIME_FORMAT,
2300             GST_TIME_ARGS (segment.start), GST_TIME_ARGS (segment.stop));
2301         GST_OBJECT_UNLOCK (demux);
2302       }
2303
2304       /* we only expect a BYTE segment, e.g. following a seek */
2305       if (segment.format == GST_FORMAT_BYTES) {
2306         if (GST_CLOCK_TIME_IS_VALID (segment.start)) {
2307           offset = segment.start;
2308
2309           gst_qtdemux_find_sample (demux, segment.start, TRUE, FALSE, NULL,
2310               NULL, (gint64 *) & segment.start);
2311           if ((gint64) segment.start < 0)
2312             segment.start = 0;
2313         }
2314         if (GST_CLOCK_TIME_IS_VALID (segment.stop)) {
2315           gst_qtdemux_find_sample (demux, segment.stop, FALSE, FALSE, NULL,
2316               NULL, (gint64 *) & segment.stop);
2317           /* keyframe seeking should already arrange for start >= stop,
2318            * but make sure in other rare cases */
2319           segment.stop = MAX (segment.stop, segment.start);
2320         }
2321       } else if (segment.format == GST_FORMAT_TIME) {
2322         /* push all data on the adapter before starting this
2323          * new segment */
2324         gst_qtdemux_process_adapter (demux, TRUE);
2325       } else {
2326         GST_DEBUG_OBJECT (demux, "unsupported segment format, ignoring");
2327         goto exit;
2328       }
2329
2330       /* We shouldn't modify upstream driven TIME FORMAT segment */
2331       if (!demux->upstream_format_is_time) {
2332         /* accept upstream's notion of segment and distribute along */
2333         segment.format = GST_FORMAT_TIME;
2334         segment.position = segment.time = segment.start;
2335         segment.duration = demux->segment.duration;
2336         segment.base = gst_segment_to_running_time (&demux->segment,
2337             GST_FORMAT_TIME, demux->segment.position);
2338       }
2339
2340       gst_segment_copy_into (&segment, &demux->segment);
2341       GST_DEBUG_OBJECT (demux, "Pushing newseg %" GST_SEGMENT_FORMAT, &segment);
2342
2343       /* map segment to internal qt segments and push on each stream */
2344       if (demux->n_streams) {
2345         demux->need_segment = TRUE;
2346         gst_qtdemux_check_send_pending_segment (demux);
2347       }
2348
2349       /* clear leftover in current segment, if any */
2350       gst_adapter_clear (demux->adapter);
2351
2352       /* set up streaming thread */
2353       demux->offset = offset;
2354       if (demux->upstream_format_is_time) {
2355         GST_DEBUG_OBJECT (demux, "Upstream is driving in time format, "
2356             "set values to restart reading from a new atom");
2357         demux->neededbytes = 16;
2358         demux->todrop = 0;
2359       } else {
2360         gst_qtdemux_find_sample (demux, offset, TRUE, TRUE, &stream, &idx,
2361             NULL);
2362         if (stream) {
2363           demux->todrop = stream->samples[idx].offset - offset;
2364           demux->neededbytes = demux->todrop + stream->samples[idx].size;
2365         } else {
2366           /* set up for EOS */
2367           demux->neededbytes = -1;
2368           demux->todrop = 0;
2369         }
2370       }
2371     exit:
2372       gst_event_unref (event);
2373       res = TRUE;
2374       goto drop;
2375     }
2376     case GST_EVENT_FLUSH_START:
2377     {
2378       if (gst_event_get_seqnum (event) == demux->offset_seek_seqnum) {
2379         gst_event_unref (event);
2380         goto drop;
2381       }
2382       QTDEMUX_EXPOSE_LOCK (demux);
2383       res = gst_pad_event_default (demux->sinkpad, parent, event);
2384       QTDEMUX_EXPOSE_UNLOCK (demux);
2385       goto drop;
2386     }
2387     case GST_EVENT_FLUSH_STOP:
2388     {
2389       guint64 dur;
2390
2391       dur = demux->segment.duration;
2392       gst_qtdemux_reset (demux, FALSE);
2393       demux->segment.duration = dur;
2394
2395       if (gst_event_get_seqnum (event) == demux->offset_seek_seqnum) {
2396         gst_event_unref (event);
2397         goto drop;
2398       }
2399       break;
2400     }
2401     case GST_EVENT_EOS:
2402       /* If we are in push mode, and get an EOS before we've seen any streams,
2403        * then error out - we have nowhere to send the EOS */
2404       if (!demux->pullbased) {
2405         GList *iter;
2406         gboolean has_valid_stream = FALSE;
2407         for (iter = demux->active_streams; iter; iter = g_list_next (iter)) {
2408           if (QTDEMUX_STREAM (iter->data)->pad != NULL) {
2409             has_valid_stream = TRUE;
2410             break;
2411           }
2412         }
2413         if (!has_valid_stream)
2414           gst_qtdemux_post_no_playable_stream_error (demux);
2415         else {
2416           GST_DEBUG_OBJECT (demux, "Data still available after EOS: %u",
2417               (guint) gst_adapter_available (demux->adapter));
2418           if (gst_qtdemux_process_adapter (demux, TRUE) != GST_FLOW_OK) {
2419             res = FALSE;
2420           }
2421         }
2422       }
2423       break;
2424     case GST_EVENT_CAPS:{
2425       GstCaps *caps = NULL;
2426
2427       gst_event_parse_caps (event, &caps);
2428       gst_qtdemux_setcaps (demux, caps);
2429       res = TRUE;
2430       gst_event_unref (event);
2431       goto drop;
2432     }
2433     case GST_EVENT_PROTECTION:
2434     {
2435       const gchar *system_id = NULL;
2436
2437       gst_event_parse_protection (event, &system_id, NULL, NULL);
2438       GST_DEBUG_OBJECT (demux, "Received protection event for system ID %s",
2439           system_id);
2440       gst_qtdemux_append_protection_system_id (demux, system_id);
2441       /* save the event for later, for source pads that have not been created */
2442       g_queue_push_tail (&demux->protection_event_queue, gst_event_ref (event));
2443       /* send it to all pads that already exist */
2444       gst_qtdemux_push_event (demux, event);
2445       res = TRUE;
2446       goto drop;
2447     }
2448     case GST_EVENT_STREAM_START:
2449     {
2450       res = TRUE;
2451       gst_event_unref (event);
2452
2453       /* Drain all the buffers */
2454       gst_qtdemux_process_adapter (demux, TRUE);
2455       gst_qtdemux_reset (demux, FALSE);
2456       /* We expect new moov box after new stream-start event */
2457       demux->old_streams =
2458           g_list_concat (demux->old_streams, demux->active_streams);
2459       demux->active_streams = NULL;
2460
2461       goto drop;
2462     }
2463     default:
2464       break;
2465   }
2466
2467   res = gst_pad_event_default (demux->sinkpad, parent, event) & res;
2468
2469 drop:
2470   return res;
2471 }
2472
2473 #if 0
2474 static void
2475 gst_qtdemux_set_index (GstElement * element, GstIndex * index)
2476 {
2477   GstQTDemux *demux = GST_QTDEMUX (element);
2478
2479   GST_OBJECT_LOCK (demux);
2480   if (demux->element_index)
2481     gst_object_unref (demux->element_index);
2482   if (index) {
2483     demux->element_index = gst_object_ref (index);
2484   } else {
2485     demux->element_index = NULL;
2486   }
2487   GST_OBJECT_UNLOCK (demux);
2488   /* object lock might be taken again */
2489   if (index)
2490     gst_index_get_writer_id (index, GST_OBJECT (element), &demux->index_id);
2491   GST_DEBUG_OBJECT (demux, "Set index %" GST_PTR_FORMAT "for writer id %d",
2492       demux->element_index, demux->index_id);
2493 }
2494
2495 static GstIndex *
2496 gst_qtdemux_get_index (GstElement * element)
2497 {
2498   GstIndex *result = NULL;
2499   GstQTDemux *demux = GST_QTDEMUX (element);
2500
2501   GST_OBJECT_LOCK (demux);
2502   if (demux->element_index)
2503     result = gst_object_ref (demux->element_index);
2504   GST_OBJECT_UNLOCK (demux);
2505
2506   GST_DEBUG_OBJECT (demux, "Returning index %" GST_PTR_FORMAT, result);
2507
2508   return result;
2509 }
2510 #endif
2511
2512 static void
2513 gst_qtdemux_stbl_free (QtDemuxStream * stream)
2514 {
2515   g_free ((gpointer) stream->stco.data);
2516   stream->stco.data = NULL;
2517   g_free ((gpointer) stream->stsz.data);
2518   stream->stsz.data = NULL;
2519   g_free ((gpointer) stream->stsc.data);
2520   stream->stsc.data = NULL;
2521   g_free ((gpointer) stream->stts.data);
2522   stream->stts.data = NULL;
2523   g_free ((gpointer) stream->stss.data);
2524   stream->stss.data = NULL;
2525   g_free ((gpointer) stream->stps.data);
2526   stream->stps.data = NULL;
2527   g_free ((gpointer) stream->ctts.data);
2528   stream->ctts.data = NULL;
2529 }
2530
2531 static void
2532 gst_qtdemux_stream_flush_segments_data (QtDemuxStream * stream)
2533 {
2534   g_free (stream->segments);
2535   stream->segments = NULL;
2536   stream->segment_index = -1;
2537   stream->accumulated_base = 0;
2538 }
2539
2540 static void
2541 gst_qtdemux_stream_flush_samples_data (QtDemuxStream * stream)
2542 {
2543   g_free (stream->samples);
2544   stream->samples = NULL;
2545   gst_qtdemux_stbl_free (stream);
2546
2547   /* fragments */
2548   g_free (stream->ra_entries);
2549   stream->ra_entries = NULL;
2550   stream->n_ra_entries = 0;
2551
2552   stream->sample_index = -1;
2553   stream->stbl_index = -1;
2554   stream->n_samples = 0;
2555   stream->time_position = 0;
2556
2557   stream->n_samples_moof = 0;
2558   stream->duration_moof = 0;
2559   stream->duration_last_moof = 0;
2560 }
2561
2562 static void
2563 gst_qtdemux_stream_clear (QtDemuxStream * stream)
2564 {
2565   gint i;
2566   if (stream->allocator)
2567     gst_object_unref (stream->allocator);
2568   while (stream->buffers) {
2569     gst_buffer_unref (GST_BUFFER_CAST (stream->buffers->data));
2570     stream->buffers = g_slist_delete_link (stream->buffers, stream->buffers);
2571   }
2572   for (i = 0; i < stream->stsd_entries_length; i++) {
2573     QtDemuxStreamStsdEntry *entry = &stream->stsd_entries[i];
2574     if (entry->rgb8_palette) {
2575       gst_memory_unref (entry->rgb8_palette);
2576       entry->rgb8_palette = NULL;
2577     }
2578     entry->sparse = FALSE;
2579   }
2580
2581   if (stream->stream_tags)
2582     gst_tag_list_unref (stream->stream_tags);
2583
2584   stream->stream_tags = gst_tag_list_new_empty ();
2585   gst_tag_list_set_scope (stream->stream_tags, GST_TAG_SCOPE_STREAM);
2586   g_free (stream->redirect_uri);
2587   stream->redirect_uri = NULL;
2588   stream->sent_eos = FALSE;
2589   stream->protected = FALSE;
2590   if (stream->protection_scheme_info) {
2591     if (stream->protection_scheme_type == FOURCC_cenc) {
2592       QtDemuxCencSampleSetInfo *info =
2593           (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
2594       if (info->default_properties)
2595         gst_structure_free (info->default_properties);
2596       if (info->crypto_info)
2597         g_ptr_array_free (info->crypto_info, TRUE);
2598     }
2599     g_free (stream->protection_scheme_info);
2600     stream->protection_scheme_info = NULL;
2601   }
2602   stream->protection_scheme_type = 0;
2603   stream->protection_scheme_version = 0;
2604   g_queue_foreach (&stream->protection_scheme_event_queue,
2605       (GFunc) gst_event_unref, NULL);
2606   g_queue_clear (&stream->protection_scheme_event_queue);
2607   gst_qtdemux_stream_flush_segments_data (stream);
2608   gst_qtdemux_stream_flush_samples_data (stream);
2609 }
2610
2611 static void
2612 gst_qtdemux_stream_reset (QtDemuxStream * stream)
2613 {
2614   gint i;
2615   gst_qtdemux_stream_clear (stream);
2616   for (i = 0; i < stream->stsd_entries_length; i++) {
2617     QtDemuxStreamStsdEntry *entry = &stream->stsd_entries[i];
2618     if (entry->caps) {
2619       gst_caps_unref (entry->caps);
2620       entry->caps = NULL;
2621     }
2622   }
2623   g_free (stream->stsd_entries);
2624   stream->stsd_entries = NULL;
2625   stream->stsd_entries_length = 0;
2626 }
2627
2628
2629 static void
2630 gst_qtdemux_stream_free (QtDemuxStream * stream)
2631 {
2632   gst_qtdemux_stream_reset (stream);
2633   gst_tag_list_unref (stream->stream_tags);
2634   if (stream->pad) {
2635     GstQTDemux *demux = stream->demux;
2636     gst_element_remove_pad (GST_ELEMENT_CAST (demux), stream->pad);
2637     gst_flow_combiner_remove_pad (demux->flowcombiner, stream->pad);
2638   }
2639   g_free (stream->stream_id);
2640   g_free (stream);
2641 }
2642
2643 static void
2644 gst_qtdemux_remove_stream (GstQTDemux * qtdemux, QtDemuxStream * stream)
2645 {
2646   qtdemux->active_streams = g_list_remove (qtdemux->active_streams, stream);
2647   gst_qtdemux_stream_free (stream);
2648   qtdemux->n_streams--;
2649 }
2650
2651 static GstStateChangeReturn
2652 gst_qtdemux_change_state (GstElement * element, GstStateChange transition)
2653 {
2654   GstQTDemux *qtdemux = GST_QTDEMUX (element);
2655   GstStateChangeReturn result = GST_STATE_CHANGE_FAILURE;
2656
2657   switch (transition) {
2658     case GST_STATE_CHANGE_READY_TO_PAUSED:
2659       gst_qtdemux_reset (qtdemux, TRUE);
2660       break;
2661     default:
2662       break;
2663   }
2664
2665   result = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
2666
2667   switch (transition) {
2668     case GST_STATE_CHANGE_PAUSED_TO_READY:{
2669       gst_qtdemux_reset (qtdemux, TRUE);
2670       break;
2671     }
2672     default:
2673       break;
2674   }
2675
2676   return result;
2677 }
2678
2679 static void
2680 gst_qtdemux_set_context (GstElement * element, GstContext * context)
2681 {
2682   GstQTDemux *qtdemux = GST_QTDEMUX (element);
2683
2684   g_return_if_fail (GST_IS_CONTEXT (context));
2685
2686   if (gst_context_has_context_type (context,
2687           "drm-preferred-decryption-system-id")) {
2688     const GstStructure *s;
2689
2690     s = gst_context_get_structure (context);
2691     g_free (qtdemux->preferred_protection_system_id);
2692     qtdemux->preferred_protection_system_id =
2693         g_strdup (gst_structure_get_string (s, "decryption-system-id"));
2694     GST_DEBUG_OBJECT (element, "set preferred decryption system to %s",
2695         qtdemux->preferred_protection_system_id);
2696   }
2697
2698   GST_ELEMENT_CLASS (parent_class)->set_context (element, context);
2699 }
2700
2701 static void
2702 qtdemux_parse_ftyp (GstQTDemux * qtdemux, const guint8 * buffer, gint length)
2703 {
2704   /* counts as header data */
2705   qtdemux->header_size += length;
2706
2707   /* only consider at least a sufficiently complete ftyp atom */
2708   if (length >= 20) {
2709     GstBuffer *buf;
2710
2711     qtdemux->major_brand = QT_FOURCC (buffer + 8);
2712     GST_DEBUG_OBJECT (qtdemux, "major brand: %" GST_FOURCC_FORMAT,
2713         GST_FOURCC_ARGS (qtdemux->major_brand));
2714     if (qtdemux->comp_brands)
2715       gst_buffer_unref (qtdemux->comp_brands);
2716     buf = qtdemux->comp_brands = gst_buffer_new_and_alloc (length - 16);
2717     gst_buffer_fill (buf, 0, buffer + 16, length - 16);
2718   }
2719 }
2720
2721 static void
2722 qtdemux_handle_xmp_taglist (GstQTDemux * qtdemux, GstTagList * taglist,
2723     GstTagList * xmptaglist)
2724 {
2725   /* Strip out bogus fields */
2726   if (xmptaglist) {
2727     if (gst_tag_list_get_scope (taglist) == GST_TAG_SCOPE_GLOBAL) {
2728       gst_tag_list_remove_tag (xmptaglist, GST_TAG_VIDEO_CODEC);
2729       gst_tag_list_remove_tag (xmptaglist, GST_TAG_AUDIO_CODEC);
2730     } else {
2731       gst_tag_list_remove_tag (xmptaglist, GST_TAG_CONTAINER_FORMAT);
2732     }
2733
2734     GST_DEBUG_OBJECT (qtdemux, "Found XMP tags %" GST_PTR_FORMAT, xmptaglist);
2735
2736     /* prioritize native tags using _KEEP mode */
2737     gst_tag_list_insert (taglist, xmptaglist, GST_TAG_MERGE_KEEP);
2738     gst_tag_list_unref (xmptaglist);
2739   }
2740 }
2741
2742 static void
2743 qtdemux_update_default_sample_encryption_settings (GstQTDemux * qtdemux,
2744     QtDemuxCencSampleSetInfo * info, guint32 is_encrypted, guint8 iv_size,
2745     const guint8 * kid)
2746 {
2747   GstBuffer *kid_buf = gst_buffer_new_allocate (NULL, 16, NULL);
2748   gst_buffer_fill (kid_buf, 0, kid, 16);
2749   if (info->default_properties)
2750     gst_structure_free (info->default_properties);
2751   info->default_properties =
2752       gst_structure_new ("application/x-cenc",
2753       "iv_size", G_TYPE_UINT, iv_size,
2754       "encrypted", G_TYPE_BOOLEAN, (is_encrypted == 1),
2755       "kid", GST_TYPE_BUFFER, kid_buf, NULL);
2756   GST_DEBUG_OBJECT (qtdemux, "default sample properties: "
2757       "is_encrypted=%u, iv_size=%u", is_encrypted, iv_size);
2758   gst_buffer_unref (kid_buf);
2759 }
2760
2761 static gboolean
2762 qtdemux_update_default_piff_encryption_settings (GstQTDemux * qtdemux,
2763     QtDemuxCencSampleSetInfo * info, GstByteReader * br)
2764 {
2765   guint32 algorithm_id = 0;
2766   const guint8 *kid;
2767   gboolean is_encrypted = TRUE;
2768   guint8 iv_size = 8;
2769
2770   if (!gst_byte_reader_get_uint24_le (br, &algorithm_id)) {
2771     GST_ERROR_OBJECT (qtdemux, "Error getting box's algorithm ID field");
2772     return FALSE;
2773   }
2774
2775   algorithm_id >>= 8;
2776   if (algorithm_id == 0) {
2777     is_encrypted = FALSE;
2778   } else if (algorithm_id == 1) {
2779     GST_DEBUG_OBJECT (qtdemux, "AES 128-bits CTR encrypted stream");
2780   } else if (algorithm_id == 2) {
2781     GST_DEBUG_OBJECT (qtdemux, "AES 128-bits CBC encrypted stream");
2782   }
2783
2784   if (!gst_byte_reader_get_uint8 (br, &iv_size))
2785     return FALSE;
2786
2787   if (!gst_byte_reader_get_data (br, 16, &kid))
2788     return FALSE;
2789
2790   qtdemux_update_default_sample_encryption_settings (qtdemux, info,
2791       is_encrypted, iv_size, kid);
2792   gst_structure_set (info->default_properties, "piff_algorithm_id",
2793       G_TYPE_UINT, algorithm_id, NULL);
2794   return TRUE;
2795 }
2796
2797
2798 static void
2799 qtdemux_parse_piff (GstQTDemux * qtdemux, const guint8 * buffer, gint length,
2800     guint offset)
2801 {
2802   GstByteReader br;
2803   guint8 version;
2804   guint32 flags = 0;
2805   guint i;
2806   guint iv_size = 8;
2807   QtDemuxStream *stream;
2808   GstStructure *structure;
2809   QtDemuxCencSampleSetInfo *ss_info = NULL;
2810   const gchar *system_id;
2811   gboolean uses_sub_sample_encryption = FALSE;
2812   guint32 sample_count;
2813
2814   stream = QTDEMUX_FIRST_STREAM (qtdemux);
2815   if (!stream)
2816     return;
2817
2818   structure = gst_caps_get_structure (CUR_STREAM (stream)->caps, 0);
2819   if (!gst_structure_has_name (structure, "application/x-cenc")) {
2820     GST_WARNING_OBJECT (qtdemux,
2821         "Attempting PIFF box parsing on an unencrypted stream.");
2822     return;
2823   }
2824
2825   gst_structure_get (structure, GST_PROTECTION_SYSTEM_ID_CAPS_FIELD,
2826       G_TYPE_STRING, &system_id, NULL);
2827   gst_qtdemux_append_protection_system_id (qtdemux, system_id);
2828
2829   stream->protected = TRUE;
2830   stream->protection_scheme_type = FOURCC_cenc;
2831
2832   if (!stream->protection_scheme_info)
2833     stream->protection_scheme_info = g_new0 (QtDemuxCencSampleSetInfo, 1);
2834
2835   ss_info = (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
2836   if (!ss_info->default_properties) {
2837     ss_info->default_properties =
2838         gst_structure_new ("application/x-cenc",
2839         "iv_size", G_TYPE_UINT, iv_size, "encrypted", G_TYPE_BOOLEAN, TRUE,
2840         NULL);
2841
2842   }
2843
2844   if (ss_info->crypto_info) {
2845     GST_LOG_OBJECT (qtdemux, "unreffing existing crypto_info");
2846     g_ptr_array_free (ss_info->crypto_info, TRUE);
2847     ss_info->crypto_info = NULL;
2848   }
2849
2850   /* skip UUID */
2851   gst_byte_reader_init (&br, buffer + offset + 16, length - offset - 16);
2852
2853   if (!gst_byte_reader_get_uint8 (&br, &version)) {
2854     GST_ERROR_OBJECT (qtdemux, "Error getting box's version field");
2855     return;
2856   }
2857
2858   if (!gst_byte_reader_get_uint24_be (&br, &flags)) {
2859     GST_ERROR_OBJECT (qtdemux, "Error getting box's flags field");
2860     return;
2861   }
2862
2863   if ((flags & 0x000001)) {
2864     if (!qtdemux_update_default_piff_encryption_settings (qtdemux, ss_info,
2865             &br))
2866       return;
2867   } else if ((flags & 0x000002)) {
2868     uses_sub_sample_encryption = TRUE;
2869   }
2870
2871   if (!gst_structure_get_uint (ss_info->default_properties, "iv_size",
2872           &iv_size)) {
2873     GST_ERROR_OBJECT (qtdemux, "Error getting encryption IV size field");
2874     return;
2875   }
2876
2877   if (!gst_byte_reader_get_uint32_be (&br, &sample_count)) {
2878     GST_ERROR_OBJECT (qtdemux, "Error getting box's sample count field");
2879     return;
2880   }
2881
2882   ss_info->crypto_info =
2883       g_ptr_array_new_full (sample_count,
2884       (GDestroyNotify) qtdemux_gst_structure_free);
2885
2886   for (i = 0; i < sample_count; ++i) {
2887     GstStructure *properties;
2888     guint8 *data;
2889     GstBuffer *buf;
2890
2891     properties = qtdemux_get_cenc_sample_properties (qtdemux, stream, i);
2892     if (properties == NULL) {
2893       GST_ERROR_OBJECT (qtdemux, "failed to get properties for sample %u", i);
2894       qtdemux->cenc_aux_sample_count = i;
2895       return;
2896     }
2897
2898     if (!gst_byte_reader_dup_data (&br, iv_size, &data)) {
2899       GST_ERROR_OBJECT (qtdemux, "IV data not present for sample %u", i);
2900       gst_structure_free (properties);
2901       qtdemux->cenc_aux_sample_count = i;
2902       return;
2903     }
2904     buf = gst_buffer_new_wrapped (data, iv_size);
2905     gst_structure_set (properties, "iv", GST_TYPE_BUFFER, buf, NULL);
2906     gst_buffer_unref (buf);
2907
2908     if (uses_sub_sample_encryption) {
2909       guint16 n_subsamples;
2910       const GValue *kid_buf_value;
2911
2912       if (!gst_byte_reader_get_uint16_be (&br, &n_subsamples)
2913           || n_subsamples == 0) {
2914         GST_ERROR_OBJECT (qtdemux,
2915             "failed to get subsample count for sample %u", i);
2916         gst_structure_free (properties);
2917         qtdemux->cenc_aux_sample_count = i;
2918         return;
2919       }
2920       GST_LOG_OBJECT (qtdemux, "subsample count: %u", n_subsamples);
2921       if (!gst_byte_reader_dup_data (&br, n_subsamples * 6, &data)) {
2922         GST_ERROR_OBJECT (qtdemux, "failed to get subsample data for sample %u",
2923             i);
2924         gst_structure_free (properties);
2925         qtdemux->cenc_aux_sample_count = i;
2926         return;
2927       }
2928       buf = gst_buffer_new_wrapped (data, n_subsamples * 6);
2929
2930       kid_buf_value =
2931           gst_structure_get_value (ss_info->default_properties, "kid");
2932
2933       gst_structure_set (properties,
2934           "subsample_count", G_TYPE_UINT, n_subsamples,
2935           "subsamples", GST_TYPE_BUFFER, buf, NULL);
2936       gst_structure_set_value (properties, "kid", kid_buf_value);
2937       gst_buffer_unref (buf);
2938     } else {
2939       gst_structure_set (properties, "subsample_count", G_TYPE_UINT, 0, NULL);
2940     }
2941
2942     g_ptr_array_add (ss_info->crypto_info, properties);
2943   }
2944
2945   qtdemux->cenc_aux_sample_count = sample_count;
2946 }
2947
2948 static void
2949 qtdemux_parse_uuid (GstQTDemux * qtdemux, const guint8 * buffer, gint length)
2950 {
2951   static const guint8 xmp_uuid[] = { 0xBE, 0x7A, 0xCF, 0xCB,
2952     0x97, 0xA9, 0x42, 0xE8,
2953     0x9C, 0x71, 0x99, 0x94,
2954     0x91, 0xE3, 0xAF, 0xAC
2955   };
2956   static const guint8 playready_uuid[] = {
2957     0xd0, 0x8a, 0x4f, 0x18, 0x10, 0xf3, 0x4a, 0x82,
2958     0xb6, 0xc8, 0x32, 0xd8, 0xab, 0xa1, 0x83, 0xd3
2959   };
2960
2961   static const guint8 piff_sample_encryption_uuid[] = {
2962     0xa2, 0x39, 0x4f, 0x52, 0x5a, 0x9b, 0x4f, 0x14,
2963     0xa2, 0x44, 0x6c, 0x42, 0x7c, 0x64, 0x8d, 0xf4
2964   };
2965
2966   guint offset;
2967
2968   /* counts as header data */
2969   qtdemux->header_size += length;
2970
2971   offset = (QT_UINT32 (buffer) == 0) ? 16 : 8;
2972
2973   if (length <= offset + 16) {
2974     GST_DEBUG_OBJECT (qtdemux, "uuid atom is too short, skipping");
2975     return;
2976   }
2977
2978   if (memcmp (buffer + offset, xmp_uuid, 16) == 0) {
2979     GstBuffer *buf;
2980     GstTagList *taglist;
2981
2982     buf = _gst_buffer_new_wrapped ((guint8 *) buffer + offset + 16,
2983         length - offset - 16, NULL);
2984     taglist = gst_tag_list_from_xmp_buffer (buf);
2985     gst_buffer_unref (buf);
2986
2987     /* make sure we have a usable taglist */
2988     qtdemux->tag_list = gst_tag_list_make_writable (qtdemux->tag_list);
2989
2990     qtdemux_handle_xmp_taglist (qtdemux, qtdemux->tag_list, taglist);
2991
2992   } else if (memcmp (buffer + offset, playready_uuid, 16) == 0) {
2993     int len;
2994     const gunichar2 *s_utf16;
2995     char *contents;
2996
2997     len = GST_READ_UINT16_LE (buffer + offset + 0x30);
2998     s_utf16 = (const gunichar2 *) (buffer + offset + 0x32);
2999     contents = g_utf16_to_utf8 (s_utf16, len / 2, NULL, NULL, NULL);
3000     GST_ERROR_OBJECT (qtdemux, "contents: %s", contents);
3001
3002     g_free (contents);
3003
3004     GST_ELEMENT_ERROR (qtdemux, STREAM, DECRYPT,
3005         (_("Cannot play stream because it is encrypted with PlayReady DRM.")),
3006         (NULL));
3007   } else if (memcmp (buffer + offset, piff_sample_encryption_uuid, 16) == 0) {
3008     qtdemux_parse_piff (qtdemux, buffer, length, offset);
3009   } else {
3010     GST_DEBUG_OBJECT (qtdemux, "Ignoring unknown uuid: %08x-%08x-%08x-%08x",
3011         GST_READ_UINT32_LE (buffer + offset),
3012         GST_READ_UINT32_LE (buffer + offset + 4),
3013         GST_READ_UINT32_LE (buffer + offset + 8),
3014         GST_READ_UINT32_LE (buffer + offset + 12));
3015   }
3016 }
3017
3018 static void
3019 qtdemux_parse_sidx (GstQTDemux * qtdemux, const guint8 * buffer, gint length)
3020 {
3021   GstSidxParser sidx_parser;
3022   GstIsoffParserResult res;
3023   guint consumed;
3024
3025   gst_isoff_qt_sidx_parser_init (&sidx_parser);
3026
3027   res =
3028       gst_isoff_qt_sidx_parser_add_data (&sidx_parser, buffer, length,
3029       &consumed);
3030   GST_DEBUG_OBJECT (qtdemux, "sidx parse result: %d", res);
3031   if (res == GST_ISOFF_QT_PARSER_DONE) {
3032     check_update_duration (qtdemux, sidx_parser.cumulative_pts);
3033   }
3034   gst_isoff_qt_sidx_parser_clear (&sidx_parser);
3035 }
3036
3037 /* caller verifies at least 8 bytes in buf */
3038 static void
3039 extract_initial_length_and_fourcc (const guint8 * data, guint size,
3040     guint64 * plength, guint32 * pfourcc)
3041 {
3042   guint64 length;
3043   guint32 fourcc;
3044
3045   length = QT_UINT32 (data);
3046   GST_DEBUG ("length 0x%08" G_GINT64_MODIFIER "x", length);
3047   fourcc = QT_FOURCC (data + 4);
3048   GST_DEBUG ("atom type %" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (fourcc));
3049
3050   if (length == 0) {
3051     length = G_MAXUINT64;
3052   } else if (length == 1 && size >= 16) {
3053     /* this means we have an extended size, which is the 64 bit value of
3054      * the next 8 bytes */
3055     length = QT_UINT64 (data + 8);
3056     GST_DEBUG ("length 0x%08" G_GINT64_MODIFIER "x", length);
3057   }
3058
3059   if (plength)
3060     *plength = length;
3061   if (pfourcc)
3062     *pfourcc = fourcc;
3063 }
3064
3065 static gboolean
3066 qtdemux_parse_mehd (GstQTDemux * qtdemux, GstByteReader * br)
3067 {
3068   guint32 version = 0;
3069   GstClockTime duration = 0;
3070
3071   if (!gst_byte_reader_get_uint32_be (br, &version))
3072     goto failed;
3073
3074   version >>= 24;
3075   if (version == 1) {
3076     if (!gst_byte_reader_get_uint64_be (br, &duration))
3077       goto failed;
3078   } else {
3079     guint32 dur = 0;
3080
3081     if (!gst_byte_reader_get_uint32_be (br, &dur))
3082       goto failed;
3083     duration = dur;
3084   }
3085
3086   GST_INFO_OBJECT (qtdemux, "mehd duration: %" G_GUINT64_FORMAT, duration);
3087   qtdemux->duration = duration;
3088
3089   return TRUE;
3090
3091 failed:
3092   {
3093     GST_DEBUG_OBJECT (qtdemux, "parsing mehd failed");
3094     return FALSE;
3095   }
3096 }
3097
3098 static gboolean
3099 qtdemux_parse_trex (GstQTDemux * qtdemux, QtDemuxStream * stream,
3100     guint32 * ds_duration, guint32 * ds_size, guint32 * ds_flags)
3101 {
3102   if (!stream->parsed_trex && qtdemux->moov_node) {
3103     GNode *mvex, *trex;
3104     GstByteReader trex_data;
3105
3106     mvex = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_mvex);
3107     if (mvex) {
3108       trex = qtdemux_tree_get_child_by_type_full (mvex, FOURCC_trex,
3109           &trex_data);
3110       while (trex) {
3111         guint32 id = 0, sdi = 0, dur = 0, size = 0, flags = 0;
3112
3113         /* skip version/flags */
3114         if (!gst_byte_reader_skip (&trex_data, 4))
3115           goto next;
3116         if (!gst_byte_reader_get_uint32_be (&trex_data, &id))
3117           goto next;
3118         if (id != stream->track_id)
3119           goto next;
3120         if (!gst_byte_reader_get_uint32_be (&trex_data, &sdi))
3121           goto next;
3122         if (!gst_byte_reader_get_uint32_be (&trex_data, &dur))
3123           goto next;
3124         if (!gst_byte_reader_get_uint32_be (&trex_data, &size))
3125           goto next;
3126         if (!gst_byte_reader_get_uint32_be (&trex_data, &flags))
3127           goto next;
3128
3129         GST_DEBUG_OBJECT (qtdemux, "fragment defaults for stream %d; "
3130             "duration %d,  size %d, flags 0x%x", stream->track_id,
3131             dur, size, flags);
3132
3133         stream->parsed_trex = TRUE;
3134         stream->def_sample_description_index = sdi;
3135         stream->def_sample_duration = dur;
3136         stream->def_sample_size = size;
3137         stream->def_sample_flags = flags;
3138
3139       next:
3140         /* iterate all siblings */
3141         trex = qtdemux_tree_get_sibling_by_type_full (trex, FOURCC_trex,
3142             &trex_data);
3143       }
3144     }
3145   }
3146
3147   *ds_duration = stream->def_sample_duration;
3148   *ds_size = stream->def_sample_size;
3149   *ds_flags = stream->def_sample_flags;
3150
3151   /* even then, above values are better than random ... */
3152   if (G_UNLIKELY (!stream->parsed_trex)) {
3153     GST_WARNING_OBJECT (qtdemux,
3154         "failed to find fragment defaults for stream %d", stream->track_id);
3155     return FALSE;
3156   }
3157
3158   return TRUE;
3159 }
3160
3161 /* This method should be called whenever a more accurate duration might
3162  * have been found. It will update all relevant variables if/where needed
3163  */
3164 static void
3165 check_update_duration (GstQTDemux * qtdemux, GstClockTime duration)
3166 {
3167   guint i;
3168   guint64 movdur;
3169   GstClockTime prevdur;
3170   GList *iter;
3171
3172   movdur = GSTTIME_TO_QTTIME (qtdemux, duration);
3173
3174   if (movdur > qtdemux->duration) {
3175     prevdur = QTTIME_TO_GSTTIME (qtdemux, qtdemux->duration);
3176     GST_DEBUG_OBJECT (qtdemux,
3177         "Updating total duration to %" GST_TIME_FORMAT " was %" GST_TIME_FORMAT,
3178         GST_TIME_ARGS (duration), GST_TIME_ARGS (prevdur));
3179     qtdemux->duration = movdur;
3180     GST_DEBUG_OBJECT (qtdemux,
3181         "qtdemux->segment.duration: %" GST_TIME_FORMAT " .stop: %"
3182         GST_TIME_FORMAT, GST_TIME_ARGS (qtdemux->segment.duration),
3183         GST_TIME_ARGS (qtdemux->segment.stop));
3184     if (qtdemux->segment.duration == prevdur) {
3185       /* If the current segment has duration/stop identical to previous duration
3186        * update them also (because they were set at that point in time with
3187        * the wrong duration */
3188       /* We convert the value *from* the timescale version to avoid rounding errors */
3189       GstClockTime fixeddur = QTTIME_TO_GSTTIME (qtdemux, movdur);
3190       GST_DEBUG_OBJECT (qtdemux, "Updated segment.duration and segment.stop");
3191       qtdemux->segment.duration = fixeddur;
3192       qtdemux->segment.stop = fixeddur;
3193     }
3194   }
3195   for (iter = qtdemux->active_streams, i = 0; iter;
3196       iter = g_list_next (iter), i++) {
3197     QtDemuxStream *stream = QTDEMUX_STREAM (iter->data);
3198
3199     movdur = GSTTIME_TO_QTSTREAMTIME (stream, duration);
3200     if (movdur > stream->duration) {
3201       GST_DEBUG_OBJECT (qtdemux,
3202           "Updating stream #%d duration to %" GST_TIME_FORMAT, i,
3203           GST_TIME_ARGS (duration));
3204       stream->duration = movdur;
3205       /* internal duration tracking state has been updated above, so */
3206       /* preserve an open-ended dummy segment rather than repeatedly updating
3207        * it and spamming downstream accordingly with segment events */
3208       if (stream->dummy_segment &&
3209           GST_CLOCK_TIME_IS_VALID (stream->segments[0].duration)) {
3210         /* Update all dummy values to new duration */
3211         stream->segments[0].stop_time = duration;
3212         stream->segments[0].duration = duration;
3213         stream->segments[0].media_stop = duration;
3214
3215         /* let downstream know we possibly have a new stop time */
3216         if (stream->segment_index != -1) {
3217           GstClockTime pos;
3218
3219           if (qtdemux->segment.rate >= 0) {
3220             pos = stream->segment.start;
3221           } else {
3222             pos = stream->segment.stop;
3223           }
3224
3225           gst_qtdemux_stream_update_segment (qtdemux, stream,
3226               stream->segment_index, pos, NULL, NULL);
3227         }
3228       }
3229     }
3230   }
3231 }
3232
3233 static gboolean
3234 qtdemux_parse_trun (GstQTDemux * qtdemux, GstByteReader * trun,
3235     QtDemuxStream * stream, guint32 d_sample_duration, guint32 d_sample_size,
3236     guint32 d_sample_flags, gint64 moof_offset, gint64 moof_length,
3237     gint64 * base_offset, gint64 * running_offset, gint64 decode_ts,
3238     gboolean has_tfdt)
3239 {
3240   GstClockTime gst_ts = GST_CLOCK_TIME_NONE;
3241   guint64 timestamp;
3242   gint32 data_offset = 0;
3243   guint32 flags = 0, first_flags = 0, samples_count = 0;
3244   gint i;
3245   guint8 *data;
3246   guint entry_size, dur_offset, size_offset, flags_offset = 0, ct_offset = 0;
3247   QtDemuxSample *sample;
3248   gboolean ismv = FALSE;
3249   gint64 initial_offset;
3250
3251   GST_LOG_OBJECT (qtdemux, "parsing trun track-id %d; "
3252       "default dur %d, size %d, flags 0x%x, base offset %" G_GINT64_FORMAT ", "
3253       "decode ts %" G_GINT64_FORMAT, stream->track_id, d_sample_duration,
3254       d_sample_size, d_sample_flags, *base_offset, decode_ts);
3255
3256   if (stream->pending_seek && moof_offset < stream->pending_seek->moof_offset) {
3257     GST_INFO_OBJECT (stream->pad, "skipping trun before seek target fragment");
3258     return TRUE;
3259   }
3260
3261   /* presence of stss or not can't really tell us much,
3262    * and flags and so on tend to be marginally reliable in these files */
3263   if (stream->subtype == FOURCC_soun) {
3264     GST_DEBUG_OBJECT (qtdemux,
3265         "sound track in fragmented file; marking all keyframes");
3266     stream->all_keyframe = TRUE;
3267   }
3268
3269   if (!gst_byte_reader_skip (trun, 1) ||
3270       !gst_byte_reader_get_uint24_be (trun, &flags))
3271     goto fail;
3272
3273   if (!gst_byte_reader_get_uint32_be (trun, &samples_count))
3274     goto fail;
3275
3276   if (flags & TR_DATA_OFFSET) {
3277     /* note this is really signed */
3278     if (!gst_byte_reader_get_int32_be (trun, &data_offset))
3279       goto fail;
3280     GST_LOG_OBJECT (qtdemux, "trun data offset %d", data_offset);
3281     /* default base offset = first byte of moof */
3282     if (*base_offset == -1) {
3283       GST_LOG_OBJECT (qtdemux, "base_offset at moof");
3284       *base_offset = moof_offset;
3285     }
3286     *running_offset = *base_offset + data_offset;
3287   } else {
3288     /* if no offset at all, that would mean data starts at moof start,
3289      * which is a bit wrong and is ismv crappy way, so compensate
3290      * assuming data is in mdat following moof */
3291     if (*base_offset == -1) {
3292       *base_offset = moof_offset + moof_length + 8;
3293       GST_LOG_OBJECT (qtdemux, "base_offset assumed in mdat after moof");
3294       ismv = TRUE;
3295     }
3296     if (*running_offset == -1)
3297       *running_offset = *base_offset;
3298   }
3299
3300   GST_LOG_OBJECT (qtdemux, "running offset now %" G_GINT64_FORMAT,
3301       *running_offset);
3302   GST_LOG_OBJECT (qtdemux, "trun offset %d, flags 0x%x, entries %d",
3303       data_offset, flags, samples_count);
3304
3305   if (flags & TR_FIRST_SAMPLE_FLAGS) {
3306     if (G_UNLIKELY (flags & TR_SAMPLE_FLAGS)) {
3307       GST_DEBUG_OBJECT (qtdemux,
3308           "invalid flags; SAMPLE and FIRST_SAMPLE present, discarding latter");
3309       flags ^= TR_FIRST_SAMPLE_FLAGS;
3310     } else {
3311       if (!gst_byte_reader_get_uint32_be (trun, &first_flags))
3312         goto fail;
3313       GST_LOG_OBJECT (qtdemux, "first flags: 0x%x", first_flags);
3314     }
3315   }
3316
3317   /* FIXME ? spec says other bits should also be checked to determine
3318    * entry size (and prefix size for that matter) */
3319   entry_size = 0;
3320   dur_offset = size_offset = 0;
3321   if (flags & TR_SAMPLE_DURATION) {
3322     GST_LOG_OBJECT (qtdemux, "entry duration present");
3323     dur_offset = entry_size;
3324     entry_size += 4;
3325   }
3326   if (flags & TR_SAMPLE_SIZE) {
3327     GST_LOG_OBJECT (qtdemux, "entry size present");
3328     size_offset = entry_size;
3329     entry_size += 4;
3330   }
3331   if (flags & TR_SAMPLE_FLAGS) {
3332     GST_LOG_OBJECT (qtdemux, "entry flags present");
3333     flags_offset = entry_size;
3334     entry_size += 4;
3335   }
3336   if (flags & TR_COMPOSITION_TIME_OFFSETS) {
3337     GST_LOG_OBJECT (qtdemux, "entry ct offset present");
3338     ct_offset = entry_size;
3339     entry_size += 4;
3340   }
3341
3342   if (!qt_atom_parser_has_chunks (trun, samples_count, entry_size))
3343     goto fail;
3344   data = (guint8 *) gst_byte_reader_peek_data_unchecked (trun);
3345
3346   if (stream->n_samples + samples_count >=
3347       QTDEMUX_MAX_SAMPLE_INDEX_SIZE / sizeof (QtDemuxSample))
3348     goto index_too_big;
3349
3350   GST_DEBUG_OBJECT (qtdemux, "allocating n_samples %u * %u (%.2f MB)",
3351       stream->n_samples + samples_count, (guint) sizeof (QtDemuxSample),
3352       (stream->n_samples + samples_count) *
3353       sizeof (QtDemuxSample) / (1024.0 * 1024.0));
3354
3355   /* create a new array of samples if it's the first sample parsed */
3356   if (stream->n_samples == 0) {
3357     g_assert (stream->samples == NULL);
3358     stream->samples = g_try_new0 (QtDemuxSample, samples_count);
3359     /* or try to reallocate it with space enough to insert the new samples */
3360   } else
3361     stream->samples = g_try_renew (QtDemuxSample, stream->samples,
3362         stream->n_samples + samples_count);
3363   if (stream->samples == NULL)
3364     goto out_of_memory;
3365
3366   if (qtdemux->fragment_start != -1) {
3367     timestamp = GSTTIME_TO_QTSTREAMTIME (stream, qtdemux->fragment_start);
3368     qtdemux->fragment_start = -1;
3369   } else {
3370     if (stream->n_samples == 0) {
3371       if (decode_ts > 0) {
3372         timestamp = decode_ts;
3373       } else if (stream->pending_seek != NULL) {
3374         /* if we don't have a timestamp from a tfdt box, we'll use the one
3375          * from the mfra seek table */
3376         GST_INFO_OBJECT (stream->pad, "pending seek ts = %" GST_TIME_FORMAT,
3377             GST_TIME_ARGS (stream->pending_seek->ts));
3378
3379         /* FIXME: this is not fully correct, the timestamp refers to the random
3380          * access sample refered to in the tfra entry, which may not necessarily
3381          * be the first sample in the tfrag/trun (but hopefully/usually is) */
3382         timestamp = GSTTIME_TO_QTSTREAMTIME (stream, stream->pending_seek->ts);
3383       } else {
3384         timestamp = 0;
3385       }
3386
3387       gst_ts = QTSTREAMTIME_TO_GSTTIME (stream, timestamp);
3388       GST_INFO_OBJECT (stream->pad, "first sample ts %" GST_TIME_FORMAT,
3389           GST_TIME_ARGS (gst_ts));
3390     } else {
3391       /* subsequent fragments extend stream */
3392       timestamp =
3393           stream->samples[stream->n_samples - 1].timestamp +
3394           stream->samples[stream->n_samples - 1].duration;
3395
3396       /* If this is a GST_FORMAT_BYTES stream and there's a significant
3397        * difference (1 sec.) between decode_ts and timestamp, prefer the
3398        * former */
3399       if (has_tfdt && !qtdemux->upstream_format_is_time
3400           && ABSDIFF (decode_ts, timestamp) >
3401           MAX (stream->duration_last_moof / 2,
3402               GSTTIME_TO_QTSTREAMTIME (stream, GST_SECOND))) {
3403         GST_INFO_OBJECT (qtdemux,
3404             "decode_ts (%" GST_TIME_FORMAT ") and timestamp (%" GST_TIME_FORMAT
3405             ") are significantly different (more than %" GST_TIME_FORMAT
3406             "), using decode_ts",
3407             GST_TIME_ARGS (QTSTREAMTIME_TO_GSTTIME (stream, decode_ts)),
3408             GST_TIME_ARGS (QTSTREAMTIME_TO_GSTTIME (stream, timestamp)),
3409             GST_TIME_ARGS (QTSTREAMTIME_TO_GSTTIME (stream,
3410                     MAX (stream->duration_last_moof / 2,
3411                         GSTTIME_TO_QTSTREAMTIME (stream, GST_SECOND)))));
3412         timestamp = decode_ts;
3413       }
3414
3415       gst_ts = QTSTREAMTIME_TO_GSTTIME (stream, timestamp);
3416       GST_INFO_OBJECT (qtdemux, "first sample ts %" GST_TIME_FORMAT
3417           " (extends previous samples)", GST_TIME_ARGS (gst_ts));
3418     }
3419   }
3420
3421   initial_offset = *running_offset;
3422
3423   sample = stream->samples + stream->n_samples;
3424   for (i = 0; i < samples_count; i++) {
3425     guint32 dur, size, sflags, ct;
3426
3427     /* first read sample data */
3428     if (flags & TR_SAMPLE_DURATION) {
3429       dur = QT_UINT32 (data + dur_offset);
3430     } else {
3431       dur = d_sample_duration;
3432     }
3433     if (flags & TR_SAMPLE_SIZE) {
3434       size = QT_UINT32 (data + size_offset);
3435     } else {
3436       size = d_sample_size;
3437     }
3438     if (flags & TR_FIRST_SAMPLE_FLAGS) {
3439       if (i == 0) {
3440         sflags = first_flags;
3441       } else {
3442         sflags = d_sample_flags;
3443       }
3444     } else if (flags & TR_SAMPLE_FLAGS) {
3445       sflags = QT_UINT32 (data + flags_offset);
3446     } else {
3447       sflags = d_sample_flags;
3448     }
3449     if (flags & TR_COMPOSITION_TIME_OFFSETS) {
3450       ct = QT_UINT32 (data + ct_offset);
3451     } else {
3452       ct = 0;
3453     }
3454     data += entry_size;
3455
3456     /* fill the sample information */
3457     sample->offset = *running_offset;
3458     sample->pts_offset = ct;
3459     sample->size = size;
3460     sample->timestamp = timestamp;
3461     sample->duration = dur;
3462     /* sample-is-difference-sample */
3463     /* ismv seems to use 0x40 for keyframe, 0xc0 for non-keyframe,
3464      * now idea how it relates to bitfield other than massive LE/BE confusion */
3465     sample->keyframe = ismv ? ((sflags & 0xff) == 0x40) : !(sflags & 0x10000);
3466     *running_offset += size;
3467     timestamp += dur;
3468     stream->duration_moof += dur;
3469     sample++;
3470   }
3471
3472   /* Update total duration if needed */
3473   check_update_duration (qtdemux, QTSTREAMTIME_TO_GSTTIME (stream, timestamp));
3474
3475   /* Pre-emptively figure out size of mdat based on trun information.
3476    * If the [mdat] atom is effectivelly read, it will be replaced by the actual
3477    * size, else we will still be able to use this when dealing with gap'ed
3478    * input */
3479   qtdemux->mdatleft = *running_offset - initial_offset;
3480   qtdemux->mdatoffset = initial_offset;
3481   qtdemux->mdatsize = qtdemux->mdatleft;
3482
3483   stream->n_samples += samples_count;
3484   stream->n_samples_moof += samples_count;
3485
3486   if (stream->pending_seek != NULL)
3487     stream->pending_seek = NULL;
3488
3489   return TRUE;
3490
3491 fail:
3492   {
3493     GST_WARNING_OBJECT (qtdemux, "failed to parse trun");
3494     return FALSE;
3495   }
3496 out_of_memory:
3497   {
3498     GST_WARNING_OBJECT (qtdemux, "failed to allocate %d samples",
3499         stream->n_samples);
3500     return FALSE;
3501   }
3502 index_too_big:
3503   {
3504     GST_WARNING_OBJECT (qtdemux, "not allocating index of %d samples, would "
3505         "be larger than %uMB (broken file?)", stream->n_samples,
3506         QTDEMUX_MAX_SAMPLE_INDEX_SIZE >> 20);
3507     return FALSE;
3508   }
3509 }
3510
3511 /* find stream with @id */
3512 static inline QtDemuxStream *
3513 qtdemux_find_stream (GstQTDemux * qtdemux, guint32 id)
3514 {
3515   QtDemuxStream *stream;
3516   GList *iter;
3517
3518   /* check */
3519   if (G_UNLIKELY (!id)) {
3520     GST_DEBUG_OBJECT (qtdemux, "invalid track id 0");
3521     return NULL;
3522   }
3523
3524   for (iter = qtdemux->active_streams; iter; iter = g_list_next (iter)) {
3525     stream = QTDEMUX_STREAM (iter->data);
3526     if (stream->track_id == id)
3527       return stream;
3528   }
3529   if (qtdemux->mss_mode) {
3530     /* mss should have only 1 stream anyway */
3531     return QTDEMUX_FIRST_STREAM (qtdemux);
3532   }
3533
3534   return NULL;
3535 }
3536
3537 static gboolean
3538 qtdemux_parse_mfhd (GstQTDemux * qtdemux, GstByteReader * mfhd,
3539     guint32 * fragment_number)
3540 {
3541   if (!gst_byte_reader_skip (mfhd, 4))
3542     goto fail;
3543   if (!gst_byte_reader_get_uint32_be (mfhd, fragment_number))
3544     goto fail;
3545   return TRUE;
3546 fail:
3547   {
3548     GST_WARNING_OBJECT (qtdemux, "Failed to parse mfhd atom");
3549     return FALSE;
3550   }
3551 }
3552
3553 static gboolean
3554 qtdemux_parse_tfhd (GstQTDemux * qtdemux, GstByteReader * tfhd,
3555     QtDemuxStream ** stream, guint32 * default_sample_duration,
3556     guint32 * default_sample_size, guint32 * default_sample_flags,
3557     gint64 * base_offset)
3558 {
3559   guint32 flags = 0;
3560   guint32 track_id = 0;
3561
3562   if (!gst_byte_reader_skip (tfhd, 1) ||
3563       !gst_byte_reader_get_uint24_be (tfhd, &flags))
3564     goto invalid_track;
3565
3566   if (!gst_byte_reader_get_uint32_be (tfhd, &track_id))
3567     goto invalid_track;
3568
3569   *stream = qtdemux_find_stream (qtdemux, track_id);
3570   if (G_UNLIKELY (!*stream))
3571     goto unknown_stream;
3572
3573   if (flags & TF_DEFAULT_BASE_IS_MOOF)
3574     *base_offset = qtdemux->moof_offset;
3575
3576   if (flags & TF_BASE_DATA_OFFSET)
3577     if (!gst_byte_reader_get_uint64_be (tfhd, (guint64 *) base_offset))
3578       goto invalid_track;
3579
3580   /* obtain stream defaults */
3581   qtdemux_parse_trex (qtdemux, *stream,
3582       default_sample_duration, default_sample_size, default_sample_flags);
3583
3584   (*stream)->stsd_sample_description_id =
3585       (*stream)->def_sample_description_index - 1;
3586
3587   if (flags & TF_SAMPLE_DESCRIPTION_INDEX) {
3588     guint32 sample_description_index;
3589     if (!gst_byte_reader_get_uint32_be (tfhd, &sample_description_index))
3590       goto invalid_track;
3591     (*stream)->stsd_sample_description_id = sample_description_index - 1;
3592   }
3593
3594   if (qtdemux->mss_mode) {
3595     /* mss has no stsd entry */
3596     (*stream)->stsd_sample_description_id = 0;
3597   }
3598
3599   if (flags & TF_DEFAULT_SAMPLE_DURATION)
3600     if (!gst_byte_reader_get_uint32_be (tfhd, default_sample_duration))
3601       goto invalid_track;
3602
3603   if (flags & TF_DEFAULT_SAMPLE_SIZE)
3604     if (!gst_byte_reader_get_uint32_be (tfhd, default_sample_size))
3605       goto invalid_track;
3606
3607   if (flags & TF_DEFAULT_SAMPLE_FLAGS)
3608     if (!gst_byte_reader_get_uint32_be (tfhd, default_sample_flags))
3609       goto invalid_track;
3610
3611   return TRUE;
3612
3613 invalid_track:
3614   {
3615     GST_WARNING_OBJECT (qtdemux, "invalid track fragment header");
3616     return FALSE;
3617   }
3618 unknown_stream:
3619   {
3620     GST_DEBUG_OBJECT (qtdemux, "unknown stream in tfhd");
3621     return TRUE;
3622   }
3623 }
3624
3625 static gboolean
3626 qtdemux_parse_tfdt (GstQTDemux * qtdemux, GstByteReader * br,
3627     guint64 * decode_time)
3628 {
3629   guint32 version = 0;
3630
3631   if (!gst_byte_reader_get_uint32_be (br, &version))
3632     return FALSE;
3633
3634   version >>= 24;
3635   if (version == 1) {
3636     if (!gst_byte_reader_get_uint64_be (br, decode_time))
3637       goto failed;
3638   } else {
3639     guint32 dec_time = 0;
3640     if (!gst_byte_reader_get_uint32_be (br, &dec_time))
3641       goto failed;
3642     *decode_time = dec_time;
3643   }
3644
3645   GST_INFO_OBJECT (qtdemux, "Track fragment decode time: %" G_GUINT64_FORMAT,
3646       *decode_time);
3647
3648   return TRUE;
3649
3650 failed:
3651   {
3652     GST_DEBUG_OBJECT (qtdemux, "parsing tfdt failed");
3653     return FALSE;
3654   }
3655 }
3656
3657 /* Returns a pointer to a GstStructure containing the properties of
3658  * the stream sample identified by @sample_index. The caller must unref
3659  * the returned object after use. Returns NULL if unsuccessful. */
3660 static GstStructure *
3661 qtdemux_get_cenc_sample_properties (GstQTDemux * qtdemux,
3662     QtDemuxStream * stream, guint sample_index)
3663 {
3664   QtDemuxCencSampleSetInfo *info = NULL;
3665
3666   g_return_val_if_fail (stream != NULL, NULL);
3667   g_return_val_if_fail (stream->protected, NULL);
3668   g_return_val_if_fail (stream->protection_scheme_info != NULL, NULL);
3669
3670   info = (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
3671
3672   /* Currently, cenc properties for groups of samples are not supported, so
3673    * simply return a copy of the default sample properties */
3674   return gst_structure_copy (info->default_properties);
3675 }
3676
3677 /* Parses the sizes of sample auxiliary information contained within a stream,
3678  * as given in a saiz box. Returns array of sample_count guint8 size values,
3679  * or NULL on failure */
3680 static guint8 *
3681 qtdemux_parse_saiz (GstQTDemux * qtdemux, QtDemuxStream * stream,
3682     GstByteReader * br, guint32 * sample_count)
3683 {
3684   guint32 flags = 0;
3685   guint8 *info_sizes;
3686   guint8 default_info_size;
3687
3688   g_return_val_if_fail (qtdemux != NULL, NULL);
3689   g_return_val_if_fail (stream != NULL, NULL);
3690   g_return_val_if_fail (br != NULL, NULL);
3691   g_return_val_if_fail (sample_count != NULL, NULL);
3692
3693   if (!gst_byte_reader_get_uint32_be (br, &flags))
3694     return NULL;
3695
3696   if (flags & 0x1) {
3697     /* aux_info_type and aux_info_type_parameter are ignored */
3698     if (!gst_byte_reader_skip (br, 8))
3699       return NULL;
3700   }
3701
3702   if (!gst_byte_reader_get_uint8 (br, &default_info_size))
3703     return NULL;
3704   GST_DEBUG_OBJECT (qtdemux, "default_info_size: %u", default_info_size);
3705
3706   if (!gst_byte_reader_get_uint32_be (br, sample_count))
3707     return NULL;
3708   GST_DEBUG_OBJECT (qtdemux, "sample_count: %u", *sample_count);
3709
3710
3711   if (default_info_size == 0) {
3712     if (!gst_byte_reader_dup_data (br, *sample_count, &info_sizes)) {
3713       return NULL;
3714     }
3715   } else {
3716     info_sizes = g_new (guint8, *sample_count);
3717     memset (info_sizes, default_info_size, *sample_count);
3718   }
3719
3720   return info_sizes;
3721 }
3722
3723 /* Parses the offset of sample auxiliary information contained within a stream,
3724  * as given in a saio box. Returns TRUE if successful; FALSE otherwise. */
3725 static gboolean
3726 qtdemux_parse_saio (GstQTDemux * qtdemux, QtDemuxStream * stream,
3727     GstByteReader * br, guint32 * info_type, guint32 * info_type_parameter,
3728     guint64 * offset)
3729 {
3730   guint8 version = 0;
3731   guint32 flags = 0;
3732   guint32 aux_info_type = 0;
3733   guint32 aux_info_type_parameter = 0;
3734   guint32 entry_count;
3735   guint32 off_32;
3736   guint64 off_64;
3737   const guint8 *aux_info_type_data = NULL;
3738
3739   g_return_val_if_fail (qtdemux != NULL, FALSE);
3740   g_return_val_if_fail (stream != NULL, FALSE);
3741   g_return_val_if_fail (br != NULL, FALSE);
3742   g_return_val_if_fail (offset != NULL, FALSE);
3743
3744   if (!gst_byte_reader_get_uint8 (br, &version))
3745     return FALSE;
3746
3747   if (!gst_byte_reader_get_uint24_be (br, &flags))
3748     return FALSE;
3749
3750   if (flags & 0x1) {
3751
3752     if (!gst_byte_reader_get_data (br, 4, &aux_info_type_data))
3753       return FALSE;
3754     aux_info_type = QT_FOURCC (aux_info_type_data);
3755
3756     if (!gst_byte_reader_get_uint32_be (br, &aux_info_type_parameter))
3757       return FALSE;
3758   } else if (stream->protected) {
3759     aux_info_type = stream->protection_scheme_type;
3760   } else {
3761     aux_info_type = CUR_STREAM (stream)->fourcc;
3762   }
3763
3764   if (info_type)
3765     *info_type = aux_info_type;
3766   if (info_type_parameter)
3767     *info_type_parameter = aux_info_type_parameter;
3768
3769   GST_DEBUG_OBJECT (qtdemux, "aux_info_type: '%" GST_FOURCC_FORMAT "', "
3770       "aux_info_type_parameter:  %#06x",
3771       GST_FOURCC_ARGS (aux_info_type), aux_info_type_parameter);
3772
3773   if (!gst_byte_reader_get_uint32_be (br, &entry_count))
3774     return FALSE;
3775
3776   if (entry_count != 1) {
3777     GST_ERROR_OBJECT (qtdemux, "multiple offsets are not supported");
3778     return FALSE;
3779   }
3780
3781   if (version == 0) {
3782     if (!gst_byte_reader_get_uint32_be (br, &off_32))
3783       return FALSE;
3784     *offset = (guint64) off_32;
3785   } else {
3786     if (!gst_byte_reader_get_uint64_be (br, &off_64))
3787       return FALSE;
3788     *offset = off_64;
3789   }
3790
3791   GST_DEBUG_OBJECT (qtdemux, "offset: %" G_GUINT64_FORMAT, *offset);
3792   return TRUE;
3793 }
3794
3795 static void
3796 qtdemux_gst_structure_free (GstStructure * gststructure)
3797 {
3798   if (gststructure) {
3799     gst_structure_free (gststructure);
3800   }
3801 }
3802
3803 /* Parses auxiliary information relating to samples protected using Common
3804  * Encryption (cenc); the format of this information is defined in
3805  * ISO/IEC 23001-7. Returns TRUE if successful; FALSE otherwise. */
3806 static gboolean
3807 qtdemux_parse_cenc_aux_info (GstQTDemux * qtdemux, QtDemuxStream * stream,
3808     GstByteReader * br, guint8 * info_sizes, guint32 sample_count)
3809 {
3810   QtDemuxCencSampleSetInfo *ss_info = NULL;
3811   guint8 size;
3812   gint i;
3813   GPtrArray *old_crypto_info = NULL;
3814   guint old_entries = 0;
3815
3816   g_return_val_if_fail (qtdemux != NULL, FALSE);
3817   g_return_val_if_fail (stream != NULL, FALSE);
3818   g_return_val_if_fail (br != NULL, FALSE);
3819   g_return_val_if_fail (stream->protected, FALSE);
3820   g_return_val_if_fail (stream->protection_scheme_info != NULL, FALSE);
3821
3822   ss_info = (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
3823
3824   if (ss_info->crypto_info) {
3825     old_crypto_info = ss_info->crypto_info;
3826     /* Count number of non-null entries remaining at the tail end */
3827     for (i = old_crypto_info->len - 1; i >= 0; i--) {
3828       if (g_ptr_array_index (old_crypto_info, i) == NULL)
3829         break;
3830       old_entries++;
3831     }
3832   }
3833
3834   ss_info->crypto_info =
3835       g_ptr_array_new_full (sample_count + old_entries,
3836       (GDestroyNotify) qtdemux_gst_structure_free);
3837
3838   /* We preserve old entries because we parse the next moof in advance
3839    * of consuming all samples from the previous moof, and otherwise
3840    * we'd discard the corresponding crypto info for the samples
3841    * from the previous fragment. */
3842   if (old_entries) {
3843     GST_DEBUG_OBJECT (qtdemux, "Preserving %d old crypto info entries",
3844         old_entries);
3845     for (i = old_crypto_info->len - old_entries; i < old_crypto_info->len; i++) {
3846       g_ptr_array_add (ss_info->crypto_info, g_ptr_array_index (old_crypto_info,
3847               i));
3848       g_ptr_array_index (old_crypto_info, i) = NULL;
3849     }
3850   }
3851
3852   if (old_crypto_info) {
3853     /* Everything now belongs to the new array */
3854     g_ptr_array_free (old_crypto_info, TRUE);
3855   }
3856
3857   for (i = 0; i < sample_count; ++i) {
3858     GstStructure *properties;
3859     guint16 n_subsamples = 0;
3860     guint8 *data;
3861     guint iv_size;
3862     GstBuffer *buf;
3863
3864     properties = qtdemux_get_cenc_sample_properties (qtdemux, stream, i);
3865     if (properties == NULL) {
3866       GST_ERROR_OBJECT (qtdemux, "failed to get properties for sample %u", i);
3867       return FALSE;
3868     }
3869     if (!gst_structure_get_uint (properties, "iv_size", &iv_size)) {
3870       GST_ERROR_OBJECT (qtdemux, "failed to get iv_size for sample %u", i);
3871       gst_structure_free (properties);
3872       return FALSE;
3873     }
3874     if (!gst_byte_reader_dup_data (br, iv_size, &data)) {
3875       GST_ERROR_OBJECT (qtdemux, "failed to get IV for sample %u", i);
3876       gst_structure_free (properties);
3877       return FALSE;
3878     }
3879     buf = gst_buffer_new_wrapped (data, iv_size);
3880     gst_structure_set (properties, "iv", GST_TYPE_BUFFER, buf, NULL);
3881     gst_buffer_unref (buf);
3882     size = info_sizes[i];
3883     if (size > iv_size) {
3884       if (!gst_byte_reader_get_uint16_be (br, &n_subsamples)
3885           || !(n_subsamples > 0)) {
3886         gst_structure_free (properties);
3887         GST_ERROR_OBJECT (qtdemux,
3888             "failed to get subsample count for sample %u", i);
3889         return FALSE;
3890       }
3891       GST_LOG_OBJECT (qtdemux, "subsample count: %u", n_subsamples);
3892       if (!gst_byte_reader_dup_data (br, n_subsamples * 6, &data)) {
3893         GST_ERROR_OBJECT (qtdemux, "failed to get subsample data for sample %u",
3894             i);
3895         gst_structure_free (properties);
3896         return FALSE;
3897       }
3898       buf = gst_buffer_new_wrapped (data, n_subsamples * 6);
3899       if (!buf) {
3900         gst_structure_free (properties);
3901         return FALSE;
3902       }
3903       gst_structure_set (properties,
3904           "subsample_count", G_TYPE_UINT, n_subsamples,
3905           "subsamples", GST_TYPE_BUFFER, buf, NULL);
3906       gst_buffer_unref (buf);
3907     } else {
3908       gst_structure_set (properties, "subsample_count", G_TYPE_UINT, 0, NULL);
3909     }
3910     g_ptr_array_add (ss_info->crypto_info, properties);
3911   }
3912   return TRUE;
3913 }
3914
3915 /* Converts a UUID in raw byte form to a string representation, as defined in
3916  * RFC 4122. The caller takes ownership of the returned string and is
3917  * responsible for freeing it after use. */
3918 static gchar *
3919 qtdemux_uuid_bytes_to_string (gconstpointer uuid_bytes)
3920 {
3921   const guint8 *uuid = (const guint8 *) uuid_bytes;
3922
3923   return g_strdup_printf ("%02x%02x%02x%02x-%02x%02x-%02x%02x-"
3924       "%02x%02x-%02x%02x%02x%02x%02x%02x",
3925       uuid[0], uuid[1], uuid[2], uuid[3],
3926       uuid[4], uuid[5], uuid[6], uuid[7],
3927       uuid[8], uuid[9], uuid[10], uuid[11],
3928       uuid[12], uuid[13], uuid[14], uuid[15]);
3929 }
3930
3931 /* Parses a Protection System Specific Header box (pssh), as defined in the
3932  * Common Encryption (cenc) standard (ISO/IEC 23001-7), which contains
3933  * information needed by a specific content protection system in order to
3934  * decrypt cenc-protected tracks. Returns TRUE if successful; FALSE
3935  * otherwise. */
3936 static gboolean
3937 qtdemux_parse_pssh (GstQTDemux * qtdemux, GNode * node)
3938 {
3939   gchar *sysid_string;
3940   guint32 pssh_size = QT_UINT32 (node->data);
3941   GstBuffer *pssh = NULL;
3942   GstEvent *event = NULL;
3943   guint32 parent_box_type;
3944   GList *iter;
3945
3946   if (G_UNLIKELY (pssh_size < 32U)) {
3947     GST_ERROR_OBJECT (qtdemux, "invalid box size");
3948     return FALSE;
3949   }
3950
3951   sysid_string =
3952       qtdemux_uuid_bytes_to_string ((const guint8 *) node->data + 12);
3953
3954   gst_qtdemux_append_protection_system_id (qtdemux, sysid_string);
3955
3956   pssh = gst_buffer_new_wrapped (g_memdup (node->data, pssh_size), pssh_size);
3957   GST_LOG_OBJECT (qtdemux, "cenc pssh size: %" G_GSIZE_FORMAT,
3958       gst_buffer_get_size (pssh));
3959
3960   parent_box_type = QT_FOURCC ((const guint8 *) node->parent->data + 4);
3961
3962   /* Push an event containing the pssh box onto the queues of all streams. */
3963   event = gst_event_new_protection (sysid_string, pssh,
3964       (parent_box_type == FOURCC_moov) ? "isobmff/moov" : "isobmff/moof");
3965   for (iter = qtdemux->active_streams; iter; iter = g_list_next (iter)) {
3966     QtDemuxStream *stream = QTDEMUX_STREAM (iter->data);
3967     GST_TRACE_OBJECT (qtdemux,
3968         "adding protection event for stream %s and system %s",
3969         stream->stream_id, sysid_string);
3970     g_queue_push_tail (&stream->protection_scheme_event_queue,
3971         gst_event_ref (event));
3972   }
3973   g_free (sysid_string);
3974   gst_event_unref (event);
3975   gst_buffer_unref (pssh);
3976   return TRUE;
3977 }
3978
3979 static gboolean
3980 qtdemux_parse_moof (GstQTDemux * qtdemux, const guint8 * buffer, guint length,
3981     guint64 moof_offset, QtDemuxStream * stream)
3982 {
3983   GNode *moof_node, *traf_node, *tfhd_node, *trun_node, *tfdt_node, *mfhd_node;
3984   GNode *uuid_node;
3985   GstByteReader mfhd_data, trun_data, tfhd_data, tfdt_data;
3986   GNode *saiz_node, *saio_node, *pssh_node;
3987   GstByteReader saiz_data, saio_data;
3988   guint32 ds_size = 0, ds_duration = 0, ds_flags = 0;
3989   gint64 base_offset, running_offset;
3990   guint32 frag_num;
3991   GstClockTime min_dts = GST_CLOCK_TIME_NONE;
3992
3993   /* NOTE @stream ignored */
3994
3995   moof_node = g_node_new ((guint8 *) buffer);
3996   qtdemux_parse_node (qtdemux, moof_node, buffer, length);
3997   qtdemux_node_dump (qtdemux, moof_node);
3998
3999   /* Get fragment number from mfhd and check it's valid */
4000   mfhd_node =
4001       qtdemux_tree_get_child_by_type_full (moof_node, FOURCC_mfhd, &mfhd_data);
4002   if (mfhd_node == NULL)
4003     goto missing_mfhd;
4004   if (!qtdemux_parse_mfhd (qtdemux, &mfhd_data, &frag_num))
4005     goto fail;
4006   GST_DEBUG_OBJECT (qtdemux, "Fragment #%d", frag_num);
4007
4008   /* unknown base_offset to start with */
4009   base_offset = running_offset = -1;
4010   traf_node = qtdemux_tree_get_child_by_type (moof_node, FOURCC_traf);
4011   while (traf_node) {
4012     guint64 decode_time = 0;
4013
4014     /* Fragment Header node */
4015     tfhd_node =
4016         qtdemux_tree_get_child_by_type_full (traf_node, FOURCC_tfhd,
4017         &tfhd_data);
4018     if (!tfhd_node)
4019       goto missing_tfhd;
4020     if (!qtdemux_parse_tfhd (qtdemux, &tfhd_data, &stream, &ds_duration,
4021             &ds_size, &ds_flags, &base_offset))
4022       goto missing_tfhd;
4023
4024     /* The following code assumes at most a single set of sample auxiliary
4025      * data in the fragment (consisting of a saiz box and a corresponding saio
4026      * box); in theory, however, there could be multiple sets of sample
4027      * auxiliary data in a fragment. */
4028     saiz_node =
4029         qtdemux_tree_get_child_by_type_full (traf_node, FOURCC_saiz,
4030         &saiz_data);
4031     if (saiz_node) {
4032       guint32 info_type = 0;
4033       guint64 offset = 0;
4034       guint32 info_type_parameter = 0;
4035
4036       g_free (qtdemux->cenc_aux_info_sizes);
4037
4038       qtdemux->cenc_aux_info_sizes =
4039           qtdemux_parse_saiz (qtdemux, stream, &saiz_data,
4040           &qtdemux->cenc_aux_sample_count);
4041       if (qtdemux->cenc_aux_info_sizes == NULL) {
4042         GST_ERROR_OBJECT (qtdemux, "failed to parse saiz box");
4043         goto fail;
4044       }
4045       saio_node =
4046           qtdemux_tree_get_child_by_type_full (traf_node, FOURCC_saio,
4047           &saio_data);
4048       if (!saio_node) {
4049         GST_ERROR_OBJECT (qtdemux, "saiz box without a corresponding saio box");
4050         g_free (qtdemux->cenc_aux_info_sizes);
4051         qtdemux->cenc_aux_info_sizes = NULL;
4052         goto fail;
4053       }
4054
4055       if (G_UNLIKELY (!qtdemux_parse_saio (qtdemux, stream, &saio_data,
4056                   &info_type, &info_type_parameter, &offset))) {
4057         GST_ERROR_OBJECT (qtdemux, "failed to parse saio box");
4058         g_free (qtdemux->cenc_aux_info_sizes);
4059         qtdemux->cenc_aux_info_sizes = NULL;
4060         goto fail;
4061       }
4062       if (base_offset > -1 && base_offset > qtdemux->moof_offset)
4063         offset += (guint64) (base_offset - qtdemux->moof_offset);
4064       if (info_type == FOURCC_cenc && info_type_parameter == 0U) {
4065         GstByteReader br;
4066         if (offset > length) {
4067           GST_DEBUG_OBJECT (qtdemux, "cenc auxiliary info stored out of moof");
4068           qtdemux->cenc_aux_info_offset = offset;
4069         } else {
4070           gst_byte_reader_init (&br, buffer + offset, length - offset);
4071           if (!qtdemux_parse_cenc_aux_info (qtdemux, stream, &br,
4072                   qtdemux->cenc_aux_info_sizes,
4073                   qtdemux->cenc_aux_sample_count)) {
4074             GST_ERROR_OBJECT (qtdemux, "failed to parse cenc auxiliary info");
4075             g_free (qtdemux->cenc_aux_info_sizes);
4076             qtdemux->cenc_aux_info_sizes = NULL;
4077             goto fail;
4078           }
4079         }
4080       }
4081     }
4082
4083     tfdt_node =
4084         qtdemux_tree_get_child_by_type_full (traf_node, FOURCC_tfdt,
4085         &tfdt_data);
4086     if (tfdt_node) {
4087       /* We'll use decode_time to interpolate timestamps
4088        * in case the input timestamps are missing */
4089       qtdemux_parse_tfdt (qtdemux, &tfdt_data, &decode_time);
4090
4091       GST_DEBUG_OBJECT (qtdemux, "decode time %" G_GINT64_FORMAT
4092           " (%" GST_TIME_FORMAT ")", decode_time,
4093           GST_TIME_ARGS (stream ? QTSTREAMTIME_TO_GSTTIME (stream,
4094                   decode_time) : GST_CLOCK_TIME_NONE));
4095
4096       /* Discard the fragment buffer timestamp info to avoid using it.
4097        * Rely on tfdt instead as it is more accurate than the timestamp
4098        * that is fetched from a manifest/playlist and is usually
4099        * less accurate. */
4100       qtdemux->fragment_start = -1;
4101     }
4102
4103     if (G_UNLIKELY (!stream)) {
4104       /* we lost track of offset, we'll need to regain it,
4105        * but can delay complaining until later or avoid doing so altogether */
4106       base_offset = -2;
4107       goto next;
4108     }
4109     if (G_UNLIKELY (base_offset < -1))
4110       goto lost_offset;
4111
4112     min_dts = MIN (min_dts, QTSTREAMTIME_TO_GSTTIME (stream, decode_time));
4113
4114     if (!qtdemux->pullbased) {
4115       /* Sample tables can grow enough to be problematic if the system memory
4116        * is very low (e.g. embedded devices) and the videos very long
4117        * (~8 MiB/hour for 25-30 fps video + typical AAC audio frames).
4118        * Fortunately, we can easily discard them for each new fragment when
4119        * we know qtdemux will not receive seeks outside of the current fragment.
4120        * adaptivedemux honors this assumption.
4121        * This optimization is also useful for applications that use qtdemux as
4122        * a push-based simple demuxer, like Media Source Extensions. */
4123       gst_qtdemux_stream_flush_samples_data (stream);
4124     }
4125
4126     /* initialise moof sample data */
4127     stream->n_samples_moof = 0;
4128     stream->duration_last_moof = stream->duration_moof;
4129     stream->duration_moof = 0;
4130
4131     /* Track Run node */
4132     trun_node =
4133         qtdemux_tree_get_child_by_type_full (traf_node, FOURCC_trun,
4134         &trun_data);
4135     while (trun_node) {
4136       qtdemux_parse_trun (qtdemux, &trun_data, stream,
4137           ds_duration, ds_size, ds_flags, moof_offset, length, &base_offset,
4138           &running_offset, decode_time, (tfdt_node != NULL));
4139       /* iterate all siblings */
4140       trun_node = qtdemux_tree_get_sibling_by_type_full (trun_node, FOURCC_trun,
4141           &trun_data);
4142     }
4143
4144     uuid_node = qtdemux_tree_get_child_by_type (traf_node, FOURCC_uuid);
4145     if (uuid_node) {
4146       guint8 *uuid_buffer = (guint8 *) uuid_node->data;
4147       guint32 box_length = QT_UINT32 (uuid_buffer);
4148
4149       qtdemux_parse_uuid (qtdemux, uuid_buffer, box_length);
4150     }
4151
4152     /* if no new base_offset provided for next traf,
4153      * base is end of current traf */
4154     base_offset = running_offset;
4155     running_offset = -1;
4156
4157     if (stream->n_samples_moof && stream->duration_moof)
4158       stream->new_caps = TRUE;
4159
4160   next:
4161     /* iterate all siblings */
4162     traf_node = qtdemux_tree_get_sibling_by_type (traf_node, FOURCC_traf);
4163   }
4164
4165   /* parse any protection system info */
4166   pssh_node = qtdemux_tree_get_child_by_type (moof_node, FOURCC_pssh);
4167   while (pssh_node) {
4168     GST_LOG_OBJECT (qtdemux, "Parsing pssh box.");
4169     qtdemux_parse_pssh (qtdemux, pssh_node);
4170     pssh_node = qtdemux_tree_get_sibling_by_type (pssh_node, FOURCC_pssh);
4171   }
4172
4173   if (!qtdemux->upstream_format_is_time && !qtdemux->first_moof_already_parsed
4174       && !qtdemux->received_seek && GST_CLOCK_TIME_IS_VALID (min_dts)
4175       && min_dts != 0) {
4176     /* Unless the user has explictly requested another seek, perform an
4177      * internal seek to the time specified in the tfdt.
4178      *
4179      * This way if the user opens a file where the first tfdt is 1 hour
4180      * into the presentation, they will not have to wait 1 hour for run
4181      * time to catch up and actual playback to start. */
4182     GList *iter;
4183
4184     GST_DEBUG_OBJECT (qtdemux, "First fragment has a non-zero tfdt, "
4185         "performing an internal seek to %" GST_TIME_FORMAT,
4186         GST_TIME_ARGS (min_dts));
4187
4188     qtdemux->segment.start = min_dts;
4189     qtdemux->segment.time = qtdemux->segment.position = min_dts;
4190
4191     for (iter = qtdemux->active_streams; iter; iter = g_list_next (iter)) {
4192       QtDemuxStream *stream = QTDEMUX_STREAM (iter->data);
4193       stream->time_position = min_dts;
4194     }
4195
4196     /* Before this code was run a segment was already sent when the moov was
4197      * parsed... which is OK -- some apps (mostly tests) expect a segment to
4198      * be emitted after a moov, and we can emit a second segment anyway for
4199      * special cases like this. */
4200     qtdemux->need_segment = TRUE;
4201   }
4202
4203   qtdemux->first_moof_already_parsed = TRUE;
4204
4205   g_node_destroy (moof_node);
4206   return TRUE;
4207
4208 missing_tfhd:
4209   {
4210     GST_DEBUG_OBJECT (qtdemux, "missing tfhd box");
4211     goto fail;
4212   }
4213 missing_mfhd:
4214   {
4215     GST_DEBUG_OBJECT (qtdemux, "Missing mfhd box");
4216     goto fail;
4217   }
4218 lost_offset:
4219   {
4220     GST_DEBUG_OBJECT (qtdemux, "lost offset");
4221     goto fail;
4222   }
4223 fail:
4224   {
4225     g_node_destroy (moof_node);
4226     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
4227         (_("This file is corrupt and cannot be played.")), (NULL));
4228     return FALSE;
4229   }
4230 }
4231
4232 #if 0
4233 /* might be used if some day we actually use mfra & co
4234  * for random access to fragments,
4235  * but that will require quite some modifications and much less relying
4236  * on a sample array */
4237 #endif
4238
4239 static gboolean
4240 qtdemux_parse_tfra (GstQTDemux * qtdemux, GNode * tfra_node)
4241 {
4242   QtDemuxStream *stream;
4243   guint32 ver_flags, track_id, len, num_entries, i;
4244   guint value_size, traf_size, trun_size, sample_size;
4245   guint64 time = 0, moof_offset = 0;
4246 #if 0
4247   GstBuffer *buf = NULL;
4248   GstFlowReturn ret;
4249 #endif
4250   GstByteReader tfra;
4251
4252   gst_byte_reader_init (&tfra, tfra_node->data, QT_UINT32 (tfra_node->data));
4253
4254   if (!gst_byte_reader_skip (&tfra, 8))
4255     return FALSE;
4256
4257   if (!gst_byte_reader_get_uint32_be (&tfra, &ver_flags))
4258     return FALSE;
4259
4260   if (!gst_byte_reader_get_uint32_be (&tfra, &track_id)
4261       || !gst_byte_reader_get_uint32_be (&tfra, &len)
4262       || !gst_byte_reader_get_uint32_be (&tfra, &num_entries))
4263     return FALSE;
4264
4265   GST_DEBUG_OBJECT (qtdemux, "parsing tfra box for track id %u", track_id);
4266
4267   stream = qtdemux_find_stream (qtdemux, track_id);
4268   if (stream == NULL)
4269     goto unknown_trackid;
4270
4271   value_size = ((ver_flags >> 24) == 1) ? sizeof (guint64) : sizeof (guint32);
4272   sample_size = (len & 3) + 1;
4273   trun_size = ((len & 12) >> 2) + 1;
4274   traf_size = ((len & 48) >> 4) + 1;
4275
4276   GST_DEBUG_OBJECT (qtdemux, "%u entries, sizes: value %u, traf %u, trun %u, "
4277       "sample %u", num_entries, value_size, traf_size, trun_size, sample_size);
4278
4279   if (num_entries == 0)
4280     goto no_samples;
4281
4282   if (!qt_atom_parser_has_chunks (&tfra, num_entries,
4283           value_size + value_size + traf_size + trun_size + sample_size))
4284     goto corrupt_file;
4285
4286   g_free (stream->ra_entries);
4287   stream->ra_entries = g_new (QtDemuxRandomAccessEntry, num_entries);
4288   stream->n_ra_entries = num_entries;
4289
4290   for (i = 0; i < num_entries; i++) {
4291     qt_atom_parser_get_offset (&tfra, value_size, &time);
4292     qt_atom_parser_get_offset (&tfra, value_size, &moof_offset);
4293     qt_atom_parser_get_uint_with_size_unchecked (&tfra, traf_size);
4294     qt_atom_parser_get_uint_with_size_unchecked (&tfra, trun_size);
4295     qt_atom_parser_get_uint_with_size_unchecked (&tfra, sample_size);
4296
4297     time = QTSTREAMTIME_TO_GSTTIME (stream, time);
4298
4299     GST_LOG_OBJECT (qtdemux, "fragment time: %" GST_TIME_FORMAT ", "
4300         " moof_offset: %" G_GUINT64_FORMAT, GST_TIME_ARGS (time), moof_offset);
4301
4302     stream->ra_entries[i].ts = time;
4303     stream->ra_entries[i].moof_offset = moof_offset;
4304
4305     /* don't want to go through the entire file and read all moofs at startup */
4306 #if 0
4307     ret = gst_qtdemux_pull_atom (qtdemux, moof_offset, 0, &buf);
4308     if (ret != GST_FLOW_OK)
4309       goto corrupt_file;
4310     qtdemux_parse_moof (qtdemux, GST_BUFFER_DATA (buf), GST_BUFFER_SIZE (buf),
4311         moof_offset, stream);
4312     gst_buffer_unref (buf);
4313 #endif
4314   }
4315
4316   check_update_duration (qtdemux, time);
4317
4318   return TRUE;
4319
4320 /* ERRORS */
4321 unknown_trackid:
4322   {
4323     GST_WARNING_OBJECT (qtdemux, "Couldn't find stream for track %u", track_id);
4324     return FALSE;
4325   }
4326 corrupt_file:
4327   {
4328     GST_WARNING_OBJECT (qtdemux, "broken traf box, ignoring");
4329     return FALSE;
4330   }
4331 no_samples:
4332   {
4333     GST_WARNING_OBJECT (qtdemux, "stream has no samples");
4334     return FALSE;
4335   }
4336 }
4337
4338 static gboolean
4339 qtdemux_pull_mfro_mfra (GstQTDemux * qtdemux)
4340 {
4341   GstMapInfo mfro_map = GST_MAP_INFO_INIT;
4342   GstMapInfo mfra_map = GST_MAP_INFO_INIT;
4343   GstBuffer *mfro = NULL, *mfra = NULL;
4344   GstFlowReturn flow;
4345   gboolean ret = FALSE;
4346   GNode *mfra_node, *tfra_node;
4347   guint64 mfra_offset = 0;
4348   guint32 fourcc, mfra_size;
4349   gint64 len;
4350
4351   /* query upstream size in bytes */
4352   if (!gst_pad_peer_query_duration (qtdemux->sinkpad, GST_FORMAT_BYTES, &len))
4353     goto size_query_failed;
4354
4355   /* mfro box should be at the very end of the file */
4356   flow = gst_qtdemux_pull_atom (qtdemux, len - 16, 16, &mfro);
4357   if (flow != GST_FLOW_OK)
4358     goto exit;
4359
4360   gst_buffer_map (mfro, &mfro_map, GST_MAP_READ);
4361
4362   fourcc = QT_FOURCC (mfro_map.data + 4);
4363   if (fourcc != FOURCC_mfro)
4364     goto exit;
4365
4366   GST_INFO_OBJECT (qtdemux, "Found mfro box");
4367   if (mfro_map.size < 16)
4368     goto invalid_mfro_size;
4369
4370   mfra_size = QT_UINT32 (mfro_map.data + 12);
4371   if (mfra_size >= len)
4372     goto invalid_mfra_size;
4373
4374   mfra_offset = len - mfra_size;
4375
4376   GST_INFO_OBJECT (qtdemux, "mfra offset: %" G_GUINT64_FORMAT ", size %u",
4377       mfra_offset, mfra_size);
4378
4379   /* now get and parse mfra box */
4380   flow = gst_qtdemux_pull_atom (qtdemux, mfra_offset, mfra_size, &mfra);
4381   if (flow != GST_FLOW_OK)
4382     goto broken_file;
4383
4384   gst_buffer_map (mfra, &mfra_map, GST_MAP_READ);
4385
4386   mfra_node = g_node_new ((guint8 *) mfra_map.data);
4387   qtdemux_parse_node (qtdemux, mfra_node, mfra_map.data, mfra_map.size);
4388
4389   tfra_node = qtdemux_tree_get_child_by_type (mfra_node, FOURCC_tfra);
4390
4391   while (tfra_node) {
4392     qtdemux_parse_tfra (qtdemux, tfra_node);
4393     /* iterate all siblings */
4394     tfra_node = qtdemux_tree_get_sibling_by_type (tfra_node, FOURCC_tfra);
4395   }
4396   g_node_destroy (mfra_node);
4397
4398   GST_INFO_OBJECT (qtdemux, "parsed movie fragment random access box (mfra)");
4399   ret = TRUE;
4400
4401 exit:
4402
4403   if (mfro) {
4404     if (mfro_map.memory != NULL)
4405       gst_buffer_unmap (mfro, &mfro_map);
4406     gst_buffer_unref (mfro);
4407   }
4408   if (mfra) {
4409     if (mfra_map.memory != NULL)
4410       gst_buffer_unmap (mfra, &mfra_map);
4411     gst_buffer_unref (mfra);
4412   }
4413   return ret;
4414
4415 /* ERRORS */
4416 size_query_failed:
4417   {
4418     GST_WARNING_OBJECT (qtdemux, "could not query upstream size");
4419     goto exit;
4420   }
4421 invalid_mfro_size:
4422   {
4423     GST_WARNING_OBJECT (qtdemux, "mfro size is too small");
4424     goto exit;
4425   }
4426 invalid_mfra_size:
4427   {
4428     GST_WARNING_OBJECT (qtdemux, "mfra_size in mfro box is invalid");
4429     goto exit;
4430   }
4431 broken_file:
4432   {
4433     GST_WARNING_OBJECT (qtdemux, "bogus mfra offset or size, broken file");
4434     goto exit;
4435   }
4436 }
4437
4438 static guint64
4439 add_offset (guint64 offset, guint64 advance)
4440 {
4441   /* Avoid 64-bit overflow by clamping */
4442   if (offset > G_MAXUINT64 - advance)
4443     return G_MAXUINT64;
4444   return offset + advance;
4445 }
4446
4447 static GstFlowReturn
4448 gst_qtdemux_loop_state_header (GstQTDemux * qtdemux)
4449 {
4450   guint64 length = 0;
4451   guint32 fourcc = 0;
4452   GstBuffer *buf = NULL;
4453   GstFlowReturn ret = GST_FLOW_OK;
4454   guint64 cur_offset = qtdemux->offset;
4455   GstMapInfo map;
4456
4457   ret = gst_pad_pull_range (qtdemux->sinkpad, cur_offset, 16, &buf);
4458   if (G_UNLIKELY (ret != GST_FLOW_OK))
4459     goto beach;
4460   gst_buffer_map (buf, &map, GST_MAP_READ);
4461   if (G_LIKELY (map.size >= 8))
4462     extract_initial_length_and_fourcc (map.data, map.size, &length, &fourcc);
4463   gst_buffer_unmap (buf, &map);
4464   gst_buffer_unref (buf);
4465
4466   /* maybe we already got most we needed, so only consider this eof */
4467   if (G_UNLIKELY (length == 0)) {
4468     GST_ELEMENT_WARNING (qtdemux, STREAM, DEMUX,
4469         (_("Invalid atom size.")),
4470         ("Header atom '%" GST_FOURCC_FORMAT "' has empty length",
4471             GST_FOURCC_ARGS (fourcc)));
4472     ret = GST_FLOW_EOS;
4473     goto beach;
4474   }
4475
4476   switch (fourcc) {
4477     case FOURCC_moof:
4478       /* record for later parsing when needed */
4479       if (!qtdemux->moof_offset) {
4480         qtdemux->moof_offset = qtdemux->offset;
4481       }
4482       if (qtdemux_pull_mfro_mfra (qtdemux)) {
4483         /* FIXME */
4484       } else {
4485         qtdemux->offset += length;      /* skip moof and keep going */
4486       }
4487       if (qtdemux->got_moov) {
4488         GST_INFO_OBJECT (qtdemux, "moof header, got moov, done with headers");
4489         ret = GST_FLOW_EOS;
4490         goto beach;
4491       }
4492       break;
4493     case FOURCC_mdat:
4494     case FOURCC_free:
4495     case FOURCC_skip:
4496     case FOURCC_wide:
4497     case FOURCC_PICT:
4498     case FOURCC_pnot:
4499     {
4500       GST_LOG_OBJECT (qtdemux,
4501           "skipping atom '%" GST_FOURCC_FORMAT "' at %" G_GUINT64_FORMAT,
4502           GST_FOURCC_ARGS (fourcc), cur_offset);
4503       qtdemux->offset = add_offset (qtdemux->offset, length);
4504       break;
4505     }
4506     case FOURCC_moov:
4507     {
4508       GstBuffer *moov = NULL;
4509
4510       if (qtdemux->got_moov) {
4511         GST_DEBUG_OBJECT (qtdemux, "Skipping moov atom as we have one already");
4512         qtdemux->offset = add_offset (qtdemux->offset, length);
4513         goto beach;
4514       }
4515
4516       ret = gst_pad_pull_range (qtdemux->sinkpad, cur_offset, length, &moov);
4517       if (ret != GST_FLOW_OK)
4518         goto beach;
4519       gst_buffer_map (moov, &map, GST_MAP_READ);
4520
4521       if (length != map.size) {
4522         /* Some files have a 'moov' atom at the end of the file which contains
4523          * a terminal 'free' atom where the body of the atom is missing.
4524          * Check for, and permit, this special case.
4525          */
4526         if (map.size >= 8) {
4527           guint8 *final_data = map.data + (map.size - 8);
4528           guint32 final_length = QT_UINT32 (final_data);
4529           guint32 final_fourcc = QT_FOURCC (final_data + 4);
4530
4531           if (final_fourcc == FOURCC_free
4532               && map.size + final_length - 8 == length) {
4533             /* Ok, we've found that special case. Allocate a new buffer with
4534              * that free atom actually present. */
4535             GstBuffer *newmoov = gst_buffer_new_and_alloc (length);
4536             gst_buffer_fill (newmoov, 0, map.data, map.size);
4537             gst_buffer_memset (newmoov, map.size, 0, final_length - 8);
4538             gst_buffer_unmap (moov, &map);
4539             gst_buffer_unref (moov);
4540             moov = newmoov;
4541             gst_buffer_map (moov, &map, GST_MAP_READ);
4542           }
4543         }
4544       }
4545
4546       if (length != map.size) {
4547         GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
4548             (_("This file is incomplete and cannot be played.")),
4549             ("We got less than expected (received %" G_GSIZE_FORMAT
4550                 ", wanted %u, offset %" G_GUINT64_FORMAT ")", map.size,
4551                 (guint) length, cur_offset));
4552         gst_buffer_unmap (moov, &map);
4553         gst_buffer_unref (moov);
4554         ret = GST_FLOW_ERROR;
4555         goto beach;
4556       }
4557       qtdemux->offset += length;
4558
4559       qtdemux_parse_moov (qtdemux, map.data, length);
4560       qtdemux_node_dump (qtdemux, qtdemux->moov_node);
4561
4562       qtdemux_parse_tree (qtdemux);
4563       if (qtdemux->moov_node_compressed) {
4564         g_node_destroy (qtdemux->moov_node_compressed);
4565         g_free (qtdemux->moov_node->data);
4566       }
4567       qtdemux->moov_node_compressed = NULL;
4568       g_node_destroy (qtdemux->moov_node);
4569       qtdemux->moov_node = NULL;
4570       gst_buffer_unmap (moov, &map);
4571       gst_buffer_unref (moov);
4572       qtdemux->got_moov = TRUE;
4573
4574       break;
4575     }
4576     case FOURCC_ftyp:
4577     {
4578       GstBuffer *ftyp = NULL;
4579
4580       /* extract major brand; might come in handy for ISO vs QT issues */
4581       ret = gst_qtdemux_pull_atom (qtdemux, cur_offset, length, &ftyp);
4582       if (ret != GST_FLOW_OK)
4583         goto beach;
4584       qtdemux->offset += length;
4585       gst_buffer_map (ftyp, &map, GST_MAP_READ);
4586       qtdemux_parse_ftyp (qtdemux, map.data, map.size);
4587       gst_buffer_unmap (ftyp, &map);
4588       gst_buffer_unref (ftyp);
4589       break;
4590     }
4591     case FOURCC_uuid:
4592     {
4593       GstBuffer *uuid = NULL;
4594
4595       /* uuid are extension atoms */
4596       ret = gst_qtdemux_pull_atom (qtdemux, cur_offset, length, &uuid);
4597       if (ret != GST_FLOW_OK)
4598         goto beach;
4599       qtdemux->offset += length;
4600       gst_buffer_map (uuid, &map, GST_MAP_READ);
4601       qtdemux_parse_uuid (qtdemux, map.data, map.size);
4602       gst_buffer_unmap (uuid, &map);
4603       gst_buffer_unref (uuid);
4604       break;
4605     }
4606     case FOURCC_sidx:
4607     {
4608       GstBuffer *sidx = NULL;
4609       ret = gst_qtdemux_pull_atom (qtdemux, cur_offset, length, &sidx);
4610       if (ret != GST_FLOW_OK)
4611         goto beach;
4612       qtdemux->offset += length;
4613       gst_buffer_map (sidx, &map, GST_MAP_READ);
4614       qtdemux_parse_sidx (qtdemux, map.data, map.size);
4615       gst_buffer_unmap (sidx, &map);
4616       gst_buffer_unref (sidx);
4617       break;
4618     }
4619     default:
4620     {
4621       GstBuffer *unknown = NULL;
4622
4623       GST_LOG_OBJECT (qtdemux,
4624           "unknown %08x '%" GST_FOURCC_FORMAT "' of size %" G_GUINT64_FORMAT
4625           " at %" G_GUINT64_FORMAT, fourcc, GST_FOURCC_ARGS (fourcc), length,
4626           cur_offset);
4627       ret = gst_qtdemux_pull_atom (qtdemux, cur_offset, length, &unknown);
4628       if (ret != GST_FLOW_OK)
4629         goto beach;
4630       gst_buffer_map (unknown, &map, GST_MAP_READ);
4631       GST_MEMDUMP ("Unknown tag", map.data, map.size);
4632       gst_buffer_unmap (unknown, &map);
4633       gst_buffer_unref (unknown);
4634       qtdemux->offset += length;
4635       break;
4636     }
4637   }
4638
4639 beach:
4640   if (ret == GST_FLOW_EOS && (qtdemux->got_moov || qtdemux->media_caps)) {
4641     /* digested all data, show what we have */
4642     qtdemux_prepare_streams (qtdemux);
4643     QTDEMUX_EXPOSE_LOCK (qtdemux);
4644     ret = qtdemux_expose_streams (qtdemux);
4645     QTDEMUX_EXPOSE_UNLOCK (qtdemux);
4646
4647     qtdemux->state = QTDEMUX_STATE_MOVIE;
4648     GST_DEBUG_OBJECT (qtdemux, "switching state to STATE_MOVIE (%d)",
4649         qtdemux->state);
4650     return ret;
4651   }
4652   return ret;
4653 }
4654
4655 /* Seeks to the previous keyframe of the indexed stream and
4656  * aligns other streams with respect to the keyframe timestamp
4657  * of indexed stream. Only called in case of Reverse Playback
4658  */
4659 static GstFlowReturn
4660 gst_qtdemux_seek_to_previous_keyframe (GstQTDemux * qtdemux)
4661 {
4662   guint32 seg_idx = 0, k_index = 0;
4663   guint32 ref_seg_idx, ref_k_index;
4664   GstClockTime k_pos = 0, last_stop = 0;
4665   QtDemuxSegment *seg = NULL;
4666   QtDemuxStream *ref_str = NULL;
4667   guint64 seg_media_start_mov;  /* segment media start time in mov format */
4668   guint64 target_ts;
4669   GList *iter;
4670
4671   /* Now we choose an arbitrary stream, get the previous keyframe timestamp
4672    * and finally align all the other streams on that timestamp with their
4673    * respective keyframes */
4674   for (iter = qtdemux->active_streams; iter; iter = g_list_next (iter)) {
4675     QtDemuxStream *str = QTDEMUX_STREAM (iter->data);
4676
4677     /* No candidate yet, take the first stream */
4678     if (!ref_str) {
4679       ref_str = str;
4680       continue;
4681     }
4682
4683     /* So that stream has a segment, we prefer video streams */
4684     if (str->subtype == FOURCC_vide) {
4685       ref_str = str;
4686       break;
4687     }
4688   }
4689
4690   if (G_UNLIKELY (!ref_str)) {
4691     GST_DEBUG_OBJECT (qtdemux, "couldn't find any stream");
4692     goto eos;
4693   }
4694
4695   if (G_UNLIKELY (!ref_str->from_sample)) {
4696     GST_DEBUG_OBJECT (qtdemux, "reached the beginning of the file");
4697     goto eos;
4698   }
4699
4700   /* So that stream has been playing from from_sample to to_sample. We will
4701    * get the timestamp of the previous sample and search for a keyframe before
4702    * that. For audio streams we do an arbitrary jump in the past (10 samples) */
4703   if (ref_str->subtype == FOURCC_vide) {
4704     k_index = gst_qtdemux_find_keyframe (qtdemux, ref_str,
4705         ref_str->from_sample - 1, FALSE);
4706   } else {
4707     if (ref_str->from_sample >= 10)
4708       k_index = ref_str->from_sample - 10;
4709     else
4710       k_index = 0;
4711   }
4712
4713   target_ts =
4714       ref_str->samples[k_index].timestamp +
4715       ref_str->samples[k_index].pts_offset;
4716
4717   /* get current segment for that stream */
4718   seg = &ref_str->segments[ref_str->segment_index];
4719   /* Use segment start in original timescale for comparisons */
4720   seg_media_start_mov = seg->trak_media_start;
4721
4722   GST_LOG_OBJECT (qtdemux, "keyframe index %u ts %" G_GUINT64_FORMAT
4723       " seg start %" G_GUINT64_FORMAT " %" GST_TIME_FORMAT "\n",
4724       k_index, target_ts, seg_media_start_mov,
4725       GST_TIME_ARGS (seg->media_start));
4726
4727   /* Crawl back through segments to find the one containing this I frame */
4728   while (target_ts < seg_media_start_mov) {
4729     GST_DEBUG_OBJECT (qtdemux,
4730         "keyframe position (sample %u) is out of segment %u " " target %"
4731         G_GUINT64_FORMAT " seg start %" G_GUINT64_FORMAT, k_index,
4732         ref_str->segment_index, target_ts, seg_media_start_mov);
4733
4734     if (G_UNLIKELY (!ref_str->segment_index)) {
4735       /* Reached first segment, let's consider it's EOS */
4736       goto eos;
4737     }
4738     ref_str->segment_index--;
4739     seg = &ref_str->segments[ref_str->segment_index];
4740     /* Use segment start in original timescale for comparisons */
4741     seg_media_start_mov = seg->trak_media_start;
4742   }
4743   /* Calculate time position of the keyframe and where we should stop */
4744   k_pos =
4745       QTSTREAMTIME_TO_GSTTIME (ref_str,
4746       target_ts - seg->trak_media_start) + seg->time;
4747   last_stop =
4748       QTSTREAMTIME_TO_GSTTIME (ref_str,
4749       ref_str->samples[ref_str->from_sample].timestamp -
4750       seg->trak_media_start) + seg->time;
4751
4752   GST_DEBUG_OBJECT (qtdemux, "preferred stream played from sample %u, "
4753       "now going to sample %u (pts %" GST_TIME_FORMAT ")", ref_str->from_sample,
4754       k_index, GST_TIME_ARGS (k_pos));
4755
4756   /* Set last_stop with the keyframe timestamp we pushed of that stream */
4757   qtdemux->segment.position = last_stop;
4758   GST_DEBUG_OBJECT (qtdemux, "last_stop now is %" GST_TIME_FORMAT,
4759       GST_TIME_ARGS (last_stop));
4760
4761   if (G_UNLIKELY (last_stop < qtdemux->segment.start)) {
4762     GST_DEBUG_OBJECT (qtdemux, "reached the beginning of segment");
4763     goto eos;
4764   }
4765
4766   ref_seg_idx = ref_str->segment_index;
4767   ref_k_index = k_index;
4768
4769   /* Align them all on this */
4770   for (iter = qtdemux->active_streams; iter; iter = g_list_next (iter)) {
4771     guint32 index = 0;
4772     GstClockTime seg_time = 0;
4773     QtDemuxStream *str = QTDEMUX_STREAM (iter->data);
4774
4775     /* aligning reference stream again might lead to backing up to yet another
4776      * keyframe (due to timestamp rounding issues),
4777      * potentially putting more load on downstream; so let's try to avoid */
4778     if (str == ref_str) {
4779       seg_idx = ref_seg_idx;
4780       seg = &str->segments[seg_idx];
4781       k_index = ref_k_index;
4782       GST_DEBUG_OBJECT (qtdemux, "reference track-id %u segment %d, "
4783           "sample at index %d", str->track_id, ref_str->segment_index, k_index);
4784     } else {
4785       seg_idx = gst_qtdemux_find_segment (qtdemux, str, k_pos);
4786       GST_DEBUG_OBJECT (qtdemux,
4787           "track-id %u align segment %d for keyframe pos %" GST_TIME_FORMAT,
4788           str->track_id, seg_idx, GST_TIME_ARGS (k_pos));
4789
4790       /* get segment and time in the segment */
4791       seg = &str->segments[seg_idx];
4792       seg_time = k_pos - seg->time;
4793
4794       /* get the media time in the segment.
4795        * No adjustment for empty "filler" segments */
4796       if (seg->media_start != GST_CLOCK_TIME_NONE)
4797         seg_time += seg->media_start;
4798
4799       /* get the index of the sample with media time */
4800       index = gst_qtdemux_find_index_linear (qtdemux, str, seg_time);
4801       GST_DEBUG_OBJECT (qtdemux,
4802           "track-id %u sample for %" GST_TIME_FORMAT " at %u", str->track_id,
4803           GST_TIME_ARGS (seg_time), index);
4804
4805       /* find previous keyframe */
4806       k_index = gst_qtdemux_find_keyframe (qtdemux, str, index, FALSE);
4807     }
4808
4809     /* Remember until where we want to go */
4810     str->to_sample = str->from_sample - 1;
4811     /* Define our time position */
4812     target_ts =
4813         str->samples[k_index].timestamp + str->samples[k_index].pts_offset;
4814     str->time_position = QTSTREAMTIME_TO_GSTTIME (str, target_ts) + seg->time;
4815     if (seg->media_start != GST_CLOCK_TIME_NONE)
4816       str->time_position -= seg->media_start;
4817
4818     /* Now seek back in time */
4819     gst_qtdemux_move_stream (qtdemux, str, k_index);
4820     GST_DEBUG_OBJECT (qtdemux, "track-id %u keyframe at %u, time position %"
4821         GST_TIME_FORMAT " playing from sample %u to %u", str->track_id, k_index,
4822         GST_TIME_ARGS (str->time_position), str->from_sample, str->to_sample);
4823   }
4824
4825   return GST_FLOW_OK;
4826
4827 eos:
4828   return GST_FLOW_EOS;
4829 }
4830
4831 /*
4832  * Gets the current qt segment start, stop and position for the
4833  * given time offset. This is used in update_segment()
4834  */
4835 static void
4836 gst_qtdemux_stream_segment_get_boundaries (GstQTDemux * qtdemux,
4837     QtDemuxStream * stream, GstClockTime offset,
4838     GstClockTime * _start, GstClockTime * _stop, GstClockTime * _time)
4839 {
4840   GstClockTime seg_time;
4841   GstClockTime start, stop, time;
4842   QtDemuxSegment *segment;
4843
4844   segment = &stream->segments[stream->segment_index];
4845
4846   /* get time in this segment */
4847   seg_time = (offset - segment->time) * segment->rate;
4848
4849   GST_LOG_OBJECT (stream->pad, "seg_time %" GST_TIME_FORMAT,
4850       GST_TIME_ARGS (seg_time));
4851
4852   if (G_UNLIKELY (seg_time > segment->duration)) {
4853     GST_LOG_OBJECT (stream->pad,
4854         "seg_time > segment->duration %" GST_TIME_FORMAT,
4855         GST_TIME_ARGS (segment->duration));
4856     seg_time = segment->duration;
4857   }
4858
4859   /* qtdemux->segment.stop is in outside-time-realm, whereas
4860    * segment->media_stop is in track-time-realm.
4861    *
4862    * In order to compare the two, we need to bring segment.stop
4863    * into the track-time-realm
4864    *
4865    * FIXME - does this comment still hold? Don't see any conversion here */
4866
4867   stop = qtdemux->segment.stop;
4868   if (stop == GST_CLOCK_TIME_NONE)
4869     stop = qtdemux->segment.duration;
4870   if (stop == GST_CLOCK_TIME_NONE)
4871     stop = segment->media_stop;
4872   else
4873     stop =
4874         MIN (segment->media_stop, stop - segment->time + segment->media_start);
4875
4876   if (G_UNLIKELY (QTSEGMENT_IS_EMPTY (segment))) {
4877     start = segment->time + seg_time;
4878     time = offset;
4879     stop = start - seg_time + segment->duration;
4880   } else if (qtdemux->segment.rate >= 0) {
4881     start = MIN (segment->media_start + seg_time, stop);
4882     time = offset;
4883   } else {
4884     if (segment->media_start >= qtdemux->segment.start) {
4885       time = segment->time;
4886     } else {
4887       time = segment->time + (qtdemux->segment.start - segment->media_start);
4888     }
4889
4890     start = MAX (segment->media_start, qtdemux->segment.start);
4891     stop = MIN (segment->media_start + seg_time, stop);
4892   }
4893
4894   *_start = start;
4895   *_stop = stop;
4896   *_time = time;
4897 }
4898
4899 /*
4900  * Updates the qt segment used for the stream and pushes a new segment event
4901  * downstream on this stream's pad.
4902  */
4903 static gboolean
4904 gst_qtdemux_stream_update_segment (GstQTDemux * qtdemux, QtDemuxStream * stream,
4905     gint seg_idx, GstClockTime offset, GstClockTime * _start,
4906     GstClockTime * _stop)
4907 {
4908   QtDemuxSegment *segment;
4909   GstClockTime start = 0, stop = GST_CLOCK_TIME_NONE, time = 0;
4910   gdouble rate;
4911   GstEvent *event;
4912
4913   /* update the current segment */
4914   stream->segment_index = seg_idx;
4915
4916   /* get the segment */
4917   segment = &stream->segments[seg_idx];
4918
4919   if (G_UNLIKELY (offset < segment->time)) {
4920     GST_WARNING_OBJECT (stream->pad, "offset < segment->time %" GST_TIME_FORMAT,
4921         GST_TIME_ARGS (segment->time));
4922     return FALSE;
4923   }
4924
4925   /* segment lies beyond total indicated duration */
4926   if (G_UNLIKELY (qtdemux->segment.duration != GST_CLOCK_TIME_NONE &&
4927           segment->time > qtdemux->segment.duration)) {
4928     GST_WARNING_OBJECT (stream->pad, "file duration %" GST_TIME_FORMAT
4929         " < segment->time %" GST_TIME_FORMAT,
4930         GST_TIME_ARGS (qtdemux->segment.duration),
4931         GST_TIME_ARGS (segment->time));
4932     return FALSE;
4933   }
4934
4935   gst_qtdemux_stream_segment_get_boundaries (qtdemux, stream, offset,
4936       &start, &stop, &time);
4937
4938   GST_DEBUG_OBJECT (stream->pad, "new segment %d from %" GST_TIME_FORMAT
4939       " to %" GST_TIME_FORMAT ", time %" GST_TIME_FORMAT, seg_idx,
4940       GST_TIME_ARGS (start), GST_TIME_ARGS (stop), GST_TIME_ARGS (time));
4941
4942   /* combine global rate with that of the segment */
4943   rate = segment->rate * qtdemux->segment.rate;
4944
4945   /* Copy flags from main segment */
4946   stream->segment.flags = qtdemux->segment.flags;
4947
4948   /* update the segment values used for clipping */
4949   stream->segment.offset = qtdemux->segment.offset;
4950   stream->segment.base = qtdemux->segment.base + stream->accumulated_base;
4951   stream->segment.applied_rate = qtdemux->segment.applied_rate;
4952   stream->segment.rate = rate;
4953   stream->segment.start = start + QTSTREAMTIME_TO_GSTTIME (stream,
4954       stream->cslg_shift);
4955   stream->segment.stop = stop + QTSTREAMTIME_TO_GSTTIME (stream,
4956       stream->cslg_shift);
4957   stream->segment.time = time;
4958   stream->segment.position = stream->segment.start;
4959
4960   GST_DEBUG_OBJECT (stream->pad, "New segment: %" GST_SEGMENT_FORMAT,
4961       &stream->segment);
4962
4963   /* now prepare and send the segment */
4964   if (stream->pad) {
4965     event = gst_event_new_segment (&stream->segment);
4966     if (qtdemux->segment_seqnum != GST_SEQNUM_INVALID) {
4967       gst_event_set_seqnum (event, qtdemux->segment_seqnum);
4968     }
4969     gst_pad_push_event (stream->pad, event);
4970     /* assume we can send more data now */
4971     GST_PAD_LAST_FLOW_RETURN (stream->pad) = GST_FLOW_OK;
4972     /* clear to send tags on this pad now */
4973     gst_qtdemux_push_tags (qtdemux, stream);
4974   }
4975
4976   if (_start)
4977     *_start = start;
4978   if (_stop)
4979     *_stop = stop;
4980
4981   return TRUE;
4982 }
4983
4984 /* activate the given segment number @seg_idx of @stream at time @offset.
4985  * @offset is an absolute global position over all the segments.
4986  *
4987  * This will push out a NEWSEGMENT event with the right values and
4988  * position the stream index to the first decodable sample before
4989  * @offset.
4990  */
4991 static gboolean
4992 gst_qtdemux_activate_segment (GstQTDemux * qtdemux, QtDemuxStream * stream,
4993     guint32 seg_idx, GstClockTime offset)
4994 {
4995   QtDemuxSegment *segment;
4996   guint32 index, kf_index;
4997   GstClockTime start = 0, stop = GST_CLOCK_TIME_NONE;
4998
4999   GST_LOG_OBJECT (stream->pad, "activate segment %d, offset %" GST_TIME_FORMAT,
5000       seg_idx, GST_TIME_ARGS (offset));
5001
5002   if (!gst_qtdemux_stream_update_segment (qtdemux, stream, seg_idx, offset,
5003           &start, &stop))
5004     return FALSE;
5005
5006   segment = &stream->segments[stream->segment_index];
5007
5008   /* in the fragmented case, we pick a fragment that starts before our
5009    * desired position and rely on downstream to wait for a keyframe
5010    * (FIXME: doesn't seem to work so well with ismv and wmv, as no parser; the
5011    * tfra entries tells us which trun/sample the key unit is in, but we don't
5012    * make use of this additional information at the moment) */
5013   if (qtdemux->fragmented && !qtdemux->fragmented_seek_pending) {
5014     stream->to_sample = G_MAXUINT32;
5015     return TRUE;
5016   } else {
5017     /* well, it will be taken care of below */
5018     qtdemux->fragmented_seek_pending = FALSE;
5019     /* FIXME ideally the do_fragmented_seek can be done right here,
5020      * rather than at loop level
5021      * (which might even allow handling edit lists in a fragmented file) */
5022   }
5023
5024   /* We don't need to look for a sample in push-based */
5025   if (!qtdemux->pullbased)
5026     return TRUE;
5027
5028   /* and move to the keyframe before the indicated media time of the
5029    * segment */
5030   if (G_LIKELY (!QTSEGMENT_IS_EMPTY (segment))) {
5031     if (qtdemux->segment.rate >= 0) {
5032       index = gst_qtdemux_find_index_linear (qtdemux, stream, start);
5033       stream->to_sample = G_MAXUINT32;
5034       GST_DEBUG_OBJECT (stream->pad,
5035           "moving data pointer to %" GST_TIME_FORMAT ", index: %u, pts %"
5036           GST_TIME_FORMAT, GST_TIME_ARGS (start), index,
5037           GST_TIME_ARGS (QTSAMPLE_PTS (stream, &stream->samples[index])));
5038     } else {
5039       index = gst_qtdemux_find_index_linear (qtdemux, stream, stop);
5040       stream->to_sample = index;
5041       GST_DEBUG_OBJECT (stream->pad,
5042           "moving data pointer to %" GST_TIME_FORMAT ", index: %u, pts %"
5043           GST_TIME_FORMAT, GST_TIME_ARGS (stop), index,
5044           GST_TIME_ARGS (QTSAMPLE_PTS (stream, &stream->samples[index])));
5045     }
5046   } else {
5047     GST_DEBUG_OBJECT (stream->pad, "No need to look for keyframe, "
5048         "this is an empty segment");
5049     return TRUE;
5050   }
5051
5052   /* gst_qtdemux_parse_sample () called from gst_qtdemux_find_index_linear ()
5053    * encountered an error and printed a message so we return appropriately */
5054   if (index == -1)
5055     return FALSE;
5056
5057   /* we're at the right spot */
5058   if (index == stream->sample_index) {
5059     GST_DEBUG_OBJECT (stream->pad, "we are at the right index");
5060     return TRUE;
5061   }
5062
5063   /* find keyframe of the target index */
5064   kf_index = gst_qtdemux_find_keyframe (qtdemux, stream, index, FALSE);
5065
5066 /* *INDENT-OFF* */
5067 /* indent does stupid stuff with stream->samples[].timestamp */
5068
5069   /* if we move forwards, we don't have to go back to the previous
5070    * keyframe since we already sent that. We can also just jump to
5071    * the keyframe right before the target index if there is one. */
5072   if (index > stream->sample_index) {
5073     /* moving forwards check if we move past a keyframe */
5074     if (kf_index > stream->sample_index) {
5075       GST_DEBUG_OBJECT (stream->pad,
5076            "moving forwards to keyframe at %u (pts %" GST_TIME_FORMAT " dts %"GST_TIME_FORMAT" )", kf_index,
5077            GST_TIME_ARGS (QTSAMPLE_PTS(stream, &stream->samples[kf_index])),
5078            GST_TIME_ARGS (QTSAMPLE_DTS(stream, &stream->samples[kf_index])));
5079       gst_qtdemux_move_stream (qtdemux, stream, kf_index);
5080     } else {
5081       GST_DEBUG_OBJECT (stream->pad,
5082           "moving forwards, keyframe at %u (pts %" GST_TIME_FORMAT " dts %"GST_TIME_FORMAT" ) already sent", kf_index,
5083           GST_TIME_ARGS (QTSAMPLE_PTS (stream, &stream->samples[kf_index])),
5084           GST_TIME_ARGS (QTSAMPLE_DTS (stream, &stream->samples[kf_index])));
5085     }
5086   } else {
5087     GST_DEBUG_OBJECT (stream->pad,
5088         "moving backwards to keyframe at %u (pts %" GST_TIME_FORMAT " dts %"GST_TIME_FORMAT" )", kf_index,
5089         GST_TIME_ARGS (QTSAMPLE_PTS(stream, &stream->samples[kf_index])),
5090         GST_TIME_ARGS (QTSAMPLE_DTS(stream, &stream->samples[kf_index])));
5091     gst_qtdemux_move_stream (qtdemux, stream, kf_index);
5092   }
5093
5094 /* *INDENT-ON* */
5095
5096   return TRUE;
5097 }
5098
5099 /* prepare to get the current sample of @stream, getting essential values.
5100  *
5101  * This function will also prepare and send the segment when needed.
5102  *
5103  * Return FALSE if the stream is EOS.
5104  *
5105  * PULL-BASED
5106  */
5107 static gboolean
5108 gst_qtdemux_prepare_current_sample (GstQTDemux * qtdemux,
5109     QtDemuxStream * stream, gboolean * empty, guint64 * offset, guint * size,
5110     GstClockTime * dts, GstClockTime * pts, GstClockTime * duration,
5111     gboolean * keyframe)
5112 {
5113   QtDemuxSample *sample;
5114   GstClockTime time_position;
5115   guint32 seg_idx;
5116
5117   g_return_val_if_fail (stream != NULL, FALSE);
5118
5119   time_position = stream->time_position;
5120   if (G_UNLIKELY (time_position == GST_CLOCK_TIME_NONE))
5121     goto eos;
5122
5123   seg_idx = stream->segment_index;
5124   if (G_UNLIKELY (seg_idx == -1)) {
5125     /* find segment corresponding to time_position if we are looking
5126      * for a segment. */
5127     seg_idx = gst_qtdemux_find_segment (qtdemux, stream, time_position);
5128   }
5129
5130   /* different segment, activate it, sample_index will be set. */
5131   if (G_UNLIKELY (stream->segment_index != seg_idx))
5132     gst_qtdemux_activate_segment (qtdemux, stream, seg_idx, time_position);
5133
5134   if (G_UNLIKELY (QTSEGMENT_IS_EMPTY (&stream->segments[stream->
5135                   segment_index]))) {
5136     QtDemuxSegment *seg = &stream->segments[stream->segment_index];
5137
5138     GST_LOG_OBJECT (qtdemux, "Empty segment activated,"
5139         " prepare empty sample");
5140
5141     *empty = TRUE;
5142     *pts = *dts = time_position;
5143     *duration = seg->duration - (time_position - seg->time);
5144
5145     return TRUE;
5146   }
5147
5148   *empty = FALSE;
5149
5150   if (stream->sample_index == -1)
5151     stream->sample_index = 0;
5152
5153   GST_LOG_OBJECT (qtdemux, "segment active, index = %u of %u",
5154       stream->sample_index, stream->n_samples);
5155
5156   if (G_UNLIKELY (stream->sample_index >= stream->n_samples)) {
5157     if (!qtdemux->fragmented)
5158       goto eos;
5159
5160     GST_INFO_OBJECT (qtdemux, "out of samples, trying to add more");
5161     do {
5162       GstFlowReturn flow;
5163
5164       GST_OBJECT_LOCK (qtdemux);
5165       flow = qtdemux_add_fragmented_samples (qtdemux);
5166       GST_OBJECT_UNLOCK (qtdemux);
5167
5168       if (flow != GST_FLOW_OK)
5169         goto eos;
5170     }
5171     while (stream->sample_index >= stream->n_samples);
5172   }
5173
5174   if (!qtdemux_parse_samples (qtdemux, stream, stream->sample_index)) {
5175     GST_LOG_OBJECT (qtdemux, "Parsing of index %u failed!",
5176         stream->sample_index);
5177     return FALSE;
5178   }
5179
5180   /* now get the info for the sample we're at */
5181   sample = &stream->samples[stream->sample_index];
5182
5183   *dts = QTSAMPLE_DTS (stream, sample);
5184   *pts = QTSAMPLE_PTS (stream, sample);
5185   *offset = sample->offset;
5186   *size = sample->size;
5187   *duration = QTSAMPLE_DUR_DTS (stream, sample, *dts);
5188   *keyframe = QTSAMPLE_KEYFRAME (stream, sample);
5189
5190   return TRUE;
5191
5192   /* special cases */
5193 eos:
5194   {
5195     stream->time_position = GST_CLOCK_TIME_NONE;
5196     return FALSE;
5197   }
5198 }
5199
5200 /* move to the next sample in @stream.
5201  *
5202  * Moves to the next segment when needed.
5203  */
5204 static void
5205 gst_qtdemux_advance_sample (GstQTDemux * qtdemux, QtDemuxStream * stream)
5206 {
5207   QtDemuxSample *sample;
5208   QtDemuxSegment *segment;
5209
5210   /* get current segment */
5211   segment = &stream->segments[stream->segment_index];
5212
5213   if (G_UNLIKELY (QTSEGMENT_IS_EMPTY (segment))) {
5214     GST_DEBUG_OBJECT (qtdemux, "Empty segment, no samples to advance");
5215     goto next_segment;
5216   }
5217
5218   if (G_UNLIKELY (stream->sample_index >= stream->to_sample)) {
5219     /* Mark the stream as EOS */
5220     GST_DEBUG_OBJECT (qtdemux,
5221         "reached max allowed sample %u, mark EOS", stream->to_sample);
5222     stream->time_position = GST_CLOCK_TIME_NONE;
5223     return;
5224   }
5225
5226   /* move to next sample */
5227   stream->sample_index++;
5228   stream->offset_in_sample = 0;
5229
5230   /* reached the last sample, we need the next segment */
5231   if (G_UNLIKELY (stream->sample_index >= stream->n_samples))
5232     goto next_segment;
5233
5234   if (!qtdemux_parse_samples (qtdemux, stream, stream->sample_index)) {
5235     GST_LOG_OBJECT (qtdemux, "Parsing of index %u failed!",
5236         stream->sample_index);
5237     return;
5238   }
5239
5240   /* get next sample */
5241   sample = &stream->samples[stream->sample_index];
5242
5243   /* see if we are past the segment */
5244   if (G_UNLIKELY (QTSAMPLE_DTS (stream, sample) >= segment->media_stop))
5245     goto next_segment;
5246
5247   if (QTSAMPLE_DTS (stream, sample) >= segment->media_start) {
5248     /* inside the segment, update time_position, looks very familiar to
5249      * GStreamer segments, doesn't it? */
5250     stream->time_position =
5251         QTSAMPLE_DTS (stream, sample) - segment->media_start + segment->time;
5252   } else {
5253     /* not yet in segment, time does not yet increment. This means
5254      * that we are still prerolling keyframes to the decoder so it can
5255      * decode the first sample of the segment. */
5256     stream->time_position = segment->time;
5257   }
5258   return;
5259
5260   /* move to the next segment */
5261 next_segment:
5262   {
5263     GST_DEBUG_OBJECT (qtdemux, "segment %d ended ", stream->segment_index);
5264
5265     if (stream->segment_index == stream->n_segments - 1) {
5266       /* are we at the end of the last segment, we're EOS */
5267       stream->time_position = GST_CLOCK_TIME_NONE;
5268     } else {
5269       /* else we're only at the end of the current segment */
5270       stream->time_position = segment->stop_time;
5271     }
5272     /* make sure we select a new segment */
5273
5274     /* accumulate previous segments */
5275     if (GST_CLOCK_TIME_IS_VALID (stream->segment.stop))
5276       stream->accumulated_base +=
5277           (stream->segment.stop -
5278           stream->segment.start) / ABS (stream->segment.rate);
5279
5280     stream->segment_index = -1;
5281   }
5282 }
5283
5284 static void
5285 gst_qtdemux_sync_streams (GstQTDemux * demux)
5286 {
5287   GList *iter;
5288
5289   if (demux->n_streams <= 1)
5290     return;
5291
5292   for (iter = demux->active_streams; iter; iter = g_list_next (iter)) {
5293     QtDemuxStream *stream;
5294     GstClockTime end_time;
5295
5296     stream = QTDEMUX_STREAM (iter->data);
5297
5298     if (!stream->pad)
5299       continue;
5300
5301     /* TODO advance time on subtitle streams here, if any some day */
5302
5303     /* some clips/trailers may have unbalanced streams at the end,
5304      * so send EOS on shorter stream to prevent stalling others */
5305
5306     /* do not mess with EOS if SEGMENT seeking */
5307     if (demux->segment.flags & GST_SEEK_FLAG_SEGMENT)
5308       continue;
5309
5310     if (demux->pullbased) {
5311       /* loop mode is sample time based */
5312       if (!STREAM_IS_EOS (stream))
5313         continue;
5314     } else {
5315       /* push mode is byte position based */
5316       if (stream->n_samples &&
5317           stream->samples[stream->n_samples - 1].offset >= demux->offset)
5318         continue;
5319     }
5320
5321     if (stream->sent_eos)
5322       continue;
5323
5324     /* only act if some gap */
5325     end_time = stream->segments[stream->n_segments - 1].stop_time;
5326     GST_LOG_OBJECT (demux, "current position: %" GST_TIME_FORMAT
5327         ", stream end: %" GST_TIME_FORMAT,
5328         GST_TIME_ARGS (demux->segment.position), GST_TIME_ARGS (end_time));
5329     if (GST_CLOCK_TIME_IS_VALID (end_time)
5330         && (end_time + 2 * GST_SECOND < demux->segment.position)) {
5331       GstEvent *event;
5332
5333       GST_DEBUG_OBJECT (demux, "sending EOS for stream %s",
5334           GST_PAD_NAME (stream->pad));
5335       stream->sent_eos = TRUE;
5336       event = gst_event_new_eos ();
5337       if (demux->segment_seqnum != GST_SEQNUM_INVALID)
5338         gst_event_set_seqnum (event, demux->segment_seqnum);
5339       gst_pad_push_event (stream->pad, event);
5340     }
5341   }
5342 }
5343
5344 /* EOS and NOT_LINKED need to be combined. This means that we return:
5345  *
5346  *  GST_FLOW_NOT_LINKED: when all pads NOT_LINKED.
5347  *  GST_FLOW_EOS: when all pads EOS or NOT_LINKED.
5348  */
5349 static GstFlowReturn
5350 gst_qtdemux_combine_flows (GstQTDemux * demux, QtDemuxStream * stream,
5351     GstFlowReturn ret)
5352 {
5353   GST_LOG_OBJECT (demux, "flow return: %s", gst_flow_get_name (ret));
5354
5355   if (stream->pad)
5356     ret = gst_flow_combiner_update_pad_flow (demux->flowcombiner, stream->pad,
5357         ret);
5358   else
5359     ret = gst_flow_combiner_update_flow (demux->flowcombiner, ret);
5360
5361   GST_LOG_OBJECT (demux, "combined flow return: %s", gst_flow_get_name (ret));
5362   return ret;
5363 }
5364
5365 /* the input buffer metadata must be writable. Returns NULL when the buffer is
5366  * completely clipped
5367  *
5368  * Should be used only with raw buffers */
5369 static GstBuffer *
5370 gst_qtdemux_clip_buffer (GstQTDemux * qtdemux, QtDemuxStream * stream,
5371     GstBuffer * buf)
5372 {
5373   guint64 start, stop, cstart, cstop, diff;
5374   GstClockTime pts, duration;
5375   gsize size, osize;
5376   gint num_rate, denom_rate;
5377   gint frame_size;
5378   gboolean clip_data;
5379   guint offset;
5380
5381   osize = size = gst_buffer_get_size (buf);
5382   offset = 0;
5383
5384   /* depending on the type, setup the clip parameters */
5385   if (stream->subtype == FOURCC_soun) {
5386     frame_size = CUR_STREAM (stream)->bytes_per_frame;
5387     num_rate = GST_SECOND;
5388     denom_rate = (gint) CUR_STREAM (stream)->rate;
5389     clip_data = TRUE;
5390   } else if (stream->subtype == FOURCC_vide) {
5391     frame_size = size;
5392     num_rate = CUR_STREAM (stream)->fps_n;
5393     denom_rate = CUR_STREAM (stream)->fps_d;
5394     clip_data = FALSE;
5395   } else
5396     goto wrong_type;
5397
5398   if (frame_size <= 0)
5399     goto bad_frame_size;
5400
5401   /* we can only clip if we have a valid pts */
5402   pts = GST_BUFFER_PTS (buf);
5403   if (G_UNLIKELY (!GST_CLOCK_TIME_IS_VALID (pts)))
5404     goto no_pts;
5405
5406   duration = GST_BUFFER_DURATION (buf);
5407
5408   if (G_UNLIKELY (!GST_CLOCK_TIME_IS_VALID (duration))) {
5409     duration =
5410         gst_util_uint64_scale_int (size / frame_size, num_rate, denom_rate);
5411   }
5412
5413   start = pts;
5414   stop = start + duration;
5415
5416   if (G_UNLIKELY (!gst_segment_clip (&stream->segment,
5417               GST_FORMAT_TIME, start, stop, &cstart, &cstop)))
5418     goto clipped;
5419
5420   /* see if some clipping happened */
5421   diff = cstart - start;
5422   if (diff > 0) {
5423     pts += diff;
5424     duration -= diff;
5425
5426     if (clip_data) {
5427       /* bring clipped time to samples and to bytes */
5428       diff = gst_util_uint64_scale_int (diff, denom_rate, num_rate);
5429       diff *= frame_size;
5430
5431       GST_DEBUG_OBJECT (qtdemux,
5432           "clipping start to %" GST_TIME_FORMAT " %"
5433           G_GUINT64_FORMAT " bytes", GST_TIME_ARGS (cstart), diff);
5434
5435       offset = diff;
5436       size -= diff;
5437     }
5438   }
5439   diff = stop - cstop;
5440   if (diff > 0) {
5441     duration -= diff;
5442
5443     if (clip_data) {
5444       /* bring clipped time to samples and then to bytes */
5445       diff = gst_util_uint64_scale_int (diff, denom_rate, num_rate);
5446       diff *= frame_size;
5447       GST_DEBUG_OBJECT (qtdemux,
5448           "clipping stop to %" GST_TIME_FORMAT " %" G_GUINT64_FORMAT
5449           " bytes", GST_TIME_ARGS (cstop), diff);
5450       size -= diff;
5451     }
5452   }
5453
5454   if (offset != 0 || size != osize)
5455     gst_buffer_resize (buf, offset, size);
5456
5457   GST_BUFFER_DTS (buf) = GST_CLOCK_TIME_NONE;
5458   GST_BUFFER_PTS (buf) = pts;
5459   GST_BUFFER_DURATION (buf) = duration;
5460
5461   return buf;
5462
5463   /* dropped buffer */
5464 wrong_type:
5465   {
5466     GST_DEBUG_OBJECT (qtdemux, "unknown stream type");
5467     return buf;
5468   }
5469 bad_frame_size:
5470   {
5471     GST_DEBUG_OBJECT (qtdemux, "bad frame size");
5472     return buf;
5473   }
5474 no_pts:
5475   {
5476     GST_DEBUG_OBJECT (qtdemux, "no pts on buffer");
5477     return buf;
5478   }
5479 clipped:
5480   {
5481     GST_DEBUG_OBJECT (qtdemux, "clipped buffer");
5482     gst_buffer_unref (buf);
5483     return NULL;
5484   }
5485 }
5486
5487 static GstBuffer *
5488 gst_qtdemux_align_buffer (GstQTDemux * demux,
5489     GstBuffer * buffer, gsize alignment)
5490 {
5491   GstMapInfo map;
5492
5493   gst_buffer_map (buffer, &map, GST_MAP_READ);
5494
5495   if (map.size < sizeof (guintptr)) {
5496     gst_buffer_unmap (buffer, &map);
5497     return buffer;
5498   }
5499
5500   if (((guintptr) map.data) & (alignment - 1)) {
5501     GstBuffer *new_buffer;
5502     GstAllocationParams params = { 0, alignment - 1, 0, 0, };
5503
5504     new_buffer = gst_buffer_new_allocate (NULL,
5505         gst_buffer_get_size (buffer), &params);
5506
5507     /* Copy data "by hand", so ensure alignment is kept: */
5508     gst_buffer_fill (new_buffer, 0, map.data, map.size);
5509
5510     gst_buffer_copy_into (new_buffer, buffer, GST_BUFFER_COPY_METADATA, 0, -1);
5511     GST_DEBUG_OBJECT (demux,
5512         "We want output aligned on %" G_GSIZE_FORMAT ", reallocated",
5513         alignment);
5514
5515     gst_buffer_unmap (buffer, &map);
5516     gst_buffer_unref (buffer);
5517
5518     return new_buffer;
5519   }
5520
5521   gst_buffer_unmap (buffer, &map);
5522   return buffer;
5523 }
5524
5525 static guint8 *
5526 convert_to_ccdata (const guint8 * ccpair, guint8 ccpair_size, guint field,
5527     gsize * res)
5528 {
5529   guint8 *storage;
5530   gsize i;
5531
5532   /* We are converting from pairs to triplets */
5533   *res = ccpair_size / 2 * 3;
5534   storage = g_malloc (*res);
5535   for (i = 0; i * 2 < ccpair_size; i += 1) {
5536     if (field == 1)
5537       storage[i * 3] = 0xfc;
5538     else
5539       storage[i * 3] = 0xfd;
5540     storage[i * 3 + 1] = ccpair[i * 2];
5541     storage[i * 3 + 2] = ccpair[i * 2 + 1];
5542   }
5543
5544   return storage;
5545 }
5546
5547 static guint8 *
5548 extract_cc_from_data (QtDemuxStream * stream, const guint8 * data, gsize size,
5549     gsize * cclen)
5550 {
5551   guint8 *res = NULL;
5552   guint32 atom_length, fourcc;
5553   QtDemuxStreamStsdEntry *stsd_entry;
5554
5555   GST_MEMDUMP ("caption atom", data, size);
5556
5557   /* There might be multiple atoms */
5558
5559   *cclen = 0;
5560   if (size < 8)
5561     goto invalid_cdat;
5562   atom_length = QT_UINT32 (data);
5563   fourcc = QT_FOURCC (data + 4);
5564   if (G_UNLIKELY (atom_length > size || atom_length == 8))
5565     goto invalid_cdat;
5566
5567   GST_DEBUG_OBJECT (stream->pad, "here");
5568
5569   /* Check if we have somethig compatible */
5570   stsd_entry = CUR_STREAM (stream);
5571   switch (stsd_entry->fourcc) {
5572     case FOURCC_c608:{
5573       guint8 *cdat = NULL, *cdt2 = NULL;
5574       gsize cdat_size = 0, cdt2_size = 0;
5575       /* Should be cdat or cdt2 */
5576       if (fourcc != FOURCC_cdat && fourcc != FOURCC_cdt2) {
5577         GST_WARNING_OBJECT (stream->pad,
5578             "Unknown data atom (%" GST_FOURCC_FORMAT ") for CEA608",
5579             GST_FOURCC_ARGS (fourcc));
5580         goto invalid_cdat;
5581       }
5582
5583       /* Convert to cc_data triplet */
5584       if (fourcc == FOURCC_cdat)
5585         cdat = convert_to_ccdata (data + 8, atom_length - 8, 1, &cdat_size);
5586       else
5587         cdt2 = convert_to_ccdata (data + 8, atom_length - 8, 2, &cdt2_size);
5588       GST_DEBUG_OBJECT (stream->pad, "size:%" G_GSIZE_FORMAT " atom_length:%u",
5589           size, atom_length);
5590
5591       /* Check for another atom ? */
5592       if (size > atom_length + 8) {
5593         guint32 new_atom_length = QT_UINT32 (data + atom_length);
5594         if (size >= atom_length + new_atom_length) {
5595           fourcc = QT_FOURCC (data + atom_length + 4);
5596           if (fourcc == FOURCC_cdat) {
5597             if (cdat == NULL)
5598               cdat =
5599                   convert_to_ccdata (data + atom_length + 8,
5600                   new_atom_length - 8, 1, &cdat_size);
5601             else
5602               GST_WARNING_OBJECT (stream->pad,
5603                   "Got multiple [cdat] atoms in a c608 sample. This is unsupported for now. Please file a bug");
5604           } else {
5605             if (cdt2 == NULL)
5606               cdt2 =
5607                   convert_to_ccdata (data + atom_length + 8,
5608                   new_atom_length - 8, 2, &cdt2_size);
5609             else
5610               GST_WARNING_OBJECT (stream->pad,
5611                   "Got multiple [cdt2] atoms in a c608 sample. This is unsupported for now. Please file a bug");
5612           }
5613         }
5614       }
5615
5616       *cclen = cdat_size + cdt2_size;
5617       res = g_malloc (*cclen);
5618       if (cdat_size)
5619         memcpy (res, cdat, cdat_size);
5620       if (cdt2_size)
5621         memcpy (res + cdat_size, cdt2, cdt2_size);
5622       g_free (cdat);
5623       g_free (cdt2);
5624     }
5625       break;
5626     case FOURCC_c708:
5627       if (fourcc != FOURCC_ccdp) {
5628         GST_WARNING_OBJECT (stream->pad,
5629             "Unknown data atom (%" GST_FOURCC_FORMAT ") for CEA708",
5630             GST_FOURCC_ARGS (fourcc));
5631         goto invalid_cdat;
5632       }
5633       *cclen = atom_length - 8;
5634       res = g_memdup (data + 8, *cclen);
5635       break;
5636     default:
5637       /* Keep this here in case other closed caption formats are added */
5638       g_assert_not_reached ();
5639       break;
5640   }
5641
5642   GST_MEMDUMP ("Output", res, *cclen);
5643   return res;
5644
5645   /* Errors */
5646 invalid_cdat:
5647   GST_WARNING ("[cdat] atom is too small or invalid");
5648   return NULL;
5649 }
5650
5651 /* the input buffer metadata must be writable,
5652  * but time/duration etc not yet set and need not be preserved */
5653 static GstBuffer *
5654 gst_qtdemux_process_buffer (GstQTDemux * qtdemux, QtDemuxStream * stream,
5655     GstBuffer * buf)
5656 {
5657   GstMapInfo map;
5658   guint nsize = 0;
5659   gchar *str;
5660
5661   /* not many cases for now */
5662   if (G_UNLIKELY (CUR_STREAM (stream)->fourcc == FOURCC_mp4s)) {
5663     /* send a one time dvd clut event */
5664     if (stream->pending_event && stream->pad)
5665       gst_pad_push_event (stream->pad, stream->pending_event);
5666     stream->pending_event = NULL;
5667   }
5668
5669   if (G_UNLIKELY (stream->subtype != FOURCC_text
5670           && stream->subtype != FOURCC_sbtl &&
5671           stream->subtype != FOURCC_subp && stream->subtype != FOURCC_clcp)) {
5672     return buf;
5673   }
5674
5675   gst_buffer_map (buf, &map, GST_MAP_READ);
5676
5677   /* empty buffer is sent to terminate previous subtitle */
5678   if (map.size <= 2) {
5679     gst_buffer_unmap (buf, &map);
5680     gst_buffer_unref (buf);
5681     return NULL;
5682   }
5683   if (stream->subtype == FOURCC_subp) {
5684     /* That's all the processing needed for subpictures */
5685     gst_buffer_unmap (buf, &map);
5686     return buf;
5687   }
5688
5689   if (stream->subtype == FOURCC_clcp) {
5690     guint8 *cc;
5691     gsize cclen = 0;
5692     /* For closed caption, we need to extract the information from the
5693      * [cdat],[cdt2] or [ccdp] atom */
5694     cc = extract_cc_from_data (stream, map.data, map.size, &cclen);
5695     gst_buffer_unmap (buf, &map);
5696     gst_buffer_unref (buf);
5697     if (cc) {
5698       buf = _gst_buffer_new_wrapped (cc, cclen, g_free);
5699     } else {
5700       /* Conversion failed or there's nothing */
5701       buf = NULL;
5702     }
5703     return buf;
5704   }
5705
5706   nsize = GST_READ_UINT16_BE (map.data);
5707   nsize = MIN (nsize, map.size - 2);
5708
5709   GST_LOG_OBJECT (qtdemux, "3GPP timed text subtitle: %d/%" G_GSIZE_FORMAT "",
5710       nsize, map.size);
5711
5712   /* takes care of UTF-8 validation or UTF-16 recognition,
5713    * no other encoding expected */
5714   str = gst_tag_freeform_string_to_utf8 ((gchar *) map.data + 2, nsize, NULL);
5715   gst_buffer_unmap (buf, &map);
5716   if (str) {
5717     gst_buffer_unref (buf);
5718     buf = _gst_buffer_new_wrapped (str, strlen (str), g_free);
5719   } else {
5720     /* this should not really happen unless the subtitle is corrupted */
5721     gst_buffer_unref (buf);
5722     buf = NULL;
5723   }
5724
5725   /* FIXME ? convert optional subsequent style info to markup */
5726
5727   return buf;
5728 }
5729
5730 /* Sets a buffer's attributes properly and pushes it downstream.
5731  * Also checks for additional actions and custom processing that may
5732  * need to be done first.
5733  */
5734 static GstFlowReturn
5735 gst_qtdemux_decorate_and_push_buffer (GstQTDemux * qtdemux,
5736     QtDemuxStream * stream, GstBuffer * buf,
5737     GstClockTime dts, GstClockTime pts, GstClockTime duration,
5738     gboolean keyframe, GstClockTime position, guint64 byte_position)
5739 {
5740   GstFlowReturn ret = GST_FLOW_OK;
5741
5742   /* offset the timestamps according to the edit list */
5743
5744   if (G_UNLIKELY (CUR_STREAM (stream)->fourcc == FOURCC_rtsp)) {
5745     gchar *url;
5746     GstMapInfo map;
5747
5748     gst_buffer_map (buf, &map, GST_MAP_READ);
5749     url = g_strndup ((gchar *) map.data, map.size);
5750     gst_buffer_unmap (buf, &map);
5751     if (url != NULL && strlen (url) != 0) {
5752       /* we have RTSP redirect now */
5753       gst_element_post_message (GST_ELEMENT_CAST (qtdemux),
5754           gst_message_new_element (GST_OBJECT_CAST (qtdemux),
5755               gst_structure_new ("redirect",
5756                   "new-location", G_TYPE_STRING, url, NULL)));
5757       qtdemux->posted_redirect = TRUE;
5758     } else {
5759       GST_WARNING_OBJECT (qtdemux, "Redirect URI of stream is empty, not "
5760           "posting");
5761     }
5762     g_free (url);
5763   }
5764
5765   /* position reporting */
5766   if (qtdemux->segment.rate >= 0) {
5767     qtdemux->segment.position = position;
5768     gst_qtdemux_sync_streams (qtdemux);
5769   }
5770
5771   if (G_UNLIKELY (!stream->pad)) {
5772     GST_DEBUG_OBJECT (qtdemux, "No output pad for stream, ignoring");
5773     gst_buffer_unref (buf);
5774     goto exit;
5775   }
5776
5777   /* send out pending buffers */
5778   while (stream->buffers) {
5779     GstBuffer *buffer = (GstBuffer *) stream->buffers->data;
5780
5781     if (G_UNLIKELY (stream->discont)) {
5782       GST_LOG_OBJECT (qtdemux, "marking discont buffer");
5783       GST_BUFFER_FLAG_SET (buffer, GST_BUFFER_FLAG_DISCONT);
5784       stream->discont = FALSE;
5785     } else {
5786       GST_BUFFER_FLAG_UNSET (buf, GST_BUFFER_FLAG_DISCONT);
5787     }
5788
5789     if (stream->alignment > 1)
5790       buffer = gst_qtdemux_align_buffer (qtdemux, buffer, stream->alignment);
5791     gst_pad_push (stream->pad, buffer);
5792
5793     stream->buffers = g_slist_delete_link (stream->buffers, stream->buffers);
5794   }
5795
5796   /* we're going to modify the metadata */
5797   buf = gst_buffer_make_writable (buf);
5798
5799   if (G_UNLIKELY (stream->need_process))
5800     buf = gst_qtdemux_process_buffer (qtdemux, stream, buf);
5801
5802   if (!buf) {
5803     goto exit;
5804   }
5805
5806   GST_BUFFER_DTS (buf) = dts;
5807   GST_BUFFER_PTS (buf) = pts;
5808   GST_BUFFER_DURATION (buf) = duration;
5809   GST_BUFFER_OFFSET (buf) = -1;
5810   GST_BUFFER_OFFSET_END (buf) = -1;
5811
5812   if (G_UNLIKELY (CUR_STREAM (stream)->rgb8_palette))
5813     gst_buffer_append_memory (buf,
5814         gst_memory_ref (CUR_STREAM (stream)->rgb8_palette));
5815
5816   if (G_UNLIKELY (CUR_STREAM (stream)->padding)) {
5817     gst_buffer_resize (buf, CUR_STREAM (stream)->padding, -1);
5818   }
5819 #if 0
5820   if (G_UNLIKELY (qtdemux->element_index)) {
5821     GstClockTime stream_time;
5822
5823     stream_time =
5824         gst_segment_to_stream_time (&stream->segment, GST_FORMAT_TIME,
5825         timestamp);
5826     if (GST_CLOCK_TIME_IS_VALID (stream_time)) {
5827       GST_LOG_OBJECT (qtdemux,
5828           "adding association %" GST_TIME_FORMAT "-> %"
5829           G_GUINT64_FORMAT, GST_TIME_ARGS (stream_time), byte_position);
5830       gst_index_add_association (qtdemux->element_index,
5831           qtdemux->index_id,
5832           keyframe ? GST_ASSOCIATION_FLAG_KEY_UNIT :
5833           GST_ASSOCIATION_FLAG_DELTA_UNIT, GST_FORMAT_TIME, stream_time,
5834           GST_FORMAT_BYTES, byte_position, NULL);
5835     }
5836   }
5837 #endif
5838
5839   if (stream->need_clip)
5840     buf = gst_qtdemux_clip_buffer (qtdemux, stream, buf);
5841
5842   if (G_UNLIKELY (buf == NULL))
5843     goto exit;
5844
5845   if (G_UNLIKELY (stream->discont)) {
5846     GST_LOG_OBJECT (qtdemux, "marking discont buffer");
5847     GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_DISCONT);
5848     stream->discont = FALSE;
5849   } else {
5850     GST_BUFFER_FLAG_UNSET (buf, GST_BUFFER_FLAG_DISCONT);
5851   }
5852
5853   if (!keyframe) {
5854     GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_DELTA_UNIT);
5855     stream->on_keyframe = FALSE;
5856   } else {
5857     stream->on_keyframe = TRUE;
5858   }
5859
5860
5861   GST_LOG_OBJECT (qtdemux,
5862       "Pushing buffer with dts %" GST_TIME_FORMAT ", pts %" GST_TIME_FORMAT
5863       ", duration %" GST_TIME_FORMAT " on pad %s", GST_TIME_ARGS (dts),
5864       GST_TIME_ARGS (pts), GST_TIME_ARGS (duration),
5865       GST_PAD_NAME (stream->pad));
5866
5867   if (stream->protected && stream->protection_scheme_type == FOURCC_cenc) {
5868     GstStructure *crypto_info;
5869     QtDemuxCencSampleSetInfo *info =
5870         (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
5871     gint index;
5872     GstEvent *event;
5873
5874     while ((event = g_queue_pop_head (&stream->protection_scheme_event_queue))) {
5875       GST_TRACE_OBJECT (stream->pad, "pushing protection event: %"
5876           GST_PTR_FORMAT, event);
5877       gst_pad_push_event (stream->pad, event);
5878     }
5879
5880     if (info->crypto_info == NULL) {
5881       GST_DEBUG_OBJECT (qtdemux,
5882           "cenc metadata hasn't been parsed yet, pushing buffer as if it wasn't encrypted");
5883     } else {
5884       /* The end of the crypto_info array matches our n_samples position,
5885        * so count backward from there */
5886       index = stream->sample_index - stream->n_samples + info->crypto_info->len;
5887       if (G_LIKELY (index >= 0 && index < info->crypto_info->len)) {
5888         /* steal structure from array */
5889         crypto_info = g_ptr_array_index (info->crypto_info, index);
5890         g_ptr_array_index (info->crypto_info, index) = NULL;
5891         GST_LOG_OBJECT (qtdemux, "attaching cenc metadata [%u/%u]", index,
5892             info->crypto_info->len);
5893         if (!crypto_info || !gst_buffer_add_protection_meta (buf, crypto_info))
5894           GST_ERROR_OBJECT (qtdemux,
5895               "failed to attach cenc metadata to buffer");
5896       } else {
5897         GST_INFO_OBJECT (qtdemux, "No crypto info with index %d and sample %d",
5898             index, stream->sample_index);
5899       }
5900     }
5901   }
5902
5903   if (stream->alignment > 1)
5904     buf = gst_qtdemux_align_buffer (qtdemux, buf, stream->alignment);
5905
5906   ret = gst_pad_push (stream->pad, buf);
5907
5908   if (GST_CLOCK_TIME_IS_VALID (pts) && GST_CLOCK_TIME_IS_VALID (duration)) {
5909     /* mark position in stream, we'll need this to know when to send GAP event */
5910     stream->segment.position = pts + duration;
5911   }
5912
5913 exit:
5914   return ret;
5915 }
5916
5917 static const QtDemuxRandomAccessEntry *
5918 gst_qtdemux_stream_seek_fragment (GstQTDemux * qtdemux, QtDemuxStream * stream,
5919     GstClockTime pos, gboolean after)
5920 {
5921   QtDemuxRandomAccessEntry *entries = stream->ra_entries;
5922   guint n_entries = stream->n_ra_entries;
5923   guint i;
5924
5925   /* we assume the table is sorted */
5926   for (i = 0; i < n_entries; ++i) {
5927     if (entries[i].ts > pos)
5928       break;
5929   }
5930
5931   /* FIXME: maybe save first moof_offset somewhere instead, but for now it's
5932    * probably okay to assume that the index lists the very first fragment */
5933   if (i == 0)
5934     return &entries[0];
5935
5936   if (after)
5937     return &entries[i];
5938   else
5939     return &entries[i - 1];
5940 }
5941
5942 static gboolean
5943 gst_qtdemux_do_fragmented_seek (GstQTDemux * qtdemux)
5944 {
5945   const QtDemuxRandomAccessEntry *best_entry = NULL;
5946   GList *iter;
5947
5948   GST_OBJECT_LOCK (qtdemux);
5949
5950   g_assert (qtdemux->n_streams > 0);
5951
5952   /* first see if we can determine where to go to using mfra,
5953    * before we start clearing things */
5954   for (iter = qtdemux->active_streams; iter; iter = g_list_next (iter)) {
5955     const QtDemuxRandomAccessEntry *entry;
5956     QtDemuxStream *stream;
5957     gboolean is_audio_or_video;
5958
5959     stream = QTDEMUX_STREAM (iter->data);
5960
5961     if (stream->ra_entries == NULL)
5962       continue;
5963
5964     if (stream->subtype == FOURCC_vide || stream->subtype == FOURCC_soun)
5965       is_audio_or_video = TRUE;
5966     else
5967       is_audio_or_video = FALSE;
5968
5969     entry =
5970         gst_qtdemux_stream_seek_fragment (qtdemux, stream,
5971         stream->time_position, !is_audio_or_video);
5972
5973     GST_INFO_OBJECT (stream->pad, "%" GST_TIME_FORMAT " at offset "
5974         "%" G_GUINT64_FORMAT, GST_TIME_ARGS (entry->ts), entry->moof_offset);
5975
5976     stream->pending_seek = entry;
5977
5978     /* decide position to jump to just based on audio/video tracks, not subs */
5979     if (!is_audio_or_video)
5980       continue;
5981
5982     if (best_entry == NULL || entry->moof_offset < best_entry->moof_offset)
5983       best_entry = entry;
5984   }
5985
5986   /* no luck, will handle seek otherwise */
5987   if (best_entry == NULL) {
5988     GST_OBJECT_UNLOCK (qtdemux);
5989     return FALSE;
5990   }
5991
5992   /* ok, now we can prepare for processing as of located moof */
5993   for (iter = qtdemux->active_streams; iter; iter = g_list_next (iter)) {
5994     QtDemuxStream *stream;
5995
5996     stream = QTDEMUX_STREAM (iter->data);
5997
5998     g_free (stream->samples);
5999     stream->samples = NULL;
6000     stream->n_samples = 0;
6001     stream->stbl_index = -1;    /* no samples have yet been parsed */
6002     stream->sample_index = -1;
6003
6004     if (stream->protection_scheme_info) {
6005       /* Clear out any old cenc crypto info entries as we'll move to a new moof */
6006       if (stream->protection_scheme_type == FOURCC_cenc) {
6007         QtDemuxCencSampleSetInfo *info =
6008             (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
6009         if (info->crypto_info) {
6010           g_ptr_array_free (info->crypto_info, TRUE);
6011           info->crypto_info = NULL;
6012         }
6013       }
6014     }
6015   }
6016
6017   GST_INFO_OBJECT (qtdemux, "seek to %" GST_TIME_FORMAT ", best fragment "
6018       "moof offset: %" G_GUINT64_FORMAT ", ts %" GST_TIME_FORMAT,
6019       GST_TIME_ARGS (QTDEMUX_FIRST_STREAM (qtdemux)->time_position),
6020       best_entry->moof_offset, GST_TIME_ARGS (best_entry->ts));
6021
6022   qtdemux->moof_offset = best_entry->moof_offset;
6023
6024   qtdemux_add_fragmented_samples (qtdemux);
6025
6026   GST_OBJECT_UNLOCK (qtdemux);
6027   return TRUE;
6028 }
6029
6030 static GstFlowReturn
6031 gst_qtdemux_loop_state_movie (GstQTDemux * qtdemux)
6032 {
6033   GstFlowReturn ret = GST_FLOW_OK;
6034   GstBuffer *buf = NULL;
6035   QtDemuxStream *stream, *target_stream = NULL;
6036   GstClockTime min_time;
6037   guint64 offset = 0;
6038   GstClockTime dts = GST_CLOCK_TIME_NONE;
6039   GstClockTime pts = GST_CLOCK_TIME_NONE;
6040   GstClockTime duration = 0;
6041   gboolean keyframe = FALSE;
6042   guint sample_size = 0;
6043   gboolean empty = 0;
6044   guint size;
6045   GList *iter;
6046
6047   if (qtdemux->fragmented_seek_pending) {
6048     GST_INFO_OBJECT (qtdemux, "pending fragmented seek");
6049     if (gst_qtdemux_do_fragmented_seek (qtdemux)) {
6050       GST_INFO_OBJECT (qtdemux, "fragmented seek done!");
6051       qtdemux->fragmented_seek_pending = FALSE;
6052     } else {
6053       GST_INFO_OBJECT (qtdemux, "fragmented seek still pending");
6054     }
6055   }
6056
6057   /* Figure out the next stream sample to output, min_time is expressed in
6058    * global time and runs over the edit list segments. */
6059   min_time = G_MAXUINT64;
6060   for (iter = qtdemux->active_streams; iter; iter = g_list_next (iter)) {
6061     GstClockTime position;
6062
6063     stream = QTDEMUX_STREAM (iter->data);
6064     position = stream->time_position;
6065
6066     /* position of -1 is EOS */
6067     if (position != GST_CLOCK_TIME_NONE && position < min_time) {
6068       min_time = position;
6069       target_stream = stream;
6070     }
6071   }
6072   /* all are EOS */
6073   if (G_UNLIKELY (target_stream == NULL)) {
6074     GST_DEBUG_OBJECT (qtdemux, "all streams are EOS");
6075     goto eos;
6076   }
6077
6078   /* check for segment end */
6079   if (G_UNLIKELY (qtdemux->segment.stop != -1
6080           && ((qtdemux->segment.rate >= 0 && qtdemux->segment.stop <= min_time)
6081               || (qtdemux->segment.rate < 0
6082                   && qtdemux->segment.start > min_time))
6083           && target_stream->on_keyframe)) {
6084     GST_DEBUG_OBJECT (qtdemux, "we reached the end of our segment.");
6085     target_stream->time_position = GST_CLOCK_TIME_NONE;
6086     goto eos_stream;
6087   }
6088
6089   /* gap events for subtitle streams */
6090   for (iter = qtdemux->active_streams; iter; iter = g_list_next (iter)) {
6091     stream = QTDEMUX_STREAM (iter->data);
6092     if (stream->pad && (stream->subtype == FOURCC_subp
6093             || stream->subtype == FOURCC_text
6094             || stream->subtype == FOURCC_sbtl)) {
6095       /* send one second gap events until the stream catches up */
6096       /* gaps can only be sent after segment is activated (segment.stop is no longer -1) */
6097       while (GST_CLOCK_TIME_IS_VALID (stream->segment.stop) &&
6098           GST_CLOCK_TIME_IS_VALID (stream->segment.position) &&
6099           stream->segment.position + GST_SECOND < min_time) {
6100         GstEvent *gap =
6101             gst_event_new_gap (stream->segment.position, GST_SECOND);
6102         gst_pad_push_event (stream->pad, gap);
6103         stream->segment.position += GST_SECOND;
6104       }
6105     }
6106   }
6107
6108   stream = target_stream;
6109   /* fetch info for the current sample of this stream */
6110   if (G_UNLIKELY (!gst_qtdemux_prepare_current_sample (qtdemux, stream, &empty,
6111               &offset, &sample_size, &dts, &pts, &duration, &keyframe)))
6112     goto eos_stream;
6113
6114   gst_qtdemux_stream_check_and_change_stsd_index (qtdemux, stream);
6115   if (stream->new_caps) {
6116     gst_qtdemux_configure_stream (qtdemux, stream);
6117     qtdemux_do_allocation (qtdemux, stream);
6118   }
6119
6120   /* If we're doing a keyframe-only trickmode, only push keyframes on video streams */
6121   if (G_UNLIKELY (qtdemux->
6122           segment.flags & GST_SEGMENT_FLAG_TRICKMODE_KEY_UNITS)) {
6123     if (stream->subtype == FOURCC_vide && !keyframe) {
6124       GST_LOG_OBJECT (qtdemux, "Skipping non-keyframe on track-id %u",
6125           stream->track_id);
6126       goto next;
6127     }
6128   }
6129
6130   GST_DEBUG_OBJECT (qtdemux,
6131       "pushing from track-id %u, empty %d offset %" G_GUINT64_FORMAT
6132       ", size %d, dts=%" GST_TIME_FORMAT ", pts=%" GST_TIME_FORMAT
6133       ", duration %" GST_TIME_FORMAT, stream->track_id, empty, offset,
6134       sample_size, GST_TIME_ARGS (dts), GST_TIME_ARGS (pts),
6135       GST_TIME_ARGS (duration));
6136
6137   if (G_UNLIKELY (empty)) {
6138     /* empty segment, push a gap if there's a second or more
6139      * difference and move to the next one */
6140     if ((pts + duration - stream->segment.position) >= GST_SECOND)
6141       gst_pad_push_event (stream->pad, gst_event_new_gap (pts, duration));
6142     stream->segment.position = pts + duration;
6143     goto next;
6144   }
6145
6146   /* hmm, empty sample, skip and move to next sample */
6147   if (G_UNLIKELY (sample_size <= 0))
6148     goto next;
6149
6150   /* last pushed sample was out of boundary, goto next sample */
6151   if (G_UNLIKELY (GST_PAD_LAST_FLOW_RETURN (stream->pad) == GST_FLOW_EOS))
6152     goto next;
6153
6154   if (stream->max_buffer_size == 0 || sample_size <= stream->max_buffer_size) {
6155     size = sample_size;
6156   } else {
6157     GST_DEBUG_OBJECT (qtdemux,
6158         "size %d larger than stream max_buffer_size %d, trimming",
6159         sample_size, stream->max_buffer_size);
6160     size =
6161         MIN (sample_size - stream->offset_in_sample, stream->max_buffer_size);
6162   }
6163
6164   if (qtdemux->cenc_aux_info_offset > 0) {
6165     GstMapInfo map;
6166     GstByteReader br;
6167     GstBuffer *aux_info = NULL;
6168
6169     /* pull the data stored before the sample */
6170     ret =
6171         gst_qtdemux_pull_atom (qtdemux, qtdemux->offset,
6172         offset + stream->offset_in_sample - qtdemux->offset, &aux_info);
6173     if (G_UNLIKELY (ret != GST_FLOW_OK))
6174       goto beach;
6175     gst_buffer_map (aux_info, &map, GST_MAP_READ);
6176     GST_DEBUG_OBJECT (qtdemux, "parsing cenc auxiliary info");
6177     gst_byte_reader_init (&br, map.data + 8, map.size);
6178     if (!qtdemux_parse_cenc_aux_info (qtdemux, stream, &br,
6179             qtdemux->cenc_aux_info_sizes, qtdemux->cenc_aux_sample_count)) {
6180       GST_ERROR_OBJECT (qtdemux, "failed to parse cenc auxiliary info");
6181       gst_buffer_unmap (aux_info, &map);
6182       gst_buffer_unref (aux_info);
6183       ret = GST_FLOW_ERROR;
6184       goto beach;
6185     }
6186     gst_buffer_unmap (aux_info, &map);
6187     gst_buffer_unref (aux_info);
6188   }
6189
6190   GST_LOG_OBJECT (qtdemux, "reading %d bytes @ %" G_GUINT64_FORMAT, size,
6191       offset);
6192
6193   if (stream->use_allocator) {
6194     /* if we have a per-stream allocator, use it */
6195     buf = gst_buffer_new_allocate (stream->allocator, size, &stream->params);
6196   }
6197
6198   ret = gst_qtdemux_pull_atom (qtdemux, offset + stream->offset_in_sample,
6199       size, &buf);
6200   if (G_UNLIKELY (ret != GST_FLOW_OK))
6201     goto beach;
6202
6203   if (size != sample_size) {
6204     pts += gst_util_uint64_scale_int (GST_SECOND,
6205         stream->offset_in_sample / CUR_STREAM (stream)->bytes_per_frame,
6206         stream->timescale);
6207     dts +=
6208         gst_util_uint64_scale_int (GST_SECOND,
6209         stream->offset_in_sample / CUR_STREAM (stream)->bytes_per_frame,
6210         stream->timescale);
6211     duration =
6212         gst_util_uint64_scale_int (GST_SECOND,
6213         size / CUR_STREAM (stream)->bytes_per_frame, stream->timescale);
6214   }
6215
6216   ret = gst_qtdemux_decorate_and_push_buffer (qtdemux, stream, buf,
6217       dts, pts, duration, keyframe, min_time, offset);
6218
6219   if (size != sample_size) {
6220     QtDemuxSample *sample = &stream->samples[stream->sample_index];
6221     QtDemuxSegment *segment = &stream->segments[stream->segment_index];
6222
6223     GstClockTime time_position = QTSTREAMTIME_TO_GSTTIME (stream,
6224         sample->timestamp +
6225         stream->offset_in_sample / CUR_STREAM (stream)->bytes_per_frame);
6226     if (time_position >= segment->media_start) {
6227       /* inside the segment, update time_position, looks very familiar to
6228        * GStreamer segments, doesn't it? */
6229       stream->time_position = (time_position - segment->media_start) +
6230           segment->time;
6231     } else {
6232       /* not yet in segment, time does not yet increment. This means
6233        * that we are still prerolling keyframes to the decoder so it can
6234        * decode the first sample of the segment. */
6235       stream->time_position = segment->time;
6236     }
6237   }
6238
6239   /* combine flows */
6240   ret = gst_qtdemux_combine_flows (qtdemux, stream, ret);
6241   /* ignore unlinked, we will not push on the pad anymore and we will EOS when
6242    * we have no more data for the pad to push */
6243   if (ret == GST_FLOW_EOS)
6244     ret = GST_FLOW_OK;
6245
6246   stream->offset_in_sample += size;
6247   if (stream->offset_in_sample >= sample_size) {
6248     gst_qtdemux_advance_sample (qtdemux, stream);
6249   }
6250   goto beach;
6251
6252 next:
6253   gst_qtdemux_advance_sample (qtdemux, stream);
6254
6255 beach:
6256   return ret;
6257
6258   /* special cases */
6259 eos:
6260   {
6261     GST_DEBUG_OBJECT (qtdemux, "No samples left for any streams - EOS");
6262     ret = GST_FLOW_EOS;
6263     goto beach;
6264   }
6265 eos_stream:
6266   {
6267     GST_DEBUG_OBJECT (qtdemux, "No samples left for stream");
6268     /* EOS will be raised if all are EOS */
6269     ret = GST_FLOW_OK;
6270     goto beach;
6271   }
6272 }
6273
6274 static void
6275 gst_qtdemux_loop (GstPad * pad)
6276 {
6277   GstQTDemux *qtdemux;
6278   guint64 cur_offset;
6279   GstFlowReturn ret;
6280
6281   qtdemux = GST_QTDEMUX (gst_pad_get_parent (pad));
6282
6283   cur_offset = qtdemux->offset;
6284   GST_LOG_OBJECT (qtdemux, "loop at position %" G_GUINT64_FORMAT ", state %s",
6285       cur_offset, qt_demux_state_string (qtdemux->state));
6286
6287   switch (qtdemux->state) {
6288     case QTDEMUX_STATE_INITIAL:
6289     case QTDEMUX_STATE_HEADER:
6290       ret = gst_qtdemux_loop_state_header (qtdemux);
6291       break;
6292     case QTDEMUX_STATE_MOVIE:
6293       ret = gst_qtdemux_loop_state_movie (qtdemux);
6294       if (qtdemux->segment.rate < 0 && ret == GST_FLOW_EOS) {
6295         ret = gst_qtdemux_seek_to_previous_keyframe (qtdemux);
6296       }
6297       break;
6298     default:
6299       /* ouch */
6300       goto invalid_state;
6301   }
6302
6303   /* if something went wrong, pause */
6304   if (ret != GST_FLOW_OK)
6305     goto pause;
6306
6307 done:
6308   gst_object_unref (qtdemux);
6309   return;
6310
6311   /* ERRORS */
6312 invalid_state:
6313   {
6314     GST_ELEMENT_ERROR (qtdemux, STREAM, FAILED,
6315         (NULL), ("streaming stopped, invalid state"));
6316     gst_pad_pause_task (pad);
6317     gst_qtdemux_push_event (qtdemux, gst_event_new_eos ());
6318     goto done;
6319   }
6320 pause:
6321   {
6322     const gchar *reason = gst_flow_get_name (ret);
6323
6324     GST_LOG_OBJECT (qtdemux, "pausing task, reason %s", reason);
6325
6326     gst_pad_pause_task (pad);
6327
6328     /* fatal errors need special actions */
6329     /* check EOS */
6330     if (ret == GST_FLOW_EOS) {
6331       if (qtdemux->n_streams == 0) {
6332         /* we have no streams, post an error */
6333         gst_qtdemux_post_no_playable_stream_error (qtdemux);
6334       }
6335       if (qtdemux->segment.flags & GST_SEEK_FLAG_SEGMENT) {
6336         gint64 stop;
6337
6338         if ((stop = qtdemux->segment.stop) == -1)
6339           stop = qtdemux->segment.duration;
6340
6341         if (qtdemux->segment.rate >= 0) {
6342           GstMessage *message;
6343           GstEvent *event;
6344
6345           GST_LOG_OBJECT (qtdemux, "Sending segment done, at end of segment");
6346           message = gst_message_new_segment_done (GST_OBJECT_CAST (qtdemux),
6347               GST_FORMAT_TIME, stop);
6348           event = gst_event_new_segment_done (GST_FORMAT_TIME, stop);
6349           if (qtdemux->segment_seqnum != GST_SEQNUM_INVALID) {
6350             gst_message_set_seqnum (message, qtdemux->segment_seqnum);
6351             gst_event_set_seqnum (event, qtdemux->segment_seqnum);
6352           }
6353           gst_element_post_message (GST_ELEMENT_CAST (qtdemux), message);
6354           gst_qtdemux_push_event (qtdemux, event);
6355         } else {
6356           GstMessage *message;
6357           GstEvent *event;
6358
6359           /*  For Reverse Playback */
6360           GST_LOG_OBJECT (qtdemux, "Sending segment done, at start of segment");
6361           message = gst_message_new_segment_done (GST_OBJECT_CAST (qtdemux),
6362               GST_FORMAT_TIME, qtdemux->segment.start);
6363           event = gst_event_new_segment_done (GST_FORMAT_TIME,
6364               qtdemux->segment.start);
6365           if (qtdemux->segment_seqnum != GST_SEQNUM_INVALID) {
6366             gst_message_set_seqnum (message, qtdemux->segment_seqnum);
6367             gst_event_set_seqnum (event, qtdemux->segment_seqnum);
6368           }
6369           gst_element_post_message (GST_ELEMENT_CAST (qtdemux), message);
6370           gst_qtdemux_push_event (qtdemux, event);
6371         }
6372       } else {
6373         GstEvent *event;
6374
6375         GST_LOG_OBJECT (qtdemux, "Sending EOS at end of segment");
6376         event = gst_event_new_eos ();
6377         if (qtdemux->segment_seqnum != GST_SEQNUM_INVALID)
6378           gst_event_set_seqnum (event, qtdemux->segment_seqnum);
6379         gst_qtdemux_push_event (qtdemux, event);
6380       }
6381     } else if (ret == GST_FLOW_NOT_LINKED || ret < GST_FLOW_EOS) {
6382       GST_ELEMENT_FLOW_ERROR (qtdemux, ret);
6383       gst_qtdemux_push_event (qtdemux, gst_event_new_eos ());
6384     }
6385     goto done;
6386   }
6387 }
6388
6389 /*
6390  * has_next_entry
6391  *
6392  * Returns if there are samples to be played.
6393  */
6394 static gboolean
6395 has_next_entry (GstQTDemux * demux)
6396 {
6397   QtDemuxStream *stream;
6398   GList *iter;
6399
6400   GST_DEBUG_OBJECT (demux, "Checking if there are samples not played yet");
6401
6402   for (iter = demux->active_streams; iter; iter = g_list_next (iter)) {
6403     stream = QTDEMUX_STREAM (iter->data);
6404
6405     if (stream->sample_index == -1) {
6406       stream->sample_index = 0;
6407       stream->offset_in_sample = 0;
6408     }
6409
6410     if (stream->sample_index >= stream->n_samples) {
6411       GST_LOG_OBJECT (demux, "track-id %u samples exhausted", stream->track_id);
6412       continue;
6413     }
6414     GST_DEBUG_OBJECT (demux, "Found a sample");
6415     return TRUE;
6416   }
6417
6418   GST_DEBUG_OBJECT (demux, "There wasn't any next sample");
6419   return FALSE;
6420 }
6421
6422 /*
6423  * next_entry_size
6424  *
6425  * Returns the size of the first entry at the current offset.
6426  * If -1, there are none (which means EOS or empty file).
6427  */
6428 static guint64
6429 next_entry_size (GstQTDemux * demux)
6430 {
6431   QtDemuxStream *stream, *target_stream = NULL;
6432   guint64 smalloffs = (guint64) - 1;
6433   QtDemuxSample *sample;
6434   GList *iter;
6435
6436   GST_LOG_OBJECT (demux, "Finding entry at offset %" G_GUINT64_FORMAT,
6437       demux->offset);
6438
6439   for (iter = demux->active_streams; iter; iter = g_list_next (iter)) {
6440     stream = QTDEMUX_STREAM (iter->data);
6441
6442     if (stream->sample_index == -1) {
6443       stream->sample_index = 0;
6444       stream->offset_in_sample = 0;
6445     }
6446
6447     if (stream->sample_index >= stream->n_samples) {
6448       GST_LOG_OBJECT (demux, "track-id %u samples exhausted", stream->track_id);
6449       continue;
6450     }
6451
6452     if (!qtdemux_parse_samples (demux, stream, stream->sample_index)) {
6453       GST_LOG_OBJECT (demux, "Parsing of index %u from stbl atom failed!",
6454           stream->sample_index);
6455       return -1;
6456     }
6457
6458     sample = &stream->samples[stream->sample_index];
6459
6460     GST_LOG_OBJECT (demux,
6461         "Checking track-id %u (sample_index:%d / offset:%" G_GUINT64_FORMAT
6462         " / size:%" G_GUINT32_FORMAT ")", stream->track_id,
6463         stream->sample_index, sample->offset, sample->size);
6464
6465     if (((smalloffs == -1)
6466             || (sample->offset < smalloffs)) && (sample->size)) {
6467       smalloffs = sample->offset;
6468       target_stream = stream;
6469     }
6470   }
6471
6472   if (!target_stream)
6473     return -1;
6474
6475   GST_LOG_OBJECT (demux,
6476       "track-id %u offset %" G_GUINT64_FORMAT " demux->offset :%"
6477       G_GUINT64_FORMAT, target_stream->track_id, smalloffs, demux->offset);
6478
6479   stream = target_stream;
6480   sample = &stream->samples[stream->sample_index];
6481
6482   if (sample->offset >= demux->offset) {
6483     demux->todrop = sample->offset - demux->offset;
6484     return sample->size + demux->todrop;
6485   }
6486
6487   GST_DEBUG_OBJECT (demux,
6488       "There wasn't any entry at offset %" G_GUINT64_FORMAT, demux->offset);
6489   return -1;
6490 }
6491
6492 static void
6493 gst_qtdemux_post_progress (GstQTDemux * demux, gint num, gint denom)
6494 {
6495   gint perc = (gint) ((gdouble) num * 100.0 / (gdouble) denom);
6496
6497   gst_element_post_message (GST_ELEMENT_CAST (demux),
6498       gst_message_new_element (GST_OBJECT_CAST (demux),
6499           gst_structure_new ("progress", "percent", G_TYPE_INT, perc, NULL)));
6500 }
6501
6502 static gboolean
6503 qtdemux_seek_offset (GstQTDemux * demux, guint64 offset)
6504 {
6505   GstEvent *event;
6506   gboolean res = 0;
6507
6508   GST_DEBUG_OBJECT (demux, "Seeking to %" G_GUINT64_FORMAT, offset);
6509
6510   event =
6511       gst_event_new_seek (1.0, GST_FORMAT_BYTES,
6512       GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_ACCURATE, GST_SEEK_TYPE_SET, offset,
6513       GST_SEEK_TYPE_NONE, -1);
6514
6515   /* store seqnum to drop flush events, they don't need to reach downstream */
6516   demux->offset_seek_seqnum = gst_event_get_seqnum (event);
6517   res = gst_pad_push_event (demux->sinkpad, event);
6518   demux->offset_seek_seqnum = GST_SEQNUM_INVALID;
6519
6520   return res;
6521 }
6522
6523 /* check for seekable upstream, above and beyond a mere query */
6524 static void
6525 gst_qtdemux_check_seekability (GstQTDemux * demux)
6526 {
6527   GstQuery *query;
6528   gboolean seekable = FALSE;
6529   gint64 start = -1, stop = -1;
6530
6531   if (demux->upstream_size)
6532     return;
6533
6534   if (demux->upstream_format_is_time)
6535     return;
6536
6537   query = gst_query_new_seeking (GST_FORMAT_BYTES);
6538   if (!gst_pad_peer_query (demux->sinkpad, query)) {
6539     GST_DEBUG_OBJECT (demux, "seeking query failed");
6540     goto done;
6541   }
6542
6543   gst_query_parse_seeking (query, NULL, &seekable, &start, &stop);
6544
6545   /* try harder to query upstream size if we didn't get it the first time */
6546   if (seekable && stop == -1) {
6547     GST_DEBUG_OBJECT (demux, "doing duration query to fix up unset stop");
6548     gst_pad_peer_query_duration (demux->sinkpad, GST_FORMAT_BYTES, &stop);
6549   }
6550
6551   /* if upstream doesn't know the size, it's likely that it's not seekable in
6552    * practice even if it technically may be seekable */
6553   if (seekable && (start != 0 || stop <= start)) {
6554     GST_DEBUG_OBJECT (demux, "seekable but unknown start/stop -> disable");
6555     seekable = FALSE;
6556   }
6557
6558 done:
6559   gst_query_unref (query);
6560
6561   GST_DEBUG_OBJECT (demux, "seekable: %d (%" G_GUINT64_FORMAT " - %"
6562       G_GUINT64_FORMAT ")", seekable, start, stop);
6563   demux->upstream_seekable = seekable;
6564   demux->upstream_size = seekable ? stop : -1;
6565 }
6566
6567 static void
6568 gst_qtdemux_drop_data (GstQTDemux * demux, gint bytes)
6569 {
6570   g_return_if_fail (bytes <= demux->todrop);
6571
6572   GST_LOG_OBJECT (demux, "Dropping %d bytes", bytes);
6573   gst_adapter_flush (demux->adapter, bytes);
6574   demux->neededbytes -= bytes;
6575   demux->offset += bytes;
6576   demux->todrop -= bytes;
6577 }
6578
6579 /* PUSH-MODE only: Send a segment, if not done already. */
6580 static void
6581 gst_qtdemux_check_send_pending_segment (GstQTDemux * demux)
6582 {
6583   if (G_UNLIKELY (demux->need_segment)) {
6584     gint i;
6585     GList *iter;
6586
6587     if (!demux->upstream_format_is_time) {
6588       gst_qtdemux_map_and_push_segments (demux, &demux->segment);
6589     } else {
6590       GstEvent *segment_event;
6591       segment_event = gst_event_new_segment (&demux->segment);
6592       if (demux->segment_seqnum != GST_SEQNUM_INVALID)
6593         gst_event_set_seqnum (segment_event, demux->segment_seqnum);
6594       gst_qtdemux_push_event (demux, segment_event);
6595     }
6596
6597     demux->need_segment = FALSE;
6598
6599     /* clear to send tags on all streams */
6600     for (iter = demux->active_streams, i = 0; iter;
6601         iter = g_list_next (iter), i++) {
6602       QtDemuxStream *stream = QTDEMUX_STREAM (iter->data);
6603       gst_qtdemux_push_tags (demux, stream);
6604       if (CUR_STREAM (stream)->sparse) {
6605         GST_INFO_OBJECT (demux, "Sending gap event on stream %d", i);
6606         gst_pad_push_event (stream->pad,
6607             gst_event_new_gap (stream->segment.position, GST_CLOCK_TIME_NONE));
6608       }
6609     }
6610   }
6611 }
6612
6613 /* Used for push mode only. */
6614 static void
6615 gst_qtdemux_send_gap_for_segment (GstQTDemux * demux,
6616     QtDemuxStream * stream, gint segment_index, GstClockTime pos)
6617 {
6618   GstClockTime ts, dur;
6619
6620   ts = pos;
6621   dur =
6622       stream->segments[segment_index].duration - (pos -
6623       stream->segments[segment_index].time);
6624   stream->time_position += dur;
6625
6626   /* Only gaps with a duration of at least one second are propagated.
6627    * Same workaround as in pull mode.
6628    * (See 2e45926a96ec5298c6ef29bf912e5e6a06dc3e0e) */
6629   if (dur >= GST_SECOND) {
6630     GstEvent *gap;
6631     gap = gst_event_new_gap (ts, dur);
6632
6633     GST_DEBUG_OBJECT (stream->pad, "Pushing gap for empty "
6634         "segment: %" GST_PTR_FORMAT, gap);
6635     gst_pad_push_event (stream->pad, gap);
6636   }
6637 }
6638
6639 static GstFlowReturn
6640 gst_qtdemux_chain (GstPad * sinkpad, GstObject * parent, GstBuffer * inbuf)
6641 {
6642   GstQTDemux *demux;
6643
6644   demux = GST_QTDEMUX (parent);
6645
6646   GST_DEBUG_OBJECT (demux,
6647       "Received buffer pts:%" GST_TIME_FORMAT " dts:%" GST_TIME_FORMAT
6648       " offset:%" G_GUINT64_FORMAT " size:%" G_GSIZE_FORMAT " demux offset:%"
6649       G_GUINT64_FORMAT, GST_TIME_ARGS (GST_BUFFER_PTS (inbuf)),
6650       GST_TIME_ARGS (GST_BUFFER_DTS (inbuf)), GST_BUFFER_OFFSET (inbuf),
6651       gst_buffer_get_size (inbuf), demux->offset);
6652
6653   if (GST_BUFFER_FLAG_IS_SET (inbuf, GST_BUFFER_FLAG_DISCONT)) {
6654     gboolean is_gap_input = FALSE;
6655     GList *iter;
6656
6657     GST_DEBUG_OBJECT (demux, "Got DISCONT, marking all streams as DISCONT");
6658
6659     for (iter = demux->active_streams; iter; iter = g_list_next (iter)) {
6660       QTDEMUX_STREAM (iter->data)->discont = TRUE;
6661     }
6662
6663     /* Check if we can land back on our feet in the case where upstream is
6664      * handling the seeking/pushing of samples with gaps in between (like
6665      * in the case of trick-mode DASH for example) */
6666     if (demux->upstream_format_is_time
6667         && GST_BUFFER_OFFSET (inbuf) != GST_BUFFER_OFFSET_NONE) {
6668       for (iter = demux->active_streams; iter; iter = g_list_next (iter)) {
6669         guint32 res;
6670         QtDemuxStream *stream = QTDEMUX_STREAM (iter->data);
6671         GST_LOG_OBJECT (demux,
6672             "track-id #%u , checking if offset %" G_GUINT64_FORMAT
6673             " is a sample start", stream->track_id, GST_BUFFER_OFFSET (inbuf));
6674         res =
6675             gst_qtdemux_find_index_for_given_media_offset_linear (demux,
6676             stream, GST_BUFFER_OFFSET (inbuf));
6677         if (res != -1) {
6678           QtDemuxSample *sample = &stream->samples[res];
6679           GST_LOG_OBJECT (demux,
6680               "Checking if sample %d from track-id %u is valid (offset:%"
6681               G_GUINT64_FORMAT " size:%" G_GUINT32_FORMAT ")", res,
6682               stream->track_id, sample->offset, sample->size);
6683           if (sample->offset == GST_BUFFER_OFFSET (inbuf)) {
6684             GST_LOG_OBJECT (demux,
6685                 "new buffer corresponds to a valid sample : %" G_GUINT32_FORMAT,
6686                 res);
6687             is_gap_input = TRUE;
6688             /* We can go back to standard playback mode */
6689             demux->state = QTDEMUX_STATE_MOVIE;
6690             /* Remember which sample this stream is at */
6691             stream->sample_index = res;
6692             /* Finally update all push-based values to the expected values */
6693             demux->neededbytes = stream->samples[res].size;
6694             demux->offset = GST_BUFFER_OFFSET (inbuf);
6695             demux->mdatleft =
6696                 demux->mdatsize - demux->offset + demux->mdatoffset;
6697             demux->todrop = 0;
6698           }
6699         }
6700       }
6701       if (!is_gap_input) {
6702         GST_DEBUG_OBJECT (demux, "Resetting, actual DISCONT");
6703         /* Reset state if it's a real discont */
6704         demux->neededbytes = 16;
6705         demux->state = QTDEMUX_STATE_INITIAL;
6706         demux->offset = GST_BUFFER_OFFSET (inbuf);
6707         gst_adapter_clear (demux->adapter);
6708       }
6709     }
6710     /* Reverse fragmented playback, need to flush all we have before
6711      * consuming a new fragment.
6712      * The samples array have the timestamps calculated by accumulating the
6713      * durations but this won't work for reverse playback of fragments as
6714      * the timestamps of a subsequent fragment should be smaller than the
6715      * previously received one. */
6716     if (!is_gap_input && demux->fragmented && demux->segment.rate < 0) {
6717       gst_qtdemux_process_adapter (demux, TRUE);
6718       g_list_foreach (demux->active_streams,
6719           (GFunc) gst_qtdemux_stream_flush_samples_data, NULL);
6720     }
6721   }
6722
6723   gst_adapter_push (demux->adapter, inbuf);
6724
6725   GST_DEBUG_OBJECT (demux,
6726       "pushing in inbuf %p, neededbytes:%u, available:%" G_GSIZE_FORMAT, inbuf,
6727       demux->neededbytes, gst_adapter_available (demux->adapter));
6728
6729   return gst_qtdemux_process_adapter (demux, FALSE);
6730 }
6731
6732 static GstFlowReturn
6733 gst_qtdemux_process_adapter (GstQTDemux * demux, gboolean force)
6734 {
6735   GstFlowReturn ret = GST_FLOW_OK;
6736
6737   /* we never really mean to buffer that much */
6738   if (demux->neededbytes == -1) {
6739     goto eos;
6740   }
6741
6742   while (((gst_adapter_available (demux->adapter)) >= demux->neededbytes) &&
6743       (ret == GST_FLOW_OK || (ret == GST_FLOW_NOT_LINKED && force))) {
6744
6745 #ifndef GST_DISABLE_GST_DEBUG
6746     {
6747       guint64 discont_offset, distance_from_discont;
6748
6749       discont_offset = gst_adapter_offset_at_discont (demux->adapter);
6750       distance_from_discont =
6751           gst_adapter_distance_from_discont (demux->adapter);
6752
6753       GST_DEBUG_OBJECT (demux,
6754           "state:%s , demux->neededbytes:%d, demux->offset:%" G_GUINT64_FORMAT
6755           " adapter offset :%" G_GUINT64_FORMAT " (+ %" G_GUINT64_FORMAT
6756           " bytes)", qt_demux_state_string (demux->state), demux->neededbytes,
6757           demux->offset, discont_offset, distance_from_discont);
6758     }
6759 #endif
6760
6761     switch (demux->state) {
6762       case QTDEMUX_STATE_INITIAL:{
6763         const guint8 *data;
6764         guint32 fourcc;
6765         guint64 size;
6766
6767         gst_qtdemux_check_seekability (demux);
6768
6769         data = gst_adapter_map (demux->adapter, demux->neededbytes);
6770
6771         /* get fourcc/length, set neededbytes */
6772         extract_initial_length_and_fourcc ((guint8 *) data, demux->neededbytes,
6773             &size, &fourcc);
6774         gst_adapter_unmap (demux->adapter);
6775         data = NULL;
6776         GST_DEBUG_OBJECT (demux, "Peeking found [%" GST_FOURCC_FORMAT "] "
6777             "size: %" G_GUINT64_FORMAT, GST_FOURCC_ARGS (fourcc), size);
6778         if (size == 0) {
6779           GST_ELEMENT_ERROR (demux, STREAM, DEMUX,
6780               (_("This file is invalid and cannot be played.")),
6781               ("initial atom '%" GST_FOURCC_FORMAT "' has empty length",
6782                   GST_FOURCC_ARGS (fourcc)));
6783           ret = GST_FLOW_ERROR;
6784           break;
6785         }
6786         if (fourcc == FOURCC_mdat) {
6787           gint next_entry = next_entry_size (demux);
6788           if (demux->n_streams > 0 && (next_entry != -1 || !demux->fragmented)) {
6789             /* we have the headers, start playback */
6790             demux->state = QTDEMUX_STATE_MOVIE;
6791             demux->neededbytes = next_entry;
6792             demux->mdatleft = size;
6793             demux->mdatsize = demux->mdatleft;
6794           } else {
6795             /* no headers yet, try to get them */
6796             guint bs;
6797             gboolean res;
6798             guint64 old, target;
6799
6800           buffer_data:
6801             old = demux->offset;
6802             target = old + size;
6803
6804             /* try to jump over the atom with a seek */
6805             /* only bother if it seems worth doing so,
6806              * and avoids possible upstream/server problems */
6807             if (demux->upstream_seekable &&
6808                 demux->upstream_size > 4 * (1 << 20)) {
6809               res = qtdemux_seek_offset (demux, target);
6810             } else {
6811               GST_DEBUG_OBJECT (demux, "skipping seek");
6812               res = FALSE;
6813             }
6814
6815             if (res) {
6816               GST_DEBUG_OBJECT (demux, "seek success");
6817               /* remember the offset fo the first mdat so we can seek back to it
6818                * after we have the headers */
6819               if (fourcc == FOURCC_mdat && demux->first_mdat == -1) {
6820                 demux->first_mdat = old;
6821                 GST_DEBUG_OBJECT (demux, "first mdat at %" G_GUINT64_FORMAT,
6822                     demux->first_mdat);
6823               }
6824               /* seek worked, continue reading */
6825               demux->offset = target;
6826               demux->neededbytes = 16;
6827               demux->state = QTDEMUX_STATE_INITIAL;
6828             } else {
6829               /* seek failed, need to buffer */
6830               demux->offset = old;
6831               GST_DEBUG_OBJECT (demux, "seek failed/skipped");
6832               /* there may be multiple mdat (or alike) buffers */
6833               /* sanity check */
6834               if (demux->mdatbuffer)
6835                 bs = gst_buffer_get_size (demux->mdatbuffer);
6836               else
6837                 bs = 0;
6838               if (size + bs > 10 * (1 << 20))
6839                 goto no_moov;
6840               demux->state = QTDEMUX_STATE_BUFFER_MDAT;
6841               demux->neededbytes = size;
6842               if (!demux->mdatbuffer)
6843                 demux->mdatoffset = demux->offset;
6844             }
6845           }
6846         } else if (G_UNLIKELY (size > QTDEMUX_MAX_ATOM_SIZE)) {
6847           GST_ELEMENT_ERROR (demux, STREAM, DEMUX,
6848               (_("This file is invalid and cannot be played.")),
6849               ("atom %" GST_FOURCC_FORMAT " has bogus size %" G_GUINT64_FORMAT,
6850                   GST_FOURCC_ARGS (fourcc), size));
6851           ret = GST_FLOW_ERROR;
6852           break;
6853         } else {
6854           /* this means we already started buffering and still no moov header,
6855            * let's continue buffering everything till we get moov */
6856           if (demux->mdatbuffer && !(fourcc == FOURCC_moov
6857                   || fourcc == FOURCC_moof))
6858             goto buffer_data;
6859           demux->neededbytes = size;
6860           demux->state = QTDEMUX_STATE_HEADER;
6861         }
6862         break;
6863       }
6864       case QTDEMUX_STATE_HEADER:{
6865         const guint8 *data;
6866         guint32 fourcc;
6867
6868         GST_DEBUG_OBJECT (demux, "In header");
6869
6870         data = gst_adapter_map (demux->adapter, demux->neededbytes);
6871
6872         /* parse the header */
6873         extract_initial_length_and_fourcc (data, demux->neededbytes, NULL,
6874             &fourcc);
6875         if (fourcc == FOURCC_moov) {
6876           /* in usual fragmented setup we could try to scan for more
6877            * and end up at the the moov (after mdat) again */
6878           if (demux->got_moov && demux->n_streams > 0 &&
6879               (!demux->fragmented
6880                   || demux->last_moov_offset == demux->offset)) {
6881             GST_DEBUG_OBJECT (demux,
6882                 "Skipping moov atom as we have (this) one already");
6883           } else {
6884             GST_DEBUG_OBJECT (demux, "Parsing [moov]");
6885
6886             if (demux->got_moov && demux->fragmented) {
6887               GST_DEBUG_OBJECT (demux,
6888                   "Got a second moov, clean up data from old one");
6889               if (demux->moov_node_compressed) {
6890                 g_node_destroy (demux->moov_node_compressed);
6891                 if (demux->moov_node)
6892                   g_free (demux->moov_node->data);
6893               }
6894               demux->moov_node_compressed = NULL;
6895               if (demux->moov_node)
6896                 g_node_destroy (demux->moov_node);
6897               demux->moov_node = NULL;
6898             }
6899
6900             demux->last_moov_offset = demux->offset;
6901
6902             /* Update streams with new moov */
6903             demux->old_streams =
6904                 g_list_concat (demux->old_streams, demux->active_streams);
6905             demux->active_streams = NULL;
6906
6907             qtdemux_parse_moov (demux, data, demux->neededbytes);
6908             qtdemux_node_dump (demux, demux->moov_node);
6909             qtdemux_parse_tree (demux);
6910             qtdemux_prepare_streams (demux);
6911             QTDEMUX_EXPOSE_LOCK (demux);
6912             qtdemux_expose_streams (demux);
6913             QTDEMUX_EXPOSE_UNLOCK (demux);
6914
6915             demux->got_moov = TRUE;
6916
6917             gst_qtdemux_check_send_pending_segment (demux);
6918
6919             if (demux->moov_node_compressed) {
6920               g_node_destroy (demux->moov_node_compressed);
6921               g_free (demux->moov_node->data);
6922             }
6923             demux->moov_node_compressed = NULL;
6924             g_node_destroy (demux->moov_node);
6925             demux->moov_node = NULL;
6926             GST_DEBUG_OBJECT (demux, "Finished parsing the header");
6927           }
6928         } else if (fourcc == FOURCC_moof) {
6929           if ((demux->got_moov || demux->media_caps) && demux->fragmented) {
6930             guint64 dist = 0;
6931             GstClockTime prev_pts;
6932             guint64 prev_offset;
6933             guint64 adapter_discont_offset, adapter_discont_dist;
6934
6935             GST_DEBUG_OBJECT (demux, "Parsing [moof]");
6936
6937             /*
6938              * The timestamp of the moof buffer is relevant as some scenarios
6939              * won't have the initial timestamp in the atoms. Whenever a new
6940              * buffer has started, we get that buffer's PTS and use it as a base
6941              * timestamp for the trun entries.
6942              *
6943              * To keep track of the current buffer timestamp and starting point
6944              * we use gst_adapter_prev_pts that gives us the PTS and the distance
6945              * from the beggining of the buffer, with the distance and demux->offset
6946              * we know if it is still the same buffer or not.
6947              */
6948             prev_pts = gst_adapter_prev_pts (demux->adapter, &dist);
6949             prev_offset = demux->offset - dist;
6950             if (demux->fragment_start_offset == -1
6951                 || prev_offset > demux->fragment_start_offset) {
6952               demux->fragment_start_offset = prev_offset;
6953               demux->fragment_start = prev_pts;
6954               GST_DEBUG_OBJECT (demux,
6955                   "New fragment start found at: %" G_GUINT64_FORMAT " : %"
6956                   GST_TIME_FORMAT, demux->fragment_start_offset,
6957                   GST_TIME_ARGS (demux->fragment_start));
6958             }
6959
6960             /* We can't use prev_offset() here because this would require
6961              * upstream to set consistent and correct offsets on all buffers
6962              * since the discont. Nothing ever did that in the past and we
6963              * would break backwards compatibility here then.
6964              * Instead take the offset we had at the last discont and count
6965              * the bytes from there. This works with old code as there would
6966              * be no discont between moov and moof, and also works with
6967              * adaptivedemux which correctly sets offset and will set the
6968              * DISCONT flag accordingly when needed.
6969              *
6970              * We also only do this for upstream TIME segments as otherwise
6971              * there are potential backwards compatibility problems with
6972              * seeking in PUSH mode and upstream providing inconsistent
6973              * timestamps. */
6974             adapter_discont_offset =
6975                 gst_adapter_offset_at_discont (demux->adapter);
6976             adapter_discont_dist =
6977                 gst_adapter_distance_from_discont (demux->adapter);
6978
6979             GST_DEBUG_OBJECT (demux,
6980                 "demux offset %" G_GUINT64_FORMAT " adapter offset %"
6981                 G_GUINT64_FORMAT " (+ %" G_GUINT64_FORMAT " bytes)",
6982                 demux->offset, adapter_discont_offset, adapter_discont_dist);
6983
6984             if (demux->upstream_format_is_time) {
6985               demux->moof_offset = adapter_discont_offset;
6986               if (demux->moof_offset != GST_BUFFER_OFFSET_NONE)
6987                 demux->moof_offset += adapter_discont_dist;
6988               if (demux->moof_offset == GST_BUFFER_OFFSET_NONE)
6989                 demux->moof_offset = demux->offset;
6990             } else {
6991               demux->moof_offset = demux->offset;
6992             }
6993
6994             if (!qtdemux_parse_moof (demux, data, demux->neededbytes,
6995                     demux->moof_offset, NULL)) {
6996               gst_adapter_unmap (demux->adapter);
6997               ret = GST_FLOW_ERROR;
6998               goto done;
6999             }
7000
7001             /* in MSS we need to expose the pads after the first moof as we won't get a moov */
7002             if (demux->mss_mode && !demux->exposed) {
7003               QTDEMUX_EXPOSE_LOCK (demux);
7004               qtdemux_expose_streams (demux);
7005               QTDEMUX_EXPOSE_UNLOCK (demux);
7006             }
7007
7008             gst_qtdemux_check_send_pending_segment (demux);
7009           } else {
7010             GST_DEBUG_OBJECT (demux, "Discarding [moof]");
7011           }
7012         } else if (fourcc == FOURCC_ftyp) {
7013           GST_DEBUG_OBJECT (demux, "Parsing [ftyp]");
7014           qtdemux_parse_ftyp (demux, data, demux->neededbytes);
7015         } else if (fourcc == FOURCC_uuid) {
7016           GST_DEBUG_OBJECT (demux, "Parsing [uuid]");
7017           qtdemux_parse_uuid (demux, data, demux->neededbytes);
7018         } else if (fourcc == FOURCC_sidx) {
7019           GST_DEBUG_OBJECT (demux, "Parsing [sidx]");
7020           qtdemux_parse_sidx (demux, data, demux->neededbytes);
7021         } else {
7022           switch (fourcc) {
7023             case FOURCC_styp:
7024               /* [styp] is like a [ftyp], but in fragment header. We ignore it for now
7025                * FALLTHROUGH */
7026             case FOURCC_skip:
7027             case FOURCC_free:
7028               /* [free] and [skip] are padding atoms */
7029               GST_DEBUG_OBJECT (demux,
7030                   "Skipping fourcc while parsing header : %" GST_FOURCC_FORMAT,
7031                   GST_FOURCC_ARGS (fourcc));
7032               break;
7033             default:
7034               GST_WARNING_OBJECT (demux,
7035                   "Unknown fourcc while parsing header : %" GST_FOURCC_FORMAT,
7036                   GST_FOURCC_ARGS (fourcc));
7037               /* Let's jump that one and go back to initial state */
7038               break;
7039           }
7040         }
7041         gst_adapter_unmap (demux->adapter);
7042         data = NULL;
7043
7044         if (demux->mdatbuffer && demux->n_streams) {
7045           gsize remaining_data_size = 0;
7046
7047           /* the mdat was before the header */
7048           GST_DEBUG_OBJECT (demux, "We have n_streams:%d and mdatbuffer:%p",
7049               demux->n_streams, demux->mdatbuffer);
7050           /* restore our adapter/offset view of things with upstream;
7051            * put preceding buffered data ahead of current moov data.
7052            * This should also handle evil mdat, moov, mdat cases and alike */
7053           gst_adapter_flush (demux->adapter, demux->neededbytes);
7054
7055           /* Store any remaining data after the mdat for later usage */
7056           remaining_data_size = gst_adapter_available (demux->adapter);
7057           if (remaining_data_size > 0) {
7058             g_assert (demux->restoredata_buffer == NULL);
7059             demux->restoredata_buffer =
7060                 gst_adapter_take_buffer (demux->adapter, remaining_data_size);
7061             demux->restoredata_offset = demux->offset + demux->neededbytes;
7062             GST_DEBUG_OBJECT (demux,
7063                 "Stored %" G_GSIZE_FORMAT " post mdat bytes at offset %"
7064                 G_GUINT64_FORMAT, remaining_data_size,
7065                 demux->restoredata_offset);
7066           }
7067
7068           gst_adapter_push (demux->adapter, demux->mdatbuffer);
7069           demux->mdatbuffer = NULL;
7070           demux->offset = demux->mdatoffset;
7071           demux->neededbytes = next_entry_size (demux);
7072           demux->state = QTDEMUX_STATE_MOVIE;
7073           demux->mdatleft = gst_adapter_available (demux->adapter);
7074           demux->mdatsize = demux->mdatleft;
7075         } else {
7076           GST_DEBUG_OBJECT (demux, "Carrying on normally");
7077           gst_adapter_flush (demux->adapter, demux->neededbytes);
7078
7079           /* only go back to the mdat if there are samples to play */
7080           if (demux->got_moov && demux->first_mdat != -1
7081               && has_next_entry (demux)) {
7082             gboolean res;
7083
7084             /* we need to seek back */
7085             res = qtdemux_seek_offset (demux, demux->first_mdat);
7086             if (res) {
7087               demux->offset = demux->first_mdat;
7088             } else {
7089               GST_DEBUG_OBJECT (demux, "Seek back failed");
7090             }
7091           } else {
7092             demux->offset += demux->neededbytes;
7093           }
7094           demux->neededbytes = 16;
7095           demux->state = QTDEMUX_STATE_INITIAL;
7096         }
7097
7098         break;
7099       }
7100       case QTDEMUX_STATE_BUFFER_MDAT:{
7101         GstBuffer *buf;
7102         guint8 fourcc[4];
7103
7104         GST_DEBUG_OBJECT (demux, "Got our buffer at offset %" G_GUINT64_FORMAT,
7105             demux->offset);
7106         buf = gst_adapter_take_buffer (demux->adapter, demux->neededbytes);
7107         gst_buffer_extract (buf, 0, fourcc, 4);
7108         GST_DEBUG_OBJECT (demux, "mdatbuffer starts with %" GST_FOURCC_FORMAT,
7109             GST_FOURCC_ARGS (QT_FOURCC (fourcc)));
7110         if (demux->mdatbuffer)
7111           demux->mdatbuffer = gst_buffer_append (demux->mdatbuffer, buf);
7112         else
7113           demux->mdatbuffer = buf;
7114         demux->offset += demux->neededbytes;
7115         demux->neededbytes = 16;
7116         demux->state = QTDEMUX_STATE_INITIAL;
7117         gst_qtdemux_post_progress (demux, 1, 1);
7118
7119         break;
7120       }
7121       case QTDEMUX_STATE_MOVIE:{
7122         QtDemuxStream *stream = NULL;
7123         QtDemuxSample *sample;
7124         GstClockTime dts, pts, duration;
7125         gboolean keyframe;
7126         GList *iter;
7127
7128         GST_DEBUG_OBJECT (demux,
7129             "BEGIN // in MOVIE for offset %" G_GUINT64_FORMAT, demux->offset);
7130
7131         if (demux->fragmented) {
7132           GST_DEBUG_OBJECT (demux, "mdat remaining %" G_GUINT64_FORMAT,
7133               demux->mdatleft);
7134           if (G_LIKELY (demux->todrop < demux->mdatleft)) {
7135             /* if needed data starts within this atom,
7136              * then it should not exceed this atom */
7137             if (G_UNLIKELY (demux->neededbytes > demux->mdatleft)) {
7138               GST_ELEMENT_ERROR (demux, STREAM, DEMUX,
7139                   (_("This file is invalid and cannot be played.")),
7140                   ("sample data crosses atom boundary"));
7141               ret = GST_FLOW_ERROR;
7142               break;
7143             }
7144             demux->mdatleft -= demux->neededbytes;
7145           } else {
7146             GST_DEBUG_OBJECT (demux, "data atom emptied; resuming atom scan");
7147             /* so we are dropping more than left in this atom */
7148             gst_qtdemux_drop_data (demux, demux->mdatleft);
7149             demux->mdatleft = 0;
7150
7151             /* need to resume atom parsing so we do not miss any other pieces */
7152             demux->state = QTDEMUX_STATE_INITIAL;
7153             demux->neededbytes = 16;
7154
7155             /* check if there was any stored post mdat data from previous buffers */
7156             if (demux->restoredata_buffer) {
7157               g_assert (gst_adapter_available (demux->adapter) == 0);
7158
7159               gst_adapter_push (demux->adapter, demux->restoredata_buffer);
7160               demux->restoredata_buffer = NULL;
7161               demux->offset = demux->restoredata_offset;
7162             }
7163
7164             break;
7165           }
7166         }
7167
7168         if (demux->todrop) {
7169           if (demux->cenc_aux_info_offset > 0) {
7170             GstByteReader br;
7171             const guint8 *data;
7172
7173             GST_DEBUG_OBJECT (demux, "parsing cenc auxiliary info");
7174             data = gst_adapter_map (demux->adapter, demux->todrop);
7175             gst_byte_reader_init (&br, data + 8, demux->todrop);
7176             if (!qtdemux_parse_cenc_aux_info (demux,
7177                     QTDEMUX_FIRST_STREAM (demux), &br,
7178                     demux->cenc_aux_info_sizes, demux->cenc_aux_sample_count)) {
7179               GST_ERROR_OBJECT (demux, "failed to parse cenc auxiliary info");
7180               ret = GST_FLOW_ERROR;
7181               gst_adapter_unmap (demux->adapter);
7182               g_free (demux->cenc_aux_info_sizes);
7183               demux->cenc_aux_info_sizes = NULL;
7184               goto done;
7185             }
7186             demux->cenc_aux_info_offset = 0;
7187             g_free (demux->cenc_aux_info_sizes);
7188             demux->cenc_aux_info_sizes = NULL;
7189             gst_adapter_unmap (demux->adapter);
7190           }
7191           gst_qtdemux_drop_data (demux, demux->todrop);
7192         }
7193
7194         /* first buffer? */
7195         /* initial newsegment sent here after having added pads,
7196          * possible others in sink_event */
7197         gst_qtdemux_check_send_pending_segment (demux);
7198
7199         /* Figure out which stream this packet belongs to */
7200         for (iter = demux->active_streams; iter; iter = g_list_next (iter)) {
7201           stream = QTDEMUX_STREAM (iter->data);
7202           if (stream->sample_index >= stream->n_samples) {
7203             /* reset to be checked below G_UNLIKELY (stream == NULL) */
7204             stream = NULL;
7205             continue;
7206           }
7207           GST_LOG_OBJECT (demux,
7208               "Checking track-id %u (sample_index:%d / offset:%"
7209               G_GUINT64_FORMAT " / size:%d)", stream->track_id,
7210               stream->sample_index,
7211               stream->samples[stream->sample_index].offset,
7212               stream->samples[stream->sample_index].size);
7213
7214           if (stream->samples[stream->sample_index].offset == demux->offset)
7215             break;
7216         }
7217
7218         if (G_UNLIKELY (stream == NULL))
7219           goto unknown_stream;
7220
7221         gst_qtdemux_stream_check_and_change_stsd_index (demux, stream);
7222
7223         if (stream->new_caps) {
7224           gst_qtdemux_configure_stream (demux, stream);
7225         }
7226
7227         /* Put data in a buffer, set timestamps, caps, ... */
7228         sample = &stream->samples[stream->sample_index];
7229
7230         if (G_LIKELY (!(STREAM_IS_EOS (stream)))) {
7231           GST_DEBUG_OBJECT (demux, "stream : %" GST_FOURCC_FORMAT,
7232               GST_FOURCC_ARGS (CUR_STREAM (stream)->fourcc));
7233
7234           dts = QTSAMPLE_DTS (stream, sample);
7235           pts = QTSAMPLE_PTS (stream, sample);
7236           duration = QTSAMPLE_DUR_DTS (stream, sample, dts);
7237           keyframe = QTSAMPLE_KEYFRAME (stream, sample);
7238
7239           /* check for segment end */
7240           if (G_UNLIKELY (demux->segment.stop != -1
7241                   && demux->segment.stop <= pts && stream->on_keyframe)
7242               && !(demux->upstream_format_is_time && demux->segment.rate < 0)) {
7243             GST_DEBUG_OBJECT (demux, "we reached the end of our segment.");
7244             stream->time_position = GST_CLOCK_TIME_NONE;        /* this means EOS */
7245
7246             /* skip this data, stream is EOS */
7247             gst_adapter_flush (demux->adapter, demux->neededbytes);
7248             demux->offset += demux->neededbytes;
7249
7250             /* check if all streams are eos */
7251             ret = GST_FLOW_EOS;
7252             for (iter = demux->active_streams; iter; iter = g_list_next (iter)) {
7253               if (!STREAM_IS_EOS (QTDEMUX_STREAM (iter->data))) {
7254                 ret = GST_FLOW_OK;
7255                 break;
7256               }
7257             }
7258           } else {
7259             GstBuffer *outbuf;
7260
7261             outbuf =
7262                 gst_adapter_take_buffer (demux->adapter, demux->neededbytes);
7263
7264             /* FIXME: should either be an assert or a plain check */
7265             g_return_val_if_fail (outbuf != NULL, GST_FLOW_ERROR);
7266
7267             ret = gst_qtdemux_decorate_and_push_buffer (demux, stream, outbuf,
7268                 dts, pts, duration, keyframe, dts, demux->offset);
7269           }
7270
7271           /* combine flows */
7272           ret = gst_qtdemux_combine_flows (demux, stream, ret);
7273         } else {
7274           /* skip this data, stream is EOS */
7275           gst_adapter_flush (demux->adapter, demux->neededbytes);
7276         }
7277
7278         stream->sample_index++;
7279         stream->offset_in_sample = 0;
7280
7281         /* update current offset and figure out size of next buffer */
7282         GST_LOG_OBJECT (demux, "increasing offset %" G_GUINT64_FORMAT " by %u",
7283             demux->offset, demux->neededbytes);
7284         demux->offset += demux->neededbytes;
7285         GST_LOG_OBJECT (demux, "offset is now %" G_GUINT64_FORMAT,
7286             demux->offset);
7287
7288
7289         if (ret == GST_FLOW_EOS) {
7290           GST_DEBUG_OBJECT (demux, "All streams are EOS, signal upstream");
7291           demux->neededbytes = -1;
7292           goto eos;
7293         }
7294
7295         if ((demux->neededbytes = next_entry_size (demux)) == -1) {
7296           if (demux->fragmented) {
7297             GST_DEBUG_OBJECT (demux, "(temporarily) out of fragmented samples");
7298             /* there may be more to follow, only finish this atom */
7299             demux->todrop = demux->mdatleft;
7300             demux->neededbytes = demux->todrop;
7301             break;
7302           }
7303           goto eos;
7304         }
7305         if (ret != GST_FLOW_OK && ret != GST_FLOW_NOT_LINKED) {
7306           goto non_ok_unlinked_flow;
7307         }
7308         break;
7309       }
7310       default:
7311         goto invalid_state;
7312     }
7313   }
7314
7315   /* when buffering movie data, at least show user something is happening */
7316   if (ret == GST_FLOW_OK && demux->state == QTDEMUX_STATE_BUFFER_MDAT &&
7317       gst_adapter_available (demux->adapter) <= demux->neededbytes) {
7318     gst_qtdemux_post_progress (demux, gst_adapter_available (demux->adapter),
7319         demux->neededbytes);
7320   }
7321 done:
7322
7323   return ret;
7324
7325   /* ERRORS */
7326 non_ok_unlinked_flow:
7327   {
7328     GST_DEBUG_OBJECT (demux, "Stopping, combined return flow %s",
7329         gst_flow_get_name (ret));
7330     return ret;
7331   }
7332 unknown_stream:
7333   {
7334     GST_ELEMENT_ERROR (demux, STREAM, FAILED, (NULL), ("unknown stream found"));
7335     ret = GST_FLOW_ERROR;
7336     goto done;
7337   }
7338 eos:
7339   {
7340     GST_DEBUG_OBJECT (demux, "no next entry, EOS");
7341     ret = GST_FLOW_EOS;
7342     goto done;
7343   }
7344 invalid_state:
7345   {
7346     GST_ELEMENT_ERROR (demux, STREAM, FAILED,
7347         (NULL), ("qtdemuxer invalid state %d", demux->state));
7348     ret = GST_FLOW_ERROR;
7349     goto done;
7350   }
7351 no_moov:
7352   {
7353     GST_ELEMENT_ERROR (demux, STREAM, FAILED,
7354         (NULL), ("no 'moov' atom within the first 10 MB"));
7355     ret = GST_FLOW_ERROR;
7356     goto done;
7357   }
7358 }
7359
7360 static gboolean
7361 qtdemux_sink_activate (GstPad * sinkpad, GstObject * parent)
7362 {
7363   GstQuery *query;
7364   gboolean pull_mode;
7365
7366   query = gst_query_new_scheduling ();
7367
7368   if (!gst_pad_peer_query (sinkpad, query)) {
7369     gst_query_unref (query);
7370     goto activate_push;
7371   }
7372
7373   pull_mode = gst_query_has_scheduling_mode_with_flags (query,
7374       GST_PAD_MODE_PULL, GST_SCHEDULING_FLAG_SEEKABLE);
7375   gst_query_unref (query);
7376
7377   if (!pull_mode)
7378     goto activate_push;
7379
7380   GST_DEBUG_OBJECT (sinkpad, "activating pull");
7381   return gst_pad_activate_mode (sinkpad, GST_PAD_MODE_PULL, TRUE);
7382
7383 activate_push:
7384   {
7385     GST_DEBUG_OBJECT (sinkpad, "activating push");
7386     return gst_pad_activate_mode (sinkpad, GST_PAD_MODE_PUSH, TRUE);
7387   }
7388 }
7389
7390 static gboolean
7391 qtdemux_sink_activate_mode (GstPad * sinkpad, GstObject * parent,
7392     GstPadMode mode, gboolean active)
7393 {
7394   gboolean res;
7395   GstQTDemux *demux = GST_QTDEMUX (parent);
7396
7397   switch (mode) {
7398     case GST_PAD_MODE_PUSH:
7399       demux->pullbased = FALSE;
7400       res = TRUE;
7401       break;
7402     case GST_PAD_MODE_PULL:
7403       if (active) {
7404         demux->pullbased = TRUE;
7405         res = gst_pad_start_task (sinkpad, (GstTaskFunction) gst_qtdemux_loop,
7406             sinkpad, NULL);
7407       } else {
7408         res = gst_pad_stop_task (sinkpad);
7409       }
7410       break;
7411     default:
7412       res = FALSE;
7413       break;
7414   }
7415   return res;
7416 }
7417
7418 #ifdef HAVE_ZLIB
7419 static void *
7420 qtdemux_inflate (void *z_buffer, guint z_length, guint * length)
7421 {
7422   guint8 *buffer;
7423   z_stream z;
7424   int ret;
7425
7426   memset (&z, 0, sizeof (z));
7427   z.zalloc = NULL;
7428   z.zfree = NULL;
7429   z.opaque = NULL;
7430
7431   if ((ret = inflateInit (&z)) != Z_OK) {
7432     GST_ERROR ("inflateInit() returned %d", ret);
7433     return NULL;
7434   }
7435
7436   z.next_in = z_buffer;
7437   z.avail_in = z_length;
7438
7439   buffer = (guint8 *) g_malloc (*length);
7440   z.avail_out = *length;
7441   z.next_out = (Bytef *) buffer;
7442   do {
7443     ret = inflate (&z, Z_NO_FLUSH);
7444     if (ret == Z_STREAM_END) {
7445       break;
7446     } else if (ret != Z_OK) {
7447       GST_WARNING ("inflate() returned %d", ret);
7448       break;
7449     }
7450
7451     *length += 4096;
7452     buffer = (guint8 *) g_realloc (buffer, *length);
7453     z.next_out = (Bytef *) (buffer + z.total_out);
7454     z.avail_out += 4096;
7455   } while (z.avail_in > 0);
7456
7457   if (ret != Z_STREAM_END) {
7458     g_free (buffer);
7459     buffer = NULL;
7460     *length = 0;
7461   } else {
7462     *length = z.total_out;
7463   }
7464
7465   inflateEnd (&z);
7466
7467   return buffer;
7468 }
7469 #endif /* HAVE_ZLIB */
7470
7471 static gboolean
7472 qtdemux_parse_moov (GstQTDemux * qtdemux, const guint8 * buffer, guint length)
7473 {
7474   GNode *cmov;
7475
7476   qtdemux->moov_node = g_node_new ((guint8 *) buffer);
7477
7478   /* counts as header data */
7479   qtdemux->header_size += length;
7480
7481   GST_DEBUG_OBJECT (qtdemux, "parsing 'moov' atom");
7482   qtdemux_parse_node (qtdemux, qtdemux->moov_node, buffer, length);
7483
7484   cmov = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_cmov);
7485   if (cmov) {
7486     guint32 method;
7487     GNode *dcom;
7488     GNode *cmvd;
7489     guint32 dcom_len;
7490
7491     dcom = qtdemux_tree_get_child_by_type (cmov, FOURCC_dcom);
7492     cmvd = qtdemux_tree_get_child_by_type (cmov, FOURCC_cmvd);
7493     if (dcom == NULL || cmvd == NULL)
7494       goto invalid_compression;
7495
7496     dcom_len = QT_UINT32 (dcom->data);
7497     if (dcom_len < 12)
7498       goto invalid_compression;
7499
7500     method = QT_FOURCC ((guint8 *) dcom->data + 8);
7501     switch (method) {
7502 #ifdef HAVE_ZLIB
7503       case FOURCC_zlib:{
7504         guint uncompressed_length;
7505         guint compressed_length;
7506         guint8 *buf;
7507         guint32 cmvd_len;
7508
7509         cmvd_len = QT_UINT32 ((guint8 *) cmvd->data);
7510         if (cmvd_len < 12)
7511           goto invalid_compression;
7512
7513         uncompressed_length = QT_UINT32 ((guint8 *) cmvd->data + 8);
7514         compressed_length = cmvd_len - 12;
7515         GST_LOG ("length = %u", uncompressed_length);
7516
7517         buf =
7518             (guint8 *) qtdemux_inflate ((guint8 *) cmvd->data + 12,
7519             compressed_length, &uncompressed_length);
7520
7521         if (buf) {
7522           qtdemux->moov_node_compressed = qtdemux->moov_node;
7523           qtdemux->moov_node = g_node_new (buf);
7524
7525           qtdemux_parse_node (qtdemux, qtdemux->moov_node, buf,
7526               uncompressed_length);
7527         }
7528         break;
7529       }
7530 #endif /* HAVE_ZLIB */
7531       default:
7532         GST_WARNING_OBJECT (qtdemux, "unknown or unhandled header compression "
7533             "type %" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (method));
7534         break;
7535     }
7536   }
7537   return TRUE;
7538
7539   /* ERRORS */
7540 invalid_compression:
7541   {
7542     GST_ERROR_OBJECT (qtdemux, "invalid compressed header");
7543     return FALSE;
7544   }
7545 }
7546
7547 static gboolean
7548 qtdemux_parse_container (GstQTDemux * qtdemux, GNode * node, const guint8 * buf,
7549     const guint8 * end)
7550 {
7551   while (G_UNLIKELY (buf < end)) {
7552     GNode *child;
7553     guint32 len;
7554
7555     if (G_UNLIKELY (buf + 4 > end)) {
7556       GST_LOG_OBJECT (qtdemux, "buffer overrun");
7557       break;
7558     }
7559     len = QT_UINT32 (buf);
7560     if (G_UNLIKELY (len == 0)) {
7561       GST_LOG_OBJECT (qtdemux, "empty container");
7562       break;
7563     }
7564     if (G_UNLIKELY (len < 8)) {
7565       GST_WARNING_OBJECT (qtdemux, "length too short (%d < 8)", len);
7566       break;
7567     }
7568     if (G_UNLIKELY (len > (end - buf))) {
7569       GST_WARNING_OBJECT (qtdemux, "length too long (%d > %d)", len,
7570           (gint) (end - buf));
7571       break;
7572     }
7573
7574     child = g_node_new ((guint8 *) buf);
7575     g_node_append (node, child);
7576     GST_LOG_OBJECT (qtdemux, "adding new node of len %d", len);
7577     qtdemux_parse_node (qtdemux, child, buf, len);
7578
7579     buf += len;
7580   }
7581   return TRUE;
7582 }
7583
7584 static gboolean
7585 qtdemux_parse_theora_extension (GstQTDemux * qtdemux, QtDemuxStream * stream,
7586     GNode * xdxt)
7587 {
7588   int len = QT_UINT32 (xdxt->data);
7589   guint8 *buf = xdxt->data;
7590   guint8 *end = buf + len;
7591   GstBuffer *buffer;
7592
7593   /* skip size and type */
7594   buf += 8;
7595   end -= 8;
7596
7597   while (buf < end) {
7598     gint size;
7599     guint32 type;
7600
7601     size = QT_UINT32 (buf);
7602     type = QT_FOURCC (buf + 4);
7603
7604     GST_LOG_OBJECT (qtdemux, "%p %p", buf, end);
7605
7606     if (buf + size > end || size <= 0)
7607       break;
7608
7609     buf += 8;
7610     size -= 8;
7611
7612     GST_WARNING_OBJECT (qtdemux, "have cookie %" GST_FOURCC_FORMAT,
7613         GST_FOURCC_ARGS (type));
7614
7615     switch (type) {
7616       case FOURCC_tCtH:
7617         buffer = gst_buffer_new_and_alloc (size);
7618         gst_buffer_fill (buffer, 0, buf, size);
7619         stream->buffers = g_slist_append (stream->buffers, buffer);
7620         GST_LOG_OBJECT (qtdemux, "parsing theora header");
7621         break;
7622       case FOURCC_tCt_:
7623         buffer = gst_buffer_new_and_alloc (size);
7624         gst_buffer_fill (buffer, 0, buf, size);
7625         stream->buffers = g_slist_append (stream->buffers, buffer);
7626         GST_LOG_OBJECT (qtdemux, "parsing theora comment");
7627         break;
7628       case FOURCC_tCtC:
7629         buffer = gst_buffer_new_and_alloc (size);
7630         gst_buffer_fill (buffer, 0, buf, size);
7631         stream->buffers = g_slist_append (stream->buffers, buffer);
7632         GST_LOG_OBJECT (qtdemux, "parsing theora codebook");
7633         break;
7634       default:
7635         GST_WARNING_OBJECT (qtdemux,
7636             "unknown theora cookie %" GST_FOURCC_FORMAT,
7637             GST_FOURCC_ARGS (type));
7638         break;
7639     }
7640     buf += size;
7641   }
7642   return TRUE;
7643 }
7644
7645 static gboolean
7646 qtdemux_parse_node (GstQTDemux * qtdemux, GNode * node, const guint8 * buffer,
7647     guint length)
7648 {
7649   guint32 fourcc = 0;
7650   guint32 node_length = 0;
7651   const QtNodeType *type;
7652   const guint8 *end;
7653
7654   GST_LOG_OBJECT (qtdemux, "qtdemux_parse buffer %p length %u", buffer, length);
7655
7656   if (G_UNLIKELY (length < 8))
7657     goto not_enough_data;
7658
7659   node_length = QT_UINT32 (buffer);
7660   fourcc = QT_FOURCC (buffer + 4);
7661
7662   /* ignore empty nodes */
7663   if (G_UNLIKELY (fourcc == 0 || node_length == 8))
7664     return TRUE;
7665
7666   type = qtdemux_type_get (fourcc);
7667
7668   end = buffer + length;
7669
7670   GST_LOG_OBJECT (qtdemux,
7671       "parsing '%" GST_FOURCC_FORMAT "', length=%u, name '%s'",
7672       GST_FOURCC_ARGS (fourcc), node_length, type->name);
7673
7674   if (node_length > length)
7675     goto broken_atom_size;
7676
7677   if (type->flags & QT_FLAG_CONTAINER) {
7678     qtdemux_parse_container (qtdemux, node, buffer + 8, end);
7679   } else {
7680     switch (fourcc) {
7681       case FOURCC_stsd:
7682       {
7683         if (node_length < 20) {
7684           GST_LOG_OBJECT (qtdemux, "skipping small stsd box");
7685           break;
7686         }
7687         GST_DEBUG_OBJECT (qtdemux,
7688             "parsing stsd (sample table, sample description) atom");
7689         /* Skip over 8 byte atom hdr + 1 byte version, 3 bytes flags, 4 byte num_entries */
7690         qtdemux_parse_container (qtdemux, node, buffer + 16, end);
7691         break;
7692       }
7693       case FOURCC_mp4a:
7694       case FOURCC_alac:
7695       case FOURCC_fLaC:
7696       {
7697         guint32 version;
7698         guint32 offset;
7699         guint min_size;
7700
7701         /* also read alac (or whatever) in stead of mp4a in the following,
7702          * since a similar layout is used in other cases as well */
7703         if (fourcc == FOURCC_mp4a)
7704           min_size = 20;
7705         else if (fourcc == FOURCC_fLaC)
7706           min_size = 86;
7707         else
7708           min_size = 40;
7709
7710         /* There are two things we might encounter here: a true mp4a atom, and
7711            an mp4a entry in an stsd atom. The latter is what we're interested
7712            in, and it looks like an atom, but isn't really one. The true mp4a
7713            atom is short, so we detect it based on length here. */
7714         if (length < min_size) {
7715           GST_LOG_OBJECT (qtdemux, "skipping small %" GST_FOURCC_FORMAT " box",
7716               GST_FOURCC_ARGS (fourcc));
7717           break;
7718         }
7719
7720         /* 'version' here is the sound sample description version. Types 0 and
7721            1 are documented in the QTFF reference, but type 2 is not: it's
7722            described in Apple header files instead (struct SoundDescriptionV2
7723            in Movies.h) */
7724         version = QT_UINT16 (buffer + 16);
7725
7726         GST_DEBUG_OBJECT (qtdemux, "%" GST_FOURCC_FORMAT " version 0x%08x",
7727             GST_FOURCC_ARGS (fourcc), version);
7728
7729         /* parse any esds descriptors */
7730         switch (version) {
7731           case 0:
7732             offset = 0x24;
7733             break;
7734           case 1:
7735             offset = 0x34;
7736             break;
7737           case 2:
7738             offset = 0x48;
7739             break;
7740           default:
7741             GST_WARNING_OBJECT (qtdemux,
7742                 "unhandled %" GST_FOURCC_FORMAT " version 0x%08x",
7743                 GST_FOURCC_ARGS (fourcc), version);
7744             offset = 0;
7745             break;
7746         }
7747         if (offset)
7748           qtdemux_parse_container (qtdemux, node, buffer + offset, end);
7749         break;
7750       }
7751       case FOURCC_mp4v:
7752       case FOURCC_MP4V:
7753       case FOURCC_fmp4:
7754       case FOURCC_FMP4:
7755       case FOURCC_apcs:
7756       case FOURCC_apch:
7757       case FOURCC_apcn:
7758       case FOURCC_apco:
7759       case FOURCC_ap4h:
7760       case FOURCC_xvid:
7761       case FOURCC_XVID:
7762       case FOURCC_H264:
7763       case FOURCC_avc1:
7764       case FOURCC_avc3:
7765       case FOURCC_H265:
7766       case FOURCC_hvc1:
7767       case FOURCC_hev1:
7768       case FOURCC_mjp2:
7769       case FOURCC_encv:
7770       {
7771         guint32 version;
7772         guint32 str_len;
7773
7774         /* codec_data is contained inside these atoms, which all have
7775          * the same format. */
7776         /* video sample description size is 86 bytes without extension.
7777          * node_length have to be bigger than 86 bytes because video sample
7778          * description can include extenstions such as esds, fiel, glbl, etc. */
7779         if (node_length < 86) {
7780           GST_WARNING_OBJECT (qtdemux, "%" GST_FOURCC_FORMAT
7781               " sample description length too short (%u < 86)",
7782               GST_FOURCC_ARGS (fourcc), node_length);
7783           break;
7784         }
7785
7786         GST_DEBUG_OBJECT (qtdemux, "parsing in %" GST_FOURCC_FORMAT,
7787             GST_FOURCC_ARGS (fourcc));
7788
7789         /* version (2 bytes) : this is set to 0, unless a compressor has changed
7790          *              its data format.
7791          * revision level (2 bytes) : must be set to 0. */
7792         version = QT_UINT32 (buffer + 16);
7793         GST_DEBUG_OBJECT (qtdemux, "version %08x", version);
7794
7795         /* compressor name : PASCAL string and informative purposes
7796          * first byte : the number of bytes to be displayed.
7797          *              it has to be less than 32 because it is reserved
7798          *              space of 32 bytes total including itself. */
7799         str_len = QT_UINT8 (buffer + 50);
7800         if (str_len < 32)
7801           GST_DEBUG_OBJECT (qtdemux, "compressorname = %.*s", str_len,
7802               (char *) buffer + 51);
7803         else
7804           GST_WARNING_OBJECT (qtdemux,
7805               "compressorname length too big (%u > 31)", str_len);
7806
7807         GST_MEMDUMP_OBJECT (qtdemux, "video sample description", buffer,
7808             end - buffer);
7809         qtdemux_parse_container (qtdemux, node, buffer + 86, end);
7810         break;
7811       }
7812       case FOURCC_meta:
7813       {
7814         GST_DEBUG_OBJECT (qtdemux, "parsing meta atom");
7815
7816         /* You are reading this correctly. QTFF specifies that the
7817          * metadata atom is a short atom, whereas ISO BMFF specifies
7818          * it's a full atom. But since so many people are doing things
7819          * differently, we actually peek into the atom to see which
7820          * variant it is */
7821         if (length < 16) {
7822           GST_LOG_OBJECT (qtdemux, "skipping small %" GST_FOURCC_FORMAT " box",
7823               GST_FOURCC_ARGS (fourcc));
7824           break;
7825         }
7826         if (QT_FOURCC (buffer + 12) == FOURCC_hdlr) {
7827           /* Variant 1: What QTFF specifies. 'meta' is a short header which
7828            * starts with a 'hdlr' atom */
7829           qtdemux_parse_container (qtdemux, node, buffer + 8, end);
7830         } else if (QT_UINT32 (buffer + 8) == 0x00000000) {
7831           /* Variant 2: What ISO BMFF specifies. 'meta' is a _full_ atom
7832            * with version/flags both set to zero */
7833           qtdemux_parse_container (qtdemux, node, buffer + 12, end);
7834         } else
7835           GST_WARNING_OBJECT (qtdemux, "Unknown 'meta' atom format");
7836         break;
7837       }
7838       case FOURCC_mp4s:
7839       {
7840         GST_MEMDUMP_OBJECT (qtdemux, "mp4s", buffer, end - buffer);
7841         /* Skip 8 byte header, plus 8 byte version + flags + entry_count */
7842         qtdemux_parse_container (qtdemux, node, buffer + 16, end);
7843         break;
7844       }
7845       case FOURCC_XiTh:
7846       {
7847         guint32 version;
7848         guint32 offset;
7849
7850         if (length < 16) {
7851           GST_LOG_OBJECT (qtdemux, "skipping small %" GST_FOURCC_FORMAT " box",
7852               GST_FOURCC_ARGS (fourcc));
7853           break;
7854         }
7855
7856         version = QT_UINT32 (buffer + 12);
7857         GST_DEBUG_OBJECT (qtdemux, "parsing XiTh atom version 0x%08x", version);
7858
7859         switch (version) {
7860           case 0x00000001:
7861             offset = 0x62;
7862             break;
7863           default:
7864             GST_DEBUG_OBJECT (qtdemux, "unknown version 0x%08x", version);
7865             offset = 0;
7866             break;
7867         }
7868         if (offset) {
7869           if (length < offset) {
7870             GST_WARNING_OBJECT (qtdemux,
7871                 "skipping too small %" GST_FOURCC_FORMAT " box",
7872                 GST_FOURCC_ARGS (fourcc));
7873             break;
7874           }
7875           qtdemux_parse_container (qtdemux, node, buffer + offset, end);
7876         }
7877         break;
7878       }
7879       case FOURCC_in24:
7880       {
7881         qtdemux_parse_container (qtdemux, node, buffer + 0x34, end);
7882         break;
7883       }
7884       case FOURCC_uuid:
7885       {
7886         qtdemux_parse_uuid (qtdemux, buffer, end - buffer);
7887         break;
7888       }
7889       case FOURCC_enca:
7890       {
7891         qtdemux_parse_container (qtdemux, node, buffer + 36, end);
7892         break;
7893       }
7894       default:
7895         if (!strcmp (type->name, "unknown"))
7896           GST_MEMDUMP ("Unknown tag", buffer + 4, end - buffer - 4);
7897         break;
7898     }
7899   }
7900   GST_LOG_OBJECT (qtdemux, "parsed '%" GST_FOURCC_FORMAT "'",
7901       GST_FOURCC_ARGS (fourcc));
7902   return TRUE;
7903
7904 /* ERRORS */
7905 not_enough_data:
7906   {
7907     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
7908         (_("This file is corrupt and cannot be played.")),
7909         ("Not enough data for an atom header, got only %u bytes", length));
7910     return FALSE;
7911   }
7912 broken_atom_size:
7913   {
7914     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
7915         (_("This file is corrupt and cannot be played.")),
7916         ("Atom '%" GST_FOURCC_FORMAT "' has size of %u bytes, but we have only "
7917             "%u bytes available.", GST_FOURCC_ARGS (fourcc), node_length,
7918             length));
7919     return FALSE;
7920   }
7921 }
7922
7923 static GNode *
7924 qtdemux_tree_get_child_by_type (GNode * node, guint32 fourcc)
7925 {
7926   GNode *child;
7927   guint8 *buffer;
7928   guint32 child_fourcc;
7929
7930   for (child = g_node_first_child (node); child;
7931       child = g_node_next_sibling (child)) {
7932     buffer = (guint8 *) child->data;
7933
7934     child_fourcc = QT_FOURCC (buffer + 4);
7935
7936     if (G_UNLIKELY (child_fourcc == fourcc)) {
7937       return child;
7938     }
7939   }
7940   return NULL;
7941 }
7942
7943 static GNode *
7944 qtdemux_tree_get_child_by_type_full (GNode * node, guint32 fourcc,
7945     GstByteReader * parser)
7946 {
7947   GNode *child;
7948   guint8 *buffer;
7949   guint32 child_fourcc, child_len;
7950
7951   for (child = g_node_first_child (node); child;
7952       child = g_node_next_sibling (child)) {
7953     buffer = (guint8 *) child->data;
7954
7955     child_len = QT_UINT32 (buffer);
7956     child_fourcc = QT_FOURCC (buffer + 4);
7957
7958     if (G_UNLIKELY (child_fourcc == fourcc)) {
7959       if (G_UNLIKELY (child_len < (4 + 4)))
7960         return NULL;
7961       /* FIXME: must verify if atom length < parent atom length */
7962       gst_byte_reader_init (parser, buffer + (4 + 4), child_len - (4 + 4));
7963       return child;
7964     }
7965   }
7966   return NULL;
7967 }
7968
7969 static GNode *
7970 qtdemux_tree_get_child_by_index (GNode * node, guint index)
7971 {
7972   return g_node_nth_child (node, index);
7973 }
7974
7975 static GNode *
7976 qtdemux_tree_get_sibling_by_type_full (GNode * node, guint32 fourcc,
7977     GstByteReader * parser)
7978 {
7979   GNode *child;
7980   guint8 *buffer;
7981   guint32 child_fourcc, child_len;
7982
7983   for (child = g_node_next_sibling (node); child;
7984       child = g_node_next_sibling (child)) {
7985     buffer = (guint8 *) child->data;
7986
7987     child_fourcc = QT_FOURCC (buffer + 4);
7988
7989     if (child_fourcc == fourcc) {
7990       if (parser) {
7991         child_len = QT_UINT32 (buffer);
7992         if (G_UNLIKELY (child_len < (4 + 4)))
7993           return NULL;
7994         /* FIXME: must verify if atom length < parent atom length */
7995         gst_byte_reader_init (parser, buffer + (4 + 4), child_len - (4 + 4));
7996       }
7997       return child;
7998     }
7999   }
8000   return NULL;
8001 }
8002
8003 static GNode *
8004 qtdemux_tree_get_sibling_by_type (GNode * node, guint32 fourcc)
8005 {
8006   return qtdemux_tree_get_sibling_by_type_full (node, fourcc, NULL);
8007 }
8008
8009 static void
8010 qtdemux_do_allocation (GstQTDemux * qtdemux, QtDemuxStream * stream)
8011 {
8012 /* FIXME: This can only reliably work if demuxers have a
8013  * separate streaming thread per srcpad. This should be
8014  * done in a demuxer base class, which integrates parts
8015  * of multiqueue
8016  *
8017  * https://bugzilla.gnome.org/show_bug.cgi?id=701856
8018  */
8019 #if 0
8020   GstQuery *query;
8021
8022   query = gst_query_new_allocation (stream->caps, FALSE);
8023
8024   if (!gst_pad_peer_query (stream->pad, query)) {
8025     /* not a problem, just debug a little */
8026     GST_DEBUG_OBJECT (qtdemux, "peer ALLOCATION query failed");
8027   }
8028
8029   if (stream->allocator)
8030     gst_object_unref (stream->allocator);
8031
8032   if (gst_query_get_n_allocation_params (query) > 0) {
8033     /* try the allocator */
8034     gst_query_parse_nth_allocation_param (query, 0, &stream->allocator,
8035         &stream->params);
8036     stream->use_allocator = TRUE;
8037   } else {
8038     stream->allocator = NULL;
8039     gst_allocation_params_init (&stream->params);
8040     stream->use_allocator = FALSE;
8041   }
8042   gst_query_unref (query);
8043 #endif
8044 }
8045
8046 static gboolean
8047 pad_query (const GValue * item, GValue * value, gpointer user_data)
8048 {
8049   GstPad *pad = g_value_get_object (item);
8050   GstQuery *query = user_data;
8051   gboolean res;
8052
8053   res = gst_pad_peer_query (pad, query);
8054
8055   if (res) {
8056     g_value_set_boolean (value, TRUE);
8057     return FALSE;
8058   }
8059
8060   GST_INFO_OBJECT (pad, "pad peer query failed");
8061   return TRUE;
8062 }
8063
8064 static gboolean
8065 gst_qtdemux_run_query (GstElement * element, GstQuery * query,
8066     GstPadDirection direction)
8067 {
8068   GstIterator *it;
8069   GstIteratorFoldFunction func = pad_query;
8070   GValue res = { 0, };
8071
8072   g_value_init (&res, G_TYPE_BOOLEAN);
8073   g_value_set_boolean (&res, FALSE);
8074
8075   /* Ask neighbor */
8076   if (direction == GST_PAD_SRC)
8077     it = gst_element_iterate_src_pads (element);
8078   else
8079     it = gst_element_iterate_sink_pads (element);
8080
8081   while (gst_iterator_fold (it, func, &res, query) == GST_ITERATOR_RESYNC)
8082     gst_iterator_resync (it);
8083
8084   gst_iterator_free (it);
8085
8086   return g_value_get_boolean (&res);
8087 }
8088
8089 static void
8090 gst_qtdemux_request_protection_context (GstQTDemux * qtdemux,
8091     QtDemuxStream * stream)
8092 {
8093   GstQuery *query;
8094   GstContext *ctxt;
8095   GstElement *element = GST_ELEMENT (qtdemux);
8096   GstStructure *st;
8097   gchar **filtered_sys_ids;
8098   GValue event_list = G_VALUE_INIT;
8099   GList *walk;
8100
8101   /* 1. Check if we already have the context. */
8102   if (qtdemux->preferred_protection_system_id != NULL) {
8103     GST_LOG_OBJECT (element,
8104         "already have the protection context, no need to request it again");
8105     return;
8106   }
8107
8108   g_ptr_array_add (qtdemux->protection_system_ids, NULL);
8109   filtered_sys_ids = gst_protection_filter_systems_by_available_decryptors (
8110       (const gchar **) qtdemux->protection_system_ids->pdata);
8111
8112   g_ptr_array_remove_index (qtdemux->protection_system_ids,
8113       qtdemux->protection_system_ids->len - 1);
8114   GST_TRACE_OBJECT (qtdemux, "detected %u protection systems, we have "
8115       "decryptors for %u of them, running context request",
8116       qtdemux->protection_system_ids->len, g_strv_length (filtered_sys_ids));
8117
8118   if (stream->protection_scheme_event_queue.length) {
8119     GST_TRACE_OBJECT (qtdemux, "using stream event queue, length %u",
8120         stream->protection_scheme_event_queue.length);
8121     walk = stream->protection_scheme_event_queue.tail;
8122   } else {
8123     GST_TRACE_OBJECT (qtdemux, "using demuxer event queue, length %u",
8124         qtdemux->protection_event_queue.length);
8125     walk = qtdemux->protection_event_queue.tail;
8126   }
8127
8128   g_value_init (&event_list, GST_TYPE_LIST);
8129   for (; walk; walk = g_list_previous (walk)) {
8130     GValue *event_value = g_new0 (GValue, 1);
8131     g_value_init (event_value, GST_TYPE_EVENT);
8132     g_value_set_boxed (event_value, walk->data);
8133     gst_value_list_append_and_take_value (&event_list, event_value);
8134   }
8135
8136   /*  2a) Query downstream with GST_QUERY_CONTEXT for the context and
8137    *      check if downstream already has a context of the specific type
8138    *  2b) Query upstream as above.
8139    */
8140   query = gst_query_new_context ("drm-preferred-decryption-system-id");
8141   st = gst_query_writable_structure (query);
8142   gst_structure_set (st, "track-id", G_TYPE_UINT, stream->track_id,
8143       "available-stream-encryption-systems", G_TYPE_STRV, filtered_sys_ids,
8144       NULL);
8145   gst_structure_set_value (st, "stream-encryption-events", &event_list);
8146   if (gst_qtdemux_run_query (element, query, GST_PAD_SRC)) {
8147     gst_query_parse_context (query, &ctxt);
8148     GST_INFO_OBJECT (element, "found context (%p) in downstream query", ctxt);
8149     gst_element_set_context (element, ctxt);
8150   } else if (gst_qtdemux_run_query (element, query, GST_PAD_SINK)) {
8151     gst_query_parse_context (query, &ctxt);
8152     GST_INFO_OBJECT (element, "found context (%p) in upstream query", ctxt);
8153     gst_element_set_context (element, ctxt);
8154   } else {
8155     /* 3) Post a GST_MESSAGE_NEED_CONTEXT message on the bus with
8156      *    the required context type and afterwards check if a
8157      *    usable context was set now as in 1). The message could
8158      *    be handled by the parent bins of the element and the
8159      *    application.
8160      */
8161     GstMessage *msg;
8162
8163     GST_INFO_OBJECT (element, "posting need context message");
8164     msg = gst_message_new_need_context (GST_OBJECT_CAST (element),
8165         "drm-preferred-decryption-system-id");
8166     st = (GstStructure *) gst_message_get_structure (msg);
8167     gst_structure_set (st, "track-id", G_TYPE_UINT, stream->track_id,
8168         "available-stream-encryption-systems", G_TYPE_STRV, filtered_sys_ids,
8169         NULL);
8170
8171     gst_structure_set_value (st, "stream-encryption-events", &event_list);
8172     gst_element_post_message (element, msg);
8173   }
8174
8175   g_strfreev (filtered_sys_ids);
8176   g_value_unset (&event_list);
8177   gst_query_unref (query);
8178 }
8179
8180 static gboolean
8181 gst_qtdemux_configure_protected_caps (GstQTDemux * qtdemux,
8182     QtDemuxStream * stream)
8183 {
8184   GstStructure *s;
8185   const gchar *selected_system = NULL;
8186
8187   g_return_val_if_fail (qtdemux != NULL, FALSE);
8188   g_return_val_if_fail (stream != NULL, FALSE);
8189   g_return_val_if_fail (gst_caps_get_size (CUR_STREAM (stream)->caps) == 1,
8190       FALSE);
8191
8192   if (stream->protection_scheme_type != FOURCC_cenc) {
8193     GST_ERROR_OBJECT (qtdemux,
8194         "unsupported protection scheme: %" GST_FOURCC_FORMAT,
8195         GST_FOURCC_ARGS (stream->protection_scheme_type));
8196     return FALSE;
8197   }
8198   if (qtdemux->protection_system_ids == NULL) {
8199     GST_ERROR_OBJECT (qtdemux, "stream is protected using cenc, but no "
8200         "cenc protection system information has been found");
8201     return FALSE;
8202   }
8203
8204   gst_qtdemux_request_protection_context (qtdemux, stream);
8205   if (qtdemux->preferred_protection_system_id != NULL) {
8206     const gchar *preferred_system_array[] =
8207         { qtdemux->preferred_protection_system_id, NULL };
8208
8209     selected_system = gst_protection_select_system (preferred_system_array);
8210
8211     if (selected_system) {
8212       GST_TRACE_OBJECT (qtdemux, "selected preferred system %s",
8213           qtdemux->preferred_protection_system_id);
8214     } else {
8215       GST_WARNING_OBJECT (qtdemux, "could not select preferred system %s "
8216           "because there is no available decryptor",
8217           qtdemux->preferred_protection_system_id);
8218     }
8219   }
8220
8221   if (!selected_system) {
8222     g_ptr_array_add (qtdemux->protection_system_ids, NULL);
8223     selected_system = gst_protection_select_system ((const gchar **)
8224         qtdemux->protection_system_ids->pdata);
8225     g_ptr_array_remove_index (qtdemux->protection_system_ids,
8226         qtdemux->protection_system_ids->len - 1);
8227   }
8228
8229   if (!selected_system) {
8230     GST_ERROR_OBJECT (qtdemux, "stream is protected, but no "
8231         "suitable decryptor element has been found");
8232     return FALSE;
8233   }
8234
8235   GST_DEBUG_OBJECT (qtdemux, "selected protection system is %s",
8236       selected_system);
8237
8238   s = gst_caps_get_structure (CUR_STREAM (stream)->caps, 0);
8239   if (!gst_structure_has_name (s, "application/x-cenc")) {
8240     gst_structure_set (s,
8241         "original-media-type", G_TYPE_STRING, gst_structure_get_name (s),
8242         GST_PROTECTION_SYSTEM_ID_CAPS_FIELD, G_TYPE_STRING, selected_system,
8243         NULL);
8244     gst_structure_set_name (s, "application/x-cenc");
8245   }
8246   return TRUE;
8247 }
8248
8249 static gboolean
8250 gst_qtdemux_configure_stream (GstQTDemux * qtdemux, QtDemuxStream * stream)
8251 {
8252   if (stream->subtype == FOURCC_vide) {
8253     /* fps is calculated base on the duration of the average framerate since
8254      * qt does not have a fixed framerate. */
8255     gboolean fps_available = TRUE;
8256     guint32 first_duration = 0;
8257
8258     if (stream->n_samples > 0)
8259       first_duration = stream->samples[0].duration;
8260
8261     if ((stream->n_samples == 1 && first_duration == 0)
8262         || (qtdemux->fragmented && stream->n_samples_moof == 1)) {
8263       /* still frame */
8264       CUR_STREAM (stream)->fps_n = 0;
8265       CUR_STREAM (stream)->fps_d = 1;
8266     } else {
8267       if (stream->duration == 0 || stream->n_samples < 2) {
8268         CUR_STREAM (stream)->fps_n = stream->timescale;
8269         CUR_STREAM (stream)->fps_d = 1;
8270         fps_available = FALSE;
8271       } else {
8272         GstClockTime avg_duration;
8273         guint64 duration;
8274         guint32 n_samples;
8275
8276         /* duration and n_samples can be updated for fragmented format
8277          * so, framerate of fragmented format is calculated using data in a moof */
8278         if (qtdemux->fragmented && stream->n_samples_moof > 0
8279             && stream->duration_moof > 0) {
8280           n_samples = stream->n_samples_moof;
8281           duration = stream->duration_moof;
8282         } else {
8283           n_samples = stream->n_samples;
8284           duration = stream->duration;
8285         }
8286
8287         /* Calculate a framerate, ignoring the first sample which is sometimes truncated */
8288         /* stream->duration is guint64, timescale, n_samples are guint32 */
8289         avg_duration =
8290             gst_util_uint64_scale_round (duration -
8291             first_duration, GST_SECOND,
8292             (guint64) (stream->timescale) * (n_samples - 1));
8293
8294         GST_LOG_OBJECT (qtdemux,
8295             "Calculating avg sample duration based on stream (or moof) duration %"
8296             G_GUINT64_FORMAT
8297             " minus first sample %u, leaving %d samples gives %"
8298             GST_TIME_FORMAT, duration, first_duration,
8299             n_samples - 1, GST_TIME_ARGS (avg_duration));
8300
8301         gst_video_guess_framerate (avg_duration, &CUR_STREAM (stream)->fps_n,
8302             &CUR_STREAM (stream)->fps_d);
8303
8304         GST_DEBUG_OBJECT (qtdemux,
8305             "Calculating framerate, timescale %u gave fps_n %d fps_d %d",
8306             stream->timescale, CUR_STREAM (stream)->fps_n,
8307             CUR_STREAM (stream)->fps_d);
8308       }
8309     }
8310
8311     if (CUR_STREAM (stream)->caps) {
8312       CUR_STREAM (stream)->caps =
8313           gst_caps_make_writable (CUR_STREAM (stream)->caps);
8314
8315       gst_caps_set_simple (CUR_STREAM (stream)->caps,
8316           "width", G_TYPE_INT, CUR_STREAM (stream)->width,
8317           "height", G_TYPE_INT, CUR_STREAM (stream)->height, NULL);
8318
8319       /* set framerate if calculated framerate is reliable */
8320       if (fps_available) {
8321         gst_caps_set_simple (CUR_STREAM (stream)->caps,
8322             "framerate", GST_TYPE_FRACTION, CUR_STREAM (stream)->fps_n,
8323             CUR_STREAM (stream)->fps_d, NULL);
8324       }
8325
8326       /* calculate pixel-aspect-ratio using display width and height */
8327       GST_DEBUG_OBJECT (qtdemux,
8328           "video size %dx%d, target display size %dx%d",
8329           CUR_STREAM (stream)->width, CUR_STREAM (stream)->height,
8330           stream->display_width, stream->display_height);
8331       /* qt file might have pasp atom */
8332       if (CUR_STREAM (stream)->par_w > 0 && CUR_STREAM (stream)->par_h > 0) {
8333         GST_DEBUG_OBJECT (qtdemux, "par %d:%d", CUR_STREAM (stream)->par_w,
8334             CUR_STREAM (stream)->par_h);
8335         gst_caps_set_simple (CUR_STREAM (stream)->caps, "pixel-aspect-ratio",
8336             GST_TYPE_FRACTION, CUR_STREAM (stream)->par_w,
8337             CUR_STREAM (stream)->par_h, NULL);
8338       } else if (stream->display_width > 0 && stream->display_height > 0
8339           && CUR_STREAM (stream)->width > 0
8340           && CUR_STREAM (stream)->height > 0) {
8341         gint n, d;
8342
8343         /* calculate the pixel aspect ratio using the display and pixel w/h */
8344         n = stream->display_width * CUR_STREAM (stream)->height;
8345         d = stream->display_height * CUR_STREAM (stream)->width;
8346         if (n == d)
8347           n = d = 1;
8348         GST_DEBUG_OBJECT (qtdemux, "setting PAR to %d/%d", n, d);
8349         CUR_STREAM (stream)->par_w = n;
8350         CUR_STREAM (stream)->par_h = d;
8351         gst_caps_set_simple (CUR_STREAM (stream)->caps, "pixel-aspect-ratio",
8352             GST_TYPE_FRACTION, CUR_STREAM (stream)->par_w,
8353             CUR_STREAM (stream)->par_h, NULL);
8354       }
8355
8356       if (CUR_STREAM (stream)->interlace_mode > 0) {
8357         if (CUR_STREAM (stream)->interlace_mode == 1) {
8358           gst_caps_set_simple (CUR_STREAM (stream)->caps, "interlace-mode",
8359               G_TYPE_STRING, "progressive", NULL);
8360         } else if (CUR_STREAM (stream)->interlace_mode == 2) {
8361           gst_caps_set_simple (CUR_STREAM (stream)->caps, "interlace-mode",
8362               G_TYPE_STRING, "interleaved", NULL);
8363           if (CUR_STREAM (stream)->field_order == 9) {
8364             gst_caps_set_simple (CUR_STREAM (stream)->caps, "field-order",
8365                 G_TYPE_STRING, "top-field-first", NULL);
8366           } else if (CUR_STREAM (stream)->field_order == 14) {
8367             gst_caps_set_simple (CUR_STREAM (stream)->caps, "field-order",
8368                 G_TYPE_STRING, "bottom-field-first", NULL);
8369           }
8370         }
8371       }
8372
8373       /* Create incomplete colorimetry here if needed */
8374       if (CUR_STREAM (stream)->colorimetry.range ||
8375           CUR_STREAM (stream)->colorimetry.matrix ||
8376           CUR_STREAM (stream)->colorimetry.transfer
8377           || CUR_STREAM (stream)->colorimetry.primaries) {
8378         gchar *colorimetry =
8379             gst_video_colorimetry_to_string (&CUR_STREAM (stream)->colorimetry);
8380         gst_caps_set_simple (CUR_STREAM (stream)->caps, "colorimetry",
8381             G_TYPE_STRING, colorimetry, NULL);
8382         g_free (colorimetry);
8383       }
8384
8385       if (stream->multiview_mode != GST_VIDEO_MULTIVIEW_MODE_NONE) {
8386         guint par_w = 1, par_h = 1;
8387
8388         if (CUR_STREAM (stream)->par_w > 0 && CUR_STREAM (stream)->par_h > 0) {
8389           par_w = CUR_STREAM (stream)->par_w;
8390           par_h = CUR_STREAM (stream)->par_h;
8391         }
8392
8393         if (gst_video_multiview_guess_half_aspect (stream->multiview_mode,
8394                 CUR_STREAM (stream)->width, CUR_STREAM (stream)->height, par_w,
8395                 par_h)) {
8396           stream->multiview_flags |= GST_VIDEO_MULTIVIEW_FLAGS_HALF_ASPECT;
8397         }
8398
8399         gst_caps_set_simple (CUR_STREAM (stream)->caps,
8400             "multiview-mode", G_TYPE_STRING,
8401             gst_video_multiview_mode_to_caps_string (stream->multiview_mode),
8402             "multiview-flags", GST_TYPE_VIDEO_MULTIVIEW_FLAGSET,
8403             stream->multiview_flags, GST_FLAG_SET_MASK_EXACT, NULL);
8404       }
8405     }
8406   }
8407
8408   else if (stream->subtype == FOURCC_soun) {
8409     if (CUR_STREAM (stream)->caps) {
8410       CUR_STREAM (stream)->caps =
8411           gst_caps_make_writable (CUR_STREAM (stream)->caps);
8412       if (CUR_STREAM (stream)->rate > 0)
8413         gst_caps_set_simple (CUR_STREAM (stream)->caps,
8414             "rate", G_TYPE_INT, (int) CUR_STREAM (stream)->rate, NULL);
8415       if (CUR_STREAM (stream)->n_channels > 0)
8416         gst_caps_set_simple (CUR_STREAM (stream)->caps,
8417             "channels", G_TYPE_INT, CUR_STREAM (stream)->n_channels, NULL);
8418       if (CUR_STREAM (stream)->n_channels > 2) {
8419         /* FIXME: Need to parse the 'chan' atom to get channel layouts
8420          * correctly; this is just the minimum we can do - assume
8421          * we don't actually have any channel positions. */
8422         gst_caps_set_simple (CUR_STREAM (stream)->caps,
8423             "channel-mask", GST_TYPE_BITMASK, G_GUINT64_CONSTANT (0), NULL);
8424       }
8425     }
8426   }
8427
8428   if (stream->pad) {
8429     GstCaps *prev_caps = NULL;
8430
8431     GST_PAD_ELEMENT_PRIVATE (stream->pad) = stream;
8432     gst_pad_set_event_function (stream->pad, gst_qtdemux_handle_src_event);
8433     gst_pad_set_query_function (stream->pad, gst_qtdemux_handle_src_query);
8434     gst_pad_set_active (stream->pad, TRUE);
8435
8436     gst_pad_use_fixed_caps (stream->pad);
8437
8438     if (stream->protected) {
8439       if (!gst_qtdemux_configure_protected_caps (qtdemux, stream)) {
8440         GST_ERROR_OBJECT (qtdemux,
8441             "Failed to configure protected stream caps.");
8442         return FALSE;
8443       }
8444     }
8445
8446     GST_DEBUG_OBJECT (qtdemux, "setting caps %" GST_PTR_FORMAT,
8447         CUR_STREAM (stream)->caps);
8448     if (stream->new_stream) {
8449       GstEvent *event;
8450       GstStreamFlags stream_flags = GST_STREAM_FLAG_NONE;
8451
8452       event =
8453           gst_pad_get_sticky_event (qtdemux->sinkpad, GST_EVENT_STREAM_START,
8454           0);
8455       if (event) {
8456         gst_event_parse_stream_flags (event, &stream_flags);
8457         if (gst_event_parse_group_id (event, &qtdemux->group_id))
8458           qtdemux->have_group_id = TRUE;
8459         else
8460           qtdemux->have_group_id = FALSE;
8461         gst_event_unref (event);
8462       } else if (!qtdemux->have_group_id) {
8463         qtdemux->have_group_id = TRUE;
8464         qtdemux->group_id = gst_util_group_id_next ();
8465       }
8466
8467       stream->new_stream = FALSE;
8468       event = gst_event_new_stream_start (stream->stream_id);
8469       if (qtdemux->have_group_id)
8470         gst_event_set_group_id (event, qtdemux->group_id);
8471       if (stream->disabled)
8472         stream_flags |= GST_STREAM_FLAG_UNSELECT;
8473       if (CUR_STREAM (stream)->sparse) {
8474         stream_flags |= GST_STREAM_FLAG_SPARSE;
8475       } else {
8476         stream_flags &= ~GST_STREAM_FLAG_SPARSE;
8477       }
8478       gst_event_set_stream_flags (event, stream_flags);
8479       gst_pad_push_event (stream->pad, event);
8480     }
8481
8482     prev_caps = gst_pad_get_current_caps (stream->pad);
8483
8484     if (CUR_STREAM (stream)->caps) {
8485       if (!prev_caps
8486           || !gst_caps_is_equal_fixed (prev_caps, CUR_STREAM (stream)->caps)) {
8487         GST_DEBUG_OBJECT (qtdemux, "setting caps %" GST_PTR_FORMAT,
8488             CUR_STREAM (stream)->caps);
8489         gst_pad_set_caps (stream->pad, CUR_STREAM (stream)->caps);
8490       } else {
8491         GST_DEBUG_OBJECT (qtdemux, "ignore duplicated caps");
8492       }
8493     } else {
8494       GST_WARNING_OBJECT (qtdemux, "stream without caps");
8495     }
8496
8497     if (prev_caps)
8498       gst_caps_unref (prev_caps);
8499     stream->new_caps = FALSE;
8500   }
8501   return TRUE;
8502 }
8503
8504 static void
8505 gst_qtdemux_stream_check_and_change_stsd_index (GstQTDemux * demux,
8506     QtDemuxStream * stream)
8507 {
8508   if (stream->cur_stsd_entry_index == stream->stsd_sample_description_id)
8509     return;
8510
8511   GST_DEBUG_OBJECT (stream->pad, "Changing stsd index from '%u' to '%u'",
8512       stream->cur_stsd_entry_index, stream->stsd_sample_description_id);
8513   if (G_UNLIKELY (stream->stsd_sample_description_id >=
8514           stream->stsd_entries_length)) {
8515     GST_ELEMENT_ERROR (demux, STREAM, DEMUX,
8516         (_("This file is invalid and cannot be played.")),
8517         ("New sample description id is out of bounds (%d >= %d)",
8518             stream->stsd_sample_description_id, stream->stsd_entries_length));
8519   } else {
8520     stream->cur_stsd_entry_index = stream->stsd_sample_description_id;
8521     stream->new_caps = TRUE;
8522   }
8523 }
8524
8525 static gboolean
8526 gst_qtdemux_add_stream (GstQTDemux * qtdemux,
8527     QtDemuxStream * stream, GstTagList * list)
8528 {
8529   gboolean ret = TRUE;
8530   /* consistent default for push based mode */
8531   gst_segment_init (&stream->segment, GST_FORMAT_TIME);
8532
8533   if (stream->subtype == FOURCC_vide) {
8534     gchar *name = g_strdup_printf ("video_%u", qtdemux->n_video_streams);
8535
8536     stream->pad =
8537         gst_pad_new_from_static_template (&gst_qtdemux_videosrc_template, name);
8538     g_free (name);
8539
8540     if (!gst_qtdemux_configure_stream (qtdemux, stream)) {
8541       gst_object_unref (stream->pad);
8542       stream->pad = NULL;
8543       ret = FALSE;
8544       goto done;
8545     }
8546
8547     qtdemux->n_video_streams++;
8548   } else if (stream->subtype == FOURCC_soun) {
8549     gchar *name = g_strdup_printf ("audio_%u", qtdemux->n_audio_streams);
8550
8551     stream->pad =
8552         gst_pad_new_from_static_template (&gst_qtdemux_audiosrc_template, name);
8553     g_free (name);
8554     if (!gst_qtdemux_configure_stream (qtdemux, stream)) {
8555       gst_object_unref (stream->pad);
8556       stream->pad = NULL;
8557       ret = FALSE;
8558       goto done;
8559     }
8560     qtdemux->n_audio_streams++;
8561   } else if (stream->subtype == FOURCC_strm) {
8562     GST_DEBUG_OBJECT (qtdemux, "stream type, not creating pad");
8563   } else if (stream->subtype == FOURCC_subp || stream->subtype == FOURCC_text
8564       || stream->subtype == FOURCC_sbtl || stream->subtype == FOURCC_subt
8565       || stream->subtype == FOURCC_clcp) {
8566     gchar *name = g_strdup_printf ("subtitle_%u", qtdemux->n_sub_streams);
8567
8568     stream->pad =
8569         gst_pad_new_from_static_template (&gst_qtdemux_subsrc_template, name);
8570     g_free (name);
8571     if (!gst_qtdemux_configure_stream (qtdemux, stream)) {
8572       gst_object_unref (stream->pad);
8573       stream->pad = NULL;
8574       ret = FALSE;
8575       goto done;
8576     }
8577     qtdemux->n_sub_streams++;
8578   } else if (CUR_STREAM (stream)->caps) {
8579     gchar *name = g_strdup_printf ("video_%u", qtdemux->n_video_streams);
8580
8581     stream->pad =
8582         gst_pad_new_from_static_template (&gst_qtdemux_videosrc_template, name);
8583     g_free (name);
8584     if (!gst_qtdemux_configure_stream (qtdemux, stream)) {
8585       gst_object_unref (stream->pad);
8586       stream->pad = NULL;
8587       ret = FALSE;
8588       goto done;
8589     }
8590     qtdemux->n_video_streams++;
8591   } else {
8592     GST_DEBUG_OBJECT (qtdemux, "unknown stream type");
8593     goto done;
8594   }
8595
8596   if (stream->pad) {
8597     GList *l;
8598
8599     GST_DEBUG_OBJECT (qtdemux, "adding pad %s %p to qtdemux %p",
8600         GST_OBJECT_NAME (stream->pad), stream->pad, qtdemux);
8601     gst_element_add_pad (GST_ELEMENT_CAST (qtdemux), stream->pad);
8602     gst_flow_combiner_add_pad (qtdemux->flowcombiner, stream->pad);
8603
8604     if (stream->stream_tags)
8605       gst_tag_list_unref (stream->stream_tags);
8606     stream->stream_tags = list;
8607     list = NULL;
8608     /* global tags go on each pad anyway */
8609     stream->send_global_tags = TRUE;
8610     /* send upstream GST_EVENT_PROTECTION events that were received before
8611        this source pad was created */
8612     for (l = qtdemux->protection_event_queue.head; l != NULL; l = l->next)
8613       gst_pad_push_event (stream->pad, gst_event_ref (l->data));
8614   }
8615 done:
8616   if (list)
8617     gst_tag_list_unref (list);
8618   return ret;
8619 }
8620
8621 /* find next atom with @fourcc starting at @offset */
8622 static GstFlowReturn
8623 qtdemux_find_atom (GstQTDemux * qtdemux, guint64 * offset,
8624     guint64 * length, guint32 fourcc)
8625 {
8626   GstFlowReturn ret;
8627   guint32 lfourcc;
8628   GstBuffer *buf;
8629
8630   GST_LOG_OBJECT (qtdemux, "finding fourcc %" GST_FOURCC_FORMAT " at offset %"
8631       G_GUINT64_FORMAT, GST_FOURCC_ARGS (fourcc), *offset);
8632
8633   while (TRUE) {
8634     GstMapInfo map;
8635
8636     buf = NULL;
8637     ret = gst_pad_pull_range (qtdemux->sinkpad, *offset, 16, &buf);
8638     if (G_UNLIKELY (ret != GST_FLOW_OK))
8639       goto locate_failed;
8640     if (G_UNLIKELY (gst_buffer_get_size (buf) != 16)) {
8641       /* likely EOF */
8642       ret = GST_FLOW_EOS;
8643       gst_buffer_unref (buf);
8644       goto locate_failed;
8645     }
8646     gst_buffer_map (buf, &map, GST_MAP_READ);
8647     extract_initial_length_and_fourcc (map.data, 16, length, &lfourcc);
8648     gst_buffer_unmap (buf, &map);
8649     gst_buffer_unref (buf);
8650
8651     if (G_UNLIKELY (*length == 0)) {
8652       GST_DEBUG_OBJECT (qtdemux, "invalid length 0");
8653       ret = GST_FLOW_ERROR;
8654       goto locate_failed;
8655     }
8656
8657     if (lfourcc == fourcc) {
8658       GST_DEBUG_OBJECT (qtdemux, "found fourcc at offset %" G_GUINT64_FORMAT,
8659           *offset);
8660       break;
8661     } else {
8662       GST_LOG_OBJECT (qtdemux,
8663           "skipping atom '%" GST_FOURCC_FORMAT "' at %" G_GUINT64_FORMAT,
8664           GST_FOURCC_ARGS (fourcc), *offset);
8665       *offset += *length;
8666     }
8667   }
8668
8669   return GST_FLOW_OK;
8670
8671 locate_failed:
8672   {
8673     /* might simply have had last one */
8674     GST_DEBUG_OBJECT (qtdemux, "fourcc not found");
8675     return ret;
8676   }
8677 }
8678
8679 /* should only do something in pull mode */
8680 /* call with OBJECT lock */
8681 static GstFlowReturn
8682 qtdemux_add_fragmented_samples (GstQTDemux * qtdemux)
8683 {
8684   guint64 length, offset;
8685   GstBuffer *buf = NULL;
8686   GstFlowReturn ret = GST_FLOW_OK;
8687   GstFlowReturn res = GST_FLOW_OK;
8688   GstMapInfo map;
8689
8690   offset = qtdemux->moof_offset;
8691   GST_DEBUG_OBJECT (qtdemux, "next moof at offset %" G_GUINT64_FORMAT, offset);
8692
8693   if (!offset) {
8694     GST_DEBUG_OBJECT (qtdemux, "no next moof");
8695     return GST_FLOW_EOS;
8696   }
8697
8698   /* best not do pull etc with lock held */
8699   GST_OBJECT_UNLOCK (qtdemux);
8700
8701   ret = qtdemux_find_atom (qtdemux, &offset, &length, FOURCC_moof);
8702   if (ret != GST_FLOW_OK)
8703     goto flow_failed;
8704
8705   ret = gst_qtdemux_pull_atom (qtdemux, offset, length, &buf);
8706   if (G_UNLIKELY (ret != GST_FLOW_OK))
8707     goto flow_failed;
8708   gst_buffer_map (buf, &map, GST_MAP_READ);
8709   if (!qtdemux_parse_moof (qtdemux, map.data, map.size, offset, NULL)) {
8710     gst_buffer_unmap (buf, &map);
8711     gst_buffer_unref (buf);
8712     buf = NULL;
8713     goto parse_failed;
8714   }
8715
8716   gst_buffer_unmap (buf, &map);
8717   gst_buffer_unref (buf);
8718   buf = NULL;
8719
8720   offset += length;
8721   /* look for next moof */
8722   ret = qtdemux_find_atom (qtdemux, &offset, &length, FOURCC_moof);
8723   if (G_UNLIKELY (ret != GST_FLOW_OK))
8724     goto flow_failed;
8725
8726 exit:
8727   GST_OBJECT_LOCK (qtdemux);
8728
8729   qtdemux->moof_offset = offset;
8730
8731   return res;
8732
8733 parse_failed:
8734   {
8735     GST_DEBUG_OBJECT (qtdemux, "failed to parse moof");
8736     offset = 0;
8737     res = GST_FLOW_ERROR;
8738     goto exit;
8739   }
8740 flow_failed:
8741   {
8742     /* maybe upstream temporarily flushing */
8743     if (ret != GST_FLOW_FLUSHING) {
8744       GST_DEBUG_OBJECT (qtdemux, "no next moof");
8745       offset = 0;
8746     } else {
8747       GST_DEBUG_OBJECT (qtdemux, "upstream WRONG_STATE");
8748       /* resume at current position next time */
8749     }
8750     res = ret;
8751     goto exit;
8752   }
8753 }
8754
8755 /* initialise bytereaders for stbl sub-atoms */
8756 static gboolean
8757 qtdemux_stbl_init (GstQTDemux * qtdemux, QtDemuxStream * stream, GNode * stbl)
8758 {
8759   stream->stbl_index = -1;      /* no samples have yet been parsed */
8760   stream->sample_index = -1;
8761
8762   /* time-to-sample atom */
8763   if (!qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stts, &stream->stts))
8764     goto corrupt_file;
8765
8766   /* copy atom data into a new buffer for later use */
8767   stream->stts.data = g_memdup (stream->stts.data, stream->stts.size);
8768
8769   /* skip version + flags */
8770   if (!gst_byte_reader_skip (&stream->stts, 1 + 3) ||
8771       !gst_byte_reader_get_uint32_be (&stream->stts, &stream->n_sample_times))
8772     goto corrupt_file;
8773   GST_LOG_OBJECT (qtdemux, "%u timestamp blocks", stream->n_sample_times);
8774
8775   /* make sure there's enough data */
8776   if (!qt_atom_parser_has_chunks (&stream->stts, stream->n_sample_times, 8)) {
8777     stream->n_sample_times = gst_byte_reader_get_remaining (&stream->stts) / 8;
8778     GST_LOG_OBJECT (qtdemux, "overriding to %u timestamp blocks",
8779         stream->n_sample_times);
8780     if (!stream->n_sample_times)
8781       goto corrupt_file;
8782   }
8783
8784   /* sync sample atom */
8785   stream->stps_present = FALSE;
8786   if ((stream->stss_present =
8787           ! !qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stss,
8788               &stream->stss) ? TRUE : FALSE) == TRUE) {
8789     /* copy atom data into a new buffer for later use */
8790     stream->stss.data = g_memdup (stream->stss.data, stream->stss.size);
8791
8792     /* skip version + flags */
8793     if (!gst_byte_reader_skip (&stream->stss, 1 + 3) ||
8794         !gst_byte_reader_get_uint32_be (&stream->stss, &stream->n_sample_syncs))
8795       goto corrupt_file;
8796
8797     if (stream->n_sample_syncs) {
8798       /* make sure there's enough data */
8799       if (!qt_atom_parser_has_chunks (&stream->stss, stream->n_sample_syncs, 4))
8800         goto corrupt_file;
8801     }
8802
8803     /* partial sync sample atom */
8804     if ((stream->stps_present =
8805             ! !qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stps,
8806                 &stream->stps) ? TRUE : FALSE) == TRUE) {
8807       /* copy atom data into a new buffer for later use */
8808       stream->stps.data = g_memdup (stream->stps.data, stream->stps.size);
8809
8810       /* skip version + flags */
8811       if (!gst_byte_reader_skip (&stream->stps, 1 + 3) ||
8812           !gst_byte_reader_get_uint32_be (&stream->stps,
8813               &stream->n_sample_partial_syncs))
8814         goto corrupt_file;
8815
8816       /* if there are no entries, the stss table contains the real
8817        * sync samples */
8818       if (stream->n_sample_partial_syncs) {
8819         /* make sure there's enough data */
8820         if (!qt_atom_parser_has_chunks (&stream->stps,
8821                 stream->n_sample_partial_syncs, 4))
8822           goto corrupt_file;
8823       }
8824     }
8825   }
8826
8827   /* sample size */
8828   if (!qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stsz, &stream->stsz))
8829     goto no_samples;
8830
8831   /* copy atom data into a new buffer for later use */
8832   stream->stsz.data = g_memdup (stream->stsz.data, stream->stsz.size);
8833
8834   /* skip version + flags */
8835   if (!gst_byte_reader_skip (&stream->stsz, 1 + 3) ||
8836       !gst_byte_reader_get_uint32_be (&stream->stsz, &stream->sample_size))
8837     goto corrupt_file;
8838
8839   if (!gst_byte_reader_get_uint32_be (&stream->stsz, &stream->n_samples))
8840     goto corrupt_file;
8841
8842   if (!stream->n_samples)
8843     goto no_samples;
8844
8845   /* sample-to-chunk atom */
8846   if (!qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stsc, &stream->stsc))
8847     goto corrupt_file;
8848
8849   /* copy atom data into a new buffer for later use */
8850   stream->stsc.data = g_memdup (stream->stsc.data, stream->stsc.size);
8851
8852   /* skip version + flags */
8853   if (!gst_byte_reader_skip (&stream->stsc, 1 + 3) ||
8854       !gst_byte_reader_get_uint32_be (&stream->stsc,
8855           &stream->n_samples_per_chunk))
8856     goto corrupt_file;
8857
8858   GST_DEBUG_OBJECT (qtdemux, "n_samples_per_chunk %u",
8859       stream->n_samples_per_chunk);
8860
8861   /* make sure there's enough data */
8862   if (!qt_atom_parser_has_chunks (&stream->stsc, stream->n_samples_per_chunk,
8863           12))
8864     goto corrupt_file;
8865
8866
8867   /* chunk offset */
8868   if (qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stco, &stream->stco))
8869     stream->co_size = sizeof (guint32);
8870   else if (qtdemux_tree_get_child_by_type_full (stbl, FOURCC_co64,
8871           &stream->stco))
8872     stream->co_size = sizeof (guint64);
8873   else
8874     goto corrupt_file;
8875
8876   /* copy atom data into a new buffer for later use */
8877   stream->stco.data = g_memdup (stream->stco.data, stream->stco.size);
8878
8879   /* skip version + flags */
8880   if (!gst_byte_reader_skip (&stream->stco, 1 + 3))
8881     goto corrupt_file;
8882
8883   /* chunks_are_samples == TRUE means treat chunks as samples */
8884   stream->chunks_are_samples = stream->sample_size
8885       && !CUR_STREAM (stream)->sampled;
8886   if (stream->chunks_are_samples) {
8887     /* treat chunks as samples */
8888     if (!gst_byte_reader_get_uint32_be (&stream->stco, &stream->n_samples))
8889       goto corrupt_file;
8890   } else {
8891     /* skip number of entries */
8892     if (!gst_byte_reader_skip (&stream->stco, 4))
8893       goto corrupt_file;
8894
8895     /* make sure there are enough data in the stsz atom */
8896     if (!stream->sample_size) {
8897       /* different sizes for each sample */
8898       if (!qt_atom_parser_has_chunks (&stream->stsz, stream->n_samples, 4))
8899         goto corrupt_file;
8900     }
8901   }
8902
8903   GST_DEBUG_OBJECT (qtdemux, "allocating n_samples %u * %u (%.2f MB)",
8904       stream->n_samples, (guint) sizeof (QtDemuxSample),
8905       stream->n_samples * sizeof (QtDemuxSample) / (1024.0 * 1024.0));
8906
8907   if (stream->n_samples >=
8908       QTDEMUX_MAX_SAMPLE_INDEX_SIZE / sizeof (QtDemuxSample)) {
8909     GST_WARNING_OBJECT (qtdemux, "not allocating index of %d samples, would "
8910         "be larger than %uMB (broken file?)", stream->n_samples,
8911         QTDEMUX_MAX_SAMPLE_INDEX_SIZE >> 20);
8912     return FALSE;
8913   }
8914
8915   g_assert (stream->samples == NULL);
8916   stream->samples = g_try_new0 (QtDemuxSample, stream->n_samples);
8917   if (!stream->samples) {
8918     GST_WARNING_OBJECT (qtdemux, "failed to allocate %d samples",
8919         stream->n_samples);
8920     return FALSE;
8921   }
8922
8923   /* composition time-to-sample */
8924   if ((stream->ctts_present =
8925           ! !qtdemux_tree_get_child_by_type_full (stbl, FOURCC_ctts,
8926               &stream->ctts) ? TRUE : FALSE) == TRUE) {
8927     GstByteReader cslg = GST_BYTE_READER_INIT (NULL, 0);
8928
8929     /* copy atom data into a new buffer for later use */
8930     stream->ctts.data = g_memdup (stream->ctts.data, stream->ctts.size);
8931
8932     /* skip version + flags */
8933     if (!gst_byte_reader_skip (&stream->ctts, 1 + 3)
8934         || !gst_byte_reader_get_uint32_be (&stream->ctts,
8935             &stream->n_composition_times))
8936       goto corrupt_file;
8937
8938     /* make sure there's enough data */
8939     if (!qt_atom_parser_has_chunks (&stream->ctts, stream->n_composition_times,
8940             4 + 4))
8941       goto corrupt_file;
8942
8943     /* This is optional, if missing we iterate the ctts */
8944     if (qtdemux_tree_get_child_by_type_full (stbl, FOURCC_cslg, &cslg)) {
8945       if (!gst_byte_reader_skip (&cslg, 1 + 3)
8946           || !gst_byte_reader_get_uint32_be (&cslg, &stream->cslg_shift)) {
8947         g_free ((gpointer) cslg.data);
8948         goto corrupt_file;
8949       }
8950     } else {
8951       gint32 cslg_least = 0;
8952       guint num_entries, pos;
8953       gint i;
8954
8955       pos = gst_byte_reader_get_pos (&stream->ctts);
8956       num_entries = stream->n_composition_times;
8957
8958       stream->cslg_shift = 0;
8959
8960       for (i = 0; i < num_entries; i++) {
8961         gint32 offset;
8962
8963         gst_byte_reader_skip_unchecked (&stream->ctts, 4);
8964         offset = gst_byte_reader_get_int32_be_unchecked (&stream->ctts);
8965
8966         if (offset < cslg_least)
8967           cslg_least = offset;
8968       }
8969
8970       if (cslg_least < 0)
8971         stream->cslg_shift = ABS (cslg_least);
8972       else
8973         stream->cslg_shift = 0;
8974
8975       /* reset the reader so we can generate sample table */
8976       gst_byte_reader_set_pos (&stream->ctts, pos);
8977     }
8978   } else {
8979     /* Ensure the cslg_shift value is consistent so we can use it
8980      * unconditionnally to produce TS and Segment */
8981     stream->cslg_shift = 0;
8982   }
8983
8984   return TRUE;
8985
8986 corrupt_file:
8987   {
8988     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
8989         (_("This file is corrupt and cannot be played.")), (NULL));
8990     return FALSE;
8991   }
8992 no_samples:
8993   {
8994     gst_qtdemux_stbl_free (stream);
8995     if (!qtdemux->fragmented) {
8996       /* not quite good */
8997       GST_WARNING_OBJECT (qtdemux, "stream has no samples");
8998       return FALSE;
8999     } else {
9000       /* may pick up samples elsewhere */
9001       return TRUE;
9002     }
9003   }
9004 }
9005
9006 /* collect samples from the next sample to be parsed up to sample @n for @stream
9007  * by reading the info from @stbl
9008  *
9009  * This code can be executed from both the streaming thread and the seeking
9010  * thread so it takes the object lock to protect itself
9011  */
9012 static gboolean
9013 qtdemux_parse_samples (GstQTDemux * qtdemux, QtDemuxStream * stream, guint32 n)
9014 {
9015   gint i, j, k;
9016   QtDemuxSample *samples, *first, *cur, *last;
9017   guint32 n_samples_per_chunk;
9018   guint32 n_samples;
9019
9020   GST_LOG_OBJECT (qtdemux, "parsing samples for stream fourcc %"
9021       GST_FOURCC_FORMAT ", pad %s",
9022       GST_FOURCC_ARGS (CUR_STREAM (stream)->fourcc),
9023       stream->pad ? GST_PAD_NAME (stream->pad) : "(NULL)");
9024
9025   n_samples = stream->n_samples;
9026
9027   if (n >= n_samples)
9028     goto out_of_samples;
9029
9030   GST_OBJECT_LOCK (qtdemux);
9031   if (n <= stream->stbl_index)
9032     goto already_parsed;
9033
9034   GST_DEBUG_OBJECT (qtdemux, "parsing up to sample %u", n);
9035
9036   if (!stream->stsz.data) {
9037     /* so we already parsed and passed all the moov samples;
9038      * onto fragmented ones */
9039     g_assert (qtdemux->fragmented);
9040     goto done;
9041   }
9042
9043   /* pointer to the sample table */
9044   samples = stream->samples;
9045
9046   /* starts from -1, moves to the next sample index to parse */
9047   stream->stbl_index++;
9048
9049   /* keep track of the first and last sample to fill */
9050   first = &samples[stream->stbl_index];
9051   last = &samples[n];
9052
9053   if (!stream->chunks_are_samples) {
9054     /* set the sample sizes */
9055     if (stream->sample_size == 0) {
9056       /* different sizes for each sample */
9057       for (cur = first; cur <= last; cur++) {
9058         cur->size = gst_byte_reader_get_uint32_be_unchecked (&stream->stsz);
9059         GST_LOG_OBJECT (qtdemux, "sample %d has size %u",
9060             (guint) (cur - samples), cur->size);
9061       }
9062     } else {
9063       /* samples have the same size */
9064       GST_LOG_OBJECT (qtdemux, "all samples have size %u", stream->sample_size);
9065       for (cur = first; cur <= last; cur++)
9066         cur->size = stream->sample_size;
9067     }
9068   }
9069
9070   n_samples_per_chunk = stream->n_samples_per_chunk;
9071   cur = first;
9072
9073   for (i = stream->stsc_index; i < n_samples_per_chunk; i++) {
9074     guint32 last_chunk;
9075
9076     if (stream->stsc_chunk_index >= stream->last_chunk
9077         || stream->stsc_chunk_index < stream->first_chunk) {
9078       stream->first_chunk =
9079           gst_byte_reader_get_uint32_be_unchecked (&stream->stsc);
9080       stream->samples_per_chunk =
9081           gst_byte_reader_get_uint32_be_unchecked (&stream->stsc);
9082       /* starts from 1 */
9083       stream->stsd_sample_description_id =
9084           gst_byte_reader_get_uint32_be_unchecked (&stream->stsc) - 1;
9085
9086       /* chunk numbers are counted from 1 it seems */
9087       if (G_UNLIKELY (stream->first_chunk == 0))
9088         goto corrupt_file;
9089
9090       --stream->first_chunk;
9091
9092       /* the last chunk of each entry is calculated by taking the first chunk
9093        * of the next entry; except if there is no next, where we fake it with
9094        * INT_MAX */
9095       if (G_UNLIKELY (i == (stream->n_samples_per_chunk - 1))) {
9096         stream->last_chunk = G_MAXUINT32;
9097       } else {
9098         stream->last_chunk =
9099             gst_byte_reader_peek_uint32_be_unchecked (&stream->stsc);
9100         if (G_UNLIKELY (stream->last_chunk == 0))
9101           goto corrupt_file;
9102
9103         --stream->last_chunk;
9104       }
9105
9106       GST_LOG_OBJECT (qtdemux,
9107           "entry %d has first_chunk %d, last_chunk %d, samples_per_chunk %d"
9108           "sample desc ID: %d", i, stream->first_chunk, stream->last_chunk,
9109           stream->samples_per_chunk, stream->stsd_sample_description_id);
9110
9111       if (G_UNLIKELY (stream->last_chunk < stream->first_chunk))
9112         goto corrupt_file;
9113
9114       if (stream->last_chunk != G_MAXUINT32) {
9115         if (!qt_atom_parser_peek_sub (&stream->stco,
9116                 stream->first_chunk * stream->co_size,
9117                 (stream->last_chunk - stream->first_chunk) * stream->co_size,
9118                 &stream->co_chunk))
9119           goto corrupt_file;
9120
9121       } else {
9122         stream->co_chunk = stream->stco;
9123         if (!gst_byte_reader_skip (&stream->co_chunk,
9124                 stream->first_chunk * stream->co_size))
9125           goto corrupt_file;
9126       }
9127
9128       stream->stsc_chunk_index = stream->first_chunk;
9129     }
9130
9131     last_chunk = stream->last_chunk;
9132
9133     if (stream->chunks_are_samples) {
9134       cur = &samples[stream->stsc_chunk_index];
9135
9136       for (j = stream->stsc_chunk_index; j < last_chunk; j++) {
9137         if (j > n) {
9138           /* save state */
9139           stream->stsc_chunk_index = j;
9140           goto done;
9141         }
9142
9143         cur->offset =
9144             qt_atom_parser_get_offset_unchecked (&stream->co_chunk,
9145             stream->co_size);
9146
9147         GST_LOG_OBJECT (qtdemux, "Created entry %d with offset "
9148             "%" G_GUINT64_FORMAT, j, cur->offset);
9149
9150         if (CUR_STREAM (stream)->samples_per_frame > 0 &&
9151             CUR_STREAM (stream)->bytes_per_frame > 0) {
9152           cur->size =
9153               (stream->samples_per_chunk * CUR_STREAM (stream)->n_channels) /
9154               CUR_STREAM (stream)->samples_per_frame *
9155               CUR_STREAM (stream)->bytes_per_frame;
9156         } else {
9157           cur->size = stream->samples_per_chunk;
9158         }
9159
9160         GST_DEBUG_OBJECT (qtdemux,
9161             "keyframe sample %d: timestamp %" GST_TIME_FORMAT ", size %u",
9162             j, GST_TIME_ARGS (QTSTREAMTIME_TO_GSTTIME (stream,
9163                     stream->stco_sample_index)), cur->size);
9164
9165         cur->timestamp = stream->stco_sample_index;
9166         cur->duration = stream->samples_per_chunk;
9167         cur->keyframe = TRUE;
9168         cur++;
9169
9170         stream->stco_sample_index += stream->samples_per_chunk;
9171       }
9172       stream->stsc_chunk_index = j;
9173     } else {
9174       for (j = stream->stsc_chunk_index; j < last_chunk; j++) {
9175         guint32 samples_per_chunk;
9176         guint64 chunk_offset;
9177
9178         if (!stream->stsc_sample_index
9179             && !qt_atom_parser_get_offset (&stream->co_chunk, stream->co_size,
9180                 &stream->chunk_offset))
9181           goto corrupt_file;
9182
9183         samples_per_chunk = stream->samples_per_chunk;
9184         chunk_offset = stream->chunk_offset;
9185
9186         for (k = stream->stsc_sample_index; k < samples_per_chunk; k++) {
9187           GST_LOG_OBJECT (qtdemux, "creating entry %d with offset %"
9188               G_GUINT64_FORMAT " and size %d",
9189               (guint) (cur - samples), chunk_offset, cur->size);
9190
9191           cur->offset = chunk_offset;
9192           chunk_offset += cur->size;
9193           cur++;
9194
9195           if (G_UNLIKELY (cur > last)) {
9196             /* save state */
9197             stream->stsc_sample_index = k + 1;
9198             stream->chunk_offset = chunk_offset;
9199             stream->stsc_chunk_index = j;
9200             goto done2;
9201           }
9202         }
9203         stream->stsc_sample_index = 0;
9204       }
9205       stream->stsc_chunk_index = j;
9206     }
9207     stream->stsc_index++;
9208   }
9209
9210   if (stream->chunks_are_samples)
9211     goto ctts;
9212 done2:
9213   {
9214     guint32 n_sample_times;
9215
9216     n_sample_times = stream->n_sample_times;
9217     cur = first;
9218
9219     for (i = stream->stts_index; i < n_sample_times; i++) {
9220       guint32 stts_samples;
9221       gint32 stts_duration;
9222       gint64 stts_time;
9223
9224       if (stream->stts_sample_index >= stream->stts_samples
9225           || !stream->stts_sample_index) {
9226
9227         stream->stts_samples =
9228             gst_byte_reader_get_uint32_be_unchecked (&stream->stts);
9229         stream->stts_duration =
9230             gst_byte_reader_get_uint32_be_unchecked (&stream->stts);
9231
9232         GST_LOG_OBJECT (qtdemux, "block %d, %u timestamps, duration %u",
9233             i, stream->stts_samples, stream->stts_duration);
9234
9235         stream->stts_sample_index = 0;
9236       }
9237
9238       stts_samples = stream->stts_samples;
9239       stts_duration = stream->stts_duration;
9240       stts_time = stream->stts_time;
9241
9242       for (j = stream->stts_sample_index; j < stts_samples; j++) {
9243         GST_DEBUG_OBJECT (qtdemux,
9244             "sample %d: index %d, timestamp %" GST_TIME_FORMAT,
9245             (guint) (cur - samples), j,
9246             GST_TIME_ARGS (QTSTREAMTIME_TO_GSTTIME (stream, stts_time)));
9247
9248         cur->timestamp = stts_time;
9249         cur->duration = stts_duration;
9250
9251         /* avoid 32-bit wrap-around,
9252          * but still mind possible 'negative' duration */
9253         stts_time += (gint64) stts_duration;
9254         cur++;
9255
9256         if (G_UNLIKELY (cur > last)) {
9257           /* save values */
9258           stream->stts_time = stts_time;
9259           stream->stts_sample_index = j + 1;
9260           if (stream->stts_sample_index >= stream->stts_samples)
9261             stream->stts_index++;
9262           goto done3;
9263         }
9264       }
9265       stream->stts_sample_index = 0;
9266       stream->stts_time = stts_time;
9267       stream->stts_index++;
9268     }
9269     /* fill up empty timestamps with the last timestamp, this can happen when
9270      * the last samples do not decode and so we don't have timestamps for them.
9271      * We however look at the last timestamp to estimate the track length so we
9272      * need something in here. */
9273     for (; cur < last; cur++) {
9274       GST_DEBUG_OBJECT (qtdemux,
9275           "fill sample %d: timestamp %" GST_TIME_FORMAT,
9276           (guint) (cur - samples),
9277           GST_TIME_ARGS (QTSTREAMTIME_TO_GSTTIME (stream, stream->stts_time)));
9278       cur->timestamp = stream->stts_time;
9279       cur->duration = -1;
9280     }
9281   }
9282 done3:
9283   {
9284     /* sample sync, can be NULL */
9285     if (stream->stss_present == TRUE) {
9286       guint32 n_sample_syncs;
9287
9288       n_sample_syncs = stream->n_sample_syncs;
9289
9290       if (!n_sample_syncs) {
9291         GST_DEBUG_OBJECT (qtdemux, "all samples are keyframes");
9292         stream->all_keyframe = TRUE;
9293       } else {
9294         for (i = stream->stss_index; i < n_sample_syncs; i++) {
9295           /* note that the first sample is index 1, not 0 */
9296           guint32 index;
9297
9298           index = gst_byte_reader_get_uint32_be_unchecked (&stream->stss);
9299
9300           if (G_LIKELY (index > 0 && index <= n_samples)) {
9301             index -= 1;
9302             samples[index].keyframe = TRUE;
9303             GST_DEBUG_OBJECT (qtdemux, "samples at %u is keyframe", index);
9304             /* and exit if we have enough samples */
9305             if (G_UNLIKELY (index >= n)) {
9306               i++;
9307               break;
9308             }
9309           }
9310         }
9311         /* save state */
9312         stream->stss_index = i;
9313       }
9314
9315       /* stps marks partial sync frames like open GOP I-Frames */
9316       if (stream->stps_present == TRUE) {
9317         guint32 n_sample_partial_syncs;
9318
9319         n_sample_partial_syncs = stream->n_sample_partial_syncs;
9320
9321         /* if there are no entries, the stss table contains the real
9322          * sync samples */
9323         if (n_sample_partial_syncs) {
9324           for (i = stream->stps_index; i < n_sample_partial_syncs; i++) {
9325             /* note that the first sample is index 1, not 0 */
9326             guint32 index;
9327
9328             index = gst_byte_reader_get_uint32_be_unchecked (&stream->stps);
9329
9330             if (G_LIKELY (index > 0 && index <= n_samples)) {
9331               index -= 1;
9332               samples[index].keyframe = TRUE;
9333               GST_DEBUG_OBJECT (qtdemux, "samples at %u is keyframe", index);
9334               /* and exit if we have enough samples */
9335               if (G_UNLIKELY (index >= n)) {
9336                 i++;
9337                 break;
9338               }
9339             }
9340           }
9341           /* save state */
9342           stream->stps_index = i;
9343         }
9344       }
9345     } else {
9346       /* no stss, all samples are keyframes */
9347       stream->all_keyframe = TRUE;
9348       GST_DEBUG_OBJECT (qtdemux, "setting all keyframes");
9349     }
9350   }
9351
9352 ctts:
9353   /* composition time to sample */
9354   if (stream->ctts_present == TRUE) {
9355     guint32 n_composition_times;
9356     guint32 ctts_count;
9357     gint32 ctts_soffset;
9358
9359     /* Fill in the pts_offsets */
9360     cur = first;
9361     n_composition_times = stream->n_composition_times;
9362
9363     for (i = stream->ctts_index; i < n_composition_times; i++) {
9364       if (stream->ctts_sample_index >= stream->ctts_count
9365           || !stream->ctts_sample_index) {
9366         stream->ctts_count =
9367             gst_byte_reader_get_uint32_be_unchecked (&stream->ctts);
9368         stream->ctts_soffset =
9369             gst_byte_reader_get_int32_be_unchecked (&stream->ctts);
9370         stream->ctts_sample_index = 0;
9371       }
9372
9373       ctts_count = stream->ctts_count;
9374       ctts_soffset = stream->ctts_soffset;
9375
9376       for (j = stream->ctts_sample_index; j < ctts_count; j++) {
9377         cur->pts_offset = ctts_soffset;
9378         cur++;
9379
9380         if (G_UNLIKELY (cur > last)) {
9381           /* save state */
9382           stream->ctts_sample_index = j + 1;
9383           goto done;
9384         }
9385       }
9386       stream->ctts_sample_index = 0;
9387       stream->ctts_index++;
9388     }
9389   }
9390 done:
9391   stream->stbl_index = n;
9392   /* if index has been completely parsed, free data that is no-longer needed */
9393   if (n + 1 == stream->n_samples) {
9394     gst_qtdemux_stbl_free (stream);
9395     GST_DEBUG_OBJECT (qtdemux, "parsed all available samples;");
9396     if (qtdemux->pullbased) {
9397       GST_DEBUG_OBJECT (qtdemux, "checking for more samples");
9398       while (n + 1 == stream->n_samples)
9399         if (qtdemux_add_fragmented_samples (qtdemux) != GST_FLOW_OK)
9400           break;
9401     }
9402   }
9403   GST_OBJECT_UNLOCK (qtdemux);
9404
9405   return TRUE;
9406
9407   /* SUCCESS */
9408 already_parsed:
9409   {
9410     GST_LOG_OBJECT (qtdemux,
9411         "Tried to parse up to sample %u but this sample has already been parsed",
9412         n);
9413     /* if fragmented, there may be more */
9414     if (qtdemux->fragmented && n == stream->stbl_index)
9415       goto done;
9416     GST_OBJECT_UNLOCK (qtdemux);
9417     return TRUE;
9418   }
9419   /* ERRORS */
9420 out_of_samples:
9421   {
9422     GST_LOG_OBJECT (qtdemux,
9423         "Tried to parse up to sample %u but there are only %u samples", n + 1,
9424         stream->n_samples);
9425     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
9426         (_("This file is corrupt and cannot be played.")), (NULL));
9427     return FALSE;
9428   }
9429 corrupt_file:
9430   {
9431     GST_OBJECT_UNLOCK (qtdemux);
9432     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
9433         (_("This file is corrupt and cannot be played.")), (NULL));
9434     return FALSE;
9435   }
9436 }
9437
9438 /* collect all segment info for @stream.
9439  */
9440 static gboolean
9441 qtdemux_parse_segments (GstQTDemux * qtdemux, QtDemuxStream * stream,
9442     GNode * trak)
9443 {
9444   GNode *edts;
9445   /* accept edts if they contain gaps at start and there is only
9446    * one media segment */
9447   gboolean allow_pushbased_edts = TRUE;
9448   gint media_segments_count = 0;
9449
9450   /* parse and prepare segment info from the edit list */
9451   GST_DEBUG_OBJECT (qtdemux, "looking for edit list container");
9452   stream->n_segments = 0;
9453   stream->segments = NULL;
9454   if ((edts = qtdemux_tree_get_child_by_type (trak, FOURCC_edts))) {
9455     GNode *elst;
9456     gint n_segments;
9457     gint segment_number, entry_size;
9458     guint64 time;
9459     GstClockTime stime;
9460     const guint8 *buffer;
9461     guint8 version;
9462     guint32 size;
9463
9464     GST_DEBUG_OBJECT (qtdemux, "looking for edit list");
9465     if (!(elst = qtdemux_tree_get_child_by_type (edts, FOURCC_elst)))
9466       goto done;
9467
9468     buffer = elst->data;
9469
9470     size = QT_UINT32 (buffer);
9471     /* version, flags, n_segments */
9472     if (size < 16) {
9473       GST_WARNING_OBJECT (qtdemux, "Invalid edit list");
9474       goto done;
9475     }
9476     version = QT_UINT8 (buffer + 8);
9477     entry_size = (version == 1) ? 20 : 12;
9478
9479     n_segments = QT_UINT32 (buffer + 12);
9480
9481     if (n_segments > 100000 || size < 16 + n_segments * entry_size) {
9482       GST_WARNING_OBJECT (qtdemux, "Invalid edit list");
9483       goto done;
9484     }
9485
9486     /* we might allocate a bit too much, at least allocate 1 segment */
9487     stream->segments = g_new (QtDemuxSegment, MAX (n_segments, 1));
9488
9489     /* segments always start from 0 */
9490     time = 0;
9491     stime = 0;
9492     buffer += 16;
9493     for (segment_number = 0; segment_number < n_segments; segment_number++) {
9494       guint64 duration;
9495       guint64 media_time;
9496       gboolean empty_edit = FALSE;
9497       QtDemuxSegment *segment;
9498       guint32 rate_int;
9499       GstClockTime media_start = GST_CLOCK_TIME_NONE;
9500
9501       if (version == 1) {
9502         media_time = QT_UINT64 (buffer + 8);
9503         duration = QT_UINT64 (buffer);
9504         if (media_time == G_MAXUINT64)
9505           empty_edit = TRUE;
9506       } else {
9507         media_time = QT_UINT32 (buffer + 4);
9508         duration = QT_UINT32 (buffer);
9509         if (media_time == G_MAXUINT32)
9510           empty_edit = TRUE;
9511       }
9512
9513       if (!empty_edit)
9514         media_start = QTSTREAMTIME_TO_GSTTIME (stream, media_time);
9515
9516       segment = &stream->segments[segment_number];
9517
9518       /* time and duration expressed in global timescale */
9519       segment->time = stime;
9520       if (duration != 0 || empty_edit) {
9521         /* edge case: empty edits with duration=zero are treated here.
9522          * (files should not have these anyway). */
9523
9524         /* add non scaled values so we don't cause roundoff errors */
9525         time += duration;
9526         stime = QTTIME_TO_GSTTIME (qtdemux, time);
9527         segment->duration = stime - segment->time;
9528       } else {
9529         /* zero duration does not imply media_start == media_stop
9530          * but, only specify media_start. The edit ends with the track. */
9531         stime = segment->duration = GST_CLOCK_TIME_NONE;
9532         /* Don't allow more edits after this one. */
9533         n_segments = segment_number + 1;
9534       }
9535       segment->stop_time = stime;
9536
9537       segment->trak_media_start = media_time;
9538       /* media_time expressed in stream timescale */
9539       if (!empty_edit) {
9540         segment->media_start = media_start;
9541         segment->media_stop = GST_CLOCK_TIME_IS_VALID (segment->duration)
9542             ? segment->media_start + segment->duration : GST_CLOCK_TIME_NONE;
9543         media_segments_count++;
9544       } else {
9545         segment->media_start = GST_CLOCK_TIME_NONE;
9546         segment->media_stop = GST_CLOCK_TIME_NONE;
9547       }
9548       rate_int = QT_UINT32 (buffer + ((version == 1) ? 16 : 8));
9549
9550       if (rate_int <= 1) {
9551         /* 0 is not allowed, some programs write 1 instead of the floating point
9552          * value */
9553         GST_WARNING_OBJECT (qtdemux, "found suspicious rate %" G_GUINT32_FORMAT,
9554             rate_int);
9555         segment->rate = 1;
9556       } else {
9557         segment->rate = rate_int / 65536.0;
9558       }
9559
9560       GST_DEBUG_OBJECT (qtdemux, "created segment %d time %" GST_TIME_FORMAT
9561           ", duration %" GST_TIME_FORMAT ", media_start %" GST_TIME_FORMAT
9562           " (%" G_GUINT64_FORMAT ") , media_stop %" GST_TIME_FORMAT
9563           " stop_time %" GST_TIME_FORMAT " rate %g, (%d) timescale %u",
9564           segment_number, GST_TIME_ARGS (segment->time),
9565           GST_TIME_ARGS (segment->duration),
9566           GST_TIME_ARGS (segment->media_start), media_time,
9567           GST_TIME_ARGS (segment->media_stop),
9568           GST_TIME_ARGS (segment->stop_time), segment->rate, rate_int,
9569           stream->timescale);
9570       if (segment->stop_time > qtdemux->segment.stop &&
9571           !qtdemux->upstream_format_is_time) {
9572         GST_WARNING_OBJECT (qtdemux, "Segment %d "
9573             " extends to %" GST_TIME_FORMAT
9574             " past the end of the declared movie duration %" GST_TIME_FORMAT
9575             " movie segment will be extended", segment_number,
9576             GST_TIME_ARGS (segment->stop_time),
9577             GST_TIME_ARGS (qtdemux->segment.stop));
9578         qtdemux->segment.stop = qtdemux->segment.duration = segment->stop_time;
9579       }
9580
9581       buffer += entry_size;
9582     }
9583     GST_DEBUG_OBJECT (qtdemux, "found %d segments", n_segments);
9584     stream->n_segments = n_segments;
9585     if (media_segments_count != 1)
9586       allow_pushbased_edts = FALSE;
9587   }
9588 done:
9589
9590   /* push based does not handle segments, so act accordingly here,
9591    * and warn if applicable */
9592   if (!qtdemux->pullbased && !allow_pushbased_edts) {
9593     GST_WARNING_OBJECT (qtdemux, "streaming; discarding edit list segments");
9594     /* remove and use default one below, we stream like it anyway */
9595     g_free (stream->segments);
9596     stream->segments = NULL;
9597     stream->n_segments = 0;
9598   }
9599
9600   /* no segments, create one to play the complete trak */
9601   if (stream->n_segments == 0) {
9602     GstClockTime stream_duration =
9603         QTSTREAMTIME_TO_GSTTIME (stream, stream->duration);
9604
9605     if (stream->segments == NULL)
9606       stream->segments = g_new (QtDemuxSegment, 1);
9607
9608     /* represent unknown our way */
9609     if (stream_duration == 0)
9610       stream_duration = GST_CLOCK_TIME_NONE;
9611
9612     stream->segments[0].time = 0;
9613     stream->segments[0].stop_time = stream_duration;
9614     stream->segments[0].duration = stream_duration;
9615     stream->segments[0].media_start = 0;
9616     stream->segments[0].media_stop = stream_duration;
9617     stream->segments[0].rate = 1.0;
9618     stream->segments[0].trak_media_start = 0;
9619
9620     GST_DEBUG_OBJECT (qtdemux, "created dummy segment %" GST_TIME_FORMAT,
9621         GST_TIME_ARGS (stream_duration));
9622     stream->n_segments = 1;
9623     stream->dummy_segment = TRUE;
9624   }
9625   GST_DEBUG_OBJECT (qtdemux, "using %d segments", stream->n_segments);
9626
9627   return TRUE;
9628 }
9629
9630 /*
9631  * Parses the stsd atom of a svq3 trak looking for
9632  * the SMI and gama atoms.
9633  */
9634 static void
9635 qtdemux_parse_svq3_stsd_data (GstQTDemux * qtdemux,
9636     const guint8 * stsd_entry_data, const guint8 ** gamma, GstBuffer ** seqh)
9637 {
9638   const guint8 *_gamma = NULL;
9639   GstBuffer *_seqh = NULL;
9640   const guint8 *stsd_data = stsd_entry_data;
9641   guint32 length = QT_UINT32 (stsd_data);
9642   guint16 version;
9643
9644   if (length < 32) {
9645     GST_WARNING_OBJECT (qtdemux, "stsd too short");
9646     goto end;
9647   }
9648
9649   stsd_data += 16;
9650   length -= 16;
9651   version = QT_UINT16 (stsd_data);
9652   if (version == 3) {
9653     if (length >= 70) {
9654       length -= 70;
9655       stsd_data += 70;
9656       while (length > 8) {
9657         guint32 fourcc, size;
9658         const guint8 *data;
9659         size = QT_UINT32 (stsd_data);
9660         fourcc = QT_FOURCC (stsd_data + 4);
9661         data = stsd_data + 8;
9662
9663         if (size == 0) {
9664           GST_WARNING_OBJECT (qtdemux, "Atom of size 0 found, aborting "
9665               "svq3 atom parsing");
9666           goto end;
9667         }
9668
9669         switch (fourcc) {
9670           case FOURCC_gama:{
9671             if (size == 12) {
9672               _gamma = data;
9673             } else {
9674               GST_WARNING_OBJECT (qtdemux, "Unexpected size %" G_GUINT32_FORMAT
9675                   " for gama atom, expected 12", size);
9676             }
9677             break;
9678           }
9679           case FOURCC_SMI_:{
9680             if (size > 16 && QT_FOURCC (data) == FOURCC_SEQH) {
9681               guint32 seqh_size;
9682               if (_seqh != NULL) {
9683                 GST_WARNING_OBJECT (qtdemux, "Unexpected second SEQH SMI atom "
9684                     " found, ignoring");
9685               } else {
9686                 seqh_size = QT_UINT32 (data + 4);
9687                 if (seqh_size > 0) {
9688                   _seqh = gst_buffer_new_and_alloc (seqh_size);
9689                   gst_buffer_fill (_seqh, 0, data + 8, seqh_size);
9690                 }
9691               }
9692             }
9693             break;
9694           }
9695           default:{
9696             GST_WARNING_OBJECT (qtdemux, "Unhandled atom %" GST_FOURCC_FORMAT
9697                 " in SVQ3 entry in stsd atom", GST_FOURCC_ARGS (fourcc));
9698           }
9699         }
9700
9701         if (size <= length) {
9702           length -= size;
9703           stsd_data += size;
9704         }
9705       }
9706     } else {
9707       GST_WARNING_OBJECT (qtdemux, "SVQ3 entry too short in stsd atom");
9708     }
9709   } else {
9710     GST_WARNING_OBJECT (qtdemux, "Unexpected version for SVQ3 entry %"
9711         G_GUINT16_FORMAT, version);
9712     goto end;
9713   }
9714
9715 end:
9716   if (gamma) {
9717     *gamma = _gamma;
9718   }
9719   if (seqh) {
9720     *seqh = _seqh;
9721   } else if (_seqh) {
9722     gst_buffer_unref (_seqh);
9723   }
9724 }
9725
9726 static gchar *
9727 qtdemux_get_rtsp_uri_from_hndl (GstQTDemux * qtdemux, GNode * minf)
9728 {
9729   GNode *dinf;
9730   GstByteReader dref;
9731   gchar *uri = NULL;
9732
9733   /*
9734    * Get 'dinf', to get its child 'dref', that might contain a 'hndl'
9735    * atom that might contain a 'data' atom with the rtsp uri.
9736    * This case was reported in bug #597497, some info about
9737    * the hndl atom can be found in TN1195
9738    */
9739   dinf = qtdemux_tree_get_child_by_type (minf, FOURCC_dinf);
9740   GST_DEBUG_OBJECT (qtdemux, "Trying to obtain rtsp URI for stream trak");
9741
9742   if (dinf) {
9743     guint32 dref_num_entries = 0;
9744     if (qtdemux_tree_get_child_by_type_full (dinf, FOURCC_dref, &dref) &&
9745         gst_byte_reader_skip (&dref, 4) &&
9746         gst_byte_reader_get_uint32_be (&dref, &dref_num_entries)) {
9747       gint i;
9748
9749       /* search dref entries for hndl atom */
9750       for (i = 0; i < dref_num_entries; i++) {
9751         guint32 size = 0, type;
9752         guint8 string_len = 0;
9753         if (gst_byte_reader_get_uint32_be (&dref, &size) &&
9754             qt_atom_parser_get_fourcc (&dref, &type)) {
9755           if (type == FOURCC_hndl) {
9756             GST_DEBUG_OBJECT (qtdemux, "Found hndl atom");
9757
9758             /* skip data reference handle bytes and the
9759              * following pascal string and some extra 4
9760              * bytes I have no idea what are */
9761             if (!gst_byte_reader_skip (&dref, 4) ||
9762                 !gst_byte_reader_get_uint8 (&dref, &string_len) ||
9763                 !gst_byte_reader_skip (&dref, string_len + 4)) {
9764               GST_WARNING_OBJECT (qtdemux, "Failed to parse hndl atom");
9765               break;
9766             }
9767
9768             /* iterate over the atoms to find the data atom */
9769             while (gst_byte_reader_get_remaining (&dref) >= 8) {
9770               guint32 atom_size;
9771               guint32 atom_type;
9772
9773               if (gst_byte_reader_get_uint32_be (&dref, &atom_size) &&
9774                   qt_atom_parser_get_fourcc (&dref, &atom_type)) {
9775                 if (atom_type == FOURCC_data) {
9776                   const guint8 *uri_aux = NULL;
9777
9778                   /* found the data atom that might contain the rtsp uri */
9779                   GST_DEBUG_OBJECT (qtdemux, "Found data atom inside "
9780                       "hndl atom, interpreting it as an URI");
9781                   if (gst_byte_reader_peek_data (&dref, atom_size - 8,
9782                           &uri_aux)) {
9783                     if (g_strstr_len ((gchar *) uri_aux, 7, "rtsp://") != NULL)
9784                       uri = g_strndup ((gchar *) uri_aux, atom_size - 8);
9785                     else
9786                       GST_WARNING_OBJECT (qtdemux, "Data atom in hndl atom "
9787                           "didn't contain a rtsp address");
9788                   } else {
9789                     GST_WARNING_OBJECT (qtdemux, "Failed to get the data "
9790                         "atom contents");
9791                   }
9792                   break;
9793                 }
9794                 /* skipping to the next entry */
9795                 if (!gst_byte_reader_skip (&dref, atom_size - 8))
9796                   break;
9797               } else {
9798                 GST_WARNING_OBJECT (qtdemux, "Failed to parse hndl child "
9799                     "atom header");
9800                 break;
9801               }
9802             }
9803             break;
9804           }
9805           /* skip to the next entry */
9806           if (!gst_byte_reader_skip (&dref, size - 8))
9807             break;
9808         } else {
9809           GST_WARNING_OBJECT (qtdemux, "Error parsing dref atom");
9810         }
9811       }
9812       GST_DEBUG_OBJECT (qtdemux, "Finished parsing dref atom");
9813     }
9814   }
9815   return uri;
9816 }
9817
9818 #define AMR_NB_ALL_MODES        0x81ff
9819 #define AMR_WB_ALL_MODES        0x83ff
9820 static guint
9821 qtdemux_parse_amr_bitrate (GstBuffer * buf, gboolean wb)
9822 {
9823   /* The 'damr' atom is of the form:
9824    *
9825    * | vendor | decoder_ver | mode_set | mode_change_period | frames/sample |
9826    *    32 b       8 b          16 b           8 b                 8 b
9827    *
9828    * The highest set bit of the first 7 (AMR-NB) or 8 (AMR-WB) bits of mode_set
9829    * represents the highest mode used in the stream (and thus the maximum
9830    * bitrate), with a couple of special cases as seen below.
9831    */
9832
9833   /* Map of frame type ID -> bitrate */
9834   static const guint nb_bitrates[] = {
9835     4750, 5150, 5900, 6700, 7400, 7950, 10200, 12200
9836   };
9837   static const guint wb_bitrates[] = {
9838     6600, 8850, 12650, 14250, 15850, 18250, 19850, 23050, 23850
9839   };
9840   GstMapInfo map;
9841   gsize max_mode;
9842   guint16 mode_set;
9843
9844   gst_buffer_map (buf, &map, GST_MAP_READ);
9845
9846   if (map.size != 0x11) {
9847     GST_DEBUG ("Atom should have size 0x11, not %" G_GSIZE_FORMAT, map.size);
9848     goto bad_data;
9849   }
9850
9851   if (QT_FOURCC (map.data + 4) != FOURCC_damr) {
9852     GST_DEBUG ("Unknown atom in %" GST_FOURCC_FORMAT,
9853         GST_FOURCC_ARGS (QT_UINT32 (map.data + 4)));
9854     goto bad_data;
9855   }
9856
9857   mode_set = QT_UINT16 (map.data + 13);
9858
9859   if (mode_set == (wb ? AMR_WB_ALL_MODES : AMR_NB_ALL_MODES))
9860     max_mode = 7 + (wb ? 1 : 0);
9861   else
9862     /* AMR-NB modes fo from 0-7, and AMR-WB modes go from 0-8 */
9863     max_mode = g_bit_nth_msf ((gulong) mode_set & (wb ? 0x1ff : 0xff), -1);
9864
9865   if (max_mode == -1) {
9866     GST_DEBUG ("No mode indication was found (mode set) = %x",
9867         (guint) mode_set);
9868     goto bad_data;
9869   }
9870
9871   gst_buffer_unmap (buf, &map);
9872   return wb ? wb_bitrates[max_mode] : nb_bitrates[max_mode];
9873
9874 bad_data:
9875   gst_buffer_unmap (buf, &map);
9876   return 0;
9877 }
9878
9879 static gboolean
9880 qtdemux_parse_transformation_matrix (GstQTDemux * qtdemux,
9881     GstByteReader * reader, guint32 * matrix, const gchar * atom)
9882 {
9883   /*
9884    * 9 values of 32 bits (fixed point 16.16, except 2 5 and 8 that are 2.30)
9885    * [0 1 2]
9886    * [3 4 5]
9887    * [6 7 8]
9888    */
9889
9890   if (gst_byte_reader_get_remaining (reader) < 36)
9891     return FALSE;
9892
9893   matrix[0] = gst_byte_reader_get_uint32_be_unchecked (reader);
9894   matrix[1] = gst_byte_reader_get_uint32_be_unchecked (reader);
9895   matrix[2] = gst_byte_reader_get_uint32_be_unchecked (reader);
9896   matrix[3] = gst_byte_reader_get_uint32_be_unchecked (reader);
9897   matrix[4] = gst_byte_reader_get_uint32_be_unchecked (reader);
9898   matrix[5] = gst_byte_reader_get_uint32_be_unchecked (reader);
9899   matrix[6] = gst_byte_reader_get_uint32_be_unchecked (reader);
9900   matrix[7] = gst_byte_reader_get_uint32_be_unchecked (reader);
9901   matrix[8] = gst_byte_reader_get_uint32_be_unchecked (reader);
9902
9903   GST_DEBUG_OBJECT (qtdemux, "Transformation matrix from atom %s", atom);
9904   GST_DEBUG_OBJECT (qtdemux, "%u.%u %u.%u %u.%u", matrix[0] >> 16,
9905       matrix[0] & 0xFFFF, matrix[1] >> 16, matrix[1] & 0xFF, matrix[2] >> 16,
9906       matrix[2] & 0xFF);
9907   GST_DEBUG_OBJECT (qtdemux, "%u.%u %u.%u %u.%u", matrix[3] >> 16,
9908       matrix[3] & 0xFFFF, matrix[4] >> 16, matrix[4] & 0xFF, matrix[5] >> 16,
9909       matrix[5] & 0xFF);
9910   GST_DEBUG_OBJECT (qtdemux, "%u.%u %u.%u %u.%u", matrix[6] >> 16,
9911       matrix[6] & 0xFFFF, matrix[7] >> 16, matrix[7] & 0xFF, matrix[8] >> 16,
9912       matrix[8] & 0xFF);
9913
9914   return TRUE;
9915 }
9916
9917 static void
9918 qtdemux_inspect_transformation_matrix (GstQTDemux * qtdemux,
9919     QtDemuxStream * stream, guint32 * matrix, GstTagList ** taglist)
9920 {
9921
9922 /* [a b c]
9923  * [d e f]
9924  * [g h i]
9925  *
9926  * This macro will only compare value abdegh, it expects cfi to have already
9927  * been checked
9928  */
9929 #define QTCHECK_MATRIX(m,a,b,d,e) ((m)[0] == (a << 16) && (m)[1] == (b << 16) && \
9930                                    (m)[3] == (d << 16) && (m)[4] == (e << 16))
9931
9932   /* only handle the cases where the last column has standard values */
9933   if (matrix[2] == 0 && matrix[5] == 0 && matrix[8] == 1 << 30) {
9934     const gchar *rotation_tag = NULL;
9935
9936     /* no rotation needed */
9937     if (QTCHECK_MATRIX (matrix, 1, 0, 0, 1)) {
9938       /* NOP */
9939     } else if (QTCHECK_MATRIX (matrix, 0, 1, G_MAXUINT16, 0)) {
9940       rotation_tag = "rotate-90";
9941     } else if (QTCHECK_MATRIX (matrix, G_MAXUINT16, 0, 0, G_MAXUINT16)) {
9942       rotation_tag = "rotate-180";
9943     } else if (QTCHECK_MATRIX (matrix, 0, G_MAXUINT16, 1, 0)) {
9944       rotation_tag = "rotate-270";
9945     } else {
9946       GST_FIXME_OBJECT (qtdemux, "Unhandled transformation matrix values");
9947     }
9948
9949     GST_DEBUG_OBJECT (qtdemux, "Transformation matrix rotation %s",
9950         rotation_tag);
9951     if (rotation_tag != NULL) {
9952       if (*taglist == NULL)
9953         *taglist = gst_tag_list_new_empty ();
9954       gst_tag_list_add (*taglist, GST_TAG_MERGE_REPLACE,
9955           GST_TAG_IMAGE_ORIENTATION, rotation_tag, NULL);
9956     }
9957   } else {
9958     GST_FIXME_OBJECT (qtdemux, "Unhandled transformation matrix values");
9959   }
9960 }
9961
9962 /* Parses the boxes defined in ISO/IEC 14496-12 that enable support for
9963  * protected streams (sinf, frma, schm and schi); if the protection scheme is
9964  * Common Encryption (cenc), the function will also parse the tenc box (defined
9965  * in ISO/IEC 23001-7). @container points to the node that contains these boxes
9966  * (typically an enc[v|a|t|s] sample entry); the function will set
9967  * @original_fmt to the fourcc of the original unencrypted stream format.
9968  * Returns TRUE if successful; FALSE otherwise. */
9969 static gboolean
9970 qtdemux_parse_protection_scheme_info (GstQTDemux * qtdemux,
9971     QtDemuxStream * stream, GNode * container, guint32 * original_fmt)
9972 {
9973   GNode *sinf;
9974   GNode *frma;
9975   GNode *schm;
9976   GNode *schi;
9977   QtDemuxCencSampleSetInfo *info;
9978   GNode *tenc;
9979   const guint8 *tenc_data;
9980
9981   g_return_val_if_fail (qtdemux != NULL, FALSE);
9982   g_return_val_if_fail (stream != NULL, FALSE);
9983   g_return_val_if_fail (container != NULL, FALSE);
9984   g_return_val_if_fail (original_fmt != NULL, FALSE);
9985
9986   sinf = qtdemux_tree_get_child_by_type (container, FOURCC_sinf);
9987   if (G_UNLIKELY (!sinf)) {
9988     if (stream->protection_scheme_type == FOURCC_cenc) {
9989       GST_ERROR_OBJECT (qtdemux, "sinf box does not contain schi box, which is "
9990           "mandatory for Common Encryption");
9991       return FALSE;
9992     }
9993     return TRUE;
9994   }
9995
9996   frma = qtdemux_tree_get_child_by_type (sinf, FOURCC_frma);
9997   if (G_UNLIKELY (!frma)) {
9998     GST_ERROR_OBJECT (qtdemux, "sinf box does not contain mandatory frma box");
9999     return FALSE;
10000   }
10001
10002   *original_fmt = QT_FOURCC ((const guint8 *) frma->data + 8);
10003   GST_DEBUG_OBJECT (qtdemux, "original stream format: '%" GST_FOURCC_FORMAT "'",
10004       GST_FOURCC_ARGS (*original_fmt));
10005
10006   schm = qtdemux_tree_get_child_by_type (sinf, FOURCC_schm);
10007   if (!schm) {
10008     GST_DEBUG_OBJECT (qtdemux, "sinf box does not contain schm box");
10009     return FALSE;
10010   }
10011   stream->protection_scheme_type = QT_FOURCC ((const guint8 *) schm->data + 12);
10012   stream->protection_scheme_version =
10013       QT_UINT32 ((const guint8 *) schm->data + 16);
10014
10015   GST_DEBUG_OBJECT (qtdemux,
10016       "protection_scheme_type: %" GST_FOURCC_FORMAT ", "
10017       "protection_scheme_version: %#010x",
10018       GST_FOURCC_ARGS (stream->protection_scheme_type),
10019       stream->protection_scheme_version);
10020
10021   schi = qtdemux_tree_get_child_by_type (sinf, FOURCC_schi);
10022   if (!schi) {
10023     GST_DEBUG_OBJECT (qtdemux, "sinf box does not contain schi box");
10024     return FALSE;
10025   }
10026   if (stream->protection_scheme_type != FOURCC_cenc &&
10027       stream->protection_scheme_type != FOURCC_piff) {
10028     GST_ERROR_OBJECT (qtdemux,
10029         "Invalid protection_scheme_type: %" GST_FOURCC_FORMAT,
10030         GST_FOURCC_ARGS (stream->protection_scheme_type));
10031     return FALSE;
10032   }
10033
10034   if (G_UNLIKELY (!stream->protection_scheme_info))
10035     stream->protection_scheme_info =
10036         g_malloc0 (sizeof (QtDemuxCencSampleSetInfo));
10037
10038   info = (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
10039
10040   if (stream->protection_scheme_type == FOURCC_cenc) {
10041     guint32 is_encrypted;
10042     guint8 iv_size;
10043     const guint8 *default_kid;
10044
10045     tenc = qtdemux_tree_get_child_by_type (schi, FOURCC_tenc);
10046     if (!tenc) {
10047       GST_ERROR_OBJECT (qtdemux, "schi box does not contain tenc box, "
10048           "which is mandatory for Common Encryption");
10049       return FALSE;
10050     }
10051     tenc_data = (const guint8 *) tenc->data + 12;
10052     is_encrypted = QT_UINT24 (tenc_data);
10053     iv_size = QT_UINT8 (tenc_data + 3);
10054     default_kid = (tenc_data + 4);
10055     qtdemux_update_default_sample_encryption_settings (qtdemux, info,
10056         is_encrypted, iv_size, default_kid);
10057   } else if (stream->protection_scheme_type == FOURCC_piff) {
10058     GstByteReader br;
10059     static const guint8 piff_track_encryption_uuid[] = {
10060       0x89, 0x74, 0xdb, 0xce, 0x7b, 0xe7, 0x4c, 0x51,
10061       0x84, 0xf9, 0x71, 0x48, 0xf9, 0x88, 0x25, 0x54
10062     };
10063
10064     tenc = qtdemux_tree_get_child_by_type (schi, FOURCC_uuid);
10065     if (!tenc) {
10066       GST_ERROR_OBJECT (qtdemux, "schi box does not contain tenc box, "
10067           "which is mandatory for Common Encryption");
10068       return FALSE;
10069     }
10070
10071     tenc_data = (const guint8 *) tenc->data + 8;
10072     if (memcmp (tenc_data, piff_track_encryption_uuid, 16) != 0) {
10073       gchar *box_uuid = qtdemux_uuid_bytes_to_string (tenc_data);
10074       GST_ERROR_OBJECT (qtdemux,
10075           "Unsupported track encryption box with uuid: %s", box_uuid);
10076       g_free (box_uuid);
10077       return FALSE;
10078     }
10079     tenc_data = (const guint8 *) tenc->data + 16 + 12;
10080     gst_byte_reader_init (&br, tenc_data, 20);
10081     if (!qtdemux_update_default_piff_encryption_settings (qtdemux, info, &br)) {
10082       GST_ERROR_OBJECT (qtdemux, "PIFF track box parsing error");
10083       return FALSE;
10084     }
10085     stream->protection_scheme_type = FOURCC_cenc;
10086   }
10087
10088   return TRUE;
10089 }
10090
10091 static gint
10092 qtdemux_track_id_compare_func (QtDemuxStream * stream1, QtDemuxStream * stream2)
10093 {
10094   return (gint) stream1->track_id - (gint) stream2->track_id;
10095 }
10096
10097 /* parse the traks.
10098  * With each track we associate a new QtDemuxStream that contains all the info
10099  * about the trak.
10100  * traks that do not decode to something (like strm traks) will not have a pad.
10101  */
10102 static gboolean
10103 qtdemux_parse_trak (GstQTDemux * qtdemux, GNode * trak)
10104 {
10105   GstByteReader tkhd;
10106   int offset;
10107   GNode *mdia;
10108   GNode *mdhd;
10109   GNode *hdlr;
10110   GNode *minf;
10111   GNode *stbl;
10112   GNode *stsd;
10113   GNode *mp4a;
10114   GNode *mp4v;
10115   GNode *esds;
10116   GNode *tref;
10117   GNode *udta;
10118   GNode *svmi;
10119
10120   QtDemuxStream *stream = NULL;
10121   const guint8 *stsd_data;
10122   const guint8 *stsd_entry_data;
10123   guint remaining_stsd_len;
10124   guint stsd_entry_count;
10125   guint stsd_index;
10126   guint16 lang_code;            /* quicktime lang code or packed iso code */
10127   guint32 version;
10128   guint32 tkhd_flags = 0;
10129   guint8 tkhd_version = 0;
10130   guint32 w = 0, h = 0;
10131   guint value_size, stsd_len, len;
10132   guint32 track_id;
10133   guint32 dummy;
10134
10135   GST_DEBUG_OBJECT (qtdemux, "parse_trak");
10136
10137   if (!qtdemux_tree_get_child_by_type_full (trak, FOURCC_tkhd, &tkhd)
10138       || !gst_byte_reader_get_uint8 (&tkhd, &tkhd_version)
10139       || !gst_byte_reader_get_uint24_be (&tkhd, &tkhd_flags))
10140     goto corrupt_file;
10141
10142   /* pick between 64 or 32 bits */
10143   value_size = tkhd_version == 1 ? 8 : 4;
10144   if (!gst_byte_reader_skip (&tkhd, value_size * 2) ||
10145       !gst_byte_reader_get_uint32_be (&tkhd, &track_id))
10146     goto corrupt_file;
10147
10148   /* Check if current moov has duplicated track_id */
10149   if (qtdemux_find_stream (qtdemux, track_id))
10150     goto existing_stream;
10151
10152   stream = _create_stream (qtdemux, track_id);
10153   stream->stream_tags = gst_tag_list_make_writable (stream->stream_tags);
10154
10155   /* need defaults for fragments */
10156   qtdemux_parse_trex (qtdemux, stream, &dummy, &dummy, &dummy);
10157
10158   if ((tkhd_flags & 1) == 0)
10159     stream->disabled = TRUE;
10160
10161   GST_LOG_OBJECT (qtdemux, "track[tkhd] version/flags/id: 0x%02x/%06x/%u",
10162       tkhd_version, tkhd_flags, stream->track_id);
10163
10164   if (!(mdia = qtdemux_tree_get_child_by_type (trak, FOURCC_mdia)))
10165     goto corrupt_file;
10166
10167   if (!(mdhd = qtdemux_tree_get_child_by_type (mdia, FOURCC_mdhd))) {
10168     /* be nice for some crooked mjp2 files that use mhdr for mdhd */
10169     if (qtdemux->major_brand != FOURCC_mjp2 ||
10170         !(mdhd = qtdemux_tree_get_child_by_type (mdia, FOURCC_mhdr)))
10171       goto corrupt_file;
10172   }
10173
10174   len = QT_UINT32 ((guint8 *) mdhd->data);
10175   version = QT_UINT32 ((guint8 *) mdhd->data + 8);
10176   GST_LOG_OBJECT (qtdemux, "track version/flags: %08x", version);
10177   if (version == 0x01000000) {
10178     if (len < 38)
10179       goto corrupt_file;
10180     stream->timescale = QT_UINT32 ((guint8 *) mdhd->data + 28);
10181     stream->duration = QT_UINT64 ((guint8 *) mdhd->data + 32);
10182     lang_code = QT_UINT16 ((guint8 *) mdhd->data + 36);
10183   } else {
10184     if (len < 30)
10185       goto corrupt_file;
10186     stream->timescale = QT_UINT32 ((guint8 *) mdhd->data + 20);
10187     stream->duration = QT_UINT32 ((guint8 *) mdhd->data + 24);
10188     lang_code = QT_UINT16 ((guint8 *) mdhd->data + 28);
10189   }
10190
10191   if (lang_code < 0x400) {
10192     qtdemux_lang_map_qt_code_to_iso (stream->lang_id, lang_code);
10193   } else if (lang_code == 0x7fff) {
10194     stream->lang_id[0] = 0;     /* unspecified */
10195   } else {
10196     stream->lang_id[0] = 0x60 + ((lang_code >> 10) & 0x1F);
10197     stream->lang_id[1] = 0x60 + ((lang_code >> 5) & 0x1F);
10198     stream->lang_id[2] = 0x60 + (lang_code & 0x1F);
10199     stream->lang_id[3] = 0;
10200   }
10201
10202   GST_LOG_OBJECT (qtdemux, "track timescale: %" G_GUINT32_FORMAT,
10203       stream->timescale);
10204   GST_LOG_OBJECT (qtdemux, "track duration: %" G_GUINT64_FORMAT,
10205       stream->duration);
10206   GST_LOG_OBJECT (qtdemux, "track language code/id: 0x%04x/%s",
10207       lang_code, stream->lang_id);
10208
10209   if (G_UNLIKELY (stream->timescale == 0 || qtdemux->timescale == 0))
10210     goto corrupt_file;
10211
10212   if ((tref = qtdemux_tree_get_child_by_type (trak, FOURCC_tref))) {
10213     /* chapters track reference */
10214     GNode *chap = qtdemux_tree_get_child_by_type (tref, FOURCC_chap);
10215     if (chap) {
10216       gsize length = GST_READ_UINT32_BE (chap->data);
10217       if (qtdemux->chapters_track_id)
10218         GST_FIXME_OBJECT (qtdemux, "Multiple CHAP tracks");
10219
10220       if (length >= 12) {
10221         qtdemux->chapters_track_id =
10222             GST_READ_UINT32_BE ((gint8 *) chap->data + 8);
10223       }
10224     }
10225   }
10226
10227   /* fragmented files may have bogus duration in moov */
10228   if (!qtdemux->fragmented &&
10229       qtdemux->duration != G_MAXINT64 && stream->duration != G_MAXINT32) {
10230     guint64 tdur1, tdur2;
10231
10232     /* don't overflow */
10233     tdur1 = stream->timescale * (guint64) qtdemux->duration;
10234     tdur2 = qtdemux->timescale * (guint64) stream->duration;
10235
10236     /* HACK:
10237      * some of those trailers, nowadays, have prologue images that are
10238      * themselves video tracks as well. I haven't really found a way to
10239      * identify those yet, except for just looking at their duration. */
10240     if (tdur1 != 0 && (tdur2 * 10 / tdur1) < 2) {
10241       GST_WARNING_OBJECT (qtdemux,
10242           "Track shorter than 20%% (%" G_GUINT64_FORMAT "/%" G_GUINT32_FORMAT
10243           " vs. %" G_GUINT64_FORMAT "/%" G_GUINT32_FORMAT ") of the stream "
10244           "found, assuming preview image or something; skipping track",
10245           stream->duration, stream->timescale, qtdemux->duration,
10246           qtdemux->timescale);
10247       gst_qtdemux_stream_free (stream);
10248       return TRUE;
10249     }
10250   }
10251
10252   if (!(hdlr = qtdemux_tree_get_child_by_type (mdia, FOURCC_hdlr)))
10253     goto corrupt_file;
10254
10255   GST_LOG_OBJECT (qtdemux, "track type: %" GST_FOURCC_FORMAT,
10256       GST_FOURCC_ARGS (QT_FOURCC ((guint8 *) hdlr->data + 12)));
10257
10258   len = QT_UINT32 ((guint8 *) hdlr->data);
10259   if (len >= 20)
10260     stream->subtype = QT_FOURCC ((guint8 *) hdlr->data + 16);
10261   GST_LOG_OBJECT (qtdemux, "track subtype: %" GST_FOURCC_FORMAT,
10262       GST_FOURCC_ARGS (stream->subtype));
10263
10264   if (!(minf = qtdemux_tree_get_child_by_type (mdia, FOURCC_minf)))
10265     goto corrupt_file;
10266
10267   if (!(stbl = qtdemux_tree_get_child_by_type (minf, FOURCC_stbl)))
10268     goto corrupt_file;
10269
10270   /*parse svmi header if existing */
10271   svmi = qtdemux_tree_get_child_by_type (stbl, FOURCC_svmi);
10272   if (svmi) {
10273     len = QT_UINT32 ((guint8 *) svmi->data);
10274     version = QT_UINT32 ((guint8 *) svmi->data + 8);
10275     if (!version) {
10276       GstVideoMultiviewMode mode = GST_VIDEO_MULTIVIEW_MODE_NONE;
10277       GstVideoMultiviewFlags flags = GST_VIDEO_MULTIVIEW_FLAGS_NONE;
10278       guint8 frame_type, frame_layout;
10279
10280       /* MPEG-A stereo video */
10281       if (qtdemux->major_brand == FOURCC_ss02)
10282         flags |= GST_VIDEO_MULTIVIEW_FLAGS_MIXED_MONO;
10283
10284       frame_type = QT_UINT8 ((guint8 *) svmi->data + 12);
10285       frame_layout = QT_UINT8 ((guint8 *) svmi->data + 13) & 0x01;
10286       switch (frame_type) {
10287         case 0:
10288           mode = GST_VIDEO_MULTIVIEW_MODE_SIDE_BY_SIDE;
10289           break;
10290         case 1:
10291           mode = GST_VIDEO_MULTIVIEW_MODE_ROW_INTERLEAVED;
10292           break;
10293         case 2:
10294           mode = GST_VIDEO_MULTIVIEW_MODE_FRAME_BY_FRAME;
10295           break;
10296         case 3:
10297           /* mode 3 is primary/secondary view sequence, ie
10298            * left/right views in separate tracks. See section 7.2
10299            * of ISO/IEC 23000-11:2009 */
10300           GST_FIXME_OBJECT (qtdemux,
10301               "Implement stereo video in separate streams");
10302       }
10303
10304       if ((frame_layout & 0x1) == 0)
10305         flags |= GST_VIDEO_MULTIVIEW_FLAGS_RIGHT_VIEW_FIRST;
10306
10307       GST_LOG_OBJECT (qtdemux,
10308           "StereoVideo: composition type: %u, is_left_first: %u",
10309           frame_type, frame_layout);
10310       stream->multiview_mode = mode;
10311       stream->multiview_flags = flags;
10312     }
10313   }
10314
10315   /* parse rest of tkhd */
10316   if (stream->subtype == FOURCC_vide) {
10317     guint32 matrix[9];
10318
10319     /* version 1 uses some 64-bit ints */
10320     if (!gst_byte_reader_skip (&tkhd, 20 + value_size))
10321       goto corrupt_file;
10322
10323     if (!qtdemux_parse_transformation_matrix (qtdemux, &tkhd, matrix, "tkhd"))
10324       goto corrupt_file;
10325
10326     if (!gst_byte_reader_get_uint32_be (&tkhd, &w)
10327         || !gst_byte_reader_get_uint32_be (&tkhd, &h))
10328       goto corrupt_file;
10329
10330     qtdemux_inspect_transformation_matrix (qtdemux, stream, matrix,
10331         &stream->stream_tags);
10332   }
10333
10334   /* parse stsd */
10335   if (!(stsd = qtdemux_tree_get_child_by_type (stbl, FOURCC_stsd)))
10336     goto corrupt_file;
10337   stsd_data = (const guint8 *) stsd->data;
10338
10339   /* stsd should at least have one entry */
10340   stsd_len = QT_UINT32 (stsd_data);
10341   if (stsd_len < 24) {
10342     /* .. but skip stream with empty stsd produced by some Vivotek cameras */
10343     if (stream->subtype == FOURCC_vivo) {
10344       gst_qtdemux_stream_free (stream);
10345       return TRUE;
10346     } else {
10347       goto corrupt_file;
10348     }
10349   }
10350
10351   stream->stsd_entries_length = stsd_entry_count = QT_UINT32 (stsd_data + 12);
10352   stream->stsd_entries = g_new0 (QtDemuxStreamStsdEntry, stsd_entry_count);
10353   GST_LOG_OBJECT (qtdemux, "stsd len:           %d", stsd_len);
10354   GST_LOG_OBJECT (qtdemux, "stsd entry count:   %u", stsd_entry_count);
10355
10356   stsd_entry_data = stsd_data + 16;
10357   remaining_stsd_len = stsd_len - 16;
10358   for (stsd_index = 0; stsd_index < stsd_entry_count; stsd_index++) {
10359     guint32 fourcc;
10360     gchar *codec = NULL;
10361     QtDemuxStreamStsdEntry *entry = &stream->stsd_entries[stsd_index];
10362
10363     /* and that entry should fit within stsd */
10364     len = QT_UINT32 (stsd_entry_data);
10365     if (len > remaining_stsd_len)
10366       goto corrupt_file;
10367
10368     entry->fourcc = fourcc = QT_FOURCC (stsd_entry_data + 4);
10369     GST_LOG_OBJECT (qtdemux, "stsd type:          %" GST_FOURCC_FORMAT,
10370         GST_FOURCC_ARGS (entry->fourcc));
10371     GST_LOG_OBJECT (qtdemux, "stsd type len:      %d", len);
10372
10373     if ((fourcc == FOURCC_drms) || (fourcc == FOURCC_drmi))
10374       goto error_encrypted;
10375
10376     if (fourcc == FOURCC_encv || fourcc == FOURCC_enca) {
10377       /* FIXME this looks wrong, there might be multiple children
10378        * with the same type */
10379       GNode *enc = qtdemux_tree_get_child_by_type (stsd, fourcc);
10380       stream->protected = TRUE;
10381       if (!qtdemux_parse_protection_scheme_info (qtdemux, stream, enc, &fourcc))
10382         GST_ERROR_OBJECT (qtdemux, "Failed to parse protection scheme info");
10383     }
10384
10385     if (stream->subtype == FOURCC_vide) {
10386       GNode *colr;
10387       GNode *fiel;
10388       GNode *pasp;
10389       gboolean gray;
10390       gint depth, palette_size, palette_count;
10391       guint32 *palette_data = NULL;
10392
10393       entry->sampled = TRUE;
10394
10395       stream->display_width = w >> 16;
10396       stream->display_height = h >> 16;
10397
10398       offset = 16;
10399       if (len < 86)             /* TODO verify */
10400         goto corrupt_file;
10401
10402       entry->width = QT_UINT16 (stsd_entry_data + offset + 16);
10403       entry->height = QT_UINT16 (stsd_entry_data + offset + 18);
10404       entry->fps_n = 0;         /* this is filled in later */
10405       entry->fps_d = 0;         /* this is filled in later */
10406       entry->bits_per_sample = QT_UINT16 (stsd_entry_data + offset + 66);
10407       entry->color_table_id = QT_UINT16 (stsd_entry_data + offset + 68);
10408
10409       /* if color_table_id is 0, ctab atom must follow; however some files
10410        * produced by TMPEGEnc have color_table_id = 0 and no ctab atom, so
10411        * if color table is not present we'll correct the value */
10412       if (entry->color_table_id == 0 &&
10413           (len < 90
10414               || QT_FOURCC (stsd_entry_data + offset + 70) != FOURCC_ctab)) {
10415         entry->color_table_id = -1;
10416       }
10417
10418       GST_LOG_OBJECT (qtdemux, "width %d, height %d, bps %d, color table id %d",
10419           entry->width, entry->height, entry->bits_per_sample,
10420           entry->color_table_id);
10421
10422       depth = entry->bits_per_sample;
10423
10424       /* more than 32 bits means grayscale */
10425       gray = (depth > 32);
10426       /* low 32 bits specify the depth  */
10427       depth &= 0x1F;
10428
10429       /* different number of palette entries is determined by depth. */
10430       palette_count = 0;
10431       if ((depth == 1) || (depth == 2) || (depth == 4) || (depth == 8))
10432         palette_count = (1 << depth);
10433       palette_size = palette_count * 4;
10434
10435       if (entry->color_table_id) {
10436         switch (palette_count) {
10437           case 0:
10438             break;
10439           case 2:
10440             palette_data = g_memdup (ff_qt_default_palette_2, palette_size);
10441             break;
10442           case 4:
10443             palette_data = g_memdup (ff_qt_default_palette_4, palette_size);
10444             break;
10445           case 16:
10446             if (gray)
10447               palette_data =
10448                   g_memdup (ff_qt_grayscale_palette_16, palette_size);
10449             else
10450               palette_data = g_memdup (ff_qt_default_palette_16, palette_size);
10451             break;
10452           case 256:
10453             if (gray)
10454               palette_data =
10455                   g_memdup (ff_qt_grayscale_palette_256, palette_size);
10456             else
10457               palette_data = g_memdup (ff_qt_default_palette_256, palette_size);
10458             break;
10459           default:
10460             GST_ELEMENT_WARNING (qtdemux, STREAM, DEMUX,
10461                 (_("The video in this file might not play correctly.")),
10462                 ("unsupported palette depth %d", depth));
10463             break;
10464         }
10465       } else {
10466         gint i, j, start, end;
10467
10468         if (len < 94)
10469           goto corrupt_file;
10470
10471         /* read table */
10472         start = QT_UINT32 (stsd_entry_data + offset + 70);
10473         palette_count = QT_UINT16 (stsd_entry_data + offset + 74);
10474         end = QT_UINT16 (stsd_entry_data + offset + 76);
10475
10476         GST_LOG_OBJECT (qtdemux, "start %d, end %d, palette_count %d",
10477             start, end, palette_count);
10478
10479         if (end > 255)
10480           end = 255;
10481         if (start > end)
10482           start = end;
10483
10484         if (len < 94 + (end - start) * 8)
10485           goto corrupt_file;
10486
10487         /* palette is always the same size */
10488         palette_data = g_malloc0 (256 * 4);
10489         palette_size = 256 * 4;
10490
10491         for (j = 0, i = start; i <= end; j++, i++) {
10492           guint32 a, r, g, b;
10493
10494           a = QT_UINT16 (stsd_entry_data + offset + 78 + (j * 8));
10495           r = QT_UINT16 (stsd_entry_data + offset + 80 + (j * 8));
10496           g = QT_UINT16 (stsd_entry_data + offset + 82 + (j * 8));
10497           b = QT_UINT16 (stsd_entry_data + offset + 84 + (j * 8));
10498
10499           palette_data[i] = ((a & 0xff00) << 16) | ((r & 0xff00) << 8) |
10500               (g & 0xff00) | (b >> 8);
10501         }
10502       }
10503
10504       if (entry->caps)
10505         gst_caps_unref (entry->caps);
10506
10507       entry->caps =
10508           qtdemux_video_caps (qtdemux, stream, entry, fourcc, stsd_entry_data,
10509           &codec);
10510       if (G_UNLIKELY (!entry->caps)) {
10511         g_free (palette_data);
10512         goto unknown_stream;
10513       }
10514
10515       if (codec) {
10516         gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
10517             GST_TAG_VIDEO_CODEC, codec, NULL);
10518         g_free (codec);
10519         codec = NULL;
10520       }
10521
10522       if (palette_data) {
10523         GstStructure *s;
10524
10525         if (entry->rgb8_palette)
10526           gst_memory_unref (entry->rgb8_palette);
10527         entry->rgb8_palette = gst_memory_new_wrapped (GST_MEMORY_FLAG_READONLY,
10528             palette_data, palette_size, 0, palette_size, palette_data, g_free);
10529
10530         s = gst_caps_get_structure (entry->caps, 0);
10531
10532         /* non-raw video has a palette_data property. raw video has the palette as
10533          * an extra plane that we append to the output buffers before we push
10534          * them*/
10535         if (!gst_structure_has_name (s, "video/x-raw")) {
10536           GstBuffer *palette;
10537
10538           palette = gst_buffer_new ();
10539           gst_buffer_append_memory (palette, entry->rgb8_palette);
10540           entry->rgb8_palette = NULL;
10541
10542           gst_caps_set_simple (entry->caps, "palette_data",
10543               GST_TYPE_BUFFER, palette, NULL);
10544           gst_buffer_unref (palette);
10545         }
10546       } else if (palette_count != 0) {
10547         GST_ELEMENT_WARNING (qtdemux, STREAM, NOT_IMPLEMENTED,
10548             (NULL), ("Unsupported palette depth %d", depth));
10549       }
10550
10551       GST_LOG_OBJECT (qtdemux, "frame count:   %u",
10552           QT_UINT16 (stsd_entry_data + offset + 32));
10553
10554       esds = NULL;
10555       pasp = NULL;
10556       colr = NULL;
10557       fiel = NULL;
10558       /* pick 'the' stsd child */
10559       mp4v = qtdemux_tree_get_child_by_index (stsd, stsd_index);
10560       if (!stream->protected) {
10561         if (QTDEMUX_TREE_NODE_FOURCC (mp4v) != fourcc) {
10562           mp4v = NULL;
10563         }
10564       } else {
10565         if (QTDEMUX_TREE_NODE_FOURCC (mp4v) != FOURCC_encv) {
10566           mp4v = NULL;
10567         }
10568       }
10569
10570       if (mp4v) {
10571         esds = qtdemux_tree_get_child_by_type (mp4v, FOURCC_esds);
10572         pasp = qtdemux_tree_get_child_by_type (mp4v, FOURCC_pasp);
10573         colr = qtdemux_tree_get_child_by_type (mp4v, FOURCC_colr);
10574         fiel = qtdemux_tree_get_child_by_type (mp4v, FOURCC_fiel);
10575       }
10576
10577       if (pasp) {
10578         const guint8 *pasp_data = (const guint8 *) pasp->data;
10579         gint len = QT_UINT32 (pasp_data);
10580
10581         if (len == 16) {
10582           CUR_STREAM (stream)->par_w = QT_UINT32 (pasp_data + 8);
10583           CUR_STREAM (stream)->par_h = QT_UINT32 (pasp_data + 12);
10584         } else {
10585           CUR_STREAM (stream)->par_w = 0;
10586           CUR_STREAM (stream)->par_h = 0;
10587         }
10588       } else {
10589         CUR_STREAM (stream)->par_w = 0;
10590         CUR_STREAM (stream)->par_h = 0;
10591       }
10592
10593       if (fiel) {
10594         const guint8 *fiel_data = (const guint8 *) fiel->data;
10595         gint len = QT_UINT32 (fiel_data);
10596
10597         if (len == 10) {
10598           CUR_STREAM (stream)->interlace_mode = GST_READ_UINT8 (fiel_data + 8);
10599           CUR_STREAM (stream)->field_order = GST_READ_UINT8 (fiel_data + 9);
10600         }
10601       }
10602
10603       if (colr) {
10604         const guint8 *colr_data = (const guint8 *) colr->data;
10605         gint len = QT_UINT32 (colr_data);
10606
10607         if (len == 19 || len == 18) {
10608           guint32 color_type = GST_READ_UINT32_LE (colr_data + 8);
10609
10610           if (color_type == FOURCC_nclx || color_type == FOURCC_nclc) {
10611             guint16 primaries = GST_READ_UINT16_BE (colr_data + 12);
10612             guint16 transfer_function = GST_READ_UINT16_BE (colr_data + 14);
10613             guint16 matrix = GST_READ_UINT16_BE (colr_data + 16);
10614             gboolean full_range = len == 19 ? colr_data[17] >> 7 : FALSE;
10615
10616             switch (primaries) {
10617               case 1:
10618                 CUR_STREAM (stream)->colorimetry.primaries =
10619                     GST_VIDEO_COLOR_PRIMARIES_BT709;
10620                 break;
10621               case 5:
10622                 CUR_STREAM (stream)->colorimetry.primaries =
10623                     GST_VIDEO_COLOR_PRIMARIES_BT470BG;
10624                 break;
10625               case 6:
10626                 CUR_STREAM (stream)->colorimetry.primaries =
10627                     GST_VIDEO_COLOR_PRIMARIES_SMPTE170M;
10628                 break;
10629               case 9:
10630                 CUR_STREAM (stream)->colorimetry.primaries =
10631                     GST_VIDEO_COLOR_PRIMARIES_BT2020;
10632                 break;
10633               default:
10634                 break;
10635             }
10636
10637             switch (transfer_function) {
10638               case 1:
10639                 CUR_STREAM (stream)->colorimetry.transfer =
10640                     GST_VIDEO_TRANSFER_BT709;
10641                 break;
10642               case 7:
10643                 CUR_STREAM (stream)->colorimetry.transfer =
10644                     GST_VIDEO_TRANSFER_SMPTE240M;
10645                 break;
10646               default:
10647                 break;
10648             }
10649
10650             switch (matrix) {
10651               case 1:
10652                 CUR_STREAM (stream)->colorimetry.matrix =
10653                     GST_VIDEO_COLOR_MATRIX_BT709;
10654                 break;
10655               case 6:
10656                 CUR_STREAM (stream)->colorimetry.matrix =
10657                     GST_VIDEO_COLOR_MATRIX_BT601;
10658                 break;
10659               case 7:
10660                 CUR_STREAM (stream)->colorimetry.matrix =
10661                     GST_VIDEO_COLOR_MATRIX_SMPTE240M;
10662                 break;
10663               case 9:
10664                 CUR_STREAM (stream)->colorimetry.matrix =
10665                     GST_VIDEO_COLOR_MATRIX_BT2020;
10666                 break;
10667               default:
10668                 break;
10669             }
10670
10671             CUR_STREAM (stream)->colorimetry.range =
10672                 full_range ? GST_VIDEO_COLOR_RANGE_0_255 :
10673                 GST_VIDEO_COLOR_RANGE_16_235;
10674           } else {
10675             GST_DEBUG_OBJECT (qtdemux, "Unsupported color type");
10676           }
10677         } else {
10678           GST_WARNING_OBJECT (qtdemux, "Invalid colr atom size");
10679         }
10680       }
10681
10682       if (esds) {
10683         gst_qtdemux_handle_esds (qtdemux, stream, entry, esds,
10684             stream->stream_tags);
10685       } else {
10686         switch (fourcc) {
10687           case FOURCC_H264:
10688           case FOURCC_avc1:
10689           case FOURCC_avc3:
10690           {
10691             gint len = QT_UINT32 (stsd_entry_data) - 0x56;
10692             const guint8 *avc_data = stsd_entry_data + 0x56;
10693
10694             /* find avcC */
10695             while (len >= 0x8) {
10696               gint size;
10697
10698               if (QT_UINT32 (avc_data) <= len)
10699                 size = QT_UINT32 (avc_data) - 0x8;
10700               else
10701                 size = len - 0x8;
10702
10703               if (size < 1)
10704                 /* No real data, so break out */
10705                 break;
10706
10707               switch (QT_FOURCC (avc_data + 0x4)) {
10708                 case FOURCC_avcC:
10709                 {
10710                   /* parse, if found */
10711                   GstBuffer *buf;
10712
10713                   GST_DEBUG_OBJECT (qtdemux, "found avcC codec_data in stsd");
10714
10715                   /* First 4 bytes are the length of the atom, the next 4 bytes
10716                    * are the fourcc, the next 1 byte is the version, and the
10717                    * subsequent bytes are profile_tier_level structure like data. */
10718                   gst_codec_utils_h264_caps_set_level_and_profile (entry->caps,
10719                       avc_data + 8 + 1, size - 1);
10720                   buf = gst_buffer_new_and_alloc (size);
10721                   gst_buffer_fill (buf, 0, avc_data + 0x8, size);
10722                   gst_caps_set_simple (entry->caps,
10723                       "codec_data", GST_TYPE_BUFFER, buf, NULL);
10724                   gst_buffer_unref (buf);
10725
10726                   break;
10727                 }
10728                 case FOURCC_strf:
10729                 {
10730                   GstBuffer *buf;
10731
10732                   GST_DEBUG_OBJECT (qtdemux, "found strf codec_data in stsd");
10733
10734                   /* First 4 bytes are the length of the atom, the next 4 bytes
10735                    * are the fourcc, next 40 bytes are BITMAPINFOHEADER,
10736                    * next 1 byte is the version, and the
10737                    * subsequent bytes are sequence parameter set like data. */
10738
10739                   size -= 40;   /* we'll be skipping BITMAPINFOHEADER */
10740                   if (size > 1) {
10741                     gst_codec_utils_h264_caps_set_level_and_profile
10742                         (entry->caps, avc_data + 8 + 40 + 1, size - 1);
10743
10744                     buf = gst_buffer_new_and_alloc (size);
10745                     gst_buffer_fill (buf, 0, avc_data + 8 + 40, size);
10746                     gst_caps_set_simple (entry->caps,
10747                         "codec_data", GST_TYPE_BUFFER, buf, NULL);
10748                     gst_buffer_unref (buf);
10749                   }
10750                   break;
10751                 }
10752                 case FOURCC_btrt:
10753                 {
10754                   guint avg_bitrate, max_bitrate;
10755
10756                   /* bufferSizeDB, maxBitrate and avgBitrate - 4 bytes each */
10757                   if (size < 12)
10758                     break;
10759
10760                   max_bitrate = QT_UINT32 (avc_data + 0xc);
10761                   avg_bitrate = QT_UINT32 (avc_data + 0x10);
10762
10763                   if (!max_bitrate && !avg_bitrate)
10764                     break;
10765
10766                   /* Some muxers seem to swap the average and maximum bitrates
10767                    * (I'm looking at you, YouTube), so we swap for sanity. */
10768                   if (max_bitrate > 0 && max_bitrate < avg_bitrate) {
10769                     guint temp = avg_bitrate;
10770
10771                     avg_bitrate = max_bitrate;
10772                     max_bitrate = temp;
10773                   }
10774
10775                   if (max_bitrate > 0 && max_bitrate < G_MAXUINT32) {
10776                     gst_tag_list_add (stream->stream_tags,
10777                         GST_TAG_MERGE_REPLACE, GST_TAG_MAXIMUM_BITRATE,
10778                         max_bitrate, NULL);
10779                   }
10780                   if (avg_bitrate > 0 && avg_bitrate < G_MAXUINT32) {
10781                     gst_tag_list_add (stream->stream_tags,
10782                         GST_TAG_MERGE_REPLACE, GST_TAG_BITRATE, avg_bitrate,
10783                         NULL);
10784                   }
10785
10786                   break;
10787                 }
10788
10789                 default:
10790                   break;
10791               }
10792
10793               len -= size + 8;
10794               avc_data += size + 8;
10795             }
10796
10797             break;
10798           }
10799           case FOURCC_H265:
10800           case FOURCC_hvc1:
10801           case FOURCC_hev1:
10802           {
10803             gint len = QT_UINT32 (stsd_entry_data) - 0x56;
10804             const guint8 *hevc_data = stsd_entry_data + 0x56;
10805
10806             /* find hevc */
10807             while (len >= 0x8) {
10808               gint size;
10809
10810               if (QT_UINT32 (hevc_data) <= len)
10811                 size = QT_UINT32 (hevc_data) - 0x8;
10812               else
10813                 size = len - 0x8;
10814
10815               if (size < 1)
10816                 /* No real data, so break out */
10817                 break;
10818
10819               switch (QT_FOURCC (hevc_data + 0x4)) {
10820                 case FOURCC_hvcC:
10821                 {
10822                   /* parse, if found */
10823                   GstBuffer *buf;
10824
10825                   GST_DEBUG_OBJECT (qtdemux, "found hvcC codec_data in stsd");
10826
10827                   /* First 4 bytes are the length of the atom, the next 4 bytes
10828                    * are the fourcc, the next 1 byte is the version, and the
10829                    * subsequent bytes are sequence parameter set like data. */
10830                   gst_codec_utils_h265_caps_set_level_tier_and_profile
10831                       (entry->caps, hevc_data + 8 + 1, size - 1);
10832
10833                   buf = gst_buffer_new_and_alloc (size);
10834                   gst_buffer_fill (buf, 0, hevc_data + 0x8, size);
10835                   gst_caps_set_simple (entry->caps,
10836                       "codec_data", GST_TYPE_BUFFER, buf, NULL);
10837                   gst_buffer_unref (buf);
10838                   break;
10839                 }
10840                 default:
10841                   break;
10842               }
10843               len -= size + 8;
10844               hevc_data += size + 8;
10845             }
10846             break;
10847           }
10848           case FOURCC_mp4v:
10849           case FOURCC_MP4V:
10850           case FOURCC_fmp4:
10851           case FOURCC_FMP4:
10852           case FOURCC_xvid:
10853           case FOURCC_XVID:
10854           {
10855             GNode *glbl;
10856
10857             GST_DEBUG_OBJECT (qtdemux, "found %" GST_FOURCC_FORMAT,
10858                 GST_FOURCC_ARGS (fourcc));
10859
10860             /* codec data might be in glbl extension atom */
10861             glbl = mp4v ?
10862                 qtdemux_tree_get_child_by_type (mp4v, FOURCC_glbl) : NULL;
10863             if (glbl) {
10864               guint8 *data;
10865               GstBuffer *buf;
10866               gint len;
10867
10868               GST_DEBUG_OBJECT (qtdemux, "found glbl data in stsd");
10869               data = glbl->data;
10870               len = QT_UINT32 (data);
10871               if (len > 0x8) {
10872                 len -= 0x8;
10873                 buf = gst_buffer_new_and_alloc (len);
10874                 gst_buffer_fill (buf, 0, data + 8, len);
10875                 gst_caps_set_simple (entry->caps,
10876                     "codec_data", GST_TYPE_BUFFER, buf, NULL);
10877                 gst_buffer_unref (buf);
10878               }
10879             }
10880             break;
10881           }
10882           case FOURCC_mjp2:
10883           {
10884             /* see annex I of the jpeg2000 spec */
10885             GNode *jp2h, *ihdr, *colr, *mjp2, *field, *prefix, *cmap, *cdef;
10886             const guint8 *data;
10887             const gchar *colorspace = NULL;
10888             gint ncomp = 0;
10889             guint32 ncomp_map = 0;
10890             gint32 *comp_map = NULL;
10891             guint32 nchan_def = 0;
10892             gint32 *chan_def = NULL;
10893
10894             GST_DEBUG_OBJECT (qtdemux, "found mjp2");
10895             /* some required atoms */
10896             mjp2 = qtdemux_tree_get_child_by_index (stsd, stsd_index);
10897             if (!mjp2)
10898               break;
10899             jp2h = qtdemux_tree_get_child_by_type (mjp2, FOURCC_jp2h);
10900             if (!jp2h)
10901               break;
10902
10903             /* number of components; redundant with info in codestream, but useful
10904                to a muxer */
10905             ihdr = qtdemux_tree_get_child_by_type (jp2h, FOURCC_ihdr);
10906             if (!ihdr || QT_UINT32 (ihdr->data) != 22)
10907               break;
10908             ncomp = QT_UINT16 (((guint8 *) ihdr->data) + 16);
10909
10910             colr = qtdemux_tree_get_child_by_type (jp2h, FOURCC_colr);
10911             if (!colr)
10912               break;
10913             GST_DEBUG_OBJECT (qtdemux, "found colr");
10914             /* extract colour space info */
10915             if (QT_UINT8 ((guint8 *) colr->data + 8) == 1) {
10916               switch (QT_UINT32 ((guint8 *) colr->data + 11)) {
10917                 case 16:
10918                   colorspace = "sRGB";
10919                   break;
10920                 case 17:
10921                   colorspace = "GRAY";
10922                   break;
10923                 case 18:
10924                   colorspace = "sYUV";
10925                   break;
10926                 default:
10927                   colorspace = NULL;
10928                   break;
10929               }
10930             }
10931             if (!colorspace)
10932               /* colr is required, and only values 16, 17, and 18 are specified,
10933                  so error if we have no colorspace */
10934               break;
10935
10936             /* extract component mapping */
10937             cmap = qtdemux_tree_get_child_by_type (jp2h, FOURCC_cmap);
10938             if (cmap) {
10939               guint32 cmap_len = 0;
10940               int i;
10941               cmap_len = QT_UINT32 (cmap->data);
10942               if (cmap_len >= 8) {
10943                 /* normal box, subtract off header */
10944                 cmap_len -= 8;
10945                 /* cmap: { u16 cmp; u8 mtyp; u8 pcol; }* */
10946                 if (cmap_len % 4 == 0) {
10947                   ncomp_map = (cmap_len / 4);
10948                   comp_map = g_new0 (gint32, ncomp_map);
10949                   for (i = 0; i < ncomp_map; i++) {
10950                     guint16 cmp;
10951                     guint8 mtyp, pcol;
10952                     cmp = QT_UINT16 (((guint8 *) cmap->data) + 8 + i * 4);
10953                     mtyp = QT_UINT8 (((guint8 *) cmap->data) + 8 + i * 4 + 2);
10954                     pcol = QT_UINT8 (((guint8 *) cmap->data) + 8 + i * 4 + 3);
10955                     comp_map[i] = (mtyp << 24) | (pcol << 16) | cmp;
10956                   }
10957                 }
10958               }
10959             }
10960             /* extract channel definitions */
10961             cdef = qtdemux_tree_get_child_by_type (jp2h, FOURCC_cdef);
10962             if (cdef) {
10963               guint32 cdef_len = 0;
10964               int i;
10965               cdef_len = QT_UINT32 (cdef->data);
10966               if (cdef_len >= 10) {
10967                 /* normal box, subtract off header and len */
10968                 cdef_len -= 10;
10969                 /* cdef: u16 n; { u16 cn; u16 typ; u16 asoc; }* */
10970                 if (cdef_len % 6 == 0) {
10971                   nchan_def = (cdef_len / 6);
10972                   chan_def = g_new0 (gint32, nchan_def);
10973                   for (i = 0; i < nchan_def; i++)
10974                     chan_def[i] = -1;
10975                   for (i = 0; i < nchan_def; i++) {
10976                     guint16 cn, typ, asoc;
10977                     cn = QT_UINT16 (((guint8 *) cdef->data) + 10 + i * 6);
10978                     typ = QT_UINT16 (((guint8 *) cdef->data) + 10 + i * 6 + 2);
10979                     asoc = QT_UINT16 (((guint8 *) cdef->data) + 10 + i * 6 + 4);
10980                     if (cn < nchan_def) {
10981                       switch (typ) {
10982                         case 0:
10983                           chan_def[cn] = asoc;
10984                           break;
10985                         case 1:
10986                           chan_def[cn] = 0;     /* alpha */
10987                           break;
10988                         default:
10989                           chan_def[cn] = -typ;
10990                       }
10991                     }
10992                   }
10993                 }
10994               }
10995             }
10996
10997             gst_caps_set_simple (entry->caps,
10998                 "num-components", G_TYPE_INT, ncomp, NULL);
10999             gst_caps_set_simple (entry->caps,
11000                 "colorspace", G_TYPE_STRING, colorspace, NULL);
11001
11002             if (comp_map) {
11003               GValue arr = { 0, };
11004               GValue elt = { 0, };
11005               int i;
11006               g_value_init (&arr, GST_TYPE_ARRAY);
11007               g_value_init (&elt, G_TYPE_INT);
11008               for (i = 0; i < ncomp_map; i++) {
11009                 g_value_set_int (&elt, comp_map[i]);
11010                 gst_value_array_append_value (&arr, &elt);
11011               }
11012               gst_structure_set_value (gst_caps_get_structure (entry->caps, 0),
11013                   "component-map", &arr);
11014               g_value_unset (&elt);
11015               g_value_unset (&arr);
11016               g_free (comp_map);
11017             }
11018
11019             if (chan_def) {
11020               GValue arr = { 0, };
11021               GValue elt = { 0, };
11022               int i;
11023               g_value_init (&arr, GST_TYPE_ARRAY);
11024               g_value_init (&elt, G_TYPE_INT);
11025               for (i = 0; i < nchan_def; i++) {
11026                 g_value_set_int (&elt, chan_def[i]);
11027                 gst_value_array_append_value (&arr, &elt);
11028               }
11029               gst_structure_set_value (gst_caps_get_structure (entry->caps, 0),
11030                   "channel-definitions", &arr);
11031               g_value_unset (&elt);
11032               g_value_unset (&arr);
11033               g_free (chan_def);
11034             }
11035
11036             /* some optional atoms */
11037             field = qtdemux_tree_get_child_by_type (mjp2, FOURCC_fiel);
11038             prefix = qtdemux_tree_get_child_by_type (mjp2, FOURCC_jp2x);
11039
11040             /* indicate possible fields in caps */
11041             if (field) {
11042               data = (guint8 *) field->data + 8;
11043               if (*data != 1)
11044                 gst_caps_set_simple (entry->caps, "fields", G_TYPE_INT,
11045                     (gint) * data, NULL);
11046             }
11047             /* add codec_data if provided */
11048             if (prefix) {
11049               GstBuffer *buf;
11050               gint len;
11051
11052               GST_DEBUG_OBJECT (qtdemux, "found prefix data in stsd");
11053               data = prefix->data;
11054               len = QT_UINT32 (data);
11055               if (len > 0x8) {
11056                 len -= 0x8;
11057                 buf = gst_buffer_new_and_alloc (len);
11058                 gst_buffer_fill (buf, 0, data + 8, len);
11059                 gst_caps_set_simple (entry->caps,
11060                     "codec_data", GST_TYPE_BUFFER, buf, NULL);
11061                 gst_buffer_unref (buf);
11062               }
11063             }
11064             break;
11065           }
11066           case FOURCC_SVQ3:
11067           case FOURCC_VP31:
11068           {
11069             GstBuffer *buf;
11070             GstBuffer *seqh = NULL;
11071             const guint8 *gamma_data = NULL;
11072             gint len = QT_UINT32 (stsd_data);   /* FIXME review - why put the whole stsd in codec data? */
11073
11074             qtdemux_parse_svq3_stsd_data (qtdemux, stsd_entry_data, &gamma_data,
11075                 &seqh);
11076             if (gamma_data) {
11077               gst_caps_set_simple (entry->caps, "applied-gamma", G_TYPE_DOUBLE,
11078                   QT_FP32 (gamma_data), NULL);
11079             }
11080             if (seqh) {
11081               /* sorry for the bad name, but we don't know what this is, other
11082                * than its own fourcc */
11083               gst_caps_set_simple (entry->caps, "seqh", GST_TYPE_BUFFER, seqh,
11084                   NULL);
11085               gst_buffer_unref (seqh);
11086             }
11087
11088             GST_DEBUG_OBJECT (qtdemux, "found codec_data in stsd");
11089             buf = gst_buffer_new_and_alloc (len);
11090             gst_buffer_fill (buf, 0, stsd_data, len);
11091             gst_caps_set_simple (entry->caps,
11092                 "codec_data", GST_TYPE_BUFFER, buf, NULL);
11093             gst_buffer_unref (buf);
11094             break;
11095           }
11096           case FOURCC_jpeg:
11097           {
11098             /* https://developer.apple.com/standards/qtff-2001.pdf,
11099              * page 92, "Video Sample Description", under table 3.1 */
11100             GstByteReader br;
11101
11102             const gint compressor_offset =
11103                 16 + 4 + 4 * 3 + 2 * 2 + 2 * 4 + 4 + 2;
11104             const gint min_size = compressor_offset + 32 + 2 + 2;
11105             GNode *jpeg;
11106             guint32 len;
11107             guint16 color_table_id = 0;
11108             gboolean ok;
11109
11110             GST_DEBUG_OBJECT (qtdemux, "found jpeg");
11111
11112             /* recover information on interlaced/progressive */
11113             jpeg = qtdemux_tree_get_child_by_type (stsd, FOURCC_jpeg);
11114             if (!jpeg)
11115               break;
11116
11117             len = QT_UINT32 (jpeg->data);
11118             GST_DEBUG_OBJECT (qtdemux, "Found jpeg: len %u, need %d", len,
11119                 min_size);
11120             if (len >= min_size) {
11121               gst_byte_reader_init (&br, jpeg->data, len);
11122
11123               gst_byte_reader_skip (&br, compressor_offset + 32 + 2);
11124               gst_byte_reader_get_uint16_le (&br, &color_table_id);
11125               if (color_table_id != 0) {
11126                 /* the spec says there can be concatenated chunks in the data, and we want
11127                  * to find one called field. Walk through them. */
11128                 gint offset = min_size;
11129                 while (offset + 8 < len) {
11130                   guint32 size = 0, tag;
11131                   ok = gst_byte_reader_get_uint32_le (&br, &size);
11132                   ok &= gst_byte_reader_get_uint32_le (&br, &tag);
11133                   if (!ok || size < 8) {
11134                     GST_WARNING_OBJECT (qtdemux,
11135                         "Failed to walk optional chunk list");
11136                     break;
11137                   }
11138                   GST_DEBUG_OBJECT (qtdemux,
11139                       "Found optional %4.4s chunk, size %u",
11140                       (const char *) &tag, size);
11141                   if (tag == FOURCC_fiel) {
11142                     guint8 n_fields = 0, ordering = 0;
11143                     gst_byte_reader_get_uint8 (&br, &n_fields);
11144                     gst_byte_reader_get_uint8 (&br, &ordering);
11145                     if (n_fields == 1 || n_fields == 2) {
11146                       GST_DEBUG_OBJECT (qtdemux,
11147                           "Found fiel tag with %u fields, ordering %u",
11148                           n_fields, ordering);
11149                       if (n_fields == 2)
11150                         gst_caps_set_simple (CUR_STREAM (stream)->caps,
11151                             "interlace-mode", G_TYPE_STRING, "interleaved",
11152                             NULL);
11153                     } else {
11154                       GST_WARNING_OBJECT (qtdemux,
11155                           "Found fiel tag with invalid fields (%u)", n_fields);
11156                     }
11157                   }
11158                   offset += size;
11159                 }
11160               } else {
11161                 GST_DEBUG_OBJECT (qtdemux,
11162                     "Color table ID is 0, not trying to get interlacedness");
11163               }
11164             } else {
11165               GST_WARNING_OBJECT (qtdemux,
11166                   "Length of jpeg chunk is too small, not trying to get interlacedness");
11167             }
11168
11169             break;
11170           }
11171           case FOURCC_rle_:
11172           case FOURCC_WRLE:
11173           {
11174             gst_caps_set_simple (entry->caps,
11175                 "depth", G_TYPE_INT, QT_UINT16 (stsd_entry_data + offset + 66),
11176                 NULL);
11177             break;
11178           }
11179           case FOURCC_XiTh:
11180           {
11181             GNode *xith, *xdxt;
11182
11183             GST_DEBUG_OBJECT (qtdemux, "found XiTh");
11184             xith = qtdemux_tree_get_child_by_index (stsd, stsd_index);
11185             if (!xith)
11186               break;
11187
11188             xdxt = qtdemux_tree_get_child_by_type (xith, FOURCC_XdxT);
11189             if (!xdxt)
11190               break;
11191
11192             GST_DEBUG_OBJECT (qtdemux, "found XdxT node");
11193             /* collect the headers and store them in a stream list so that we can
11194              * send them out first */
11195             qtdemux_parse_theora_extension (qtdemux, stream, xdxt);
11196             break;
11197           }
11198           case FOURCC_ovc1:
11199           {
11200             GNode *ovc1;
11201             guint8 *ovc1_data;
11202             guint ovc1_len;
11203             GstBuffer *buf;
11204
11205             GST_DEBUG_OBJECT (qtdemux, "parse ovc1 header");
11206             ovc1 = qtdemux_tree_get_child_by_index (stsd, stsd_index);
11207             if (!ovc1)
11208               break;
11209             ovc1_data = ovc1->data;
11210             ovc1_len = QT_UINT32 (ovc1_data);
11211             if (ovc1_len <= 198) {
11212               GST_WARNING_OBJECT (qtdemux, "Too small ovc1 header, skipping");
11213               break;
11214             }
11215             buf = gst_buffer_new_and_alloc (ovc1_len - 198);
11216             gst_buffer_fill (buf, 0, ovc1_data + 198, ovc1_len - 198);
11217             gst_caps_set_simple (entry->caps,
11218                 "codec_data", GST_TYPE_BUFFER, buf, NULL);
11219             gst_buffer_unref (buf);
11220             break;
11221           }
11222           case FOURCC_vc_1:
11223           {
11224             gint len = QT_UINT32 (stsd_entry_data) - 0x56;
11225             const guint8 *vc1_data = stsd_entry_data + 0x56;
11226
11227             /* find dvc1 */
11228             while (len >= 8) {
11229               gint size;
11230
11231               if (QT_UINT32 (vc1_data) <= len)
11232                 size = QT_UINT32 (vc1_data) - 8;
11233               else
11234                 size = len - 8;
11235
11236               if (size < 1)
11237                 /* No real data, so break out */
11238                 break;
11239
11240               switch (QT_FOURCC (vc1_data + 0x4)) {
11241                 case GST_MAKE_FOURCC ('d', 'v', 'c', '1'):
11242                 {
11243                   GstBuffer *buf;
11244
11245                   GST_DEBUG_OBJECT (qtdemux, "found dvc1 codec_data in stsd");
11246                   buf = gst_buffer_new_and_alloc (size);
11247                   gst_buffer_fill (buf, 0, vc1_data + 8, size);
11248                   gst_caps_set_simple (entry->caps,
11249                       "codec_data", GST_TYPE_BUFFER, buf, NULL);
11250                   gst_buffer_unref (buf);
11251                   break;
11252                 }
11253                 default:
11254                   break;
11255               }
11256               len -= size + 8;
11257               vc1_data += size + 8;
11258             }
11259             break;
11260           }
11261           case FOURCC_av01:
11262           {
11263             gint len = QT_UINT32 (stsd_entry_data) - 0x56;
11264             const guint8 *av1_data = stsd_entry_data + 0x56;
11265
11266             /* find av1C */
11267             while (len >= 0x8) {
11268               gint size;
11269
11270               if (QT_UINT32 (av1_data) <= len)
11271                 size = QT_UINT32 (av1_data) - 0x8;
11272               else
11273                 size = len - 0x8;
11274
11275               if (size < 1)
11276                 /* No real data, so break out */
11277                 break;
11278
11279               switch (QT_FOURCC (av1_data + 0x4)) {
11280                 case FOURCC_av1C:
11281                 {
11282                   /* parse, if found */
11283                   GstBuffer *buf;
11284                   guint8 pres_delay_field;
11285
11286                   GST_DEBUG_OBJECT (qtdemux,
11287                       "found av1C codec_data in stsd of size %d", size);
11288
11289                   /* not enough data, just ignore and hope for the best */
11290                   if (size < 5)
11291                     break;
11292
11293                   /* Content is:
11294                    * 4 bytes: atom length
11295                    * 4 bytes: fourcc
11296                    * 1 byte: version
11297                    * 3 bytes: flags
11298                    * 3 bits: reserved
11299                    * 1 bits:  initial_presentation_delay_present
11300                    * 4 bits: initial_presentation_delay (if present else reserved
11301                    * rest: OBUs.
11302                    */
11303
11304                   if (av1_data[9] != 0) {
11305                     GST_WARNING ("Unknown version %d of av1C box", av1_data[9]);
11306                     break;
11307                   }
11308
11309                   /* We skip initial_presentation_delay* for now */
11310                   pres_delay_field = *(av1_data + 12);
11311                   if (pres_delay_field & (1 << 5)) {
11312                     gst_caps_set_simple (entry->caps,
11313                         "presentation-delay", G_TYPE_INT,
11314                         (gint) (pres_delay_field & 0x0F) + 1, NULL);
11315                   }
11316                   if (size > 5) {
11317                     buf = gst_buffer_new_and_alloc (size - 5);
11318                     GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_HEADER);
11319                     gst_buffer_fill (buf, 0, av1_data + 13, size - 5);
11320                     gst_caps_set_simple (entry->caps,
11321                         "codec_data", GST_TYPE_BUFFER, buf, NULL);
11322                     gst_buffer_unref (buf);
11323                   }
11324                   break;
11325                 }
11326                 default:
11327                   break;
11328               }
11329
11330               len -= size + 8;
11331               av1_data += size + 8;
11332             }
11333
11334             break;
11335           }
11336           default:
11337             break;
11338         }
11339       }
11340
11341       GST_INFO_OBJECT (qtdemux,
11342           "type %" GST_FOURCC_FORMAT " caps %" GST_PTR_FORMAT,
11343           GST_FOURCC_ARGS (fourcc), entry->caps);
11344
11345     } else if (stream->subtype == FOURCC_soun) {
11346       GNode *wave;
11347       int version, samplesize;
11348       guint16 compression_id;
11349       gboolean amrwb = FALSE;
11350
11351       offset = 16;
11352       /* sample description entry (16) + sound sample description v0 (20) */
11353       if (len < 36)
11354         goto corrupt_file;
11355
11356       version = QT_UINT32 (stsd_entry_data + offset);
11357       entry->n_channels = QT_UINT16 (stsd_entry_data + offset + 8);
11358       samplesize = QT_UINT16 (stsd_entry_data + offset + 10);
11359       compression_id = QT_UINT16 (stsd_entry_data + offset + 12);
11360       entry->rate = QT_FP32 (stsd_entry_data + offset + 16);
11361
11362       GST_LOG_OBJECT (qtdemux, "version/rev:      %08x", version);
11363       GST_LOG_OBJECT (qtdemux, "vendor:           %08x",
11364           QT_UINT32 (stsd_entry_data + offset + 4));
11365       GST_LOG_OBJECT (qtdemux, "n_channels:       %d", entry->n_channels);
11366       GST_LOG_OBJECT (qtdemux, "sample_size:      %d", samplesize);
11367       GST_LOG_OBJECT (qtdemux, "compression_id:   %d", compression_id);
11368       GST_LOG_OBJECT (qtdemux, "packet size:      %d",
11369           QT_UINT16 (stsd_entry_data + offset + 14));
11370       GST_LOG_OBJECT (qtdemux, "sample rate:      %g", entry->rate);
11371
11372       if (compression_id == 0xfffe)
11373         entry->sampled = TRUE;
11374
11375       /* first assume uncompressed audio */
11376       entry->bytes_per_sample = samplesize / 8;
11377       entry->samples_per_frame = entry->n_channels;
11378       entry->bytes_per_frame = entry->n_channels * entry->bytes_per_sample;
11379       entry->samples_per_packet = entry->samples_per_frame;
11380       entry->bytes_per_packet = entry->bytes_per_sample;
11381
11382       offset = 36;
11383       switch (fourcc) {
11384           /* Yes, these have to be hard-coded */
11385         case FOURCC_MAC6:
11386         {
11387           entry->samples_per_packet = 6;
11388           entry->bytes_per_packet = 1;
11389           entry->bytes_per_frame = 1 * entry->n_channels;
11390           entry->bytes_per_sample = 1;
11391           entry->samples_per_frame = 6 * entry->n_channels;
11392           break;
11393         }
11394         case FOURCC_MAC3:
11395         {
11396           entry->samples_per_packet = 3;
11397           entry->bytes_per_packet = 1;
11398           entry->bytes_per_frame = 1 * entry->n_channels;
11399           entry->bytes_per_sample = 1;
11400           entry->samples_per_frame = 3 * entry->n_channels;
11401           break;
11402         }
11403         case FOURCC_ima4:
11404         {
11405           entry->samples_per_packet = 64;
11406           entry->bytes_per_packet = 34;
11407           entry->bytes_per_frame = 34 * entry->n_channels;
11408           entry->bytes_per_sample = 2;
11409           entry->samples_per_frame = 64 * entry->n_channels;
11410           break;
11411         }
11412         case FOURCC_ulaw:
11413         case FOURCC_alaw:
11414         {
11415           entry->samples_per_packet = 1;
11416           entry->bytes_per_packet = 1;
11417           entry->bytes_per_frame = 1 * entry->n_channels;
11418           entry->bytes_per_sample = 1;
11419           entry->samples_per_frame = 1 * entry->n_channels;
11420           break;
11421         }
11422         case FOURCC_agsm:
11423         {
11424           entry->samples_per_packet = 160;
11425           entry->bytes_per_packet = 33;
11426           entry->bytes_per_frame = 33 * entry->n_channels;
11427           entry->bytes_per_sample = 2;
11428           entry->samples_per_frame = 160 * entry->n_channels;
11429           break;
11430         }
11431         default:
11432           break;
11433       }
11434
11435       if (version == 0x00010000) {
11436         /* sample description entry (16) + sound sample description v1 (20+16) */
11437         if (len < 52)
11438           goto corrupt_file;
11439
11440         switch (fourcc) {
11441           case FOURCC_twos:
11442           case FOURCC_sowt:
11443           case FOURCC_raw_:
11444           case FOURCC_lpcm:
11445             break;
11446           default:
11447           {
11448             /* only parse extra decoding config for non-pcm audio */
11449             entry->samples_per_packet = QT_UINT32 (stsd_entry_data + offset);
11450             entry->bytes_per_packet = QT_UINT32 (stsd_entry_data + offset + 4);
11451             entry->bytes_per_frame = QT_UINT32 (stsd_entry_data + offset + 8);
11452             entry->bytes_per_sample = QT_UINT32 (stsd_entry_data + offset + 12);
11453
11454             GST_LOG_OBJECT (qtdemux, "samples/packet:   %d",
11455                 entry->samples_per_packet);
11456             GST_LOG_OBJECT (qtdemux, "bytes/packet:     %d",
11457                 entry->bytes_per_packet);
11458             GST_LOG_OBJECT (qtdemux, "bytes/frame:      %d",
11459                 entry->bytes_per_frame);
11460             GST_LOG_OBJECT (qtdemux, "bytes/sample:     %d",
11461                 entry->bytes_per_sample);
11462
11463             if (!entry->sampled && entry->bytes_per_packet) {
11464               entry->samples_per_frame = (entry->bytes_per_frame /
11465                   entry->bytes_per_packet) * entry->samples_per_packet;
11466               GST_LOG_OBJECT (qtdemux, "samples/frame:    %d",
11467                   entry->samples_per_frame);
11468             }
11469             break;
11470           }
11471         }
11472       } else if (version == 0x00020000) {
11473         union
11474         {
11475           gdouble fp;
11476           guint64 val;
11477         } qtfp;
11478
11479         /* sample description entry (16) + sound sample description v2 (56) */
11480         if (len < 72)
11481           goto corrupt_file;
11482
11483         qtfp.val = QT_UINT64 (stsd_entry_data + offset + 4);
11484         entry->rate = qtfp.fp;
11485         entry->n_channels = QT_UINT32 (stsd_entry_data + offset + 12);
11486
11487         GST_LOG_OBJECT (qtdemux, "Sound sample description Version 2");
11488         GST_LOG_OBJECT (qtdemux, "sample rate:        %g", entry->rate);
11489         GST_LOG_OBJECT (qtdemux, "n_channels:         %d", entry->n_channels);
11490         GST_LOG_OBJECT (qtdemux, "bits/channel:       %d",
11491             QT_UINT32 (stsd_entry_data + offset + 20));
11492         GST_LOG_OBJECT (qtdemux, "format flags:       %X",
11493             QT_UINT32 (stsd_entry_data + offset + 24));
11494         GST_LOG_OBJECT (qtdemux, "bytes/packet:       %d",
11495             QT_UINT32 (stsd_entry_data + offset + 28));
11496         GST_LOG_OBJECT (qtdemux, "LPCM frames/packet: %d",
11497             QT_UINT32 (stsd_entry_data + offset + 32));
11498       } else if (version != 0x00000) {
11499         GST_WARNING_OBJECT (qtdemux, "unknown audio STSD version %08x",
11500             version);
11501       }
11502
11503       if (entry->caps)
11504         gst_caps_unref (entry->caps);
11505
11506       entry->caps = qtdemux_audio_caps (qtdemux, stream, entry, fourcc,
11507           stsd_entry_data + 32, len - 16, &codec);
11508
11509       switch (fourcc) {
11510         case FOURCC_in24:
11511         {
11512           GNode *enda;
11513           GNode *in24;
11514
11515           in24 = qtdemux_tree_get_child_by_type (stsd, FOURCC_in24);
11516
11517           enda = qtdemux_tree_get_child_by_type (in24, FOURCC_enda);
11518           if (!enda) {
11519             wave = qtdemux_tree_get_child_by_type (in24, FOURCC_wave);
11520             if (wave)
11521               enda = qtdemux_tree_get_child_by_type (wave, FOURCC_enda);
11522           }
11523           if (enda) {
11524             int enda_value = QT_UINT16 ((guint8 *) enda->data + 8);
11525             gst_caps_set_simple (entry->caps,
11526                 "format", G_TYPE_STRING, (enda_value) ? "S24LE" : "S24BE",
11527                 NULL);
11528           }
11529           break;
11530         }
11531         case FOURCC_owma:
11532         {
11533           const guint8 *owma_data;
11534           const gchar *codec_name = NULL;
11535           guint owma_len;
11536           GstBuffer *buf;
11537           gint version = 1;
11538           /* from http://msdn.microsoft.com/en-us/library/dd757720(VS.85).aspx */
11539           /* FIXME this should also be gst_riff_strf_auds,
11540            * but the latter one is actually missing bits-per-sample :( */
11541           typedef struct
11542           {
11543             gint16 wFormatTag;
11544             gint16 nChannels;
11545             gint32 nSamplesPerSec;
11546             gint32 nAvgBytesPerSec;
11547             gint16 nBlockAlign;
11548             gint16 wBitsPerSample;
11549             gint16 cbSize;
11550           } WAVEFORMATEX;
11551           WAVEFORMATEX *wfex;
11552
11553           GST_DEBUG_OBJECT (qtdemux, "parse owma");
11554           owma_data = stsd_entry_data;
11555           owma_len = QT_UINT32 (owma_data);
11556           if (owma_len <= 54) {
11557             GST_WARNING_OBJECT (qtdemux, "Too small owma header, skipping");
11558             break;
11559           }
11560           wfex = (WAVEFORMATEX *) (owma_data + 36);
11561           buf = gst_buffer_new_and_alloc (owma_len - 54);
11562           gst_buffer_fill (buf, 0, owma_data + 54, owma_len - 54);
11563           if (wfex->wFormatTag == 0x0161) {
11564             codec_name = "Windows Media Audio";
11565             version = 2;
11566           } else if (wfex->wFormatTag == 0x0162) {
11567             codec_name = "Windows Media Audio 9 Pro";
11568             version = 3;
11569           } else if (wfex->wFormatTag == 0x0163) {
11570             codec_name = "Windows Media Audio 9 Lossless";
11571             /* is that correct? gstffmpegcodecmap.c is missing it, but
11572              * fluendo codec seems to support it */
11573             version = 4;
11574           }
11575
11576           gst_caps_set_simple (entry->caps,
11577               "codec_data", GST_TYPE_BUFFER, buf,
11578               "wmaversion", G_TYPE_INT, version,
11579               "block_align", G_TYPE_INT,
11580               GST_READ_UINT16_LE (&wfex->nBlockAlign), "bitrate", G_TYPE_INT,
11581               GST_READ_UINT32_LE (&wfex->nAvgBytesPerSec), "width", G_TYPE_INT,
11582               GST_READ_UINT16_LE (&wfex->wBitsPerSample), "depth", G_TYPE_INT,
11583               GST_READ_UINT16_LE (&wfex->wBitsPerSample), NULL);
11584           gst_buffer_unref (buf);
11585
11586           if (codec_name) {
11587             g_free (codec);
11588             codec = g_strdup (codec_name);
11589           }
11590           break;
11591         }
11592         case FOURCC_wma_:
11593         {
11594           gint len = QT_UINT32 (stsd_entry_data) - offset;
11595           const guint8 *wfex_data = stsd_entry_data + offset;
11596           const gchar *codec_name = NULL;
11597           gint version = 1;
11598           /* from http://msdn.microsoft.com/en-us/library/dd757720(VS.85).aspx */
11599           /* FIXME this should also be gst_riff_strf_auds,
11600            * but the latter one is actually missing bits-per-sample :( */
11601           typedef struct
11602           {
11603             gint16 wFormatTag;
11604             gint16 nChannels;
11605             gint32 nSamplesPerSec;
11606             gint32 nAvgBytesPerSec;
11607             gint16 nBlockAlign;
11608             gint16 wBitsPerSample;
11609             gint16 cbSize;
11610           } WAVEFORMATEX;
11611           WAVEFORMATEX wfex;
11612
11613           /* FIXME: unify with similar wavformatex parsing code above */
11614           GST_DEBUG_OBJECT (qtdemux, "parse wma, looking for wfex");
11615
11616           /* find wfex */
11617           while (len >= 8) {
11618             gint size;
11619
11620             if (QT_UINT32 (wfex_data) <= len)
11621               size = QT_UINT32 (wfex_data) - 8;
11622             else
11623               size = len - 8;
11624
11625             if (size < 1)
11626               /* No real data, so break out */
11627               break;
11628
11629             switch (QT_FOURCC (wfex_data + 4)) {
11630               case GST_MAKE_FOURCC ('w', 'f', 'e', 'x'):
11631               {
11632                 GST_DEBUG_OBJECT (qtdemux, "found wfex in stsd");
11633
11634                 if (size < 8 + 18)
11635                   break;
11636
11637                 wfex.wFormatTag = GST_READ_UINT16_LE (wfex_data + 8 + 0);
11638                 wfex.nChannels = GST_READ_UINT16_LE (wfex_data + 8 + 2);
11639                 wfex.nSamplesPerSec = GST_READ_UINT32_LE (wfex_data + 8 + 4);
11640                 wfex.nAvgBytesPerSec = GST_READ_UINT32_LE (wfex_data + 8 + 8);
11641                 wfex.nBlockAlign = GST_READ_UINT16_LE (wfex_data + 8 + 12);
11642                 wfex.wBitsPerSample = GST_READ_UINT16_LE (wfex_data + 8 + 14);
11643                 wfex.cbSize = GST_READ_UINT16_LE (wfex_data + 8 + 16);
11644
11645                 GST_LOG_OBJECT (qtdemux, "Found wfex box in stsd:");
11646                 GST_LOG_OBJECT (qtdemux, "FormatTag = 0x%04x, Channels = %u, "
11647                     "SamplesPerSec = %u, AvgBytesPerSec = %u, BlockAlign = %u, "
11648                     "BitsPerSample = %u, Size = %u", wfex.wFormatTag,
11649                     wfex.nChannels, wfex.nSamplesPerSec, wfex.nAvgBytesPerSec,
11650                     wfex.nBlockAlign, wfex.wBitsPerSample, wfex.cbSize);
11651
11652                 if (wfex.wFormatTag == 0x0161) {
11653                   codec_name = "Windows Media Audio";
11654                   version = 2;
11655                 } else if (wfex.wFormatTag == 0x0162) {
11656                   codec_name = "Windows Media Audio 9 Pro";
11657                   version = 3;
11658                 } else if (wfex.wFormatTag == 0x0163) {
11659                   codec_name = "Windows Media Audio 9 Lossless";
11660                   /* is that correct? gstffmpegcodecmap.c is missing it, but
11661                    * fluendo codec seems to support it */
11662                   version = 4;
11663                 }
11664
11665                 gst_caps_set_simple (entry->caps,
11666                     "wmaversion", G_TYPE_INT, version,
11667                     "block_align", G_TYPE_INT, wfex.nBlockAlign,
11668                     "bitrate", G_TYPE_INT, wfex.nAvgBytesPerSec,
11669                     "width", G_TYPE_INT, wfex.wBitsPerSample,
11670                     "depth", G_TYPE_INT, wfex.wBitsPerSample, NULL);
11671
11672                 if (size > wfex.cbSize) {
11673                   GstBuffer *buf;
11674
11675                   buf = gst_buffer_new_and_alloc (size - wfex.cbSize);
11676                   gst_buffer_fill (buf, 0, wfex_data + 8 + wfex.cbSize,
11677                       size - wfex.cbSize);
11678                   gst_caps_set_simple (entry->caps,
11679                       "codec_data", GST_TYPE_BUFFER, buf, NULL);
11680                   gst_buffer_unref (buf);
11681                 } else {
11682                   GST_WARNING_OBJECT (qtdemux, "no codec data");
11683                 }
11684
11685                 if (codec_name) {
11686                   g_free (codec);
11687                   codec = g_strdup (codec_name);
11688                 }
11689                 break;
11690               }
11691               default:
11692                 break;
11693             }
11694             len -= size + 8;
11695             wfex_data += size + 8;
11696           }
11697           break;
11698         }
11699         case FOURCC_opus:
11700         {
11701           const guint8 *opus_data;
11702           guint8 *channel_mapping = NULL;
11703           guint32 rate;
11704           guint8 channels;
11705           guint8 channel_mapping_family;
11706           guint8 stream_count;
11707           guint8 coupled_count;
11708           guint8 i;
11709
11710           opus_data = stsd_entry_data;
11711
11712           channels = GST_READ_UINT8 (opus_data + 45);
11713           rate = GST_READ_UINT32_LE (opus_data + 48);
11714           channel_mapping_family = GST_READ_UINT8 (opus_data + 54);
11715           stream_count = GST_READ_UINT8 (opus_data + 55);
11716           coupled_count = GST_READ_UINT8 (opus_data + 56);
11717
11718           if (channels > 0) {
11719             channel_mapping = g_malloc (channels * sizeof (guint8));
11720             for (i = 0; i < channels; i++)
11721               channel_mapping[i] = GST_READ_UINT8 (opus_data + i + 57);
11722           }
11723
11724           entry->caps = gst_codec_utils_opus_create_caps (rate, channels,
11725               channel_mapping_family, stream_count, coupled_count,
11726               channel_mapping);
11727           break;
11728         }
11729         default:
11730           break;
11731       }
11732
11733       if (codec) {
11734         GstStructure *s;
11735         gint bitrate = 0;
11736
11737         gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
11738             GST_TAG_AUDIO_CODEC, codec, NULL);
11739         g_free (codec);
11740         codec = NULL;
11741
11742         /* some bitrate info may have ended up in caps */
11743         s = gst_caps_get_structure (entry->caps, 0);
11744         gst_structure_get_int (s, "bitrate", &bitrate);
11745         if (bitrate > 0)
11746           gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
11747               GST_TAG_BITRATE, bitrate, NULL);
11748       }
11749
11750       mp4a = qtdemux_tree_get_child_by_index (stsd, stsd_index);
11751       if (!stream->protected) {
11752       } else {
11753         if (QTDEMUX_TREE_NODE_FOURCC (mp4v) != FOURCC_encv) {
11754           mp4v = NULL;
11755         }
11756       }
11757       if (stream->protected && fourcc == FOURCC_mp4a) {
11758         if (QTDEMUX_TREE_NODE_FOURCC (mp4a) != FOURCC_enca) {
11759           mp4a = NULL;
11760         }
11761       } else {
11762         if (QTDEMUX_TREE_NODE_FOURCC (mp4a) != FOURCC_mp4a) {
11763           mp4a = NULL;
11764         }
11765       }
11766
11767       wave = NULL;
11768       esds = NULL;
11769       if (mp4a) {
11770         wave = qtdemux_tree_get_child_by_type (mp4a, FOURCC_wave);
11771         if (wave)
11772           esds = qtdemux_tree_get_child_by_type (wave, FOURCC_esds);
11773         if (!esds)
11774           esds = qtdemux_tree_get_child_by_type (mp4a, FOURCC_esds);
11775       }
11776
11777
11778       /* If the fourcc's bottom 16 bits gives 'sm', then the top
11779          16 bits is a byte-swapped wave-style codec identifier,
11780          and we can find a WAVE header internally to a 'wave' atom here.
11781          This can more clearly be thought of as 'ms' as the top 16 bits, and a
11782          codec id as the bottom 16 bits - but byte-swapped to store in QT (which
11783          is big-endian).
11784        */
11785       if ((fourcc & 0xffff) == (('s' << 8) | 'm')) {
11786         if (len < offset + 20) {
11787           GST_WARNING_OBJECT (qtdemux, "No wave atom in MS-style audio");
11788         } else {
11789           guint32 datalen = QT_UINT32 (stsd_entry_data + offset + 16);
11790           const guint8 *data = stsd_entry_data + offset + 16;
11791           GNode *wavenode;
11792           GNode *waveheadernode;
11793
11794           wavenode = g_node_new ((guint8 *) data);
11795           if (qtdemux_parse_node (qtdemux, wavenode, data, datalen)) {
11796             const guint8 *waveheader;
11797             guint32 headerlen;
11798
11799             waveheadernode = qtdemux_tree_get_child_by_type (wavenode, fourcc);
11800             if (waveheadernode) {
11801               waveheader = (const guint8 *) waveheadernode->data;
11802               headerlen = QT_UINT32 (waveheader);
11803
11804               if (headerlen > 8) {
11805                 gst_riff_strf_auds *header = NULL;
11806                 GstBuffer *headerbuf;
11807                 GstBuffer *extra;
11808
11809                 waveheader += 8;
11810                 headerlen -= 8;
11811
11812                 headerbuf = gst_buffer_new_and_alloc (headerlen);
11813                 gst_buffer_fill (headerbuf, 0, waveheader, headerlen);
11814
11815                 if (gst_riff_parse_strf_auds (GST_ELEMENT_CAST (qtdemux),
11816                         headerbuf, &header, &extra)) {
11817                   gst_caps_unref (entry->caps);
11818                   /* FIXME: Need to do something with the channel reorder map */
11819                   entry->caps =
11820                       gst_riff_create_audio_caps (header->format, NULL, header,
11821                       extra, NULL, NULL, NULL);
11822
11823                   if (extra)
11824                     gst_buffer_unref (extra);
11825                   g_free (header);
11826                 }
11827               }
11828             } else
11829               GST_DEBUG ("Didn't find waveheadernode for this codec");
11830           }
11831           g_node_destroy (wavenode);
11832         }
11833       } else if (esds) {
11834         gst_qtdemux_handle_esds (qtdemux, stream, entry, esds,
11835             stream->stream_tags);
11836       } else {
11837         switch (fourcc) {
11838 #if 0
11839             /* FIXME: what is in the chunk? */
11840           case FOURCC_QDMC:
11841           {
11842             gint len = QT_UINT32 (stsd_data);
11843
11844             /* seems to be always = 116 = 0x74 */
11845             break;
11846           }
11847 #endif
11848           case FOURCC_QDM2:
11849           {
11850             gint len = QT_UINT32 (stsd_entry_data);
11851
11852             if (len > 0x3C) {
11853               GstBuffer *buf = gst_buffer_new_and_alloc (len - 0x3C);
11854
11855               gst_buffer_fill (buf, 0, stsd_entry_data + 0x3C, len - 0x3C);
11856               gst_caps_set_simple (entry->caps,
11857                   "codec_data", GST_TYPE_BUFFER, buf, NULL);
11858               gst_buffer_unref (buf);
11859             }
11860             gst_caps_set_simple (entry->caps,
11861                 "samplesize", G_TYPE_INT, samplesize, NULL);
11862             break;
11863           }
11864           case FOURCC_alac:
11865           {
11866             GNode *alac, *wave = NULL;
11867
11868             /* apparently, m4a has this atom appended directly in the stsd entry,
11869              * while mov has it in a wave atom */
11870             alac = qtdemux_tree_get_child_by_type (stsd, FOURCC_alac);
11871             if (alac) {
11872               /* alac now refers to stsd entry atom */
11873               wave = qtdemux_tree_get_child_by_type (alac, FOURCC_wave);
11874               if (wave)
11875                 alac = qtdemux_tree_get_child_by_type (wave, FOURCC_alac);
11876               else
11877                 alac = qtdemux_tree_get_child_by_type (alac, FOURCC_alac);
11878             }
11879             if (alac) {
11880               const guint8 *alac_data = alac->data;
11881               gint len = QT_UINT32 (alac->data);
11882               GstBuffer *buf;
11883
11884               if (len < 36) {
11885                 GST_DEBUG_OBJECT (qtdemux,
11886                     "discarding alac atom with unexpected len %d", len);
11887               } else {
11888                 /* codec-data contains alac atom size and prefix,
11889                  * ffmpeg likes it that way, not quite gst-ish though ...*/
11890                 buf = gst_buffer_new_and_alloc (len);
11891                 gst_buffer_fill (buf, 0, alac->data, len);
11892                 gst_caps_set_simple (entry->caps,
11893                     "codec_data", GST_TYPE_BUFFER, buf, NULL);
11894                 gst_buffer_unref (buf);
11895
11896                 entry->bytes_per_frame = QT_UINT32 (alac_data + 12);
11897                 entry->n_channels = QT_UINT8 (alac_data + 21);
11898                 entry->rate = QT_UINT32 (alac_data + 32);
11899               }
11900             }
11901             gst_caps_set_simple (entry->caps,
11902                 "samplesize", G_TYPE_INT, samplesize, NULL);
11903             break;
11904           }
11905           case FOURCC_fLaC:
11906           {
11907             /* The codingname of the sample entry is 'fLaC' */
11908             GNode *flac = qtdemux_tree_get_child_by_type (stsd, FOURCC_fLaC);
11909
11910             if (flac) {
11911               /* The 'dfLa' box is added to the sample entry to convey
11912                  initializing information for the decoder. */
11913               const GNode *dfla =
11914                   qtdemux_tree_get_child_by_type (flac, FOURCC_dfLa);
11915
11916               if (dfla) {
11917                 const guint32 len = QT_UINT32 (dfla->data);
11918
11919                 /* Must contain at least dfLa box header (12),
11920                  * METADATA_BLOCK_HEADER (4), METADATA_BLOCK_STREAMINFO (34) */
11921                 if (len < 50) {
11922                   GST_DEBUG_OBJECT (qtdemux,
11923                       "discarding dfla atom with unexpected len %d", len);
11924                 } else {
11925                   /* skip dfLa header to get the METADATA_BLOCKs */
11926                   const guint8 *metadata_blocks = (guint8 *) dfla->data + 12;
11927                   const guint32 metadata_blocks_len = len - 12;
11928
11929                   gchar *stream_marker = g_strdup ("fLaC");
11930                   GstBuffer *block = gst_buffer_new_wrapped (stream_marker,
11931                       strlen (stream_marker));
11932
11933                   guint32 index = 0;
11934                   guint32 remainder = 0;
11935                   guint32 block_size = 0;
11936                   gboolean is_last = FALSE;
11937
11938                   GValue array = G_VALUE_INIT;
11939                   GValue value = G_VALUE_INIT;
11940
11941                   g_value_init (&array, GST_TYPE_ARRAY);
11942                   g_value_init (&value, GST_TYPE_BUFFER);
11943
11944                   gst_value_set_buffer (&value, block);
11945                   gst_value_array_append_value (&array, &value);
11946                   g_value_reset (&value);
11947
11948                   gst_buffer_unref (block);
11949
11950                   /* check there's at least one METADATA_BLOCK_HEADER's worth
11951                    * of data, and we haven't already finished parsing */
11952                   while (!is_last && ((index + 3) < metadata_blocks_len)) {
11953                     remainder = metadata_blocks_len - index;
11954
11955                     /* add the METADATA_BLOCK_HEADER size to the signalled size */
11956                     block_size = 4 +
11957                         (metadata_blocks[index + 1] << 16) +
11958                         (metadata_blocks[index + 2] << 8) +
11959                         metadata_blocks[index + 3];
11960
11961                     /* be careful not to read off end of box */
11962                     if (block_size > remainder) {
11963                       break;
11964                     }
11965
11966                     is_last = metadata_blocks[index] >> 7;
11967
11968                     block = gst_buffer_new_and_alloc (block_size);
11969
11970                     gst_buffer_fill (block, 0, &metadata_blocks[index],
11971                         block_size);
11972
11973                     gst_value_set_buffer (&value, block);
11974                     gst_value_array_append_value (&array, &value);
11975                     g_value_reset (&value);
11976
11977                     gst_buffer_unref (block);
11978
11979                     index += block_size;
11980                   }
11981
11982                   /* only append the metadata if we successfully read all of it */
11983                   if (is_last) {
11984                     gst_structure_set_value (gst_caps_get_structure (CUR_STREAM
11985                             (stream)->caps, 0), "streamheader", &array);
11986                   } else {
11987                     GST_WARNING_OBJECT (qtdemux,
11988                         "discarding all METADATA_BLOCKs due to invalid "
11989                         "block_size %d at idx %d, rem %d", block_size, index,
11990                         remainder);
11991                   }
11992
11993                   g_value_unset (&value);
11994                   g_value_unset (&array);
11995
11996                   /* The sample rate obtained from the stsd may not be accurate
11997                    * since it cannot represent rates greater than 65535Hz, so
11998                    * override that value with the sample rate from the
11999                    * METADATA_BLOCK_STREAMINFO block */
12000                   CUR_STREAM (stream)->rate =
12001                       (QT_UINT32 (metadata_blocks + 14) >> 12) & 0xFFFFF;
12002                 }
12003               }
12004             }
12005             break;
12006           }
12007           case FOURCC_sawb:
12008             /* Fallthrough! */
12009             amrwb = TRUE;
12010           case FOURCC_samr:
12011           {
12012             gint len = QT_UINT32 (stsd_entry_data);
12013
12014             if (len > 0x24) {
12015               GstBuffer *buf = gst_buffer_new_and_alloc (len - 0x24);
12016               guint bitrate;
12017
12018               gst_buffer_fill (buf, 0, stsd_entry_data + 0x24, len - 0x24);
12019
12020               /* If we have enough data, let's try to get the 'damr' atom. See
12021                * the 3GPP container spec (26.244) for more details. */
12022               if ((len - 0x34) > 8 &&
12023                   (bitrate = qtdemux_parse_amr_bitrate (buf, amrwb))) {
12024                 gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
12025                     GST_TAG_MAXIMUM_BITRATE, bitrate, NULL);
12026               }
12027
12028               gst_caps_set_simple (entry->caps,
12029                   "codec_data", GST_TYPE_BUFFER, buf, NULL);
12030               gst_buffer_unref (buf);
12031             }
12032             break;
12033           }
12034           case FOURCC_mp4a:
12035           {
12036             /* mp4a atom withtout ESDS; Attempt to build codec data from atom */
12037             gint len = QT_UINT32 (stsd_entry_data);
12038
12039             if (len >= 34) {
12040               guint16 sound_version = QT_UINT16 (stsd_entry_data + 16);
12041
12042               if (sound_version == 1) {
12043                 guint16 channels = QT_UINT16 (stsd_entry_data + 24);
12044                 guint32 time_scale = QT_UINT32 (stsd_entry_data + 30);
12045                 guint8 codec_data[2];
12046                 GstBuffer *buf;
12047                 gint profile = 2;       /* FIXME: Can this be determined somehow? There doesn't seem to be anything in mp4a atom that specifis compression */
12048
12049                 gint sample_rate_index =
12050                     gst_codec_utils_aac_get_index_from_sample_rate (time_scale);
12051
12052                 /* build AAC codec data */
12053                 codec_data[0] = profile << 3;
12054                 codec_data[0] |= ((sample_rate_index >> 1) & 0x7);
12055                 codec_data[1] = (sample_rate_index & 0x01) << 7;
12056                 codec_data[1] |= (channels & 0xF) << 3;
12057
12058                 buf = gst_buffer_new_and_alloc (2);
12059                 gst_buffer_fill (buf, 0, codec_data, 2);
12060                 gst_caps_set_simple (entry->caps,
12061                     "codec_data", GST_TYPE_BUFFER, buf, NULL);
12062                 gst_buffer_unref (buf);
12063               }
12064             }
12065             break;
12066           }
12067           case FOURCC_lpcm:
12068             /* Fully handled elsewhere */
12069             break;
12070           default:
12071             GST_INFO_OBJECT (qtdemux,
12072                 "unhandled type %" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (fourcc));
12073             break;
12074         }
12075       }
12076       GST_INFO_OBJECT (qtdemux,
12077           "type %" GST_FOURCC_FORMAT " caps %" GST_PTR_FORMAT,
12078           GST_FOURCC_ARGS (fourcc), entry->caps);
12079
12080     } else if (stream->subtype == FOURCC_strm) {
12081       if (fourcc == FOURCC_rtsp) {
12082         stream->redirect_uri = qtdemux_get_rtsp_uri_from_hndl (qtdemux, minf);
12083       } else {
12084         GST_INFO_OBJECT (qtdemux, "unhandled stream type %" GST_FOURCC_FORMAT,
12085             GST_FOURCC_ARGS (fourcc));
12086         goto unknown_stream;
12087       }
12088       entry->sampled = TRUE;
12089     } else if (stream->subtype == FOURCC_subp || stream->subtype == FOURCC_text
12090         || stream->subtype == FOURCC_sbtl || stream->subtype == FOURCC_subt
12091         || stream->subtype == FOURCC_clcp) {
12092
12093       entry->sampled = TRUE;
12094       entry->sparse = TRUE;
12095
12096       entry->caps =
12097           qtdemux_sub_caps (qtdemux, stream, entry, fourcc, stsd_entry_data,
12098           &codec);
12099       if (codec) {
12100         gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
12101             GST_TAG_SUBTITLE_CODEC, codec, NULL);
12102         g_free (codec);
12103         codec = NULL;
12104       }
12105
12106       /* hunt for sort-of codec data */
12107       switch (fourcc) {
12108         case FOURCC_mp4s:
12109         {
12110           GNode *mp4s = NULL;
12111           GNode *esds = NULL;
12112
12113           /* look for palette in a stsd->mp4s->esds sub-atom */
12114           mp4s = qtdemux_tree_get_child_by_type (stsd, FOURCC_mp4s);
12115           if (mp4s)
12116             esds = qtdemux_tree_get_child_by_type (mp4s, FOURCC_esds);
12117           if (esds == NULL) {
12118             /* Invalid STSD */
12119             GST_LOG_OBJECT (qtdemux, "Skipping invalid stsd: no esds child");
12120             break;
12121           }
12122
12123           gst_qtdemux_handle_esds (qtdemux, stream, entry, esds,
12124               stream->stream_tags);
12125           break;
12126         }
12127         default:
12128           GST_INFO_OBJECT (qtdemux,
12129               "unhandled type %" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (fourcc));
12130           break;
12131       }
12132       GST_INFO_OBJECT (qtdemux,
12133           "type %" GST_FOURCC_FORMAT " caps %" GST_PTR_FORMAT,
12134           GST_FOURCC_ARGS (fourcc), entry->caps);
12135     } else {
12136       /* everything in 1 sample */
12137       entry->sampled = TRUE;
12138
12139       entry->caps =
12140           qtdemux_generic_caps (qtdemux, stream, entry, fourcc, stsd_entry_data,
12141           &codec);
12142
12143       if (entry->caps == NULL)
12144         goto unknown_stream;
12145
12146       if (codec) {
12147         gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
12148             GST_TAG_SUBTITLE_CODEC, codec, NULL);
12149         g_free (codec);
12150         codec = NULL;
12151       }
12152     }
12153
12154     /* promote to sampled format */
12155     if (entry->fourcc == FOURCC_samr) {
12156       /* force mono 8000 Hz for AMR */
12157       entry->sampled = TRUE;
12158       entry->n_channels = 1;
12159       entry->rate = 8000;
12160     } else if (entry->fourcc == FOURCC_sawb) {
12161       /* force mono 16000 Hz for AMR-WB */
12162       entry->sampled = TRUE;
12163       entry->n_channels = 1;
12164       entry->rate = 16000;
12165     } else if (entry->fourcc == FOURCC_mp4a) {
12166       entry->sampled = TRUE;
12167     }
12168
12169
12170     stsd_entry_data += len;
12171     remaining_stsd_len -= len;
12172
12173   }
12174
12175   /* collect sample information */
12176   if (!qtdemux_stbl_init (qtdemux, stream, stbl))
12177     goto samples_failed;
12178
12179   if (qtdemux->fragmented) {
12180     guint64 offset;
12181
12182     /* need all moov samples as basis; probably not many if any at all */
12183     /* prevent moof parsing taking of at this time */
12184     offset = qtdemux->moof_offset;
12185     qtdemux->moof_offset = 0;
12186     if (stream->n_samples &&
12187         !qtdemux_parse_samples (qtdemux, stream, stream->n_samples - 1)) {
12188       qtdemux->moof_offset = offset;
12189       goto samples_failed;
12190     }
12191     qtdemux->moof_offset = 0;
12192     /* movie duration more reliable in this case (e.g. mehd) */
12193     if (qtdemux->segment.duration &&
12194         GST_CLOCK_TIME_IS_VALID (qtdemux->segment.duration))
12195       stream->duration =
12196           GSTTIME_TO_QTSTREAMTIME (stream, qtdemux->segment.duration);
12197   }
12198
12199   /* configure segments */
12200   if (!qtdemux_parse_segments (qtdemux, stream, trak))
12201     goto segments_failed;
12202
12203   /* add some language tag, if useful */
12204   if (stream->lang_id[0] != '\0' && strcmp (stream->lang_id, "unk") &&
12205       strcmp (stream->lang_id, "und")) {
12206     const gchar *lang_code;
12207
12208     /* convert ISO 639-2 code to ISO 639-1 */
12209     lang_code = gst_tag_get_language_code (stream->lang_id);
12210     gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
12211         GST_TAG_LANGUAGE_CODE, (lang_code) ? lang_code : stream->lang_id, NULL);
12212   }
12213
12214   /* Check for UDTA tags */
12215   if ((udta = qtdemux_tree_get_child_by_type (trak, FOURCC_udta))) {
12216     qtdemux_parse_udta (qtdemux, stream->stream_tags, udta);
12217   }
12218
12219   /* Insert and sort new stream in track-id order.
12220    * This will help in comparing old/new streams during stream update check */
12221   qtdemux->active_streams =
12222       g_list_insert_sorted (qtdemux->active_streams, stream,
12223       (GCompareFunc) qtdemux_track_id_compare_func);
12224   qtdemux->n_streams++;
12225   GST_DEBUG_OBJECT (qtdemux, "n_streams is now %d", qtdemux->n_streams);
12226
12227   return TRUE;
12228
12229 /* ERRORS */
12230 corrupt_file:
12231   {
12232     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
12233         (_("This file is corrupt and cannot be played.")), (NULL));
12234     if (stream)
12235       gst_qtdemux_stream_free (stream);
12236     return FALSE;
12237   }
12238 error_encrypted:
12239   {
12240     GST_ELEMENT_ERROR (qtdemux, STREAM, DECRYPT, (NULL), (NULL));
12241     gst_qtdemux_stream_free (stream);
12242     return FALSE;
12243   }
12244 samples_failed:
12245 segments_failed:
12246   {
12247     /* we posted an error already */
12248     /* free stbl sub-atoms */
12249     gst_qtdemux_stbl_free (stream);
12250     gst_qtdemux_stream_free (stream);
12251     return FALSE;
12252   }
12253 existing_stream:
12254   {
12255     GST_INFO_OBJECT (qtdemux, "stream with track id %i already exists",
12256         track_id);
12257     return TRUE;
12258   }
12259 unknown_stream:
12260   {
12261     GST_INFO_OBJECT (qtdemux, "unknown subtype %" GST_FOURCC_FORMAT,
12262         GST_FOURCC_ARGS (stream->subtype));
12263     gst_qtdemux_stream_free (stream);
12264     return TRUE;
12265   }
12266 }
12267
12268 /* If we can estimate the overall bitrate, and don't have information about the
12269  * stream bitrate for exactly one stream, this guesses the stream bitrate as
12270  * the overall bitrate minus the sum of the bitrates of all other streams. This
12271  * should be useful for the common case where we have one audio and one video
12272  * stream and can estimate the bitrate of one, but not the other. */
12273 static void
12274 gst_qtdemux_guess_bitrate (GstQTDemux * qtdemux)
12275 {
12276   QtDemuxStream *stream = NULL;
12277   gint64 size, sys_bitrate, sum_bitrate = 0;
12278   GstClockTime duration;
12279   guint bitrate;
12280   GList *iter;
12281
12282   if (qtdemux->fragmented)
12283     return;
12284
12285   GST_DEBUG_OBJECT (qtdemux, "Looking for streams with unknown bitrate");
12286
12287   if (!gst_pad_peer_query_duration (qtdemux->sinkpad, GST_FORMAT_BYTES, &size)
12288       || size <= 0) {
12289     GST_DEBUG_OBJECT (qtdemux,
12290         "Size in bytes of the stream not known - bailing");
12291     return;
12292   }
12293
12294   /* Subtract the header size */
12295   GST_DEBUG_OBJECT (qtdemux, "Total size %" G_GINT64_FORMAT ", header size %u",
12296       size, qtdemux->header_size);
12297
12298   if (size < qtdemux->header_size)
12299     return;
12300
12301   size = size - qtdemux->header_size;
12302
12303   if (!gst_qtdemux_get_duration (qtdemux, &duration)) {
12304     GST_DEBUG_OBJECT (qtdemux, "Stream duration not known - bailing");
12305     return;
12306   }
12307
12308   for (iter = qtdemux->active_streams; iter; iter = g_list_next (iter)) {
12309     QtDemuxStream *str = QTDEMUX_STREAM (iter->data);
12310     switch (str->subtype) {
12311       case FOURCC_soun:
12312       case FOURCC_vide:
12313         GST_DEBUG_OBJECT (qtdemux, "checking bitrate for %" GST_PTR_FORMAT,
12314             CUR_STREAM (str)->caps);
12315         /* retrieve bitrate, prefer avg then max */
12316         bitrate = 0;
12317         if (str->stream_tags) {
12318           if (gst_tag_list_get_uint (str->stream_tags,
12319                   GST_TAG_MAXIMUM_BITRATE, &bitrate))
12320             GST_DEBUG_OBJECT (qtdemux, "max-bitrate: %u", bitrate);
12321           if (gst_tag_list_get_uint (str->stream_tags,
12322                   GST_TAG_NOMINAL_BITRATE, &bitrate))
12323             GST_DEBUG_OBJECT (qtdemux, "nominal-bitrate: %u", bitrate);
12324           if (gst_tag_list_get_uint (str->stream_tags,
12325                   GST_TAG_BITRATE, &bitrate))
12326             GST_DEBUG_OBJECT (qtdemux, "bitrate: %u", bitrate);
12327         }
12328         if (bitrate)
12329           sum_bitrate += bitrate;
12330         else {
12331           if (stream) {
12332             GST_DEBUG_OBJECT (qtdemux,
12333                 ">1 stream with unknown bitrate - bailing");
12334             return;
12335           } else
12336             stream = str;
12337         }
12338
12339       default:
12340         /* For other subtypes, we assume no significant impact on bitrate */
12341         break;
12342     }
12343   }
12344
12345   if (!stream) {
12346     GST_DEBUG_OBJECT (qtdemux, "All stream bitrates are known");
12347     return;
12348   }
12349
12350   sys_bitrate = gst_util_uint64_scale (size, GST_SECOND * 8, duration);
12351
12352   if (sys_bitrate < sum_bitrate) {
12353     /* This can happen, since sum_bitrate might be derived from maximum
12354      * bitrates and not average bitrates */
12355     GST_DEBUG_OBJECT (qtdemux,
12356         "System bitrate less than sum bitrate - bailing");
12357     return;
12358   }
12359
12360   bitrate = sys_bitrate - sum_bitrate;
12361   GST_DEBUG_OBJECT (qtdemux, "System bitrate = %" G_GINT64_FORMAT
12362       ", Stream bitrate = %u", sys_bitrate, bitrate);
12363
12364   if (!stream->stream_tags)
12365     stream->stream_tags = gst_tag_list_new_empty ();
12366   else
12367     stream->stream_tags = gst_tag_list_make_writable (stream->stream_tags);
12368
12369   gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
12370       GST_TAG_BITRATE, bitrate, NULL);
12371 }
12372
12373 static GstFlowReturn
12374 qtdemux_prepare_streams (GstQTDemux * qtdemux)
12375 {
12376   GstFlowReturn ret = GST_FLOW_OK;
12377   GList *iter, *next;
12378
12379   GST_DEBUG_OBJECT (qtdemux, "prepare streams");
12380
12381   for (iter = qtdemux->active_streams; ret == GST_FLOW_OK && iter; iter = next) {
12382     QtDemuxStream *stream = QTDEMUX_STREAM (iter->data);
12383     guint32 sample_num = 0;
12384
12385     next = iter->next;
12386
12387     GST_DEBUG_OBJECT (qtdemux, "track-id %u, fourcc %" GST_FOURCC_FORMAT,
12388         stream->track_id, GST_FOURCC_ARGS (CUR_STREAM (stream)->fourcc));
12389
12390     if (qtdemux->fragmented) {
12391       /* need all moov samples first */
12392       GST_OBJECT_LOCK (qtdemux);
12393       while (stream->n_samples == 0)
12394         if ((ret = qtdemux_add_fragmented_samples (qtdemux)) != GST_FLOW_OK)
12395           break;
12396       GST_OBJECT_UNLOCK (qtdemux);
12397     } else {
12398       /* discard any stray moof */
12399       qtdemux->moof_offset = 0;
12400     }
12401
12402     /* prepare braking */
12403     if (ret != GST_FLOW_ERROR)
12404       ret = GST_FLOW_OK;
12405
12406     /* in pull mode, we should have parsed some sample info by now;
12407      * and quite some code will not handle no samples.
12408      * in push mode, we'll just have to deal with it */
12409     if (G_UNLIKELY (qtdemux->pullbased && !stream->n_samples)) {
12410       GST_DEBUG_OBJECT (qtdemux, "no samples for stream; discarding");
12411       gst_qtdemux_remove_stream (qtdemux, stream);
12412       continue;
12413     } else if (stream->track_id == qtdemux->chapters_track_id &&
12414         (stream->subtype == FOURCC_text || stream->subtype == FOURCC_sbtl)) {
12415       /* TODO - parse chapters track and expose it as GstToc; For now just ignore it
12416          so that it doesn't look like a subtitle track */
12417       gst_qtdemux_remove_stream (qtdemux, stream);
12418       continue;
12419     }
12420
12421     /* parse the initial sample for use in setting the frame rate cap */
12422     while (sample_num == 0 && sample_num < stream->n_samples) {
12423       if (!qtdemux_parse_samples (qtdemux, stream, sample_num))
12424         break;
12425       ++sample_num;
12426     }
12427   }
12428
12429   return ret;
12430 }
12431
12432 static GList *
12433 _stream_in_list (GList * list, QtDemuxStream * stream)
12434 {
12435   GList *iter;
12436
12437   for (iter = list; iter; iter = g_list_next (iter)) {
12438     QtDemuxStream *tmp = QTDEMUX_STREAM (iter->data);
12439     if (!g_strcmp0 (tmp->stream_id, stream->stream_id))
12440       return iter;
12441   }
12442
12443   return NULL;
12444 }
12445
12446 static gboolean
12447 qtdemux_is_streams_update (GstQTDemux * qtdemux)
12448 {
12449   GList *new, *old;
12450
12451   if (!qtdemux->active_streams)
12452     return FALSE;
12453
12454   /* streams in list are sorted in track-id order */
12455   for (new = qtdemux->active_streams, old = qtdemux->old_streams; new && old;
12456       new = g_list_next (new), old = g_list_next (old)) {
12457
12458     /* Different stream-id, updated */
12459     if (g_strcmp0 (QTDEMUX_STREAM (new->data)->stream_id,
12460             QTDEMUX_STREAM (old->data)->stream_id))
12461       return TRUE;
12462   }
12463
12464   /* Different length, updated */
12465   if (new != NULL || old != NULL)
12466     return TRUE;
12467
12468   return FALSE;
12469 }
12470
12471 static gboolean
12472 qtdemux_reuse_and_configure_stream (GstQTDemux * qtdemux,
12473     QtDemuxStream * oldstream, QtDemuxStream * newstream)
12474 {
12475   /* Connect old stream's srcpad to new stream */
12476   newstream->pad = oldstream->pad;
12477   oldstream->pad = NULL;
12478
12479   /* unset new_stream to prevent stream-start event */
12480   newstream->new_stream = FALSE;
12481
12482   return gst_qtdemux_configure_stream (qtdemux, newstream);
12483 }
12484
12485 static gboolean
12486 qtdemux_update_streams (GstQTDemux * qtdemux)
12487 {
12488   GList *iter, *next;
12489   g_assert (qtdemux->streams_aware);
12490
12491   /* At below, figure out which stream in active_streams has identical stream-id
12492    * with that of in old_streams. If there is matching stream-id,
12493    * corresponding newstream will not be exposed again,
12494    * but demux will reuse srcpad of matched old stream
12495    *
12496    * active_streams : newly created streams from the latest moov
12497    * old_streams : existing streams (belong to previous moov)
12498    */
12499
12500   /* Count n_streams again */
12501   qtdemux->n_streams = 0;
12502
12503   for (iter = qtdemux->active_streams; iter; iter = next) {
12504     GList *tmp;
12505     QtDemuxStream *stream = QTDEMUX_STREAM (iter->data);
12506
12507     next = iter->next;
12508
12509     GST_DEBUG_OBJECT (qtdemux, "track-id %u, fourcc %" GST_FOURCC_FORMAT,
12510         stream->track_id, GST_FOURCC_ARGS (CUR_STREAM (stream)->fourcc));
12511
12512     qtdemux->n_streams++;
12513
12514     if ((tmp = _stream_in_list (qtdemux->old_streams, stream)) != NULL
12515         && QTDEMUX_STREAM (tmp->data)->pad) {
12516       QtDemuxStream *oldstream = QTDEMUX_STREAM (tmp->data);
12517
12518       GST_DEBUG_OBJECT (qtdemux, "Reuse track-id %d", oldstream->track_id);
12519
12520       if (!qtdemux_reuse_and_configure_stream (qtdemux, oldstream, stream))
12521         return FALSE;
12522
12523       qtdemux->old_streams = g_list_remove (qtdemux->old_streams, oldstream);
12524       gst_qtdemux_stream_free (oldstream);
12525     } else {
12526       GstTagList *list;
12527
12528       /* now we have all info and can expose */
12529       list = stream->stream_tags;
12530       stream->stream_tags = NULL;
12531       if (!gst_qtdemux_add_stream (qtdemux, stream, list))
12532         return FALSE;
12533     }
12534   }
12535
12536   return TRUE;
12537 }
12538
12539 /* Must be called with expose lock */
12540 static GstFlowReturn
12541 qtdemux_expose_streams (GstQTDemux * qtdemux)
12542 {
12543   GList *iter, *next;
12544
12545   GST_DEBUG_OBJECT (qtdemux, "exposing streams");
12546
12547   if (!qtdemux_is_streams_update (qtdemux)) {
12548     GList *new, *old;
12549
12550     GST_DEBUG_OBJECT (qtdemux, "Reuse all streams");
12551     for (new = qtdemux->active_streams, old = qtdemux->old_streams; new && old;
12552         new = g_list_next (new), old = g_list_next (old)) {
12553       if (!qtdemux_reuse_and_configure_stream (qtdemux,
12554               QTDEMUX_STREAM (old->data), QTDEMUX_STREAM (new->data)))
12555         return GST_FLOW_ERROR;
12556     }
12557
12558     g_list_free_full (qtdemux->old_streams,
12559         (GDestroyNotify) gst_qtdemux_stream_free);
12560     qtdemux->old_streams = NULL;
12561
12562     return GST_FLOW_OK;
12563   }
12564
12565   if (qtdemux->streams_aware) {
12566     if (!qtdemux_update_streams (qtdemux))
12567       return GST_FLOW_ERROR;
12568   } else {
12569     for (iter = qtdemux->active_streams; iter; iter = g_list_next (iter)) {
12570       QtDemuxStream *stream = QTDEMUX_STREAM (iter->data);
12571       GstTagList *list;
12572
12573       /* now we have all info and can expose */
12574       list = stream->stream_tags;
12575       stream->stream_tags = NULL;
12576       if (!gst_qtdemux_add_stream (qtdemux, stream, list))
12577         return GST_FLOW_ERROR;
12578
12579     }
12580   }
12581
12582   gst_qtdemux_guess_bitrate (qtdemux);
12583
12584   gst_element_no_more_pads (GST_ELEMENT_CAST (qtdemux));
12585
12586   /* If we have still old_streams, it's no more used stream */
12587   for (iter = qtdemux->old_streams; iter; iter = next) {
12588     QtDemuxStream *stream = QTDEMUX_STREAM (iter->data);
12589     next = g_list_next (iter);
12590
12591     if (stream->pad) {
12592       GstEvent *event;
12593
12594       event = gst_event_new_eos ();
12595       if (qtdemux->segment_seqnum)
12596         gst_event_set_seqnum (event, qtdemux->segment_seqnum);
12597
12598       gst_pad_push_event (stream->pad, event);
12599     }
12600
12601     qtdemux->old_streams = g_list_remove (qtdemux->old_streams, stream);
12602     gst_qtdemux_stream_free (stream);
12603   }
12604
12605   /* check if we should post a redirect in case there is a single trak
12606    * and it is a redirecting trak */
12607   if (qtdemux->n_streams == 1 &&
12608       QTDEMUX_FIRST_STREAM (qtdemux)->redirect_uri != NULL) {
12609     GstMessage *m;
12610
12611     GST_INFO_OBJECT (qtdemux, "Issuing a redirect due to a single track with "
12612         "an external content");
12613     m = gst_message_new_element (GST_OBJECT_CAST (qtdemux),
12614         gst_structure_new ("redirect",
12615             "new-location", G_TYPE_STRING,
12616             QTDEMUX_FIRST_STREAM (qtdemux)->redirect_uri, NULL));
12617     gst_element_post_message (GST_ELEMENT_CAST (qtdemux), m);
12618     qtdemux->posted_redirect = TRUE;
12619   }
12620
12621   for (iter = qtdemux->active_streams; iter; iter = g_list_next (iter)) {
12622     qtdemux_do_allocation (qtdemux, QTDEMUX_STREAM (iter->data));
12623   }
12624
12625   qtdemux->need_segment = TRUE;
12626
12627   qtdemux->exposed = TRUE;
12628   return GST_FLOW_OK;
12629 }
12630
12631 /* check if major or compatible brand is 3GP */
12632 static inline gboolean
12633 qtdemux_is_brand_3gp (GstQTDemux * qtdemux, gboolean major)
12634 {
12635   if (major) {
12636     return ((qtdemux->major_brand & GST_MAKE_FOURCC (255, 255, 0, 0)) ==
12637         FOURCC_3g__);
12638   } else if (qtdemux->comp_brands != NULL) {
12639     GstMapInfo map;
12640     guint8 *data;
12641     gsize size;
12642     gboolean res = FALSE;
12643
12644     gst_buffer_map (qtdemux->comp_brands, &map, GST_MAP_READ);
12645     data = map.data;
12646     size = map.size;
12647     while (size >= 4) {
12648       res = res || ((QT_FOURCC (data) & GST_MAKE_FOURCC (255, 255, 0, 0)) ==
12649           FOURCC_3g__);
12650       data += 4;
12651       size -= 4;
12652     }
12653     gst_buffer_unmap (qtdemux->comp_brands, &map);
12654     return res;
12655   } else {
12656     return FALSE;
12657   }
12658 }
12659
12660 /* check if tag is a spec'ed 3GP tag keyword storing a string */
12661 static inline gboolean
12662 qtdemux_is_string_tag_3gp (GstQTDemux * qtdemux, guint32 fourcc)
12663 {
12664   return fourcc == FOURCC_cprt || fourcc == FOURCC_gnre || fourcc == FOURCC_titl
12665       || fourcc == FOURCC_dscp || fourcc == FOURCC_perf || fourcc == FOURCC_auth
12666       || fourcc == FOURCC_albm;
12667 }
12668
12669 static void
12670 qtdemux_tag_add_location (GstQTDemux * qtdemux, GstTagList * taglist,
12671     const char *tag, const char *dummy, GNode * node)
12672 {
12673   const gchar *env_vars[] = { "GST_QT_TAG_ENCODING", "GST_TAG_ENCODING", NULL };
12674   int offset;
12675   char *name;
12676   gchar *data;
12677   gdouble longitude, latitude, altitude;
12678   gint len;
12679
12680   len = QT_UINT32 (node->data);
12681   if (len <= 14)
12682     goto short_read;
12683
12684   data = node->data;
12685   offset = 14;
12686
12687   /* TODO: language code skipped */
12688
12689   name = gst_tag_freeform_string_to_utf8 (data + offset, -1, env_vars);
12690
12691   if (!name) {
12692     /* do not alarm in trivial case, but bail out otherwise */
12693     if (*(data + offset) != 0) {
12694       GST_DEBUG_OBJECT (qtdemux, "failed to convert %s tag to UTF-8, "
12695           "giving up", tag);
12696     }
12697   } else {
12698     gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE,
12699         GST_TAG_GEO_LOCATION_NAME, name, NULL);
12700     offset += strlen (name);
12701     g_free (name);
12702   }
12703
12704   if (len < offset + 2 + 4 + 4 + 4)
12705     goto short_read;
12706
12707   /* +1 +1 = skip null-terminator and location role byte */
12708   offset += 1 + 1;
12709   /* table in spec says unsigned, semantics say negative has meaning ... */
12710   longitude = QT_SFP32 (data + offset);
12711
12712   offset += 4;
12713   latitude = QT_SFP32 (data + offset);
12714
12715   offset += 4;
12716   altitude = QT_SFP32 (data + offset);
12717
12718   /* one invalid means all are invalid */
12719   if (longitude >= -180.0 && longitude <= 180.0 &&
12720       latitude >= -90.0 && latitude <= 90.0) {
12721     gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE,
12722         GST_TAG_GEO_LOCATION_LATITUDE, latitude,
12723         GST_TAG_GEO_LOCATION_LONGITUDE, longitude,
12724         GST_TAG_GEO_LOCATION_ELEVATION, altitude, NULL);
12725   }
12726
12727   /* TODO: no GST_TAG_, so astronomical body and additional notes skipped */
12728
12729   return;
12730
12731   /* ERRORS */
12732 short_read:
12733   {
12734     GST_DEBUG_OBJECT (qtdemux, "short read parsing 3GP location");
12735     return;
12736   }
12737 }
12738
12739
12740 static void
12741 qtdemux_tag_add_year (GstQTDemux * qtdemux, GstTagList * taglist,
12742     const char *tag, const char *dummy, GNode * node)
12743 {
12744   guint16 y;
12745   GDate *date;
12746   gint len;
12747
12748   len = QT_UINT32 (node->data);
12749   if (len < 14)
12750     return;
12751
12752   y = QT_UINT16 ((guint8 *) node->data + 12);
12753   if (y == 0) {
12754     GST_DEBUG_OBJECT (qtdemux, "year: %u is not a valid year", y);
12755     return;
12756   }
12757   GST_DEBUG_OBJECT (qtdemux, "year: %u", y);
12758
12759   date = g_date_new_dmy (1, 1, y);
12760   gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag, date, NULL);
12761   g_date_free (date);
12762 }
12763
12764 static void
12765 qtdemux_tag_add_classification (GstQTDemux * qtdemux, GstTagList * taglist,
12766     const char *tag, const char *dummy, GNode * node)
12767 {
12768   int offset;
12769   char *tag_str = NULL;
12770   guint8 *entity;
12771   guint16 table;
12772   gint len;
12773
12774   len = QT_UINT32 (node->data);
12775   if (len <= 20)
12776     goto short_read;
12777
12778   offset = 12;
12779   entity = (guint8 *) node->data + offset;
12780   if (entity[0] == 0 || entity[1] == 0 || entity[2] == 0 || entity[3] == 0) {
12781     GST_DEBUG_OBJECT (qtdemux,
12782         "classification info: %c%c%c%c invalid classification entity",
12783         entity[0], entity[1], entity[2], entity[3]);
12784     return;
12785   }
12786
12787   offset += 4;
12788   table = QT_UINT16 ((guint8 *) node->data + offset);
12789
12790   /* Language code skipped */
12791
12792   offset += 4;
12793
12794   /* Tag format: "XXXX://Y[YYYY]/classification info string"
12795    * XXXX: classification entity, fixed length 4 chars.
12796    * Y[YYYY]: classification table, max 5 chars.
12797    */
12798   tag_str = g_strdup_printf ("----://%u/%s",
12799       table, (char *) node->data + offset);
12800
12801   /* memcpy To be sure we're preserving byte order */
12802   memcpy (tag_str, entity, 4);
12803   GST_DEBUG_OBJECT (qtdemux, "classification info: %s", tag_str);
12804
12805   gst_tag_list_add (taglist, GST_TAG_MERGE_APPEND, tag, tag_str, NULL);
12806
12807   g_free (tag_str);
12808
12809   return;
12810
12811   /* ERRORS */
12812 short_read:
12813   {
12814     GST_DEBUG_OBJECT (qtdemux, "short read parsing 3GP classification");
12815     return;
12816   }
12817 }
12818
12819 static gboolean
12820 qtdemux_tag_add_str_full (GstQTDemux * qtdemux, GstTagList * taglist,
12821     const char *tag, const char *dummy, GNode * node)
12822 {
12823   const gchar *env_vars[] = { "GST_QT_TAG_ENCODING", "GST_TAG_ENCODING", NULL };
12824   GNode *data;
12825   char *s;
12826   int len;
12827   guint32 type;
12828   int offset;
12829   gboolean ret = TRUE;
12830   const gchar *charset = NULL;
12831
12832   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
12833   if (data) {
12834     len = QT_UINT32 (data->data);
12835     type = QT_UINT32 ((guint8 *) data->data + 8);
12836     if (type == 0x00000001 && len > 16) {
12837       s = gst_tag_freeform_string_to_utf8 ((char *) data->data + 16, len - 16,
12838           env_vars);
12839       if (s) {
12840         GST_DEBUG_OBJECT (qtdemux, "adding tag %s", GST_STR_NULL (s));
12841         gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag, s, NULL);
12842         g_free (s);
12843       } else {
12844         GST_DEBUG_OBJECT (qtdemux, "failed to convert %s tag to UTF-8", tag);
12845       }
12846     }
12847   } else {
12848     len = QT_UINT32 (node->data);
12849     type = QT_UINT32 ((guint8 *) node->data + 4);
12850     if ((type >> 24) == 0xa9 && len > 8 + 4) {
12851       gint str_len;
12852       gint lang_code;
12853
12854       /* Type starts with the (C) symbol, so the next data is a list
12855        * of (string size(16), language code(16), string) */
12856
12857       str_len = QT_UINT16 ((guint8 *) node->data + 8);
12858       lang_code = QT_UINT16 ((guint8 *) node->data + 10);
12859
12860       /* the string + fourcc + size + 2 16bit fields,
12861        * means that there are more tags in this atom */
12862       if (len > str_len + 8 + 4) {
12863         /* TODO how to represent the same tag in different languages? */
12864         GST_WARNING_OBJECT (qtdemux, "Ignoring metadata entry with multiple "
12865             "text alternatives, reading only first one");
12866       }
12867
12868       offset = 12;
12869       len = MIN (len, str_len + 8 + 4); /* remove trailing strings that we don't use */
12870       GST_DEBUG_OBJECT (qtdemux, "found international text tag");
12871
12872       if (lang_code < 0x800) {  /* MAC encoded string */
12873         charset = "mac";
12874       }
12875     } else if (len > 14 && qtdemux_is_string_tag_3gp (qtdemux,
12876             QT_FOURCC ((guint8 *) node->data + 4))) {
12877       guint32 type = QT_UINT32 ((guint8 *) node->data + 8);
12878
12879       /* we go for 3GP style encoding if major brands claims so,
12880        * or if no hope for data be ok UTF-8, and compatible 3GP brand present */
12881       if (qtdemux_is_brand_3gp (qtdemux, TRUE) ||
12882           (qtdemux_is_brand_3gp (qtdemux, FALSE) &&
12883               ((type & 0x00FFFFFF) == 0x0) && (type >> 24 <= 0xF))) {
12884         offset = 14;
12885         /* 16-bit Language code is ignored here as well */
12886         GST_DEBUG_OBJECT (qtdemux, "found 3gpp text tag");
12887       } else {
12888         goto normal;
12889       }
12890     } else {
12891     normal:
12892       offset = 8;
12893       GST_DEBUG_OBJECT (qtdemux, "found normal text tag");
12894       ret = FALSE;              /* may have to fallback */
12895     }
12896     if (charset) {
12897       GError *err = NULL;
12898
12899       s = g_convert ((gchar *) node->data + offset, len - offset, "utf8",
12900           charset, NULL, NULL, &err);
12901       if (err) {
12902         GST_DEBUG_OBJECT (qtdemux, "Failed to convert string from charset %s:"
12903             " %s(%d): %s", charset, g_quark_to_string (err->domain), err->code,
12904             err->message);
12905         g_error_free (err);
12906       }
12907     } else {
12908       s = gst_tag_freeform_string_to_utf8 ((char *) node->data + offset,
12909           len - offset, env_vars);
12910     }
12911     if (s) {
12912       GST_DEBUG_OBJECT (qtdemux, "adding tag %s", GST_STR_NULL (s));
12913       gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag, s, NULL);
12914       g_free (s);
12915       ret = TRUE;
12916     } else {
12917       GST_DEBUG_OBJECT (qtdemux, "failed to convert %s tag to UTF-8", tag);
12918     }
12919   }
12920   return ret;
12921 }
12922
12923 static void
12924 qtdemux_tag_add_str (GstQTDemux * qtdemux, GstTagList * taglist,
12925     const char *tag, const char *dummy, GNode * node)
12926 {
12927   qtdemux_tag_add_str_full (qtdemux, taglist, tag, dummy, node);
12928 }
12929
12930 static void
12931 qtdemux_tag_add_keywords (GstQTDemux * qtdemux, GstTagList * taglist,
12932     const char *tag, const char *dummy, GNode * node)
12933 {
12934   const gchar *env_vars[] = { "GST_QT_TAG_ENCODING", "GST_TAG_ENCODING", NULL };
12935   guint8 *data;
12936   char *s, *t, *k = NULL;
12937   int len;
12938   int offset;
12939   int count;
12940
12941   /* first try normal string tag if major brand not 3GP */
12942   if (!qtdemux_is_brand_3gp (qtdemux, TRUE)) {
12943     if (!qtdemux_tag_add_str_full (qtdemux, taglist, tag, dummy, node)) {
12944       /* hm, that did not work, maybe 3gpp storage in non-3gpp major brand;
12945        * let's try it 3gpp way after minor safety check */
12946       data = node->data;
12947       if (QT_UINT32 (data) < 15 || !qtdemux_is_brand_3gp (qtdemux, FALSE))
12948         return;
12949     } else
12950       return;
12951   }
12952
12953   GST_DEBUG_OBJECT (qtdemux, "found 3gpp keyword tag");
12954
12955   data = node->data;
12956
12957   len = QT_UINT32 (data);
12958   if (len < 15)
12959     goto short_read;
12960
12961   count = QT_UINT8 (data + 14);
12962   offset = 15;
12963   for (; count; count--) {
12964     gint slen;
12965
12966     if (offset + 1 > len)
12967       goto short_read;
12968     slen = QT_UINT8 (data + offset);
12969     offset += 1;
12970     if (offset + slen > len)
12971       goto short_read;
12972     s = gst_tag_freeform_string_to_utf8 ((char *) node->data + offset,
12973         slen, env_vars);
12974     if (s) {
12975       GST_DEBUG_OBJECT (qtdemux, "adding keyword %s", GST_STR_NULL (s));
12976       if (k) {
12977         t = g_strjoin (",", k, s, NULL);
12978         g_free (s);
12979         g_free (k);
12980         k = t;
12981       } else {
12982         k = s;
12983       }
12984     } else {
12985       GST_DEBUG_OBJECT (qtdemux, "failed to convert keyword to UTF-8");
12986     }
12987     offset += slen;
12988   }
12989
12990 done:
12991   if (k) {
12992     GST_DEBUG_OBJECT (qtdemux, "adding tag %s", GST_STR_NULL (k));
12993     gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag, k, NULL);
12994   }
12995   g_free (k);
12996
12997   return;
12998
12999   /* ERRORS */
13000 short_read:
13001   {
13002     GST_DEBUG_OBJECT (qtdemux, "short read parsing 3GP keywords");
13003     goto done;
13004   }
13005 }
13006
13007 static void
13008 qtdemux_tag_add_num (GstQTDemux * qtdemux, GstTagList * taglist,
13009     const char *tag1, const char *tag2, GNode * node)
13010 {
13011   GNode *data;
13012   int len;
13013   int type;
13014   int n1, n2;
13015
13016   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
13017   if (data) {
13018     len = QT_UINT32 (data->data);
13019     type = QT_UINT32 ((guint8 *) data->data + 8);
13020     if (type == 0x00000000 && len >= 22) {
13021       n1 = QT_UINT16 ((guint8 *) data->data + 18);
13022       n2 = QT_UINT16 ((guint8 *) data->data + 20);
13023       if (n1 > 0) {
13024         GST_DEBUG_OBJECT (qtdemux, "adding tag %s=%d", tag1, n1);
13025         gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag1, n1, NULL);
13026       }
13027       if (n2 > 0) {
13028         GST_DEBUG_OBJECT (qtdemux, "adding tag %s=%d", tag2, n2);
13029         gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag2, n2, NULL);
13030       }
13031     }
13032   }
13033 }
13034
13035 static void
13036 qtdemux_tag_add_tmpo (GstQTDemux * qtdemux, GstTagList * taglist,
13037     const char *tag1, const char *dummy, GNode * node)
13038 {
13039   GNode *data;
13040   int len;
13041   int type;
13042   int n1;
13043
13044   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
13045   if (data) {
13046     len = QT_UINT32 (data->data);
13047     type = QT_UINT32 ((guint8 *) data->data + 8);
13048     GST_DEBUG_OBJECT (qtdemux, "have tempo tag, type=%d,len=%d", type, len);
13049     /* some files wrongly have a type 0x0f=15, but it should be 0x15 */
13050     if ((type == 0x00000015 || type == 0x0000000f) && len >= 18) {
13051       n1 = QT_UINT16 ((guint8 *) data->data + 16);
13052       if (n1) {
13053         /* do not add bpm=0 */
13054         GST_DEBUG_OBJECT (qtdemux, "adding tag %d", n1);
13055         gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag1, (gdouble) n1,
13056             NULL);
13057       }
13058     }
13059   }
13060 }
13061
13062 static void
13063 qtdemux_tag_add_uint32 (GstQTDemux * qtdemux, GstTagList * taglist,
13064     const char *tag1, const char *dummy, GNode * node)
13065 {
13066   GNode *data;
13067   int len;
13068   int type;
13069   guint32 num;
13070
13071   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
13072   if (data) {
13073     len = QT_UINT32 (data->data);
13074     type = QT_UINT32 ((guint8 *) data->data + 8);
13075     GST_DEBUG_OBJECT (qtdemux, "have %s tag, type=%d,len=%d", tag1, type, len);
13076     /* some files wrongly have a type 0x0f=15, but it should be 0x15 */
13077     if ((type == 0x00000015 || type == 0x0000000f) && len >= 20) {
13078       num = QT_UINT32 ((guint8 *) data->data + 16);
13079       if (num) {
13080         /* do not add num=0 */
13081         GST_DEBUG_OBJECT (qtdemux, "adding tag %d", num);
13082         gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag1, num, NULL);
13083       }
13084     }
13085   }
13086 }
13087
13088 static void
13089 qtdemux_tag_add_covr (GstQTDemux * qtdemux, GstTagList * taglist,
13090     const char *tag1, const char *dummy, GNode * node)
13091 {
13092   GNode *data;
13093   int len;
13094   int type;
13095   GstSample *sample;
13096
13097   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
13098   if (data) {
13099     len = QT_UINT32 (data->data);
13100     type = QT_UINT32 ((guint8 *) data->data + 8);
13101     GST_DEBUG_OBJECT (qtdemux, "have covr tag, type=%d,len=%d", type, len);
13102     if ((type == 0x0000000d || type == 0x0000000e) && len > 16) {
13103       GstTagImageType image_type;
13104
13105       if (gst_tag_list_get_tag_size (taglist, GST_TAG_IMAGE) == 0)
13106         image_type = GST_TAG_IMAGE_TYPE_FRONT_COVER;
13107       else
13108         image_type = GST_TAG_IMAGE_TYPE_NONE;
13109
13110       if ((sample =
13111               gst_tag_image_data_to_image_sample ((guint8 *) data->data + 16,
13112                   len - 16, image_type))) {
13113         GST_DEBUG_OBJECT (qtdemux, "adding tag size %d", len - 16);
13114         gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag1, sample, NULL);
13115         gst_sample_unref (sample);
13116       }
13117     }
13118   }
13119 }
13120
13121 static void
13122 qtdemux_tag_add_date (GstQTDemux * qtdemux, GstTagList * taglist,
13123     const char *tag, const char *dummy, GNode * node)
13124 {
13125   GNode *data;
13126   GstDateTime *datetime = NULL;
13127   char *s;
13128   int len;
13129   int type;
13130
13131   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
13132   if (data) {
13133     len = QT_UINT32 (data->data);
13134     type = QT_UINT32 ((guint8 *) data->data + 8);
13135     if (type == 0x00000001 && len > 16) {
13136       guint y, m = 1, d = 1;
13137       gint ret;
13138
13139       s = g_strndup ((char *) data->data + 16, len - 16);
13140       GST_DEBUG_OBJECT (qtdemux, "adding date '%s'", s);
13141       datetime = gst_date_time_new_from_iso8601_string (s);
13142       if (datetime != NULL) {
13143         gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, GST_TAG_DATE_TIME,
13144             datetime, NULL);
13145         gst_date_time_unref (datetime);
13146       }
13147
13148       ret = sscanf (s, "%u-%u-%u", &y, &m, &d);
13149       if (ret >= 1 && y > 1500 && y < 3000) {
13150         GDate *date;
13151
13152         date = g_date_new_dmy (d, m, y);
13153         gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag, date, NULL);
13154         g_date_free (date);
13155       } else {
13156         GST_DEBUG_OBJECT (qtdemux, "could not parse date string '%s'", s);
13157       }
13158       g_free (s);
13159     }
13160   }
13161 }
13162
13163 static void
13164 qtdemux_tag_add_gnre (GstQTDemux * qtdemux, GstTagList * taglist,
13165     const char *tag, const char *dummy, GNode * node)
13166 {
13167   GNode *data;
13168
13169   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
13170
13171   /* re-route to normal string tag if major brand says so
13172    * or no data atom and compatible brand suggests so */
13173   if (qtdemux_is_brand_3gp (qtdemux, TRUE) ||
13174       (qtdemux_is_brand_3gp (qtdemux, FALSE) && !data)) {
13175     qtdemux_tag_add_str (qtdemux, taglist, tag, dummy, node);
13176     return;
13177   }
13178
13179   if (data) {
13180     guint len, type, n;
13181
13182     len = QT_UINT32 (data->data);
13183     type = QT_UINT32 ((guint8 *) data->data + 8);
13184     if (type == 0x00000000 && len >= 18) {
13185       n = QT_UINT16 ((guint8 *) data->data + 16);
13186       if (n > 0) {
13187         const gchar *genre;
13188
13189         genre = gst_tag_id3_genre_get (n - 1);
13190         if (genre != NULL) {
13191           GST_DEBUG_OBJECT (qtdemux, "adding %d [%s]", n, genre);
13192           gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag, genre, NULL);
13193         }
13194       }
13195     }
13196   }
13197 }
13198
13199 static void
13200 qtdemux_add_double_tag_from_str (GstQTDemux * demux, GstTagList * taglist,
13201     const gchar * tag, guint8 * data, guint32 datasize)
13202 {
13203   gdouble value;
13204   gchar *datacopy;
13205
13206   /* make a copy to have \0 at the end */
13207   datacopy = g_strndup ((gchar *) data, datasize);
13208
13209   /* convert the str to double */
13210   if (sscanf (datacopy, "%lf", &value) == 1) {
13211     GST_DEBUG_OBJECT (demux, "adding tag: %s [%s]", tag, datacopy);
13212     gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag, value, NULL);
13213   } else {
13214     GST_WARNING_OBJECT (demux, "Failed to parse double from string: %s",
13215         datacopy);
13216   }
13217   g_free (datacopy);
13218 }
13219
13220
13221 static void
13222 qtdemux_tag_add_revdns (GstQTDemux * demux, GstTagList * taglist,
13223     const char *tag, const char *tag_bis, GNode * node)
13224 {
13225   GNode *mean;
13226   GNode *name;
13227   GNode *data;
13228   guint32 meansize;
13229   guint32 namesize;
13230   guint32 datatype;
13231   guint32 datasize;
13232   const gchar *meanstr;
13233   const gchar *namestr;
13234
13235   /* checking the whole ---- atom size for consistency */
13236   if (QT_UINT32 (node->data) <= 4 + 12 + 12 + 16) {
13237     GST_WARNING_OBJECT (demux, "Tag ---- atom is too small, ignoring");
13238     return;
13239   }
13240
13241   mean = qtdemux_tree_get_child_by_type (node, FOURCC_mean);
13242   if (!mean) {
13243     GST_WARNING_OBJECT (demux, "No 'mean' atom found");
13244     return;
13245   }
13246
13247   meansize = QT_UINT32 (mean->data);
13248   if (meansize <= 12) {
13249     GST_WARNING_OBJECT (demux, "Small mean atom, ignoring the whole tag");
13250     return;
13251   }
13252   meanstr = ((gchar *) mean->data) + 12;
13253   meansize -= 12;
13254
13255   name = qtdemux_tree_get_child_by_type (node, FOURCC_name);
13256   if (!name) {
13257     GST_WARNING_OBJECT (demux, "'name' atom not found, ignoring tag");
13258     return;
13259   }
13260
13261   namesize = QT_UINT32 (name->data);
13262   if (namesize <= 12) {
13263     GST_WARNING_OBJECT (demux, "'name' atom is too small, ignoring tag");
13264     return;
13265   }
13266   namestr = ((gchar *) name->data) + 12;
13267   namesize -= 12;
13268
13269   /*
13270    * Data atom is:
13271    * uint32 - size
13272    * uint32 - name
13273    * uint8  - version
13274    * uint24 - data type
13275    * uint32 - all 0
13276    * rest   - the data
13277    */
13278   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
13279   if (!data) {
13280     GST_WARNING_OBJECT (demux, "No data atom in this tag");
13281     return;
13282   }
13283   datasize = QT_UINT32 (data->data);
13284   if (datasize <= 16) {
13285     GST_WARNING_OBJECT (demux, "Data atom too small");
13286     return;
13287   }
13288   datatype = QT_UINT32 (((gchar *) data->data) + 8) & 0xFFFFFF;
13289
13290   if ((strncmp (meanstr, "com.apple.iTunes", meansize) == 0) ||
13291       (strncmp (meanstr, "org.hydrogenaudio.replaygain", meansize) == 0)) {
13292     static const struct
13293     {
13294       const gchar name[28];
13295       const gchar tag[28];
13296     } tags[] = {
13297       {
13298       "replaygain_track_gain", GST_TAG_TRACK_GAIN}, {
13299       "replaygain_track_peak", GST_TAG_TRACK_PEAK}, {
13300       "replaygain_album_gain", GST_TAG_ALBUM_GAIN}, {
13301       "replaygain_album_peak", GST_TAG_ALBUM_PEAK}, {
13302       "MusicBrainz Track Id", GST_TAG_MUSICBRAINZ_TRACKID}, {
13303       "MusicBrainz Artist Id", GST_TAG_MUSICBRAINZ_ARTISTID}, {
13304       "MusicBrainz Album Id", GST_TAG_MUSICBRAINZ_ALBUMID}, {
13305       "MusicBrainz Album Artist Id", GST_TAG_MUSICBRAINZ_ALBUMARTISTID}
13306     };
13307     int i;
13308
13309     for (i = 0; i < G_N_ELEMENTS (tags); ++i) {
13310       if (!g_ascii_strncasecmp (tags[i].name, namestr, namesize)) {
13311         switch (gst_tag_get_type (tags[i].tag)) {
13312           case G_TYPE_DOUBLE:
13313             qtdemux_add_double_tag_from_str (demux, taglist, tags[i].tag,
13314                 ((guint8 *) data->data) + 16, datasize - 16);
13315             break;
13316           case G_TYPE_STRING:
13317             qtdemux_tag_add_str (demux, taglist, tags[i].tag, NULL, node);
13318             break;
13319           default:
13320             /* not reached */
13321             break;
13322         }
13323         break;
13324       }
13325     }
13326     if (i == G_N_ELEMENTS (tags))
13327       goto unknown_tag;
13328   } else {
13329     goto unknown_tag;
13330   }
13331
13332   return;
13333
13334 /* errors */
13335 unknown_tag:
13336 #ifndef GST_DISABLE_GST_DEBUG
13337   {
13338     gchar *namestr_dbg;
13339     gchar *meanstr_dbg;
13340
13341     meanstr_dbg = g_strndup (meanstr, meansize);
13342     namestr_dbg = g_strndup (namestr, namesize);
13343
13344     GST_WARNING_OBJECT (demux, "This tag %s:%s type:%u is not mapped, "
13345         "file a bug at bugzilla.gnome.org", meanstr_dbg, namestr_dbg, datatype);
13346
13347     g_free (namestr_dbg);
13348     g_free (meanstr_dbg);
13349   }
13350 #endif
13351   return;
13352 }
13353
13354 static void
13355 qtdemux_tag_add_id32 (GstQTDemux * demux, GstTagList * taglist, const char *tag,
13356     const char *tag_bis, GNode * node)
13357 {
13358   guint8 *data;
13359   GstBuffer *buf;
13360   guint len;
13361   GstTagList *id32_taglist = NULL;
13362
13363   GST_LOG_OBJECT (demux, "parsing ID32");
13364
13365   data = node->data;
13366   len = GST_READ_UINT32_BE (data);
13367
13368   /* need at least full box and language tag */
13369   if (len < 12 + 2)
13370     return;
13371
13372   buf = gst_buffer_new_allocate (NULL, len - 14, NULL);
13373   gst_buffer_fill (buf, 0, data + 14, len - 14);
13374
13375   id32_taglist = gst_tag_list_from_id3v2_tag (buf);
13376   if (id32_taglist) {
13377     GST_LOG_OBJECT (demux, "parsing ok");
13378     gst_tag_list_insert (taglist, id32_taglist, GST_TAG_MERGE_KEEP);
13379     gst_tag_list_unref (id32_taglist);
13380   } else {
13381     GST_LOG_OBJECT (demux, "parsing failed");
13382   }
13383
13384   gst_buffer_unref (buf);
13385 }
13386
13387 typedef void (*GstQTDemuxAddTagFunc) (GstQTDemux * demux, GstTagList * taglist,
13388     const char *tag, const char *tag_bis, GNode * node);
13389
13390 /* unmapped tags
13391 FOURCC_pcst -> if media is a podcast -> bool
13392 FOURCC_cpil -> if media is part of a compilation -> bool
13393 FOURCC_pgap -> if media is part of a gapless context -> bool
13394 FOURCC_tven -> the tv episode id e.g. S01E23 -> str
13395 */
13396
13397 static const struct
13398 {
13399   guint32 fourcc;
13400   const gchar *gst_tag;
13401   const gchar *gst_tag_bis;
13402   const GstQTDemuxAddTagFunc func;
13403 } add_funcs[] = {
13404   {
13405   FOURCC__nam, GST_TAG_TITLE, NULL, qtdemux_tag_add_str}, {
13406   FOURCC_titl, GST_TAG_TITLE, NULL, qtdemux_tag_add_str}, {
13407   FOURCC__grp, GST_TAG_GROUPING, NULL, qtdemux_tag_add_str}, {
13408   FOURCC__wrt, GST_TAG_COMPOSER, NULL, qtdemux_tag_add_str}, {
13409   FOURCC__ART, GST_TAG_ARTIST, NULL, qtdemux_tag_add_str}, {
13410   FOURCC_aART, GST_TAG_ALBUM_ARTIST, NULL, qtdemux_tag_add_str}, {
13411   FOURCC_perf, GST_TAG_ARTIST, NULL, qtdemux_tag_add_str}, {
13412   FOURCC_auth, GST_TAG_COMPOSER, NULL, qtdemux_tag_add_str}, {
13413   FOURCC__alb, GST_TAG_ALBUM, NULL, qtdemux_tag_add_str}, {
13414   FOURCC_albm, GST_TAG_ALBUM, NULL, qtdemux_tag_add_str}, {
13415   FOURCC_cprt, GST_TAG_COPYRIGHT, NULL, qtdemux_tag_add_str}, {
13416   FOURCC__cpy, GST_TAG_COPYRIGHT, NULL, qtdemux_tag_add_str}, {
13417   FOURCC__cmt, GST_TAG_COMMENT, NULL, qtdemux_tag_add_str}, {
13418   FOURCC__des, GST_TAG_DESCRIPTION, NULL, qtdemux_tag_add_str}, {
13419   FOURCC_desc, GST_TAG_DESCRIPTION, NULL, qtdemux_tag_add_str}, {
13420   FOURCC_dscp, GST_TAG_DESCRIPTION, NULL, qtdemux_tag_add_str}, {
13421   FOURCC__lyr, GST_TAG_LYRICS, NULL, qtdemux_tag_add_str}, {
13422   FOURCC__day, GST_TAG_DATE, NULL, qtdemux_tag_add_date}, {
13423   FOURCC_yrrc, GST_TAG_DATE, NULL, qtdemux_tag_add_year}, {
13424   FOURCC__too, GST_TAG_ENCODER, NULL, qtdemux_tag_add_str}, {
13425   FOURCC__inf, GST_TAG_COMMENT, NULL, qtdemux_tag_add_str}, {
13426   FOURCC_trkn, GST_TAG_TRACK_NUMBER, GST_TAG_TRACK_COUNT, qtdemux_tag_add_num}, {
13427   FOURCC_disk, GST_TAG_ALBUM_VOLUME_NUMBER, GST_TAG_ALBUM_VOLUME_COUNT,
13428         qtdemux_tag_add_num}, {
13429   FOURCC_disc, GST_TAG_ALBUM_VOLUME_NUMBER, GST_TAG_ALBUM_VOLUME_COUNT,
13430         qtdemux_tag_add_num}, {
13431   FOURCC__gen, GST_TAG_GENRE, NULL, qtdemux_tag_add_str}, {
13432   FOURCC_gnre, GST_TAG_GENRE, NULL, qtdemux_tag_add_gnre}, {
13433   FOURCC_tmpo, GST_TAG_BEATS_PER_MINUTE, NULL, qtdemux_tag_add_tmpo}, {
13434   FOURCC_covr, GST_TAG_IMAGE, NULL, qtdemux_tag_add_covr}, {
13435   FOURCC_sonm, GST_TAG_TITLE_SORTNAME, NULL, qtdemux_tag_add_str}, {
13436   FOURCC_soal, GST_TAG_ALBUM_SORTNAME, NULL, qtdemux_tag_add_str}, {
13437   FOURCC_soar, GST_TAG_ARTIST_SORTNAME, NULL, qtdemux_tag_add_str}, {
13438   FOURCC_soaa, GST_TAG_ALBUM_ARTIST_SORTNAME, NULL, qtdemux_tag_add_str}, {
13439   FOURCC_soco, GST_TAG_COMPOSER_SORTNAME, NULL, qtdemux_tag_add_str}, {
13440   FOURCC_sosn, GST_TAG_SHOW_SORTNAME, NULL, qtdemux_tag_add_str}, {
13441   FOURCC_tvsh, GST_TAG_SHOW_NAME, NULL, qtdemux_tag_add_str}, {
13442   FOURCC_tvsn, GST_TAG_SHOW_SEASON_NUMBER, NULL, qtdemux_tag_add_uint32}, {
13443   FOURCC_tves, GST_TAG_SHOW_EPISODE_NUMBER, NULL, qtdemux_tag_add_uint32}, {
13444   FOURCC_kywd, GST_TAG_KEYWORDS, NULL, qtdemux_tag_add_keywords}, {
13445   FOURCC_keyw, GST_TAG_KEYWORDS, NULL, qtdemux_tag_add_str}, {
13446   FOURCC__enc, GST_TAG_ENCODER, NULL, qtdemux_tag_add_str}, {
13447   FOURCC_loci, GST_TAG_GEO_LOCATION_NAME, NULL, qtdemux_tag_add_location}, {
13448   FOURCC_clsf, GST_QT_DEMUX_CLASSIFICATION_TAG, NULL,
13449         qtdemux_tag_add_classification}, {
13450   FOURCC__mak, GST_TAG_DEVICE_MANUFACTURER, NULL, qtdemux_tag_add_str}, {
13451   FOURCC__mod, GST_TAG_DEVICE_MODEL, NULL, qtdemux_tag_add_str}, {
13452   FOURCC__swr, GST_TAG_APPLICATION_NAME, NULL, qtdemux_tag_add_str}, {
13453
13454     /* This is a special case, some tags are stored in this
13455      * 'reverse dns naming', according to:
13456      * http://atomicparsley.sourceforge.net/mpeg-4files.html and
13457      * bug #614471
13458      */
13459   FOURCC_____, "", NULL, qtdemux_tag_add_revdns}, {
13460     /* see http://www.mp4ra.org/specs.html for ID32 in meta box */
13461   FOURCC_ID32, "", NULL, qtdemux_tag_add_id32}
13462 };
13463
13464 struct _GstQtDemuxTagList
13465 {
13466   GstQTDemux *demux;
13467   GstTagList *taglist;
13468 };
13469 typedef struct _GstQtDemuxTagList GstQtDemuxTagList;
13470
13471 static void
13472 qtdemux_tag_add_blob (GNode * node, GstQtDemuxTagList * qtdemuxtaglist)
13473 {
13474   gint len;
13475   guint8 *data;
13476   GstBuffer *buf;
13477   gchar *media_type;
13478   const gchar *style;
13479   GstSample *sample;
13480   GstStructure *s;
13481   guint i;
13482   guint8 ndata[4];
13483   GstQTDemux *demux = qtdemuxtaglist->demux;
13484   GstTagList *taglist = qtdemuxtaglist->taglist;
13485
13486   data = node->data;
13487   len = QT_UINT32 (data);
13488   buf = gst_buffer_new_and_alloc (len);
13489   gst_buffer_fill (buf, 0, data, len);
13490
13491   /* heuristic to determine style of tag */
13492   if (QT_FOURCC (data + 4) == FOURCC_____ ||
13493       (len > 8 + 12 && QT_FOURCC (data + 12) == FOURCC_data))
13494     style = "itunes";
13495   else if (demux->major_brand == FOURCC_qt__)
13496     style = "quicktime";
13497   /* fall back to assuming iso/3gp tag style */
13498   else
13499     style = "iso";
13500
13501   /* santize the name for the caps. */
13502   for (i = 0; i < 4; i++) {
13503     guint8 d = data[4 + i];
13504     if (g_ascii_isalnum (d))
13505       ndata[i] = g_ascii_tolower (d);
13506     else
13507       ndata[i] = '_';
13508   }
13509
13510   media_type = g_strdup_printf ("application/x-gst-qt-%c%c%c%c-tag",
13511       ndata[0], ndata[1], ndata[2], ndata[3]);
13512   GST_DEBUG_OBJECT (demux, "media type %s", media_type);
13513
13514   s = gst_structure_new (media_type, "style", G_TYPE_STRING, style, NULL);
13515   sample = gst_sample_new (buf, NULL, NULL, s);
13516   gst_buffer_unref (buf);
13517   g_free (media_type);
13518
13519   GST_DEBUG_OBJECT (demux, "adding private tag; size %d, info %" GST_PTR_FORMAT,
13520       len, s);
13521
13522   gst_tag_list_add (taglist, GST_TAG_MERGE_APPEND,
13523       GST_QT_DEMUX_PRIVATE_TAG, sample, NULL);
13524
13525   gst_sample_unref (sample);
13526 }
13527
13528 static void
13529 qtdemux_parse_udta (GstQTDemux * qtdemux, GstTagList * taglist, GNode * udta)
13530 {
13531   GNode *meta;
13532   GNode *ilst;
13533   GNode *xmp_;
13534   GNode *node;
13535   gint i;
13536   GstQtDemuxTagList demuxtaglist;
13537
13538   demuxtaglist.demux = qtdemux;
13539   demuxtaglist.taglist = taglist;
13540
13541   meta = qtdemux_tree_get_child_by_type (udta, FOURCC_meta);
13542   if (meta != NULL) {
13543     ilst = qtdemux_tree_get_child_by_type (meta, FOURCC_ilst);
13544     if (ilst == NULL) {
13545       GST_LOG_OBJECT (qtdemux, "no ilst");
13546       return;
13547     }
13548   } else {
13549     ilst = udta;
13550     GST_LOG_OBJECT (qtdemux, "no meta so using udta itself");
13551   }
13552
13553   i = 0;
13554   while (i < G_N_ELEMENTS (add_funcs)) {
13555     node = qtdemux_tree_get_child_by_type (ilst, add_funcs[i].fourcc);
13556     if (node) {
13557       gint len;
13558
13559       len = QT_UINT32 (node->data);
13560       if (len < 12) {
13561         GST_DEBUG_OBJECT (qtdemux, "too small tag atom %" GST_FOURCC_FORMAT,
13562             GST_FOURCC_ARGS (add_funcs[i].fourcc));
13563       } else {
13564         add_funcs[i].func (qtdemux, taglist, add_funcs[i].gst_tag,
13565             add_funcs[i].gst_tag_bis, node);
13566       }
13567       g_node_destroy (node);
13568     } else {
13569       i++;
13570     }
13571   }
13572
13573   /* parsed nodes have been removed, pass along remainder as blob */
13574   g_node_children_foreach (ilst, G_TRAVERSE_ALL,
13575       (GNodeForeachFunc) qtdemux_tag_add_blob, &demuxtaglist);
13576
13577   /* parse up XMP_ node if existing */
13578   xmp_ = qtdemux_tree_get_child_by_type (udta, FOURCC_XMP_);
13579   if (xmp_ != NULL) {
13580     GstBuffer *buf;
13581     GstTagList *xmptaglist;
13582
13583     buf = _gst_buffer_new_wrapped (((guint8 *) xmp_->data) + 8,
13584         QT_UINT32 ((guint8 *) xmp_->data) - 8, NULL);
13585     xmptaglist = gst_tag_list_from_xmp_buffer (buf);
13586     gst_buffer_unref (buf);
13587
13588     qtdemux_handle_xmp_taglist (qtdemux, taglist, xmptaglist);
13589   } else {
13590     GST_DEBUG_OBJECT (qtdemux, "No XMP_ node found");
13591   }
13592 }
13593
13594 typedef struct
13595 {
13596   GstStructure *structure;      /* helper for sort function */
13597   gchar *location;
13598   guint min_req_bitrate;
13599   guint min_req_qt_version;
13600 } GstQtReference;
13601
13602 static gint
13603 qtdemux_redirects_sort_func (gconstpointer a, gconstpointer b)
13604 {
13605   GstQtReference *ref_a = (GstQtReference *) a;
13606   GstQtReference *ref_b = (GstQtReference *) b;
13607
13608   if (ref_b->min_req_qt_version != ref_a->min_req_qt_version)
13609     return ref_b->min_req_qt_version - ref_a->min_req_qt_version;
13610
13611   /* known bitrates go before unknown; higher bitrates go first */
13612   return ref_b->min_req_bitrate - ref_a->min_req_bitrate;
13613 }
13614
13615 /* sort the redirects and post a message for the application.
13616  */
13617 static void
13618 qtdemux_process_redirects (GstQTDemux * qtdemux, GList * references)
13619 {
13620   GstQtReference *best;
13621   GstStructure *s;
13622   GstMessage *msg;
13623   GValue list_val = { 0, };
13624   GList *l;
13625
13626   g_assert (references != NULL);
13627
13628   references = g_list_sort (references, qtdemux_redirects_sort_func);
13629
13630   best = (GstQtReference *) references->data;
13631
13632   g_value_init (&list_val, GST_TYPE_LIST);
13633
13634   for (l = references; l != NULL; l = l->next) {
13635     GstQtReference *ref = (GstQtReference *) l->data;
13636     GValue struct_val = { 0, };
13637
13638     ref->structure = gst_structure_new ("redirect",
13639         "new-location", G_TYPE_STRING, ref->location, NULL);
13640
13641     if (ref->min_req_bitrate > 0) {
13642       gst_structure_set (ref->structure, "minimum-bitrate", G_TYPE_INT,
13643           ref->min_req_bitrate, NULL);
13644     }
13645
13646     g_value_init (&struct_val, GST_TYPE_STRUCTURE);
13647     g_value_set_boxed (&struct_val, ref->structure);
13648     gst_value_list_append_value (&list_val, &struct_val);
13649     g_value_unset (&struct_val);
13650     /* don't free anything here yet, since we need best->structure below */
13651   }
13652
13653   g_assert (best != NULL);
13654   s = gst_structure_copy (best->structure);
13655
13656   if (g_list_length (references) > 1) {
13657     gst_structure_set_value (s, "locations", &list_val);
13658   }
13659
13660   g_value_unset (&list_val);
13661
13662   for (l = references; l != NULL; l = l->next) {
13663     GstQtReference *ref = (GstQtReference *) l->data;
13664
13665     gst_structure_free (ref->structure);
13666     g_free (ref->location);
13667     g_free (ref);
13668   }
13669   g_list_free (references);
13670
13671   GST_INFO_OBJECT (qtdemux, "posting redirect message: %" GST_PTR_FORMAT, s);
13672   msg = gst_message_new_element (GST_OBJECT_CAST (qtdemux), s);
13673   gst_element_post_message (GST_ELEMENT_CAST (qtdemux), msg);
13674   qtdemux->posted_redirect = TRUE;
13675 }
13676
13677 /* look for redirect nodes, collect all redirect information and
13678  * process it.
13679  */
13680 static gboolean
13681 qtdemux_parse_redirects (GstQTDemux * qtdemux)
13682 {
13683   GNode *rmra, *rmda, *rdrf;
13684
13685   rmra = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_rmra);
13686   if (rmra) {
13687     GList *redirects = NULL;
13688
13689     rmda = qtdemux_tree_get_child_by_type (rmra, FOURCC_rmda);
13690     while (rmda) {
13691       GstQtReference ref = { NULL, NULL, 0, 0 };
13692       GNode *rmdr, *rmvc;
13693
13694       if ((rmdr = qtdemux_tree_get_child_by_type (rmda, FOURCC_rmdr))) {
13695         ref.min_req_bitrate = QT_UINT32 ((guint8 *) rmdr->data + 12);
13696         GST_LOG_OBJECT (qtdemux, "data rate atom, required bitrate = %u",
13697             ref.min_req_bitrate);
13698       }
13699
13700       if ((rmvc = qtdemux_tree_get_child_by_type (rmda, FOURCC_rmvc))) {
13701         guint32 package = QT_FOURCC ((guint8 *) rmvc->data + 12);
13702         guint version = QT_UINT32 ((guint8 *) rmvc->data + 16);
13703
13704 #ifndef GST_DISABLE_GST_DEBUG
13705         guint bitmask = QT_UINT32 ((guint8 *) rmvc->data + 20);
13706 #endif
13707         guint check_type = QT_UINT16 ((guint8 *) rmvc->data + 24);
13708
13709         GST_LOG_OBJECT (qtdemux,
13710             "version check atom [%" GST_FOURCC_FORMAT "], version=0x%08x"
13711             ", mask=%08x, check_type=%u", GST_FOURCC_ARGS (package), version,
13712             bitmask, check_type);
13713         if (package == FOURCC_qtim && check_type == 0) {
13714           ref.min_req_qt_version = version;
13715         }
13716       }
13717
13718       rdrf = qtdemux_tree_get_child_by_type (rmda, FOURCC_rdrf);
13719       if (rdrf) {
13720         guint32 ref_type;
13721         guint8 *ref_data;
13722         guint ref_len;
13723
13724         ref_len = QT_UINT32 ((guint8 *) rdrf->data);
13725         if (ref_len > 20) {
13726           ref_type = QT_FOURCC ((guint8 *) rdrf->data + 12);
13727           ref_data = (guint8 *) rdrf->data + 20;
13728           if (ref_type == FOURCC_alis) {
13729             guint record_len, record_version, fn_len;
13730
13731             if (ref_len > 70) {
13732               /* MacOSX alias record, google for alias-layout.txt */
13733               record_len = QT_UINT16 (ref_data + 4);
13734               record_version = QT_UINT16 (ref_data + 4 + 2);
13735               fn_len = QT_UINT8 (ref_data + 50);
13736               if (record_len > 50 && record_version == 2 && fn_len > 0) {
13737                 ref.location = g_strndup ((gchar *) ref_data + 51, fn_len);
13738               }
13739             } else {
13740               GST_WARNING_OBJECT (qtdemux, "Invalid rdrf/alis size (%u < 70)",
13741                   ref_len);
13742             }
13743           } else if (ref_type == FOURCC_url_) {
13744             ref.location = g_strndup ((gchar *) ref_data, ref_len - 8);
13745           } else {
13746             GST_DEBUG_OBJECT (qtdemux,
13747                 "unknown rdrf reference type %" GST_FOURCC_FORMAT,
13748                 GST_FOURCC_ARGS (ref_type));
13749           }
13750           if (ref.location != NULL) {
13751             GST_INFO_OBJECT (qtdemux, "New location: %s", ref.location);
13752             redirects =
13753                 g_list_prepend (redirects, g_memdup (&ref, sizeof (ref)));
13754           } else {
13755             GST_WARNING_OBJECT (qtdemux,
13756                 "Failed to extract redirect location from rdrf atom");
13757           }
13758         } else {
13759           GST_WARNING_OBJECT (qtdemux, "Invalid rdrf size (%u < 20)", ref_len);
13760         }
13761       }
13762
13763       /* look for others */
13764       rmda = qtdemux_tree_get_sibling_by_type (rmda, FOURCC_rmda);
13765     }
13766
13767     if (redirects != NULL) {
13768       qtdemux_process_redirects (qtdemux, redirects);
13769     }
13770   }
13771   return TRUE;
13772 }
13773
13774 static GstTagList *
13775 qtdemux_add_container_format (GstQTDemux * qtdemux, GstTagList * tags)
13776 {
13777   const gchar *fmt;
13778
13779   if (tags == NULL) {
13780     tags = gst_tag_list_new_empty ();
13781     gst_tag_list_set_scope (tags, GST_TAG_SCOPE_GLOBAL);
13782   }
13783
13784   if (qtdemux->major_brand == FOURCC_mjp2)
13785     fmt = "Motion JPEG 2000";
13786   else if ((qtdemux->major_brand & 0xffff) == FOURCC_3g__)
13787     fmt = "3GP";
13788   else if (qtdemux->major_brand == FOURCC_qt__)
13789     fmt = "Quicktime";
13790   else if (qtdemux->fragmented)
13791     fmt = "ISO fMP4";
13792   else
13793     fmt = "ISO MP4/M4A";
13794
13795   GST_LOG_OBJECT (qtdemux, "mapped %" GST_FOURCC_FORMAT " to '%s'",
13796       GST_FOURCC_ARGS (qtdemux->major_brand), fmt);
13797
13798   gst_tag_list_add (tags, GST_TAG_MERGE_REPLACE, GST_TAG_CONTAINER_FORMAT,
13799       fmt, NULL);
13800
13801   return tags;
13802 }
13803
13804 /* we have read the complete moov node now.
13805  * This function parses all of the relevant info, creates the traks and
13806  * prepares all data structures for playback
13807  */
13808 static gboolean
13809 qtdemux_parse_tree (GstQTDemux * qtdemux)
13810 {
13811   GNode *mvhd;
13812   GNode *trak;
13813   GNode *udta;
13814   GNode *mvex;
13815   GNode *pssh;
13816   guint64 creation_time;
13817   GstDateTime *datetime = NULL;
13818   gint version;
13819
13820   /* make sure we have a usable taglist */
13821   qtdemux->tag_list = gst_tag_list_make_writable (qtdemux->tag_list);
13822
13823   mvhd = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_mvhd);
13824   if (mvhd == NULL) {
13825     GST_LOG_OBJECT (qtdemux, "No mvhd node found, looking for redirects.");
13826     return qtdemux_parse_redirects (qtdemux);
13827   }
13828
13829   version = QT_UINT8 ((guint8 *) mvhd->data + 8);
13830   if (version == 1) {
13831     creation_time = QT_UINT64 ((guint8 *) mvhd->data + 12);
13832     qtdemux->timescale = QT_UINT32 ((guint8 *) mvhd->data + 28);
13833     qtdemux->duration = QT_UINT64 ((guint8 *) mvhd->data + 32);
13834   } else if (version == 0) {
13835     creation_time = QT_UINT32 ((guint8 *) mvhd->data + 12);
13836     qtdemux->timescale = QT_UINT32 ((guint8 *) mvhd->data + 20);
13837     qtdemux->duration = QT_UINT32 ((guint8 *) mvhd->data + 24);
13838   } else {
13839     GST_WARNING_OBJECT (qtdemux, "Unhandled mvhd version %d", version);
13840     return FALSE;
13841   }
13842
13843   /* Moving qt creation time (secs since 1904) to unix time */
13844   if (creation_time != 0) {
13845     /* Try to use epoch first as it should be faster and more commonly found */
13846     if (creation_time >= QTDEMUX_SECONDS_FROM_1904_TO_1970) {
13847       GTimeVal now;
13848
13849       creation_time -= QTDEMUX_SECONDS_FROM_1904_TO_1970;
13850       /* some data cleansing sanity */
13851       g_get_current_time (&now);
13852       if (now.tv_sec + 24 * 3600 < creation_time) {
13853         GST_DEBUG_OBJECT (qtdemux, "discarding bogus future creation time");
13854       } else {
13855         datetime = gst_date_time_new_from_unix_epoch_utc (creation_time);
13856       }
13857     } else {
13858       GDateTime *base_dt = g_date_time_new_utc (1904, 1, 1, 0, 0, 0);
13859       GDateTime *dt, *dt_local;
13860
13861       dt = g_date_time_add_seconds (base_dt, creation_time);
13862       dt_local = g_date_time_to_local (dt);
13863       datetime = gst_date_time_new_from_g_date_time (dt_local);
13864
13865       g_date_time_unref (base_dt);
13866       g_date_time_unref (dt);
13867     }
13868   }
13869   if (datetime) {
13870     /* Use KEEP as explicit tags should have a higher priority than mvhd tag */
13871     gst_tag_list_add (qtdemux->tag_list, GST_TAG_MERGE_KEEP, GST_TAG_DATE_TIME,
13872         datetime, NULL);
13873     gst_date_time_unref (datetime);
13874   }
13875
13876   GST_INFO_OBJECT (qtdemux, "timescale: %u", qtdemux->timescale);
13877   GST_INFO_OBJECT (qtdemux, "duration: %" G_GUINT64_FORMAT, qtdemux->duration);
13878
13879   /* check for fragmented file and get some (default) data */
13880   mvex = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_mvex);
13881   if (mvex) {
13882     GNode *mehd;
13883     GstByteReader mehd_data;
13884
13885     /* let track parsing or anyone know weird stuff might happen ... */
13886     qtdemux->fragmented = TRUE;
13887
13888     /* compensate for total duration */
13889     mehd = qtdemux_tree_get_child_by_type_full (mvex, FOURCC_mehd, &mehd_data);
13890     if (mehd)
13891       qtdemux_parse_mehd (qtdemux, &mehd_data);
13892   }
13893
13894   /* Update the movie segment duration, unless it was directly given to us
13895    * by upstream. Otherwise let it as is, as we don't want to mangle the
13896    * duration provided by upstream that may come e.g. from a MPD file. */
13897   if (!qtdemux->upstream_format_is_time) {
13898     GstClockTime duration;
13899     /* set duration in the segment info */
13900     gst_qtdemux_get_duration (qtdemux, &duration);
13901     qtdemux->segment.duration = duration;
13902     /* also do not exceed duration; stop is set that way post seek anyway,
13903      * and segment activation falls back to duration,
13904      * whereas loop only checks stop, so let's align this here as well */
13905     qtdemux->segment.stop = duration;
13906   }
13907
13908   /* parse all traks */
13909   trak = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_trak);
13910   while (trak) {
13911     qtdemux_parse_trak (qtdemux, trak);
13912     /* iterate all siblings */
13913     trak = qtdemux_tree_get_sibling_by_type (trak, FOURCC_trak);
13914   }
13915
13916   qtdemux->tag_list = gst_tag_list_make_writable (qtdemux->tag_list);
13917
13918   /* find tags */
13919   udta = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_udta);
13920   if (udta) {
13921     qtdemux_parse_udta (qtdemux, qtdemux->tag_list, udta);
13922   } else {
13923     GST_LOG_OBJECT (qtdemux, "No udta node found.");
13924   }
13925
13926   /* maybe also some tags in meta box */
13927   udta = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_meta);
13928   if (udta) {
13929     GST_DEBUG_OBJECT (qtdemux, "Parsing meta box for tags.");
13930     qtdemux_parse_udta (qtdemux, qtdemux->tag_list, udta);
13931   } else {
13932     GST_LOG_OBJECT (qtdemux, "No meta node found.");
13933   }
13934
13935   /* parse any protection system info */
13936   pssh = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_pssh);
13937   while (pssh) {
13938     GST_LOG_OBJECT (qtdemux, "Parsing pssh box.");
13939     qtdemux_parse_pssh (qtdemux, pssh);
13940     pssh = qtdemux_tree_get_sibling_by_type (pssh, FOURCC_pssh);
13941   }
13942
13943   qtdemux->tag_list = qtdemux_add_container_format (qtdemux, qtdemux->tag_list);
13944
13945   return TRUE;
13946 }
13947
13948 /* taken from ffmpeg */
13949 static int
13950 read_descr_size (guint8 * ptr, guint8 * end, guint8 ** end_out)
13951 {
13952   int count = 4;
13953   int len = 0;
13954
13955   while (count--) {
13956     int c;
13957
13958     if (ptr >= end)
13959       return -1;
13960
13961     c = *ptr++;
13962     len = (len << 7) | (c & 0x7f);
13963     if (!(c & 0x80))
13964       break;
13965   }
13966   *end_out = ptr;
13967   return len;
13968 }
13969
13970 static GList *
13971 parse_xiph_stream_headers (GstQTDemux * qtdemux, gpointer codec_data,
13972     gsize codec_data_size)
13973 {
13974   GList *list = NULL;
13975   guint8 *p = codec_data;
13976   gint i, offset, num_packets;
13977   guint *length, last;
13978
13979   GST_MEMDUMP_OBJECT (qtdemux, "xiph codec data", codec_data, codec_data_size);
13980
13981   if (codec_data == NULL || codec_data_size == 0)
13982     goto error;
13983
13984   /* start of the stream and vorbis audio or theora video, need to
13985    * send the codec_priv data as first three packets */
13986   num_packets = p[0] + 1;
13987   GST_DEBUG_OBJECT (qtdemux,
13988       "%u stream headers, total length=%" G_GSIZE_FORMAT " bytes",
13989       (guint) num_packets, codec_data_size);
13990
13991   /* Let's put some limits, Don't think there even is a xiph codec
13992    * with more than 3-4 headers */
13993   if (G_UNLIKELY (num_packets > 16)) {
13994     GST_WARNING_OBJECT (qtdemux,
13995         "Unlikely number of xiph headers, most likely not valid");
13996     goto error;
13997   }
13998
13999   length = g_alloca (num_packets * sizeof (guint));
14000   last = 0;
14001   offset = 1;
14002
14003   /* first packets, read length values */
14004   for (i = 0; i < num_packets - 1; i++) {
14005     length[i] = 0;
14006     while (offset < codec_data_size) {
14007       length[i] += p[offset];
14008       if (p[offset++] != 0xff)
14009         break;
14010     }
14011     last += length[i];
14012   }
14013   if (offset + last > codec_data_size)
14014     goto error;
14015
14016   /* last packet is the remaining size */
14017   length[i] = codec_data_size - offset - last;
14018
14019   for (i = 0; i < num_packets; i++) {
14020     GstBuffer *hdr;
14021
14022     GST_DEBUG_OBJECT (qtdemux, "buffer %d: %u bytes", i, (guint) length[i]);
14023
14024     if (offset + length[i] > codec_data_size)
14025       goto error;
14026
14027     hdr = gst_buffer_new_wrapped (g_memdup (p + offset, length[i]), length[i]);
14028     list = g_list_append (list, hdr);
14029
14030     offset += length[i];
14031   }
14032
14033   return list;
14034
14035   /* ERRORS */
14036 error:
14037   {
14038     if (list != NULL)
14039       g_list_free_full (list, (GDestroyNotify) gst_buffer_unref);
14040     return NULL;
14041   }
14042
14043 }
14044
14045 /* this can change the codec originally present in @list */
14046 static void
14047 gst_qtdemux_handle_esds (GstQTDemux * qtdemux, QtDemuxStream * stream,
14048     QtDemuxStreamStsdEntry * entry, GNode * esds, GstTagList * list)
14049 {
14050   int len = QT_UINT32 (esds->data);
14051   guint8 *ptr = esds->data;
14052   guint8 *end = ptr + len;
14053   int tag;
14054   guint8 *data_ptr = NULL;
14055   int data_len = 0;
14056   guint8 object_type_id = 0;
14057   guint8 stream_type = 0;
14058   const char *codec_name = NULL;
14059   GstCaps *caps = NULL;
14060
14061   GST_MEMDUMP_OBJECT (qtdemux, "esds", ptr, len);
14062   ptr += 8;
14063   GST_DEBUG_OBJECT (qtdemux, "version/flags = %08x", QT_UINT32 (ptr));
14064   ptr += 4;
14065   while (ptr + 1 < end) {
14066     tag = QT_UINT8 (ptr);
14067     GST_DEBUG_OBJECT (qtdemux, "tag = %02x", tag);
14068     ptr++;
14069     len = read_descr_size (ptr, end, &ptr);
14070     GST_DEBUG_OBJECT (qtdemux, "len = %d", len);
14071
14072     /* Check the stated amount of data is available for reading */
14073     if (len < 0 || ptr + len > end)
14074       break;
14075
14076     switch (tag) {
14077       case ES_DESCRIPTOR_TAG:
14078         GST_DEBUG_OBJECT (qtdemux, "ID 0x%04x", QT_UINT16 (ptr));
14079         GST_DEBUG_OBJECT (qtdemux, "priority 0x%04x", QT_UINT8 (ptr + 2));
14080         ptr += 3;
14081         break;
14082       case DECODER_CONFIG_DESC_TAG:{
14083         guint max_bitrate, avg_bitrate;
14084
14085         object_type_id = QT_UINT8 (ptr);
14086         stream_type = QT_UINT8 (ptr + 1) >> 2;
14087         max_bitrate = QT_UINT32 (ptr + 5);
14088         avg_bitrate = QT_UINT32 (ptr + 9);
14089         GST_DEBUG_OBJECT (qtdemux, "object_type_id %02x", object_type_id);
14090         GST_DEBUG_OBJECT (qtdemux, "stream_type %02x", stream_type);
14091         GST_DEBUG_OBJECT (qtdemux, "buffer_size_db %02x", QT_UINT24 (ptr + 2));
14092         GST_DEBUG_OBJECT (qtdemux, "max bitrate %u", max_bitrate);
14093         GST_DEBUG_OBJECT (qtdemux, "avg bitrate %u", avg_bitrate);
14094         if (max_bitrate > 0 && max_bitrate < G_MAXUINT32) {
14095           gst_tag_list_add (list, GST_TAG_MERGE_REPLACE,
14096               GST_TAG_MAXIMUM_BITRATE, max_bitrate, NULL);
14097         }
14098         if (avg_bitrate > 0 && avg_bitrate < G_MAXUINT32) {
14099           gst_tag_list_add (list, GST_TAG_MERGE_REPLACE, GST_TAG_BITRATE,
14100               avg_bitrate, NULL);
14101         }
14102         ptr += 13;
14103         break;
14104       }
14105       case DECODER_SPECIFIC_INFO_TAG:
14106         GST_MEMDUMP_OBJECT (qtdemux, "data", ptr, len);
14107         if (object_type_id == 0xe0 && len == 0x40) {
14108           guint8 *data;
14109           GstStructure *s;
14110           guint32 clut[16];
14111           gint i;
14112
14113           GST_DEBUG_OBJECT (qtdemux,
14114               "Have VOBSUB palette. Creating palette event");
14115           /* move to decConfigDescr data and read palette */
14116           data = ptr;
14117           for (i = 0; i < 16; i++) {
14118             clut[i] = QT_UINT32 (data);
14119             data += 4;
14120           }
14121
14122           s = gst_structure_new ("application/x-gst-dvd", "event",
14123               G_TYPE_STRING, "dvd-spu-clut-change",
14124               "clut00", G_TYPE_INT, clut[0], "clut01", G_TYPE_INT, clut[1],
14125               "clut02", G_TYPE_INT, clut[2], "clut03", G_TYPE_INT, clut[3],
14126               "clut04", G_TYPE_INT, clut[4], "clut05", G_TYPE_INT, clut[5],
14127               "clut06", G_TYPE_INT, clut[6], "clut07", G_TYPE_INT, clut[7],
14128               "clut08", G_TYPE_INT, clut[8], "clut09", G_TYPE_INT, clut[9],
14129               "clut10", G_TYPE_INT, clut[10], "clut11", G_TYPE_INT, clut[11],
14130               "clut12", G_TYPE_INT, clut[12], "clut13", G_TYPE_INT, clut[13],
14131               "clut14", G_TYPE_INT, clut[14], "clut15", G_TYPE_INT, clut[15],
14132               NULL);
14133
14134           /* store event and trigger custom processing */
14135           stream->pending_event =
14136               gst_event_new_custom (GST_EVENT_CUSTOM_DOWNSTREAM, s);
14137         } else {
14138           /* Generic codec_data handler puts it on the caps */
14139           data_ptr = ptr;
14140           data_len = len;
14141         }
14142
14143         ptr += len;
14144         break;
14145       case SL_CONFIG_DESC_TAG:
14146         GST_DEBUG_OBJECT (qtdemux, "data %02x", QT_UINT8 (ptr));
14147         ptr += 1;
14148         break;
14149       default:
14150         GST_DEBUG_OBJECT (qtdemux, "Unknown/unhandled descriptor tag %02x",
14151             tag);
14152         GST_MEMDUMP_OBJECT (qtdemux, "descriptor data", ptr, len);
14153         ptr += len;
14154         break;
14155     }
14156   }
14157
14158   /* object_type_id in the esds atom in mp4a and mp4v tells us which codec is
14159    * in use, and should also be used to override some other parameters for some
14160    * codecs. */
14161   switch (object_type_id) {
14162     case 0x20:                 /* MPEG-4 */
14163       /* 4 bytes for the visual_object_sequence_start_code and 1 byte for the
14164        * profile_and_level_indication */
14165       if (data_ptr != NULL && data_len >= 5 &&
14166           GST_READ_UINT32_BE (data_ptr) == 0x000001b0) {
14167         gst_codec_utils_mpeg4video_caps_set_level_and_profile (entry->caps,
14168             data_ptr + 4, data_len - 4);
14169       }
14170       break;                    /* Nothing special needed here */
14171     case 0x21:                 /* H.264 */
14172       codec_name = "H.264 / AVC";
14173       caps = gst_caps_new_simple ("video/x-h264",
14174           "stream-format", G_TYPE_STRING, "avc",
14175           "alignment", G_TYPE_STRING, "au", NULL);
14176       break;
14177     case 0x40:                 /* AAC (any) */
14178     case 0x66:                 /* AAC Main */
14179     case 0x67:                 /* AAC LC */
14180     case 0x68:                 /* AAC SSR */
14181       /* Override channels and rate based on the codec_data, as it's often
14182        * wrong. */
14183       /* Only do so for basic setup without HE-AAC extension */
14184       if (data_ptr && data_len == 2) {
14185         guint channels, rate;
14186
14187         channels = gst_codec_utils_aac_get_channels (data_ptr, data_len);
14188         if (channels > 0)
14189           entry->n_channels = channels;
14190
14191         rate = gst_codec_utils_aac_get_sample_rate (data_ptr, data_len);
14192         if (rate > 0)
14193           entry->rate = rate;
14194       }
14195
14196       /* Set level and profile if possible */
14197       if (data_ptr != NULL && data_len >= 2) {
14198         gst_codec_utils_aac_caps_set_level_and_profile (entry->caps,
14199             data_ptr, data_len);
14200       } else {
14201         const gchar *profile_str = NULL;
14202         GstBuffer *buffer;
14203         GstMapInfo map;
14204         guint8 *codec_data;
14205         gint rate_idx, profile;
14206
14207         /* No codec_data, let's invent something.
14208          * FIXME: This is wrong for SBR! */
14209
14210         GST_WARNING_OBJECT (qtdemux, "No codec_data for AAC available");
14211
14212         buffer = gst_buffer_new_and_alloc (2);
14213         gst_buffer_map (buffer, &map, GST_MAP_WRITE);
14214         codec_data = map.data;
14215
14216         rate_idx =
14217             gst_codec_utils_aac_get_index_from_sample_rate (CUR_STREAM
14218             (stream)->rate);
14219
14220         switch (object_type_id) {
14221           case 0x66:
14222             profile_str = "main";
14223             profile = 0;
14224             break;
14225           case 0x67:
14226             profile_str = "lc";
14227             profile = 1;
14228             break;
14229           case 0x68:
14230             profile_str = "ssr";
14231             profile = 2;
14232             break;
14233           default:
14234             profile = 3;
14235             break;
14236         }
14237
14238         codec_data[0] = ((profile + 1) << 3) | ((rate_idx & 0xE) >> 1);
14239         codec_data[1] =
14240             ((rate_idx & 0x1) << 7) | (CUR_STREAM (stream)->n_channels << 3);
14241
14242         gst_buffer_unmap (buffer, &map);
14243         gst_caps_set_simple (CUR_STREAM (stream)->caps, "codec_data",
14244             GST_TYPE_BUFFER, buffer, NULL);
14245         gst_buffer_unref (buffer);
14246
14247         if (profile_str) {
14248           gst_caps_set_simple (CUR_STREAM (stream)->caps, "profile",
14249               G_TYPE_STRING, profile_str, NULL);
14250         }
14251       }
14252       break;
14253     case 0x60:                 /* MPEG-2, various profiles */
14254     case 0x61:
14255     case 0x62:
14256     case 0x63:
14257     case 0x64:
14258     case 0x65:
14259       codec_name = "MPEG-2 video";
14260       caps = gst_caps_new_simple ("video/mpeg",
14261           "mpegversion", G_TYPE_INT, 2,
14262           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
14263       break;
14264     case 0x69:                 /* MPEG-2 BC audio */
14265     case 0x6B:                 /* MPEG-1 audio */
14266       caps = gst_caps_new_simple ("audio/mpeg",
14267           "mpegversion", G_TYPE_INT, 1, NULL);
14268       codec_name = "MPEG-1 audio";
14269       break;
14270     case 0x6A:                 /* MPEG-1 */
14271       codec_name = "MPEG-1 video";
14272       caps = gst_caps_new_simple ("video/mpeg",
14273           "mpegversion", G_TYPE_INT, 1,
14274           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
14275       break;
14276     case 0x6C:                 /* MJPEG */
14277       caps =
14278           gst_caps_new_simple ("image/jpeg", "parsed", G_TYPE_BOOLEAN, TRUE,
14279           NULL);
14280       codec_name = "Motion-JPEG";
14281       break;
14282     case 0x6D:                 /* PNG */
14283       caps =
14284           gst_caps_new_simple ("image/png", "parsed", G_TYPE_BOOLEAN, TRUE,
14285           NULL);
14286       codec_name = "PNG still images";
14287       break;
14288     case 0x6E:                 /* JPEG2000 */
14289       codec_name = "JPEG-2000";
14290       caps = gst_caps_new_simple ("image/x-j2c", "fields", G_TYPE_INT, 1, NULL);
14291       break;
14292     case 0xA4:                 /* Dirac */
14293       codec_name = "Dirac";
14294       caps = gst_caps_new_empty_simple ("video/x-dirac");
14295       break;
14296     case 0xA5:                 /* AC3 */
14297       codec_name = "AC-3 audio";
14298       caps = gst_caps_new_simple ("audio/x-ac3",
14299           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
14300       break;
14301     case 0xA9:                 /* AC3 */
14302       codec_name = "DTS audio";
14303       caps = gst_caps_new_simple ("audio/x-dts",
14304           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
14305       break;
14306     case 0xDD:
14307       if (stream_type == 0x05 && data_ptr) {
14308         GList *headers =
14309             parse_xiph_stream_headers (qtdemux, data_ptr, data_len);
14310         if (headers) {
14311           GList *tmp;
14312           GValue arr_val = G_VALUE_INIT;
14313           GValue buf_val = G_VALUE_INIT;
14314           GstStructure *s;
14315
14316           /* Let's assume it's vorbis if it's an audio stream of type 0xdd and we have codec data that extracts properly */
14317           codec_name = "Vorbis";
14318           caps = gst_caps_new_empty_simple ("audio/x-vorbis");
14319           g_value_init (&arr_val, GST_TYPE_ARRAY);
14320           g_value_init (&buf_val, GST_TYPE_BUFFER);
14321           for (tmp = headers; tmp; tmp = tmp->next) {
14322             g_value_set_boxed (&buf_val, (GstBuffer *) tmp->data);
14323             gst_value_array_append_value (&arr_val, &buf_val);
14324           }
14325           s = gst_caps_get_structure (caps, 0);
14326           gst_structure_take_value (s, "streamheader", &arr_val);
14327           g_value_unset (&buf_val);
14328           g_list_free (headers);
14329
14330           data_ptr = NULL;
14331           data_len = 0;
14332         }
14333       }
14334       break;
14335     case 0xE1:                 /* QCELP */
14336       /* QCELP, the codec_data is a riff tag (little endian) with
14337        * 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). */
14338       caps = gst_caps_new_empty_simple ("audio/qcelp");
14339       codec_name = "QCELP";
14340       break;
14341     default:
14342       break;
14343   }
14344
14345   /* If we have a replacement caps, then change our caps for this stream */
14346   if (caps) {
14347     gst_caps_unref (entry->caps);
14348     entry->caps = caps;
14349   }
14350
14351   if (codec_name && list)
14352     gst_tag_list_add (list, GST_TAG_MERGE_REPLACE,
14353         GST_TAG_AUDIO_CODEC, codec_name, NULL);
14354
14355   /* Add the codec_data attribute to caps, if we have it */
14356   if (data_ptr) {
14357     GstBuffer *buffer;
14358
14359     buffer = gst_buffer_new_and_alloc (data_len);
14360     gst_buffer_fill (buffer, 0, data_ptr, data_len);
14361
14362     GST_DEBUG_OBJECT (qtdemux, "setting codec_data from esds");
14363     GST_MEMDUMP_OBJECT (qtdemux, "codec_data from esds", data_ptr, data_len);
14364
14365     gst_caps_set_simple (entry->caps, "codec_data", GST_TYPE_BUFFER,
14366         buffer, NULL);
14367     gst_buffer_unref (buffer);
14368   }
14369
14370 }
14371
14372 static inline GstCaps *
14373 _get_unknown_codec_name (const gchar * type, guint32 fourcc)
14374 {
14375   GstCaps *caps;
14376   guint i;
14377   char *s, fourstr[5];
14378
14379   g_snprintf (fourstr, 5, "%" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (fourcc));
14380   for (i = 0; i < 4; i++) {
14381     if (!g_ascii_isalnum (fourstr[i]))
14382       fourstr[i] = '_';
14383   }
14384   s = g_strdup_printf ("%s/x-gst-fourcc-%s", type, g_strstrip (fourstr));
14385   caps = gst_caps_new_empty_simple (s);
14386   g_free (s);
14387   return caps;
14388 }
14389
14390 #define _codec(name) \
14391   do { \
14392     if (codec_name) { \
14393       *codec_name = g_strdup (name); \
14394     } \
14395   } while (0)
14396
14397 static GstCaps *
14398 qtdemux_video_caps (GstQTDemux * qtdemux, QtDemuxStream * stream,
14399     QtDemuxStreamStsdEntry * entry, guint32 fourcc,
14400     const guint8 * stsd_entry_data, gchar ** codec_name)
14401 {
14402   GstCaps *caps = NULL;
14403   GstVideoFormat format = GST_VIDEO_FORMAT_UNKNOWN;
14404
14405   switch (fourcc) {
14406     case FOURCC_png:
14407       _codec ("PNG still images");
14408       caps = gst_caps_new_empty_simple ("image/png");
14409       break;
14410     case FOURCC_jpeg:
14411       _codec ("JPEG still images");
14412       caps =
14413           gst_caps_new_simple ("image/jpeg", "parsed", G_TYPE_BOOLEAN, TRUE,
14414           NULL);
14415       break;
14416     case GST_MAKE_FOURCC ('m', 'j', 'p', 'a'):
14417     case GST_MAKE_FOURCC ('A', 'V', 'D', 'J'):
14418     case GST_MAKE_FOURCC ('M', 'J', 'P', 'G'):
14419     case GST_MAKE_FOURCC ('d', 'm', 'b', '1'):
14420       _codec ("Motion-JPEG");
14421       caps =
14422           gst_caps_new_simple ("image/jpeg", "parsed", G_TYPE_BOOLEAN, TRUE,
14423           NULL);
14424       break;
14425     case GST_MAKE_FOURCC ('m', 'j', 'p', 'b'):
14426       _codec ("Motion-JPEG format B");
14427       caps = gst_caps_new_empty_simple ("video/x-mjpeg-b");
14428       break;
14429     case FOURCC_mjp2:
14430       _codec ("JPEG-2000");
14431       /* override to what it should be according to spec, avoid palette_data */
14432       entry->bits_per_sample = 24;
14433       caps = gst_caps_new_simple ("image/x-j2c", "fields", G_TYPE_INT, 1, NULL);
14434       break;
14435     case FOURCC_SVQ3:
14436       _codec ("Sorensen video v.3");
14437       caps = gst_caps_new_simple ("video/x-svq",
14438           "svqversion", G_TYPE_INT, 3, NULL);
14439       break;
14440     case GST_MAKE_FOURCC ('s', 'v', 'q', 'i'):
14441     case GST_MAKE_FOURCC ('S', 'V', 'Q', '1'):
14442       _codec ("Sorensen video v.1");
14443       caps = gst_caps_new_simple ("video/x-svq",
14444           "svqversion", G_TYPE_INT, 1, NULL);
14445       break;
14446     case GST_MAKE_FOURCC ('W', 'R', 'A', 'W'):
14447       caps = gst_caps_new_empty_simple ("video/x-raw");
14448       gst_caps_set_simple (caps, "format", G_TYPE_STRING, "RGB8P", NULL);
14449       _codec ("Windows Raw RGB");
14450       stream->alignment = 32;
14451       break;
14452     case FOURCC_raw_:
14453     {
14454       guint16 bps;
14455
14456       bps = QT_UINT16 (stsd_entry_data + 82);
14457       switch (bps) {
14458         case 15:
14459           format = GST_VIDEO_FORMAT_RGB15;
14460           break;
14461         case 16:
14462           format = GST_VIDEO_FORMAT_RGB16;
14463           break;
14464         case 24:
14465           format = GST_VIDEO_FORMAT_RGB;
14466           break;
14467         case 32:
14468           format = GST_VIDEO_FORMAT_ARGB;
14469           break;
14470         default:
14471           /* unknown */
14472           break;
14473       }
14474       break;
14475     }
14476     case GST_MAKE_FOURCC ('y', 'v', '1', '2'):
14477       format = GST_VIDEO_FORMAT_I420;
14478       break;
14479     case GST_MAKE_FOURCC ('y', 'u', 'v', '2'):
14480     case GST_MAKE_FOURCC ('Y', 'u', 'v', '2'):
14481       format = GST_VIDEO_FORMAT_I420;
14482       break;
14483     case FOURCC_2vuy:
14484     case GST_MAKE_FOURCC ('2', 'V', 'u', 'y'):
14485       format = GST_VIDEO_FORMAT_UYVY;
14486       break;
14487     case GST_MAKE_FOURCC ('v', '3', '0', '8'):
14488       format = GST_VIDEO_FORMAT_v308;
14489       break;
14490     case GST_MAKE_FOURCC ('v', '2', '1', '6'):
14491       format = GST_VIDEO_FORMAT_v216;
14492       break;
14493     case FOURCC_v210:
14494       format = GST_VIDEO_FORMAT_v210;
14495       break;
14496     case GST_MAKE_FOURCC ('r', '2', '1', '0'):
14497       format = GST_VIDEO_FORMAT_r210;
14498       break;
14499       /* Packed YUV 4:4:4 10 bit in 32 bits, complex
14500          case GST_MAKE_FOURCC ('v', '4', '1', '0'):
14501          format = GST_VIDEO_FORMAT_v410;
14502          break;
14503        */
14504       /* Packed YUV 4:4:4:4 8 bit in 32 bits
14505        * but different order than AYUV
14506        case GST_MAKE_FOURCC ('v', '4', '0', '8'):
14507        format = GST_VIDEO_FORMAT_v408;
14508        break;
14509        */
14510     case GST_MAKE_FOURCC ('m', 'p', 'e', 'g'):
14511     case GST_MAKE_FOURCC ('m', 'p', 'g', '1'):
14512       _codec ("MPEG-1 video");
14513       caps = gst_caps_new_simple ("video/mpeg", "mpegversion", G_TYPE_INT, 1,
14514           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
14515       break;
14516     case GST_MAKE_FOURCC ('h', 'd', 'v', '1'): /* HDV 720p30 */
14517     case GST_MAKE_FOURCC ('h', 'd', 'v', '2'): /* HDV 1080i60 */
14518     case GST_MAKE_FOURCC ('h', 'd', 'v', '3'): /* HDV 1080i50 */
14519     case GST_MAKE_FOURCC ('h', 'd', 'v', '4'): /* HDV 720p24 */
14520     case GST_MAKE_FOURCC ('h', 'd', 'v', '5'): /* HDV 720p25 */
14521     case GST_MAKE_FOURCC ('h', 'd', 'v', '6'): /* HDV 1080p24 */
14522     case GST_MAKE_FOURCC ('h', 'd', 'v', '7'): /* HDV 1080p25 */
14523     case GST_MAKE_FOURCC ('h', 'd', 'v', '8'): /* HDV 1080p30 */
14524     case GST_MAKE_FOURCC ('h', 'd', 'v', '9'): /* HDV 720p60 */
14525     case GST_MAKE_FOURCC ('h', 'd', 'v', 'a'): /* HDV 720p50 */
14526     case GST_MAKE_FOURCC ('m', 'x', '5', 'n'): /* MPEG2 IMX NTSC 525/60 50mb/s produced by FCP */
14527     case GST_MAKE_FOURCC ('m', 'x', '5', 'p'): /* MPEG2 IMX PAL 625/60 50mb/s produced by FCP */
14528     case GST_MAKE_FOURCC ('m', 'x', '4', 'n'): /* MPEG2 IMX NTSC 525/60 40mb/s produced by FCP */
14529     case GST_MAKE_FOURCC ('m', 'x', '4', 'p'): /* MPEG2 IMX PAL 625/60 40mb/s produced by FCP */
14530     case GST_MAKE_FOURCC ('m', 'x', '3', 'n'): /* MPEG2 IMX NTSC 525/60 30mb/s produced by FCP */
14531     case GST_MAKE_FOURCC ('m', 'x', '3', 'p'): /* MPEG2 IMX PAL 625/50 30mb/s produced by FCP */
14532     case GST_MAKE_FOURCC ('x', 'd', 'v', '1'): /* XDCAM HD 720p30 35Mb/s */
14533     case GST_MAKE_FOURCC ('x', 'd', 'v', '2'): /* XDCAM HD 1080i60 35Mb/s */
14534     case GST_MAKE_FOURCC ('x', 'd', 'v', '3'): /* XDCAM HD 1080i50 35Mb/s */
14535     case GST_MAKE_FOURCC ('x', 'd', 'v', '4'): /* XDCAM HD 720p24 35Mb/s */
14536     case GST_MAKE_FOURCC ('x', 'd', 'v', '5'): /* XDCAM HD 720p25 35Mb/s */
14537     case GST_MAKE_FOURCC ('x', 'd', 'v', '6'): /* XDCAM HD 1080p24 35Mb/s */
14538     case GST_MAKE_FOURCC ('x', 'd', 'v', '7'): /* XDCAM HD 1080p25 35Mb/s */
14539     case GST_MAKE_FOURCC ('x', 'd', 'v', '8'): /* XDCAM HD 1080p30 35Mb/s */
14540     case GST_MAKE_FOURCC ('x', 'd', 'v', '9'): /* XDCAM HD 720p60 35Mb/s */
14541     case GST_MAKE_FOURCC ('x', 'd', 'v', 'a'): /* XDCAM HD 720p50 35Mb/s */
14542     case GST_MAKE_FOURCC ('x', 'd', 'v', 'b'): /* XDCAM EX 1080i60 50Mb/s CBR */
14543     case GST_MAKE_FOURCC ('x', 'd', 'v', 'c'): /* XDCAM EX 1080i50 50Mb/s CBR */
14544     case GST_MAKE_FOURCC ('x', 'd', 'v', 'd'): /* XDCAM HD 1080p24 50Mb/s CBR */
14545     case GST_MAKE_FOURCC ('x', 'd', 'v', 'e'): /* XDCAM HD 1080p25 50Mb/s CBR */
14546     case GST_MAKE_FOURCC ('x', 'd', 'v', 'f'): /* XDCAM HD 1080p30 50Mb/s CBR */
14547     case GST_MAKE_FOURCC ('x', 'd', '5', '1'): /* XDCAM HD422 720p30 50Mb/s CBR */
14548     case GST_MAKE_FOURCC ('x', 'd', '5', '4'): /* XDCAM HD422 720p24 50Mb/s CBR */
14549     case GST_MAKE_FOURCC ('x', 'd', '5', '5'): /* XDCAM HD422 720p25 50Mb/s CBR */
14550     case GST_MAKE_FOURCC ('x', 'd', '5', '9'): /* XDCAM HD422 720p60 50Mb/s CBR */
14551     case GST_MAKE_FOURCC ('x', 'd', '5', 'a'): /* XDCAM HD422 720p50 50Mb/s CBR */
14552     case GST_MAKE_FOURCC ('x', 'd', '5', 'b'): /* XDCAM HD422 1080i50 50Mb/s CBR */
14553     case GST_MAKE_FOURCC ('x', 'd', '5', 'c'): /* XDCAM HD422 1080i50 50Mb/s CBR */
14554     case GST_MAKE_FOURCC ('x', 'd', '5', 'd'): /* XDCAM HD422 1080p24 50Mb/s CBR */
14555     case GST_MAKE_FOURCC ('x', 'd', '5', 'e'): /* XDCAM HD422 1080p25 50Mb/s CBR */
14556     case GST_MAKE_FOURCC ('x', 'd', '5', 'f'): /* XDCAM HD422 1080p30 50Mb/s CBR */
14557     case GST_MAKE_FOURCC ('x', 'd', 'h', 'd'): /* XDCAM HD 540p */
14558     case GST_MAKE_FOURCC ('x', 'd', 'h', '2'): /* XDCAM HD422 540p */
14559     case GST_MAKE_FOURCC ('A', 'V', 'm', 'p'): /* AVID IMX PAL */
14560     case GST_MAKE_FOURCC ('m', 'p', 'g', '2'): /* AVID IMX PAL */
14561     case GST_MAKE_FOURCC ('m', 'p', '2', 'v'): /* AVID IMX PAL */
14562     case GST_MAKE_FOURCC ('m', '2', 'v', '1'):
14563       _codec ("MPEG-2 video");
14564       caps = gst_caps_new_simple ("video/mpeg", "mpegversion", G_TYPE_INT, 2,
14565           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
14566       break;
14567     case GST_MAKE_FOURCC ('g', 'i', 'f', ' '):
14568       _codec ("GIF still images");
14569       caps = gst_caps_new_empty_simple ("image/gif");
14570       break;
14571     case FOURCC_h263:
14572     case GST_MAKE_FOURCC ('H', '2', '6', '3'):
14573     case FOURCC_s263:
14574     case GST_MAKE_FOURCC ('U', '2', '6', '3'):
14575       _codec ("H.263");
14576       /* ffmpeg uses the height/width props, don't know why */
14577       caps = gst_caps_new_simple ("video/x-h263",
14578           "variant", G_TYPE_STRING, "itu", NULL);
14579       break;
14580     case FOURCC_mp4v:
14581     case FOURCC_MP4V:
14582       _codec ("MPEG-4 video");
14583       caps = gst_caps_new_simple ("video/mpeg", "mpegversion", G_TYPE_INT, 4,
14584           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
14585       break;
14586     case GST_MAKE_FOURCC ('3', 'i', 'v', 'd'):
14587     case GST_MAKE_FOURCC ('3', 'I', 'V', 'D'):
14588       _codec ("Microsoft MPEG-4 4.3");  /* FIXME? */
14589       caps = gst_caps_new_simple ("video/x-msmpeg",
14590           "msmpegversion", G_TYPE_INT, 43, NULL);
14591       break;
14592     case GST_MAKE_FOURCC ('D', 'I', 'V', '3'):
14593       _codec ("DivX 3");
14594       caps = gst_caps_new_simple ("video/x-divx",
14595           "divxversion", G_TYPE_INT, 3, NULL);
14596       break;
14597     case GST_MAKE_FOURCC ('D', 'I', 'V', 'X'):
14598     case GST_MAKE_FOURCC ('d', 'i', 'v', 'x'):
14599       _codec ("DivX 4");
14600       caps = gst_caps_new_simple ("video/x-divx",
14601           "divxversion", G_TYPE_INT, 4, NULL);
14602       break;
14603     case GST_MAKE_FOURCC ('D', 'X', '5', '0'):
14604       _codec ("DivX 5");
14605       caps = gst_caps_new_simple ("video/x-divx",
14606           "divxversion", G_TYPE_INT, 5, NULL);
14607       break;
14608
14609     case GST_MAKE_FOURCC ('F', 'F', 'V', '1'):
14610       _codec ("FFV1");
14611       caps = gst_caps_new_simple ("video/x-ffv",
14612           "ffvversion", G_TYPE_INT, 1, NULL);
14613       break;
14614
14615     case GST_MAKE_FOURCC ('3', 'I', 'V', '1'):
14616     case GST_MAKE_FOURCC ('3', 'I', 'V', '2'):
14617     case FOURCC_XVID:
14618     case FOURCC_xvid:
14619     case FOURCC_FMP4:
14620     case FOURCC_fmp4:
14621     case GST_MAKE_FOURCC ('U', 'M', 'P', '4'):
14622       caps = gst_caps_new_simple ("video/mpeg", "mpegversion", G_TYPE_INT, 4,
14623           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
14624       _codec ("MPEG-4");
14625       break;
14626
14627     case GST_MAKE_FOURCC ('c', 'v', 'i', 'd'):
14628       _codec ("Cinepak");
14629       caps = gst_caps_new_empty_simple ("video/x-cinepak");
14630       break;
14631     case GST_MAKE_FOURCC ('q', 'd', 'r', 'w'):
14632       _codec ("Apple QuickDraw");
14633       caps = gst_caps_new_empty_simple ("video/x-qdrw");
14634       break;
14635     case GST_MAKE_FOURCC ('r', 'p', 'z', 'a'):
14636       _codec ("Apple video");
14637       caps = gst_caps_new_empty_simple ("video/x-apple-video");
14638       break;
14639     case FOURCC_H264:
14640     case FOURCC_avc1:
14641       _codec ("H.264 / AVC");
14642       caps = gst_caps_new_simple ("video/x-h264",
14643           "stream-format", G_TYPE_STRING, "avc",
14644           "alignment", G_TYPE_STRING, "au", NULL);
14645       break;
14646     case FOURCC_avc3:
14647       _codec ("H.264 / AVC");
14648       caps = gst_caps_new_simple ("video/x-h264",
14649           "stream-format", G_TYPE_STRING, "avc3",
14650           "alignment", G_TYPE_STRING, "au", NULL);
14651       break;
14652     case FOURCC_H265:
14653     case FOURCC_hvc1:
14654       _codec ("H.265 / HEVC");
14655       caps = gst_caps_new_simple ("video/x-h265",
14656           "stream-format", G_TYPE_STRING, "hvc1",
14657           "alignment", G_TYPE_STRING, "au", NULL);
14658       break;
14659     case FOURCC_hev1:
14660       _codec ("H.265 / HEVC");
14661       caps = gst_caps_new_simple ("video/x-h265",
14662           "stream-format", G_TYPE_STRING, "hev1",
14663           "alignment", G_TYPE_STRING, "au", NULL);
14664       break;
14665     case FOURCC_rle_:
14666       _codec ("Run-length encoding");
14667       caps = gst_caps_new_simple ("video/x-rle",
14668           "layout", G_TYPE_STRING, "quicktime", NULL);
14669       break;
14670     case FOURCC_WRLE:
14671       _codec ("Run-length encoding");
14672       caps = gst_caps_new_simple ("video/x-rle",
14673           "layout", G_TYPE_STRING, "microsoft", NULL);
14674       break;
14675     case GST_MAKE_FOURCC ('I', 'V', '3', '2'):
14676     case GST_MAKE_FOURCC ('i', 'v', '3', '2'):
14677       _codec ("Indeo Video 3");
14678       caps = gst_caps_new_simple ("video/x-indeo",
14679           "indeoversion", G_TYPE_INT, 3, NULL);
14680       break;
14681     case GST_MAKE_FOURCC ('I', 'V', '4', '1'):
14682     case GST_MAKE_FOURCC ('i', 'v', '4', '1'):
14683       _codec ("Intel Video 4");
14684       caps = gst_caps_new_simple ("video/x-indeo",
14685           "indeoversion", G_TYPE_INT, 4, NULL);
14686       break;
14687     case FOURCC_dvcp:
14688     case FOURCC_dvc_:
14689     case GST_MAKE_FOURCC ('d', 'v', 's', 'd'):
14690     case GST_MAKE_FOURCC ('D', 'V', 'S', 'D'):
14691     case GST_MAKE_FOURCC ('d', 'v', 'c', 's'):
14692     case GST_MAKE_FOURCC ('D', 'V', 'C', 'S'):
14693     case GST_MAKE_FOURCC ('d', 'v', '2', '5'):
14694     case GST_MAKE_FOURCC ('d', 'v', 'p', 'p'):
14695       _codec ("DV Video");
14696       caps = gst_caps_new_simple ("video/x-dv", "dvversion", G_TYPE_INT, 25,
14697           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
14698       break;
14699     case FOURCC_dv5n:          /* DVCPRO50 NTSC */
14700     case FOURCC_dv5p:          /* DVCPRO50 PAL */
14701       _codec ("DVCPro50 Video");
14702       caps = gst_caps_new_simple ("video/x-dv", "dvversion", G_TYPE_INT, 50,
14703           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
14704       break;
14705     case GST_MAKE_FOURCC ('d', 'v', 'h', '5'): /* DVCPRO HD 50i produced by FCP */
14706     case GST_MAKE_FOURCC ('d', 'v', 'h', '6'): /* DVCPRO HD 60i produced by FCP */
14707       _codec ("DVCProHD Video");
14708       caps = gst_caps_new_simple ("video/x-dv", "dvversion", G_TYPE_INT, 100,
14709           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
14710       break;
14711     case GST_MAKE_FOURCC ('s', 'm', 'c', ' '):
14712       _codec ("Apple Graphics (SMC)");
14713       caps = gst_caps_new_empty_simple ("video/x-smc");
14714       break;
14715     case GST_MAKE_FOURCC ('V', 'P', '3', '1'):
14716       _codec ("VP3");
14717       caps = gst_caps_new_empty_simple ("video/x-vp3");
14718       break;
14719     case GST_MAKE_FOURCC ('V', 'P', '6', 'F'):
14720       _codec ("VP6 Flash");
14721       caps = gst_caps_new_empty_simple ("video/x-vp6-flash");
14722       break;
14723     case FOURCC_XiTh:
14724       _codec ("Theora");
14725       caps = gst_caps_new_empty_simple ("video/x-theora");
14726       /* theora uses one byte of padding in the data stream because it does not
14727        * allow 0 sized packets while theora does */
14728       entry->padding = 1;
14729       break;
14730     case FOURCC_drac:
14731       _codec ("Dirac");
14732       caps = gst_caps_new_empty_simple ("video/x-dirac");
14733       break;
14734     case GST_MAKE_FOURCC ('t', 'i', 'f', 'f'):
14735       _codec ("TIFF still images");
14736       caps = gst_caps_new_empty_simple ("image/tiff");
14737       break;
14738     case GST_MAKE_FOURCC ('i', 'c', 'o', 'd'):
14739       _codec ("Apple Intermediate Codec");
14740       caps = gst_caps_from_string ("video/x-apple-intermediate-codec");
14741       break;
14742     case GST_MAKE_FOURCC ('A', 'V', 'd', 'n'):
14743       _codec ("AVID DNxHD");
14744       caps = gst_caps_from_string ("video/x-dnxhd");
14745       break;
14746     case FOURCC_VP80:
14747     case FOURCC_vp08:
14748       _codec ("On2 VP8");
14749       caps = gst_caps_from_string ("video/x-vp8");
14750       break;
14751     case FOURCC_vp09:
14752       _codec ("Google VP9");
14753       caps = gst_caps_from_string ("video/x-vp9");
14754       break;
14755     case FOURCC_apcs:
14756       _codec ("Apple ProRes LT");
14757       caps =
14758           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING, "lt",
14759           NULL);
14760       break;
14761     case FOURCC_apch:
14762       _codec ("Apple ProRes HQ");
14763       caps =
14764           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING, "hq",
14765           NULL);
14766       break;
14767     case FOURCC_apcn:
14768       _codec ("Apple ProRes");
14769       caps =
14770           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING,
14771           "standard", NULL);
14772       break;
14773     case FOURCC_apco:
14774       _codec ("Apple ProRes Proxy");
14775       caps =
14776           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING,
14777           "proxy", NULL);
14778       break;
14779     case FOURCC_ap4h:
14780       _codec ("Apple ProRes 4444");
14781       caps =
14782           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING,
14783           "4444", NULL);
14784       break;
14785     case FOURCC_ap4x:
14786       _codec ("Apple ProRes 4444 XQ");
14787       caps =
14788           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING,
14789           "4444xq", NULL);
14790       break;
14791     case FOURCC_cfhd:
14792       _codec ("GoPro CineForm");
14793       caps = gst_caps_from_string ("video/x-cineform");
14794       break;
14795     case FOURCC_vc_1:
14796     case FOURCC_ovc1:
14797       _codec ("VC-1");
14798       caps = gst_caps_new_simple ("video/x-wmv",
14799           "wmvversion", G_TYPE_INT, 3, "format", G_TYPE_STRING, "WVC1", NULL);
14800       break;
14801     case FOURCC_av01:
14802       _codec ("AV1");
14803       caps = gst_caps_new_empty_simple ("video/x-av1");
14804       break;
14805     case GST_MAKE_FOURCC ('k', 'p', 'c', 'd'):
14806     default:
14807     {
14808       caps = _get_unknown_codec_name ("video", fourcc);
14809       break;
14810     }
14811   }
14812
14813   if (format != GST_VIDEO_FORMAT_UNKNOWN) {
14814     GstVideoInfo info;
14815
14816     gst_video_info_init (&info);
14817     gst_video_info_set_format (&info, format, entry->width, entry->height);
14818
14819     caps = gst_video_info_to_caps (&info);
14820     *codec_name = gst_pb_utils_get_codec_description (caps);
14821
14822     /* enable clipping for raw video streams */
14823     stream->need_clip = TRUE;
14824     stream->alignment = 32;
14825   }
14826
14827   return caps;
14828 }
14829
14830 static guint
14831 round_up_pow2 (guint n)
14832 {
14833   n = n - 1;
14834   n = n | (n >> 1);
14835   n = n | (n >> 2);
14836   n = n | (n >> 4);
14837   n = n | (n >> 8);
14838   n = n | (n >> 16);
14839   return n + 1;
14840 }
14841
14842 static GstCaps *
14843 qtdemux_audio_caps (GstQTDemux * qtdemux, QtDemuxStream * stream,
14844     QtDemuxStreamStsdEntry * entry, guint32 fourcc, const guint8 * data,
14845     int len, gchar ** codec_name)
14846 {
14847   GstCaps *caps;
14848   const GstStructure *s;
14849   const gchar *name;
14850   gint endian = 0;
14851   GstAudioFormat format = 0;
14852   gint depth;
14853
14854   GST_DEBUG_OBJECT (qtdemux, "resolve fourcc 0x%08x", GUINT32_TO_BE (fourcc));
14855
14856   depth = entry->bytes_per_packet * 8;
14857
14858   switch (fourcc) {
14859     case GST_MAKE_FOURCC ('N', 'O', 'N', 'E'):
14860     case FOURCC_raw_:
14861       /* 8-bit audio is unsigned */
14862       if (depth == 8)
14863         format = GST_AUDIO_FORMAT_U8;
14864       /* otherwise it's signed and big-endian just like 'twos' */
14865     case FOURCC_twos:
14866       endian = G_BIG_ENDIAN;
14867       /* fall-through */
14868     case FOURCC_sowt:
14869     {
14870       gchar *str;
14871
14872       if (!endian)
14873         endian = G_LITTLE_ENDIAN;
14874
14875       if (!format)
14876         format = gst_audio_format_build_integer (TRUE, endian, depth, depth);
14877
14878       str = g_strdup_printf ("Raw %d-bit PCM audio", depth);
14879       _codec (str);
14880       g_free (str);
14881
14882       caps = gst_caps_new_simple ("audio/x-raw",
14883           "format", G_TYPE_STRING, gst_audio_format_to_string (format),
14884           "layout", G_TYPE_STRING, "interleaved", NULL);
14885       stream->alignment = GST_ROUND_UP_8 (depth);
14886       stream->alignment = round_up_pow2 (stream->alignment);
14887       break;
14888     }
14889     case GST_MAKE_FOURCC ('f', 'l', '6', '4'):
14890       _codec ("Raw 64-bit floating-point audio");
14891       caps = gst_caps_new_simple ("audio/x-raw",
14892           "format", G_TYPE_STRING, "F64BE",
14893           "layout", G_TYPE_STRING, "interleaved", NULL);
14894       stream->alignment = 8;
14895       break;
14896     case GST_MAKE_FOURCC ('f', 'l', '3', '2'):
14897       _codec ("Raw 32-bit floating-point audio");
14898       caps = gst_caps_new_simple ("audio/x-raw",
14899           "format", G_TYPE_STRING, "F32BE",
14900           "layout", G_TYPE_STRING, "interleaved", NULL);
14901       stream->alignment = 4;
14902       break;
14903     case FOURCC_in24:
14904       _codec ("Raw 24-bit PCM audio");
14905       /* we assume BIG ENDIAN, an enda box will tell us to change this to little
14906        * endian later */
14907       caps = gst_caps_new_simple ("audio/x-raw",
14908           "format", G_TYPE_STRING, "S24BE",
14909           "layout", G_TYPE_STRING, "interleaved", NULL);
14910       stream->alignment = 4;
14911       break;
14912     case GST_MAKE_FOURCC ('i', 'n', '3', '2'):
14913       _codec ("Raw 32-bit PCM audio");
14914       caps = gst_caps_new_simple ("audio/x-raw",
14915           "format", G_TYPE_STRING, "S32BE",
14916           "layout", G_TYPE_STRING, "interleaved", NULL);
14917       stream->alignment = 4;
14918       break;
14919     case GST_MAKE_FOURCC ('s', '1', '6', 'l'):
14920       _codec ("Raw 16-bit PCM audio");
14921       caps = gst_caps_new_simple ("audio/x-raw",
14922           "format", G_TYPE_STRING, "S16LE",
14923           "layout", G_TYPE_STRING, "interleaved", NULL);
14924       stream->alignment = 2;
14925       break;
14926     case FOURCC_ulaw:
14927       _codec ("Mu-law audio");
14928       caps = gst_caps_new_empty_simple ("audio/x-mulaw");
14929       break;
14930     case FOURCC_alaw:
14931       _codec ("A-law audio");
14932       caps = gst_caps_new_empty_simple ("audio/x-alaw");
14933       break;
14934     case 0x0200736d:
14935     case 0x6d730002:
14936       _codec ("Microsoft ADPCM");
14937       /* Microsoft ADPCM-ACM code 2 */
14938       caps = gst_caps_new_simple ("audio/x-adpcm",
14939           "layout", G_TYPE_STRING, "microsoft", NULL);
14940       break;
14941     case 0x1100736d:
14942     case 0x6d730011:
14943       _codec ("DVI/IMA ADPCM");
14944       caps = gst_caps_new_simple ("audio/x-adpcm",
14945           "layout", G_TYPE_STRING, "dvi", NULL);
14946       break;
14947     case 0x1700736d:
14948     case 0x6d730017:
14949       _codec ("DVI/Intel IMA ADPCM");
14950       /* FIXME DVI/Intel IMA ADPCM/ACM code 17 */
14951       caps = gst_caps_new_simple ("audio/x-adpcm",
14952           "layout", G_TYPE_STRING, "quicktime", NULL);
14953       break;
14954     case 0x5500736d:
14955     case 0x6d730055:
14956       /* MPEG layer 3, CBR only (pre QT4.1) */
14957     case FOURCC__mp3:
14958       _codec ("MPEG-1 layer 3");
14959       /* MPEG layer 3, CBR & VBR (QT4.1 and later) */
14960       caps = gst_caps_new_simple ("audio/mpeg", "layer", G_TYPE_INT, 3,
14961           "mpegversion", G_TYPE_INT, 1, NULL);
14962       break;
14963     case GST_MAKE_FOURCC ('.', 'm', 'p', '2'):
14964       _codec ("MPEG-1 layer 2");
14965       /* MPEG layer 2 */
14966       caps = gst_caps_new_simple ("audio/mpeg", "layer", G_TYPE_INT, 2,
14967           "mpegversion", G_TYPE_INT, 1, NULL);
14968       break;
14969     case 0x20736d:
14970     case GST_MAKE_FOURCC ('e', 'c', '-', '3'):
14971       _codec ("EAC-3 audio");
14972       caps = gst_caps_new_simple ("audio/x-eac3",
14973           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
14974       entry->sampled = TRUE;
14975       break;
14976     case GST_MAKE_FOURCC ('s', 'a', 'c', '3'): // Nero Recode
14977     case FOURCC_ac_3:
14978       _codec ("AC-3 audio");
14979       caps = gst_caps_new_simple ("audio/x-ac3",
14980           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
14981       entry->sampled = TRUE;
14982       break;
14983     case GST_MAKE_FOURCC ('d', 't', 's', 'c'):
14984     case GST_MAKE_FOURCC ('D', 'T', 'S', ' '):
14985       _codec ("DTS audio");
14986       caps = gst_caps_new_simple ("audio/x-dts",
14987           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
14988       entry->sampled = TRUE;
14989       break;
14990     case GST_MAKE_FOURCC ('d', 't', 's', 'h'): // DTS-HD
14991     case GST_MAKE_FOURCC ('d', 't', 's', 'l'): // DTS-HD Lossless
14992       _codec ("DTS-HD audio");
14993       caps = gst_caps_new_simple ("audio/x-dts",
14994           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
14995       entry->sampled = TRUE;
14996       break;
14997     case FOURCC_MAC3:
14998       _codec ("MACE-3");
14999       caps = gst_caps_new_simple ("audio/x-mace",
15000           "maceversion", G_TYPE_INT, 3, NULL);
15001       break;
15002     case FOURCC_MAC6:
15003       _codec ("MACE-6");
15004       caps = gst_caps_new_simple ("audio/x-mace",
15005           "maceversion", G_TYPE_INT, 6, NULL);
15006       break;
15007     case GST_MAKE_FOURCC ('O', 'g', 'g', 'V'):
15008       /* ogg/vorbis */
15009       caps = gst_caps_new_empty_simple ("application/ogg");
15010       break;
15011     case GST_MAKE_FOURCC ('d', 'v', 'c', 'a'):
15012       _codec ("DV audio");
15013       caps = gst_caps_new_empty_simple ("audio/x-dv");
15014       break;
15015     case FOURCC_mp4a:
15016       _codec ("MPEG-4 AAC audio");
15017       caps = gst_caps_new_simple ("audio/mpeg",
15018           "mpegversion", G_TYPE_INT, 4, "framed", G_TYPE_BOOLEAN, TRUE,
15019           "stream-format", G_TYPE_STRING, "raw", NULL);
15020       break;
15021     case GST_MAKE_FOURCC ('Q', 'D', 'M', 'C'):
15022       _codec ("QDesign Music");
15023       caps = gst_caps_new_empty_simple ("audio/x-qdm");
15024       break;
15025     case FOURCC_QDM2:
15026       _codec ("QDesign Music v.2");
15027       /* FIXME: QDesign music version 2 (no constant) */
15028       if (FALSE && data) {
15029         caps = gst_caps_new_simple ("audio/x-qdm2",
15030             "framesize", G_TYPE_INT, QT_UINT32 (data + 52),
15031             "bitrate", G_TYPE_INT, QT_UINT32 (data + 40),
15032             "blocksize", G_TYPE_INT, QT_UINT32 (data + 44), NULL);
15033       } else {
15034         caps = gst_caps_new_empty_simple ("audio/x-qdm2");
15035       }
15036       break;
15037     case FOURCC_agsm:
15038       _codec ("GSM audio");
15039       caps = gst_caps_new_empty_simple ("audio/x-gsm");
15040       break;
15041     case FOURCC_samr:
15042       _codec ("AMR audio");
15043       caps = gst_caps_new_empty_simple ("audio/AMR");
15044       break;
15045     case FOURCC_sawb:
15046       _codec ("AMR-WB audio");
15047       caps = gst_caps_new_empty_simple ("audio/AMR-WB");
15048       break;
15049     case FOURCC_ima4:
15050       _codec ("Quicktime IMA ADPCM");
15051       caps = gst_caps_new_simple ("audio/x-adpcm",
15052           "layout", G_TYPE_STRING, "quicktime", NULL);
15053       break;
15054     case FOURCC_alac:
15055       _codec ("Apple lossless audio");
15056       caps = gst_caps_new_empty_simple ("audio/x-alac");
15057       break;
15058     case FOURCC_fLaC:
15059       _codec ("Free Lossless Audio Codec");
15060       caps = gst_caps_new_simple ("audio/x-flac",
15061           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
15062       break;
15063     case GST_MAKE_FOURCC ('Q', 'c', 'l', 'p'):
15064       _codec ("QualComm PureVoice");
15065       caps = gst_caps_from_string ("audio/qcelp");
15066       break;
15067     case FOURCC_wma_:
15068     case FOURCC_owma:
15069       _codec ("WMA");
15070       caps = gst_caps_new_empty_simple ("audio/x-wma");
15071       break;
15072     case FOURCC_opus:
15073       _codec ("Opus");
15074       caps = gst_caps_new_empty_simple ("audio/x-opus");
15075       break;
15076     case FOURCC_lpcm:
15077     {
15078       guint32 flags = 0;
15079       guint32 depth = 0;
15080       guint32 width = 0;
15081       GstAudioFormat format;
15082       enum
15083       {
15084         FLAG_IS_FLOAT = 0x1,
15085         FLAG_IS_BIG_ENDIAN = 0x2,
15086         FLAG_IS_SIGNED = 0x4,
15087         FLAG_IS_PACKED = 0x8,
15088         FLAG_IS_ALIGNED_HIGH = 0x10,
15089         FLAG_IS_NON_INTERLEAVED = 0x20
15090       };
15091       _codec ("Raw LPCM audio");
15092
15093       if (data && len >= 36) {
15094         depth = QT_UINT32 (data + 24);
15095         flags = QT_UINT32 (data + 28);
15096         width = QT_UINT32 (data + 32) * 8 / entry->n_channels;
15097       }
15098       if ((flags & FLAG_IS_FLOAT) == 0) {
15099         if (depth == 0)
15100           depth = 16;
15101         if (width == 0)
15102           width = 16;
15103         if ((flags & FLAG_IS_ALIGNED_HIGH))
15104           depth = width;
15105
15106         format = gst_audio_format_build_integer ((flags & FLAG_IS_SIGNED) ?
15107             TRUE : FALSE, (flags & FLAG_IS_BIG_ENDIAN) ?
15108             G_BIG_ENDIAN : G_LITTLE_ENDIAN, width, depth);
15109         caps = gst_caps_new_simple ("audio/x-raw",
15110             "format", G_TYPE_STRING,
15111             format !=
15112             GST_AUDIO_FORMAT_UNKNOWN ? gst_audio_format_to_string (format) :
15113             "UNKNOWN", "layout", G_TYPE_STRING,
15114             (flags & FLAG_IS_NON_INTERLEAVED) ? "non-interleaved" :
15115             "interleaved", NULL);
15116         stream->alignment = GST_ROUND_UP_8 (depth);
15117         stream->alignment = round_up_pow2 (stream->alignment);
15118       } else {
15119         if (width == 0)
15120           width = 32;
15121         if (width == 64) {
15122           if (flags & FLAG_IS_BIG_ENDIAN)
15123             format = GST_AUDIO_FORMAT_F64BE;
15124           else
15125             format = GST_AUDIO_FORMAT_F64LE;
15126         } else {
15127           if (flags & FLAG_IS_BIG_ENDIAN)
15128             format = GST_AUDIO_FORMAT_F32BE;
15129           else
15130             format = GST_AUDIO_FORMAT_F32LE;
15131         }
15132         caps = gst_caps_new_simple ("audio/x-raw",
15133             "format", G_TYPE_STRING, gst_audio_format_to_string (format),
15134             "layout", G_TYPE_STRING, (flags & FLAG_IS_NON_INTERLEAVED) ?
15135             "non-interleaved" : "interleaved", NULL);
15136         stream->alignment = width / 8;
15137       }
15138       break;
15139     }
15140     case GST_MAKE_FOURCC ('q', 't', 'v', 'r'):
15141       /* ? */
15142     default:
15143     {
15144       caps = _get_unknown_codec_name ("audio", fourcc);
15145       break;
15146     }
15147   }
15148
15149   if (caps) {
15150     GstCaps *templ_caps =
15151         gst_static_pad_template_get_caps (&gst_qtdemux_audiosrc_template);
15152     GstCaps *intersection = gst_caps_intersect (caps, templ_caps);
15153     gst_caps_unref (caps);
15154     gst_caps_unref (templ_caps);
15155     caps = intersection;
15156   }
15157
15158   /* enable clipping for raw audio streams */
15159   s = gst_caps_get_structure (caps, 0);
15160   name = gst_structure_get_name (s);
15161   if (g_str_has_prefix (name, "audio/x-raw")) {
15162     stream->need_clip = TRUE;
15163     stream->max_buffer_size = 4096 * entry->bytes_per_frame;
15164     GST_DEBUG ("setting max buffer size to %d", stream->max_buffer_size);
15165   }
15166   return caps;
15167 }
15168
15169 static GstCaps *
15170 qtdemux_sub_caps (GstQTDemux * qtdemux, QtDemuxStream * stream,
15171     QtDemuxStreamStsdEntry * entry, guint32 fourcc,
15172     const guint8 * stsd_entry_data, gchar ** codec_name)
15173 {
15174   GstCaps *caps;
15175
15176   GST_DEBUG_OBJECT (qtdemux, "resolve fourcc 0x%08x", GUINT32_TO_BE (fourcc));
15177
15178   switch (fourcc) {
15179     case FOURCC_mp4s:
15180       _codec ("DVD subtitle");
15181       caps = gst_caps_new_empty_simple ("subpicture/x-dvd");
15182       stream->need_process = TRUE;
15183       break;
15184     case FOURCC_text:
15185       _codec ("Quicktime timed text");
15186       goto text;
15187     case FOURCC_tx3g:
15188       _codec ("3GPP timed text");
15189     text:
15190       caps = gst_caps_new_simple ("text/x-raw", "format", G_TYPE_STRING,
15191           "utf8", NULL);
15192       /* actual text piece needs to be extracted */
15193       stream->need_process = TRUE;
15194       break;
15195     case FOURCC_stpp:
15196       _codec ("XML subtitles");
15197       caps = gst_caps_new_empty_simple ("application/ttml+xml");
15198       break;
15199     case FOURCC_c608:
15200       _codec ("CEA 608 Closed Caption");
15201       caps =
15202           gst_caps_new_simple ("closedcaption/x-cea-608", "format",
15203           G_TYPE_STRING, "cc_data", NULL);
15204       stream->need_process = TRUE;
15205       break;
15206     case FOURCC_c708:
15207       _codec ("CEA 708 Closed Caption");
15208       caps =
15209           gst_caps_new_simple ("closedcaption/x-cea-708", "format",
15210           G_TYPE_STRING, "cdp", NULL);
15211       stream->need_process = TRUE;
15212       break;
15213
15214     default:
15215     {
15216       caps = _get_unknown_codec_name ("text", fourcc);
15217       break;
15218     }
15219   }
15220   return caps;
15221 }
15222
15223 static GstCaps *
15224 qtdemux_generic_caps (GstQTDemux * qtdemux, QtDemuxStream * stream,
15225     QtDemuxStreamStsdEntry * entry, guint32 fourcc,
15226     const guint8 * stsd_entry_data, gchar ** codec_name)
15227 {
15228   GstCaps *caps;
15229
15230   switch (fourcc) {
15231     case FOURCC_m1v:
15232       _codec ("MPEG 1 video");
15233       caps = gst_caps_new_simple ("video/mpeg", "mpegversion", G_TYPE_INT, 1,
15234           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
15235       break;
15236     default:
15237       caps = NULL;
15238       break;
15239   }
15240   return caps;
15241 }
15242
15243 static void
15244 gst_qtdemux_append_protection_system_id (GstQTDemux * qtdemux,
15245     const gchar * system_id)
15246 {
15247   gint i;
15248
15249   if (!qtdemux->protection_system_ids)
15250     qtdemux->protection_system_ids =
15251         g_ptr_array_new_with_free_func ((GDestroyNotify) g_free);
15252   /* Check whether we already have an entry for this system ID. */
15253   for (i = 0; i < qtdemux->protection_system_ids->len; ++i) {
15254     const gchar *id = g_ptr_array_index (qtdemux->protection_system_ids, i);
15255     if (g_ascii_strcasecmp (system_id, id) == 0) {
15256       return;
15257     }
15258   }
15259   GST_DEBUG_OBJECT (qtdemux, "Adding cenc protection system ID %s", system_id);
15260   g_ptr_array_add (qtdemux->protection_system_ids, g_ascii_strdown (system_id,
15261           -1));
15262 }