qtdemux: Make function foreach method friendly
[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 (QtDemuxStream * stream,
585     GstQTDemux * qtdemux);
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 (stream, qtdemux);
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 (QtDemuxStream * stream, GstQTDemux * qtdemux)
8011 {
8012 /* FIXME: This can only reliably work if demuxers have a
8013  * separate streaming thread per srcpad. This should be
8014  * done in a demuxer base class, which integrates parts
8015  * of multiqueue
8016  *
8017  * https://bugzilla.gnome.org/show_bug.cgi?id=701856
8018  */
8019 #if 0
8020   GstQuery *query;
8021
8022   query = gst_query_new_allocation (stream->caps, FALSE);
8023
8024   if (!gst_pad_peer_query (stream->pad, query)) {
8025     /* not a problem, just debug a little */
8026     GST_DEBUG_OBJECT (qtdemux, "peer ALLOCATION query failed");
8027   }
8028
8029   if (stream->allocator)
8030     gst_object_unref (stream->allocator);
8031
8032   if (gst_query_get_n_allocation_params (query) > 0) {
8033     /* try the allocator */
8034     gst_query_parse_nth_allocation_param (query, 0, &stream->allocator,
8035         &stream->params);
8036     stream->use_allocator = TRUE;
8037   } else {
8038     stream->allocator = NULL;
8039     gst_allocation_params_init (&stream->params);
8040     stream->use_allocator = FALSE;
8041   }
8042   gst_query_unref (query);
8043 #endif
8044 }
8045
8046 static gboolean
8047 pad_query (const GValue * item, GValue * value, gpointer user_data)
8048 {
8049   GstPad *pad = g_value_get_object (item);
8050   GstQuery *query = user_data;
8051   gboolean res;
8052
8053   res = gst_pad_peer_query (pad, query);
8054
8055   if (res) {
8056     g_value_set_boolean (value, TRUE);
8057     return FALSE;
8058   }
8059
8060   GST_INFO_OBJECT (pad, "pad peer query failed");
8061   return TRUE;
8062 }
8063
8064 static gboolean
8065 gst_qtdemux_run_query (GstElement * element, GstQuery * query,
8066     GstPadDirection direction)
8067 {
8068   GstIterator *it;
8069   GstIteratorFoldFunction func = pad_query;
8070   GValue res = { 0, };
8071
8072   g_value_init (&res, G_TYPE_BOOLEAN);
8073   g_value_set_boolean (&res, FALSE);
8074
8075   /* Ask neighbor */
8076   if (direction == GST_PAD_SRC)
8077     it = gst_element_iterate_src_pads (element);
8078   else
8079     it = gst_element_iterate_sink_pads (element);
8080
8081   while (gst_iterator_fold (it, func, &res, query) == GST_ITERATOR_RESYNC)
8082     gst_iterator_resync (it);
8083
8084   gst_iterator_free (it);
8085
8086   return g_value_get_boolean (&res);
8087 }
8088
8089 static void
8090 gst_qtdemux_request_protection_context (GstQTDemux * qtdemux,
8091     QtDemuxStream * stream)
8092 {
8093   GstQuery *query;
8094   GstContext *ctxt;
8095   GstElement *element = GST_ELEMENT (qtdemux);
8096   GstStructure *st;
8097   gchar **filtered_sys_ids;
8098   GValue event_list = G_VALUE_INIT;
8099   GList *walk;
8100
8101   /* 1. Check if we already have the context. */
8102   if (qtdemux->preferred_protection_system_id != NULL) {
8103     GST_LOG_OBJECT (element,
8104         "already have the protection context, no need to request it again");
8105     return;
8106   }
8107
8108   g_ptr_array_add (qtdemux->protection_system_ids, NULL);
8109   filtered_sys_ids = gst_protection_filter_systems_by_available_decryptors (
8110       (const gchar **) qtdemux->protection_system_ids->pdata);
8111
8112   g_ptr_array_remove_index (qtdemux->protection_system_ids,
8113       qtdemux->protection_system_ids->len - 1);
8114   GST_TRACE_OBJECT (qtdemux, "detected %u protection systems, we have "
8115       "decryptors for %u of them, running context request",
8116       qtdemux->protection_system_ids->len,
8117       filtered_sys_ids ? g_strv_length (filtered_sys_ids) : 0);
8118
8119
8120   if (stream->protection_scheme_event_queue.length) {
8121     GST_TRACE_OBJECT (qtdemux, "using stream event queue, length %u",
8122         stream->protection_scheme_event_queue.length);
8123     walk = stream->protection_scheme_event_queue.tail;
8124   } else {
8125     GST_TRACE_OBJECT (qtdemux, "using demuxer event queue, length %u",
8126         qtdemux->protection_event_queue.length);
8127     walk = qtdemux->protection_event_queue.tail;
8128   }
8129
8130   g_value_init (&event_list, GST_TYPE_LIST);
8131   for (; walk; walk = g_list_previous (walk)) {
8132     GValue *event_value = g_new0 (GValue, 1);
8133     g_value_init (event_value, GST_TYPE_EVENT);
8134     g_value_set_boxed (event_value, walk->data);
8135     gst_value_list_append_and_take_value (&event_list, event_value);
8136   }
8137
8138   /*  2a) Query downstream with GST_QUERY_CONTEXT for the context and
8139    *      check if downstream already has a context of the specific type
8140    *  2b) Query upstream as above.
8141    */
8142   query = gst_query_new_context ("drm-preferred-decryption-system-id");
8143   st = gst_query_writable_structure (query);
8144   gst_structure_set (st, "track-id", G_TYPE_UINT, stream->track_id,
8145       "available-stream-encryption-systems", G_TYPE_STRV, filtered_sys_ids,
8146       NULL);
8147   gst_structure_set_value (st, "stream-encryption-events", &event_list);
8148   if (gst_qtdemux_run_query (element, query, GST_PAD_SRC)) {
8149     gst_query_parse_context (query, &ctxt);
8150     GST_INFO_OBJECT (element, "found context (%p) in downstream query", ctxt);
8151     gst_element_set_context (element, ctxt);
8152   } else if (gst_qtdemux_run_query (element, query, GST_PAD_SINK)) {
8153     gst_query_parse_context (query, &ctxt);
8154     GST_INFO_OBJECT (element, "found context (%p) in upstream query", ctxt);
8155     gst_element_set_context (element, ctxt);
8156   } else {
8157     /* 3) Post a GST_MESSAGE_NEED_CONTEXT message on the bus with
8158      *    the required context type and afterwards check if a
8159      *    usable context was set now as in 1). The message could
8160      *    be handled by the parent bins of the element and the
8161      *    application.
8162      */
8163     GstMessage *msg;
8164
8165     GST_INFO_OBJECT (element, "posting need context message");
8166     msg = gst_message_new_need_context (GST_OBJECT_CAST (element),
8167         "drm-preferred-decryption-system-id");
8168     st = (GstStructure *) gst_message_get_structure (msg);
8169     gst_structure_set (st, "track-id", G_TYPE_UINT, stream->track_id,
8170         "available-stream-encryption-systems", G_TYPE_STRV, filtered_sys_ids,
8171         NULL);
8172
8173     gst_structure_set_value (st, "stream-encryption-events", &event_list);
8174     gst_element_post_message (element, msg);
8175   }
8176
8177   g_strfreev (filtered_sys_ids);
8178   g_value_unset (&event_list);
8179   gst_query_unref (query);
8180 }
8181
8182 static gboolean
8183 gst_qtdemux_configure_protected_caps (GstQTDemux * qtdemux,
8184     QtDemuxStream * stream)
8185 {
8186   GstStructure *s;
8187   const gchar *selected_system = NULL;
8188
8189   g_return_val_if_fail (qtdemux != NULL, FALSE);
8190   g_return_val_if_fail (stream != NULL, FALSE);
8191   g_return_val_if_fail (gst_caps_get_size (CUR_STREAM (stream)->caps) == 1,
8192       FALSE);
8193
8194   if (stream->protection_scheme_type != FOURCC_cenc) {
8195     GST_ERROR_OBJECT (qtdemux,
8196         "unsupported protection scheme: %" GST_FOURCC_FORMAT,
8197         GST_FOURCC_ARGS (stream->protection_scheme_type));
8198     return FALSE;
8199   }
8200   if (qtdemux->protection_system_ids == NULL) {
8201     GST_ERROR_OBJECT (qtdemux, "stream is protected using cenc, but no "
8202         "cenc protection system information has been found");
8203     return FALSE;
8204   }
8205
8206   gst_qtdemux_request_protection_context (qtdemux, stream);
8207   if (qtdemux->preferred_protection_system_id != NULL) {
8208     const gchar *preferred_system_array[] =
8209         { qtdemux->preferred_protection_system_id, NULL };
8210
8211     selected_system = gst_protection_select_system (preferred_system_array);
8212
8213     if (selected_system) {
8214       GST_TRACE_OBJECT (qtdemux, "selected preferred system %s",
8215           qtdemux->preferred_protection_system_id);
8216     } else {
8217       GST_WARNING_OBJECT (qtdemux, "could not select preferred system %s "
8218           "because there is no available decryptor",
8219           qtdemux->preferred_protection_system_id);
8220     }
8221   }
8222
8223   if (!selected_system) {
8224     g_ptr_array_add (qtdemux->protection_system_ids, NULL);
8225     selected_system = gst_protection_select_system ((const gchar **)
8226         qtdemux->protection_system_ids->pdata);
8227     g_ptr_array_remove_index (qtdemux->protection_system_ids,
8228         qtdemux->protection_system_ids->len - 1);
8229   }
8230
8231   if (!selected_system) {
8232     GST_ERROR_OBJECT (qtdemux, "stream is protected, but no "
8233         "suitable decryptor element has been found");
8234     return FALSE;
8235   }
8236
8237   GST_DEBUG_OBJECT (qtdemux, "selected protection system is %s",
8238       selected_system);
8239
8240   s = gst_caps_get_structure (CUR_STREAM (stream)->caps, 0);
8241   if (!gst_structure_has_name (s, "application/x-cenc")) {
8242     gst_structure_set (s,
8243         "original-media-type", G_TYPE_STRING, gst_structure_get_name (s),
8244         GST_PROTECTION_SYSTEM_ID_CAPS_FIELD, G_TYPE_STRING, selected_system,
8245         NULL);
8246     gst_structure_set_name (s, "application/x-cenc");
8247   }
8248   return TRUE;
8249 }
8250
8251 static gboolean
8252 gst_qtdemux_configure_stream (GstQTDemux * qtdemux, QtDemuxStream * stream)
8253 {
8254   if (stream->subtype == FOURCC_vide) {
8255     /* fps is calculated base on the duration of the average framerate since
8256      * qt does not have a fixed framerate. */
8257     gboolean fps_available = TRUE;
8258     guint32 first_duration = 0;
8259
8260     if (stream->n_samples > 0)
8261       first_duration = stream->samples[0].duration;
8262
8263     if ((stream->n_samples == 1 && first_duration == 0)
8264         || (qtdemux->fragmented && stream->n_samples_moof == 1)) {
8265       /* still frame */
8266       CUR_STREAM (stream)->fps_n = 0;
8267       CUR_STREAM (stream)->fps_d = 1;
8268     } else {
8269       if (stream->duration == 0 || stream->n_samples < 2) {
8270         CUR_STREAM (stream)->fps_n = stream->timescale;
8271         CUR_STREAM (stream)->fps_d = 1;
8272         fps_available = FALSE;
8273       } else {
8274         GstClockTime avg_duration;
8275         guint64 duration;
8276         guint32 n_samples;
8277
8278         /* duration and n_samples can be updated for fragmented format
8279          * so, framerate of fragmented format is calculated using data in a moof */
8280         if (qtdemux->fragmented && stream->n_samples_moof > 0
8281             && stream->duration_moof > 0) {
8282           n_samples = stream->n_samples_moof;
8283           duration = stream->duration_moof;
8284         } else {
8285           n_samples = stream->n_samples;
8286           duration = stream->duration;
8287         }
8288
8289         /* Calculate a framerate, ignoring the first sample which is sometimes truncated */
8290         /* stream->duration is guint64, timescale, n_samples are guint32 */
8291         avg_duration =
8292             gst_util_uint64_scale_round (duration -
8293             first_duration, GST_SECOND,
8294             (guint64) (stream->timescale) * (n_samples - 1));
8295
8296         GST_LOG_OBJECT (qtdemux,
8297             "Calculating avg sample duration based on stream (or moof) duration %"
8298             G_GUINT64_FORMAT
8299             " minus first sample %u, leaving %d samples gives %"
8300             GST_TIME_FORMAT, duration, first_duration,
8301             n_samples - 1, GST_TIME_ARGS (avg_duration));
8302
8303         gst_video_guess_framerate (avg_duration, &CUR_STREAM (stream)->fps_n,
8304             &CUR_STREAM (stream)->fps_d);
8305
8306         GST_DEBUG_OBJECT (qtdemux,
8307             "Calculating framerate, timescale %u gave fps_n %d fps_d %d",
8308             stream->timescale, CUR_STREAM (stream)->fps_n,
8309             CUR_STREAM (stream)->fps_d);
8310       }
8311     }
8312
8313     if (CUR_STREAM (stream)->caps) {
8314       CUR_STREAM (stream)->caps =
8315           gst_caps_make_writable (CUR_STREAM (stream)->caps);
8316
8317       if (CUR_STREAM (stream)->width && CUR_STREAM (stream)->height)
8318         gst_caps_set_simple (CUR_STREAM (stream)->caps,
8319             "width", G_TYPE_INT, CUR_STREAM (stream)->width,
8320             "height", G_TYPE_INT, CUR_STREAM (stream)->height, NULL);
8321
8322       /* set framerate if calculated framerate is reliable */
8323       if (fps_available) {
8324         gst_caps_set_simple (CUR_STREAM (stream)->caps,
8325             "framerate", GST_TYPE_FRACTION, CUR_STREAM (stream)->fps_n,
8326             CUR_STREAM (stream)->fps_d, NULL);
8327       }
8328
8329       /* calculate pixel-aspect-ratio using display width and height */
8330       GST_DEBUG_OBJECT (qtdemux,
8331           "video size %dx%d, target display size %dx%d",
8332           CUR_STREAM (stream)->width, CUR_STREAM (stream)->height,
8333           stream->display_width, stream->display_height);
8334       /* qt file might have pasp atom */
8335       if (CUR_STREAM (stream)->par_w > 0 && CUR_STREAM (stream)->par_h > 0) {
8336         GST_DEBUG_OBJECT (qtdemux, "par %d:%d", CUR_STREAM (stream)->par_w,
8337             CUR_STREAM (stream)->par_h);
8338         gst_caps_set_simple (CUR_STREAM (stream)->caps, "pixel-aspect-ratio",
8339             GST_TYPE_FRACTION, CUR_STREAM (stream)->par_w,
8340             CUR_STREAM (stream)->par_h, NULL);
8341       } else if (stream->display_width > 0 && stream->display_height > 0
8342           && CUR_STREAM (stream)->width > 0
8343           && CUR_STREAM (stream)->height > 0) {
8344         gint n, d;
8345
8346         /* calculate the pixel aspect ratio using the display and pixel w/h */
8347         n = stream->display_width * CUR_STREAM (stream)->height;
8348         d = stream->display_height * CUR_STREAM (stream)->width;
8349         if (n == d)
8350           n = d = 1;
8351         GST_DEBUG_OBJECT (qtdemux, "setting PAR to %d/%d", n, d);
8352         CUR_STREAM (stream)->par_w = n;
8353         CUR_STREAM (stream)->par_h = d;
8354         gst_caps_set_simple (CUR_STREAM (stream)->caps, "pixel-aspect-ratio",
8355             GST_TYPE_FRACTION, CUR_STREAM (stream)->par_w,
8356             CUR_STREAM (stream)->par_h, NULL);
8357       }
8358
8359       if (CUR_STREAM (stream)->interlace_mode > 0) {
8360         if (CUR_STREAM (stream)->interlace_mode == 1) {
8361           gst_caps_set_simple (CUR_STREAM (stream)->caps, "interlace-mode",
8362               G_TYPE_STRING, "progressive", NULL);
8363         } else if (CUR_STREAM (stream)->interlace_mode == 2) {
8364           gst_caps_set_simple (CUR_STREAM (stream)->caps, "interlace-mode",
8365               G_TYPE_STRING, "interleaved", NULL);
8366           if (CUR_STREAM (stream)->field_order == 9) {
8367             gst_caps_set_simple (CUR_STREAM (stream)->caps, "field-order",
8368                 G_TYPE_STRING, "top-field-first", NULL);
8369           } else if (CUR_STREAM (stream)->field_order == 14) {
8370             gst_caps_set_simple (CUR_STREAM (stream)->caps, "field-order",
8371                 G_TYPE_STRING, "bottom-field-first", NULL);
8372           }
8373         }
8374       }
8375
8376       /* Create incomplete colorimetry here if needed */
8377       if (CUR_STREAM (stream)->colorimetry.range ||
8378           CUR_STREAM (stream)->colorimetry.matrix ||
8379           CUR_STREAM (stream)->colorimetry.transfer
8380           || CUR_STREAM (stream)->colorimetry.primaries) {
8381         gchar *colorimetry =
8382             gst_video_colorimetry_to_string (&CUR_STREAM (stream)->colorimetry);
8383         gst_caps_set_simple (CUR_STREAM (stream)->caps, "colorimetry",
8384             G_TYPE_STRING, colorimetry, NULL);
8385         g_free (colorimetry);
8386       }
8387
8388       if (stream->multiview_mode != GST_VIDEO_MULTIVIEW_MODE_NONE) {
8389         guint par_w = 1, par_h = 1;
8390
8391         if (CUR_STREAM (stream)->par_w > 0 && CUR_STREAM (stream)->par_h > 0) {
8392           par_w = CUR_STREAM (stream)->par_w;
8393           par_h = CUR_STREAM (stream)->par_h;
8394         }
8395
8396         if (gst_video_multiview_guess_half_aspect (stream->multiview_mode,
8397                 CUR_STREAM (stream)->width, CUR_STREAM (stream)->height, par_w,
8398                 par_h)) {
8399           stream->multiview_flags |= GST_VIDEO_MULTIVIEW_FLAGS_HALF_ASPECT;
8400         }
8401
8402         gst_caps_set_simple (CUR_STREAM (stream)->caps,
8403             "multiview-mode", G_TYPE_STRING,
8404             gst_video_multiview_mode_to_caps_string (stream->multiview_mode),
8405             "multiview-flags", GST_TYPE_VIDEO_MULTIVIEW_FLAGSET,
8406             stream->multiview_flags, GST_FLAG_SET_MASK_EXACT, NULL);
8407       }
8408     }
8409   }
8410
8411   else if (stream->subtype == FOURCC_soun) {
8412     if (CUR_STREAM (stream)->caps) {
8413       CUR_STREAM (stream)->caps =
8414           gst_caps_make_writable (CUR_STREAM (stream)->caps);
8415       if (CUR_STREAM (stream)->rate > 0)
8416         gst_caps_set_simple (CUR_STREAM (stream)->caps,
8417             "rate", G_TYPE_INT, (int) CUR_STREAM (stream)->rate, NULL);
8418       if (CUR_STREAM (stream)->n_channels > 0)
8419         gst_caps_set_simple (CUR_STREAM (stream)->caps,
8420             "channels", G_TYPE_INT, CUR_STREAM (stream)->n_channels, NULL);
8421       if (CUR_STREAM (stream)->n_channels > 2) {
8422         /* FIXME: Need to parse the 'chan' atom to get channel layouts
8423          * correctly; this is just the minimum we can do - assume
8424          * we don't actually have any channel positions. */
8425         gst_caps_set_simple (CUR_STREAM (stream)->caps,
8426             "channel-mask", GST_TYPE_BITMASK, G_GUINT64_CONSTANT (0), NULL);
8427       }
8428     }
8429   }
8430
8431   if (stream->pad) {
8432     GstCaps *prev_caps = NULL;
8433
8434     GST_PAD_ELEMENT_PRIVATE (stream->pad) = stream;
8435     gst_pad_set_event_function (stream->pad, gst_qtdemux_handle_src_event);
8436     gst_pad_set_query_function (stream->pad, gst_qtdemux_handle_src_query);
8437     gst_pad_set_active (stream->pad, TRUE);
8438
8439     gst_pad_use_fixed_caps (stream->pad);
8440
8441     if (stream->protected) {
8442       if (!gst_qtdemux_configure_protected_caps (qtdemux, stream)) {
8443         GST_ERROR_OBJECT (qtdemux,
8444             "Failed to configure protected stream caps.");
8445         return FALSE;
8446       }
8447     }
8448
8449     GST_DEBUG_OBJECT (qtdemux, "setting caps %" GST_PTR_FORMAT,
8450         CUR_STREAM (stream)->caps);
8451     if (stream->new_stream) {
8452       GstEvent *event;
8453       GstStreamFlags stream_flags = GST_STREAM_FLAG_NONE;
8454
8455       event =
8456           gst_pad_get_sticky_event (qtdemux->sinkpad, GST_EVENT_STREAM_START,
8457           0);
8458       if (event) {
8459         gst_event_parse_stream_flags (event, &stream_flags);
8460         if (gst_event_parse_group_id (event, &qtdemux->group_id))
8461           qtdemux->have_group_id = TRUE;
8462         else
8463           qtdemux->have_group_id = FALSE;
8464         gst_event_unref (event);
8465       } else if (!qtdemux->have_group_id) {
8466         qtdemux->have_group_id = TRUE;
8467         qtdemux->group_id = gst_util_group_id_next ();
8468       }
8469
8470       stream->new_stream = FALSE;
8471       event = gst_event_new_stream_start (stream->stream_id);
8472       if (qtdemux->have_group_id)
8473         gst_event_set_group_id (event, qtdemux->group_id);
8474       if (stream->disabled)
8475         stream_flags |= GST_STREAM_FLAG_UNSELECT;
8476       if (CUR_STREAM (stream)->sparse) {
8477         stream_flags |= GST_STREAM_FLAG_SPARSE;
8478       } else {
8479         stream_flags &= ~GST_STREAM_FLAG_SPARSE;
8480       }
8481       gst_event_set_stream_flags (event, stream_flags);
8482       gst_pad_push_event (stream->pad, event);
8483     }
8484
8485     prev_caps = gst_pad_get_current_caps (stream->pad);
8486
8487     if (CUR_STREAM (stream)->caps) {
8488       if (!prev_caps
8489           || !gst_caps_is_equal_fixed (prev_caps, CUR_STREAM (stream)->caps)) {
8490         GST_DEBUG_OBJECT (qtdemux, "setting caps %" GST_PTR_FORMAT,
8491             CUR_STREAM (stream)->caps);
8492         gst_pad_set_caps (stream->pad, CUR_STREAM (stream)->caps);
8493       } else {
8494         GST_DEBUG_OBJECT (qtdemux, "ignore duplicated caps");
8495       }
8496     } else {
8497       GST_WARNING_OBJECT (qtdemux, "stream without caps");
8498     }
8499
8500     if (prev_caps)
8501       gst_caps_unref (prev_caps);
8502     stream->new_caps = FALSE;
8503   }
8504   return TRUE;
8505 }
8506
8507 static void
8508 gst_qtdemux_stream_check_and_change_stsd_index (GstQTDemux * demux,
8509     QtDemuxStream * stream)
8510 {
8511   if (stream->cur_stsd_entry_index == stream->stsd_sample_description_id)
8512     return;
8513
8514   GST_DEBUG_OBJECT (stream->pad, "Changing stsd index from '%u' to '%u'",
8515       stream->cur_stsd_entry_index, stream->stsd_sample_description_id);
8516   if (G_UNLIKELY (stream->stsd_sample_description_id >=
8517           stream->stsd_entries_length)) {
8518     GST_ELEMENT_ERROR (demux, STREAM, DEMUX,
8519         (_("This file is invalid and cannot be played.")),
8520         ("New sample description id is out of bounds (%d >= %d)",
8521             stream->stsd_sample_description_id, stream->stsd_entries_length));
8522   } else {
8523     stream->cur_stsd_entry_index = stream->stsd_sample_description_id;
8524     stream->new_caps = TRUE;
8525   }
8526 }
8527
8528 static gboolean
8529 gst_qtdemux_add_stream (GstQTDemux * qtdemux,
8530     QtDemuxStream * stream, GstTagList * list)
8531 {
8532   gboolean ret = TRUE;
8533   /* consistent default for push based mode */
8534   gst_segment_init (&stream->segment, GST_FORMAT_TIME);
8535
8536   if (stream->subtype == FOURCC_vide) {
8537     gchar *name = g_strdup_printf ("video_%u", qtdemux->n_video_streams);
8538
8539     stream->pad =
8540         gst_pad_new_from_static_template (&gst_qtdemux_videosrc_template, name);
8541     g_free (name);
8542
8543     if (!gst_qtdemux_configure_stream (qtdemux, stream)) {
8544       gst_object_unref (stream->pad);
8545       stream->pad = NULL;
8546       ret = FALSE;
8547       goto done;
8548     }
8549
8550     qtdemux->n_video_streams++;
8551   } else if (stream->subtype == FOURCC_soun) {
8552     gchar *name = g_strdup_printf ("audio_%u", qtdemux->n_audio_streams);
8553
8554     stream->pad =
8555         gst_pad_new_from_static_template (&gst_qtdemux_audiosrc_template, name);
8556     g_free (name);
8557     if (!gst_qtdemux_configure_stream (qtdemux, stream)) {
8558       gst_object_unref (stream->pad);
8559       stream->pad = NULL;
8560       ret = FALSE;
8561       goto done;
8562     }
8563     qtdemux->n_audio_streams++;
8564   } else if (stream->subtype == FOURCC_strm) {
8565     GST_DEBUG_OBJECT (qtdemux, "stream type, not creating pad");
8566   } else if (stream->subtype == FOURCC_subp || stream->subtype == FOURCC_text
8567       || stream->subtype == FOURCC_sbtl || stream->subtype == FOURCC_subt
8568       || stream->subtype == FOURCC_clcp) {
8569     gchar *name = g_strdup_printf ("subtitle_%u", qtdemux->n_sub_streams);
8570
8571     stream->pad =
8572         gst_pad_new_from_static_template (&gst_qtdemux_subsrc_template, name);
8573     g_free (name);
8574     if (!gst_qtdemux_configure_stream (qtdemux, stream)) {
8575       gst_object_unref (stream->pad);
8576       stream->pad = NULL;
8577       ret = FALSE;
8578       goto done;
8579     }
8580     qtdemux->n_sub_streams++;
8581   } else if (CUR_STREAM (stream)->caps) {
8582     gchar *name = g_strdup_printf ("video_%u", qtdemux->n_video_streams);
8583
8584     stream->pad =
8585         gst_pad_new_from_static_template (&gst_qtdemux_videosrc_template, name);
8586     g_free (name);
8587     if (!gst_qtdemux_configure_stream (qtdemux, stream)) {
8588       gst_object_unref (stream->pad);
8589       stream->pad = NULL;
8590       ret = FALSE;
8591       goto done;
8592     }
8593     qtdemux->n_video_streams++;
8594   } else {
8595     GST_DEBUG_OBJECT (qtdemux, "unknown stream type");
8596     goto done;
8597   }
8598
8599   if (stream->pad) {
8600     GList *l;
8601
8602     GST_DEBUG_OBJECT (qtdemux, "adding pad %s %p to qtdemux %p",
8603         GST_OBJECT_NAME (stream->pad), stream->pad, qtdemux);
8604     gst_element_add_pad (GST_ELEMENT_CAST (qtdemux), stream->pad);
8605     gst_flow_combiner_add_pad (qtdemux->flowcombiner, stream->pad);
8606
8607     if (stream->stream_tags)
8608       gst_tag_list_unref (stream->stream_tags);
8609     stream->stream_tags = list;
8610     list = NULL;
8611     /* global tags go on each pad anyway */
8612     stream->send_global_tags = TRUE;
8613     /* send upstream GST_EVENT_PROTECTION events that were received before
8614        this source pad was created */
8615     for (l = qtdemux->protection_event_queue.head; l != NULL; l = l->next)
8616       gst_pad_push_event (stream->pad, gst_event_ref (l->data));
8617   }
8618 done:
8619   if (list)
8620     gst_tag_list_unref (list);
8621   return ret;
8622 }
8623
8624 /* find next atom with @fourcc starting at @offset */
8625 static GstFlowReturn
8626 qtdemux_find_atom (GstQTDemux * qtdemux, guint64 * offset,
8627     guint64 * length, guint32 fourcc)
8628 {
8629   GstFlowReturn ret;
8630   guint32 lfourcc;
8631   GstBuffer *buf;
8632
8633   GST_LOG_OBJECT (qtdemux, "finding fourcc %" GST_FOURCC_FORMAT " at offset %"
8634       G_GUINT64_FORMAT, GST_FOURCC_ARGS (fourcc), *offset);
8635
8636   while (TRUE) {
8637     GstMapInfo map;
8638
8639     buf = NULL;
8640     ret = gst_pad_pull_range (qtdemux->sinkpad, *offset, 16, &buf);
8641     if (G_UNLIKELY (ret != GST_FLOW_OK))
8642       goto locate_failed;
8643     if (G_UNLIKELY (gst_buffer_get_size (buf) != 16)) {
8644       /* likely EOF */
8645       ret = GST_FLOW_EOS;
8646       gst_buffer_unref (buf);
8647       goto locate_failed;
8648     }
8649     gst_buffer_map (buf, &map, GST_MAP_READ);
8650     extract_initial_length_and_fourcc (map.data, 16, length, &lfourcc);
8651     gst_buffer_unmap (buf, &map);
8652     gst_buffer_unref (buf);
8653
8654     if (G_UNLIKELY (*length == 0)) {
8655       GST_DEBUG_OBJECT (qtdemux, "invalid length 0");
8656       ret = GST_FLOW_ERROR;
8657       goto locate_failed;
8658     }
8659
8660     if (lfourcc == fourcc) {
8661       GST_DEBUG_OBJECT (qtdemux, "found fourcc at offset %" G_GUINT64_FORMAT,
8662           *offset);
8663       break;
8664     } else {
8665       GST_LOG_OBJECT (qtdemux,
8666           "skipping atom '%" GST_FOURCC_FORMAT "' at %" G_GUINT64_FORMAT,
8667           GST_FOURCC_ARGS (fourcc), *offset);
8668       *offset += *length;
8669     }
8670   }
8671
8672   return GST_FLOW_OK;
8673
8674 locate_failed:
8675   {
8676     /* might simply have had last one */
8677     GST_DEBUG_OBJECT (qtdemux, "fourcc not found");
8678     return ret;
8679   }
8680 }
8681
8682 /* should only do something in pull mode */
8683 /* call with OBJECT lock */
8684 static GstFlowReturn
8685 qtdemux_add_fragmented_samples (GstQTDemux * qtdemux)
8686 {
8687   guint64 length, offset;
8688   GstBuffer *buf = NULL;
8689   GstFlowReturn ret = GST_FLOW_OK;
8690   GstFlowReturn res = GST_FLOW_OK;
8691   GstMapInfo map;
8692
8693   offset = qtdemux->moof_offset;
8694   GST_DEBUG_OBJECT (qtdemux, "next moof at offset %" G_GUINT64_FORMAT, offset);
8695
8696   if (!offset) {
8697     GST_DEBUG_OBJECT (qtdemux, "no next moof");
8698     return GST_FLOW_EOS;
8699   }
8700
8701   /* best not do pull etc with lock held */
8702   GST_OBJECT_UNLOCK (qtdemux);
8703
8704   ret = qtdemux_find_atom (qtdemux, &offset, &length, FOURCC_moof);
8705   if (ret != GST_FLOW_OK)
8706     goto flow_failed;
8707
8708   ret = gst_qtdemux_pull_atom (qtdemux, offset, length, &buf);
8709   if (G_UNLIKELY (ret != GST_FLOW_OK))
8710     goto flow_failed;
8711   gst_buffer_map (buf, &map, GST_MAP_READ);
8712   if (!qtdemux_parse_moof (qtdemux, map.data, map.size, offset, NULL)) {
8713     gst_buffer_unmap (buf, &map);
8714     gst_buffer_unref (buf);
8715     buf = NULL;
8716     goto parse_failed;
8717   }
8718
8719   gst_buffer_unmap (buf, &map);
8720   gst_buffer_unref (buf);
8721   buf = NULL;
8722
8723   offset += length;
8724   /* look for next moof */
8725   ret = qtdemux_find_atom (qtdemux, &offset, &length, FOURCC_moof);
8726   if (G_UNLIKELY (ret != GST_FLOW_OK))
8727     goto flow_failed;
8728
8729 exit:
8730   GST_OBJECT_LOCK (qtdemux);
8731
8732   qtdemux->moof_offset = offset;
8733
8734   return res;
8735
8736 parse_failed:
8737   {
8738     GST_DEBUG_OBJECT (qtdemux, "failed to parse moof");
8739     offset = 0;
8740     res = GST_FLOW_ERROR;
8741     goto exit;
8742   }
8743 flow_failed:
8744   {
8745     /* maybe upstream temporarily flushing */
8746     if (ret != GST_FLOW_FLUSHING) {
8747       GST_DEBUG_OBJECT (qtdemux, "no next moof");
8748       offset = 0;
8749     } else {
8750       GST_DEBUG_OBJECT (qtdemux, "upstream WRONG_STATE");
8751       /* resume at current position next time */
8752     }
8753     res = ret;
8754     goto exit;
8755   }
8756 }
8757
8758 /* initialise bytereaders for stbl sub-atoms */
8759 static gboolean
8760 qtdemux_stbl_init (GstQTDemux * qtdemux, QtDemuxStream * stream, GNode * stbl)
8761 {
8762   stream->stbl_index = -1;      /* no samples have yet been parsed */
8763   stream->sample_index = -1;
8764
8765   /* time-to-sample atom */
8766   if (!qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stts, &stream->stts))
8767     goto corrupt_file;
8768
8769   /* copy atom data into a new buffer for later use */
8770   stream->stts.data = g_memdup (stream->stts.data, stream->stts.size);
8771
8772   /* skip version + flags */
8773   if (!gst_byte_reader_skip (&stream->stts, 1 + 3) ||
8774       !gst_byte_reader_get_uint32_be (&stream->stts, &stream->n_sample_times))
8775     goto corrupt_file;
8776   GST_LOG_OBJECT (qtdemux, "%u timestamp blocks", stream->n_sample_times);
8777
8778   /* make sure there's enough data */
8779   if (!qt_atom_parser_has_chunks (&stream->stts, stream->n_sample_times, 8)) {
8780     stream->n_sample_times = gst_byte_reader_get_remaining (&stream->stts) / 8;
8781     GST_LOG_OBJECT (qtdemux, "overriding to %u timestamp blocks",
8782         stream->n_sample_times);
8783     if (!stream->n_sample_times)
8784       goto corrupt_file;
8785   }
8786
8787   /* sync sample atom */
8788   stream->stps_present = FALSE;
8789   if ((stream->stss_present =
8790           ! !qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stss,
8791               &stream->stss) ? TRUE : FALSE) == TRUE) {
8792     /* copy atom data into a new buffer for later use */
8793     stream->stss.data = g_memdup (stream->stss.data, stream->stss.size);
8794
8795     /* skip version + flags */
8796     if (!gst_byte_reader_skip (&stream->stss, 1 + 3) ||
8797         !gst_byte_reader_get_uint32_be (&stream->stss, &stream->n_sample_syncs))
8798       goto corrupt_file;
8799
8800     if (stream->n_sample_syncs) {
8801       /* make sure there's enough data */
8802       if (!qt_atom_parser_has_chunks (&stream->stss, stream->n_sample_syncs, 4))
8803         goto corrupt_file;
8804     }
8805
8806     /* partial sync sample atom */
8807     if ((stream->stps_present =
8808             ! !qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stps,
8809                 &stream->stps) ? TRUE : FALSE) == TRUE) {
8810       /* copy atom data into a new buffer for later use */
8811       stream->stps.data = g_memdup (stream->stps.data, stream->stps.size);
8812
8813       /* skip version + flags */
8814       if (!gst_byte_reader_skip (&stream->stps, 1 + 3) ||
8815           !gst_byte_reader_get_uint32_be (&stream->stps,
8816               &stream->n_sample_partial_syncs))
8817         goto corrupt_file;
8818
8819       /* if there are no entries, the stss table contains the real
8820        * sync samples */
8821       if (stream->n_sample_partial_syncs) {
8822         /* make sure there's enough data */
8823         if (!qt_atom_parser_has_chunks (&stream->stps,
8824                 stream->n_sample_partial_syncs, 4))
8825           goto corrupt_file;
8826       }
8827     }
8828   }
8829
8830   /* sample size */
8831   if (!qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stsz, &stream->stsz))
8832     goto no_samples;
8833
8834   /* copy atom data into a new buffer for later use */
8835   stream->stsz.data = g_memdup (stream->stsz.data, stream->stsz.size);
8836
8837   /* skip version + flags */
8838   if (!gst_byte_reader_skip (&stream->stsz, 1 + 3) ||
8839       !gst_byte_reader_get_uint32_be (&stream->stsz, &stream->sample_size))
8840     goto corrupt_file;
8841
8842   if (!gst_byte_reader_get_uint32_be (&stream->stsz, &stream->n_samples))
8843     goto corrupt_file;
8844
8845   if (!stream->n_samples)
8846     goto no_samples;
8847
8848   /* sample-to-chunk atom */
8849   if (!qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stsc, &stream->stsc))
8850     goto corrupt_file;
8851
8852   /* copy atom data into a new buffer for later use */
8853   stream->stsc.data = g_memdup (stream->stsc.data, stream->stsc.size);
8854
8855   /* skip version + flags */
8856   if (!gst_byte_reader_skip (&stream->stsc, 1 + 3) ||
8857       !gst_byte_reader_get_uint32_be (&stream->stsc,
8858           &stream->n_samples_per_chunk))
8859     goto corrupt_file;
8860
8861   GST_DEBUG_OBJECT (qtdemux, "n_samples_per_chunk %u",
8862       stream->n_samples_per_chunk);
8863
8864   /* make sure there's enough data */
8865   if (!qt_atom_parser_has_chunks (&stream->stsc, stream->n_samples_per_chunk,
8866           12))
8867     goto corrupt_file;
8868
8869
8870   /* chunk offset */
8871   if (qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stco, &stream->stco))
8872     stream->co_size = sizeof (guint32);
8873   else if (qtdemux_tree_get_child_by_type_full (stbl, FOURCC_co64,
8874           &stream->stco))
8875     stream->co_size = sizeof (guint64);
8876   else
8877     goto corrupt_file;
8878
8879   /* copy atom data into a new buffer for later use */
8880   stream->stco.data = g_memdup (stream->stco.data, stream->stco.size);
8881
8882   /* skip version + flags */
8883   if (!gst_byte_reader_skip (&stream->stco, 1 + 3))
8884     goto corrupt_file;
8885
8886   /* chunks_are_samples == TRUE means treat chunks as samples */
8887   stream->chunks_are_samples = stream->sample_size
8888       && !CUR_STREAM (stream)->sampled;
8889   if (stream->chunks_are_samples) {
8890     /* treat chunks as samples */
8891     if (!gst_byte_reader_get_uint32_be (&stream->stco, &stream->n_samples))
8892       goto corrupt_file;
8893   } else {
8894     /* skip number of entries */
8895     if (!gst_byte_reader_skip (&stream->stco, 4))
8896       goto corrupt_file;
8897
8898     /* make sure there are enough data in the stsz atom */
8899     if (!stream->sample_size) {
8900       /* different sizes for each sample */
8901       if (!qt_atom_parser_has_chunks (&stream->stsz, stream->n_samples, 4))
8902         goto corrupt_file;
8903     }
8904   }
8905
8906   GST_DEBUG_OBJECT (qtdemux, "allocating n_samples %u * %u (%.2f MB)",
8907       stream->n_samples, (guint) sizeof (QtDemuxSample),
8908       stream->n_samples * sizeof (QtDemuxSample) / (1024.0 * 1024.0));
8909
8910   if (stream->n_samples >=
8911       QTDEMUX_MAX_SAMPLE_INDEX_SIZE / sizeof (QtDemuxSample)) {
8912     GST_WARNING_OBJECT (qtdemux, "not allocating index of %d samples, would "
8913         "be larger than %uMB (broken file?)", stream->n_samples,
8914         QTDEMUX_MAX_SAMPLE_INDEX_SIZE >> 20);
8915     return FALSE;
8916   }
8917
8918   g_assert (stream->samples == NULL);
8919   stream->samples = g_try_new0 (QtDemuxSample, stream->n_samples);
8920   if (!stream->samples) {
8921     GST_WARNING_OBJECT (qtdemux, "failed to allocate %d samples",
8922         stream->n_samples);
8923     return FALSE;
8924   }
8925
8926   /* composition time-to-sample */
8927   if ((stream->ctts_present =
8928           ! !qtdemux_tree_get_child_by_type_full (stbl, FOURCC_ctts,
8929               &stream->ctts) ? TRUE : FALSE) == TRUE) {
8930     GstByteReader cslg = GST_BYTE_READER_INIT (NULL, 0);
8931
8932     /* copy atom data into a new buffer for later use */
8933     stream->ctts.data = g_memdup (stream->ctts.data, stream->ctts.size);
8934
8935     /* skip version + flags */
8936     if (!gst_byte_reader_skip (&stream->ctts, 1 + 3)
8937         || !gst_byte_reader_get_uint32_be (&stream->ctts,
8938             &stream->n_composition_times))
8939       goto corrupt_file;
8940
8941     /* make sure there's enough data */
8942     if (!qt_atom_parser_has_chunks (&stream->ctts, stream->n_composition_times,
8943             4 + 4))
8944       goto corrupt_file;
8945
8946     /* This is optional, if missing we iterate the ctts */
8947     if (qtdemux_tree_get_child_by_type_full (stbl, FOURCC_cslg, &cslg)) {
8948       if (!gst_byte_reader_skip (&cslg, 1 + 3)
8949           || !gst_byte_reader_get_uint32_be (&cslg, &stream->cslg_shift)) {
8950         g_free ((gpointer) cslg.data);
8951         goto corrupt_file;
8952       }
8953     } else {
8954       gint32 cslg_least = 0;
8955       guint num_entries, pos;
8956       gint i;
8957
8958       pos = gst_byte_reader_get_pos (&stream->ctts);
8959       num_entries = stream->n_composition_times;
8960
8961       stream->cslg_shift = 0;
8962
8963       for (i = 0; i < num_entries; i++) {
8964         gint32 offset;
8965
8966         gst_byte_reader_skip_unchecked (&stream->ctts, 4);
8967         offset = gst_byte_reader_get_int32_be_unchecked (&stream->ctts);
8968
8969         if (offset < cslg_least)
8970           cslg_least = offset;
8971       }
8972
8973       if (cslg_least < 0)
8974         stream->cslg_shift = ABS (cslg_least);
8975       else
8976         stream->cslg_shift = 0;
8977
8978       /* reset the reader so we can generate sample table */
8979       gst_byte_reader_set_pos (&stream->ctts, pos);
8980     }
8981   } else {
8982     /* Ensure the cslg_shift value is consistent so we can use it
8983      * unconditionnally to produce TS and Segment */
8984     stream->cslg_shift = 0;
8985   }
8986
8987   return TRUE;
8988
8989 corrupt_file:
8990   {
8991     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
8992         (_("This file is corrupt and cannot be played.")), (NULL));
8993     return FALSE;
8994   }
8995 no_samples:
8996   {
8997     gst_qtdemux_stbl_free (stream);
8998     if (!qtdemux->fragmented) {
8999       /* not quite good */
9000       GST_WARNING_OBJECT (qtdemux, "stream has no samples");
9001       return FALSE;
9002     } else {
9003       /* may pick up samples elsewhere */
9004       return TRUE;
9005     }
9006   }
9007 }
9008
9009 /* collect samples from the next sample to be parsed up to sample @n for @stream
9010  * by reading the info from @stbl
9011  *
9012  * This code can be executed from both the streaming thread and the seeking
9013  * thread so it takes the object lock to protect itself
9014  */
9015 static gboolean
9016 qtdemux_parse_samples (GstQTDemux * qtdemux, QtDemuxStream * stream, guint32 n)
9017 {
9018   gint i, j, k;
9019   QtDemuxSample *samples, *first, *cur, *last;
9020   guint32 n_samples_per_chunk;
9021   guint32 n_samples;
9022
9023   GST_LOG_OBJECT (qtdemux, "parsing samples for stream fourcc %"
9024       GST_FOURCC_FORMAT ", pad %s",
9025       GST_FOURCC_ARGS (CUR_STREAM (stream)->fourcc),
9026       stream->pad ? GST_PAD_NAME (stream->pad) : "(NULL)");
9027
9028   n_samples = stream->n_samples;
9029
9030   if (n >= n_samples)
9031     goto out_of_samples;
9032
9033   GST_OBJECT_LOCK (qtdemux);
9034   if (n <= stream->stbl_index)
9035     goto already_parsed;
9036
9037   GST_DEBUG_OBJECT (qtdemux, "parsing up to sample %u", n);
9038
9039   if (!stream->stsz.data) {
9040     /* so we already parsed and passed all the moov samples;
9041      * onto fragmented ones */
9042     g_assert (qtdemux->fragmented);
9043     goto done;
9044   }
9045
9046   /* pointer to the sample table */
9047   samples = stream->samples;
9048
9049   /* starts from -1, moves to the next sample index to parse */
9050   stream->stbl_index++;
9051
9052   /* keep track of the first and last sample to fill */
9053   first = &samples[stream->stbl_index];
9054   last = &samples[n];
9055
9056   if (!stream->chunks_are_samples) {
9057     /* set the sample sizes */
9058     if (stream->sample_size == 0) {
9059       /* different sizes for each sample */
9060       for (cur = first; cur <= last; cur++) {
9061         cur->size = gst_byte_reader_get_uint32_be_unchecked (&stream->stsz);
9062         GST_LOG_OBJECT (qtdemux, "sample %d has size %u",
9063             (guint) (cur - samples), cur->size);
9064       }
9065     } else {
9066       /* samples have the same size */
9067       GST_LOG_OBJECT (qtdemux, "all samples have size %u", stream->sample_size);
9068       for (cur = first; cur <= last; cur++)
9069         cur->size = stream->sample_size;
9070     }
9071   }
9072
9073   n_samples_per_chunk = stream->n_samples_per_chunk;
9074   cur = first;
9075
9076   for (i = stream->stsc_index; i < n_samples_per_chunk; i++) {
9077     guint32 last_chunk;
9078
9079     if (stream->stsc_chunk_index >= stream->last_chunk
9080         || stream->stsc_chunk_index < stream->first_chunk) {
9081       stream->first_chunk =
9082           gst_byte_reader_get_uint32_be_unchecked (&stream->stsc);
9083       stream->samples_per_chunk =
9084           gst_byte_reader_get_uint32_be_unchecked (&stream->stsc);
9085       /* starts from 1 */
9086       stream->stsd_sample_description_id =
9087           gst_byte_reader_get_uint32_be_unchecked (&stream->stsc) - 1;
9088
9089       /* chunk numbers are counted from 1 it seems */
9090       if (G_UNLIKELY (stream->first_chunk == 0))
9091         goto corrupt_file;
9092
9093       --stream->first_chunk;
9094
9095       /* the last chunk of each entry is calculated by taking the first chunk
9096        * of the next entry; except if there is no next, where we fake it with
9097        * INT_MAX */
9098       if (G_UNLIKELY (i == (stream->n_samples_per_chunk - 1))) {
9099         stream->last_chunk = G_MAXUINT32;
9100       } else {
9101         stream->last_chunk =
9102             gst_byte_reader_peek_uint32_be_unchecked (&stream->stsc);
9103         if (G_UNLIKELY (stream->last_chunk == 0))
9104           goto corrupt_file;
9105
9106         --stream->last_chunk;
9107       }
9108
9109       GST_LOG_OBJECT (qtdemux,
9110           "entry %d has first_chunk %d, last_chunk %d, samples_per_chunk %d"
9111           "sample desc ID: %d", i, stream->first_chunk, stream->last_chunk,
9112           stream->samples_per_chunk, stream->stsd_sample_description_id);
9113
9114       if (G_UNLIKELY (stream->last_chunk < stream->first_chunk))
9115         goto corrupt_file;
9116
9117       if (stream->last_chunk != G_MAXUINT32) {
9118         if (!qt_atom_parser_peek_sub (&stream->stco,
9119                 stream->first_chunk * stream->co_size,
9120                 (stream->last_chunk - stream->first_chunk) * stream->co_size,
9121                 &stream->co_chunk))
9122           goto corrupt_file;
9123
9124       } else {
9125         stream->co_chunk = stream->stco;
9126         if (!gst_byte_reader_skip (&stream->co_chunk,
9127                 stream->first_chunk * stream->co_size))
9128           goto corrupt_file;
9129       }
9130
9131       stream->stsc_chunk_index = stream->first_chunk;
9132     }
9133
9134     last_chunk = stream->last_chunk;
9135
9136     if (stream->chunks_are_samples) {
9137       cur = &samples[stream->stsc_chunk_index];
9138
9139       for (j = stream->stsc_chunk_index; j < last_chunk; j++) {
9140         if (j > n) {
9141           /* save state */
9142           stream->stsc_chunk_index = j;
9143           goto done;
9144         }
9145
9146         cur->offset =
9147             qt_atom_parser_get_offset_unchecked (&stream->co_chunk,
9148             stream->co_size);
9149
9150         GST_LOG_OBJECT (qtdemux, "Created entry %d with offset "
9151             "%" G_GUINT64_FORMAT, j, cur->offset);
9152
9153         if (CUR_STREAM (stream)->samples_per_frame > 0 &&
9154             CUR_STREAM (stream)->bytes_per_frame > 0) {
9155           cur->size =
9156               (stream->samples_per_chunk * CUR_STREAM (stream)->n_channels) /
9157               CUR_STREAM (stream)->samples_per_frame *
9158               CUR_STREAM (stream)->bytes_per_frame;
9159         } else {
9160           cur->size = stream->samples_per_chunk;
9161         }
9162
9163         GST_DEBUG_OBJECT (qtdemux,
9164             "keyframe sample %d: timestamp %" GST_TIME_FORMAT ", size %u",
9165             j, GST_TIME_ARGS (QTSTREAMTIME_TO_GSTTIME (stream,
9166                     stream->stco_sample_index)), cur->size);
9167
9168         cur->timestamp = stream->stco_sample_index;
9169         cur->duration = stream->samples_per_chunk;
9170         cur->keyframe = TRUE;
9171         cur++;
9172
9173         stream->stco_sample_index += stream->samples_per_chunk;
9174       }
9175       stream->stsc_chunk_index = j;
9176     } else {
9177       for (j = stream->stsc_chunk_index; j < last_chunk; j++) {
9178         guint32 samples_per_chunk;
9179         guint64 chunk_offset;
9180
9181         if (!stream->stsc_sample_index
9182             && !qt_atom_parser_get_offset (&stream->co_chunk, stream->co_size,
9183                 &stream->chunk_offset))
9184           goto corrupt_file;
9185
9186         samples_per_chunk = stream->samples_per_chunk;
9187         chunk_offset = stream->chunk_offset;
9188
9189         for (k = stream->stsc_sample_index; k < samples_per_chunk; k++) {
9190           GST_LOG_OBJECT (qtdemux, "creating entry %d with offset %"
9191               G_GUINT64_FORMAT " and size %d",
9192               (guint) (cur - samples), chunk_offset, cur->size);
9193
9194           cur->offset = chunk_offset;
9195           chunk_offset += cur->size;
9196           cur++;
9197
9198           if (G_UNLIKELY (cur > last)) {
9199             /* save state */
9200             stream->stsc_sample_index = k + 1;
9201             stream->chunk_offset = chunk_offset;
9202             stream->stsc_chunk_index = j;
9203             goto done2;
9204           }
9205         }
9206         stream->stsc_sample_index = 0;
9207       }
9208       stream->stsc_chunk_index = j;
9209     }
9210     stream->stsc_index++;
9211   }
9212
9213   if (stream->chunks_are_samples)
9214     goto ctts;
9215 done2:
9216   {
9217     guint32 n_sample_times;
9218
9219     n_sample_times = stream->n_sample_times;
9220     cur = first;
9221
9222     for (i = stream->stts_index; i < n_sample_times; i++) {
9223       guint32 stts_samples;
9224       gint32 stts_duration;
9225       gint64 stts_time;
9226
9227       if (stream->stts_sample_index >= stream->stts_samples
9228           || !stream->stts_sample_index) {
9229
9230         stream->stts_samples =
9231             gst_byte_reader_get_uint32_be_unchecked (&stream->stts);
9232         stream->stts_duration =
9233             gst_byte_reader_get_uint32_be_unchecked (&stream->stts);
9234
9235         GST_LOG_OBJECT (qtdemux, "block %d, %u timestamps, duration %u",
9236             i, stream->stts_samples, stream->stts_duration);
9237
9238         stream->stts_sample_index = 0;
9239       }
9240
9241       stts_samples = stream->stts_samples;
9242       stts_duration = stream->stts_duration;
9243       stts_time = stream->stts_time;
9244
9245       for (j = stream->stts_sample_index; j < stts_samples; j++) {
9246         GST_DEBUG_OBJECT (qtdemux,
9247             "sample %d: index %d, timestamp %" GST_TIME_FORMAT,
9248             (guint) (cur - samples), j,
9249             GST_TIME_ARGS (QTSTREAMTIME_TO_GSTTIME (stream, stts_time)));
9250
9251         cur->timestamp = stts_time;
9252         cur->duration = stts_duration;
9253
9254         /* avoid 32-bit wrap-around,
9255          * but still mind possible 'negative' duration */
9256         stts_time += (gint64) stts_duration;
9257         cur++;
9258
9259         if (G_UNLIKELY (cur > last)) {
9260           /* save values */
9261           stream->stts_time = stts_time;
9262           stream->stts_sample_index = j + 1;
9263           if (stream->stts_sample_index >= stream->stts_samples)
9264             stream->stts_index++;
9265           goto done3;
9266         }
9267       }
9268       stream->stts_sample_index = 0;
9269       stream->stts_time = stts_time;
9270       stream->stts_index++;
9271     }
9272     /* fill up empty timestamps with the last timestamp, this can happen when
9273      * the last samples do not decode and so we don't have timestamps for them.
9274      * We however look at the last timestamp to estimate the track length so we
9275      * need something in here. */
9276     for (; cur < last; cur++) {
9277       GST_DEBUG_OBJECT (qtdemux,
9278           "fill sample %d: timestamp %" GST_TIME_FORMAT,
9279           (guint) (cur - samples),
9280           GST_TIME_ARGS (QTSTREAMTIME_TO_GSTTIME (stream, stream->stts_time)));
9281       cur->timestamp = stream->stts_time;
9282       cur->duration = -1;
9283     }
9284   }
9285 done3:
9286   {
9287     /* sample sync, can be NULL */
9288     if (stream->stss_present == TRUE) {
9289       guint32 n_sample_syncs;
9290
9291       n_sample_syncs = stream->n_sample_syncs;
9292
9293       if (!n_sample_syncs) {
9294         GST_DEBUG_OBJECT (qtdemux, "all samples are keyframes");
9295         stream->all_keyframe = TRUE;
9296       } else {
9297         for (i = stream->stss_index; i < n_sample_syncs; i++) {
9298           /* note that the first sample is index 1, not 0 */
9299           guint32 index;
9300
9301           index = gst_byte_reader_get_uint32_be_unchecked (&stream->stss);
9302
9303           if (G_LIKELY (index > 0 && index <= n_samples)) {
9304             index -= 1;
9305             samples[index].keyframe = TRUE;
9306             GST_DEBUG_OBJECT (qtdemux, "samples at %u is keyframe", index);
9307             /* and exit if we have enough samples */
9308             if (G_UNLIKELY (index >= n)) {
9309               i++;
9310               break;
9311             }
9312           }
9313         }
9314         /* save state */
9315         stream->stss_index = i;
9316       }
9317
9318       /* stps marks partial sync frames like open GOP I-Frames */
9319       if (stream->stps_present == TRUE) {
9320         guint32 n_sample_partial_syncs;
9321
9322         n_sample_partial_syncs = stream->n_sample_partial_syncs;
9323
9324         /* if there are no entries, the stss table contains the real
9325          * sync samples */
9326         if (n_sample_partial_syncs) {
9327           for (i = stream->stps_index; i < n_sample_partial_syncs; i++) {
9328             /* note that the first sample is index 1, not 0 */
9329             guint32 index;
9330
9331             index = gst_byte_reader_get_uint32_be_unchecked (&stream->stps);
9332
9333             if (G_LIKELY (index > 0 && index <= n_samples)) {
9334               index -= 1;
9335               samples[index].keyframe = TRUE;
9336               GST_DEBUG_OBJECT (qtdemux, "samples at %u is keyframe", index);
9337               /* and exit if we have enough samples */
9338               if (G_UNLIKELY (index >= n)) {
9339                 i++;
9340                 break;
9341               }
9342             }
9343           }
9344           /* save state */
9345           stream->stps_index = i;
9346         }
9347       }
9348     } else {
9349       /* no stss, all samples are keyframes */
9350       stream->all_keyframe = TRUE;
9351       GST_DEBUG_OBJECT (qtdemux, "setting all keyframes");
9352     }
9353   }
9354
9355 ctts:
9356   /* composition time to sample */
9357   if (stream->ctts_present == TRUE) {
9358     guint32 n_composition_times;
9359     guint32 ctts_count;
9360     gint32 ctts_soffset;
9361
9362     /* Fill in the pts_offsets */
9363     cur = first;
9364     n_composition_times = stream->n_composition_times;
9365
9366     for (i = stream->ctts_index; i < n_composition_times; i++) {
9367       if (stream->ctts_sample_index >= stream->ctts_count
9368           || !stream->ctts_sample_index) {
9369         stream->ctts_count =
9370             gst_byte_reader_get_uint32_be_unchecked (&stream->ctts);
9371         stream->ctts_soffset =
9372             gst_byte_reader_get_int32_be_unchecked (&stream->ctts);
9373         stream->ctts_sample_index = 0;
9374       }
9375
9376       ctts_count = stream->ctts_count;
9377       ctts_soffset = stream->ctts_soffset;
9378
9379       for (j = stream->ctts_sample_index; j < ctts_count; j++) {
9380         cur->pts_offset = ctts_soffset;
9381         cur++;
9382
9383         if (G_UNLIKELY (cur > last)) {
9384           /* save state */
9385           stream->ctts_sample_index = j + 1;
9386           goto done;
9387         }
9388       }
9389       stream->ctts_sample_index = 0;
9390       stream->ctts_index++;
9391     }
9392   }
9393 done:
9394   stream->stbl_index = n;
9395   /* if index has been completely parsed, free data that is no-longer needed */
9396   if (n + 1 == stream->n_samples) {
9397     gst_qtdemux_stbl_free (stream);
9398     GST_DEBUG_OBJECT (qtdemux, "parsed all available samples;");
9399     if (qtdemux->pullbased) {
9400       GST_DEBUG_OBJECT (qtdemux, "checking for more samples");
9401       while (n + 1 == stream->n_samples)
9402         if (qtdemux_add_fragmented_samples (qtdemux) != GST_FLOW_OK)
9403           break;
9404     }
9405   }
9406   GST_OBJECT_UNLOCK (qtdemux);
9407
9408   return TRUE;
9409
9410   /* SUCCESS */
9411 already_parsed:
9412   {
9413     GST_LOG_OBJECT (qtdemux,
9414         "Tried to parse up to sample %u but this sample has already been parsed",
9415         n);
9416     /* if fragmented, there may be more */
9417     if (qtdemux->fragmented && n == stream->stbl_index)
9418       goto done;
9419     GST_OBJECT_UNLOCK (qtdemux);
9420     return TRUE;
9421   }
9422   /* ERRORS */
9423 out_of_samples:
9424   {
9425     GST_LOG_OBJECT (qtdemux,
9426         "Tried to parse up to sample %u but there are only %u samples", n + 1,
9427         stream->n_samples);
9428     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
9429         (_("This file is corrupt and cannot be played.")), (NULL));
9430     return FALSE;
9431   }
9432 corrupt_file:
9433   {
9434     GST_OBJECT_UNLOCK (qtdemux);
9435     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
9436         (_("This file is corrupt and cannot be played.")), (NULL));
9437     return FALSE;
9438   }
9439 }
9440
9441 /* collect all segment info for @stream.
9442  */
9443 static gboolean
9444 qtdemux_parse_segments (GstQTDemux * qtdemux, QtDemuxStream * stream,
9445     GNode * trak)
9446 {
9447   GNode *edts;
9448   /* accept edts if they contain gaps at start and there is only
9449    * one media segment */
9450   gboolean allow_pushbased_edts = TRUE;
9451   gint media_segments_count = 0;
9452
9453   /* parse and prepare segment info from the edit list */
9454   GST_DEBUG_OBJECT (qtdemux, "looking for edit list container");
9455   stream->n_segments = 0;
9456   stream->segments = NULL;
9457   if ((edts = qtdemux_tree_get_child_by_type (trak, FOURCC_edts))) {
9458     GNode *elst;
9459     gint n_segments;
9460     gint segment_number, entry_size;
9461     guint64 time;
9462     GstClockTime stime;
9463     const guint8 *buffer;
9464     guint8 version;
9465     guint32 size;
9466
9467     GST_DEBUG_OBJECT (qtdemux, "looking for edit list");
9468     if (!(elst = qtdemux_tree_get_child_by_type (edts, FOURCC_elst)))
9469       goto done;
9470
9471     buffer = elst->data;
9472
9473     size = QT_UINT32 (buffer);
9474     /* version, flags, n_segments */
9475     if (size < 16) {
9476       GST_WARNING_OBJECT (qtdemux, "Invalid edit list");
9477       goto done;
9478     }
9479     version = QT_UINT8 (buffer + 8);
9480     entry_size = (version == 1) ? 20 : 12;
9481
9482     n_segments = QT_UINT32 (buffer + 12);
9483
9484     if (n_segments > 100000 || size < 16 + n_segments * entry_size) {
9485       GST_WARNING_OBJECT (qtdemux, "Invalid edit list");
9486       goto done;
9487     }
9488
9489     /* we might allocate a bit too much, at least allocate 1 segment */
9490     stream->segments = g_new (QtDemuxSegment, MAX (n_segments, 1));
9491
9492     /* segments always start from 0 */
9493     time = 0;
9494     stime = 0;
9495     buffer += 16;
9496     for (segment_number = 0; segment_number < n_segments; segment_number++) {
9497       guint64 duration;
9498       guint64 media_time;
9499       gboolean empty_edit = FALSE;
9500       QtDemuxSegment *segment;
9501       guint32 rate_int;
9502       GstClockTime media_start = GST_CLOCK_TIME_NONE;
9503
9504       if (version == 1) {
9505         media_time = QT_UINT64 (buffer + 8);
9506         duration = QT_UINT64 (buffer);
9507         if (media_time == G_MAXUINT64)
9508           empty_edit = TRUE;
9509       } else {
9510         media_time = QT_UINT32 (buffer + 4);
9511         duration = QT_UINT32 (buffer);
9512         if (media_time == G_MAXUINT32)
9513           empty_edit = TRUE;
9514       }
9515
9516       if (!empty_edit)
9517         media_start = QTSTREAMTIME_TO_GSTTIME (stream, media_time);
9518
9519       segment = &stream->segments[segment_number];
9520
9521       /* time and duration expressed in global timescale */
9522       segment->time = stime;
9523       if (duration != 0 || empty_edit) {
9524         /* edge case: empty edits with duration=zero are treated here.
9525          * (files should not have these anyway). */
9526
9527         /* add non scaled values so we don't cause roundoff errors */
9528         time += duration;
9529         stime = QTTIME_TO_GSTTIME (qtdemux, time);
9530         segment->duration = stime - segment->time;
9531       } else {
9532         /* zero duration does not imply media_start == media_stop
9533          * but, only specify media_start. The edit ends with the track. */
9534         stime = segment->duration = GST_CLOCK_TIME_NONE;
9535         /* Don't allow more edits after this one. */
9536         n_segments = segment_number + 1;
9537       }
9538       segment->stop_time = stime;
9539
9540       segment->trak_media_start = media_time;
9541       /* media_time expressed in stream timescale */
9542       if (!empty_edit) {
9543         segment->media_start = media_start;
9544         segment->media_stop = GST_CLOCK_TIME_IS_VALID (segment->duration)
9545             ? segment->media_start + segment->duration : GST_CLOCK_TIME_NONE;
9546         media_segments_count++;
9547       } else {
9548         segment->media_start = GST_CLOCK_TIME_NONE;
9549         segment->media_stop = GST_CLOCK_TIME_NONE;
9550       }
9551       rate_int = QT_UINT32 (buffer + ((version == 1) ? 16 : 8));
9552
9553       if (rate_int <= 1) {
9554         /* 0 is not allowed, some programs write 1 instead of the floating point
9555          * value */
9556         GST_WARNING_OBJECT (qtdemux, "found suspicious rate %" G_GUINT32_FORMAT,
9557             rate_int);
9558         segment->rate = 1;
9559       } else {
9560         segment->rate = rate_int / 65536.0;
9561       }
9562
9563       GST_DEBUG_OBJECT (qtdemux, "created segment %d time %" GST_TIME_FORMAT
9564           ", duration %" GST_TIME_FORMAT ", media_start %" GST_TIME_FORMAT
9565           " (%" G_GUINT64_FORMAT ") , media_stop %" GST_TIME_FORMAT
9566           " stop_time %" GST_TIME_FORMAT " rate %g, (%d) timescale %u",
9567           segment_number, GST_TIME_ARGS (segment->time),
9568           GST_TIME_ARGS (segment->duration),
9569           GST_TIME_ARGS (segment->media_start), media_time,
9570           GST_TIME_ARGS (segment->media_stop),
9571           GST_TIME_ARGS (segment->stop_time), segment->rate, rate_int,
9572           stream->timescale);
9573       if (segment->stop_time > qtdemux->segment.stop &&
9574           !qtdemux->upstream_format_is_time) {
9575         GST_WARNING_OBJECT (qtdemux, "Segment %d "
9576             " extends to %" GST_TIME_FORMAT
9577             " past the end of the declared movie duration %" GST_TIME_FORMAT
9578             " movie segment will be extended", segment_number,
9579             GST_TIME_ARGS (segment->stop_time),
9580             GST_TIME_ARGS (qtdemux->segment.stop));
9581         qtdemux->segment.stop = qtdemux->segment.duration = segment->stop_time;
9582       }
9583
9584       buffer += entry_size;
9585     }
9586     GST_DEBUG_OBJECT (qtdemux, "found %d segments", n_segments);
9587     stream->n_segments = n_segments;
9588     if (media_segments_count != 1)
9589       allow_pushbased_edts = FALSE;
9590   }
9591 done:
9592
9593   /* push based does not handle segments, so act accordingly here,
9594    * and warn if applicable */
9595   if (!qtdemux->pullbased && !allow_pushbased_edts) {
9596     GST_WARNING_OBJECT (qtdemux, "streaming; discarding edit list segments");
9597     /* remove and use default one below, we stream like it anyway */
9598     g_free (stream->segments);
9599     stream->segments = NULL;
9600     stream->n_segments = 0;
9601   }
9602
9603   /* no segments, create one to play the complete trak */
9604   if (stream->n_segments == 0) {
9605     GstClockTime stream_duration =
9606         QTSTREAMTIME_TO_GSTTIME (stream, stream->duration);
9607
9608     if (stream->segments == NULL)
9609       stream->segments = g_new (QtDemuxSegment, 1);
9610
9611     /* represent unknown our way */
9612     if (stream_duration == 0)
9613       stream_duration = GST_CLOCK_TIME_NONE;
9614
9615     stream->segments[0].time = 0;
9616     stream->segments[0].stop_time = stream_duration;
9617     stream->segments[0].duration = stream_duration;
9618     stream->segments[0].media_start = 0;
9619     stream->segments[0].media_stop = stream_duration;
9620     stream->segments[0].rate = 1.0;
9621     stream->segments[0].trak_media_start = 0;
9622
9623     GST_DEBUG_OBJECT (qtdemux, "created dummy segment %" GST_TIME_FORMAT,
9624         GST_TIME_ARGS (stream_duration));
9625     stream->n_segments = 1;
9626     stream->dummy_segment = TRUE;
9627   }
9628   GST_DEBUG_OBJECT (qtdemux, "using %d segments", stream->n_segments);
9629
9630   return TRUE;
9631 }
9632
9633 /*
9634  * Parses the stsd atom of a svq3 trak looking for
9635  * the SMI and gama atoms.
9636  */
9637 static void
9638 qtdemux_parse_svq3_stsd_data (GstQTDemux * qtdemux,
9639     const guint8 * stsd_entry_data, const guint8 ** gamma, GstBuffer ** seqh)
9640 {
9641   const guint8 *_gamma = NULL;
9642   GstBuffer *_seqh = NULL;
9643   const guint8 *stsd_data = stsd_entry_data;
9644   guint32 length = QT_UINT32 (stsd_data);
9645   guint16 version;
9646
9647   if (length < 32) {
9648     GST_WARNING_OBJECT (qtdemux, "stsd too short");
9649     goto end;
9650   }
9651
9652   stsd_data += 16;
9653   length -= 16;
9654   version = QT_UINT16 (stsd_data);
9655   if (version == 3) {
9656     if (length >= 70) {
9657       length -= 70;
9658       stsd_data += 70;
9659       while (length > 8) {
9660         guint32 fourcc, size;
9661         const guint8 *data;
9662         size = QT_UINT32 (stsd_data);
9663         fourcc = QT_FOURCC (stsd_data + 4);
9664         data = stsd_data + 8;
9665
9666         if (size == 0) {
9667           GST_WARNING_OBJECT (qtdemux, "Atom of size 0 found, aborting "
9668               "svq3 atom parsing");
9669           goto end;
9670         }
9671
9672         switch (fourcc) {
9673           case FOURCC_gama:{
9674             if (size == 12) {
9675               _gamma = data;
9676             } else {
9677               GST_WARNING_OBJECT (qtdemux, "Unexpected size %" G_GUINT32_FORMAT
9678                   " for gama atom, expected 12", size);
9679             }
9680             break;
9681           }
9682           case FOURCC_SMI_:{
9683             if (size > 16 && QT_FOURCC (data) == FOURCC_SEQH) {
9684               guint32 seqh_size;
9685               if (_seqh != NULL) {
9686                 GST_WARNING_OBJECT (qtdemux, "Unexpected second SEQH SMI atom "
9687                     " found, ignoring");
9688               } else {
9689                 seqh_size = QT_UINT32 (data + 4);
9690                 if (seqh_size > 0) {
9691                   _seqh = gst_buffer_new_and_alloc (seqh_size);
9692                   gst_buffer_fill (_seqh, 0, data + 8, seqh_size);
9693                 }
9694               }
9695             }
9696             break;
9697           }
9698           default:{
9699             GST_WARNING_OBJECT (qtdemux, "Unhandled atom %" GST_FOURCC_FORMAT
9700                 " in SVQ3 entry in stsd atom", GST_FOURCC_ARGS (fourcc));
9701           }
9702         }
9703
9704         if (size <= length) {
9705           length -= size;
9706           stsd_data += size;
9707         }
9708       }
9709     } else {
9710       GST_WARNING_OBJECT (qtdemux, "SVQ3 entry too short in stsd atom");
9711     }
9712   } else {
9713     GST_WARNING_OBJECT (qtdemux, "Unexpected version for SVQ3 entry %"
9714         G_GUINT16_FORMAT, version);
9715     goto end;
9716   }
9717
9718 end:
9719   if (gamma) {
9720     *gamma = _gamma;
9721   }
9722   if (seqh) {
9723     *seqh = _seqh;
9724   } else if (_seqh) {
9725     gst_buffer_unref (_seqh);
9726   }
9727 }
9728
9729 static gchar *
9730 qtdemux_get_rtsp_uri_from_hndl (GstQTDemux * qtdemux, GNode * minf)
9731 {
9732   GNode *dinf;
9733   GstByteReader dref;
9734   gchar *uri = NULL;
9735
9736   /*
9737    * Get 'dinf', to get its child 'dref', that might contain a 'hndl'
9738    * atom that might contain a 'data' atom with the rtsp uri.
9739    * This case was reported in bug #597497, some info about
9740    * the hndl atom can be found in TN1195
9741    */
9742   dinf = qtdemux_tree_get_child_by_type (minf, FOURCC_dinf);
9743   GST_DEBUG_OBJECT (qtdemux, "Trying to obtain rtsp URI for stream trak");
9744
9745   if (dinf) {
9746     guint32 dref_num_entries = 0;
9747     if (qtdemux_tree_get_child_by_type_full (dinf, FOURCC_dref, &dref) &&
9748         gst_byte_reader_skip (&dref, 4) &&
9749         gst_byte_reader_get_uint32_be (&dref, &dref_num_entries)) {
9750       gint i;
9751
9752       /* search dref entries for hndl atom */
9753       for (i = 0; i < dref_num_entries; i++) {
9754         guint32 size = 0, type;
9755         guint8 string_len = 0;
9756         if (gst_byte_reader_get_uint32_be (&dref, &size) &&
9757             qt_atom_parser_get_fourcc (&dref, &type)) {
9758           if (type == FOURCC_hndl) {
9759             GST_DEBUG_OBJECT (qtdemux, "Found hndl atom");
9760
9761             /* skip data reference handle bytes and the
9762              * following pascal string and some extra 4
9763              * bytes I have no idea what are */
9764             if (!gst_byte_reader_skip (&dref, 4) ||
9765                 !gst_byte_reader_get_uint8 (&dref, &string_len) ||
9766                 !gst_byte_reader_skip (&dref, string_len + 4)) {
9767               GST_WARNING_OBJECT (qtdemux, "Failed to parse hndl atom");
9768               break;
9769             }
9770
9771             /* iterate over the atoms to find the data atom */
9772             while (gst_byte_reader_get_remaining (&dref) >= 8) {
9773               guint32 atom_size;
9774               guint32 atom_type;
9775
9776               if (gst_byte_reader_get_uint32_be (&dref, &atom_size) &&
9777                   qt_atom_parser_get_fourcc (&dref, &atom_type)) {
9778                 if (atom_type == FOURCC_data) {
9779                   const guint8 *uri_aux = NULL;
9780
9781                   /* found the data atom that might contain the rtsp uri */
9782                   GST_DEBUG_OBJECT (qtdemux, "Found data atom inside "
9783                       "hndl atom, interpreting it as an URI");
9784                   if (gst_byte_reader_peek_data (&dref, atom_size - 8,
9785                           &uri_aux)) {
9786                     if (g_strstr_len ((gchar *) uri_aux, 7, "rtsp://") != NULL)
9787                       uri = g_strndup ((gchar *) uri_aux, atom_size - 8);
9788                     else
9789                       GST_WARNING_OBJECT (qtdemux, "Data atom in hndl atom "
9790                           "didn't contain a rtsp address");
9791                   } else {
9792                     GST_WARNING_OBJECT (qtdemux, "Failed to get the data "
9793                         "atom contents");
9794                   }
9795                   break;
9796                 }
9797                 /* skipping to the next entry */
9798                 if (!gst_byte_reader_skip (&dref, atom_size - 8))
9799                   break;
9800               } else {
9801                 GST_WARNING_OBJECT (qtdemux, "Failed to parse hndl child "
9802                     "atom header");
9803                 break;
9804               }
9805             }
9806             break;
9807           }
9808           /* skip to the next entry */
9809           if (!gst_byte_reader_skip (&dref, size - 8))
9810             break;
9811         } else {
9812           GST_WARNING_OBJECT (qtdemux, "Error parsing dref atom");
9813         }
9814       }
9815       GST_DEBUG_OBJECT (qtdemux, "Finished parsing dref atom");
9816     }
9817   }
9818   return uri;
9819 }
9820
9821 #define AMR_NB_ALL_MODES        0x81ff
9822 #define AMR_WB_ALL_MODES        0x83ff
9823 static guint
9824 qtdemux_parse_amr_bitrate (GstBuffer * buf, gboolean wb)
9825 {
9826   /* The 'damr' atom is of the form:
9827    *
9828    * | vendor | decoder_ver | mode_set | mode_change_period | frames/sample |
9829    *    32 b       8 b          16 b           8 b                 8 b
9830    *
9831    * The highest set bit of the first 7 (AMR-NB) or 8 (AMR-WB) bits of mode_set
9832    * represents the highest mode used in the stream (and thus the maximum
9833    * bitrate), with a couple of special cases as seen below.
9834    */
9835
9836   /* Map of frame type ID -> bitrate */
9837   static const guint nb_bitrates[] = {
9838     4750, 5150, 5900, 6700, 7400, 7950, 10200, 12200
9839   };
9840   static const guint wb_bitrates[] = {
9841     6600, 8850, 12650, 14250, 15850, 18250, 19850, 23050, 23850
9842   };
9843   GstMapInfo map;
9844   gsize max_mode;
9845   guint16 mode_set;
9846
9847   gst_buffer_map (buf, &map, GST_MAP_READ);
9848
9849   if (map.size != 0x11) {
9850     GST_DEBUG ("Atom should have size 0x11, not %" G_GSIZE_FORMAT, map.size);
9851     goto bad_data;
9852   }
9853
9854   if (QT_FOURCC (map.data + 4) != FOURCC_damr) {
9855     GST_DEBUG ("Unknown atom in %" GST_FOURCC_FORMAT,
9856         GST_FOURCC_ARGS (QT_UINT32 (map.data + 4)));
9857     goto bad_data;
9858   }
9859
9860   mode_set = QT_UINT16 (map.data + 13);
9861
9862   if (mode_set == (wb ? AMR_WB_ALL_MODES : AMR_NB_ALL_MODES))
9863     max_mode = 7 + (wb ? 1 : 0);
9864   else
9865     /* AMR-NB modes fo from 0-7, and AMR-WB modes go from 0-8 */
9866     max_mode = g_bit_nth_msf ((gulong) mode_set & (wb ? 0x1ff : 0xff), -1);
9867
9868   if (max_mode == -1) {
9869     GST_DEBUG ("No mode indication was found (mode set) = %x",
9870         (guint) mode_set);
9871     goto bad_data;
9872   }
9873
9874   gst_buffer_unmap (buf, &map);
9875   return wb ? wb_bitrates[max_mode] : nb_bitrates[max_mode];
9876
9877 bad_data:
9878   gst_buffer_unmap (buf, &map);
9879   return 0;
9880 }
9881
9882 static gboolean
9883 qtdemux_parse_transformation_matrix (GstQTDemux * qtdemux,
9884     GstByteReader * reader, guint32 * matrix, const gchar * atom)
9885 {
9886   /*
9887    * 9 values of 32 bits (fixed point 16.16, except 2 5 and 8 that are 2.30)
9888    * [0 1 2]
9889    * [3 4 5]
9890    * [6 7 8]
9891    */
9892
9893   if (gst_byte_reader_get_remaining (reader) < 36)
9894     return FALSE;
9895
9896   matrix[0] = gst_byte_reader_get_uint32_be_unchecked (reader);
9897   matrix[1] = gst_byte_reader_get_uint32_be_unchecked (reader);
9898   matrix[2] = gst_byte_reader_get_uint32_be_unchecked (reader);
9899   matrix[3] = gst_byte_reader_get_uint32_be_unchecked (reader);
9900   matrix[4] = gst_byte_reader_get_uint32_be_unchecked (reader);
9901   matrix[5] = gst_byte_reader_get_uint32_be_unchecked (reader);
9902   matrix[6] = gst_byte_reader_get_uint32_be_unchecked (reader);
9903   matrix[7] = gst_byte_reader_get_uint32_be_unchecked (reader);
9904   matrix[8] = gst_byte_reader_get_uint32_be_unchecked (reader);
9905
9906   GST_DEBUG_OBJECT (qtdemux, "Transformation matrix from atom %s", atom);
9907   GST_DEBUG_OBJECT (qtdemux, "%u.%u %u.%u %u.%u", matrix[0] >> 16,
9908       matrix[0] & 0xFFFF, matrix[1] >> 16, matrix[1] & 0xFF, matrix[2] >> 16,
9909       matrix[2] & 0xFF);
9910   GST_DEBUG_OBJECT (qtdemux, "%u.%u %u.%u %u.%u", matrix[3] >> 16,
9911       matrix[3] & 0xFFFF, matrix[4] >> 16, matrix[4] & 0xFF, matrix[5] >> 16,
9912       matrix[5] & 0xFF);
9913   GST_DEBUG_OBJECT (qtdemux, "%u.%u %u.%u %u.%u", matrix[6] >> 16,
9914       matrix[6] & 0xFFFF, matrix[7] >> 16, matrix[7] & 0xFF, matrix[8] >> 16,
9915       matrix[8] & 0xFF);
9916
9917   return TRUE;
9918 }
9919
9920 static void
9921 qtdemux_inspect_transformation_matrix (GstQTDemux * qtdemux,
9922     QtDemuxStream * stream, guint32 * matrix, GstTagList ** taglist)
9923 {
9924
9925 /* [a b c]
9926  * [d e f]
9927  * [g h i]
9928  *
9929  * This macro will only compare value abdegh, it expects cfi to have already
9930  * been checked
9931  */
9932 #define QTCHECK_MATRIX(m,a,b,d,e) ((m)[0] == (a << 16) && (m)[1] == (b << 16) && \
9933                                    (m)[3] == (d << 16) && (m)[4] == (e << 16))
9934
9935   /* only handle the cases where the last column has standard values */
9936   if (matrix[2] == 0 && matrix[5] == 0 && matrix[8] == 1 << 30) {
9937     const gchar *rotation_tag = NULL;
9938
9939     /* no rotation needed */
9940     if (QTCHECK_MATRIX (matrix, 1, 0, 0, 1)) {
9941       /* NOP */
9942     } else if (QTCHECK_MATRIX (matrix, 0, 1, G_MAXUINT16, 0)) {
9943       rotation_tag = "rotate-90";
9944     } else if (QTCHECK_MATRIX (matrix, G_MAXUINT16, 0, 0, G_MAXUINT16)) {
9945       rotation_tag = "rotate-180";
9946     } else if (QTCHECK_MATRIX (matrix, 0, G_MAXUINT16, 1, 0)) {
9947       rotation_tag = "rotate-270";
9948     } else {
9949       GST_FIXME_OBJECT (qtdemux, "Unhandled transformation matrix values");
9950     }
9951
9952     GST_DEBUG_OBJECT (qtdemux, "Transformation matrix rotation %s",
9953         rotation_tag);
9954     if (rotation_tag != NULL) {
9955       if (*taglist == NULL)
9956         *taglist = gst_tag_list_new_empty ();
9957       gst_tag_list_add (*taglist, GST_TAG_MERGE_REPLACE,
9958           GST_TAG_IMAGE_ORIENTATION, rotation_tag, NULL);
9959     }
9960   } else {
9961     GST_FIXME_OBJECT (qtdemux, "Unhandled transformation matrix values");
9962   }
9963 }
9964
9965 /* Parses the boxes defined in ISO/IEC 14496-12 that enable support for
9966  * protected streams (sinf, frma, schm and schi); if the protection scheme is
9967  * Common Encryption (cenc), the function will also parse the tenc box (defined
9968  * in ISO/IEC 23001-7). @container points to the node that contains these boxes
9969  * (typically an enc[v|a|t|s] sample entry); the function will set
9970  * @original_fmt to the fourcc of the original unencrypted stream format.
9971  * Returns TRUE if successful; FALSE otherwise. */
9972 static gboolean
9973 qtdemux_parse_protection_scheme_info (GstQTDemux * qtdemux,
9974     QtDemuxStream * stream, GNode * container, guint32 * original_fmt)
9975 {
9976   GNode *sinf;
9977   GNode *frma;
9978   GNode *schm;
9979   GNode *schi;
9980   QtDemuxCencSampleSetInfo *info;
9981   GNode *tenc;
9982   const guint8 *tenc_data;
9983
9984   g_return_val_if_fail (qtdemux != NULL, FALSE);
9985   g_return_val_if_fail (stream != NULL, FALSE);
9986   g_return_val_if_fail (container != NULL, FALSE);
9987   g_return_val_if_fail (original_fmt != NULL, FALSE);
9988
9989   sinf = qtdemux_tree_get_child_by_type (container, FOURCC_sinf);
9990   if (G_UNLIKELY (!sinf)) {
9991     if (stream->protection_scheme_type == FOURCC_cenc) {
9992       GST_ERROR_OBJECT (qtdemux, "sinf box does not contain schi box, which is "
9993           "mandatory for Common Encryption");
9994       return FALSE;
9995     }
9996     return TRUE;
9997   }
9998
9999   frma = qtdemux_tree_get_child_by_type (sinf, FOURCC_frma);
10000   if (G_UNLIKELY (!frma)) {
10001     GST_ERROR_OBJECT (qtdemux, "sinf box does not contain mandatory frma box");
10002     return FALSE;
10003   }
10004
10005   *original_fmt = QT_FOURCC ((const guint8 *) frma->data + 8);
10006   GST_DEBUG_OBJECT (qtdemux, "original stream format: '%" GST_FOURCC_FORMAT "'",
10007       GST_FOURCC_ARGS (*original_fmt));
10008
10009   schm = qtdemux_tree_get_child_by_type (sinf, FOURCC_schm);
10010   if (!schm) {
10011     GST_DEBUG_OBJECT (qtdemux, "sinf box does not contain schm box");
10012     return FALSE;
10013   }
10014   stream->protection_scheme_type = QT_FOURCC ((const guint8 *) schm->data + 12);
10015   stream->protection_scheme_version =
10016       QT_UINT32 ((const guint8 *) schm->data + 16);
10017
10018   GST_DEBUG_OBJECT (qtdemux,
10019       "protection_scheme_type: %" GST_FOURCC_FORMAT ", "
10020       "protection_scheme_version: %#010x",
10021       GST_FOURCC_ARGS (stream->protection_scheme_type),
10022       stream->protection_scheme_version);
10023
10024   schi = qtdemux_tree_get_child_by_type (sinf, FOURCC_schi);
10025   if (!schi) {
10026     GST_DEBUG_OBJECT (qtdemux, "sinf box does not contain schi box");
10027     return FALSE;
10028   }
10029   if (stream->protection_scheme_type != FOURCC_cenc &&
10030       stream->protection_scheme_type != FOURCC_piff) {
10031     GST_ERROR_OBJECT (qtdemux,
10032         "Invalid protection_scheme_type: %" GST_FOURCC_FORMAT,
10033         GST_FOURCC_ARGS (stream->protection_scheme_type));
10034     return FALSE;
10035   }
10036
10037   if (G_UNLIKELY (!stream->protection_scheme_info))
10038     stream->protection_scheme_info =
10039         g_malloc0 (sizeof (QtDemuxCencSampleSetInfo));
10040
10041   info = (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
10042
10043   if (stream->protection_scheme_type == FOURCC_cenc) {
10044     guint32 is_encrypted;
10045     guint8 iv_size;
10046     const guint8 *default_kid;
10047
10048     tenc = qtdemux_tree_get_child_by_type (schi, FOURCC_tenc);
10049     if (!tenc) {
10050       GST_ERROR_OBJECT (qtdemux, "schi box does not contain tenc box, "
10051           "which is mandatory for Common Encryption");
10052       return FALSE;
10053     }
10054     tenc_data = (const guint8 *) tenc->data + 12;
10055     is_encrypted = QT_UINT24 (tenc_data);
10056     iv_size = QT_UINT8 (tenc_data + 3);
10057     default_kid = (tenc_data + 4);
10058     qtdemux_update_default_sample_encryption_settings (qtdemux, info,
10059         is_encrypted, iv_size, default_kid);
10060   } else if (stream->protection_scheme_type == FOURCC_piff) {
10061     GstByteReader br;
10062     static const guint8 piff_track_encryption_uuid[] = {
10063       0x89, 0x74, 0xdb, 0xce, 0x7b, 0xe7, 0x4c, 0x51,
10064       0x84, 0xf9, 0x71, 0x48, 0xf9, 0x88, 0x25, 0x54
10065     };
10066
10067     tenc = qtdemux_tree_get_child_by_type (schi, FOURCC_uuid);
10068     if (!tenc) {
10069       GST_ERROR_OBJECT (qtdemux, "schi box does not contain tenc box, "
10070           "which is mandatory for Common Encryption");
10071       return FALSE;
10072     }
10073
10074     tenc_data = (const guint8 *) tenc->data + 8;
10075     if (memcmp (tenc_data, piff_track_encryption_uuid, 16) != 0) {
10076       gchar *box_uuid = qtdemux_uuid_bytes_to_string (tenc_data);
10077       GST_ERROR_OBJECT (qtdemux,
10078           "Unsupported track encryption box with uuid: %s", box_uuid);
10079       g_free (box_uuid);
10080       return FALSE;
10081     }
10082     tenc_data = (const guint8 *) tenc->data + 16 + 12;
10083     gst_byte_reader_init (&br, tenc_data, 20);
10084     if (!qtdemux_update_default_piff_encryption_settings (qtdemux, info, &br)) {
10085       GST_ERROR_OBJECT (qtdemux, "PIFF track box parsing error");
10086       return FALSE;
10087     }
10088     stream->protection_scheme_type = FOURCC_cenc;
10089   }
10090
10091   return TRUE;
10092 }
10093
10094 static gint
10095 qtdemux_track_id_compare_func (QtDemuxStream * stream1, QtDemuxStream * stream2)
10096 {
10097   return (gint) stream1->track_id - (gint) stream2->track_id;
10098 }
10099
10100 /* parse the traks.
10101  * With each track we associate a new QtDemuxStream that contains all the info
10102  * about the trak.
10103  * traks that do not decode to something (like strm traks) will not have a pad.
10104  */
10105 static gboolean
10106 qtdemux_parse_trak (GstQTDemux * qtdemux, GNode * trak)
10107 {
10108   GstByteReader tkhd;
10109   int offset;
10110   GNode *mdia;
10111   GNode *mdhd;
10112   GNode *hdlr;
10113   GNode *minf;
10114   GNode *stbl;
10115   GNode *stsd;
10116   GNode *mp4a;
10117   GNode *mp4v;
10118   GNode *esds;
10119   GNode *tref;
10120   GNode *udta;
10121   GNode *svmi;
10122
10123   QtDemuxStream *stream = NULL;
10124   const guint8 *stsd_data;
10125   const guint8 *stsd_entry_data;
10126   guint remaining_stsd_len;
10127   guint stsd_entry_count;
10128   guint stsd_index;
10129   guint16 lang_code;            /* quicktime lang code or packed iso code */
10130   guint32 version;
10131   guint32 tkhd_flags = 0;
10132   guint8 tkhd_version = 0;
10133   guint32 w = 0, h = 0;
10134   guint value_size, stsd_len, len;
10135   guint32 track_id;
10136   guint32 dummy;
10137
10138   GST_DEBUG_OBJECT (qtdemux, "parse_trak");
10139
10140   if (!qtdemux_tree_get_child_by_type_full (trak, FOURCC_tkhd, &tkhd)
10141       || !gst_byte_reader_get_uint8 (&tkhd, &tkhd_version)
10142       || !gst_byte_reader_get_uint24_be (&tkhd, &tkhd_flags))
10143     goto corrupt_file;
10144
10145   /* pick between 64 or 32 bits */
10146   value_size = tkhd_version == 1 ? 8 : 4;
10147   if (!gst_byte_reader_skip (&tkhd, value_size * 2) ||
10148       !gst_byte_reader_get_uint32_be (&tkhd, &track_id))
10149     goto corrupt_file;
10150
10151   /* Check if current moov has duplicated track_id */
10152   if (qtdemux_find_stream (qtdemux, track_id))
10153     goto existing_stream;
10154
10155   stream = _create_stream (qtdemux, track_id);
10156   stream->stream_tags = gst_tag_list_make_writable (stream->stream_tags);
10157
10158   /* need defaults for fragments */
10159   qtdemux_parse_trex (qtdemux, stream, &dummy, &dummy, &dummy);
10160
10161   if ((tkhd_flags & 1) == 0)
10162     stream->disabled = TRUE;
10163
10164   GST_LOG_OBJECT (qtdemux, "track[tkhd] version/flags/id: 0x%02x/%06x/%u",
10165       tkhd_version, tkhd_flags, stream->track_id);
10166
10167   if (!(mdia = qtdemux_tree_get_child_by_type (trak, FOURCC_mdia)))
10168     goto corrupt_file;
10169
10170   if (!(mdhd = qtdemux_tree_get_child_by_type (mdia, FOURCC_mdhd))) {
10171     /* be nice for some crooked mjp2 files that use mhdr for mdhd */
10172     if (qtdemux->major_brand != FOURCC_mjp2 ||
10173         !(mdhd = qtdemux_tree_get_child_by_type (mdia, FOURCC_mhdr)))
10174       goto corrupt_file;
10175   }
10176
10177   len = QT_UINT32 ((guint8 *) mdhd->data);
10178   version = QT_UINT32 ((guint8 *) mdhd->data + 8);
10179   GST_LOG_OBJECT (qtdemux, "track version/flags: %08x", version);
10180   if (version == 0x01000000) {
10181     if (len < 38)
10182       goto corrupt_file;
10183     stream->timescale = QT_UINT32 ((guint8 *) mdhd->data + 28);
10184     stream->duration = QT_UINT64 ((guint8 *) mdhd->data + 32);
10185     lang_code = QT_UINT16 ((guint8 *) mdhd->data + 36);
10186   } else {
10187     if (len < 30)
10188       goto corrupt_file;
10189     stream->timescale = QT_UINT32 ((guint8 *) mdhd->data + 20);
10190     stream->duration = QT_UINT32 ((guint8 *) mdhd->data + 24);
10191     lang_code = QT_UINT16 ((guint8 *) mdhd->data + 28);
10192   }
10193
10194   if (lang_code < 0x400) {
10195     qtdemux_lang_map_qt_code_to_iso (stream->lang_id, lang_code);
10196   } else if (lang_code == 0x7fff) {
10197     stream->lang_id[0] = 0;     /* unspecified */
10198   } else {
10199     stream->lang_id[0] = 0x60 + ((lang_code >> 10) & 0x1F);
10200     stream->lang_id[1] = 0x60 + ((lang_code >> 5) & 0x1F);
10201     stream->lang_id[2] = 0x60 + (lang_code & 0x1F);
10202     stream->lang_id[3] = 0;
10203   }
10204
10205   GST_LOG_OBJECT (qtdemux, "track timescale: %" G_GUINT32_FORMAT,
10206       stream->timescale);
10207   GST_LOG_OBJECT (qtdemux, "track duration: %" G_GUINT64_FORMAT,
10208       stream->duration);
10209   GST_LOG_OBJECT (qtdemux, "track language code/id: 0x%04x/%s",
10210       lang_code, stream->lang_id);
10211
10212   if (G_UNLIKELY (stream->timescale == 0 || qtdemux->timescale == 0))
10213     goto corrupt_file;
10214
10215   if ((tref = qtdemux_tree_get_child_by_type (trak, FOURCC_tref))) {
10216     /* chapters track reference */
10217     GNode *chap = qtdemux_tree_get_child_by_type (tref, FOURCC_chap);
10218     if (chap) {
10219       gsize length = GST_READ_UINT32_BE (chap->data);
10220       if (qtdemux->chapters_track_id)
10221         GST_FIXME_OBJECT (qtdemux, "Multiple CHAP tracks");
10222
10223       if (length >= 12) {
10224         qtdemux->chapters_track_id =
10225             GST_READ_UINT32_BE ((gint8 *) chap->data + 8);
10226       }
10227     }
10228   }
10229
10230   /* fragmented files may have bogus duration in moov */
10231   if (!qtdemux->fragmented &&
10232       qtdemux->duration != G_MAXINT64 && stream->duration != G_MAXINT32) {
10233     guint64 tdur1, tdur2;
10234
10235     /* don't overflow */
10236     tdur1 = stream->timescale * (guint64) qtdemux->duration;
10237     tdur2 = qtdemux->timescale * (guint64) stream->duration;
10238
10239     /* HACK:
10240      * some of those trailers, nowadays, have prologue images that are
10241      * themselves video tracks as well. I haven't really found a way to
10242      * identify those yet, except for just looking at their duration. */
10243     if (tdur1 != 0 && (tdur2 * 10 / tdur1) < 2) {
10244       GST_WARNING_OBJECT (qtdemux,
10245           "Track shorter than 20%% (%" G_GUINT64_FORMAT "/%" G_GUINT32_FORMAT
10246           " vs. %" G_GUINT64_FORMAT "/%" G_GUINT32_FORMAT ") of the stream "
10247           "found, assuming preview image or something; skipping track",
10248           stream->duration, stream->timescale, qtdemux->duration,
10249           qtdemux->timescale);
10250       gst_qtdemux_stream_free (stream);
10251       return TRUE;
10252     }
10253   }
10254
10255   if (!(hdlr = qtdemux_tree_get_child_by_type (mdia, FOURCC_hdlr)))
10256     goto corrupt_file;
10257
10258   GST_LOG_OBJECT (qtdemux, "track type: %" GST_FOURCC_FORMAT,
10259       GST_FOURCC_ARGS (QT_FOURCC ((guint8 *) hdlr->data + 12)));
10260
10261   len = QT_UINT32 ((guint8 *) hdlr->data);
10262   if (len >= 20)
10263     stream->subtype = QT_FOURCC ((guint8 *) hdlr->data + 16);
10264   GST_LOG_OBJECT (qtdemux, "track subtype: %" GST_FOURCC_FORMAT,
10265       GST_FOURCC_ARGS (stream->subtype));
10266
10267   if (!(minf = qtdemux_tree_get_child_by_type (mdia, FOURCC_minf)))
10268     goto corrupt_file;
10269
10270   if (!(stbl = qtdemux_tree_get_child_by_type (minf, FOURCC_stbl)))
10271     goto corrupt_file;
10272
10273   /*parse svmi header if existing */
10274   svmi = qtdemux_tree_get_child_by_type (stbl, FOURCC_svmi);
10275   if (svmi) {
10276     len = QT_UINT32 ((guint8 *) svmi->data);
10277     version = QT_UINT32 ((guint8 *) svmi->data + 8);
10278     if (!version) {
10279       GstVideoMultiviewMode mode = GST_VIDEO_MULTIVIEW_MODE_NONE;
10280       GstVideoMultiviewFlags flags = GST_VIDEO_MULTIVIEW_FLAGS_NONE;
10281       guint8 frame_type, frame_layout;
10282
10283       /* MPEG-A stereo video */
10284       if (qtdemux->major_brand == FOURCC_ss02)
10285         flags |= GST_VIDEO_MULTIVIEW_FLAGS_MIXED_MONO;
10286
10287       frame_type = QT_UINT8 ((guint8 *) svmi->data + 12);
10288       frame_layout = QT_UINT8 ((guint8 *) svmi->data + 13) & 0x01;
10289       switch (frame_type) {
10290         case 0:
10291           mode = GST_VIDEO_MULTIVIEW_MODE_SIDE_BY_SIDE;
10292           break;
10293         case 1:
10294           mode = GST_VIDEO_MULTIVIEW_MODE_ROW_INTERLEAVED;
10295           break;
10296         case 2:
10297           mode = GST_VIDEO_MULTIVIEW_MODE_FRAME_BY_FRAME;
10298           break;
10299         case 3:
10300           /* mode 3 is primary/secondary view sequence, ie
10301            * left/right views in separate tracks. See section 7.2
10302            * of ISO/IEC 23000-11:2009 */
10303           GST_FIXME_OBJECT (qtdemux,
10304               "Implement stereo video in separate streams");
10305       }
10306
10307       if ((frame_layout & 0x1) == 0)
10308         flags |= GST_VIDEO_MULTIVIEW_FLAGS_RIGHT_VIEW_FIRST;
10309
10310       GST_LOG_OBJECT (qtdemux,
10311           "StereoVideo: composition type: %u, is_left_first: %u",
10312           frame_type, frame_layout);
10313       stream->multiview_mode = mode;
10314       stream->multiview_flags = flags;
10315     }
10316   }
10317
10318   /* parse rest of tkhd */
10319   if (stream->subtype == FOURCC_vide) {
10320     guint32 matrix[9];
10321
10322     /* version 1 uses some 64-bit ints */
10323     if (!gst_byte_reader_skip (&tkhd, 20 + value_size))
10324       goto corrupt_file;
10325
10326     if (!qtdemux_parse_transformation_matrix (qtdemux, &tkhd, matrix, "tkhd"))
10327       goto corrupt_file;
10328
10329     if (!gst_byte_reader_get_uint32_be (&tkhd, &w)
10330         || !gst_byte_reader_get_uint32_be (&tkhd, &h))
10331       goto corrupt_file;
10332
10333     qtdemux_inspect_transformation_matrix (qtdemux, stream, matrix,
10334         &stream->stream_tags);
10335   }
10336
10337   /* parse stsd */
10338   if (!(stsd = qtdemux_tree_get_child_by_type (stbl, FOURCC_stsd)))
10339     goto corrupt_file;
10340   stsd_data = (const guint8 *) stsd->data;
10341
10342   /* stsd should at least have one entry */
10343   stsd_len = QT_UINT32 (stsd_data);
10344   if (stsd_len < 24) {
10345     /* .. but skip stream with empty stsd produced by some Vivotek cameras */
10346     if (stream->subtype == FOURCC_vivo) {
10347       gst_qtdemux_stream_free (stream);
10348       return TRUE;
10349     } else {
10350       goto corrupt_file;
10351     }
10352   }
10353
10354   stream->stsd_entries_length = stsd_entry_count = QT_UINT32 (stsd_data + 12);
10355   stream->stsd_entries = g_new0 (QtDemuxStreamStsdEntry, stsd_entry_count);
10356   GST_LOG_OBJECT (qtdemux, "stsd len:           %d", stsd_len);
10357   GST_LOG_OBJECT (qtdemux, "stsd entry count:   %u", stsd_entry_count);
10358
10359   stsd_entry_data = stsd_data + 16;
10360   remaining_stsd_len = stsd_len - 16;
10361   for (stsd_index = 0; stsd_index < stsd_entry_count; stsd_index++) {
10362     guint32 fourcc;
10363     gchar *codec = NULL;
10364     QtDemuxStreamStsdEntry *entry = &stream->stsd_entries[stsd_index];
10365
10366     /* and that entry should fit within stsd */
10367     len = QT_UINT32 (stsd_entry_data);
10368     if (len > remaining_stsd_len)
10369       goto corrupt_file;
10370
10371     entry->fourcc = fourcc = QT_FOURCC (stsd_entry_data + 4);
10372     GST_LOG_OBJECT (qtdemux, "stsd type:          %" GST_FOURCC_FORMAT,
10373         GST_FOURCC_ARGS (entry->fourcc));
10374     GST_LOG_OBJECT (qtdemux, "stsd type len:      %d", len);
10375
10376     if ((fourcc == FOURCC_drms) || (fourcc == FOURCC_drmi))
10377       goto error_encrypted;
10378
10379     if (fourcc == FOURCC_encv || fourcc == FOURCC_enca) {
10380       /* FIXME this looks wrong, there might be multiple children
10381        * with the same type */
10382       GNode *enc = qtdemux_tree_get_child_by_type (stsd, fourcc);
10383       stream->protected = TRUE;
10384       if (!qtdemux_parse_protection_scheme_info (qtdemux, stream, enc, &fourcc))
10385         GST_ERROR_OBJECT (qtdemux, "Failed to parse protection scheme info");
10386     }
10387
10388     if (stream->subtype == FOURCC_vide) {
10389       GNode *colr;
10390       GNode *fiel;
10391       GNode *pasp;
10392       gboolean gray;
10393       gint depth, palette_size, palette_count;
10394       guint32 *palette_data = NULL;
10395
10396       entry->sampled = TRUE;
10397
10398       stream->display_width = w >> 16;
10399       stream->display_height = h >> 16;
10400
10401       offset = 16;
10402       if (len < 86)             /* TODO verify */
10403         goto corrupt_file;
10404
10405       entry->width = QT_UINT16 (stsd_entry_data + offset + 16);
10406       entry->height = QT_UINT16 (stsd_entry_data + offset + 18);
10407       entry->fps_n = 0;         /* this is filled in later */
10408       entry->fps_d = 0;         /* this is filled in later */
10409       entry->bits_per_sample = QT_UINT16 (stsd_entry_data + offset + 66);
10410       entry->color_table_id = QT_UINT16 (stsd_entry_data + offset + 68);
10411
10412       /* if color_table_id is 0, ctab atom must follow; however some files
10413        * produced by TMPEGEnc have color_table_id = 0 and no ctab atom, so
10414        * if color table is not present we'll correct the value */
10415       if (entry->color_table_id == 0 &&
10416           (len < 90
10417               || QT_FOURCC (stsd_entry_data + offset + 70) != FOURCC_ctab)) {
10418         entry->color_table_id = -1;
10419       }
10420
10421       GST_LOG_OBJECT (qtdemux, "width %d, height %d, bps %d, color table id %d",
10422           entry->width, entry->height, entry->bits_per_sample,
10423           entry->color_table_id);
10424
10425       depth = entry->bits_per_sample;
10426
10427       /* more than 32 bits means grayscale */
10428       gray = (depth > 32);
10429       /* low 32 bits specify the depth  */
10430       depth &= 0x1F;
10431
10432       /* different number of palette entries is determined by depth. */
10433       palette_count = 0;
10434       if ((depth == 1) || (depth == 2) || (depth == 4) || (depth == 8))
10435         palette_count = (1 << depth);
10436       palette_size = palette_count * 4;
10437
10438       if (entry->color_table_id) {
10439         switch (palette_count) {
10440           case 0:
10441             break;
10442           case 2:
10443             palette_data = g_memdup (ff_qt_default_palette_2, palette_size);
10444             break;
10445           case 4:
10446             palette_data = g_memdup (ff_qt_default_palette_4, palette_size);
10447             break;
10448           case 16:
10449             if (gray)
10450               palette_data =
10451                   g_memdup (ff_qt_grayscale_palette_16, palette_size);
10452             else
10453               palette_data = g_memdup (ff_qt_default_palette_16, palette_size);
10454             break;
10455           case 256:
10456             if (gray)
10457               palette_data =
10458                   g_memdup (ff_qt_grayscale_palette_256, palette_size);
10459             else
10460               palette_data = g_memdup (ff_qt_default_palette_256, palette_size);
10461             break;
10462           default:
10463             GST_ELEMENT_WARNING (qtdemux, STREAM, DEMUX,
10464                 (_("The video in this file might not play correctly.")),
10465                 ("unsupported palette depth %d", depth));
10466             break;
10467         }
10468       } else {
10469         gint i, j, start, end;
10470
10471         if (len < 94)
10472           goto corrupt_file;
10473
10474         /* read table */
10475         start = QT_UINT32 (stsd_entry_data + offset + 70);
10476         palette_count = QT_UINT16 (stsd_entry_data + offset + 74);
10477         end = QT_UINT16 (stsd_entry_data + offset + 76);
10478
10479         GST_LOG_OBJECT (qtdemux, "start %d, end %d, palette_count %d",
10480             start, end, palette_count);
10481
10482         if (end > 255)
10483           end = 255;
10484         if (start > end)
10485           start = end;
10486
10487         if (len < 94 + (end - start) * 8)
10488           goto corrupt_file;
10489
10490         /* palette is always the same size */
10491         palette_data = g_malloc0 (256 * 4);
10492         palette_size = 256 * 4;
10493
10494         for (j = 0, i = start; i <= end; j++, i++) {
10495           guint32 a, r, g, b;
10496
10497           a = QT_UINT16 (stsd_entry_data + offset + 78 + (j * 8));
10498           r = QT_UINT16 (stsd_entry_data + offset + 80 + (j * 8));
10499           g = QT_UINT16 (stsd_entry_data + offset + 82 + (j * 8));
10500           b = QT_UINT16 (stsd_entry_data + offset + 84 + (j * 8));
10501
10502           palette_data[i] = ((a & 0xff00) << 16) | ((r & 0xff00) << 8) |
10503               (g & 0xff00) | (b >> 8);
10504         }
10505       }
10506
10507       if (entry->caps)
10508         gst_caps_unref (entry->caps);
10509
10510       entry->caps =
10511           qtdemux_video_caps (qtdemux, stream, entry, fourcc, stsd_entry_data,
10512           &codec);
10513       if (G_UNLIKELY (!entry->caps)) {
10514         g_free (palette_data);
10515         goto unknown_stream;
10516       }
10517
10518       if (codec) {
10519         gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
10520             GST_TAG_VIDEO_CODEC, codec, NULL);
10521         g_free (codec);
10522         codec = NULL;
10523       }
10524
10525       if (palette_data) {
10526         GstStructure *s;
10527
10528         if (entry->rgb8_palette)
10529           gst_memory_unref (entry->rgb8_palette);
10530         entry->rgb8_palette = gst_memory_new_wrapped (GST_MEMORY_FLAG_READONLY,
10531             palette_data, palette_size, 0, palette_size, palette_data, g_free);
10532
10533         s = gst_caps_get_structure (entry->caps, 0);
10534
10535         /* non-raw video has a palette_data property. raw video has the palette as
10536          * an extra plane that we append to the output buffers before we push
10537          * them*/
10538         if (!gst_structure_has_name (s, "video/x-raw")) {
10539           GstBuffer *palette;
10540
10541           palette = gst_buffer_new ();
10542           gst_buffer_append_memory (palette, entry->rgb8_palette);
10543           entry->rgb8_palette = NULL;
10544
10545           gst_caps_set_simple (entry->caps, "palette_data",
10546               GST_TYPE_BUFFER, palette, NULL);
10547           gst_buffer_unref (palette);
10548         }
10549       } else if (palette_count != 0) {
10550         GST_ELEMENT_WARNING (qtdemux, STREAM, NOT_IMPLEMENTED,
10551             (NULL), ("Unsupported palette depth %d", depth));
10552       }
10553
10554       GST_LOG_OBJECT (qtdemux, "frame count:   %u",
10555           QT_UINT16 (stsd_entry_data + offset + 32));
10556
10557       esds = NULL;
10558       pasp = NULL;
10559       colr = NULL;
10560       fiel = NULL;
10561       /* pick 'the' stsd child */
10562       mp4v = qtdemux_tree_get_child_by_index (stsd, stsd_index);
10563       if (!stream->protected) {
10564         if (QTDEMUX_TREE_NODE_FOURCC (mp4v) != fourcc) {
10565           mp4v = NULL;
10566         }
10567       } else {
10568         if (QTDEMUX_TREE_NODE_FOURCC (mp4v) != FOURCC_encv) {
10569           mp4v = NULL;
10570         }
10571       }
10572
10573       if (mp4v) {
10574         esds = qtdemux_tree_get_child_by_type (mp4v, FOURCC_esds);
10575         pasp = qtdemux_tree_get_child_by_type (mp4v, FOURCC_pasp);
10576         colr = qtdemux_tree_get_child_by_type (mp4v, FOURCC_colr);
10577         fiel = qtdemux_tree_get_child_by_type (mp4v, FOURCC_fiel);
10578       }
10579
10580       if (pasp) {
10581         const guint8 *pasp_data = (const guint8 *) pasp->data;
10582         gint len = QT_UINT32 (pasp_data);
10583
10584         if (len == 16) {
10585           CUR_STREAM (stream)->par_w = QT_UINT32 (pasp_data + 8);
10586           CUR_STREAM (stream)->par_h = QT_UINT32 (pasp_data + 12);
10587         } else {
10588           CUR_STREAM (stream)->par_w = 0;
10589           CUR_STREAM (stream)->par_h = 0;
10590         }
10591       } else {
10592         CUR_STREAM (stream)->par_w = 0;
10593         CUR_STREAM (stream)->par_h = 0;
10594       }
10595
10596       if (fiel) {
10597         const guint8 *fiel_data = (const guint8 *) fiel->data;
10598         gint len = QT_UINT32 (fiel_data);
10599
10600         if (len == 10) {
10601           CUR_STREAM (stream)->interlace_mode = GST_READ_UINT8 (fiel_data + 8);
10602           CUR_STREAM (stream)->field_order = GST_READ_UINT8 (fiel_data + 9);
10603         }
10604       }
10605
10606       if (colr) {
10607         const guint8 *colr_data = (const guint8 *) colr->data;
10608         gint len = QT_UINT32 (colr_data);
10609
10610         if (len == 19 || len == 18) {
10611           guint32 color_type = GST_READ_UINT32_LE (colr_data + 8);
10612
10613           if (color_type == FOURCC_nclx || color_type == FOURCC_nclc) {
10614             guint16 primaries = GST_READ_UINT16_BE (colr_data + 12);
10615             guint16 transfer_function = GST_READ_UINT16_BE (colr_data + 14);
10616             guint16 matrix = GST_READ_UINT16_BE (colr_data + 16);
10617             gboolean full_range = len == 19 ? colr_data[17] >> 7 : FALSE;
10618
10619             switch (primaries) {
10620               case 1:
10621                 CUR_STREAM (stream)->colorimetry.primaries =
10622                     GST_VIDEO_COLOR_PRIMARIES_BT709;
10623                 break;
10624               case 5:
10625                 CUR_STREAM (stream)->colorimetry.primaries =
10626                     GST_VIDEO_COLOR_PRIMARIES_BT470BG;
10627                 break;
10628               case 6:
10629                 CUR_STREAM (stream)->colorimetry.primaries =
10630                     GST_VIDEO_COLOR_PRIMARIES_SMPTE170M;
10631                 break;
10632               case 9:
10633                 CUR_STREAM (stream)->colorimetry.primaries =
10634                     GST_VIDEO_COLOR_PRIMARIES_BT2020;
10635                 break;
10636               default:
10637                 break;
10638             }
10639
10640             switch (transfer_function) {
10641               case 1:
10642                 CUR_STREAM (stream)->colorimetry.transfer =
10643                     GST_VIDEO_TRANSFER_BT709;
10644                 break;
10645               case 7:
10646                 CUR_STREAM (stream)->colorimetry.transfer =
10647                     GST_VIDEO_TRANSFER_SMPTE240M;
10648                 break;
10649               default:
10650                 break;
10651             }
10652
10653             switch (matrix) {
10654               case 1:
10655                 CUR_STREAM (stream)->colorimetry.matrix =
10656                     GST_VIDEO_COLOR_MATRIX_BT709;
10657                 break;
10658               case 6:
10659                 CUR_STREAM (stream)->colorimetry.matrix =
10660                     GST_VIDEO_COLOR_MATRIX_BT601;
10661                 break;
10662               case 7:
10663                 CUR_STREAM (stream)->colorimetry.matrix =
10664                     GST_VIDEO_COLOR_MATRIX_SMPTE240M;
10665                 break;
10666               case 9:
10667                 CUR_STREAM (stream)->colorimetry.matrix =
10668                     GST_VIDEO_COLOR_MATRIX_BT2020;
10669                 break;
10670               default:
10671                 break;
10672             }
10673
10674             CUR_STREAM (stream)->colorimetry.range =
10675                 full_range ? GST_VIDEO_COLOR_RANGE_0_255 :
10676                 GST_VIDEO_COLOR_RANGE_16_235;
10677           } else {
10678             GST_DEBUG_OBJECT (qtdemux, "Unsupported color type");
10679           }
10680         } else {
10681           GST_WARNING_OBJECT (qtdemux, "Invalid colr atom size");
10682         }
10683       }
10684
10685       if (esds) {
10686         gst_qtdemux_handle_esds (qtdemux, stream, entry, esds,
10687             stream->stream_tags);
10688       } else {
10689         switch (fourcc) {
10690           case FOURCC_H264:
10691           case FOURCC_avc1:
10692           case FOURCC_avc3:
10693           {
10694             gint len = QT_UINT32 (stsd_entry_data) - 0x56;
10695             const guint8 *avc_data = stsd_entry_data + 0x56;
10696
10697             /* find avcC */
10698             while (len >= 0x8) {
10699               gint size;
10700
10701               if (QT_UINT32 (avc_data) <= len)
10702                 size = QT_UINT32 (avc_data) - 0x8;
10703               else
10704                 size = len - 0x8;
10705
10706               if (size < 1)
10707                 /* No real data, so break out */
10708                 break;
10709
10710               switch (QT_FOURCC (avc_data + 0x4)) {
10711                 case FOURCC_avcC:
10712                 {
10713                   /* parse, if found */
10714                   GstBuffer *buf;
10715
10716                   GST_DEBUG_OBJECT (qtdemux, "found avcC codec_data in stsd");
10717
10718                   /* First 4 bytes are the length of the atom, the next 4 bytes
10719                    * are the fourcc, the next 1 byte is the version, and the
10720                    * subsequent bytes are profile_tier_level structure like data. */
10721                   gst_codec_utils_h264_caps_set_level_and_profile (entry->caps,
10722                       avc_data + 8 + 1, size - 1);
10723                   buf = gst_buffer_new_and_alloc (size);
10724                   gst_buffer_fill (buf, 0, avc_data + 0x8, size);
10725                   gst_caps_set_simple (entry->caps,
10726                       "codec_data", GST_TYPE_BUFFER, buf, NULL);
10727                   gst_buffer_unref (buf);
10728
10729                   break;
10730                 }
10731                 case FOURCC_strf:
10732                 {
10733                   GstBuffer *buf;
10734
10735                   GST_DEBUG_OBJECT (qtdemux, "found strf codec_data in stsd");
10736
10737                   /* First 4 bytes are the length of the atom, the next 4 bytes
10738                    * are the fourcc, next 40 bytes are BITMAPINFOHEADER,
10739                    * next 1 byte is the version, and the
10740                    * subsequent bytes are sequence parameter set like data. */
10741
10742                   size -= 40;   /* we'll be skipping BITMAPINFOHEADER */
10743                   if (size > 1) {
10744                     gst_codec_utils_h264_caps_set_level_and_profile
10745                         (entry->caps, avc_data + 8 + 40 + 1, size - 1);
10746
10747                     buf = gst_buffer_new_and_alloc (size);
10748                     gst_buffer_fill (buf, 0, avc_data + 8 + 40, size);
10749                     gst_caps_set_simple (entry->caps,
10750                         "codec_data", GST_TYPE_BUFFER, buf, NULL);
10751                     gst_buffer_unref (buf);
10752                   }
10753                   break;
10754                 }
10755                 case FOURCC_btrt:
10756                 {
10757                   guint avg_bitrate, max_bitrate;
10758
10759                   /* bufferSizeDB, maxBitrate and avgBitrate - 4 bytes each */
10760                   if (size < 12)
10761                     break;
10762
10763                   max_bitrate = QT_UINT32 (avc_data + 0xc);
10764                   avg_bitrate = QT_UINT32 (avc_data + 0x10);
10765
10766                   if (!max_bitrate && !avg_bitrate)
10767                     break;
10768
10769                   /* Some muxers seem to swap the average and maximum bitrates
10770                    * (I'm looking at you, YouTube), so we swap for sanity. */
10771                   if (max_bitrate > 0 && max_bitrate < avg_bitrate) {
10772                     guint temp = avg_bitrate;
10773
10774                     avg_bitrate = max_bitrate;
10775                     max_bitrate = temp;
10776                   }
10777
10778                   if (max_bitrate > 0 && max_bitrate < G_MAXUINT32) {
10779                     gst_tag_list_add (stream->stream_tags,
10780                         GST_TAG_MERGE_REPLACE, GST_TAG_MAXIMUM_BITRATE,
10781                         max_bitrate, NULL);
10782                   }
10783                   if (avg_bitrate > 0 && avg_bitrate < G_MAXUINT32) {
10784                     gst_tag_list_add (stream->stream_tags,
10785                         GST_TAG_MERGE_REPLACE, GST_TAG_BITRATE, avg_bitrate,
10786                         NULL);
10787                   }
10788
10789                   break;
10790                 }
10791
10792                 default:
10793                   break;
10794               }
10795
10796               len -= size + 8;
10797               avc_data += size + 8;
10798             }
10799
10800             break;
10801           }
10802           case FOURCC_H265:
10803           case FOURCC_hvc1:
10804           case FOURCC_hev1:
10805           {
10806             gint len = QT_UINT32 (stsd_entry_data) - 0x56;
10807             const guint8 *hevc_data = stsd_entry_data + 0x56;
10808
10809             /* find hevc */
10810             while (len >= 0x8) {
10811               gint size;
10812
10813               if (QT_UINT32 (hevc_data) <= len)
10814                 size = QT_UINT32 (hevc_data) - 0x8;
10815               else
10816                 size = len - 0x8;
10817
10818               if (size < 1)
10819                 /* No real data, so break out */
10820                 break;
10821
10822               switch (QT_FOURCC (hevc_data + 0x4)) {
10823                 case FOURCC_hvcC:
10824                 {
10825                   /* parse, if found */
10826                   GstBuffer *buf;
10827
10828                   GST_DEBUG_OBJECT (qtdemux, "found hvcC codec_data in stsd");
10829
10830                   /* First 4 bytes are the length of the atom, the next 4 bytes
10831                    * are the fourcc, the next 1 byte is the version, and the
10832                    * subsequent bytes are sequence parameter set like data. */
10833                   gst_codec_utils_h265_caps_set_level_tier_and_profile
10834                       (entry->caps, hevc_data + 8 + 1, size - 1);
10835
10836                   buf = gst_buffer_new_and_alloc (size);
10837                   gst_buffer_fill (buf, 0, hevc_data + 0x8, size);
10838                   gst_caps_set_simple (entry->caps,
10839                       "codec_data", GST_TYPE_BUFFER, buf, NULL);
10840                   gst_buffer_unref (buf);
10841                   break;
10842                 }
10843                 default:
10844                   break;
10845               }
10846               len -= size + 8;
10847               hevc_data += size + 8;
10848             }
10849             break;
10850           }
10851           case FOURCC_mp4v:
10852           case FOURCC_MP4V:
10853           case FOURCC_fmp4:
10854           case FOURCC_FMP4:
10855           case FOURCC_xvid:
10856           case FOURCC_XVID:
10857           {
10858             GNode *glbl;
10859
10860             GST_DEBUG_OBJECT (qtdemux, "found %" GST_FOURCC_FORMAT,
10861                 GST_FOURCC_ARGS (fourcc));
10862
10863             /* codec data might be in glbl extension atom */
10864             glbl = mp4v ?
10865                 qtdemux_tree_get_child_by_type (mp4v, FOURCC_glbl) : NULL;
10866             if (glbl) {
10867               guint8 *data;
10868               GstBuffer *buf;
10869               gint len;
10870
10871               GST_DEBUG_OBJECT (qtdemux, "found glbl data in stsd");
10872               data = glbl->data;
10873               len = QT_UINT32 (data);
10874               if (len > 0x8) {
10875                 len -= 0x8;
10876                 buf = gst_buffer_new_and_alloc (len);
10877                 gst_buffer_fill (buf, 0, data + 8, len);
10878                 gst_caps_set_simple (entry->caps,
10879                     "codec_data", GST_TYPE_BUFFER, buf, NULL);
10880                 gst_buffer_unref (buf);
10881               }
10882             }
10883             break;
10884           }
10885           case FOURCC_mjp2:
10886           {
10887             /* see annex I of the jpeg2000 spec */
10888             GNode *jp2h, *ihdr, *colr, *mjp2, *field, *prefix, *cmap, *cdef;
10889             const guint8 *data;
10890             const gchar *colorspace = NULL;
10891             gint ncomp = 0;
10892             guint32 ncomp_map = 0;
10893             gint32 *comp_map = NULL;
10894             guint32 nchan_def = 0;
10895             gint32 *chan_def = NULL;
10896
10897             GST_DEBUG_OBJECT (qtdemux, "found mjp2");
10898             /* some required atoms */
10899             mjp2 = qtdemux_tree_get_child_by_index (stsd, stsd_index);
10900             if (!mjp2)
10901               break;
10902             jp2h = qtdemux_tree_get_child_by_type (mjp2, FOURCC_jp2h);
10903             if (!jp2h)
10904               break;
10905
10906             /* number of components; redundant with info in codestream, but useful
10907                to a muxer */
10908             ihdr = qtdemux_tree_get_child_by_type (jp2h, FOURCC_ihdr);
10909             if (!ihdr || QT_UINT32 (ihdr->data) != 22)
10910               break;
10911             ncomp = QT_UINT16 (((guint8 *) ihdr->data) + 16);
10912
10913             colr = qtdemux_tree_get_child_by_type (jp2h, FOURCC_colr);
10914             if (!colr)
10915               break;
10916             GST_DEBUG_OBJECT (qtdemux, "found colr");
10917             /* extract colour space info */
10918             if (QT_UINT8 ((guint8 *) colr->data + 8) == 1) {
10919               switch (QT_UINT32 ((guint8 *) colr->data + 11)) {
10920                 case 16:
10921                   colorspace = "sRGB";
10922                   break;
10923                 case 17:
10924                   colorspace = "GRAY";
10925                   break;
10926                 case 18:
10927                   colorspace = "sYUV";
10928                   break;
10929                 default:
10930                   colorspace = NULL;
10931                   break;
10932               }
10933             }
10934             if (!colorspace)
10935               /* colr is required, and only values 16, 17, and 18 are specified,
10936                  so error if we have no colorspace */
10937               break;
10938
10939             /* extract component mapping */
10940             cmap = qtdemux_tree_get_child_by_type (jp2h, FOURCC_cmap);
10941             if (cmap) {
10942               guint32 cmap_len = 0;
10943               int i;
10944               cmap_len = QT_UINT32 (cmap->data);
10945               if (cmap_len >= 8) {
10946                 /* normal box, subtract off header */
10947                 cmap_len -= 8;
10948                 /* cmap: { u16 cmp; u8 mtyp; u8 pcol; }* */
10949                 if (cmap_len % 4 == 0) {
10950                   ncomp_map = (cmap_len / 4);
10951                   comp_map = g_new0 (gint32, ncomp_map);
10952                   for (i = 0; i < ncomp_map; i++) {
10953                     guint16 cmp;
10954                     guint8 mtyp, pcol;
10955                     cmp = QT_UINT16 (((guint8 *) cmap->data) + 8 + i * 4);
10956                     mtyp = QT_UINT8 (((guint8 *) cmap->data) + 8 + i * 4 + 2);
10957                     pcol = QT_UINT8 (((guint8 *) cmap->data) + 8 + i * 4 + 3);
10958                     comp_map[i] = (mtyp << 24) | (pcol << 16) | cmp;
10959                   }
10960                 }
10961               }
10962             }
10963             /* extract channel definitions */
10964             cdef = qtdemux_tree_get_child_by_type (jp2h, FOURCC_cdef);
10965             if (cdef) {
10966               guint32 cdef_len = 0;
10967               int i;
10968               cdef_len = QT_UINT32 (cdef->data);
10969               if (cdef_len >= 10) {
10970                 /* normal box, subtract off header and len */
10971                 cdef_len -= 10;
10972                 /* cdef: u16 n; { u16 cn; u16 typ; u16 asoc; }* */
10973                 if (cdef_len % 6 == 0) {
10974                   nchan_def = (cdef_len / 6);
10975                   chan_def = g_new0 (gint32, nchan_def);
10976                   for (i = 0; i < nchan_def; i++)
10977                     chan_def[i] = -1;
10978                   for (i = 0; i < nchan_def; i++) {
10979                     guint16 cn, typ, asoc;
10980                     cn = QT_UINT16 (((guint8 *) cdef->data) + 10 + i * 6);
10981                     typ = QT_UINT16 (((guint8 *) cdef->data) + 10 + i * 6 + 2);
10982                     asoc = QT_UINT16 (((guint8 *) cdef->data) + 10 + i * 6 + 4);
10983                     if (cn < nchan_def) {
10984                       switch (typ) {
10985                         case 0:
10986                           chan_def[cn] = asoc;
10987                           break;
10988                         case 1:
10989                           chan_def[cn] = 0;     /* alpha */
10990                           break;
10991                         default:
10992                           chan_def[cn] = -typ;
10993                       }
10994                     }
10995                   }
10996                 }
10997               }
10998             }
10999
11000             gst_caps_set_simple (entry->caps,
11001                 "num-components", G_TYPE_INT, ncomp, NULL);
11002             gst_caps_set_simple (entry->caps,
11003                 "colorspace", G_TYPE_STRING, colorspace, NULL);
11004
11005             if (comp_map) {
11006               GValue arr = { 0, };
11007               GValue elt = { 0, };
11008               int i;
11009               g_value_init (&arr, GST_TYPE_ARRAY);
11010               g_value_init (&elt, G_TYPE_INT);
11011               for (i = 0; i < ncomp_map; i++) {
11012                 g_value_set_int (&elt, comp_map[i]);
11013                 gst_value_array_append_value (&arr, &elt);
11014               }
11015               gst_structure_set_value (gst_caps_get_structure (entry->caps, 0),
11016                   "component-map", &arr);
11017               g_value_unset (&elt);
11018               g_value_unset (&arr);
11019               g_free (comp_map);
11020             }
11021
11022             if (chan_def) {
11023               GValue arr = { 0, };
11024               GValue elt = { 0, };
11025               int i;
11026               g_value_init (&arr, GST_TYPE_ARRAY);
11027               g_value_init (&elt, G_TYPE_INT);
11028               for (i = 0; i < nchan_def; i++) {
11029                 g_value_set_int (&elt, chan_def[i]);
11030                 gst_value_array_append_value (&arr, &elt);
11031               }
11032               gst_structure_set_value (gst_caps_get_structure (entry->caps, 0),
11033                   "channel-definitions", &arr);
11034               g_value_unset (&elt);
11035               g_value_unset (&arr);
11036               g_free (chan_def);
11037             }
11038
11039             /* some optional atoms */
11040             field = qtdemux_tree_get_child_by_type (mjp2, FOURCC_fiel);
11041             prefix = qtdemux_tree_get_child_by_type (mjp2, FOURCC_jp2x);
11042
11043             /* indicate possible fields in caps */
11044             if (field) {
11045               data = (guint8 *) field->data + 8;
11046               if (*data != 1)
11047                 gst_caps_set_simple (entry->caps, "fields", G_TYPE_INT,
11048                     (gint) * data, NULL);
11049             }
11050             /* add codec_data if provided */
11051             if (prefix) {
11052               GstBuffer *buf;
11053               gint len;
11054
11055               GST_DEBUG_OBJECT (qtdemux, "found prefix data in stsd");
11056               data = prefix->data;
11057               len = QT_UINT32 (data);
11058               if (len > 0x8) {
11059                 len -= 0x8;
11060                 buf = gst_buffer_new_and_alloc (len);
11061                 gst_buffer_fill (buf, 0, data + 8, len);
11062                 gst_caps_set_simple (entry->caps,
11063                     "codec_data", GST_TYPE_BUFFER, buf, NULL);
11064                 gst_buffer_unref (buf);
11065               }
11066             }
11067             break;
11068           }
11069           case FOURCC_SVQ3:
11070           case FOURCC_VP31:
11071           {
11072             GstBuffer *buf;
11073             GstBuffer *seqh = NULL;
11074             const guint8 *gamma_data = NULL;
11075             gint len = QT_UINT32 (stsd_data);   /* FIXME review - why put the whole stsd in codec data? */
11076
11077             qtdemux_parse_svq3_stsd_data (qtdemux, stsd_entry_data, &gamma_data,
11078                 &seqh);
11079             if (gamma_data) {
11080               gst_caps_set_simple (entry->caps, "applied-gamma", G_TYPE_DOUBLE,
11081                   QT_FP32 (gamma_data), NULL);
11082             }
11083             if (seqh) {
11084               /* sorry for the bad name, but we don't know what this is, other
11085                * than its own fourcc */
11086               gst_caps_set_simple (entry->caps, "seqh", GST_TYPE_BUFFER, seqh,
11087                   NULL);
11088               gst_buffer_unref (seqh);
11089             }
11090
11091             GST_DEBUG_OBJECT (qtdemux, "found codec_data in stsd");
11092             buf = gst_buffer_new_and_alloc (len);
11093             gst_buffer_fill (buf, 0, stsd_data, len);
11094             gst_caps_set_simple (entry->caps,
11095                 "codec_data", GST_TYPE_BUFFER, buf, NULL);
11096             gst_buffer_unref (buf);
11097             break;
11098           }
11099           case FOURCC_jpeg:
11100           {
11101             /* https://developer.apple.com/standards/qtff-2001.pdf,
11102              * page 92, "Video Sample Description", under table 3.1 */
11103             GstByteReader br;
11104
11105             const gint compressor_offset =
11106                 16 + 4 + 4 * 3 + 2 * 2 + 2 * 4 + 4 + 2;
11107             const gint min_size = compressor_offset + 32 + 2 + 2;
11108             GNode *jpeg;
11109             guint32 len;
11110             guint16 color_table_id = 0;
11111             gboolean ok;
11112
11113             GST_DEBUG_OBJECT (qtdemux, "found jpeg");
11114
11115             /* recover information on interlaced/progressive */
11116             jpeg = qtdemux_tree_get_child_by_type (stsd, FOURCC_jpeg);
11117             if (!jpeg)
11118               break;
11119
11120             len = QT_UINT32 (jpeg->data);
11121             GST_DEBUG_OBJECT (qtdemux, "Found jpeg: len %u, need %d", len,
11122                 min_size);
11123             if (len >= min_size) {
11124               gst_byte_reader_init (&br, jpeg->data, len);
11125
11126               gst_byte_reader_skip (&br, compressor_offset + 32 + 2);
11127               gst_byte_reader_get_uint16_le (&br, &color_table_id);
11128               if (color_table_id != 0) {
11129                 /* the spec says there can be concatenated chunks in the data, and we want
11130                  * to find one called field. Walk through them. */
11131                 gint offset = min_size;
11132                 while (offset + 8 < len) {
11133                   guint32 size = 0, tag;
11134                   ok = gst_byte_reader_get_uint32_le (&br, &size);
11135                   ok &= gst_byte_reader_get_uint32_le (&br, &tag);
11136                   if (!ok || size < 8) {
11137                     GST_WARNING_OBJECT (qtdemux,
11138                         "Failed to walk optional chunk list");
11139                     break;
11140                   }
11141                   GST_DEBUG_OBJECT (qtdemux,
11142                       "Found optional %4.4s chunk, size %u",
11143                       (const char *) &tag, size);
11144                   if (tag == FOURCC_fiel) {
11145                     guint8 n_fields = 0, ordering = 0;
11146                     gst_byte_reader_get_uint8 (&br, &n_fields);
11147                     gst_byte_reader_get_uint8 (&br, &ordering);
11148                     if (n_fields == 1 || n_fields == 2) {
11149                       GST_DEBUG_OBJECT (qtdemux,
11150                           "Found fiel tag with %u fields, ordering %u",
11151                           n_fields, ordering);
11152                       if (n_fields == 2)
11153                         gst_caps_set_simple (CUR_STREAM (stream)->caps,
11154                             "interlace-mode", G_TYPE_STRING, "interleaved",
11155                             NULL);
11156                     } else {
11157                       GST_WARNING_OBJECT (qtdemux,
11158                           "Found fiel tag with invalid fields (%u)", n_fields);
11159                     }
11160                   }
11161                   offset += size;
11162                 }
11163               } else {
11164                 GST_DEBUG_OBJECT (qtdemux,
11165                     "Color table ID is 0, not trying to get interlacedness");
11166               }
11167             } else {
11168               GST_WARNING_OBJECT (qtdemux,
11169                   "Length of jpeg chunk is too small, not trying to get interlacedness");
11170             }
11171
11172             break;
11173           }
11174           case FOURCC_rle_:
11175           case FOURCC_WRLE:
11176           {
11177             gst_caps_set_simple (entry->caps,
11178                 "depth", G_TYPE_INT, QT_UINT16 (stsd_entry_data + offset + 66),
11179                 NULL);
11180             break;
11181           }
11182           case FOURCC_XiTh:
11183           {
11184             GNode *xith, *xdxt;
11185
11186             GST_DEBUG_OBJECT (qtdemux, "found XiTh");
11187             xith = qtdemux_tree_get_child_by_index (stsd, stsd_index);
11188             if (!xith)
11189               break;
11190
11191             xdxt = qtdemux_tree_get_child_by_type (xith, FOURCC_XdxT);
11192             if (!xdxt)
11193               break;
11194
11195             GST_DEBUG_OBJECT (qtdemux, "found XdxT node");
11196             /* collect the headers and store them in a stream list so that we can
11197              * send them out first */
11198             qtdemux_parse_theora_extension (qtdemux, stream, xdxt);
11199             break;
11200           }
11201           case FOURCC_ovc1:
11202           {
11203             GNode *ovc1;
11204             guint8 *ovc1_data;
11205             guint ovc1_len;
11206             GstBuffer *buf;
11207
11208             GST_DEBUG_OBJECT (qtdemux, "parse ovc1 header");
11209             ovc1 = qtdemux_tree_get_child_by_index (stsd, stsd_index);
11210             if (!ovc1)
11211               break;
11212             ovc1_data = ovc1->data;
11213             ovc1_len = QT_UINT32 (ovc1_data);
11214             if (ovc1_len <= 198) {
11215               GST_WARNING_OBJECT (qtdemux, "Too small ovc1 header, skipping");
11216               break;
11217             }
11218             buf = gst_buffer_new_and_alloc (ovc1_len - 198);
11219             gst_buffer_fill (buf, 0, ovc1_data + 198, ovc1_len - 198);
11220             gst_caps_set_simple (entry->caps,
11221                 "codec_data", GST_TYPE_BUFFER, buf, NULL);
11222             gst_buffer_unref (buf);
11223             break;
11224           }
11225           case FOURCC_vc_1:
11226           {
11227             gint len = QT_UINT32 (stsd_entry_data) - 0x56;
11228             const guint8 *vc1_data = stsd_entry_data + 0x56;
11229
11230             /* find dvc1 */
11231             while (len >= 8) {
11232               gint size;
11233
11234               if (QT_UINT32 (vc1_data) <= len)
11235                 size = QT_UINT32 (vc1_data) - 8;
11236               else
11237                 size = len - 8;
11238
11239               if (size < 1)
11240                 /* No real data, so break out */
11241                 break;
11242
11243               switch (QT_FOURCC (vc1_data + 0x4)) {
11244                 case GST_MAKE_FOURCC ('d', 'v', 'c', '1'):
11245                 {
11246                   GstBuffer *buf;
11247
11248                   GST_DEBUG_OBJECT (qtdemux, "found dvc1 codec_data in stsd");
11249                   buf = gst_buffer_new_and_alloc (size);
11250                   gst_buffer_fill (buf, 0, vc1_data + 8, size);
11251                   gst_caps_set_simple (entry->caps,
11252                       "codec_data", GST_TYPE_BUFFER, buf, NULL);
11253                   gst_buffer_unref (buf);
11254                   break;
11255                 }
11256                 default:
11257                   break;
11258               }
11259               len -= size + 8;
11260               vc1_data += size + 8;
11261             }
11262             break;
11263           }
11264           case FOURCC_av01:
11265           {
11266             gint len = QT_UINT32 (stsd_entry_data) - 0x56;
11267             const guint8 *av1_data = stsd_entry_data + 0x56;
11268
11269             /* find av1C */
11270             while (len >= 0x8) {
11271               gint size;
11272
11273               if (QT_UINT32 (av1_data) <= len)
11274                 size = QT_UINT32 (av1_data) - 0x8;
11275               else
11276                 size = len - 0x8;
11277
11278               if (size < 1)
11279                 /* No real data, so break out */
11280                 break;
11281
11282               switch (QT_FOURCC (av1_data + 0x4)) {
11283                 case FOURCC_av1C:
11284                 {
11285                   /* parse, if found */
11286                   GstBuffer *buf;
11287                   guint8 pres_delay_field;
11288
11289                   GST_DEBUG_OBJECT (qtdemux,
11290                       "found av1C codec_data in stsd of size %d", size);
11291
11292                   /* not enough data, just ignore and hope for the best */
11293                   if (size < 5)
11294                     break;
11295
11296                   /* Content is:
11297                    * 4 bytes: atom length
11298                    * 4 bytes: fourcc
11299                    * 1 byte: version
11300                    * 3 bytes: flags
11301                    * 3 bits: reserved
11302                    * 1 bits:  initial_presentation_delay_present
11303                    * 4 bits: initial_presentation_delay (if present else reserved
11304                    * rest: OBUs.
11305                    */
11306
11307                   if (av1_data[9] != 0) {
11308                     GST_WARNING ("Unknown version %d of av1C box", av1_data[9]);
11309                     break;
11310                   }
11311
11312                   /* We skip initial_presentation_delay* for now */
11313                   pres_delay_field = *(av1_data + 12);
11314                   if (pres_delay_field & (1 << 5)) {
11315                     gst_caps_set_simple (entry->caps,
11316                         "presentation-delay", G_TYPE_INT,
11317                         (gint) (pres_delay_field & 0x0F) + 1, NULL);
11318                   }
11319                   if (size > 5) {
11320                     buf = gst_buffer_new_and_alloc (size - 5);
11321                     GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_HEADER);
11322                     gst_buffer_fill (buf, 0, av1_data + 13, size - 5);
11323                     gst_caps_set_simple (entry->caps,
11324                         "codec_data", GST_TYPE_BUFFER, buf, NULL);
11325                     gst_buffer_unref (buf);
11326                   }
11327                   break;
11328                 }
11329                 default:
11330                   break;
11331               }
11332
11333               len -= size + 8;
11334               av1_data += size + 8;
11335             }
11336
11337             break;
11338           }
11339           default:
11340             break;
11341         }
11342       }
11343
11344       GST_INFO_OBJECT (qtdemux,
11345           "type %" GST_FOURCC_FORMAT " caps %" GST_PTR_FORMAT,
11346           GST_FOURCC_ARGS (fourcc), entry->caps);
11347
11348     } else if (stream->subtype == FOURCC_soun) {
11349       GNode *wave;
11350       int version, samplesize;
11351       guint16 compression_id;
11352       gboolean amrwb = FALSE;
11353
11354       offset = 16;
11355       /* sample description entry (16) + sound sample description v0 (20) */
11356       if (len < 36)
11357         goto corrupt_file;
11358
11359       version = QT_UINT32 (stsd_entry_data + offset);
11360       entry->n_channels = QT_UINT16 (stsd_entry_data + offset + 8);
11361       samplesize = QT_UINT16 (stsd_entry_data + offset + 10);
11362       compression_id = QT_UINT16 (stsd_entry_data + offset + 12);
11363       entry->rate = QT_FP32 (stsd_entry_data + offset + 16);
11364
11365       GST_LOG_OBJECT (qtdemux, "version/rev:      %08x", version);
11366       GST_LOG_OBJECT (qtdemux, "vendor:           %08x",
11367           QT_UINT32 (stsd_entry_data + offset + 4));
11368       GST_LOG_OBJECT (qtdemux, "n_channels:       %d", entry->n_channels);
11369       GST_LOG_OBJECT (qtdemux, "sample_size:      %d", samplesize);
11370       GST_LOG_OBJECT (qtdemux, "compression_id:   %d", compression_id);
11371       GST_LOG_OBJECT (qtdemux, "packet size:      %d",
11372           QT_UINT16 (stsd_entry_data + offset + 14));
11373       GST_LOG_OBJECT (qtdemux, "sample rate:      %g", entry->rate);
11374
11375       if (compression_id == 0xfffe)
11376         entry->sampled = TRUE;
11377
11378       /* first assume uncompressed audio */
11379       entry->bytes_per_sample = samplesize / 8;
11380       entry->samples_per_frame = entry->n_channels;
11381       entry->bytes_per_frame = entry->n_channels * entry->bytes_per_sample;
11382       entry->samples_per_packet = entry->samples_per_frame;
11383       entry->bytes_per_packet = entry->bytes_per_sample;
11384
11385       offset = 36;
11386       switch (fourcc) {
11387           /* Yes, these have to be hard-coded */
11388         case FOURCC_MAC6:
11389         {
11390           entry->samples_per_packet = 6;
11391           entry->bytes_per_packet = 1;
11392           entry->bytes_per_frame = 1 * entry->n_channels;
11393           entry->bytes_per_sample = 1;
11394           entry->samples_per_frame = 6 * entry->n_channels;
11395           break;
11396         }
11397         case FOURCC_MAC3:
11398         {
11399           entry->samples_per_packet = 3;
11400           entry->bytes_per_packet = 1;
11401           entry->bytes_per_frame = 1 * entry->n_channels;
11402           entry->bytes_per_sample = 1;
11403           entry->samples_per_frame = 3 * entry->n_channels;
11404           break;
11405         }
11406         case FOURCC_ima4:
11407         {
11408           entry->samples_per_packet = 64;
11409           entry->bytes_per_packet = 34;
11410           entry->bytes_per_frame = 34 * entry->n_channels;
11411           entry->bytes_per_sample = 2;
11412           entry->samples_per_frame = 64 * entry->n_channels;
11413           break;
11414         }
11415         case FOURCC_ulaw:
11416         case FOURCC_alaw:
11417         {
11418           entry->samples_per_packet = 1;
11419           entry->bytes_per_packet = 1;
11420           entry->bytes_per_frame = 1 * entry->n_channels;
11421           entry->bytes_per_sample = 1;
11422           entry->samples_per_frame = 1 * entry->n_channels;
11423           break;
11424         }
11425         case FOURCC_agsm:
11426         {
11427           entry->samples_per_packet = 160;
11428           entry->bytes_per_packet = 33;
11429           entry->bytes_per_frame = 33 * entry->n_channels;
11430           entry->bytes_per_sample = 2;
11431           entry->samples_per_frame = 160 * entry->n_channels;
11432           break;
11433         }
11434         default:
11435           break;
11436       }
11437
11438       if (version == 0x00010000) {
11439         /* sample description entry (16) + sound sample description v1 (20+16) */
11440         if (len < 52)
11441           goto corrupt_file;
11442
11443         switch (fourcc) {
11444           case FOURCC_twos:
11445           case FOURCC_sowt:
11446           case FOURCC_raw_:
11447           case FOURCC_lpcm:
11448             break;
11449           default:
11450           {
11451             /* only parse extra decoding config for non-pcm audio */
11452             entry->samples_per_packet = QT_UINT32 (stsd_entry_data + offset);
11453             entry->bytes_per_packet = QT_UINT32 (stsd_entry_data + offset + 4);
11454             entry->bytes_per_frame = QT_UINT32 (stsd_entry_data + offset + 8);
11455             entry->bytes_per_sample = QT_UINT32 (stsd_entry_data + offset + 12);
11456
11457             GST_LOG_OBJECT (qtdemux, "samples/packet:   %d",
11458                 entry->samples_per_packet);
11459             GST_LOG_OBJECT (qtdemux, "bytes/packet:     %d",
11460                 entry->bytes_per_packet);
11461             GST_LOG_OBJECT (qtdemux, "bytes/frame:      %d",
11462                 entry->bytes_per_frame);
11463             GST_LOG_OBJECT (qtdemux, "bytes/sample:     %d",
11464                 entry->bytes_per_sample);
11465
11466             if (!entry->sampled && entry->bytes_per_packet) {
11467               entry->samples_per_frame = (entry->bytes_per_frame /
11468                   entry->bytes_per_packet) * entry->samples_per_packet;
11469               GST_LOG_OBJECT (qtdemux, "samples/frame:    %d",
11470                   entry->samples_per_frame);
11471             }
11472             break;
11473           }
11474         }
11475       } else if (version == 0x00020000) {
11476         union
11477         {
11478           gdouble fp;
11479           guint64 val;
11480         } qtfp;
11481
11482         /* sample description entry (16) + sound sample description v2 (56) */
11483         if (len < 72)
11484           goto corrupt_file;
11485
11486         qtfp.val = QT_UINT64 (stsd_entry_data + offset + 4);
11487         entry->rate = qtfp.fp;
11488         entry->n_channels = QT_UINT32 (stsd_entry_data + offset + 12);
11489
11490         GST_LOG_OBJECT (qtdemux, "Sound sample description Version 2");
11491         GST_LOG_OBJECT (qtdemux, "sample rate:        %g", entry->rate);
11492         GST_LOG_OBJECT (qtdemux, "n_channels:         %d", entry->n_channels);
11493         GST_LOG_OBJECT (qtdemux, "bits/channel:       %d",
11494             QT_UINT32 (stsd_entry_data + offset + 20));
11495         GST_LOG_OBJECT (qtdemux, "format flags:       %X",
11496             QT_UINT32 (stsd_entry_data + offset + 24));
11497         GST_LOG_OBJECT (qtdemux, "bytes/packet:       %d",
11498             QT_UINT32 (stsd_entry_data + offset + 28));
11499         GST_LOG_OBJECT (qtdemux, "LPCM frames/packet: %d",
11500             QT_UINT32 (stsd_entry_data + offset + 32));
11501       } else if (version != 0x00000) {
11502         GST_WARNING_OBJECT (qtdemux, "unknown audio STSD version %08x",
11503             version);
11504       }
11505
11506       if (entry->caps)
11507         gst_caps_unref (entry->caps);
11508
11509       entry->caps = qtdemux_audio_caps (qtdemux, stream, entry, fourcc,
11510           stsd_entry_data + 32, len - 16, &codec);
11511
11512       switch (fourcc) {
11513         case FOURCC_in24:
11514         {
11515           GNode *enda;
11516           GNode *in24;
11517
11518           in24 = qtdemux_tree_get_child_by_type (stsd, FOURCC_in24);
11519
11520           enda = qtdemux_tree_get_child_by_type (in24, FOURCC_enda);
11521           if (!enda) {
11522             wave = qtdemux_tree_get_child_by_type (in24, FOURCC_wave);
11523             if (wave)
11524               enda = qtdemux_tree_get_child_by_type (wave, FOURCC_enda);
11525           }
11526           if (enda) {
11527             int enda_value = QT_UINT16 ((guint8 *) enda->data + 8);
11528             gst_caps_set_simple (entry->caps,
11529                 "format", G_TYPE_STRING, (enda_value) ? "S24LE" : "S24BE",
11530                 NULL);
11531           }
11532           break;
11533         }
11534         case FOURCC_owma:
11535         {
11536           const guint8 *owma_data;
11537           const gchar *codec_name = NULL;
11538           guint owma_len;
11539           GstBuffer *buf;
11540           gint version = 1;
11541           /* from http://msdn.microsoft.com/en-us/library/dd757720(VS.85).aspx */
11542           /* FIXME this should also be gst_riff_strf_auds,
11543            * but the latter one is actually missing bits-per-sample :( */
11544           typedef struct
11545           {
11546             gint16 wFormatTag;
11547             gint16 nChannels;
11548             gint32 nSamplesPerSec;
11549             gint32 nAvgBytesPerSec;
11550             gint16 nBlockAlign;
11551             gint16 wBitsPerSample;
11552             gint16 cbSize;
11553           } WAVEFORMATEX;
11554           WAVEFORMATEX *wfex;
11555
11556           GST_DEBUG_OBJECT (qtdemux, "parse owma");
11557           owma_data = stsd_entry_data;
11558           owma_len = QT_UINT32 (owma_data);
11559           if (owma_len <= 54) {
11560             GST_WARNING_OBJECT (qtdemux, "Too small owma header, skipping");
11561             break;
11562           }
11563           wfex = (WAVEFORMATEX *) (owma_data + 36);
11564           buf = gst_buffer_new_and_alloc (owma_len - 54);
11565           gst_buffer_fill (buf, 0, owma_data + 54, owma_len - 54);
11566           if (wfex->wFormatTag == 0x0161) {
11567             codec_name = "Windows Media Audio";
11568             version = 2;
11569           } else if (wfex->wFormatTag == 0x0162) {
11570             codec_name = "Windows Media Audio 9 Pro";
11571             version = 3;
11572           } else if (wfex->wFormatTag == 0x0163) {
11573             codec_name = "Windows Media Audio 9 Lossless";
11574             /* is that correct? gstffmpegcodecmap.c is missing it, but
11575              * fluendo codec seems to support it */
11576             version = 4;
11577           }
11578
11579           gst_caps_set_simple (entry->caps,
11580               "codec_data", GST_TYPE_BUFFER, buf,
11581               "wmaversion", G_TYPE_INT, version,
11582               "block_align", G_TYPE_INT,
11583               GST_READ_UINT16_LE (&wfex->nBlockAlign), "bitrate", G_TYPE_INT,
11584               GST_READ_UINT32_LE (&wfex->nAvgBytesPerSec), "width", G_TYPE_INT,
11585               GST_READ_UINT16_LE (&wfex->wBitsPerSample), "depth", G_TYPE_INT,
11586               GST_READ_UINT16_LE (&wfex->wBitsPerSample), NULL);
11587           gst_buffer_unref (buf);
11588
11589           if (codec_name) {
11590             g_free (codec);
11591             codec = g_strdup (codec_name);
11592           }
11593           break;
11594         }
11595         case FOURCC_wma_:
11596         {
11597           gint len = QT_UINT32 (stsd_entry_data) - offset;
11598           const guint8 *wfex_data = stsd_entry_data + offset;
11599           const gchar *codec_name = NULL;
11600           gint version = 1;
11601           /* from http://msdn.microsoft.com/en-us/library/dd757720(VS.85).aspx */
11602           /* FIXME this should also be gst_riff_strf_auds,
11603            * but the latter one is actually missing bits-per-sample :( */
11604           typedef struct
11605           {
11606             gint16 wFormatTag;
11607             gint16 nChannels;
11608             gint32 nSamplesPerSec;
11609             gint32 nAvgBytesPerSec;
11610             gint16 nBlockAlign;
11611             gint16 wBitsPerSample;
11612             gint16 cbSize;
11613           } WAVEFORMATEX;
11614           WAVEFORMATEX wfex;
11615
11616           /* FIXME: unify with similar wavformatex parsing code above */
11617           GST_DEBUG_OBJECT (qtdemux, "parse wma, looking for wfex");
11618
11619           /* find wfex */
11620           while (len >= 8) {
11621             gint size;
11622
11623             if (QT_UINT32 (wfex_data) <= len)
11624               size = QT_UINT32 (wfex_data) - 8;
11625             else
11626               size = len - 8;
11627
11628             if (size < 1)
11629               /* No real data, so break out */
11630               break;
11631
11632             switch (QT_FOURCC (wfex_data + 4)) {
11633               case GST_MAKE_FOURCC ('w', 'f', 'e', 'x'):
11634               {
11635                 GST_DEBUG_OBJECT (qtdemux, "found wfex in stsd");
11636
11637                 if (size < 8 + 18)
11638                   break;
11639
11640                 wfex.wFormatTag = GST_READ_UINT16_LE (wfex_data + 8 + 0);
11641                 wfex.nChannels = GST_READ_UINT16_LE (wfex_data + 8 + 2);
11642                 wfex.nSamplesPerSec = GST_READ_UINT32_LE (wfex_data + 8 + 4);
11643                 wfex.nAvgBytesPerSec = GST_READ_UINT32_LE (wfex_data + 8 + 8);
11644                 wfex.nBlockAlign = GST_READ_UINT16_LE (wfex_data + 8 + 12);
11645                 wfex.wBitsPerSample = GST_READ_UINT16_LE (wfex_data + 8 + 14);
11646                 wfex.cbSize = GST_READ_UINT16_LE (wfex_data + 8 + 16);
11647
11648                 GST_LOG_OBJECT (qtdemux, "Found wfex box in stsd:");
11649                 GST_LOG_OBJECT (qtdemux, "FormatTag = 0x%04x, Channels = %u, "
11650                     "SamplesPerSec = %u, AvgBytesPerSec = %u, BlockAlign = %u, "
11651                     "BitsPerSample = %u, Size = %u", wfex.wFormatTag,
11652                     wfex.nChannels, wfex.nSamplesPerSec, wfex.nAvgBytesPerSec,
11653                     wfex.nBlockAlign, wfex.wBitsPerSample, wfex.cbSize);
11654
11655                 if (wfex.wFormatTag == 0x0161) {
11656                   codec_name = "Windows Media Audio";
11657                   version = 2;
11658                 } else if (wfex.wFormatTag == 0x0162) {
11659                   codec_name = "Windows Media Audio 9 Pro";
11660                   version = 3;
11661                 } else if (wfex.wFormatTag == 0x0163) {
11662                   codec_name = "Windows Media Audio 9 Lossless";
11663                   /* is that correct? gstffmpegcodecmap.c is missing it, but
11664                    * fluendo codec seems to support it */
11665                   version = 4;
11666                 }
11667
11668                 gst_caps_set_simple (entry->caps,
11669                     "wmaversion", G_TYPE_INT, version,
11670                     "block_align", G_TYPE_INT, wfex.nBlockAlign,
11671                     "bitrate", G_TYPE_INT, wfex.nAvgBytesPerSec,
11672                     "width", G_TYPE_INT, wfex.wBitsPerSample,
11673                     "depth", G_TYPE_INT, wfex.wBitsPerSample, NULL);
11674
11675                 if (size > wfex.cbSize) {
11676                   GstBuffer *buf;
11677
11678                   buf = gst_buffer_new_and_alloc (size - wfex.cbSize);
11679                   gst_buffer_fill (buf, 0, wfex_data + 8 + wfex.cbSize,
11680                       size - wfex.cbSize);
11681                   gst_caps_set_simple (entry->caps,
11682                       "codec_data", GST_TYPE_BUFFER, buf, NULL);
11683                   gst_buffer_unref (buf);
11684                 } else {
11685                   GST_WARNING_OBJECT (qtdemux, "no codec data");
11686                 }
11687
11688                 if (codec_name) {
11689                   g_free (codec);
11690                   codec = g_strdup (codec_name);
11691                 }
11692                 break;
11693               }
11694               default:
11695                 break;
11696             }
11697             len -= size + 8;
11698             wfex_data += size + 8;
11699           }
11700           break;
11701         }
11702         case FOURCC_opus:
11703         {
11704           const guint8 *opus_data;
11705           guint8 *channel_mapping = NULL;
11706           guint32 rate;
11707           guint8 channels;
11708           guint8 channel_mapping_family;
11709           guint8 stream_count;
11710           guint8 coupled_count;
11711           guint8 i;
11712
11713           opus_data = stsd_entry_data;
11714
11715           channels = GST_READ_UINT8 (opus_data + 45);
11716           rate = GST_READ_UINT32_LE (opus_data + 48);
11717           channel_mapping_family = GST_READ_UINT8 (opus_data + 54);
11718           stream_count = GST_READ_UINT8 (opus_data + 55);
11719           coupled_count = GST_READ_UINT8 (opus_data + 56);
11720
11721           if (channels > 0) {
11722             channel_mapping = g_malloc (channels * sizeof (guint8));
11723             for (i = 0; i < channels; i++)
11724               channel_mapping[i] = GST_READ_UINT8 (opus_data + i + 57);
11725           }
11726
11727           entry->caps = gst_codec_utils_opus_create_caps (rate, channels,
11728               channel_mapping_family, stream_count, coupled_count,
11729               channel_mapping);
11730           break;
11731         }
11732         default:
11733           break;
11734       }
11735
11736       if (codec) {
11737         GstStructure *s;
11738         gint bitrate = 0;
11739
11740         gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
11741             GST_TAG_AUDIO_CODEC, codec, NULL);
11742         g_free (codec);
11743         codec = NULL;
11744
11745         /* some bitrate info may have ended up in caps */
11746         s = gst_caps_get_structure (entry->caps, 0);
11747         gst_structure_get_int (s, "bitrate", &bitrate);
11748         if (bitrate > 0)
11749           gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
11750               GST_TAG_BITRATE, bitrate, NULL);
11751       }
11752
11753       mp4a = qtdemux_tree_get_child_by_index (stsd, stsd_index);
11754       if (!stream->protected) {
11755       } else {
11756         if (QTDEMUX_TREE_NODE_FOURCC (mp4v) != FOURCC_encv) {
11757           mp4v = NULL;
11758         }
11759       }
11760       if (stream->protected && fourcc == FOURCC_mp4a) {
11761         if (QTDEMUX_TREE_NODE_FOURCC (mp4a) != FOURCC_enca) {
11762           mp4a = NULL;
11763         }
11764       } else {
11765         if (QTDEMUX_TREE_NODE_FOURCC (mp4a) != FOURCC_mp4a) {
11766           mp4a = NULL;
11767         }
11768       }
11769
11770       wave = NULL;
11771       esds = NULL;
11772       if (mp4a) {
11773         wave = qtdemux_tree_get_child_by_type (mp4a, FOURCC_wave);
11774         if (wave)
11775           esds = qtdemux_tree_get_child_by_type (wave, FOURCC_esds);
11776         if (!esds)
11777           esds = qtdemux_tree_get_child_by_type (mp4a, FOURCC_esds);
11778       }
11779
11780
11781       /* If the fourcc's bottom 16 bits gives 'sm', then the top
11782          16 bits is a byte-swapped wave-style codec identifier,
11783          and we can find a WAVE header internally to a 'wave' atom here.
11784          This can more clearly be thought of as 'ms' as the top 16 bits, and a
11785          codec id as the bottom 16 bits - but byte-swapped to store in QT (which
11786          is big-endian).
11787        */
11788       if ((fourcc & 0xffff) == (('s' << 8) | 'm')) {
11789         if (len < offset + 20) {
11790           GST_WARNING_OBJECT (qtdemux, "No wave atom in MS-style audio");
11791         } else {
11792           guint32 datalen = QT_UINT32 (stsd_entry_data + offset + 16);
11793           const guint8 *data = stsd_entry_data + offset + 16;
11794           GNode *wavenode;
11795           GNode *waveheadernode;
11796
11797           wavenode = g_node_new ((guint8 *) data);
11798           if (qtdemux_parse_node (qtdemux, wavenode, data, datalen)) {
11799             const guint8 *waveheader;
11800             guint32 headerlen;
11801
11802             waveheadernode = qtdemux_tree_get_child_by_type (wavenode, fourcc);
11803             if (waveheadernode) {
11804               waveheader = (const guint8 *) waveheadernode->data;
11805               headerlen = QT_UINT32 (waveheader);
11806
11807               if (headerlen > 8) {
11808                 gst_riff_strf_auds *header = NULL;
11809                 GstBuffer *headerbuf;
11810                 GstBuffer *extra;
11811
11812                 waveheader += 8;
11813                 headerlen -= 8;
11814
11815                 headerbuf = gst_buffer_new_and_alloc (headerlen);
11816                 gst_buffer_fill (headerbuf, 0, waveheader, headerlen);
11817
11818                 if (gst_riff_parse_strf_auds (GST_ELEMENT_CAST (qtdemux),
11819                         headerbuf, &header, &extra)) {
11820                   gst_caps_unref (entry->caps);
11821                   /* FIXME: Need to do something with the channel reorder map */
11822                   entry->caps =
11823                       gst_riff_create_audio_caps (header->format, NULL, header,
11824                       extra, NULL, NULL, NULL);
11825
11826                   if (extra)
11827                     gst_buffer_unref (extra);
11828                   g_free (header);
11829                 }
11830               }
11831             } else
11832               GST_DEBUG ("Didn't find waveheadernode for this codec");
11833           }
11834           g_node_destroy (wavenode);
11835         }
11836       } else if (esds) {
11837         gst_qtdemux_handle_esds (qtdemux, stream, entry, esds,
11838             stream->stream_tags);
11839       } else {
11840         switch (fourcc) {
11841 #if 0
11842             /* FIXME: what is in the chunk? */
11843           case FOURCC_QDMC:
11844           {
11845             gint len = QT_UINT32 (stsd_data);
11846
11847             /* seems to be always = 116 = 0x74 */
11848             break;
11849           }
11850 #endif
11851           case FOURCC_QDM2:
11852           {
11853             gint len = QT_UINT32 (stsd_entry_data);
11854
11855             if (len > 0x3C) {
11856               GstBuffer *buf = gst_buffer_new_and_alloc (len - 0x3C);
11857
11858               gst_buffer_fill (buf, 0, stsd_entry_data + 0x3C, len - 0x3C);
11859               gst_caps_set_simple (entry->caps,
11860                   "codec_data", GST_TYPE_BUFFER, buf, NULL);
11861               gst_buffer_unref (buf);
11862             }
11863             gst_caps_set_simple (entry->caps,
11864                 "samplesize", G_TYPE_INT, samplesize, NULL);
11865             break;
11866           }
11867           case FOURCC_alac:
11868           {
11869             GNode *alac, *wave = NULL;
11870
11871             /* apparently, m4a has this atom appended directly in the stsd entry,
11872              * while mov has it in a wave atom */
11873             alac = qtdemux_tree_get_child_by_type (stsd, FOURCC_alac);
11874             if (alac) {
11875               /* alac now refers to stsd entry atom */
11876               wave = qtdemux_tree_get_child_by_type (alac, FOURCC_wave);
11877               if (wave)
11878                 alac = qtdemux_tree_get_child_by_type (wave, FOURCC_alac);
11879               else
11880                 alac = qtdemux_tree_get_child_by_type (alac, FOURCC_alac);
11881             }
11882             if (alac) {
11883               const guint8 *alac_data = alac->data;
11884               gint len = QT_UINT32 (alac->data);
11885               GstBuffer *buf;
11886
11887               if (len < 36) {
11888                 GST_DEBUG_OBJECT (qtdemux,
11889                     "discarding alac atom with unexpected len %d", len);
11890               } else {
11891                 /* codec-data contains alac atom size and prefix,
11892                  * ffmpeg likes it that way, not quite gst-ish though ...*/
11893                 buf = gst_buffer_new_and_alloc (len);
11894                 gst_buffer_fill (buf, 0, alac->data, len);
11895                 gst_caps_set_simple (entry->caps,
11896                     "codec_data", GST_TYPE_BUFFER, buf, NULL);
11897                 gst_buffer_unref (buf);
11898
11899                 entry->bytes_per_frame = QT_UINT32 (alac_data + 12);
11900                 entry->n_channels = QT_UINT8 (alac_data + 21);
11901                 entry->rate = QT_UINT32 (alac_data + 32);
11902               }
11903             }
11904             gst_caps_set_simple (entry->caps,
11905                 "samplesize", G_TYPE_INT, samplesize, NULL);
11906             break;
11907           }
11908           case FOURCC_fLaC:
11909           {
11910             /* The codingname of the sample entry is 'fLaC' */
11911             GNode *flac = qtdemux_tree_get_child_by_type (stsd, FOURCC_fLaC);
11912
11913             if (flac) {
11914               /* The 'dfLa' box is added to the sample entry to convey
11915                  initializing information for the decoder. */
11916               const GNode *dfla =
11917                   qtdemux_tree_get_child_by_type (flac, FOURCC_dfLa);
11918
11919               if (dfla) {
11920                 const guint32 len = QT_UINT32 (dfla->data);
11921
11922                 /* Must contain at least dfLa box header (12),
11923                  * METADATA_BLOCK_HEADER (4), METADATA_BLOCK_STREAMINFO (34) */
11924                 if (len < 50) {
11925                   GST_DEBUG_OBJECT (qtdemux,
11926                       "discarding dfla atom with unexpected len %d", len);
11927                 } else {
11928                   /* skip dfLa header to get the METADATA_BLOCKs */
11929                   const guint8 *metadata_blocks = (guint8 *) dfla->data + 12;
11930                   const guint32 metadata_blocks_len = len - 12;
11931
11932                   gchar *stream_marker = g_strdup ("fLaC");
11933                   GstBuffer *block = gst_buffer_new_wrapped (stream_marker,
11934                       strlen (stream_marker));
11935
11936                   guint32 index = 0;
11937                   guint32 remainder = 0;
11938                   guint32 block_size = 0;
11939                   gboolean is_last = FALSE;
11940
11941                   GValue array = G_VALUE_INIT;
11942                   GValue value = G_VALUE_INIT;
11943
11944                   g_value_init (&array, GST_TYPE_ARRAY);
11945                   g_value_init (&value, GST_TYPE_BUFFER);
11946
11947                   gst_value_set_buffer (&value, block);
11948                   gst_value_array_append_value (&array, &value);
11949                   g_value_reset (&value);
11950
11951                   gst_buffer_unref (block);
11952
11953                   /* check there's at least one METADATA_BLOCK_HEADER's worth
11954                    * of data, and we haven't already finished parsing */
11955                   while (!is_last && ((index + 3) < metadata_blocks_len)) {
11956                     remainder = metadata_blocks_len - index;
11957
11958                     /* add the METADATA_BLOCK_HEADER size to the signalled size */
11959                     block_size = 4 +
11960                         (metadata_blocks[index + 1] << 16) +
11961                         (metadata_blocks[index + 2] << 8) +
11962                         metadata_blocks[index + 3];
11963
11964                     /* be careful not to read off end of box */
11965                     if (block_size > remainder) {
11966                       break;
11967                     }
11968
11969                     is_last = metadata_blocks[index] >> 7;
11970
11971                     block = gst_buffer_new_and_alloc (block_size);
11972
11973                     gst_buffer_fill (block, 0, &metadata_blocks[index],
11974                         block_size);
11975
11976                     gst_value_set_buffer (&value, block);
11977                     gst_value_array_append_value (&array, &value);
11978                     g_value_reset (&value);
11979
11980                     gst_buffer_unref (block);
11981
11982                     index += block_size;
11983                   }
11984
11985                   /* only append the metadata if we successfully read all of it */
11986                   if (is_last) {
11987                     gst_structure_set_value (gst_caps_get_structure (CUR_STREAM
11988                             (stream)->caps, 0), "streamheader", &array);
11989                   } else {
11990                     GST_WARNING_OBJECT (qtdemux,
11991                         "discarding all METADATA_BLOCKs due to invalid "
11992                         "block_size %d at idx %d, rem %d", block_size, index,
11993                         remainder);
11994                   }
11995
11996                   g_value_unset (&value);
11997                   g_value_unset (&array);
11998
11999                   /* The sample rate obtained from the stsd may not be accurate
12000                    * since it cannot represent rates greater than 65535Hz, so
12001                    * override that value with the sample rate from the
12002                    * METADATA_BLOCK_STREAMINFO block */
12003                   CUR_STREAM (stream)->rate =
12004                       (QT_UINT32 (metadata_blocks + 14) >> 12) & 0xFFFFF;
12005                 }
12006               }
12007             }
12008             break;
12009           }
12010           case FOURCC_sawb:
12011             /* Fallthrough! */
12012             amrwb = TRUE;
12013           case FOURCC_samr:
12014           {
12015             gint len = QT_UINT32 (stsd_entry_data);
12016
12017             if (len > 0x24) {
12018               GstBuffer *buf = gst_buffer_new_and_alloc (len - 0x24);
12019               guint bitrate;
12020
12021               gst_buffer_fill (buf, 0, stsd_entry_data + 0x24, len - 0x24);
12022
12023               /* If we have enough data, let's try to get the 'damr' atom. See
12024                * the 3GPP container spec (26.244) for more details. */
12025               if ((len - 0x34) > 8 &&
12026                   (bitrate = qtdemux_parse_amr_bitrate (buf, amrwb))) {
12027                 gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
12028                     GST_TAG_MAXIMUM_BITRATE, bitrate, NULL);
12029               }
12030
12031               gst_caps_set_simple (entry->caps,
12032                   "codec_data", GST_TYPE_BUFFER, buf, NULL);
12033               gst_buffer_unref (buf);
12034             }
12035             break;
12036           }
12037           case FOURCC_mp4a:
12038           {
12039             /* mp4a atom withtout ESDS; Attempt to build codec data from atom */
12040             gint len = QT_UINT32 (stsd_entry_data);
12041
12042             if (len >= 34) {
12043               guint16 sound_version = QT_UINT16 (stsd_entry_data + 16);
12044
12045               if (sound_version == 1) {
12046                 guint16 channels = QT_UINT16 (stsd_entry_data + 24);
12047                 guint32 time_scale = QT_UINT32 (stsd_entry_data + 30);
12048                 guint8 codec_data[2];
12049                 GstBuffer *buf;
12050                 gint profile = 2;       /* FIXME: Can this be determined somehow? There doesn't seem to be anything in mp4a atom that specifis compression */
12051
12052                 gint sample_rate_index =
12053                     gst_codec_utils_aac_get_index_from_sample_rate (time_scale);
12054
12055                 /* build AAC codec data */
12056                 codec_data[0] = profile << 3;
12057                 codec_data[0] |= ((sample_rate_index >> 1) & 0x7);
12058                 codec_data[1] = (sample_rate_index & 0x01) << 7;
12059                 codec_data[1] |= (channels & 0xF) << 3;
12060
12061                 buf = gst_buffer_new_and_alloc (2);
12062                 gst_buffer_fill (buf, 0, codec_data, 2);
12063                 gst_caps_set_simple (entry->caps,
12064                     "codec_data", GST_TYPE_BUFFER, buf, NULL);
12065                 gst_buffer_unref (buf);
12066               }
12067             }
12068             break;
12069           }
12070           case FOURCC_lpcm:
12071             /* Fully handled elsewhere */
12072             break;
12073           default:
12074             GST_INFO_OBJECT (qtdemux,
12075                 "unhandled type %" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (fourcc));
12076             break;
12077         }
12078       }
12079       GST_INFO_OBJECT (qtdemux,
12080           "type %" GST_FOURCC_FORMAT " caps %" GST_PTR_FORMAT,
12081           GST_FOURCC_ARGS (fourcc), entry->caps);
12082
12083     } else if (stream->subtype == FOURCC_strm) {
12084       if (fourcc == FOURCC_rtsp) {
12085         stream->redirect_uri = qtdemux_get_rtsp_uri_from_hndl (qtdemux, minf);
12086       } else {
12087         GST_INFO_OBJECT (qtdemux, "unhandled stream type %" GST_FOURCC_FORMAT,
12088             GST_FOURCC_ARGS (fourcc));
12089         goto unknown_stream;
12090       }
12091       entry->sampled = TRUE;
12092     } else if (stream->subtype == FOURCC_subp || stream->subtype == FOURCC_text
12093         || stream->subtype == FOURCC_sbtl || stream->subtype == FOURCC_subt
12094         || stream->subtype == FOURCC_clcp) {
12095
12096       entry->sampled = TRUE;
12097       entry->sparse = TRUE;
12098
12099       entry->caps =
12100           qtdemux_sub_caps (qtdemux, stream, entry, fourcc, stsd_entry_data,
12101           &codec);
12102       if (codec) {
12103         gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
12104             GST_TAG_SUBTITLE_CODEC, codec, NULL);
12105         g_free (codec);
12106         codec = NULL;
12107       }
12108
12109       /* hunt for sort-of codec data */
12110       switch (fourcc) {
12111         case FOURCC_mp4s:
12112         {
12113           GNode *mp4s = NULL;
12114           GNode *esds = NULL;
12115
12116           /* look for palette in a stsd->mp4s->esds sub-atom */
12117           mp4s = qtdemux_tree_get_child_by_type (stsd, FOURCC_mp4s);
12118           if (mp4s)
12119             esds = qtdemux_tree_get_child_by_type (mp4s, FOURCC_esds);
12120           if (esds == NULL) {
12121             /* Invalid STSD */
12122             GST_LOG_OBJECT (qtdemux, "Skipping invalid stsd: no esds child");
12123             break;
12124           }
12125
12126           gst_qtdemux_handle_esds (qtdemux, stream, entry, esds,
12127               stream->stream_tags);
12128           break;
12129         }
12130         default:
12131           GST_INFO_OBJECT (qtdemux,
12132               "unhandled type %" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (fourcc));
12133           break;
12134       }
12135       GST_INFO_OBJECT (qtdemux,
12136           "type %" GST_FOURCC_FORMAT " caps %" GST_PTR_FORMAT,
12137           GST_FOURCC_ARGS (fourcc), entry->caps);
12138     } else {
12139       /* everything in 1 sample */
12140       entry->sampled = TRUE;
12141
12142       entry->caps =
12143           qtdemux_generic_caps (qtdemux, stream, entry, fourcc, stsd_entry_data,
12144           &codec);
12145
12146       if (entry->caps == NULL)
12147         goto unknown_stream;
12148
12149       if (codec) {
12150         gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
12151             GST_TAG_SUBTITLE_CODEC, codec, NULL);
12152         g_free (codec);
12153         codec = NULL;
12154       }
12155     }
12156
12157     /* promote to sampled format */
12158     if (entry->fourcc == FOURCC_samr) {
12159       /* force mono 8000 Hz for AMR */
12160       entry->sampled = TRUE;
12161       entry->n_channels = 1;
12162       entry->rate = 8000;
12163     } else if (entry->fourcc == FOURCC_sawb) {
12164       /* force mono 16000 Hz for AMR-WB */
12165       entry->sampled = TRUE;
12166       entry->n_channels = 1;
12167       entry->rate = 16000;
12168     } else if (entry->fourcc == FOURCC_mp4a) {
12169       entry->sampled = TRUE;
12170     }
12171
12172
12173     stsd_entry_data += len;
12174     remaining_stsd_len -= len;
12175
12176   }
12177
12178   /* collect sample information */
12179   if (!qtdemux_stbl_init (qtdemux, stream, stbl))
12180     goto samples_failed;
12181
12182   if (qtdemux->fragmented) {
12183     guint64 offset;
12184
12185     /* need all moov samples as basis; probably not many if any at all */
12186     /* prevent moof parsing taking of at this time */
12187     offset = qtdemux->moof_offset;
12188     qtdemux->moof_offset = 0;
12189     if (stream->n_samples &&
12190         !qtdemux_parse_samples (qtdemux, stream, stream->n_samples - 1)) {
12191       qtdemux->moof_offset = offset;
12192       goto samples_failed;
12193     }
12194     qtdemux->moof_offset = 0;
12195     /* movie duration more reliable in this case (e.g. mehd) */
12196     if (qtdemux->segment.duration &&
12197         GST_CLOCK_TIME_IS_VALID (qtdemux->segment.duration))
12198       stream->duration =
12199           GSTTIME_TO_QTSTREAMTIME (stream, qtdemux->segment.duration);
12200   }
12201
12202   /* configure segments */
12203   if (!qtdemux_parse_segments (qtdemux, stream, trak))
12204     goto segments_failed;
12205
12206   /* add some language tag, if useful */
12207   if (stream->lang_id[0] != '\0' && strcmp (stream->lang_id, "unk") &&
12208       strcmp (stream->lang_id, "und")) {
12209     const gchar *lang_code;
12210
12211     /* convert ISO 639-2 code to ISO 639-1 */
12212     lang_code = gst_tag_get_language_code (stream->lang_id);
12213     gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
12214         GST_TAG_LANGUAGE_CODE, (lang_code) ? lang_code : stream->lang_id, NULL);
12215   }
12216
12217   /* Check for UDTA tags */
12218   if ((udta = qtdemux_tree_get_child_by_type (trak, FOURCC_udta))) {
12219     qtdemux_parse_udta (qtdemux, stream->stream_tags, udta);
12220   }
12221
12222   /* Insert and sort new stream in track-id order.
12223    * This will help in comparing old/new streams during stream update check */
12224   qtdemux->active_streams =
12225       g_list_insert_sorted (qtdemux->active_streams, stream,
12226       (GCompareFunc) qtdemux_track_id_compare_func);
12227   qtdemux->n_streams++;
12228   GST_DEBUG_OBJECT (qtdemux, "n_streams is now %d", qtdemux->n_streams);
12229
12230   return TRUE;
12231
12232 /* ERRORS */
12233 corrupt_file:
12234   {
12235     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
12236         (_("This file is corrupt and cannot be played.")), (NULL));
12237     if (stream)
12238       gst_qtdemux_stream_free (stream);
12239     return FALSE;
12240   }
12241 error_encrypted:
12242   {
12243     GST_ELEMENT_ERROR (qtdemux, STREAM, DECRYPT, (NULL), (NULL));
12244     gst_qtdemux_stream_free (stream);
12245     return FALSE;
12246   }
12247 samples_failed:
12248 segments_failed:
12249   {
12250     /* we posted an error already */
12251     /* free stbl sub-atoms */
12252     gst_qtdemux_stbl_free (stream);
12253     gst_qtdemux_stream_free (stream);
12254     return FALSE;
12255   }
12256 existing_stream:
12257   {
12258     GST_INFO_OBJECT (qtdemux, "stream with track id %i already exists",
12259         track_id);
12260     return TRUE;
12261   }
12262 unknown_stream:
12263   {
12264     GST_INFO_OBJECT (qtdemux, "unknown subtype %" GST_FOURCC_FORMAT,
12265         GST_FOURCC_ARGS (stream->subtype));
12266     gst_qtdemux_stream_free (stream);
12267     return TRUE;
12268   }
12269 }
12270
12271 /* If we can estimate the overall bitrate, and don't have information about the
12272  * stream bitrate for exactly one stream, this guesses the stream bitrate as
12273  * the overall bitrate minus the sum of the bitrates of all other streams. This
12274  * should be useful for the common case where we have one audio and one video
12275  * stream and can estimate the bitrate of one, but not the other. */
12276 static void
12277 gst_qtdemux_guess_bitrate (GstQTDemux * qtdemux)
12278 {
12279   QtDemuxStream *stream = NULL;
12280   gint64 size, sys_bitrate, sum_bitrate = 0;
12281   GstClockTime duration;
12282   guint bitrate;
12283   GList *iter;
12284
12285   if (qtdemux->fragmented)
12286     return;
12287
12288   GST_DEBUG_OBJECT (qtdemux, "Looking for streams with unknown bitrate");
12289
12290   if (!gst_pad_peer_query_duration (qtdemux->sinkpad, GST_FORMAT_BYTES, &size)
12291       || size <= 0) {
12292     GST_DEBUG_OBJECT (qtdemux,
12293         "Size in bytes of the stream not known - bailing");
12294     return;
12295   }
12296
12297   /* Subtract the header size */
12298   GST_DEBUG_OBJECT (qtdemux, "Total size %" G_GINT64_FORMAT ", header size %u",
12299       size, qtdemux->header_size);
12300
12301   if (size < qtdemux->header_size)
12302     return;
12303
12304   size = size - qtdemux->header_size;
12305
12306   if (!gst_qtdemux_get_duration (qtdemux, &duration)) {
12307     GST_DEBUG_OBJECT (qtdemux, "Stream duration not known - bailing");
12308     return;
12309   }
12310
12311   for (iter = qtdemux->active_streams; iter; iter = g_list_next (iter)) {
12312     QtDemuxStream *str = QTDEMUX_STREAM (iter->data);
12313     switch (str->subtype) {
12314       case FOURCC_soun:
12315       case FOURCC_vide:
12316         GST_DEBUG_OBJECT (qtdemux, "checking bitrate for %" GST_PTR_FORMAT,
12317             CUR_STREAM (str)->caps);
12318         /* retrieve bitrate, prefer avg then max */
12319         bitrate = 0;
12320         if (str->stream_tags) {
12321           if (gst_tag_list_get_uint (str->stream_tags,
12322                   GST_TAG_MAXIMUM_BITRATE, &bitrate))
12323             GST_DEBUG_OBJECT (qtdemux, "max-bitrate: %u", bitrate);
12324           if (gst_tag_list_get_uint (str->stream_tags,
12325                   GST_TAG_NOMINAL_BITRATE, &bitrate))
12326             GST_DEBUG_OBJECT (qtdemux, "nominal-bitrate: %u", bitrate);
12327           if (gst_tag_list_get_uint (str->stream_tags,
12328                   GST_TAG_BITRATE, &bitrate))
12329             GST_DEBUG_OBJECT (qtdemux, "bitrate: %u", bitrate);
12330         }
12331         if (bitrate)
12332           sum_bitrate += bitrate;
12333         else {
12334           if (stream) {
12335             GST_DEBUG_OBJECT (qtdemux,
12336                 ">1 stream with unknown bitrate - bailing");
12337             return;
12338           } else
12339             stream = str;
12340         }
12341
12342       default:
12343         /* For other subtypes, we assume no significant impact on bitrate */
12344         break;
12345     }
12346   }
12347
12348   if (!stream) {
12349     GST_DEBUG_OBJECT (qtdemux, "All stream bitrates are known");
12350     return;
12351   }
12352
12353   sys_bitrate = gst_util_uint64_scale (size, GST_SECOND * 8, duration);
12354
12355   if (sys_bitrate < sum_bitrate) {
12356     /* This can happen, since sum_bitrate might be derived from maximum
12357      * bitrates and not average bitrates */
12358     GST_DEBUG_OBJECT (qtdemux,
12359         "System bitrate less than sum bitrate - bailing");
12360     return;
12361   }
12362
12363   bitrate = sys_bitrate - sum_bitrate;
12364   GST_DEBUG_OBJECT (qtdemux, "System bitrate = %" G_GINT64_FORMAT
12365       ", Stream bitrate = %u", sys_bitrate, bitrate);
12366
12367   if (!stream->stream_tags)
12368     stream->stream_tags = gst_tag_list_new_empty ();
12369   else
12370     stream->stream_tags = gst_tag_list_make_writable (stream->stream_tags);
12371
12372   gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
12373       GST_TAG_BITRATE, bitrate, NULL);
12374 }
12375
12376 static GstFlowReturn
12377 qtdemux_prepare_streams (GstQTDemux * qtdemux)
12378 {
12379   GstFlowReturn ret = GST_FLOW_OK;
12380   GList *iter, *next;
12381
12382   GST_DEBUG_OBJECT (qtdemux, "prepare streams");
12383
12384   for (iter = qtdemux->active_streams; ret == GST_FLOW_OK && iter; iter = next) {
12385     QtDemuxStream *stream = QTDEMUX_STREAM (iter->data);
12386     guint32 sample_num = 0;
12387
12388     next = iter->next;
12389
12390     GST_DEBUG_OBJECT (qtdemux, "track-id %u, fourcc %" GST_FOURCC_FORMAT,
12391         stream->track_id, GST_FOURCC_ARGS (CUR_STREAM (stream)->fourcc));
12392
12393     if (qtdemux->fragmented) {
12394       /* need all moov samples first */
12395       GST_OBJECT_LOCK (qtdemux);
12396       while (stream->n_samples == 0)
12397         if ((ret = qtdemux_add_fragmented_samples (qtdemux)) != GST_FLOW_OK)
12398           break;
12399       GST_OBJECT_UNLOCK (qtdemux);
12400     } else {
12401       /* discard any stray moof */
12402       qtdemux->moof_offset = 0;
12403     }
12404
12405     /* prepare braking */
12406     if (ret != GST_FLOW_ERROR)
12407       ret = GST_FLOW_OK;
12408
12409     /* in pull mode, we should have parsed some sample info by now;
12410      * and quite some code will not handle no samples.
12411      * in push mode, we'll just have to deal with it */
12412     if (G_UNLIKELY (qtdemux->pullbased && !stream->n_samples)) {
12413       GST_DEBUG_OBJECT (qtdemux, "no samples for stream; discarding");
12414       gst_qtdemux_remove_stream (qtdemux, stream);
12415       continue;
12416     } else if (stream->track_id == qtdemux->chapters_track_id &&
12417         (stream->subtype == FOURCC_text || stream->subtype == FOURCC_sbtl)) {
12418       /* TODO - parse chapters track and expose it as GstToc; For now just ignore it
12419          so that it doesn't look like a subtitle track */
12420       gst_qtdemux_remove_stream (qtdemux, stream);
12421       continue;
12422     }
12423
12424     /* parse the initial sample for use in setting the frame rate cap */
12425     while (sample_num == 0 && sample_num < stream->n_samples) {
12426       if (!qtdemux_parse_samples (qtdemux, stream, sample_num))
12427         break;
12428       ++sample_num;
12429     }
12430   }
12431
12432   return ret;
12433 }
12434
12435 static GList *
12436 _stream_in_list (GList * list, QtDemuxStream * stream)
12437 {
12438   GList *iter;
12439
12440   for (iter = list; iter; iter = g_list_next (iter)) {
12441     QtDemuxStream *tmp = QTDEMUX_STREAM (iter->data);
12442     if (!g_strcmp0 (tmp->stream_id, stream->stream_id))
12443       return iter;
12444   }
12445
12446   return NULL;
12447 }
12448
12449 static gboolean
12450 qtdemux_is_streams_update (GstQTDemux * qtdemux)
12451 {
12452   GList *new, *old;
12453
12454   if (!qtdemux->active_streams)
12455     return FALSE;
12456
12457   /* streams in list are sorted in track-id order */
12458   for (new = qtdemux->active_streams, old = qtdemux->old_streams; new && old;
12459       new = g_list_next (new), old = g_list_next (old)) {
12460
12461     /* Different stream-id, updated */
12462     if (g_strcmp0 (QTDEMUX_STREAM (new->data)->stream_id,
12463             QTDEMUX_STREAM (old->data)->stream_id))
12464       return TRUE;
12465   }
12466
12467   /* Different length, updated */
12468   if (new != NULL || old != NULL)
12469     return TRUE;
12470
12471   return FALSE;
12472 }
12473
12474 static gboolean
12475 qtdemux_reuse_and_configure_stream (GstQTDemux * qtdemux,
12476     QtDemuxStream * oldstream, QtDemuxStream * newstream)
12477 {
12478   /* Connect old stream's srcpad to new stream */
12479   newstream->pad = oldstream->pad;
12480   oldstream->pad = NULL;
12481
12482   /* unset new_stream to prevent stream-start event */
12483   newstream->new_stream = FALSE;
12484
12485   return gst_qtdemux_configure_stream (qtdemux, newstream);
12486 }
12487
12488 static gboolean
12489 qtdemux_update_streams (GstQTDemux * qtdemux)
12490 {
12491   GList *iter, *next;
12492   g_assert (qtdemux->streams_aware);
12493
12494   /* At below, figure out which stream in active_streams has identical stream-id
12495    * with that of in old_streams. If there is matching stream-id,
12496    * corresponding newstream will not be exposed again,
12497    * but demux will reuse srcpad of matched old stream
12498    *
12499    * active_streams : newly created streams from the latest moov
12500    * old_streams : existing streams (belong to previous moov)
12501    */
12502
12503   /* Count n_streams again */
12504   qtdemux->n_streams = 0;
12505
12506   for (iter = qtdemux->active_streams; iter; iter = next) {
12507     GList *tmp;
12508     QtDemuxStream *stream = QTDEMUX_STREAM (iter->data);
12509
12510     next = iter->next;
12511
12512     GST_DEBUG_OBJECT (qtdemux, "track-id %u, fourcc %" GST_FOURCC_FORMAT,
12513         stream->track_id, GST_FOURCC_ARGS (CUR_STREAM (stream)->fourcc));
12514
12515     qtdemux->n_streams++;
12516
12517     if ((tmp = _stream_in_list (qtdemux->old_streams, stream)) != NULL
12518         && QTDEMUX_STREAM (tmp->data)->pad) {
12519       QtDemuxStream *oldstream = QTDEMUX_STREAM (tmp->data);
12520
12521       GST_DEBUG_OBJECT (qtdemux, "Reuse track-id %d", oldstream->track_id);
12522
12523       if (!qtdemux_reuse_and_configure_stream (qtdemux, oldstream, stream))
12524         return FALSE;
12525
12526       qtdemux->old_streams = g_list_remove (qtdemux->old_streams, oldstream);
12527       gst_qtdemux_stream_free (oldstream);
12528     } else {
12529       GstTagList *list;
12530
12531       /* now we have all info and can expose */
12532       list = stream->stream_tags;
12533       stream->stream_tags = NULL;
12534       if (!gst_qtdemux_add_stream (qtdemux, stream, list))
12535         return FALSE;
12536     }
12537   }
12538
12539   return TRUE;
12540 }
12541
12542 /* Must be called with expose lock */
12543 static GstFlowReturn
12544 qtdemux_expose_streams (GstQTDemux * qtdemux)
12545 {
12546   GList *iter, *next;
12547
12548   GST_DEBUG_OBJECT (qtdemux, "exposing streams");
12549
12550   if (!qtdemux_is_streams_update (qtdemux)) {
12551     GList *new, *old;
12552
12553     GST_DEBUG_OBJECT (qtdemux, "Reuse all streams");
12554     for (new = qtdemux->active_streams, old = qtdemux->old_streams; new && old;
12555         new = g_list_next (new), old = g_list_next (old)) {
12556       if (!qtdemux_reuse_and_configure_stream (qtdemux,
12557               QTDEMUX_STREAM (old->data), QTDEMUX_STREAM (new->data)))
12558         return GST_FLOW_ERROR;
12559     }
12560
12561     g_list_free_full (qtdemux->old_streams,
12562         (GDestroyNotify) gst_qtdemux_stream_free);
12563     qtdemux->old_streams = NULL;
12564
12565     return GST_FLOW_OK;
12566   }
12567
12568   if (qtdemux->streams_aware) {
12569     if (!qtdemux_update_streams (qtdemux))
12570       return GST_FLOW_ERROR;
12571   } else {
12572     for (iter = qtdemux->active_streams; iter; iter = g_list_next (iter)) {
12573       QtDemuxStream *stream = QTDEMUX_STREAM (iter->data);
12574       GstTagList *list;
12575
12576       /* now we have all info and can expose */
12577       list = stream->stream_tags;
12578       stream->stream_tags = NULL;
12579       if (!gst_qtdemux_add_stream (qtdemux, stream, list))
12580         return GST_FLOW_ERROR;
12581
12582     }
12583   }
12584
12585   gst_qtdemux_guess_bitrate (qtdemux);
12586
12587   gst_element_no_more_pads (GST_ELEMENT_CAST (qtdemux));
12588
12589   /* If we have still old_streams, it's no more used stream */
12590   for (iter = qtdemux->old_streams; iter; iter = next) {
12591     QtDemuxStream *stream = QTDEMUX_STREAM (iter->data);
12592     next = g_list_next (iter);
12593
12594     if (stream->pad) {
12595       GstEvent *event;
12596
12597       event = gst_event_new_eos ();
12598       if (qtdemux->segment_seqnum)
12599         gst_event_set_seqnum (event, qtdemux->segment_seqnum);
12600
12601       gst_pad_push_event (stream->pad, event);
12602     }
12603
12604     qtdemux->old_streams = g_list_remove (qtdemux->old_streams, stream);
12605     gst_qtdemux_stream_free (stream);
12606   }
12607
12608   /* check if we should post a redirect in case there is a single trak
12609    * and it is a redirecting trak */
12610   if (qtdemux->n_streams == 1 &&
12611       QTDEMUX_FIRST_STREAM (qtdemux)->redirect_uri != NULL) {
12612     GstMessage *m;
12613
12614     GST_INFO_OBJECT (qtdemux, "Issuing a redirect due to a single track with "
12615         "an external content");
12616     m = gst_message_new_element (GST_OBJECT_CAST (qtdemux),
12617         gst_structure_new ("redirect",
12618             "new-location", G_TYPE_STRING,
12619             QTDEMUX_FIRST_STREAM (qtdemux)->redirect_uri, NULL));
12620     gst_element_post_message (GST_ELEMENT_CAST (qtdemux), m);
12621     qtdemux->posted_redirect = TRUE;
12622   }
12623
12624   for (iter = qtdemux->active_streams; iter; iter = g_list_next (iter)) {
12625     qtdemux_do_allocation (QTDEMUX_STREAM (iter->data), qtdemux);
12626   }
12627
12628   qtdemux->need_segment = TRUE;
12629
12630   qtdemux->exposed = TRUE;
12631   return GST_FLOW_OK;
12632 }
12633
12634 /* check if major or compatible brand is 3GP */
12635 static inline gboolean
12636 qtdemux_is_brand_3gp (GstQTDemux * qtdemux, gboolean major)
12637 {
12638   if (major) {
12639     return ((qtdemux->major_brand & GST_MAKE_FOURCC (255, 255, 0, 0)) ==
12640         FOURCC_3g__);
12641   } else if (qtdemux->comp_brands != NULL) {
12642     GstMapInfo map;
12643     guint8 *data;
12644     gsize size;
12645     gboolean res = FALSE;
12646
12647     gst_buffer_map (qtdemux->comp_brands, &map, GST_MAP_READ);
12648     data = map.data;
12649     size = map.size;
12650     while (size >= 4) {
12651       res = res || ((QT_FOURCC (data) & GST_MAKE_FOURCC (255, 255, 0, 0)) ==
12652           FOURCC_3g__);
12653       data += 4;
12654       size -= 4;
12655     }
12656     gst_buffer_unmap (qtdemux->comp_brands, &map);
12657     return res;
12658   } else {
12659     return FALSE;
12660   }
12661 }
12662
12663 /* check if tag is a spec'ed 3GP tag keyword storing a string */
12664 static inline gboolean
12665 qtdemux_is_string_tag_3gp (GstQTDemux * qtdemux, guint32 fourcc)
12666 {
12667   return fourcc == FOURCC_cprt || fourcc == FOURCC_gnre || fourcc == FOURCC_titl
12668       || fourcc == FOURCC_dscp || fourcc == FOURCC_perf || fourcc == FOURCC_auth
12669       || fourcc == FOURCC_albm;
12670 }
12671
12672 static void
12673 qtdemux_tag_add_location (GstQTDemux * qtdemux, GstTagList * taglist,
12674     const char *tag, const char *dummy, GNode * node)
12675 {
12676   const gchar *env_vars[] = { "GST_QT_TAG_ENCODING", "GST_TAG_ENCODING", NULL };
12677   int offset;
12678   char *name;
12679   gchar *data;
12680   gdouble longitude, latitude, altitude;
12681   gint len;
12682
12683   len = QT_UINT32 (node->data);
12684   if (len <= 14)
12685     goto short_read;
12686
12687   data = node->data;
12688   offset = 14;
12689
12690   /* TODO: language code skipped */
12691
12692   name = gst_tag_freeform_string_to_utf8 (data + offset, -1, env_vars);
12693
12694   if (!name) {
12695     /* do not alarm in trivial case, but bail out otherwise */
12696     if (*(data + offset) != 0) {
12697       GST_DEBUG_OBJECT (qtdemux, "failed to convert %s tag to UTF-8, "
12698           "giving up", tag);
12699     }
12700   } else {
12701     gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE,
12702         GST_TAG_GEO_LOCATION_NAME, name, NULL);
12703     offset += strlen (name);
12704     g_free (name);
12705   }
12706
12707   if (len < offset + 2 + 4 + 4 + 4)
12708     goto short_read;
12709
12710   /* +1 +1 = skip null-terminator and location role byte */
12711   offset += 1 + 1;
12712   /* table in spec says unsigned, semantics say negative has meaning ... */
12713   longitude = QT_SFP32 (data + offset);
12714
12715   offset += 4;
12716   latitude = QT_SFP32 (data + offset);
12717
12718   offset += 4;
12719   altitude = QT_SFP32 (data + offset);
12720
12721   /* one invalid means all are invalid */
12722   if (longitude >= -180.0 && longitude <= 180.0 &&
12723       latitude >= -90.0 && latitude <= 90.0) {
12724     gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE,
12725         GST_TAG_GEO_LOCATION_LATITUDE, latitude,
12726         GST_TAG_GEO_LOCATION_LONGITUDE, longitude,
12727         GST_TAG_GEO_LOCATION_ELEVATION, altitude, NULL);
12728   }
12729
12730   /* TODO: no GST_TAG_, so astronomical body and additional notes skipped */
12731
12732   return;
12733
12734   /* ERRORS */
12735 short_read:
12736   {
12737     GST_DEBUG_OBJECT (qtdemux, "short read parsing 3GP location");
12738     return;
12739   }
12740 }
12741
12742
12743 static void
12744 qtdemux_tag_add_year (GstQTDemux * qtdemux, GstTagList * taglist,
12745     const char *tag, const char *dummy, GNode * node)
12746 {
12747   guint16 y;
12748   GDate *date;
12749   gint len;
12750
12751   len = QT_UINT32 (node->data);
12752   if (len < 14)
12753     return;
12754
12755   y = QT_UINT16 ((guint8 *) node->data + 12);
12756   if (y == 0) {
12757     GST_DEBUG_OBJECT (qtdemux, "year: %u is not a valid year", y);
12758     return;
12759   }
12760   GST_DEBUG_OBJECT (qtdemux, "year: %u", y);
12761
12762   date = g_date_new_dmy (1, 1, y);
12763   gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag, date, NULL);
12764   g_date_free (date);
12765 }
12766
12767 static void
12768 qtdemux_tag_add_classification (GstQTDemux * qtdemux, GstTagList * taglist,
12769     const char *tag, const char *dummy, GNode * node)
12770 {
12771   int offset;
12772   char *tag_str = NULL;
12773   guint8 *entity;
12774   guint16 table;
12775   gint len;
12776
12777   len = QT_UINT32 (node->data);
12778   if (len <= 20)
12779     goto short_read;
12780
12781   offset = 12;
12782   entity = (guint8 *) node->data + offset;
12783   if (entity[0] == 0 || entity[1] == 0 || entity[2] == 0 || entity[3] == 0) {
12784     GST_DEBUG_OBJECT (qtdemux,
12785         "classification info: %c%c%c%c invalid classification entity",
12786         entity[0], entity[1], entity[2], entity[3]);
12787     return;
12788   }
12789
12790   offset += 4;
12791   table = QT_UINT16 ((guint8 *) node->data + offset);
12792
12793   /* Language code skipped */
12794
12795   offset += 4;
12796
12797   /* Tag format: "XXXX://Y[YYYY]/classification info string"
12798    * XXXX: classification entity, fixed length 4 chars.
12799    * Y[YYYY]: classification table, max 5 chars.
12800    */
12801   tag_str = g_strdup_printf ("----://%u/%s",
12802       table, (char *) node->data + offset);
12803
12804   /* memcpy To be sure we're preserving byte order */
12805   memcpy (tag_str, entity, 4);
12806   GST_DEBUG_OBJECT (qtdemux, "classification info: %s", tag_str);
12807
12808   gst_tag_list_add (taglist, GST_TAG_MERGE_APPEND, tag, tag_str, NULL);
12809
12810   g_free (tag_str);
12811
12812   return;
12813
12814   /* ERRORS */
12815 short_read:
12816   {
12817     GST_DEBUG_OBJECT (qtdemux, "short read parsing 3GP classification");
12818     return;
12819   }
12820 }
12821
12822 static gboolean
12823 qtdemux_tag_add_str_full (GstQTDemux * qtdemux, GstTagList * taglist,
12824     const char *tag, const char *dummy, GNode * node)
12825 {
12826   const gchar *env_vars[] = { "GST_QT_TAG_ENCODING", "GST_TAG_ENCODING", NULL };
12827   GNode *data;
12828   char *s;
12829   int len;
12830   guint32 type;
12831   int offset;
12832   gboolean ret = TRUE;
12833   const gchar *charset = NULL;
12834
12835   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
12836   if (data) {
12837     len = QT_UINT32 (data->data);
12838     type = QT_UINT32 ((guint8 *) data->data + 8);
12839     if (type == 0x00000001 && len > 16) {
12840       s = gst_tag_freeform_string_to_utf8 ((char *) data->data + 16, len - 16,
12841           env_vars);
12842       if (s) {
12843         GST_DEBUG_OBJECT (qtdemux, "adding tag %s", GST_STR_NULL (s));
12844         gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag, s, NULL);
12845         g_free (s);
12846       } else {
12847         GST_DEBUG_OBJECT (qtdemux, "failed to convert %s tag to UTF-8", tag);
12848       }
12849     }
12850   } else {
12851     len = QT_UINT32 (node->data);
12852     type = QT_UINT32 ((guint8 *) node->data + 4);
12853     if ((type >> 24) == 0xa9 && len > 8 + 4) {
12854       gint str_len;
12855       gint lang_code;
12856
12857       /* Type starts with the (C) symbol, so the next data is a list
12858        * of (string size(16), language code(16), string) */
12859
12860       str_len = QT_UINT16 ((guint8 *) node->data + 8);
12861       lang_code = QT_UINT16 ((guint8 *) node->data + 10);
12862
12863       /* the string + fourcc + size + 2 16bit fields,
12864        * means that there are more tags in this atom */
12865       if (len > str_len + 8 + 4) {
12866         /* TODO how to represent the same tag in different languages? */
12867         GST_WARNING_OBJECT (qtdemux, "Ignoring metadata entry with multiple "
12868             "text alternatives, reading only first one");
12869       }
12870
12871       offset = 12;
12872       len = MIN (len, str_len + 8 + 4); /* remove trailing strings that we don't use */
12873       GST_DEBUG_OBJECT (qtdemux, "found international text tag");
12874
12875       if (lang_code < 0x800) {  /* MAC encoded string */
12876         charset = "mac";
12877       }
12878     } else if (len > 14 && qtdemux_is_string_tag_3gp (qtdemux,
12879             QT_FOURCC ((guint8 *) node->data + 4))) {
12880       guint32 type = QT_UINT32 ((guint8 *) node->data + 8);
12881
12882       /* we go for 3GP style encoding if major brands claims so,
12883        * or if no hope for data be ok UTF-8, and compatible 3GP brand present */
12884       if (qtdemux_is_brand_3gp (qtdemux, TRUE) ||
12885           (qtdemux_is_brand_3gp (qtdemux, FALSE) &&
12886               ((type & 0x00FFFFFF) == 0x0) && (type >> 24 <= 0xF))) {
12887         offset = 14;
12888         /* 16-bit Language code is ignored here as well */
12889         GST_DEBUG_OBJECT (qtdemux, "found 3gpp text tag");
12890       } else {
12891         goto normal;
12892       }
12893     } else {
12894     normal:
12895       offset = 8;
12896       GST_DEBUG_OBJECT (qtdemux, "found normal text tag");
12897       ret = FALSE;              /* may have to fallback */
12898     }
12899     if (charset) {
12900       GError *err = NULL;
12901
12902       s = g_convert ((gchar *) node->data + offset, len - offset, "utf8",
12903           charset, NULL, NULL, &err);
12904       if (err) {
12905         GST_DEBUG_OBJECT (qtdemux, "Failed to convert string from charset %s:"
12906             " %s(%d): %s", charset, g_quark_to_string (err->domain), err->code,
12907             err->message);
12908         g_error_free (err);
12909       }
12910     } else {
12911       s = gst_tag_freeform_string_to_utf8 ((char *) node->data + offset,
12912           len - offset, env_vars);
12913     }
12914     if (s) {
12915       GST_DEBUG_OBJECT (qtdemux, "adding tag %s", GST_STR_NULL (s));
12916       gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag, s, NULL);
12917       g_free (s);
12918       ret = TRUE;
12919     } else {
12920       GST_DEBUG_OBJECT (qtdemux, "failed to convert %s tag to UTF-8", tag);
12921     }
12922   }
12923   return ret;
12924 }
12925
12926 static void
12927 qtdemux_tag_add_str (GstQTDemux * qtdemux, GstTagList * taglist,
12928     const char *tag, const char *dummy, GNode * node)
12929 {
12930   qtdemux_tag_add_str_full (qtdemux, taglist, tag, dummy, node);
12931 }
12932
12933 static void
12934 qtdemux_tag_add_keywords (GstQTDemux * qtdemux, GstTagList * taglist,
12935     const char *tag, const char *dummy, GNode * node)
12936 {
12937   const gchar *env_vars[] = { "GST_QT_TAG_ENCODING", "GST_TAG_ENCODING", NULL };
12938   guint8 *data;
12939   char *s, *t, *k = NULL;
12940   int len;
12941   int offset;
12942   int count;
12943
12944   /* first try normal string tag if major brand not 3GP */
12945   if (!qtdemux_is_brand_3gp (qtdemux, TRUE)) {
12946     if (!qtdemux_tag_add_str_full (qtdemux, taglist, tag, dummy, node)) {
12947       /* hm, that did not work, maybe 3gpp storage in non-3gpp major brand;
12948        * let's try it 3gpp way after minor safety check */
12949       data = node->data;
12950       if (QT_UINT32 (data) < 15 || !qtdemux_is_brand_3gp (qtdemux, FALSE))
12951         return;
12952     } else
12953       return;
12954   }
12955
12956   GST_DEBUG_OBJECT (qtdemux, "found 3gpp keyword tag");
12957
12958   data = node->data;
12959
12960   len = QT_UINT32 (data);
12961   if (len < 15)
12962     goto short_read;
12963
12964   count = QT_UINT8 (data + 14);
12965   offset = 15;
12966   for (; count; count--) {
12967     gint slen;
12968
12969     if (offset + 1 > len)
12970       goto short_read;
12971     slen = QT_UINT8 (data + offset);
12972     offset += 1;
12973     if (offset + slen > len)
12974       goto short_read;
12975     s = gst_tag_freeform_string_to_utf8 ((char *) node->data + offset,
12976         slen, env_vars);
12977     if (s) {
12978       GST_DEBUG_OBJECT (qtdemux, "adding keyword %s", GST_STR_NULL (s));
12979       if (k) {
12980         t = g_strjoin (",", k, s, NULL);
12981         g_free (s);
12982         g_free (k);
12983         k = t;
12984       } else {
12985         k = s;
12986       }
12987     } else {
12988       GST_DEBUG_OBJECT (qtdemux, "failed to convert keyword to UTF-8");
12989     }
12990     offset += slen;
12991   }
12992
12993 done:
12994   if (k) {
12995     GST_DEBUG_OBJECT (qtdemux, "adding tag %s", GST_STR_NULL (k));
12996     gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag, k, NULL);
12997   }
12998   g_free (k);
12999
13000   return;
13001
13002   /* ERRORS */
13003 short_read:
13004   {
13005     GST_DEBUG_OBJECT (qtdemux, "short read parsing 3GP keywords");
13006     goto done;
13007   }
13008 }
13009
13010 static void
13011 qtdemux_tag_add_num (GstQTDemux * qtdemux, GstTagList * taglist,
13012     const char *tag1, const char *tag2, GNode * node)
13013 {
13014   GNode *data;
13015   int len;
13016   int type;
13017   int n1, n2;
13018
13019   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
13020   if (data) {
13021     len = QT_UINT32 (data->data);
13022     type = QT_UINT32 ((guint8 *) data->data + 8);
13023     if (type == 0x00000000 && len >= 22) {
13024       n1 = QT_UINT16 ((guint8 *) data->data + 18);
13025       n2 = QT_UINT16 ((guint8 *) data->data + 20);
13026       if (n1 > 0) {
13027         GST_DEBUG_OBJECT (qtdemux, "adding tag %s=%d", tag1, n1);
13028         gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag1, n1, NULL);
13029       }
13030       if (n2 > 0) {
13031         GST_DEBUG_OBJECT (qtdemux, "adding tag %s=%d", tag2, n2);
13032         gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag2, n2, NULL);
13033       }
13034     }
13035   }
13036 }
13037
13038 static void
13039 qtdemux_tag_add_tmpo (GstQTDemux * qtdemux, GstTagList * taglist,
13040     const char *tag1, const char *dummy, GNode * node)
13041 {
13042   GNode *data;
13043   int len;
13044   int type;
13045   int n1;
13046
13047   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
13048   if (data) {
13049     len = QT_UINT32 (data->data);
13050     type = QT_UINT32 ((guint8 *) data->data + 8);
13051     GST_DEBUG_OBJECT (qtdemux, "have tempo tag, type=%d,len=%d", type, len);
13052     /* some files wrongly have a type 0x0f=15, but it should be 0x15 */
13053     if ((type == 0x00000015 || type == 0x0000000f) && len >= 18) {
13054       n1 = QT_UINT16 ((guint8 *) data->data + 16);
13055       if (n1) {
13056         /* do not add bpm=0 */
13057         GST_DEBUG_OBJECT (qtdemux, "adding tag %d", n1);
13058         gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag1, (gdouble) n1,
13059             NULL);
13060       }
13061     }
13062   }
13063 }
13064
13065 static void
13066 qtdemux_tag_add_uint32 (GstQTDemux * qtdemux, GstTagList * taglist,
13067     const char *tag1, const char *dummy, GNode * node)
13068 {
13069   GNode *data;
13070   int len;
13071   int type;
13072   guint32 num;
13073
13074   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
13075   if (data) {
13076     len = QT_UINT32 (data->data);
13077     type = QT_UINT32 ((guint8 *) data->data + 8);
13078     GST_DEBUG_OBJECT (qtdemux, "have %s tag, type=%d,len=%d", tag1, type, len);
13079     /* some files wrongly have a type 0x0f=15, but it should be 0x15 */
13080     if ((type == 0x00000015 || type == 0x0000000f) && len >= 20) {
13081       num = QT_UINT32 ((guint8 *) data->data + 16);
13082       if (num) {
13083         /* do not add num=0 */
13084         GST_DEBUG_OBJECT (qtdemux, "adding tag %d", num);
13085         gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag1, num, NULL);
13086       }
13087     }
13088   }
13089 }
13090
13091 static void
13092 qtdemux_tag_add_covr (GstQTDemux * qtdemux, GstTagList * taglist,
13093     const char *tag1, const char *dummy, GNode * node)
13094 {
13095   GNode *data;
13096   int len;
13097   int type;
13098   GstSample *sample;
13099
13100   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
13101   if (data) {
13102     len = QT_UINT32 (data->data);
13103     type = QT_UINT32 ((guint8 *) data->data + 8);
13104     GST_DEBUG_OBJECT (qtdemux, "have covr tag, type=%d,len=%d", type, len);
13105     if ((type == 0x0000000d || type == 0x0000000e) && len > 16) {
13106       GstTagImageType image_type;
13107
13108       if (gst_tag_list_get_tag_size (taglist, GST_TAG_IMAGE) == 0)
13109         image_type = GST_TAG_IMAGE_TYPE_FRONT_COVER;
13110       else
13111         image_type = GST_TAG_IMAGE_TYPE_NONE;
13112
13113       if ((sample =
13114               gst_tag_image_data_to_image_sample ((guint8 *) data->data + 16,
13115                   len - 16, image_type))) {
13116         GST_DEBUG_OBJECT (qtdemux, "adding tag size %d", len - 16);
13117         gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag1, sample, NULL);
13118         gst_sample_unref (sample);
13119       }
13120     }
13121   }
13122 }
13123
13124 static void
13125 qtdemux_tag_add_date (GstQTDemux * qtdemux, GstTagList * taglist,
13126     const char *tag, const char *dummy, GNode * node)
13127 {
13128   GNode *data;
13129   GstDateTime *datetime = NULL;
13130   char *s;
13131   int len;
13132   int type;
13133
13134   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
13135   if (data) {
13136     len = QT_UINT32 (data->data);
13137     type = QT_UINT32 ((guint8 *) data->data + 8);
13138     if (type == 0x00000001 && len > 16) {
13139       guint y, m = 1, d = 1;
13140       gint ret;
13141
13142       s = g_strndup ((char *) data->data + 16, len - 16);
13143       GST_DEBUG_OBJECT (qtdemux, "adding date '%s'", s);
13144       datetime = gst_date_time_new_from_iso8601_string (s);
13145       if (datetime != NULL) {
13146         gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, GST_TAG_DATE_TIME,
13147             datetime, NULL);
13148         gst_date_time_unref (datetime);
13149       }
13150
13151       ret = sscanf (s, "%u-%u-%u", &y, &m, &d);
13152       if (ret >= 1 && y > 1500 && y < 3000) {
13153         GDate *date;
13154
13155         date = g_date_new_dmy (d, m, y);
13156         gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag, date, NULL);
13157         g_date_free (date);
13158       } else {
13159         GST_DEBUG_OBJECT (qtdemux, "could not parse date string '%s'", s);
13160       }
13161       g_free (s);
13162     }
13163   }
13164 }
13165
13166 static void
13167 qtdemux_tag_add_gnre (GstQTDemux * qtdemux, GstTagList * taglist,
13168     const char *tag, const char *dummy, GNode * node)
13169 {
13170   GNode *data;
13171
13172   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
13173
13174   /* re-route to normal string tag if major brand says so
13175    * or no data atom and compatible brand suggests so */
13176   if (qtdemux_is_brand_3gp (qtdemux, TRUE) ||
13177       (qtdemux_is_brand_3gp (qtdemux, FALSE) && !data)) {
13178     qtdemux_tag_add_str (qtdemux, taglist, tag, dummy, node);
13179     return;
13180   }
13181
13182   if (data) {
13183     guint len, type, n;
13184
13185     len = QT_UINT32 (data->data);
13186     type = QT_UINT32 ((guint8 *) data->data + 8);
13187     if (type == 0x00000000 && len >= 18) {
13188       n = QT_UINT16 ((guint8 *) data->data + 16);
13189       if (n > 0) {
13190         const gchar *genre;
13191
13192         genre = gst_tag_id3_genre_get (n - 1);
13193         if (genre != NULL) {
13194           GST_DEBUG_OBJECT (qtdemux, "adding %d [%s]", n, genre);
13195           gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag, genre, NULL);
13196         }
13197       }
13198     }
13199   }
13200 }
13201
13202 static void
13203 qtdemux_add_double_tag_from_str (GstQTDemux * demux, GstTagList * taglist,
13204     const gchar * tag, guint8 * data, guint32 datasize)
13205 {
13206   gdouble value;
13207   gchar *datacopy;
13208
13209   /* make a copy to have \0 at the end */
13210   datacopy = g_strndup ((gchar *) data, datasize);
13211
13212   /* convert the str to double */
13213   if (sscanf (datacopy, "%lf", &value) == 1) {
13214     GST_DEBUG_OBJECT (demux, "adding tag: %s [%s]", tag, datacopy);
13215     gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag, value, NULL);
13216   } else {
13217     GST_WARNING_OBJECT (demux, "Failed to parse double from string: %s",
13218         datacopy);
13219   }
13220   g_free (datacopy);
13221 }
13222
13223
13224 static void
13225 qtdemux_tag_add_revdns (GstQTDemux * demux, GstTagList * taglist,
13226     const char *tag, const char *tag_bis, GNode * node)
13227 {
13228   GNode *mean;
13229   GNode *name;
13230   GNode *data;
13231   guint32 meansize;
13232   guint32 namesize;
13233   guint32 datatype;
13234   guint32 datasize;
13235   const gchar *meanstr;
13236   const gchar *namestr;
13237
13238   /* checking the whole ---- atom size for consistency */
13239   if (QT_UINT32 (node->data) <= 4 + 12 + 12 + 16) {
13240     GST_WARNING_OBJECT (demux, "Tag ---- atom is too small, ignoring");
13241     return;
13242   }
13243
13244   mean = qtdemux_tree_get_child_by_type (node, FOURCC_mean);
13245   if (!mean) {
13246     GST_WARNING_OBJECT (demux, "No 'mean' atom found");
13247     return;
13248   }
13249
13250   meansize = QT_UINT32 (mean->data);
13251   if (meansize <= 12) {
13252     GST_WARNING_OBJECT (demux, "Small mean atom, ignoring the whole tag");
13253     return;
13254   }
13255   meanstr = ((gchar *) mean->data) + 12;
13256   meansize -= 12;
13257
13258   name = qtdemux_tree_get_child_by_type (node, FOURCC_name);
13259   if (!name) {
13260     GST_WARNING_OBJECT (demux, "'name' atom not found, ignoring tag");
13261     return;
13262   }
13263
13264   namesize = QT_UINT32 (name->data);
13265   if (namesize <= 12) {
13266     GST_WARNING_OBJECT (demux, "'name' atom is too small, ignoring tag");
13267     return;
13268   }
13269   namestr = ((gchar *) name->data) + 12;
13270   namesize -= 12;
13271
13272   /*
13273    * Data atom is:
13274    * uint32 - size
13275    * uint32 - name
13276    * uint8  - version
13277    * uint24 - data type
13278    * uint32 - all 0
13279    * rest   - the data
13280    */
13281   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
13282   if (!data) {
13283     GST_WARNING_OBJECT (demux, "No data atom in this tag");
13284     return;
13285   }
13286   datasize = QT_UINT32 (data->data);
13287   if (datasize <= 16) {
13288     GST_WARNING_OBJECT (demux, "Data atom too small");
13289     return;
13290   }
13291   datatype = QT_UINT32 (((gchar *) data->data) + 8) & 0xFFFFFF;
13292
13293   if ((strncmp (meanstr, "com.apple.iTunes", meansize) == 0) ||
13294       (strncmp (meanstr, "org.hydrogenaudio.replaygain", meansize) == 0)) {
13295     static const struct
13296     {
13297       const gchar name[28];
13298       const gchar tag[28];
13299     } tags[] = {
13300       {
13301       "replaygain_track_gain", GST_TAG_TRACK_GAIN}, {
13302       "replaygain_track_peak", GST_TAG_TRACK_PEAK}, {
13303       "replaygain_album_gain", GST_TAG_ALBUM_GAIN}, {
13304       "replaygain_album_peak", GST_TAG_ALBUM_PEAK}, {
13305       "MusicBrainz Track Id", GST_TAG_MUSICBRAINZ_TRACKID}, {
13306       "MusicBrainz Artist Id", GST_TAG_MUSICBRAINZ_ARTISTID}, {
13307       "MusicBrainz Album Id", GST_TAG_MUSICBRAINZ_ALBUMID}, {
13308       "MusicBrainz Album Artist Id", GST_TAG_MUSICBRAINZ_ALBUMARTISTID}
13309     };
13310     int i;
13311
13312     for (i = 0; i < G_N_ELEMENTS (tags); ++i) {
13313       if (!g_ascii_strncasecmp (tags[i].name, namestr, namesize)) {
13314         switch (gst_tag_get_type (tags[i].tag)) {
13315           case G_TYPE_DOUBLE:
13316             qtdemux_add_double_tag_from_str (demux, taglist, tags[i].tag,
13317                 ((guint8 *) data->data) + 16, datasize - 16);
13318             break;
13319           case G_TYPE_STRING:
13320             qtdemux_tag_add_str (demux, taglist, tags[i].tag, NULL, node);
13321             break;
13322           default:
13323             /* not reached */
13324             break;
13325         }
13326         break;
13327       }
13328     }
13329     if (i == G_N_ELEMENTS (tags))
13330       goto unknown_tag;
13331   } else {
13332     goto unknown_tag;
13333   }
13334
13335   return;
13336
13337 /* errors */
13338 unknown_tag:
13339 #ifndef GST_DISABLE_GST_DEBUG
13340   {
13341     gchar *namestr_dbg;
13342     gchar *meanstr_dbg;
13343
13344     meanstr_dbg = g_strndup (meanstr, meansize);
13345     namestr_dbg = g_strndup (namestr, namesize);
13346
13347     GST_WARNING_OBJECT (demux, "This tag %s:%s type:%u is not mapped, "
13348         "file a bug at bugzilla.gnome.org", meanstr_dbg, namestr_dbg, datatype);
13349
13350     g_free (namestr_dbg);
13351     g_free (meanstr_dbg);
13352   }
13353 #endif
13354   return;
13355 }
13356
13357 static void
13358 qtdemux_tag_add_id32 (GstQTDemux * demux, GstTagList * taglist, const char *tag,
13359     const char *tag_bis, GNode * node)
13360 {
13361   guint8 *data;
13362   GstBuffer *buf;
13363   guint len;
13364   GstTagList *id32_taglist = NULL;
13365
13366   GST_LOG_OBJECT (demux, "parsing ID32");
13367
13368   data = node->data;
13369   len = GST_READ_UINT32_BE (data);
13370
13371   /* need at least full box and language tag */
13372   if (len < 12 + 2)
13373     return;
13374
13375   buf = gst_buffer_new_allocate (NULL, len - 14, NULL);
13376   gst_buffer_fill (buf, 0, data + 14, len - 14);
13377
13378   id32_taglist = gst_tag_list_from_id3v2_tag (buf);
13379   if (id32_taglist) {
13380     GST_LOG_OBJECT (demux, "parsing ok");
13381     gst_tag_list_insert (taglist, id32_taglist, GST_TAG_MERGE_KEEP);
13382     gst_tag_list_unref (id32_taglist);
13383   } else {
13384     GST_LOG_OBJECT (demux, "parsing failed");
13385   }
13386
13387   gst_buffer_unref (buf);
13388 }
13389
13390 typedef void (*GstQTDemuxAddTagFunc) (GstQTDemux * demux, GstTagList * taglist,
13391     const char *tag, const char *tag_bis, GNode * node);
13392
13393 /* unmapped tags
13394 FOURCC_pcst -> if media is a podcast -> bool
13395 FOURCC_cpil -> if media is part of a compilation -> bool
13396 FOURCC_pgap -> if media is part of a gapless context -> bool
13397 FOURCC_tven -> the tv episode id e.g. S01E23 -> str
13398 */
13399
13400 static const struct
13401 {
13402   guint32 fourcc;
13403   const gchar *gst_tag;
13404   const gchar *gst_tag_bis;
13405   const GstQTDemuxAddTagFunc func;
13406 } add_funcs[] = {
13407   {
13408   FOURCC__nam, GST_TAG_TITLE, NULL, qtdemux_tag_add_str}, {
13409   FOURCC_titl, GST_TAG_TITLE, NULL, qtdemux_tag_add_str}, {
13410   FOURCC__grp, GST_TAG_GROUPING, NULL, qtdemux_tag_add_str}, {
13411   FOURCC__wrt, GST_TAG_COMPOSER, NULL, qtdemux_tag_add_str}, {
13412   FOURCC__ART, GST_TAG_ARTIST, NULL, qtdemux_tag_add_str}, {
13413   FOURCC_aART, GST_TAG_ALBUM_ARTIST, NULL, qtdemux_tag_add_str}, {
13414   FOURCC_perf, GST_TAG_ARTIST, NULL, qtdemux_tag_add_str}, {
13415   FOURCC_auth, GST_TAG_COMPOSER, NULL, qtdemux_tag_add_str}, {
13416   FOURCC__alb, GST_TAG_ALBUM, NULL, qtdemux_tag_add_str}, {
13417   FOURCC_albm, GST_TAG_ALBUM, NULL, qtdemux_tag_add_str}, {
13418   FOURCC_cprt, GST_TAG_COPYRIGHT, NULL, qtdemux_tag_add_str}, {
13419   FOURCC__cpy, GST_TAG_COPYRIGHT, NULL, qtdemux_tag_add_str}, {
13420   FOURCC__cmt, GST_TAG_COMMENT, NULL, qtdemux_tag_add_str}, {
13421   FOURCC__des, GST_TAG_DESCRIPTION, NULL, qtdemux_tag_add_str}, {
13422   FOURCC_desc, GST_TAG_DESCRIPTION, NULL, qtdemux_tag_add_str}, {
13423   FOURCC_dscp, GST_TAG_DESCRIPTION, NULL, qtdemux_tag_add_str}, {
13424   FOURCC__lyr, GST_TAG_LYRICS, NULL, qtdemux_tag_add_str}, {
13425   FOURCC__day, GST_TAG_DATE, NULL, qtdemux_tag_add_date}, {
13426   FOURCC_yrrc, GST_TAG_DATE, NULL, qtdemux_tag_add_year}, {
13427   FOURCC__too, GST_TAG_ENCODER, NULL, qtdemux_tag_add_str}, {
13428   FOURCC__inf, GST_TAG_COMMENT, NULL, qtdemux_tag_add_str}, {
13429   FOURCC_trkn, GST_TAG_TRACK_NUMBER, GST_TAG_TRACK_COUNT, qtdemux_tag_add_num}, {
13430   FOURCC_disk, GST_TAG_ALBUM_VOLUME_NUMBER, GST_TAG_ALBUM_VOLUME_COUNT,
13431         qtdemux_tag_add_num}, {
13432   FOURCC_disc, GST_TAG_ALBUM_VOLUME_NUMBER, GST_TAG_ALBUM_VOLUME_COUNT,
13433         qtdemux_tag_add_num}, {
13434   FOURCC__gen, GST_TAG_GENRE, NULL, qtdemux_tag_add_str}, {
13435   FOURCC_gnre, GST_TAG_GENRE, NULL, qtdemux_tag_add_gnre}, {
13436   FOURCC_tmpo, GST_TAG_BEATS_PER_MINUTE, NULL, qtdemux_tag_add_tmpo}, {
13437   FOURCC_covr, GST_TAG_IMAGE, NULL, qtdemux_tag_add_covr}, {
13438   FOURCC_sonm, GST_TAG_TITLE_SORTNAME, NULL, qtdemux_tag_add_str}, {
13439   FOURCC_soal, GST_TAG_ALBUM_SORTNAME, NULL, qtdemux_tag_add_str}, {
13440   FOURCC_soar, GST_TAG_ARTIST_SORTNAME, NULL, qtdemux_tag_add_str}, {
13441   FOURCC_soaa, GST_TAG_ALBUM_ARTIST_SORTNAME, NULL, qtdemux_tag_add_str}, {
13442   FOURCC_soco, GST_TAG_COMPOSER_SORTNAME, NULL, qtdemux_tag_add_str}, {
13443   FOURCC_sosn, GST_TAG_SHOW_SORTNAME, NULL, qtdemux_tag_add_str}, {
13444   FOURCC_tvsh, GST_TAG_SHOW_NAME, NULL, qtdemux_tag_add_str}, {
13445   FOURCC_tvsn, GST_TAG_SHOW_SEASON_NUMBER, NULL, qtdemux_tag_add_uint32}, {
13446   FOURCC_tves, GST_TAG_SHOW_EPISODE_NUMBER, NULL, qtdemux_tag_add_uint32}, {
13447   FOURCC_kywd, GST_TAG_KEYWORDS, NULL, qtdemux_tag_add_keywords}, {
13448   FOURCC_keyw, GST_TAG_KEYWORDS, NULL, qtdemux_tag_add_str}, {
13449   FOURCC__enc, GST_TAG_ENCODER, NULL, qtdemux_tag_add_str}, {
13450   FOURCC_loci, GST_TAG_GEO_LOCATION_NAME, NULL, qtdemux_tag_add_location}, {
13451   FOURCC_clsf, GST_QT_DEMUX_CLASSIFICATION_TAG, NULL,
13452         qtdemux_tag_add_classification}, {
13453   FOURCC__mak, GST_TAG_DEVICE_MANUFACTURER, NULL, qtdemux_tag_add_str}, {
13454   FOURCC__mod, GST_TAG_DEVICE_MODEL, NULL, qtdemux_tag_add_str}, {
13455   FOURCC__swr, GST_TAG_APPLICATION_NAME, NULL, qtdemux_tag_add_str}, {
13456
13457     /* This is a special case, some tags are stored in this
13458      * 'reverse dns naming', according to:
13459      * http://atomicparsley.sourceforge.net/mpeg-4files.html and
13460      * bug #614471
13461      */
13462   FOURCC_____, "", NULL, qtdemux_tag_add_revdns}, {
13463     /* see http://www.mp4ra.org/specs.html for ID32 in meta box */
13464   FOURCC_ID32, "", NULL, qtdemux_tag_add_id32}
13465 };
13466
13467 struct _GstQtDemuxTagList
13468 {
13469   GstQTDemux *demux;
13470   GstTagList *taglist;
13471 };
13472 typedef struct _GstQtDemuxTagList GstQtDemuxTagList;
13473
13474 static void
13475 qtdemux_tag_add_blob (GNode * node, GstQtDemuxTagList * qtdemuxtaglist)
13476 {
13477   gint len;
13478   guint8 *data;
13479   GstBuffer *buf;
13480   gchar *media_type;
13481   const gchar *style;
13482   GstSample *sample;
13483   GstStructure *s;
13484   guint i;
13485   guint8 ndata[4];
13486   GstQTDemux *demux = qtdemuxtaglist->demux;
13487   GstTagList *taglist = qtdemuxtaglist->taglist;
13488
13489   data = node->data;
13490   len = QT_UINT32 (data);
13491   buf = gst_buffer_new_and_alloc (len);
13492   gst_buffer_fill (buf, 0, data, len);
13493
13494   /* heuristic to determine style of tag */
13495   if (QT_FOURCC (data + 4) == FOURCC_____ ||
13496       (len > 8 + 12 && QT_FOURCC (data + 12) == FOURCC_data))
13497     style = "itunes";
13498   else if (demux->major_brand == FOURCC_qt__)
13499     style = "quicktime";
13500   /* fall back to assuming iso/3gp tag style */
13501   else
13502     style = "iso";
13503
13504   /* santize the name for the caps. */
13505   for (i = 0; i < 4; i++) {
13506     guint8 d = data[4 + i];
13507     if (g_ascii_isalnum (d))
13508       ndata[i] = g_ascii_tolower (d);
13509     else
13510       ndata[i] = '_';
13511   }
13512
13513   media_type = g_strdup_printf ("application/x-gst-qt-%c%c%c%c-tag",
13514       ndata[0], ndata[1], ndata[2], ndata[3]);
13515   GST_DEBUG_OBJECT (demux, "media type %s", media_type);
13516
13517   s = gst_structure_new (media_type, "style", G_TYPE_STRING, style, NULL);
13518   sample = gst_sample_new (buf, NULL, NULL, s);
13519   gst_buffer_unref (buf);
13520   g_free (media_type);
13521
13522   GST_DEBUG_OBJECT (demux, "adding private tag; size %d, info %" GST_PTR_FORMAT,
13523       len, s);
13524
13525   gst_tag_list_add (taglist, GST_TAG_MERGE_APPEND,
13526       GST_QT_DEMUX_PRIVATE_TAG, sample, NULL);
13527
13528   gst_sample_unref (sample);
13529 }
13530
13531 static void
13532 qtdemux_parse_udta (GstQTDemux * qtdemux, GstTagList * taglist, GNode * udta)
13533 {
13534   GNode *meta;
13535   GNode *ilst;
13536   GNode *xmp_;
13537   GNode *node;
13538   gint i;
13539   GstQtDemuxTagList demuxtaglist;
13540
13541   demuxtaglist.demux = qtdemux;
13542   demuxtaglist.taglist = taglist;
13543
13544   meta = qtdemux_tree_get_child_by_type (udta, FOURCC_meta);
13545   if (meta != NULL) {
13546     ilst = qtdemux_tree_get_child_by_type (meta, FOURCC_ilst);
13547     if (ilst == NULL) {
13548       GST_LOG_OBJECT (qtdemux, "no ilst");
13549       return;
13550     }
13551   } else {
13552     ilst = udta;
13553     GST_LOG_OBJECT (qtdemux, "no meta so using udta itself");
13554   }
13555
13556   i = 0;
13557   while (i < G_N_ELEMENTS (add_funcs)) {
13558     node = qtdemux_tree_get_child_by_type (ilst, add_funcs[i].fourcc);
13559     if (node) {
13560       gint len;
13561
13562       len = QT_UINT32 (node->data);
13563       if (len < 12) {
13564         GST_DEBUG_OBJECT (qtdemux, "too small tag atom %" GST_FOURCC_FORMAT,
13565             GST_FOURCC_ARGS (add_funcs[i].fourcc));
13566       } else {
13567         add_funcs[i].func (qtdemux, taglist, add_funcs[i].gst_tag,
13568             add_funcs[i].gst_tag_bis, node);
13569       }
13570       g_node_destroy (node);
13571     } else {
13572       i++;
13573     }
13574   }
13575
13576   /* parsed nodes have been removed, pass along remainder as blob */
13577   g_node_children_foreach (ilst, G_TRAVERSE_ALL,
13578       (GNodeForeachFunc) qtdemux_tag_add_blob, &demuxtaglist);
13579
13580   /* parse up XMP_ node if existing */
13581   xmp_ = qtdemux_tree_get_child_by_type (udta, FOURCC_XMP_);
13582   if (xmp_ != NULL) {
13583     GstBuffer *buf;
13584     GstTagList *xmptaglist;
13585
13586     buf = _gst_buffer_new_wrapped (((guint8 *) xmp_->data) + 8,
13587         QT_UINT32 ((guint8 *) xmp_->data) - 8, NULL);
13588     xmptaglist = gst_tag_list_from_xmp_buffer (buf);
13589     gst_buffer_unref (buf);
13590
13591     qtdemux_handle_xmp_taglist (qtdemux, taglist, xmptaglist);
13592   } else {
13593     GST_DEBUG_OBJECT (qtdemux, "No XMP_ node found");
13594   }
13595 }
13596
13597 typedef struct
13598 {
13599   GstStructure *structure;      /* helper for sort function */
13600   gchar *location;
13601   guint min_req_bitrate;
13602   guint min_req_qt_version;
13603 } GstQtReference;
13604
13605 static gint
13606 qtdemux_redirects_sort_func (gconstpointer a, gconstpointer b)
13607 {
13608   GstQtReference *ref_a = (GstQtReference *) a;
13609   GstQtReference *ref_b = (GstQtReference *) b;
13610
13611   if (ref_b->min_req_qt_version != ref_a->min_req_qt_version)
13612     return ref_b->min_req_qt_version - ref_a->min_req_qt_version;
13613
13614   /* known bitrates go before unknown; higher bitrates go first */
13615   return ref_b->min_req_bitrate - ref_a->min_req_bitrate;
13616 }
13617
13618 /* sort the redirects and post a message for the application.
13619  */
13620 static void
13621 qtdemux_process_redirects (GstQTDemux * qtdemux, GList * references)
13622 {
13623   GstQtReference *best;
13624   GstStructure *s;
13625   GstMessage *msg;
13626   GValue list_val = { 0, };
13627   GList *l;
13628
13629   g_assert (references != NULL);
13630
13631   references = g_list_sort (references, qtdemux_redirects_sort_func);
13632
13633   best = (GstQtReference *) references->data;
13634
13635   g_value_init (&list_val, GST_TYPE_LIST);
13636
13637   for (l = references; l != NULL; l = l->next) {
13638     GstQtReference *ref = (GstQtReference *) l->data;
13639     GValue struct_val = { 0, };
13640
13641     ref->structure = gst_structure_new ("redirect",
13642         "new-location", G_TYPE_STRING, ref->location, NULL);
13643
13644     if (ref->min_req_bitrate > 0) {
13645       gst_structure_set (ref->structure, "minimum-bitrate", G_TYPE_INT,
13646           ref->min_req_bitrate, NULL);
13647     }
13648
13649     g_value_init (&struct_val, GST_TYPE_STRUCTURE);
13650     g_value_set_boxed (&struct_val, ref->structure);
13651     gst_value_list_append_value (&list_val, &struct_val);
13652     g_value_unset (&struct_val);
13653     /* don't free anything here yet, since we need best->structure below */
13654   }
13655
13656   g_assert (best != NULL);
13657   s = gst_structure_copy (best->structure);
13658
13659   if (g_list_length (references) > 1) {
13660     gst_structure_set_value (s, "locations", &list_val);
13661   }
13662
13663   g_value_unset (&list_val);
13664
13665   for (l = references; l != NULL; l = l->next) {
13666     GstQtReference *ref = (GstQtReference *) l->data;
13667
13668     gst_structure_free (ref->structure);
13669     g_free (ref->location);
13670     g_free (ref);
13671   }
13672   g_list_free (references);
13673
13674   GST_INFO_OBJECT (qtdemux, "posting redirect message: %" GST_PTR_FORMAT, s);
13675   msg = gst_message_new_element (GST_OBJECT_CAST (qtdemux), s);
13676   gst_element_post_message (GST_ELEMENT_CAST (qtdemux), msg);
13677   qtdemux->posted_redirect = TRUE;
13678 }
13679
13680 /* look for redirect nodes, collect all redirect information and
13681  * process it.
13682  */
13683 static gboolean
13684 qtdemux_parse_redirects (GstQTDemux * qtdemux)
13685 {
13686   GNode *rmra, *rmda, *rdrf;
13687
13688   rmra = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_rmra);
13689   if (rmra) {
13690     GList *redirects = NULL;
13691
13692     rmda = qtdemux_tree_get_child_by_type (rmra, FOURCC_rmda);
13693     while (rmda) {
13694       GstQtReference ref = { NULL, NULL, 0, 0 };
13695       GNode *rmdr, *rmvc;
13696
13697       if ((rmdr = qtdemux_tree_get_child_by_type (rmda, FOURCC_rmdr))) {
13698         ref.min_req_bitrate = QT_UINT32 ((guint8 *) rmdr->data + 12);
13699         GST_LOG_OBJECT (qtdemux, "data rate atom, required bitrate = %u",
13700             ref.min_req_bitrate);
13701       }
13702
13703       if ((rmvc = qtdemux_tree_get_child_by_type (rmda, FOURCC_rmvc))) {
13704         guint32 package = QT_FOURCC ((guint8 *) rmvc->data + 12);
13705         guint version = QT_UINT32 ((guint8 *) rmvc->data + 16);
13706
13707 #ifndef GST_DISABLE_GST_DEBUG
13708         guint bitmask = QT_UINT32 ((guint8 *) rmvc->data + 20);
13709 #endif
13710         guint check_type = QT_UINT16 ((guint8 *) rmvc->data + 24);
13711
13712         GST_LOG_OBJECT (qtdemux,
13713             "version check atom [%" GST_FOURCC_FORMAT "], version=0x%08x"
13714             ", mask=%08x, check_type=%u", GST_FOURCC_ARGS (package), version,
13715             bitmask, check_type);
13716         if (package == FOURCC_qtim && check_type == 0) {
13717           ref.min_req_qt_version = version;
13718         }
13719       }
13720
13721       rdrf = qtdemux_tree_get_child_by_type (rmda, FOURCC_rdrf);
13722       if (rdrf) {
13723         guint32 ref_type;
13724         guint8 *ref_data;
13725         guint ref_len;
13726
13727         ref_len = QT_UINT32 ((guint8 *) rdrf->data);
13728         if (ref_len > 20) {
13729           ref_type = QT_FOURCC ((guint8 *) rdrf->data + 12);
13730           ref_data = (guint8 *) rdrf->data + 20;
13731           if (ref_type == FOURCC_alis) {
13732             guint record_len, record_version, fn_len;
13733
13734             if (ref_len > 70) {
13735               /* MacOSX alias record, google for alias-layout.txt */
13736               record_len = QT_UINT16 (ref_data + 4);
13737               record_version = QT_UINT16 (ref_data + 4 + 2);
13738               fn_len = QT_UINT8 (ref_data + 50);
13739               if (record_len > 50 && record_version == 2 && fn_len > 0) {
13740                 ref.location = g_strndup ((gchar *) ref_data + 51, fn_len);
13741               }
13742             } else {
13743               GST_WARNING_OBJECT (qtdemux, "Invalid rdrf/alis size (%u < 70)",
13744                   ref_len);
13745             }
13746           } else if (ref_type == FOURCC_url_) {
13747             ref.location = g_strndup ((gchar *) ref_data, ref_len - 8);
13748           } else {
13749             GST_DEBUG_OBJECT (qtdemux,
13750                 "unknown rdrf reference type %" GST_FOURCC_FORMAT,
13751                 GST_FOURCC_ARGS (ref_type));
13752           }
13753           if (ref.location != NULL) {
13754             GST_INFO_OBJECT (qtdemux, "New location: %s", ref.location);
13755             redirects =
13756                 g_list_prepend (redirects, g_memdup (&ref, sizeof (ref)));
13757           } else {
13758             GST_WARNING_OBJECT (qtdemux,
13759                 "Failed to extract redirect location from rdrf atom");
13760           }
13761         } else {
13762           GST_WARNING_OBJECT (qtdemux, "Invalid rdrf size (%u < 20)", ref_len);
13763         }
13764       }
13765
13766       /* look for others */
13767       rmda = qtdemux_tree_get_sibling_by_type (rmda, FOURCC_rmda);
13768     }
13769
13770     if (redirects != NULL) {
13771       qtdemux_process_redirects (qtdemux, redirects);
13772     }
13773   }
13774   return TRUE;
13775 }
13776
13777 static GstTagList *
13778 qtdemux_add_container_format (GstQTDemux * qtdemux, GstTagList * tags)
13779 {
13780   const gchar *fmt;
13781
13782   if (tags == NULL) {
13783     tags = gst_tag_list_new_empty ();
13784     gst_tag_list_set_scope (tags, GST_TAG_SCOPE_GLOBAL);
13785   }
13786
13787   if (qtdemux->major_brand == FOURCC_mjp2)
13788     fmt = "Motion JPEG 2000";
13789   else if ((qtdemux->major_brand & 0xffff) == FOURCC_3g__)
13790     fmt = "3GP";
13791   else if (qtdemux->major_brand == FOURCC_qt__)
13792     fmt = "Quicktime";
13793   else if (qtdemux->fragmented)
13794     fmt = "ISO fMP4";
13795   else
13796     fmt = "ISO MP4/M4A";
13797
13798   GST_LOG_OBJECT (qtdemux, "mapped %" GST_FOURCC_FORMAT " to '%s'",
13799       GST_FOURCC_ARGS (qtdemux->major_brand), fmt);
13800
13801   gst_tag_list_add (tags, GST_TAG_MERGE_REPLACE, GST_TAG_CONTAINER_FORMAT,
13802       fmt, NULL);
13803
13804   return tags;
13805 }
13806
13807 /* we have read the complete moov node now.
13808  * This function parses all of the relevant info, creates the traks and
13809  * prepares all data structures for playback
13810  */
13811 static gboolean
13812 qtdemux_parse_tree (GstQTDemux * qtdemux)
13813 {
13814   GNode *mvhd;
13815   GNode *trak;
13816   GNode *udta;
13817   GNode *mvex;
13818   GNode *pssh;
13819   guint64 creation_time;
13820   GstDateTime *datetime = NULL;
13821   gint version;
13822
13823   /* make sure we have a usable taglist */
13824   qtdemux->tag_list = gst_tag_list_make_writable (qtdemux->tag_list);
13825
13826   mvhd = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_mvhd);
13827   if (mvhd == NULL) {
13828     GST_LOG_OBJECT (qtdemux, "No mvhd node found, looking for redirects.");
13829     return qtdemux_parse_redirects (qtdemux);
13830   }
13831
13832   version = QT_UINT8 ((guint8 *) mvhd->data + 8);
13833   if (version == 1) {
13834     creation_time = QT_UINT64 ((guint8 *) mvhd->data + 12);
13835     qtdemux->timescale = QT_UINT32 ((guint8 *) mvhd->data + 28);
13836     qtdemux->duration = QT_UINT64 ((guint8 *) mvhd->data + 32);
13837   } else if (version == 0) {
13838     creation_time = QT_UINT32 ((guint8 *) mvhd->data + 12);
13839     qtdemux->timescale = QT_UINT32 ((guint8 *) mvhd->data + 20);
13840     qtdemux->duration = QT_UINT32 ((guint8 *) mvhd->data + 24);
13841   } else {
13842     GST_WARNING_OBJECT (qtdemux, "Unhandled mvhd version %d", version);
13843     return FALSE;
13844   }
13845
13846   /* Moving qt creation time (secs since 1904) to unix time */
13847   if (creation_time != 0) {
13848     /* Try to use epoch first as it should be faster and more commonly found */
13849     if (creation_time >= QTDEMUX_SECONDS_FROM_1904_TO_1970) {
13850       GTimeVal now;
13851
13852       creation_time -= QTDEMUX_SECONDS_FROM_1904_TO_1970;
13853       /* some data cleansing sanity */
13854       g_get_current_time (&now);
13855       if (now.tv_sec + 24 * 3600 < creation_time) {
13856         GST_DEBUG_OBJECT (qtdemux, "discarding bogus future creation time");
13857       } else {
13858         datetime = gst_date_time_new_from_unix_epoch_utc (creation_time);
13859       }
13860     } else {
13861       GDateTime *base_dt = g_date_time_new_utc (1904, 1, 1, 0, 0, 0);
13862       GDateTime *dt, *dt_local;
13863
13864       dt = g_date_time_add_seconds (base_dt, creation_time);
13865       dt_local = g_date_time_to_local (dt);
13866       datetime = gst_date_time_new_from_g_date_time (dt_local);
13867
13868       g_date_time_unref (base_dt);
13869       g_date_time_unref (dt);
13870     }
13871   }
13872   if (datetime) {
13873     /* Use KEEP as explicit tags should have a higher priority than mvhd tag */
13874     gst_tag_list_add (qtdemux->tag_list, GST_TAG_MERGE_KEEP, GST_TAG_DATE_TIME,
13875         datetime, NULL);
13876     gst_date_time_unref (datetime);
13877   }
13878
13879   GST_INFO_OBJECT (qtdemux, "timescale: %u", qtdemux->timescale);
13880   GST_INFO_OBJECT (qtdemux, "duration: %" G_GUINT64_FORMAT, qtdemux->duration);
13881
13882   /* check for fragmented file and get some (default) data */
13883   mvex = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_mvex);
13884   if (mvex) {
13885     GNode *mehd;
13886     GstByteReader mehd_data;
13887
13888     /* let track parsing or anyone know weird stuff might happen ... */
13889     qtdemux->fragmented = TRUE;
13890
13891     /* compensate for total duration */
13892     mehd = qtdemux_tree_get_child_by_type_full (mvex, FOURCC_mehd, &mehd_data);
13893     if (mehd)
13894       qtdemux_parse_mehd (qtdemux, &mehd_data);
13895   }
13896
13897   /* Update the movie segment duration, unless it was directly given to us
13898    * by upstream. Otherwise let it as is, as we don't want to mangle the
13899    * duration provided by upstream that may come e.g. from a MPD file. */
13900   if (!qtdemux->upstream_format_is_time) {
13901     GstClockTime duration;
13902     /* set duration in the segment info */
13903     gst_qtdemux_get_duration (qtdemux, &duration);
13904     qtdemux->segment.duration = duration;
13905     /* also do not exceed duration; stop is set that way post seek anyway,
13906      * and segment activation falls back to duration,
13907      * whereas loop only checks stop, so let's align this here as well */
13908     qtdemux->segment.stop = duration;
13909   }
13910
13911   /* parse all traks */
13912   trak = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_trak);
13913   while (trak) {
13914     qtdemux_parse_trak (qtdemux, trak);
13915     /* iterate all siblings */
13916     trak = qtdemux_tree_get_sibling_by_type (trak, FOURCC_trak);
13917   }
13918
13919   qtdemux->tag_list = gst_tag_list_make_writable (qtdemux->tag_list);
13920
13921   /* find tags */
13922   udta = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_udta);
13923   if (udta) {
13924     qtdemux_parse_udta (qtdemux, qtdemux->tag_list, udta);
13925   } else {
13926     GST_LOG_OBJECT (qtdemux, "No udta node found.");
13927   }
13928
13929   /* maybe also some tags in meta box */
13930   udta = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_meta);
13931   if (udta) {
13932     GST_DEBUG_OBJECT (qtdemux, "Parsing meta box for tags.");
13933     qtdemux_parse_udta (qtdemux, qtdemux->tag_list, udta);
13934   } else {
13935     GST_LOG_OBJECT (qtdemux, "No meta node found.");
13936   }
13937
13938   /* parse any protection system info */
13939   pssh = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_pssh);
13940   while (pssh) {
13941     GST_LOG_OBJECT (qtdemux, "Parsing pssh box.");
13942     qtdemux_parse_pssh (qtdemux, pssh);
13943     pssh = qtdemux_tree_get_sibling_by_type (pssh, FOURCC_pssh);
13944   }
13945
13946   qtdemux->tag_list = qtdemux_add_container_format (qtdemux, qtdemux->tag_list);
13947
13948   return TRUE;
13949 }
13950
13951 /* taken from ffmpeg */
13952 static int
13953 read_descr_size (guint8 * ptr, guint8 * end, guint8 ** end_out)
13954 {
13955   int count = 4;
13956   int len = 0;
13957
13958   while (count--) {
13959     int c;
13960
13961     if (ptr >= end)
13962       return -1;
13963
13964     c = *ptr++;
13965     len = (len << 7) | (c & 0x7f);
13966     if (!(c & 0x80))
13967       break;
13968   }
13969   *end_out = ptr;
13970   return len;
13971 }
13972
13973 static GList *
13974 parse_xiph_stream_headers (GstQTDemux * qtdemux, gpointer codec_data,
13975     gsize codec_data_size)
13976 {
13977   GList *list = NULL;
13978   guint8 *p = codec_data;
13979   gint i, offset, num_packets;
13980   guint *length, last;
13981
13982   GST_MEMDUMP_OBJECT (qtdemux, "xiph codec data", codec_data, codec_data_size);
13983
13984   if (codec_data == NULL || codec_data_size == 0)
13985     goto error;
13986
13987   /* start of the stream and vorbis audio or theora video, need to
13988    * send the codec_priv data as first three packets */
13989   num_packets = p[0] + 1;
13990   GST_DEBUG_OBJECT (qtdemux,
13991       "%u stream headers, total length=%" G_GSIZE_FORMAT " bytes",
13992       (guint) num_packets, codec_data_size);
13993
13994   /* Let's put some limits, Don't think there even is a xiph codec
13995    * with more than 3-4 headers */
13996   if (G_UNLIKELY (num_packets > 16)) {
13997     GST_WARNING_OBJECT (qtdemux,
13998         "Unlikely number of xiph headers, most likely not valid");
13999     goto error;
14000   }
14001
14002   length = g_alloca (num_packets * sizeof (guint));
14003   last = 0;
14004   offset = 1;
14005
14006   /* first packets, read length values */
14007   for (i = 0; i < num_packets - 1; i++) {
14008     length[i] = 0;
14009     while (offset < codec_data_size) {
14010       length[i] += p[offset];
14011       if (p[offset++] != 0xff)
14012         break;
14013     }
14014     last += length[i];
14015   }
14016   if (offset + last > codec_data_size)
14017     goto error;
14018
14019   /* last packet is the remaining size */
14020   length[i] = codec_data_size - offset - last;
14021
14022   for (i = 0; i < num_packets; i++) {
14023     GstBuffer *hdr;
14024
14025     GST_DEBUG_OBJECT (qtdemux, "buffer %d: %u bytes", i, (guint) length[i]);
14026
14027     if (offset + length[i] > codec_data_size)
14028       goto error;
14029
14030     hdr = gst_buffer_new_wrapped (g_memdup (p + offset, length[i]), length[i]);
14031     list = g_list_append (list, hdr);
14032
14033     offset += length[i];
14034   }
14035
14036   return list;
14037
14038   /* ERRORS */
14039 error:
14040   {
14041     if (list != NULL)
14042       g_list_free_full (list, (GDestroyNotify) gst_buffer_unref);
14043     return NULL;
14044   }
14045
14046 }
14047
14048 /* this can change the codec originally present in @list */
14049 static void
14050 gst_qtdemux_handle_esds (GstQTDemux * qtdemux, QtDemuxStream * stream,
14051     QtDemuxStreamStsdEntry * entry, GNode * esds, GstTagList * list)
14052 {
14053   int len = QT_UINT32 (esds->data);
14054   guint8 *ptr = esds->data;
14055   guint8 *end = ptr + len;
14056   int tag;
14057   guint8 *data_ptr = NULL;
14058   int data_len = 0;
14059   guint8 object_type_id = 0;
14060   guint8 stream_type = 0;
14061   const char *codec_name = NULL;
14062   GstCaps *caps = NULL;
14063
14064   GST_MEMDUMP_OBJECT (qtdemux, "esds", ptr, len);
14065   ptr += 8;
14066   GST_DEBUG_OBJECT (qtdemux, "version/flags = %08x", QT_UINT32 (ptr));
14067   ptr += 4;
14068   while (ptr + 1 < end) {
14069     tag = QT_UINT8 (ptr);
14070     GST_DEBUG_OBJECT (qtdemux, "tag = %02x", tag);
14071     ptr++;
14072     len = read_descr_size (ptr, end, &ptr);
14073     GST_DEBUG_OBJECT (qtdemux, "len = %d", len);
14074
14075     /* Check the stated amount of data is available for reading */
14076     if (len < 0 || ptr + len > end)
14077       break;
14078
14079     switch (tag) {
14080       case ES_DESCRIPTOR_TAG:
14081         GST_DEBUG_OBJECT (qtdemux, "ID 0x%04x", QT_UINT16 (ptr));
14082         GST_DEBUG_OBJECT (qtdemux, "priority 0x%04x", QT_UINT8 (ptr + 2));
14083         ptr += 3;
14084         break;
14085       case DECODER_CONFIG_DESC_TAG:{
14086         guint max_bitrate, avg_bitrate;
14087
14088         object_type_id = QT_UINT8 (ptr);
14089         stream_type = QT_UINT8 (ptr + 1) >> 2;
14090         max_bitrate = QT_UINT32 (ptr + 5);
14091         avg_bitrate = QT_UINT32 (ptr + 9);
14092         GST_DEBUG_OBJECT (qtdemux, "object_type_id %02x", object_type_id);
14093         GST_DEBUG_OBJECT (qtdemux, "stream_type %02x", stream_type);
14094         GST_DEBUG_OBJECT (qtdemux, "buffer_size_db %02x", QT_UINT24 (ptr + 2));
14095         GST_DEBUG_OBJECT (qtdemux, "max bitrate %u", max_bitrate);
14096         GST_DEBUG_OBJECT (qtdemux, "avg bitrate %u", avg_bitrate);
14097         if (max_bitrate > 0 && max_bitrate < G_MAXUINT32) {
14098           gst_tag_list_add (list, GST_TAG_MERGE_REPLACE,
14099               GST_TAG_MAXIMUM_BITRATE, max_bitrate, NULL);
14100         }
14101         if (avg_bitrate > 0 && avg_bitrate < G_MAXUINT32) {
14102           gst_tag_list_add (list, GST_TAG_MERGE_REPLACE, GST_TAG_BITRATE,
14103               avg_bitrate, NULL);
14104         }
14105         ptr += 13;
14106         break;
14107       }
14108       case DECODER_SPECIFIC_INFO_TAG:
14109         GST_MEMDUMP_OBJECT (qtdemux, "data", ptr, len);
14110         if (object_type_id == 0xe0 && len == 0x40) {
14111           guint8 *data;
14112           GstStructure *s;
14113           guint32 clut[16];
14114           gint i;
14115
14116           GST_DEBUG_OBJECT (qtdemux,
14117               "Have VOBSUB palette. Creating palette event");
14118           /* move to decConfigDescr data and read palette */
14119           data = ptr;
14120           for (i = 0; i < 16; i++) {
14121             clut[i] = QT_UINT32 (data);
14122             data += 4;
14123           }
14124
14125           s = gst_structure_new ("application/x-gst-dvd", "event",
14126               G_TYPE_STRING, "dvd-spu-clut-change",
14127               "clut00", G_TYPE_INT, clut[0], "clut01", G_TYPE_INT, clut[1],
14128               "clut02", G_TYPE_INT, clut[2], "clut03", G_TYPE_INT, clut[3],
14129               "clut04", G_TYPE_INT, clut[4], "clut05", G_TYPE_INT, clut[5],
14130               "clut06", G_TYPE_INT, clut[6], "clut07", G_TYPE_INT, clut[7],
14131               "clut08", G_TYPE_INT, clut[8], "clut09", G_TYPE_INT, clut[9],
14132               "clut10", G_TYPE_INT, clut[10], "clut11", G_TYPE_INT, clut[11],
14133               "clut12", G_TYPE_INT, clut[12], "clut13", G_TYPE_INT, clut[13],
14134               "clut14", G_TYPE_INT, clut[14], "clut15", G_TYPE_INT, clut[15],
14135               NULL);
14136
14137           /* store event and trigger custom processing */
14138           stream->pending_event =
14139               gst_event_new_custom (GST_EVENT_CUSTOM_DOWNSTREAM, s);
14140         } else {
14141           /* Generic codec_data handler puts it on the caps */
14142           data_ptr = ptr;
14143           data_len = len;
14144         }
14145
14146         ptr += len;
14147         break;
14148       case SL_CONFIG_DESC_TAG:
14149         GST_DEBUG_OBJECT (qtdemux, "data %02x", QT_UINT8 (ptr));
14150         ptr += 1;
14151         break;
14152       default:
14153         GST_DEBUG_OBJECT (qtdemux, "Unknown/unhandled descriptor tag %02x",
14154             tag);
14155         GST_MEMDUMP_OBJECT (qtdemux, "descriptor data", ptr, len);
14156         ptr += len;
14157         break;
14158     }
14159   }
14160
14161   /* object_type_id in the esds atom in mp4a and mp4v tells us which codec is
14162    * in use, and should also be used to override some other parameters for some
14163    * codecs. */
14164   switch (object_type_id) {
14165     case 0x20:                 /* MPEG-4 */
14166       /* 4 bytes for the visual_object_sequence_start_code and 1 byte for the
14167        * profile_and_level_indication */
14168       if (data_ptr != NULL && data_len >= 5 &&
14169           GST_READ_UINT32_BE (data_ptr) == 0x000001b0) {
14170         gst_codec_utils_mpeg4video_caps_set_level_and_profile (entry->caps,
14171             data_ptr + 4, data_len - 4);
14172       }
14173       break;                    /* Nothing special needed here */
14174     case 0x21:                 /* H.264 */
14175       codec_name = "H.264 / AVC";
14176       caps = gst_caps_new_simple ("video/x-h264",
14177           "stream-format", G_TYPE_STRING, "avc",
14178           "alignment", G_TYPE_STRING, "au", NULL);
14179       break;
14180     case 0x40:                 /* AAC (any) */
14181     case 0x66:                 /* AAC Main */
14182     case 0x67:                 /* AAC LC */
14183     case 0x68:                 /* AAC SSR */
14184       /* Override channels and rate based on the codec_data, as it's often
14185        * wrong. */
14186       /* Only do so for basic setup without HE-AAC extension */
14187       if (data_ptr && data_len == 2) {
14188         guint channels, rate;
14189
14190         channels = gst_codec_utils_aac_get_channels (data_ptr, data_len);
14191         if (channels > 0)
14192           entry->n_channels = channels;
14193
14194         rate = gst_codec_utils_aac_get_sample_rate (data_ptr, data_len);
14195         if (rate > 0)
14196           entry->rate = rate;
14197       }
14198
14199       /* Set level and profile if possible */
14200       if (data_ptr != NULL && data_len >= 2) {
14201         gst_codec_utils_aac_caps_set_level_and_profile (entry->caps,
14202             data_ptr, data_len);
14203       } else {
14204         const gchar *profile_str = NULL;
14205         GstBuffer *buffer;
14206         GstMapInfo map;
14207         guint8 *codec_data;
14208         gint rate_idx, profile;
14209
14210         /* No codec_data, let's invent something.
14211          * FIXME: This is wrong for SBR! */
14212
14213         GST_WARNING_OBJECT (qtdemux, "No codec_data for AAC available");
14214
14215         buffer = gst_buffer_new_and_alloc (2);
14216         gst_buffer_map (buffer, &map, GST_MAP_WRITE);
14217         codec_data = map.data;
14218
14219         rate_idx =
14220             gst_codec_utils_aac_get_index_from_sample_rate (CUR_STREAM
14221             (stream)->rate);
14222
14223         switch (object_type_id) {
14224           case 0x66:
14225             profile_str = "main";
14226             profile = 0;
14227             break;
14228           case 0x67:
14229             profile_str = "lc";
14230             profile = 1;
14231             break;
14232           case 0x68:
14233             profile_str = "ssr";
14234             profile = 2;
14235             break;
14236           default:
14237             profile = 3;
14238             break;
14239         }
14240
14241         codec_data[0] = ((profile + 1) << 3) | ((rate_idx & 0xE) >> 1);
14242         codec_data[1] =
14243             ((rate_idx & 0x1) << 7) | (CUR_STREAM (stream)->n_channels << 3);
14244
14245         gst_buffer_unmap (buffer, &map);
14246         gst_caps_set_simple (CUR_STREAM (stream)->caps, "codec_data",
14247             GST_TYPE_BUFFER, buffer, NULL);
14248         gst_buffer_unref (buffer);
14249
14250         if (profile_str) {
14251           gst_caps_set_simple (CUR_STREAM (stream)->caps, "profile",
14252               G_TYPE_STRING, profile_str, NULL);
14253         }
14254       }
14255       break;
14256     case 0x60:                 /* MPEG-2, various profiles */
14257     case 0x61:
14258     case 0x62:
14259     case 0x63:
14260     case 0x64:
14261     case 0x65:
14262       codec_name = "MPEG-2 video";
14263       caps = gst_caps_new_simple ("video/mpeg",
14264           "mpegversion", G_TYPE_INT, 2,
14265           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
14266       break;
14267     case 0x69:                 /* MPEG-2 BC audio */
14268     case 0x6B:                 /* MPEG-1 audio */
14269       caps = gst_caps_new_simple ("audio/mpeg",
14270           "mpegversion", G_TYPE_INT, 1, NULL);
14271       codec_name = "MPEG-1 audio";
14272       break;
14273     case 0x6A:                 /* MPEG-1 */
14274       codec_name = "MPEG-1 video";
14275       caps = gst_caps_new_simple ("video/mpeg",
14276           "mpegversion", G_TYPE_INT, 1,
14277           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
14278       break;
14279     case 0x6C:                 /* MJPEG */
14280       caps =
14281           gst_caps_new_simple ("image/jpeg", "parsed", G_TYPE_BOOLEAN, TRUE,
14282           NULL);
14283       codec_name = "Motion-JPEG";
14284       break;
14285     case 0x6D:                 /* PNG */
14286       caps =
14287           gst_caps_new_simple ("image/png", "parsed", G_TYPE_BOOLEAN, TRUE,
14288           NULL);
14289       codec_name = "PNG still images";
14290       break;
14291     case 0x6E:                 /* JPEG2000 */
14292       codec_name = "JPEG-2000";
14293       caps = gst_caps_new_simple ("image/x-j2c", "fields", G_TYPE_INT, 1, NULL);
14294       break;
14295     case 0xA4:                 /* Dirac */
14296       codec_name = "Dirac";
14297       caps = gst_caps_new_empty_simple ("video/x-dirac");
14298       break;
14299     case 0xA5:                 /* AC3 */
14300       codec_name = "AC-3 audio";
14301       caps = gst_caps_new_simple ("audio/x-ac3",
14302           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
14303       break;
14304     case 0xA9:                 /* AC3 */
14305       codec_name = "DTS audio";
14306       caps = gst_caps_new_simple ("audio/x-dts",
14307           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
14308       break;
14309     case 0xDD:
14310       if (stream_type == 0x05 && data_ptr) {
14311         GList *headers =
14312             parse_xiph_stream_headers (qtdemux, data_ptr, data_len);
14313         if (headers) {
14314           GList *tmp;
14315           GValue arr_val = G_VALUE_INIT;
14316           GValue buf_val = G_VALUE_INIT;
14317           GstStructure *s;
14318
14319           /* Let's assume it's vorbis if it's an audio stream of type 0xdd and we have codec data that extracts properly */
14320           codec_name = "Vorbis";
14321           caps = gst_caps_new_empty_simple ("audio/x-vorbis");
14322           g_value_init (&arr_val, GST_TYPE_ARRAY);
14323           g_value_init (&buf_val, GST_TYPE_BUFFER);
14324           for (tmp = headers; tmp; tmp = tmp->next) {
14325             g_value_set_boxed (&buf_val, (GstBuffer *) tmp->data);
14326             gst_value_array_append_value (&arr_val, &buf_val);
14327           }
14328           s = gst_caps_get_structure (caps, 0);
14329           gst_structure_take_value (s, "streamheader", &arr_val);
14330           g_value_unset (&buf_val);
14331           g_list_free (headers);
14332
14333           data_ptr = NULL;
14334           data_len = 0;
14335         }
14336       }
14337       break;
14338     case 0xE1:                 /* QCELP */
14339       /* QCELP, the codec_data is a riff tag (little endian) with
14340        * 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). */
14341       caps = gst_caps_new_empty_simple ("audio/qcelp");
14342       codec_name = "QCELP";
14343       break;
14344     default:
14345       break;
14346   }
14347
14348   /* If we have a replacement caps, then change our caps for this stream */
14349   if (caps) {
14350     gst_caps_unref (entry->caps);
14351     entry->caps = caps;
14352   }
14353
14354   if (codec_name && list)
14355     gst_tag_list_add (list, GST_TAG_MERGE_REPLACE,
14356         GST_TAG_AUDIO_CODEC, codec_name, NULL);
14357
14358   /* Add the codec_data attribute to caps, if we have it */
14359   if (data_ptr) {
14360     GstBuffer *buffer;
14361
14362     buffer = gst_buffer_new_and_alloc (data_len);
14363     gst_buffer_fill (buffer, 0, data_ptr, data_len);
14364
14365     GST_DEBUG_OBJECT (qtdemux, "setting codec_data from esds");
14366     GST_MEMDUMP_OBJECT (qtdemux, "codec_data from esds", data_ptr, data_len);
14367
14368     gst_caps_set_simple (entry->caps, "codec_data", GST_TYPE_BUFFER,
14369         buffer, NULL);
14370     gst_buffer_unref (buffer);
14371   }
14372
14373 }
14374
14375 static inline GstCaps *
14376 _get_unknown_codec_name (const gchar * type, guint32 fourcc)
14377 {
14378   GstCaps *caps;
14379   guint i;
14380   char *s, fourstr[5];
14381
14382   g_snprintf (fourstr, 5, "%" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (fourcc));
14383   for (i = 0; i < 4; i++) {
14384     if (!g_ascii_isalnum (fourstr[i]))
14385       fourstr[i] = '_';
14386   }
14387   s = g_strdup_printf ("%s/x-gst-fourcc-%s", type, g_strstrip (fourstr));
14388   caps = gst_caps_new_empty_simple (s);
14389   g_free (s);
14390   return caps;
14391 }
14392
14393 #define _codec(name) \
14394   do { \
14395     if (codec_name) { \
14396       *codec_name = g_strdup (name); \
14397     } \
14398   } while (0)
14399
14400 static GstCaps *
14401 qtdemux_video_caps (GstQTDemux * qtdemux, QtDemuxStream * stream,
14402     QtDemuxStreamStsdEntry * entry, guint32 fourcc,
14403     const guint8 * stsd_entry_data, gchar ** codec_name)
14404 {
14405   GstCaps *caps = NULL;
14406   GstVideoFormat format = GST_VIDEO_FORMAT_UNKNOWN;
14407
14408   switch (fourcc) {
14409     case FOURCC_png:
14410       _codec ("PNG still images");
14411       caps = gst_caps_new_empty_simple ("image/png");
14412       break;
14413     case FOURCC_jpeg:
14414       _codec ("JPEG still images");
14415       caps =
14416           gst_caps_new_simple ("image/jpeg", "parsed", G_TYPE_BOOLEAN, TRUE,
14417           NULL);
14418       break;
14419     case GST_MAKE_FOURCC ('m', 'j', 'p', 'a'):
14420     case GST_MAKE_FOURCC ('A', 'V', 'D', 'J'):
14421     case GST_MAKE_FOURCC ('M', 'J', 'P', 'G'):
14422     case GST_MAKE_FOURCC ('d', 'm', 'b', '1'):
14423       _codec ("Motion-JPEG");
14424       caps =
14425           gst_caps_new_simple ("image/jpeg", "parsed", G_TYPE_BOOLEAN, TRUE,
14426           NULL);
14427       break;
14428     case GST_MAKE_FOURCC ('m', 'j', 'p', 'b'):
14429       _codec ("Motion-JPEG format B");
14430       caps = gst_caps_new_empty_simple ("video/x-mjpeg-b");
14431       break;
14432     case FOURCC_mjp2:
14433       _codec ("JPEG-2000");
14434       /* override to what it should be according to spec, avoid palette_data */
14435       entry->bits_per_sample = 24;
14436       caps = gst_caps_new_simple ("image/x-j2c", "fields", G_TYPE_INT, 1, NULL);
14437       break;
14438     case FOURCC_SVQ3:
14439       _codec ("Sorensen video v.3");
14440       caps = gst_caps_new_simple ("video/x-svq",
14441           "svqversion", G_TYPE_INT, 3, NULL);
14442       break;
14443     case GST_MAKE_FOURCC ('s', 'v', 'q', 'i'):
14444     case GST_MAKE_FOURCC ('S', 'V', 'Q', '1'):
14445       _codec ("Sorensen video v.1");
14446       caps = gst_caps_new_simple ("video/x-svq",
14447           "svqversion", G_TYPE_INT, 1, NULL);
14448       break;
14449     case GST_MAKE_FOURCC ('W', 'R', 'A', 'W'):
14450       caps = gst_caps_new_empty_simple ("video/x-raw");
14451       gst_caps_set_simple (caps, "format", G_TYPE_STRING, "RGB8P", NULL);
14452       _codec ("Windows Raw RGB");
14453       stream->alignment = 32;
14454       break;
14455     case FOURCC_raw_:
14456     {
14457       guint16 bps;
14458
14459       bps = QT_UINT16 (stsd_entry_data + 82);
14460       switch (bps) {
14461         case 15:
14462           format = GST_VIDEO_FORMAT_RGB15;
14463           break;
14464         case 16:
14465           format = GST_VIDEO_FORMAT_RGB16;
14466           break;
14467         case 24:
14468           format = GST_VIDEO_FORMAT_RGB;
14469           break;
14470         case 32:
14471           format = GST_VIDEO_FORMAT_ARGB;
14472           break;
14473         default:
14474           /* unknown */
14475           break;
14476       }
14477       break;
14478     }
14479     case GST_MAKE_FOURCC ('y', 'v', '1', '2'):
14480       format = GST_VIDEO_FORMAT_I420;
14481       break;
14482     case GST_MAKE_FOURCC ('y', 'u', 'v', '2'):
14483     case GST_MAKE_FOURCC ('Y', 'u', 'v', '2'):
14484       format = GST_VIDEO_FORMAT_I420;
14485       break;
14486     case FOURCC_2vuy:
14487     case GST_MAKE_FOURCC ('2', 'V', 'u', 'y'):
14488       format = GST_VIDEO_FORMAT_UYVY;
14489       break;
14490     case GST_MAKE_FOURCC ('v', '3', '0', '8'):
14491       format = GST_VIDEO_FORMAT_v308;
14492       break;
14493     case GST_MAKE_FOURCC ('v', '2', '1', '6'):
14494       format = GST_VIDEO_FORMAT_v216;
14495       break;
14496     case FOURCC_v210:
14497       format = GST_VIDEO_FORMAT_v210;
14498       break;
14499     case GST_MAKE_FOURCC ('r', '2', '1', '0'):
14500       format = GST_VIDEO_FORMAT_r210;
14501       break;
14502       /* Packed YUV 4:4:4 10 bit in 32 bits, complex
14503          case GST_MAKE_FOURCC ('v', '4', '1', '0'):
14504          format = GST_VIDEO_FORMAT_v410;
14505          break;
14506        */
14507       /* Packed YUV 4:4:4:4 8 bit in 32 bits
14508        * but different order than AYUV
14509        case GST_MAKE_FOURCC ('v', '4', '0', '8'):
14510        format = GST_VIDEO_FORMAT_v408;
14511        break;
14512        */
14513     case GST_MAKE_FOURCC ('m', 'p', 'e', 'g'):
14514     case GST_MAKE_FOURCC ('m', 'p', 'g', '1'):
14515       _codec ("MPEG-1 video");
14516       caps = gst_caps_new_simple ("video/mpeg", "mpegversion", G_TYPE_INT, 1,
14517           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
14518       break;
14519     case GST_MAKE_FOURCC ('h', 'd', 'v', '1'): /* HDV 720p30 */
14520     case GST_MAKE_FOURCC ('h', 'd', 'v', '2'): /* HDV 1080i60 */
14521     case GST_MAKE_FOURCC ('h', 'd', 'v', '3'): /* HDV 1080i50 */
14522     case GST_MAKE_FOURCC ('h', 'd', 'v', '4'): /* HDV 720p24 */
14523     case GST_MAKE_FOURCC ('h', 'd', 'v', '5'): /* HDV 720p25 */
14524     case GST_MAKE_FOURCC ('h', 'd', 'v', '6'): /* HDV 1080p24 */
14525     case GST_MAKE_FOURCC ('h', 'd', 'v', '7'): /* HDV 1080p25 */
14526     case GST_MAKE_FOURCC ('h', 'd', 'v', '8'): /* HDV 1080p30 */
14527     case GST_MAKE_FOURCC ('h', 'd', 'v', '9'): /* HDV 720p60 */
14528     case GST_MAKE_FOURCC ('h', 'd', 'v', 'a'): /* HDV 720p50 */
14529     case GST_MAKE_FOURCC ('m', 'x', '5', 'n'): /* MPEG2 IMX NTSC 525/60 50mb/s produced by FCP */
14530     case GST_MAKE_FOURCC ('m', 'x', '5', 'p'): /* MPEG2 IMX PAL 625/60 50mb/s produced by FCP */
14531     case GST_MAKE_FOURCC ('m', 'x', '4', 'n'): /* MPEG2 IMX NTSC 525/60 40mb/s produced by FCP */
14532     case GST_MAKE_FOURCC ('m', 'x', '4', 'p'): /* MPEG2 IMX PAL 625/60 40mb/s produced by FCP */
14533     case GST_MAKE_FOURCC ('m', 'x', '3', 'n'): /* MPEG2 IMX NTSC 525/60 30mb/s produced by FCP */
14534     case GST_MAKE_FOURCC ('m', 'x', '3', 'p'): /* MPEG2 IMX PAL 625/50 30mb/s produced by FCP */
14535     case GST_MAKE_FOURCC ('x', 'd', 'v', '1'): /* XDCAM HD 720p30 35Mb/s */
14536     case GST_MAKE_FOURCC ('x', 'd', 'v', '2'): /* XDCAM HD 1080i60 35Mb/s */
14537     case GST_MAKE_FOURCC ('x', 'd', 'v', '3'): /* XDCAM HD 1080i50 35Mb/s */
14538     case GST_MAKE_FOURCC ('x', 'd', 'v', '4'): /* XDCAM HD 720p24 35Mb/s */
14539     case GST_MAKE_FOURCC ('x', 'd', 'v', '5'): /* XDCAM HD 720p25 35Mb/s */
14540     case GST_MAKE_FOURCC ('x', 'd', 'v', '6'): /* XDCAM HD 1080p24 35Mb/s */
14541     case GST_MAKE_FOURCC ('x', 'd', 'v', '7'): /* XDCAM HD 1080p25 35Mb/s */
14542     case GST_MAKE_FOURCC ('x', 'd', 'v', '8'): /* XDCAM HD 1080p30 35Mb/s */
14543     case GST_MAKE_FOURCC ('x', 'd', 'v', '9'): /* XDCAM HD 720p60 35Mb/s */
14544     case GST_MAKE_FOURCC ('x', 'd', 'v', 'a'): /* XDCAM HD 720p50 35Mb/s */
14545     case GST_MAKE_FOURCC ('x', 'd', 'v', 'b'): /* XDCAM EX 1080i60 50Mb/s CBR */
14546     case GST_MAKE_FOURCC ('x', 'd', 'v', 'c'): /* XDCAM EX 1080i50 50Mb/s CBR */
14547     case GST_MAKE_FOURCC ('x', 'd', 'v', 'd'): /* XDCAM HD 1080p24 50Mb/s CBR */
14548     case GST_MAKE_FOURCC ('x', 'd', 'v', 'e'): /* XDCAM HD 1080p25 50Mb/s CBR */
14549     case GST_MAKE_FOURCC ('x', 'd', 'v', 'f'): /* XDCAM HD 1080p30 50Mb/s CBR */
14550     case GST_MAKE_FOURCC ('x', 'd', '5', '1'): /* XDCAM HD422 720p30 50Mb/s CBR */
14551     case GST_MAKE_FOURCC ('x', 'd', '5', '4'): /* XDCAM HD422 720p24 50Mb/s CBR */
14552     case GST_MAKE_FOURCC ('x', 'd', '5', '5'): /* XDCAM HD422 720p25 50Mb/s CBR */
14553     case GST_MAKE_FOURCC ('x', 'd', '5', '9'): /* XDCAM HD422 720p60 50Mb/s CBR */
14554     case GST_MAKE_FOURCC ('x', 'd', '5', 'a'): /* XDCAM HD422 720p50 50Mb/s CBR */
14555     case GST_MAKE_FOURCC ('x', 'd', '5', 'b'): /* XDCAM HD422 1080i50 50Mb/s CBR */
14556     case GST_MAKE_FOURCC ('x', 'd', '5', 'c'): /* XDCAM HD422 1080i50 50Mb/s CBR */
14557     case GST_MAKE_FOURCC ('x', 'd', '5', 'd'): /* XDCAM HD422 1080p24 50Mb/s CBR */
14558     case GST_MAKE_FOURCC ('x', 'd', '5', 'e'): /* XDCAM HD422 1080p25 50Mb/s CBR */
14559     case GST_MAKE_FOURCC ('x', 'd', '5', 'f'): /* XDCAM HD422 1080p30 50Mb/s CBR */
14560     case GST_MAKE_FOURCC ('x', 'd', 'h', 'd'): /* XDCAM HD 540p */
14561     case GST_MAKE_FOURCC ('x', 'd', 'h', '2'): /* XDCAM HD422 540p */
14562     case GST_MAKE_FOURCC ('A', 'V', 'm', 'p'): /* AVID IMX PAL */
14563     case GST_MAKE_FOURCC ('m', 'p', 'g', '2'): /* AVID IMX PAL */
14564     case GST_MAKE_FOURCC ('m', 'p', '2', 'v'): /* AVID IMX PAL */
14565     case GST_MAKE_FOURCC ('m', '2', 'v', '1'):
14566       _codec ("MPEG-2 video");
14567       caps = gst_caps_new_simple ("video/mpeg", "mpegversion", G_TYPE_INT, 2,
14568           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
14569       break;
14570     case GST_MAKE_FOURCC ('g', 'i', 'f', ' '):
14571       _codec ("GIF still images");
14572       caps = gst_caps_new_empty_simple ("image/gif");
14573       break;
14574     case FOURCC_h263:
14575     case GST_MAKE_FOURCC ('H', '2', '6', '3'):
14576     case FOURCC_s263:
14577     case GST_MAKE_FOURCC ('U', '2', '6', '3'):
14578       _codec ("H.263");
14579       /* ffmpeg uses the height/width props, don't know why */
14580       caps = gst_caps_new_simple ("video/x-h263",
14581           "variant", G_TYPE_STRING, "itu", NULL);
14582       break;
14583     case FOURCC_mp4v:
14584     case FOURCC_MP4V:
14585       _codec ("MPEG-4 video");
14586       caps = gst_caps_new_simple ("video/mpeg", "mpegversion", G_TYPE_INT, 4,
14587           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
14588       break;
14589     case GST_MAKE_FOURCC ('3', 'i', 'v', 'd'):
14590     case GST_MAKE_FOURCC ('3', 'I', 'V', 'D'):
14591       _codec ("Microsoft MPEG-4 4.3");  /* FIXME? */
14592       caps = gst_caps_new_simple ("video/x-msmpeg",
14593           "msmpegversion", G_TYPE_INT, 43, NULL);
14594       break;
14595     case GST_MAKE_FOURCC ('D', 'I', 'V', '3'):
14596       _codec ("DivX 3");
14597       caps = gst_caps_new_simple ("video/x-divx",
14598           "divxversion", G_TYPE_INT, 3, NULL);
14599       break;
14600     case GST_MAKE_FOURCC ('D', 'I', 'V', 'X'):
14601     case GST_MAKE_FOURCC ('d', 'i', 'v', 'x'):
14602       _codec ("DivX 4");
14603       caps = gst_caps_new_simple ("video/x-divx",
14604           "divxversion", G_TYPE_INT, 4, NULL);
14605       break;
14606     case GST_MAKE_FOURCC ('D', 'X', '5', '0'):
14607       _codec ("DivX 5");
14608       caps = gst_caps_new_simple ("video/x-divx",
14609           "divxversion", G_TYPE_INT, 5, NULL);
14610       break;
14611
14612     case GST_MAKE_FOURCC ('F', 'F', 'V', '1'):
14613       _codec ("FFV1");
14614       caps = gst_caps_new_simple ("video/x-ffv",
14615           "ffvversion", G_TYPE_INT, 1, NULL);
14616       break;
14617
14618     case GST_MAKE_FOURCC ('3', 'I', 'V', '1'):
14619     case GST_MAKE_FOURCC ('3', 'I', 'V', '2'):
14620     case FOURCC_XVID:
14621     case FOURCC_xvid:
14622     case FOURCC_FMP4:
14623     case FOURCC_fmp4:
14624     case GST_MAKE_FOURCC ('U', 'M', 'P', '4'):
14625       caps = gst_caps_new_simple ("video/mpeg", "mpegversion", G_TYPE_INT, 4,
14626           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
14627       _codec ("MPEG-4");
14628       break;
14629
14630     case GST_MAKE_FOURCC ('c', 'v', 'i', 'd'):
14631       _codec ("Cinepak");
14632       caps = gst_caps_new_empty_simple ("video/x-cinepak");
14633       break;
14634     case GST_MAKE_FOURCC ('q', 'd', 'r', 'w'):
14635       _codec ("Apple QuickDraw");
14636       caps = gst_caps_new_empty_simple ("video/x-qdrw");
14637       break;
14638     case GST_MAKE_FOURCC ('r', 'p', 'z', 'a'):
14639       _codec ("Apple video");
14640       caps = gst_caps_new_empty_simple ("video/x-apple-video");
14641       break;
14642     case FOURCC_H264:
14643     case FOURCC_avc1:
14644       _codec ("H.264 / AVC");
14645       caps = gst_caps_new_simple ("video/x-h264",
14646           "stream-format", G_TYPE_STRING, "avc",
14647           "alignment", G_TYPE_STRING, "au", NULL);
14648       break;
14649     case FOURCC_avc3:
14650       _codec ("H.264 / AVC");
14651       caps = gst_caps_new_simple ("video/x-h264",
14652           "stream-format", G_TYPE_STRING, "avc3",
14653           "alignment", G_TYPE_STRING, "au", NULL);
14654       break;
14655     case FOURCC_H265:
14656     case FOURCC_hvc1:
14657       _codec ("H.265 / HEVC");
14658       caps = gst_caps_new_simple ("video/x-h265",
14659           "stream-format", G_TYPE_STRING, "hvc1",
14660           "alignment", G_TYPE_STRING, "au", NULL);
14661       break;
14662     case FOURCC_hev1:
14663       _codec ("H.265 / HEVC");
14664       caps = gst_caps_new_simple ("video/x-h265",
14665           "stream-format", G_TYPE_STRING, "hev1",
14666           "alignment", G_TYPE_STRING, "au", NULL);
14667       break;
14668     case FOURCC_rle_:
14669       _codec ("Run-length encoding");
14670       caps = gst_caps_new_simple ("video/x-rle",
14671           "layout", G_TYPE_STRING, "quicktime", NULL);
14672       break;
14673     case FOURCC_WRLE:
14674       _codec ("Run-length encoding");
14675       caps = gst_caps_new_simple ("video/x-rle",
14676           "layout", G_TYPE_STRING, "microsoft", NULL);
14677       break;
14678     case GST_MAKE_FOURCC ('I', 'V', '3', '2'):
14679     case GST_MAKE_FOURCC ('i', 'v', '3', '2'):
14680       _codec ("Indeo Video 3");
14681       caps = gst_caps_new_simple ("video/x-indeo",
14682           "indeoversion", G_TYPE_INT, 3, NULL);
14683       break;
14684     case GST_MAKE_FOURCC ('I', 'V', '4', '1'):
14685     case GST_MAKE_FOURCC ('i', 'v', '4', '1'):
14686       _codec ("Intel Video 4");
14687       caps = gst_caps_new_simple ("video/x-indeo",
14688           "indeoversion", G_TYPE_INT, 4, NULL);
14689       break;
14690     case FOURCC_dvcp:
14691     case FOURCC_dvc_:
14692     case GST_MAKE_FOURCC ('d', 'v', 's', 'd'):
14693     case GST_MAKE_FOURCC ('D', 'V', 'S', 'D'):
14694     case GST_MAKE_FOURCC ('d', 'v', 'c', 's'):
14695     case GST_MAKE_FOURCC ('D', 'V', 'C', 'S'):
14696     case GST_MAKE_FOURCC ('d', 'v', '2', '5'):
14697     case GST_MAKE_FOURCC ('d', 'v', 'p', 'p'):
14698       _codec ("DV Video");
14699       caps = gst_caps_new_simple ("video/x-dv", "dvversion", G_TYPE_INT, 25,
14700           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
14701       break;
14702     case FOURCC_dv5n:          /* DVCPRO50 NTSC */
14703     case FOURCC_dv5p:          /* DVCPRO50 PAL */
14704       _codec ("DVCPro50 Video");
14705       caps = gst_caps_new_simple ("video/x-dv", "dvversion", G_TYPE_INT, 50,
14706           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
14707       break;
14708     case GST_MAKE_FOURCC ('d', 'v', 'h', '5'): /* DVCPRO HD 50i produced by FCP */
14709     case GST_MAKE_FOURCC ('d', 'v', 'h', '6'): /* DVCPRO HD 60i produced by FCP */
14710       _codec ("DVCProHD Video");
14711       caps = gst_caps_new_simple ("video/x-dv", "dvversion", G_TYPE_INT, 100,
14712           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
14713       break;
14714     case GST_MAKE_FOURCC ('s', 'm', 'c', ' '):
14715       _codec ("Apple Graphics (SMC)");
14716       caps = gst_caps_new_empty_simple ("video/x-smc");
14717       break;
14718     case GST_MAKE_FOURCC ('V', 'P', '3', '1'):
14719       _codec ("VP3");
14720       caps = gst_caps_new_empty_simple ("video/x-vp3");
14721       break;
14722     case GST_MAKE_FOURCC ('V', 'P', '6', 'F'):
14723       _codec ("VP6 Flash");
14724       caps = gst_caps_new_empty_simple ("video/x-vp6-flash");
14725       break;
14726     case FOURCC_XiTh:
14727       _codec ("Theora");
14728       caps = gst_caps_new_empty_simple ("video/x-theora");
14729       /* theora uses one byte of padding in the data stream because it does not
14730        * allow 0 sized packets while theora does */
14731       entry->padding = 1;
14732       break;
14733     case FOURCC_drac:
14734       _codec ("Dirac");
14735       caps = gst_caps_new_empty_simple ("video/x-dirac");
14736       break;
14737     case GST_MAKE_FOURCC ('t', 'i', 'f', 'f'):
14738       _codec ("TIFF still images");
14739       caps = gst_caps_new_empty_simple ("image/tiff");
14740       break;
14741     case GST_MAKE_FOURCC ('i', 'c', 'o', 'd'):
14742       _codec ("Apple Intermediate Codec");
14743       caps = gst_caps_from_string ("video/x-apple-intermediate-codec");
14744       break;
14745     case GST_MAKE_FOURCC ('A', 'V', 'd', 'n'):
14746       _codec ("AVID DNxHD");
14747       caps = gst_caps_from_string ("video/x-dnxhd");
14748       break;
14749     case FOURCC_VP80:
14750     case FOURCC_vp08:
14751       _codec ("On2 VP8");
14752       caps = gst_caps_from_string ("video/x-vp8");
14753       break;
14754     case FOURCC_vp09:
14755       _codec ("Google VP9");
14756       caps = gst_caps_from_string ("video/x-vp9");
14757       break;
14758     case FOURCC_apcs:
14759       _codec ("Apple ProRes LT");
14760       caps =
14761           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING, "lt",
14762           NULL);
14763       break;
14764     case FOURCC_apch:
14765       _codec ("Apple ProRes HQ");
14766       caps =
14767           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING, "hq",
14768           NULL);
14769       break;
14770     case FOURCC_apcn:
14771       _codec ("Apple ProRes");
14772       caps =
14773           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING,
14774           "standard", NULL);
14775       break;
14776     case FOURCC_apco:
14777       _codec ("Apple ProRes Proxy");
14778       caps =
14779           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING,
14780           "proxy", NULL);
14781       break;
14782     case FOURCC_ap4h:
14783       _codec ("Apple ProRes 4444");
14784       caps =
14785           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING,
14786           "4444", NULL);
14787       break;
14788     case FOURCC_ap4x:
14789       _codec ("Apple ProRes 4444 XQ");
14790       caps =
14791           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING,
14792           "4444xq", NULL);
14793       break;
14794     case FOURCC_cfhd:
14795       _codec ("GoPro CineForm");
14796       caps = gst_caps_from_string ("video/x-cineform");
14797       break;
14798     case FOURCC_vc_1:
14799     case FOURCC_ovc1:
14800       _codec ("VC-1");
14801       caps = gst_caps_new_simple ("video/x-wmv",
14802           "wmvversion", G_TYPE_INT, 3, "format", G_TYPE_STRING, "WVC1", NULL);
14803       break;
14804     case FOURCC_av01:
14805       _codec ("AV1");
14806       caps = gst_caps_new_empty_simple ("video/x-av1");
14807       break;
14808     case GST_MAKE_FOURCC ('k', 'p', 'c', 'd'):
14809     default:
14810     {
14811       caps = _get_unknown_codec_name ("video", fourcc);
14812       break;
14813     }
14814   }
14815
14816   if (format != GST_VIDEO_FORMAT_UNKNOWN) {
14817     GstVideoInfo info;
14818
14819     gst_video_info_init (&info);
14820     gst_video_info_set_format (&info, format, entry->width, entry->height);
14821
14822     caps = gst_video_info_to_caps (&info);
14823     *codec_name = gst_pb_utils_get_codec_description (caps);
14824
14825     /* enable clipping for raw video streams */
14826     stream->need_clip = TRUE;
14827     stream->alignment = 32;
14828   }
14829
14830   return caps;
14831 }
14832
14833 static guint
14834 round_up_pow2 (guint n)
14835 {
14836   n = n - 1;
14837   n = n | (n >> 1);
14838   n = n | (n >> 2);
14839   n = n | (n >> 4);
14840   n = n | (n >> 8);
14841   n = n | (n >> 16);
14842   return n + 1;
14843 }
14844
14845 static GstCaps *
14846 qtdemux_audio_caps (GstQTDemux * qtdemux, QtDemuxStream * stream,
14847     QtDemuxStreamStsdEntry * entry, guint32 fourcc, const guint8 * data,
14848     int len, gchar ** codec_name)
14849 {
14850   GstCaps *caps;
14851   const GstStructure *s;
14852   const gchar *name;
14853   gint endian = 0;
14854   GstAudioFormat format = 0;
14855   gint depth;
14856
14857   GST_DEBUG_OBJECT (qtdemux, "resolve fourcc 0x%08x", GUINT32_TO_BE (fourcc));
14858
14859   depth = entry->bytes_per_packet * 8;
14860
14861   switch (fourcc) {
14862     case GST_MAKE_FOURCC ('N', 'O', 'N', 'E'):
14863     case FOURCC_raw_:
14864       /* 8-bit audio is unsigned */
14865       if (depth == 8)
14866         format = GST_AUDIO_FORMAT_U8;
14867       /* otherwise it's signed and big-endian just like 'twos' */
14868     case FOURCC_twos:
14869       endian = G_BIG_ENDIAN;
14870       /* fall-through */
14871     case FOURCC_sowt:
14872     {
14873       gchar *str;
14874
14875       if (!endian)
14876         endian = G_LITTLE_ENDIAN;
14877
14878       if (!format)
14879         format = gst_audio_format_build_integer (TRUE, endian, depth, depth);
14880
14881       str = g_strdup_printf ("Raw %d-bit PCM audio", depth);
14882       _codec (str);
14883       g_free (str);
14884
14885       caps = gst_caps_new_simple ("audio/x-raw",
14886           "format", G_TYPE_STRING, gst_audio_format_to_string (format),
14887           "layout", G_TYPE_STRING, "interleaved", NULL);
14888       stream->alignment = GST_ROUND_UP_8 (depth);
14889       stream->alignment = round_up_pow2 (stream->alignment);
14890       break;
14891     }
14892     case GST_MAKE_FOURCC ('f', 'l', '6', '4'):
14893       _codec ("Raw 64-bit floating-point audio");
14894       caps = gst_caps_new_simple ("audio/x-raw",
14895           "format", G_TYPE_STRING, "F64BE",
14896           "layout", G_TYPE_STRING, "interleaved", NULL);
14897       stream->alignment = 8;
14898       break;
14899     case GST_MAKE_FOURCC ('f', 'l', '3', '2'):
14900       _codec ("Raw 32-bit floating-point audio");
14901       caps = gst_caps_new_simple ("audio/x-raw",
14902           "format", G_TYPE_STRING, "F32BE",
14903           "layout", G_TYPE_STRING, "interleaved", NULL);
14904       stream->alignment = 4;
14905       break;
14906     case FOURCC_in24:
14907       _codec ("Raw 24-bit PCM audio");
14908       /* we assume BIG ENDIAN, an enda box will tell us to change this to little
14909        * endian later */
14910       caps = gst_caps_new_simple ("audio/x-raw",
14911           "format", G_TYPE_STRING, "S24BE",
14912           "layout", G_TYPE_STRING, "interleaved", NULL);
14913       stream->alignment = 4;
14914       break;
14915     case GST_MAKE_FOURCC ('i', 'n', '3', '2'):
14916       _codec ("Raw 32-bit PCM audio");
14917       caps = gst_caps_new_simple ("audio/x-raw",
14918           "format", G_TYPE_STRING, "S32BE",
14919           "layout", G_TYPE_STRING, "interleaved", NULL);
14920       stream->alignment = 4;
14921       break;
14922     case GST_MAKE_FOURCC ('s', '1', '6', 'l'):
14923       _codec ("Raw 16-bit PCM audio");
14924       caps = gst_caps_new_simple ("audio/x-raw",
14925           "format", G_TYPE_STRING, "S16LE",
14926           "layout", G_TYPE_STRING, "interleaved", NULL);
14927       stream->alignment = 2;
14928       break;
14929     case FOURCC_ulaw:
14930       _codec ("Mu-law audio");
14931       caps = gst_caps_new_empty_simple ("audio/x-mulaw");
14932       break;
14933     case FOURCC_alaw:
14934       _codec ("A-law audio");
14935       caps = gst_caps_new_empty_simple ("audio/x-alaw");
14936       break;
14937     case 0x0200736d:
14938     case 0x6d730002:
14939       _codec ("Microsoft ADPCM");
14940       /* Microsoft ADPCM-ACM code 2 */
14941       caps = gst_caps_new_simple ("audio/x-adpcm",
14942           "layout", G_TYPE_STRING, "microsoft", NULL);
14943       break;
14944     case 0x1100736d:
14945     case 0x6d730011:
14946       _codec ("DVI/IMA ADPCM");
14947       caps = gst_caps_new_simple ("audio/x-adpcm",
14948           "layout", G_TYPE_STRING, "dvi", NULL);
14949       break;
14950     case 0x1700736d:
14951     case 0x6d730017:
14952       _codec ("DVI/Intel IMA ADPCM");
14953       /* FIXME DVI/Intel IMA ADPCM/ACM code 17 */
14954       caps = gst_caps_new_simple ("audio/x-adpcm",
14955           "layout", G_TYPE_STRING, "quicktime", NULL);
14956       break;
14957     case 0x5500736d:
14958     case 0x6d730055:
14959       /* MPEG layer 3, CBR only (pre QT4.1) */
14960     case FOURCC__mp3:
14961       _codec ("MPEG-1 layer 3");
14962       /* MPEG layer 3, CBR & VBR (QT4.1 and later) */
14963       caps = gst_caps_new_simple ("audio/mpeg", "layer", G_TYPE_INT, 3,
14964           "mpegversion", G_TYPE_INT, 1, NULL);
14965       break;
14966     case GST_MAKE_FOURCC ('.', 'm', 'p', '2'):
14967       _codec ("MPEG-1 layer 2");
14968       /* MPEG layer 2 */
14969       caps = gst_caps_new_simple ("audio/mpeg", "layer", G_TYPE_INT, 2,
14970           "mpegversion", G_TYPE_INT, 1, NULL);
14971       break;
14972     case 0x20736d:
14973     case GST_MAKE_FOURCC ('e', 'c', '-', '3'):
14974       _codec ("EAC-3 audio");
14975       caps = gst_caps_new_simple ("audio/x-eac3",
14976           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
14977       entry->sampled = TRUE;
14978       break;
14979     case GST_MAKE_FOURCC ('s', 'a', 'c', '3'): // Nero Recode
14980     case FOURCC_ac_3:
14981       _codec ("AC-3 audio");
14982       caps = gst_caps_new_simple ("audio/x-ac3",
14983           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
14984       entry->sampled = TRUE;
14985       break;
14986     case GST_MAKE_FOURCC ('d', 't', 's', 'c'):
14987     case GST_MAKE_FOURCC ('D', 'T', 'S', ' '):
14988       _codec ("DTS audio");
14989       caps = gst_caps_new_simple ("audio/x-dts",
14990           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
14991       entry->sampled = TRUE;
14992       break;
14993     case GST_MAKE_FOURCC ('d', 't', 's', 'h'): // DTS-HD
14994     case GST_MAKE_FOURCC ('d', 't', 's', 'l'): // DTS-HD Lossless
14995       _codec ("DTS-HD audio");
14996       caps = gst_caps_new_simple ("audio/x-dts",
14997           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
14998       entry->sampled = TRUE;
14999       break;
15000     case FOURCC_MAC3:
15001       _codec ("MACE-3");
15002       caps = gst_caps_new_simple ("audio/x-mace",
15003           "maceversion", G_TYPE_INT, 3, NULL);
15004       break;
15005     case FOURCC_MAC6:
15006       _codec ("MACE-6");
15007       caps = gst_caps_new_simple ("audio/x-mace",
15008           "maceversion", G_TYPE_INT, 6, NULL);
15009       break;
15010     case GST_MAKE_FOURCC ('O', 'g', 'g', 'V'):
15011       /* ogg/vorbis */
15012       caps = gst_caps_new_empty_simple ("application/ogg");
15013       break;
15014     case GST_MAKE_FOURCC ('d', 'v', 'c', 'a'):
15015       _codec ("DV audio");
15016       caps = gst_caps_new_empty_simple ("audio/x-dv");
15017       break;
15018     case FOURCC_mp4a:
15019       _codec ("MPEG-4 AAC audio");
15020       caps = gst_caps_new_simple ("audio/mpeg",
15021           "mpegversion", G_TYPE_INT, 4, "framed", G_TYPE_BOOLEAN, TRUE,
15022           "stream-format", G_TYPE_STRING, "raw", NULL);
15023       break;
15024     case GST_MAKE_FOURCC ('Q', 'D', 'M', 'C'):
15025       _codec ("QDesign Music");
15026       caps = gst_caps_new_empty_simple ("audio/x-qdm");
15027       break;
15028     case FOURCC_QDM2:
15029       _codec ("QDesign Music v.2");
15030       /* FIXME: QDesign music version 2 (no constant) */
15031       if (FALSE && data) {
15032         caps = gst_caps_new_simple ("audio/x-qdm2",
15033             "framesize", G_TYPE_INT, QT_UINT32 (data + 52),
15034             "bitrate", G_TYPE_INT, QT_UINT32 (data + 40),
15035             "blocksize", G_TYPE_INT, QT_UINT32 (data + 44), NULL);
15036       } else {
15037         caps = gst_caps_new_empty_simple ("audio/x-qdm2");
15038       }
15039       break;
15040     case FOURCC_agsm:
15041       _codec ("GSM audio");
15042       caps = gst_caps_new_empty_simple ("audio/x-gsm");
15043       break;
15044     case FOURCC_samr:
15045       _codec ("AMR audio");
15046       caps = gst_caps_new_empty_simple ("audio/AMR");
15047       break;
15048     case FOURCC_sawb:
15049       _codec ("AMR-WB audio");
15050       caps = gst_caps_new_empty_simple ("audio/AMR-WB");
15051       break;
15052     case FOURCC_ima4:
15053       _codec ("Quicktime IMA ADPCM");
15054       caps = gst_caps_new_simple ("audio/x-adpcm",
15055           "layout", G_TYPE_STRING, "quicktime", NULL);
15056       break;
15057     case FOURCC_alac:
15058       _codec ("Apple lossless audio");
15059       caps = gst_caps_new_empty_simple ("audio/x-alac");
15060       break;
15061     case FOURCC_fLaC:
15062       _codec ("Free Lossless Audio Codec");
15063       caps = gst_caps_new_simple ("audio/x-flac",
15064           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
15065       break;
15066     case GST_MAKE_FOURCC ('Q', 'c', 'l', 'p'):
15067       _codec ("QualComm PureVoice");
15068       caps = gst_caps_from_string ("audio/qcelp");
15069       break;
15070     case FOURCC_wma_:
15071     case FOURCC_owma:
15072       _codec ("WMA");
15073       caps = gst_caps_new_empty_simple ("audio/x-wma");
15074       break;
15075     case FOURCC_opus:
15076       _codec ("Opus");
15077       caps = gst_caps_new_empty_simple ("audio/x-opus");
15078       break;
15079     case FOURCC_lpcm:
15080     {
15081       guint32 flags = 0;
15082       guint32 depth = 0;
15083       guint32 width = 0;
15084       GstAudioFormat format;
15085       enum
15086       {
15087         FLAG_IS_FLOAT = 0x1,
15088         FLAG_IS_BIG_ENDIAN = 0x2,
15089         FLAG_IS_SIGNED = 0x4,
15090         FLAG_IS_PACKED = 0x8,
15091         FLAG_IS_ALIGNED_HIGH = 0x10,
15092         FLAG_IS_NON_INTERLEAVED = 0x20
15093       };
15094       _codec ("Raw LPCM audio");
15095
15096       if (data && len >= 36) {
15097         depth = QT_UINT32 (data + 24);
15098         flags = QT_UINT32 (data + 28);
15099         width = QT_UINT32 (data + 32) * 8 / entry->n_channels;
15100       }
15101       if ((flags & FLAG_IS_FLOAT) == 0) {
15102         if (depth == 0)
15103           depth = 16;
15104         if (width == 0)
15105           width = 16;
15106         if ((flags & FLAG_IS_ALIGNED_HIGH))
15107           depth = width;
15108
15109         format = gst_audio_format_build_integer ((flags & FLAG_IS_SIGNED) ?
15110             TRUE : FALSE, (flags & FLAG_IS_BIG_ENDIAN) ?
15111             G_BIG_ENDIAN : G_LITTLE_ENDIAN, width, depth);
15112         caps = gst_caps_new_simple ("audio/x-raw",
15113             "format", G_TYPE_STRING,
15114             format !=
15115             GST_AUDIO_FORMAT_UNKNOWN ? gst_audio_format_to_string (format) :
15116             "UNKNOWN", "layout", G_TYPE_STRING,
15117             (flags & FLAG_IS_NON_INTERLEAVED) ? "non-interleaved" :
15118             "interleaved", NULL);
15119         stream->alignment = GST_ROUND_UP_8 (depth);
15120         stream->alignment = round_up_pow2 (stream->alignment);
15121       } else {
15122         if (width == 0)
15123           width = 32;
15124         if (width == 64) {
15125           if (flags & FLAG_IS_BIG_ENDIAN)
15126             format = GST_AUDIO_FORMAT_F64BE;
15127           else
15128             format = GST_AUDIO_FORMAT_F64LE;
15129         } else {
15130           if (flags & FLAG_IS_BIG_ENDIAN)
15131             format = GST_AUDIO_FORMAT_F32BE;
15132           else
15133             format = GST_AUDIO_FORMAT_F32LE;
15134         }
15135         caps = gst_caps_new_simple ("audio/x-raw",
15136             "format", G_TYPE_STRING, gst_audio_format_to_string (format),
15137             "layout", G_TYPE_STRING, (flags & FLAG_IS_NON_INTERLEAVED) ?
15138             "non-interleaved" : "interleaved", NULL);
15139         stream->alignment = width / 8;
15140       }
15141       break;
15142     }
15143     case GST_MAKE_FOURCC ('q', 't', 'v', 'r'):
15144       /* ? */
15145     default:
15146     {
15147       caps = _get_unknown_codec_name ("audio", fourcc);
15148       break;
15149     }
15150   }
15151
15152   if (caps) {
15153     GstCaps *templ_caps =
15154         gst_static_pad_template_get_caps (&gst_qtdemux_audiosrc_template);
15155     GstCaps *intersection = gst_caps_intersect (caps, templ_caps);
15156     gst_caps_unref (caps);
15157     gst_caps_unref (templ_caps);
15158     caps = intersection;
15159   }
15160
15161   /* enable clipping for raw audio streams */
15162   s = gst_caps_get_structure (caps, 0);
15163   name = gst_structure_get_name (s);
15164   if (g_str_has_prefix (name, "audio/x-raw")) {
15165     stream->need_clip = TRUE;
15166     stream->max_buffer_size = 4096 * entry->bytes_per_frame;
15167     GST_DEBUG ("setting max buffer size to %d", stream->max_buffer_size);
15168   }
15169   return caps;
15170 }
15171
15172 static GstCaps *
15173 qtdemux_sub_caps (GstQTDemux * qtdemux, QtDemuxStream * stream,
15174     QtDemuxStreamStsdEntry * entry, guint32 fourcc,
15175     const guint8 * stsd_entry_data, gchar ** codec_name)
15176 {
15177   GstCaps *caps;
15178
15179   GST_DEBUG_OBJECT (qtdemux, "resolve fourcc 0x%08x", GUINT32_TO_BE (fourcc));
15180
15181   switch (fourcc) {
15182     case FOURCC_mp4s:
15183       _codec ("DVD subtitle");
15184       caps = gst_caps_new_empty_simple ("subpicture/x-dvd");
15185       stream->need_process = TRUE;
15186       break;
15187     case FOURCC_text:
15188       _codec ("Quicktime timed text");
15189       goto text;
15190     case FOURCC_tx3g:
15191       _codec ("3GPP timed text");
15192     text:
15193       caps = gst_caps_new_simple ("text/x-raw", "format", G_TYPE_STRING,
15194           "utf8", NULL);
15195       /* actual text piece needs to be extracted */
15196       stream->need_process = TRUE;
15197       break;
15198     case FOURCC_stpp:
15199       _codec ("XML subtitles");
15200       caps = gst_caps_new_empty_simple ("application/ttml+xml");
15201       break;
15202     case FOURCC_c608:
15203       _codec ("CEA 608 Closed Caption");
15204       caps =
15205           gst_caps_new_simple ("closedcaption/x-cea-608", "format",
15206           G_TYPE_STRING, "cc_data", NULL);
15207       stream->need_process = TRUE;
15208       break;
15209     case FOURCC_c708:
15210       _codec ("CEA 708 Closed Caption");
15211       caps =
15212           gst_caps_new_simple ("closedcaption/x-cea-708", "format",
15213           G_TYPE_STRING, "cdp", NULL);
15214       stream->need_process = TRUE;
15215       break;
15216
15217     default:
15218     {
15219       caps = _get_unknown_codec_name ("text", fourcc);
15220       break;
15221     }
15222   }
15223   return caps;
15224 }
15225
15226 static GstCaps *
15227 qtdemux_generic_caps (GstQTDemux * qtdemux, QtDemuxStream * stream,
15228     QtDemuxStreamStsdEntry * entry, guint32 fourcc,
15229     const guint8 * stsd_entry_data, gchar ** codec_name)
15230 {
15231   GstCaps *caps;
15232
15233   switch (fourcc) {
15234     case FOURCC_m1v:
15235       _codec ("MPEG 1 video");
15236       caps = gst_caps_new_simple ("video/mpeg", "mpegversion", G_TYPE_INT, 1,
15237           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
15238       break;
15239     default:
15240       caps = NULL;
15241       break;
15242   }
15243   return caps;
15244 }
15245
15246 static void
15247 gst_qtdemux_append_protection_system_id (GstQTDemux * qtdemux,
15248     const gchar * system_id)
15249 {
15250   gint i;
15251
15252   if (!qtdemux->protection_system_ids)
15253     qtdemux->protection_system_ids =
15254         g_ptr_array_new_with_free_func ((GDestroyNotify) g_free);
15255   /* Check whether we already have an entry for this system ID. */
15256   for (i = 0; i < qtdemux->protection_system_ids->len; ++i) {
15257     const gchar *id = g_ptr_array_index (qtdemux->protection_system_ids, i);
15258     if (g_ascii_strcasecmp (system_id, id) == 0) {
15259       return;
15260     }
15261   }
15262   GST_DEBUG_OBJECT (qtdemux, "Adding cenc protection system ID %s", system_id);
15263   g_ptr_array_add (qtdemux->protection_system_ids, g_ascii_strdown (system_id,
15264           -1));
15265 }