qtdemux: Don't assert if a file does not have any active streams
[platform/upstream/gst-plugins-good.git] / gst / isomp4 / qtdemux.c
1 /* GStreamer
2  * Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu>
3  * Copyright (C) <2003> David A. Schleef <ds@schleef.org>
4  * Copyright (C) <2006> Wim Taymans <wim@fluendo.com>
5  * Copyright (C) <2007> Julien Moutte <julien@fluendo.com>
6  * Copyright (C) <2009> Tim-Philipp Müller <tim centricular net>
7  * Copyright (C) <2009> STEricsson <benjamin.gaignard@stericsson.com>
8  * Copyright (C) <2013> Sreerenj Balachandran <sreerenj.balachandran@intel.com>
9  * Copyright (C) <2013> Intel Corporation
10  * Copyright (C) <2014> Centricular Ltd
11  * Copyright (C) <2015> YouView TV Ltd.
12  * Copyright (C) <2016> British Broadcasting Corporation
13  *
14  * This library is free software; you can redistribute it and/or
15  * modify it under the terms of the GNU Library General Public
16  * License as published by the Free Software Foundation; either
17  * version 2 of the License, or (at your option) any later version.
18  *
19  * This library is distributed in the hope that it will be useful,
20  * but WITHOUT ANY WARRANTY; without even the implied warranty of
21  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
22  * Library General Public License for more details.
23  *
24  * You should have received a copy of the GNU Library General Public
25  * License along with this library; if not, write to the
26  * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
27  * Boston, MA 02110-1301, USA.
28  */
29
30 /**
31  * SECTION:element-qtdemux
32  *
33  * Demuxes a .mov file into raw or compressed audio and/or video streams.
34  *
35  * This element supports both push and pull-based scheduling, depending on the
36  * capabilities of the upstream elements.
37  *
38  * <refsect2>
39  * <title>Example launch line</title>
40  * |[
41  * gst-launch-1.0 filesrc location=test.mov ! qtdemux name=demux  demux.audio_0 ! queue ! decodebin ! audioconvert ! audioresample ! autoaudiosink   demux.video_0 ! queue ! decodebin ! videoconvert ! videoscale ! autovideosink
42  * ]| Play (parse and decode) a .mov file and try to output it to
43  * an automatically detected soundcard and videosink. If the MOV file contains
44  * compressed audio or video data, this will only work if you have the
45  * right decoder elements/plugins installed.
46  * </refsect2>
47  */
48
49 #ifdef HAVE_CONFIG_H
50 #include "config.h"
51 #endif
52
53 #include "gst/gst-i18n-plugin.h"
54
55 #include <glib/gprintf.h>
56 #include <gst/tag/tag.h>
57 #include <gst/audio/audio.h>
58 #include <gst/video/video.h>
59 #include <gst/riff/riff.h>
60 #include <gst/pbutils/pbutils.h>
61
62 #include "qtatomparser.h"
63 #include "qtdemux_types.h"
64 #include "qtdemux_dump.h"
65 #include "fourcc.h"
66 #include "descriptors.h"
67 #include "qtdemux_lang.h"
68 #include "qtdemux.h"
69 #include "qtpalette.h"
70
71 #include <stdio.h>
72 #include <stdlib.h>
73 #include <string.h>
74
75 #include <math.h>
76 #include <gst/math-compat.h>
77
78 #ifdef HAVE_ZLIB
79 # include <zlib.h>
80 #endif
81
82 /* max. size considered 'sane' for non-mdat atoms */
83 #define QTDEMUX_MAX_ATOM_SIZE (25*1024*1024)
84
85 /* if the sample index is larger than this, something is likely wrong */
86 #define QTDEMUX_MAX_SAMPLE_INDEX_SIZE (200*1024*1024)
87
88 /* For converting qt creation times to unix epoch times */
89 #define QTDEMUX_SECONDS_PER_DAY (60 * 60 * 24)
90 #define QTDEMUX_LEAP_YEARS_FROM_1904_TO_1970 17
91 #define QTDEMUX_SECONDS_FROM_1904_TO_1970 (((1970 - 1904) * (guint64) 365 + \
92     QTDEMUX_LEAP_YEARS_FROM_1904_TO_1970) * QTDEMUX_SECONDS_PER_DAY)
93
94 #define QTDEMUX_TREE_NODE_FOURCC(n) (QT_FOURCC(((guint8 *) (n)->data) + 4))
95
96 #define STREAM_IS_EOS(s) ((s)->time_position == GST_CLOCK_TIME_NONE)
97
98 #define ABSDIFF(x, y) ( (x) > (y) ? ((x) - (y)) : ((y) - (x)) )
99
100 #define QTDEMUX_FIRST_STREAM(demux) ((QtDemuxStream *)(demux)->active_streams \
101   ? (QtDemuxStream *)(demux)->active_streams->data : NULL)
102 #define QTDEMUX_STREAM(s) ((QtDemuxStream *)(s))
103
104 GST_DEBUG_CATEGORY (qtdemux_debug);
105 #define GST_CAT_DEFAULT qtdemux_debug
106
107 typedef struct _QtDemuxSegment QtDemuxSegment;
108 typedef struct _QtDemuxSample QtDemuxSample;
109
110 typedef struct _QtDemuxCencSampleSetInfo QtDemuxCencSampleSetInfo;
111
112 struct _QtDemuxSample
113 {
114   guint32 size;
115   gint32 pts_offset;            /* Add this value to timestamp to get the pts */
116   guint64 offset;
117   guint64 timestamp;            /* DTS In mov time */
118   guint32 duration;             /* In mov time */
119   gboolean keyframe;            /* TRUE when this packet is a keyframe */
120 };
121
122 /* Macros for converting to/from timescale */
123 #define QTSTREAMTIME_TO_GSTTIME(stream, value) (gst_util_uint64_scale((value), GST_SECOND, (stream)->timescale))
124 #define GSTTIME_TO_QTSTREAMTIME(stream, value) (gst_util_uint64_scale((value), (stream)->timescale, GST_SECOND))
125
126 #define QTTIME_TO_GSTTIME(qtdemux, value) (gst_util_uint64_scale((value), GST_SECOND, (qtdemux)->timescale))
127 #define GSTTIME_TO_QTTIME(qtdemux, value) (gst_util_uint64_scale((value), (qtdemux)->timescale, GST_SECOND))
128
129 /* timestamp is the DTS */
130 #define QTSAMPLE_DTS(stream,sample) (QTSTREAMTIME_TO_GSTTIME((stream), (sample)->timestamp))
131 /* timestamp + offset + cslg_shift is the outgoing PTS */
132 #define QTSAMPLE_PTS(stream,sample) (QTSTREAMTIME_TO_GSTTIME((stream), (sample)->timestamp + (stream)->cslg_shift + (sample)->pts_offset))
133 /* timestamp + offset is the PTS used for internal seek calcuations */
134 #define QTSAMPLE_PTS_NO_CSLG(stream,sample) (QTSTREAMTIME_TO_GSTTIME((stream), (sample)->timestamp + (sample)->pts_offset))
135 /* timestamp + duration - dts is the duration */
136 #define QTSAMPLE_DUR_DTS(stream, sample, dts) (QTSTREAMTIME_TO_GSTTIME ((stream), (sample)->timestamp + (sample)->duration) - (dts))
137
138 #define QTSAMPLE_KEYFRAME(stream,sample) ((stream)->all_keyframe || (sample)->keyframe)
139
140 #define QTDEMUX_EXPOSE_GET_LOCK(demux) (&((demux)->expose_lock))
141 #define QTDEMUX_EXPOSE_LOCK(demux) G_STMT_START { \
142     GST_TRACE("Locking from thread %p", g_thread_self()); \
143     g_mutex_lock (QTDEMUX_EXPOSE_GET_LOCK (demux)); \
144     GST_TRACE("Locked from thread %p", g_thread_self()); \
145  } G_STMT_END
146
147 #define QTDEMUX_EXPOSE_UNLOCK(demux) G_STMT_START { \
148     GST_TRACE("Unlocking from thread %p", g_thread_self()); \
149     g_mutex_unlock (QTDEMUX_EXPOSE_GET_LOCK (demux)); \
150  } G_STMT_END
151
152 /*
153  * Quicktime has tracks and segments. A track is a continuous piece of
154  * multimedia content. The track is not always played from start to finish but
155  * instead, pieces of the track are 'cut out' and played in sequence. This is
156  * what the segments do.
157  *
158  * Inside the track we have keyframes (K) and delta frames. The track has its
159  * own timing, which starts from 0 and extends to end. The position in the track
160  * is called the media_time.
161  *
162  * The segments now describe the pieces that should be played from this track
163  * and are basically tuples of media_time/duration/rate entries. We can have
164  * multiple segments and they are all played after one another. An example:
165  *
166  * segment 1: media_time: 1 second, duration: 1 second, rate 1
167  * segment 2: media_time: 3 second, duration: 2 second, rate 2
168  *
169  * To correctly play back this track, one must play: 1 second of media starting
170  * from media_time 1 followed by 2 seconds of media starting from media_time 3
171  * at a rate of 2.
172  *
173  * Each of the segments will be played at a specific time, the first segment at
174  * time 0, the second one after the duration of the first one, etc.. Note that
175  * the time in resulting playback is not identical to the media_time of the
176  * track anymore.
177  *
178  * Visually, assuming the track has 4 second of media_time:
179  *
180  *                (a)                   (b)          (c)              (d)
181  *         .-----------------------------------------------------------.
182  * track:  | K.....K.........K........K.......K.......K...........K... |
183  *         '-----------------------------------------------------------'
184  *         0              1              2              3              4
185  *           .------------^              ^   .----------^              ^
186  *          /              .-------------'  /       .------------------'
187  *         /              /          .-----'       /
188  *         .--------------.         .--------------.
189  *         | segment 1    |         | segment 2    |
190  *         '--------------'         '--------------'
191  *
192  * The challenge here is to cut out the right pieces of the track for each of
193  * the playback segments. This fortunately can easily be done with the SEGMENT
194  * events of GStreamer.
195  *
196  * For playback of segment 1, we need to provide the decoder with the keyframe
197  * (a), in the above figure, but we must instruct it only to output the decoded
198  * data between second 1 and 2. We do this with a SEGMENT event for 1 to 2, time
199  * position set to the time of the segment: 0.
200  *
201  * We then proceed to push data from keyframe (a) to frame (b). The decoder
202  * decodes but clips all before media_time 1.
203  *
204  * After finishing a segment, we push out a new SEGMENT event with the clipping
205  * boundaries of the new data.
206  *
207  * This is a good usecase for the GStreamer accumulated SEGMENT events.
208  */
209
210 struct _QtDemuxSegment
211 {
212   /* global time and duration, all gst time */
213   GstClockTime time;
214   GstClockTime stop_time;
215   GstClockTime duration;
216   /* media time of trak, all gst time */
217   GstClockTime media_start;
218   GstClockTime media_stop;
219   gdouble rate;
220   /* Media start time in trak timescale units */
221   guint32 trak_media_start;
222 };
223
224 #define QTSEGMENT_IS_EMPTY(s) ((s)->media_start == GST_CLOCK_TIME_NONE)
225
226 /* Used with fragmented MP4 files (mfra atom) */
227 typedef struct
228 {
229   GstClockTime ts;
230   guint64 moof_offset;
231 } QtDemuxRandomAccessEntry;
232
233 typedef struct _QtDemuxStreamStsdEntry
234 {
235   GstCaps *caps;
236   guint32 fourcc;
237   gboolean sparse;
238
239   /* video info */
240   gint width;
241   gint height;
242   gint par_w;
243   gint par_h;
244   /* Numerator/denominator framerate */
245   gint fps_n;
246   gint fps_d;
247   GstVideoColorimetry colorimetry;
248   guint16 bits_per_sample;
249   guint16 color_table_id;
250   GstMemory *rgb8_palette;
251   guint interlace_mode;
252   guint field_order;
253
254   /* audio info */
255   gdouble rate;
256   gint n_channels;
257   guint samples_per_packet;
258   guint samples_per_frame;
259   guint bytes_per_packet;
260   guint bytes_per_sample;
261   guint bytes_per_frame;
262   guint compression;
263
264   /* if we use chunks or samples */
265   gboolean sampled;
266   guint padding;
267
268 } QtDemuxStreamStsdEntry;
269
270 #define CUR_STREAM(s) (&((s)->stsd_entries[(s)->cur_stsd_entry_index]))
271
272 struct _QtDemuxStream
273 {
274   GstPad *pad;
275
276   GstQTDemux *demux;
277   gchar *stream_id;
278
279   QtDemuxStreamStsdEntry *stsd_entries;
280   guint stsd_entries_length;
281   guint cur_stsd_entry_index;
282
283   /* stream type */
284   guint32 subtype;
285
286   gboolean new_caps;            /* If TRUE, caps need to be generated (by
287                                  * calling _configure_stream()) This happens
288                                  * for MSS and fragmented streams */
289
290   gboolean new_stream;          /* signals that a stream_start is required */
291   gboolean on_keyframe;         /* if this stream last pushed buffer was a
292                                  * keyframe. This is important to identify
293                                  * where to stop pushing buffers after a
294                                  * segment stop time */
295
296   /* if the stream has a redirect URI in its headers, we store it here */
297   gchar *redirect_uri;
298
299   /* track id */
300   guint track_id;
301
302   /* duration/scale */
303   guint64 duration;             /* in timescale units */
304   guint32 timescale;
305
306   /* language */
307   gchar lang_id[4];             /* ISO 639-2T language code */
308
309   /* our samples */
310   guint32 n_samples;
311   QtDemuxSample *samples;
312   gboolean all_keyframe;        /* TRUE when all samples are keyframes (no stss) */
313   guint32 n_samples_moof;       /* sample count in a moof */
314   guint64 duration_moof;        /* duration in timescale of a moof, used for figure out
315                                  * the framerate of fragmented format stream */
316   guint64 duration_last_moof;
317
318   guint32 offset_in_sample;     /* Offset in the current sample, used for
319                                  * streams which have got exceedingly big
320                                  * sample size (such as 24s of raw audio).
321                                  * Only used when max_buffer_size is non-NULL */
322   guint32 max_buffer_size;      /* Maximum allowed size for output buffers.
323                                  * Currently only set for raw audio streams*/
324
325   /* video info */
326   /* aspect ratio */
327   gint display_width;
328   gint display_height;
329
330   /* allocation */
331   gboolean use_allocator;
332   GstAllocator *allocator;
333   GstAllocationParams params;
334
335   gsize alignment;
336
337   /* when a discontinuity is pending */
338   gboolean discont;
339
340   /* list of buffers to push first */
341   GSList *buffers;
342
343   /* if we need to clip this buffer. This is only needed for uncompressed
344    * data */
345   gboolean need_clip;
346
347   /* buffer needs some custom processing, e.g. subtitles */
348   gboolean need_process;
349
350   /* current position */
351   guint32 segment_index;
352   guint32 sample_index;
353   GstClockTime time_position;   /* in gst time */
354   guint64 accumulated_base;
355
356   /* the Gst segment we are processing out, used for clipping */
357   GstSegment segment;
358
359   /* quicktime segments */
360   guint32 n_segments;
361   QtDemuxSegment *segments;
362   gboolean dummy_segment;
363   guint32 from_sample;
364   guint32 to_sample;
365
366   gboolean sent_eos;
367   GstTagList *stream_tags;
368   gboolean send_global_tags;
369
370   GstEvent *pending_event;
371
372   GstByteReader stco;
373   GstByteReader stsz;
374   GstByteReader stsc;
375   GstByteReader stts;
376   GstByteReader stss;
377   GstByteReader stps;
378   GstByteReader ctts;
379
380   gboolean chunks_are_samples;  /* TRUE means treat chunks as samples */
381   gint64 stbl_index;
382   /* stco */
383   guint co_size;
384   GstByteReader co_chunk;
385   guint32 first_chunk;
386   guint32 current_chunk;
387   guint32 last_chunk;
388   guint32 samples_per_chunk;
389   guint32 stsd_sample_description_id;
390   guint32 stco_sample_index;
391   /* stsz */
392   guint32 sample_size;          /* 0 means variable sizes are stored in stsz */
393   /* stsc */
394   guint32 stsc_index;
395   guint32 n_samples_per_chunk;
396   guint32 stsc_chunk_index;
397   guint32 stsc_sample_index;
398   guint64 chunk_offset;
399   /* stts */
400   guint32 stts_index;
401   guint32 stts_samples;
402   guint32 n_sample_times;
403   guint32 stts_sample_index;
404   guint64 stts_time;
405   guint32 stts_duration;
406   /* stss */
407   gboolean stss_present;
408   guint32 n_sample_syncs;
409   guint32 stss_index;
410   /* stps */
411   gboolean stps_present;
412   guint32 n_sample_partial_syncs;
413   guint32 stps_index;
414   QtDemuxRandomAccessEntry *ra_entries;
415   guint n_ra_entries;
416
417   const QtDemuxRandomAccessEntry *pending_seek;
418
419   /* ctts */
420   gboolean ctts_present;
421   guint32 n_composition_times;
422   guint32 ctts_index;
423   guint32 ctts_sample_index;
424   guint32 ctts_count;
425   gint32 ctts_soffset;
426
427   /* cslg */
428   guint32 cslg_shift;
429
430   /* fragmented */
431   gboolean parsed_trex;
432   guint32 def_sample_description_index; /* index is 1-based */
433   guint32 def_sample_duration;
434   guint32 def_sample_size;
435   guint32 def_sample_flags;
436
437   gboolean disabled;
438
439   /* stereoscopic video streams */
440   GstVideoMultiviewMode multiview_mode;
441   GstVideoMultiviewFlags multiview_flags;
442
443   /* protected streams */
444   gboolean protected;
445   guint32 protection_scheme_type;
446   guint32 protection_scheme_version;
447   gpointer protection_scheme_info;      /* specific to the protection scheme */
448   GQueue protection_scheme_event_queue;
449 };
450
451 /* Contains properties and cryptographic info for a set of samples from a
452  * track protected using Common Encryption (cenc) */
453 struct _QtDemuxCencSampleSetInfo
454 {
455   GstStructure *default_properties;
456
457   /* @crypto_info holds one GstStructure per sample */
458   GPtrArray *crypto_info;
459 };
460
461 static const gchar *
462 qt_demux_state_string (enum QtDemuxState state)
463 {
464   switch (state) {
465     case QTDEMUX_STATE_INITIAL:
466       return "<INITIAL>";
467     case QTDEMUX_STATE_HEADER:
468       return "<HEADER>";
469     case QTDEMUX_STATE_MOVIE:
470       return "<MOVIE>";
471     case QTDEMUX_STATE_BUFFER_MDAT:
472       return "<BUFFER_MDAT>";
473     default:
474       return "<UNKNOWN>";
475   }
476 }
477
478 static GNode *qtdemux_tree_get_child_by_type (GNode * node, guint32 fourcc);
479 static GNode *qtdemux_tree_get_child_by_type_full (GNode * node,
480     guint32 fourcc, GstByteReader * parser);
481 static GNode *qtdemux_tree_get_sibling_by_type (GNode * node, guint32 fourcc);
482 static GNode *qtdemux_tree_get_sibling_by_type_full (GNode * node,
483     guint32 fourcc, GstByteReader * parser);
484
485 static GstFlowReturn qtdemux_add_fragmented_samples (GstQTDemux * qtdemux);
486
487 static void gst_qtdemux_check_send_pending_segment (GstQTDemux * demux);
488
489 static GstStaticPadTemplate gst_qtdemux_sink_template =
490     GST_STATIC_PAD_TEMPLATE ("sink",
491     GST_PAD_SINK,
492     GST_PAD_ALWAYS,
493     GST_STATIC_CAPS ("video/quicktime; video/mj2; audio/x-m4a; "
494         "application/x-3gp")
495     );
496
497 static GstStaticPadTemplate gst_qtdemux_videosrc_template =
498 GST_STATIC_PAD_TEMPLATE ("video_%u",
499     GST_PAD_SRC,
500     GST_PAD_SOMETIMES,
501     GST_STATIC_CAPS_ANY);
502
503 static GstStaticPadTemplate gst_qtdemux_audiosrc_template =
504 GST_STATIC_PAD_TEMPLATE ("audio_%u",
505     GST_PAD_SRC,
506     GST_PAD_SOMETIMES,
507     GST_STATIC_CAPS_ANY);
508
509 static GstStaticPadTemplate gst_qtdemux_subsrc_template =
510 GST_STATIC_PAD_TEMPLATE ("subtitle_%u",
511     GST_PAD_SRC,
512     GST_PAD_SOMETIMES,
513     GST_STATIC_CAPS_ANY);
514
515 #define gst_qtdemux_parent_class parent_class
516 G_DEFINE_TYPE (GstQTDemux, gst_qtdemux, GST_TYPE_ELEMENT);
517
518 static void gst_qtdemux_dispose (GObject * object);
519
520 static guint32
521 gst_qtdemux_find_index_linear (GstQTDemux * qtdemux, QtDemuxStream * str,
522     GstClockTime media_time);
523 static guint32
524 gst_qtdemux_find_index_for_given_media_offset_linear (GstQTDemux * qtdemux,
525     QtDemuxStream * str, gint64 media_offset);
526
527 #if 0
528 static void gst_qtdemux_set_index (GstElement * element, GstIndex * index);
529 static GstIndex *gst_qtdemux_get_index (GstElement * element);
530 #endif
531 static GstStateChangeReturn gst_qtdemux_change_state (GstElement * element,
532     GstStateChange transition);
533 static void gst_qtdemux_set_context (GstElement * element,
534     GstContext * context);
535 static gboolean qtdemux_sink_activate (GstPad * sinkpad, GstObject * parent);
536 static gboolean qtdemux_sink_activate_mode (GstPad * sinkpad,
537     GstObject * parent, GstPadMode mode, gboolean active);
538
539 static void gst_qtdemux_loop (GstPad * pad);
540 static GstFlowReturn gst_qtdemux_chain (GstPad * sinkpad, GstObject * parent,
541     GstBuffer * inbuf);
542 static gboolean gst_qtdemux_handle_sink_event (GstPad * pad, GstObject * parent,
543     GstEvent * event);
544 static gboolean gst_qtdemux_setcaps (GstQTDemux * qtdemux, GstCaps * caps);
545 static gboolean gst_qtdemux_configure_stream (GstQTDemux * qtdemux,
546     QtDemuxStream * stream);
547 static void gst_qtdemux_stream_check_and_change_stsd_index (GstQTDemux * demux,
548     QtDemuxStream * stream);
549 static GstFlowReturn gst_qtdemux_process_adapter (GstQTDemux * demux,
550     gboolean force);
551
552 static gboolean qtdemux_parse_moov (GstQTDemux * qtdemux,
553     const guint8 * buffer, guint length);
554 static gboolean qtdemux_parse_node (GstQTDemux * qtdemux, GNode * node,
555     const guint8 * buffer, guint length);
556 static gboolean qtdemux_parse_tree (GstQTDemux * qtdemux);
557 static void qtdemux_parse_udta (GstQTDemux * qtdemux, GstTagList * taglist,
558     GNode * udta);
559
560 static void gst_qtdemux_handle_esds (GstQTDemux * qtdemux,
561     QtDemuxStream * stream, QtDemuxStreamStsdEntry * entry, GNode * esds,
562     GstTagList * list);
563 static GstCaps *qtdemux_video_caps (GstQTDemux * qtdemux,
564     QtDemuxStream * stream, QtDemuxStreamStsdEntry * entry, guint32 fourcc,
565     const guint8 * stsd_entry_data, gchar ** codec_name);
566 static GstCaps *qtdemux_audio_caps (GstQTDemux * qtdemux,
567     QtDemuxStream * stream, QtDemuxStreamStsdEntry * entry, guint32 fourcc,
568     const guint8 * data, int len, gchar ** codec_name);
569 static GstCaps *qtdemux_sub_caps (GstQTDemux * qtdemux, QtDemuxStream * stream,
570     QtDemuxStreamStsdEntry * entry, guint32 fourcc, const guint8 * data,
571     gchar ** codec_name);
572 static GstCaps *qtdemux_generic_caps (GstQTDemux * qtdemux,
573     QtDemuxStream * stream, QtDemuxStreamStsdEntry * entry, guint32 fourcc,
574     const guint8 * stsd_entry_data, gchar ** codec_name);
575
576 static gboolean qtdemux_parse_samples (GstQTDemux * qtdemux,
577     QtDemuxStream * stream, guint32 n);
578 static GstFlowReturn qtdemux_expose_streams (GstQTDemux * qtdemux);
579 static void gst_qtdemux_stream_free (QtDemuxStream * stream);
580 static void gst_qtdemux_stream_clear (QtDemuxStream * stream);
581 static void gst_qtdemux_remove_stream (GstQTDemux * qtdemux,
582     QtDemuxStream * stream);
583 static GstFlowReturn qtdemux_prepare_streams (GstQTDemux * qtdemux);
584 static void qtdemux_do_allocation (GstQTDemux * qtdemux,
585     QtDemuxStream * stream);
586 static gboolean gst_qtdemux_activate_segment (GstQTDemux * qtdemux,
587     QtDemuxStream * stream, guint32 seg_idx, GstClockTime offset);
588 static gboolean gst_qtdemux_stream_update_segment (GstQTDemux * qtdemux,
589     QtDemuxStream * stream, gint seg_idx, GstClockTime offset,
590     GstClockTime * _start, GstClockTime * _stop);
591 static void gst_qtdemux_send_gap_for_segment (GstQTDemux * demux,
592     QtDemuxStream * stream, gint segment_index, GstClockTime pos);
593
594 static gboolean qtdemux_pull_mfro_mfra (GstQTDemux * qtdemux);
595 static void check_update_duration (GstQTDemux * qtdemux, GstClockTime duration);
596
597 static gchar *qtdemux_uuid_bytes_to_string (gconstpointer uuid_bytes);
598
599 static GstStructure *qtdemux_get_cenc_sample_properties (GstQTDemux * qtdemux,
600     QtDemuxStream * stream, guint sample_index);
601 static void gst_qtdemux_append_protection_system_id (GstQTDemux * qtdemux,
602     const gchar * id);
603 static void qtdemux_gst_structure_free (GstStructure * gststructure);
604 static void gst_qtdemux_reset (GstQTDemux * qtdemux, gboolean hard);
605
606 static void
607 gst_qtdemux_class_init (GstQTDemuxClass * klass)
608 {
609   GObjectClass *gobject_class;
610   GstElementClass *gstelement_class;
611
612   gobject_class = (GObjectClass *) klass;
613   gstelement_class = (GstElementClass *) klass;
614
615   parent_class = g_type_class_peek_parent (klass);
616
617   gobject_class->dispose = gst_qtdemux_dispose;
618
619   gstelement_class->change_state = GST_DEBUG_FUNCPTR (gst_qtdemux_change_state);
620 #if 0
621   gstelement_class->set_index = GST_DEBUG_FUNCPTR (gst_qtdemux_set_index);
622   gstelement_class->get_index = GST_DEBUG_FUNCPTR (gst_qtdemux_get_index);
623 #endif
624   gstelement_class->set_context = GST_DEBUG_FUNCPTR (gst_qtdemux_set_context);
625
626   gst_tag_register_musicbrainz_tags ();
627
628   gst_element_class_add_static_pad_template (gstelement_class,
629       &gst_qtdemux_sink_template);
630   gst_element_class_add_static_pad_template (gstelement_class,
631       &gst_qtdemux_videosrc_template);
632   gst_element_class_add_static_pad_template (gstelement_class,
633       &gst_qtdemux_audiosrc_template);
634   gst_element_class_add_static_pad_template (gstelement_class,
635       &gst_qtdemux_subsrc_template);
636   gst_element_class_set_static_metadata (gstelement_class, "QuickTime demuxer",
637       "Codec/Demuxer",
638       "Demultiplex a QuickTime file into audio and video streams",
639       "David Schleef <ds@schleef.org>, Wim Taymans <wim@fluendo.com>");
640
641   GST_DEBUG_CATEGORY_INIT (qtdemux_debug, "qtdemux", 0, "qtdemux plugin");
642   gst_riff_init ();
643 }
644
645 static void
646 gst_qtdemux_init (GstQTDemux * qtdemux)
647 {
648   qtdemux->sinkpad =
649       gst_pad_new_from_static_template (&gst_qtdemux_sink_template, "sink");
650   gst_pad_set_activate_function (qtdemux->sinkpad, qtdemux_sink_activate);
651   gst_pad_set_activatemode_function (qtdemux->sinkpad,
652       qtdemux_sink_activate_mode);
653   gst_pad_set_chain_function (qtdemux->sinkpad, gst_qtdemux_chain);
654   gst_pad_set_event_function (qtdemux->sinkpad, gst_qtdemux_handle_sink_event);
655   gst_element_add_pad (GST_ELEMENT_CAST (qtdemux), qtdemux->sinkpad);
656
657   qtdemux->adapter = gst_adapter_new ();
658   g_queue_init (&qtdemux->protection_event_queue);
659   qtdemux->flowcombiner = gst_flow_combiner_new ();
660   g_mutex_init (&qtdemux->expose_lock);
661
662   GST_OBJECT_FLAG_SET (qtdemux, GST_ELEMENT_FLAG_INDEXABLE);
663
664   gst_qtdemux_reset (qtdemux, TRUE);
665 }
666
667 static void
668 gst_qtdemux_dispose (GObject * object)
669 {
670   GstQTDemux *qtdemux = GST_QTDEMUX (object);
671
672   if (qtdemux->adapter) {
673     g_object_unref (G_OBJECT (qtdemux->adapter));
674     qtdemux->adapter = NULL;
675   }
676   gst_tag_list_unref (qtdemux->tag_list);
677   gst_flow_combiner_free (qtdemux->flowcombiner);
678   g_queue_foreach (&qtdemux->protection_event_queue, (GFunc) gst_event_unref,
679       NULL);
680   g_queue_clear (&qtdemux->protection_event_queue);
681
682   g_free (qtdemux->cenc_aux_info_sizes);
683   qtdemux->cenc_aux_info_sizes = NULL;
684   g_mutex_clear (&qtdemux->expose_lock);
685
686   G_OBJECT_CLASS (parent_class)->dispose (object);
687 }
688
689 static void
690 gst_qtdemux_post_no_playable_stream_error (GstQTDemux * qtdemux)
691 {
692   if (qtdemux->posted_redirect) {
693     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
694         (_("This file contains no playable streams.")),
695         ("no known streams found, a redirect message has been posted"));
696   } else {
697     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
698         (_("This file contains no playable streams.")),
699         ("no known streams found"));
700   }
701 }
702
703 static GstBuffer *
704 _gst_buffer_new_wrapped (gpointer mem, gsize size, GFreeFunc free_func)
705 {
706   return gst_buffer_new_wrapped_full (free_func ? 0 : GST_MEMORY_FLAG_READONLY,
707       mem, size, 0, size, mem, free_func);
708 }
709
710 static GstFlowReturn
711 gst_qtdemux_pull_atom (GstQTDemux * qtdemux, guint64 offset, guint64 size,
712     GstBuffer ** buf)
713 {
714   GstFlowReturn flow;
715   GstMapInfo map;
716   gsize bsize;
717
718   if (G_UNLIKELY (size == 0)) {
719     GstFlowReturn ret;
720     GstBuffer *tmp = NULL;
721
722     ret = gst_qtdemux_pull_atom (qtdemux, offset, sizeof (guint32), &tmp);
723     if (ret != GST_FLOW_OK)
724       return ret;
725
726     gst_buffer_map (tmp, &map, GST_MAP_READ);
727     size = QT_UINT32 (map.data);
728     GST_DEBUG_OBJECT (qtdemux, "size 0x%08" G_GINT64_MODIFIER "x", size);
729
730     gst_buffer_unmap (tmp, &map);
731     gst_buffer_unref (tmp);
732   }
733
734   /* Sanity check: catch bogus sizes (fuzzed/broken files) */
735   if (G_UNLIKELY (size > QTDEMUX_MAX_ATOM_SIZE)) {
736     if (qtdemux->state != QTDEMUX_STATE_MOVIE && qtdemux->got_moov) {
737       /* we're pulling header but already got most interesting bits,
738        * so never mind the rest (e.g. tags) (that much) */
739       GST_WARNING_OBJECT (qtdemux, "atom has bogus size %" G_GUINT64_FORMAT,
740           size);
741       return GST_FLOW_EOS;
742     } else {
743       GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
744           (_("This file is invalid and cannot be played.")),
745           ("atom has bogus size %" G_GUINT64_FORMAT, size));
746       return GST_FLOW_ERROR;
747     }
748   }
749
750   flow = gst_pad_pull_range (qtdemux->sinkpad, offset, size, buf);
751
752   if (G_UNLIKELY (flow != GST_FLOW_OK))
753     return flow;
754
755   bsize = gst_buffer_get_size (*buf);
756   /* Catch short reads - we don't want any partial atoms */
757   if (G_UNLIKELY (bsize < size)) {
758     GST_WARNING_OBJECT (qtdemux,
759         "short read: %" G_GSIZE_FORMAT " < %" G_GUINT64_FORMAT, bsize, size);
760     gst_buffer_unref (*buf);
761     *buf = NULL;
762     return GST_FLOW_EOS;
763   }
764
765   return flow;
766 }
767
768 #if 1
769 static gboolean
770 gst_qtdemux_src_convert (GstQTDemux * qtdemux, GstPad * pad,
771     GstFormat src_format, gint64 src_value, GstFormat dest_format,
772     gint64 * dest_value)
773 {
774   gboolean res = TRUE;
775   QtDemuxStream *stream = gst_pad_get_element_private (pad);
776   gint32 index;
777
778   if (stream->subtype != FOURCC_vide) {
779     res = FALSE;
780     goto done;
781   }
782
783   switch (src_format) {
784     case GST_FORMAT_TIME:
785       switch (dest_format) {
786         case GST_FORMAT_BYTES:{
787           index = gst_qtdemux_find_index_linear (qtdemux, stream, src_value);
788           if (-1 == index) {
789             res = FALSE;
790             goto done;
791           }
792
793           *dest_value = stream->samples[index].offset;
794
795           GST_DEBUG_OBJECT (qtdemux, "Format Conversion Time->Offset :%"
796               GST_TIME_FORMAT "->%" G_GUINT64_FORMAT,
797               GST_TIME_ARGS (src_value), *dest_value);
798           break;
799         }
800         default:
801           res = FALSE;
802           break;
803       }
804       break;
805     case GST_FORMAT_BYTES:
806       switch (dest_format) {
807         case GST_FORMAT_TIME:{
808           index =
809               gst_qtdemux_find_index_for_given_media_offset_linear (qtdemux,
810               stream, src_value);
811
812           if (-1 == index) {
813             res = FALSE;
814             goto done;
815           }
816
817           *dest_value =
818               QTSTREAMTIME_TO_GSTTIME (stream,
819               stream->samples[index].timestamp);
820           GST_DEBUG_OBJECT (qtdemux,
821               "Format Conversion Offset->Time :%" G_GUINT64_FORMAT "->%"
822               GST_TIME_FORMAT, src_value, GST_TIME_ARGS (*dest_value));
823           break;
824         }
825         default:
826           res = FALSE;
827           break;
828       }
829       break;
830     default:
831       res = FALSE;
832       break;
833   }
834
835 done:
836   return res;
837 }
838 #endif
839
840 static gboolean
841 gst_qtdemux_get_duration (GstQTDemux * qtdemux, GstClockTime * duration)
842 {
843   gboolean res = FALSE;
844
845   *duration = GST_CLOCK_TIME_NONE;
846
847   if (qtdemux->duration != 0 &&
848       qtdemux->duration != G_MAXINT64 && qtdemux->timescale != 0) {
849     *duration = QTTIME_TO_GSTTIME (qtdemux, qtdemux->duration);
850     res = TRUE;
851   } else {
852     *duration = GST_CLOCK_TIME_NONE;
853   }
854
855   return res;
856 }
857
858 static gboolean
859 gst_qtdemux_handle_src_query (GstPad * pad, GstObject * parent,
860     GstQuery * query)
861 {
862   gboolean res = FALSE;
863   GstQTDemux *qtdemux = GST_QTDEMUX (parent);
864
865   GST_LOG_OBJECT (pad, "%s query", GST_QUERY_TYPE_NAME (query));
866
867   switch (GST_QUERY_TYPE (query)) {
868     case GST_QUERY_POSITION:{
869       GstFormat fmt;
870
871       gst_query_parse_position (query, &fmt, NULL);
872       if (fmt == GST_FORMAT_TIME
873           && GST_CLOCK_TIME_IS_VALID (qtdemux->segment.position)) {
874         gst_query_set_position (query, GST_FORMAT_TIME,
875             qtdemux->segment.position);
876         res = TRUE;
877       }
878     }
879       break;
880     case GST_QUERY_DURATION:{
881       GstFormat fmt;
882
883       gst_query_parse_duration (query, &fmt, NULL);
884       if (fmt == GST_FORMAT_TIME) {
885         /* First try to query upstream */
886         res = gst_pad_query_default (pad, parent, query);
887         if (!res) {
888           GstClockTime duration;
889           if (gst_qtdemux_get_duration (qtdemux, &duration) && duration > 0) {
890             gst_query_set_duration (query, GST_FORMAT_TIME, duration);
891             res = TRUE;
892           }
893         }
894       }
895       break;
896     }
897     case GST_QUERY_CONVERT:{
898       GstFormat src_fmt, dest_fmt;
899       gint64 src_value, dest_value = 0;
900
901       gst_query_parse_convert (query, &src_fmt, &src_value, &dest_fmt, NULL);
902
903       res = gst_qtdemux_src_convert (qtdemux, pad,
904           src_fmt, src_value, dest_fmt, &dest_value);
905       if (res)
906         gst_query_set_convert (query, src_fmt, src_value, dest_fmt, dest_value);
907
908       break;
909     }
910     case GST_QUERY_FORMATS:
911       gst_query_set_formats (query, 2, GST_FORMAT_TIME, GST_FORMAT_BYTES);
912       res = TRUE;
913       break;
914     case GST_QUERY_SEEKING:{
915       GstFormat fmt;
916       gboolean seekable;
917
918       /* try upstream first */
919       res = gst_pad_query_default (pad, parent, query);
920
921       if (!res) {
922         gst_query_parse_seeking (query, &fmt, NULL, NULL, NULL);
923         if (fmt == GST_FORMAT_TIME) {
924           GstClockTime duration;
925
926           gst_qtdemux_get_duration (qtdemux, &duration);
927           seekable = TRUE;
928           if (!qtdemux->pullbased) {
929             GstQuery *q;
930
931             /* we might be able with help from upstream */
932             seekable = FALSE;
933             q = gst_query_new_seeking (GST_FORMAT_BYTES);
934             if (gst_pad_peer_query (qtdemux->sinkpad, q)) {
935               gst_query_parse_seeking (q, &fmt, &seekable, NULL, NULL);
936               GST_LOG_OBJECT (qtdemux, "upstream BYTE seekable %d", seekable);
937             }
938             gst_query_unref (q);
939           }
940           gst_query_set_seeking (query, GST_FORMAT_TIME, seekable, 0, duration);
941           res = TRUE;
942         }
943       }
944       break;
945     }
946     case GST_QUERY_SEGMENT:
947     {
948       GstFormat format;
949       gint64 start, stop;
950
951       format = qtdemux->segment.format;
952
953       start =
954           gst_segment_to_stream_time (&qtdemux->segment, format,
955           qtdemux->segment.start);
956       if ((stop = qtdemux->segment.stop) == -1)
957         stop = qtdemux->segment.duration;
958       else
959         stop = gst_segment_to_stream_time (&qtdemux->segment, format, stop);
960
961       gst_query_set_segment (query, qtdemux->segment.rate, format, start, stop);
962       res = TRUE;
963       break;
964     }
965     default:
966       res = gst_pad_query_default (pad, parent, query);
967       break;
968   }
969
970   return res;
971 }
972
973 static void
974 gst_qtdemux_push_tags (GstQTDemux * qtdemux, QtDemuxStream * stream)
975 {
976   if (G_LIKELY (stream->pad)) {
977     GST_DEBUG_OBJECT (qtdemux, "Checking pad %s:%s for tags",
978         GST_DEBUG_PAD_NAME (stream->pad));
979
980     if (!gst_tag_list_is_empty (stream->stream_tags)) {
981       GST_DEBUG_OBJECT (qtdemux, "Sending tags %" GST_PTR_FORMAT,
982           stream->stream_tags);
983       gst_pad_push_event (stream->pad,
984           gst_event_new_tag (gst_tag_list_ref (stream->stream_tags)));
985     }
986
987     if (G_UNLIKELY (stream->send_global_tags)) {
988       GST_DEBUG_OBJECT (qtdemux, "Sending global tags %" GST_PTR_FORMAT,
989           qtdemux->tag_list);
990       gst_pad_push_event (stream->pad,
991           gst_event_new_tag (gst_tag_list_ref (qtdemux->tag_list)));
992       stream->send_global_tags = FALSE;
993     }
994   }
995 }
996
997 /* push event on all source pads; takes ownership of the event */
998 static void
999 gst_qtdemux_push_event (GstQTDemux * qtdemux, GstEvent * event)
1000 {
1001   gboolean has_valid_stream = FALSE;
1002   GstEventType etype = GST_EVENT_TYPE (event);
1003   GList *iter;
1004
1005   GST_DEBUG_OBJECT (qtdemux, "pushing %s event on all source pads",
1006       GST_EVENT_TYPE_NAME (event));
1007
1008   for (iter = qtdemux->active_streams; iter; iter = g_list_next (iter)) {
1009     GstPad *pad;
1010     QtDemuxStream *stream = QTDEMUX_STREAM (iter->data);
1011     GST_DEBUG_OBJECT (qtdemux, "pushing on track-id %u", stream->track_id);
1012
1013     if ((pad = stream->pad)) {
1014       has_valid_stream = TRUE;
1015
1016       if (etype == GST_EVENT_EOS) {
1017         /* let's not send twice */
1018         if (stream->sent_eos)
1019           continue;
1020         stream->sent_eos = TRUE;
1021       }
1022
1023       gst_pad_push_event (pad, gst_event_ref (event));
1024     }
1025   }
1026
1027   gst_event_unref (event);
1028
1029   /* if it is EOS and there are no pads, post an error */
1030   if (!has_valid_stream && etype == GST_EVENT_EOS) {
1031     gst_qtdemux_post_no_playable_stream_error (qtdemux);
1032   }
1033 }
1034
1035 typedef struct
1036 {
1037   guint64 media_time;
1038 } FindData;
1039
1040 static gint
1041 find_func (QtDemuxSample * s1, gint64 * media_time, gpointer user_data)
1042 {
1043   if ((gint64) s1->timestamp > *media_time)
1044     return 1;
1045   if ((gint64) s1->timestamp == *media_time)
1046     return 0;
1047
1048   return -1;
1049 }
1050
1051 /* find the index of the sample that includes the data for @media_time using a
1052  * binary search.  Only to be called in optimized cases of linear search below.
1053  *
1054  * Returns the index of the sample with the corresponding *DTS*.
1055  */
1056 static guint32
1057 gst_qtdemux_find_index (GstQTDemux * qtdemux, QtDemuxStream * str,
1058     guint64 media_time)
1059 {
1060   QtDemuxSample *result;
1061   guint32 index;
1062
1063   /* convert media_time to mov format */
1064   media_time =
1065       gst_util_uint64_scale_ceil (media_time, str->timescale, GST_SECOND);
1066
1067   result = gst_util_array_binary_search (str->samples, str->stbl_index + 1,
1068       sizeof (QtDemuxSample), (GCompareDataFunc) find_func,
1069       GST_SEARCH_MODE_BEFORE, &media_time, NULL);
1070
1071   if (G_LIKELY (result))
1072     index = result - str->samples;
1073   else
1074     index = 0;
1075
1076   return index;
1077 }
1078
1079
1080
1081 /* find the index of the sample that includes the data for @media_offset using a
1082  * linear search
1083  *
1084  * Returns the index of the sample.
1085  */
1086 static guint32
1087 gst_qtdemux_find_index_for_given_media_offset_linear (GstQTDemux * qtdemux,
1088     QtDemuxStream * str, gint64 media_offset)
1089 {
1090   QtDemuxSample *result = str->samples;
1091   guint32 index = 0;
1092
1093   if (result == NULL || str->n_samples == 0)
1094     return -1;
1095
1096   if (media_offset == result->offset)
1097     return index;
1098
1099   result++;
1100   while (index < str->n_samples - 1) {
1101     if (!qtdemux_parse_samples (qtdemux, str, index + 1))
1102       goto parse_failed;
1103
1104     if (media_offset < result->offset)
1105       break;
1106
1107     index++;
1108     result++;
1109   }
1110   return index;
1111
1112   /* ERRORS */
1113 parse_failed:
1114   {
1115     GST_LOG_OBJECT (qtdemux, "Parsing of index %u failed!", index + 1);
1116     return -1;
1117   }
1118 }
1119
1120 /* find the index of the sample that includes the data for @media_time using a
1121  * linear search, and keeping in mind that not all samples may have been parsed
1122  * yet.  If possible, it will delegate to binary search.
1123  *
1124  * Returns the index of the sample.
1125  */
1126 static guint32
1127 gst_qtdemux_find_index_linear (GstQTDemux * qtdemux, QtDemuxStream * str,
1128     GstClockTime media_time)
1129 {
1130   guint32 index = 0;
1131   guint64 mov_time;
1132   QtDemuxSample *sample;
1133
1134   /* convert media_time to mov format */
1135   mov_time =
1136       gst_util_uint64_scale_ceil (media_time, str->timescale, GST_SECOND);
1137
1138   sample = str->samples;
1139   if (mov_time == sample->timestamp + sample->pts_offset)
1140     return index;
1141
1142   /* use faster search if requested time in already parsed range */
1143   sample = str->samples + str->stbl_index;
1144   if (str->stbl_index >= 0 && mov_time <= sample->timestamp) {
1145     index = gst_qtdemux_find_index (qtdemux, str, media_time);
1146     sample = str->samples + index;
1147   } else {
1148     while (index < str->n_samples - 1) {
1149       if (!qtdemux_parse_samples (qtdemux, str, index + 1))
1150         goto parse_failed;
1151
1152       sample = str->samples + index + 1;
1153       if (mov_time < sample->timestamp) {
1154         sample = str->samples + index;
1155         break;
1156       }
1157
1158       index++;
1159     }
1160   }
1161
1162   /* sample->timestamp is now <= media_time, need to find the corresponding
1163    * PTS now by looking backwards */
1164   while (index > 0 && sample->timestamp + sample->pts_offset > mov_time) {
1165     index--;
1166     sample = str->samples + index;
1167   }
1168
1169   return index;
1170
1171   /* ERRORS */
1172 parse_failed:
1173   {
1174     GST_LOG_OBJECT (qtdemux, "Parsing of index %u failed!", index + 1);
1175     return -1;
1176   }
1177 }
1178
1179 /* find the index of the keyframe needed to decode the sample at @index
1180  * of stream @str, or of a subsequent keyframe (depending on @next)
1181  *
1182  * Returns the index of the keyframe.
1183  */
1184 static guint32
1185 gst_qtdemux_find_keyframe (GstQTDemux * qtdemux, QtDemuxStream * str,
1186     guint32 index, gboolean next)
1187 {
1188   guint32 new_index = index;
1189
1190   if (index >= str->n_samples) {
1191     new_index = str->n_samples;
1192     goto beach;
1193   }
1194
1195   /* all keyframes, return index */
1196   if (str->all_keyframe) {
1197     new_index = index;
1198     goto beach;
1199   }
1200
1201   /* else search until we have a keyframe */
1202   while (new_index < str->n_samples) {
1203     if (next && !qtdemux_parse_samples (qtdemux, str, new_index))
1204       goto parse_failed;
1205
1206     if (str->samples[new_index].keyframe)
1207       break;
1208
1209     if (new_index == 0)
1210       break;
1211
1212     if (next)
1213       new_index++;
1214     else
1215       new_index--;
1216   }
1217
1218   if (new_index == str->n_samples) {
1219     GST_DEBUG_OBJECT (qtdemux, "no next keyframe");
1220     new_index = -1;
1221   }
1222
1223 beach:
1224   GST_DEBUG_OBJECT (qtdemux, "searching for keyframe index %s index %u "
1225       "gave %u", next ? "after" : "before", index, new_index);
1226
1227   return new_index;
1228
1229   /* ERRORS */
1230 parse_failed:
1231   {
1232     GST_LOG_OBJECT (qtdemux, "Parsing of index %u failed!", new_index);
1233     return -1;
1234   }
1235 }
1236
1237 /* find the segment for @time_position for @stream
1238  *
1239  * Returns the index of the segment containing @time_position.
1240  * Returns the last segment and sets the @eos variable to TRUE
1241  * if the time is beyond the end. @eos may be NULL
1242  */
1243 static guint32
1244 gst_qtdemux_find_segment (GstQTDemux * qtdemux, QtDemuxStream * stream,
1245     GstClockTime time_position)
1246 {
1247   gint i;
1248   guint32 seg_idx;
1249
1250   GST_LOG_OBJECT (stream->pad, "finding segment for %" GST_TIME_FORMAT,
1251       GST_TIME_ARGS (time_position));
1252
1253   seg_idx = -1;
1254   for (i = 0; i < stream->n_segments; i++) {
1255     QtDemuxSegment *segment = &stream->segments[i];
1256
1257     GST_LOG_OBJECT (stream->pad,
1258         "looking at segment %" GST_TIME_FORMAT "-%" GST_TIME_FORMAT,
1259         GST_TIME_ARGS (segment->time), GST_TIME_ARGS (segment->stop_time));
1260
1261     /* For the last segment we include stop_time in the last segment */
1262     if (i < stream->n_segments - 1) {
1263       if (segment->time <= time_position && time_position < segment->stop_time) {
1264         GST_LOG_OBJECT (stream->pad, "segment %d matches", i);
1265         seg_idx = i;
1266         break;
1267       }
1268     } else {
1269       /* Last segment always matches */
1270       seg_idx = i;
1271       break;
1272     }
1273   }
1274   return seg_idx;
1275 }
1276
1277 /* move the stream @str to the sample position @index.
1278  *
1279  * Updates @str->sample_index and marks discontinuity if needed.
1280  */
1281 static void
1282 gst_qtdemux_move_stream (GstQTDemux * qtdemux, QtDemuxStream * str,
1283     guint32 index)
1284 {
1285   /* no change needed */
1286   if (index == str->sample_index)
1287     return;
1288
1289   GST_DEBUG_OBJECT (qtdemux, "moving to sample %u of %u", index,
1290       str->n_samples);
1291
1292   /* position changed, we have a discont */
1293   str->sample_index = index;
1294   str->offset_in_sample = 0;
1295   /* Each time we move in the stream we store the position where we are
1296    * starting from */
1297   str->from_sample = index;
1298   str->discont = TRUE;
1299 }
1300
1301 static void
1302 gst_qtdemux_adjust_seek (GstQTDemux * qtdemux, gint64 desired_time,
1303     gboolean use_sparse, gboolean next, gint64 * key_time, gint64 * key_offset)
1304 {
1305   guint64 min_offset;
1306   gint64 min_byte_offset = -1;
1307   GList *iter;
1308
1309   min_offset = desired_time;
1310
1311   /* for each stream, find the index of the sample in the segment
1312    * and move back to the previous keyframe. */
1313   for (iter = qtdemux->active_streams; iter; iter = g_list_next (iter)) {
1314     QtDemuxStream *str;
1315     guint32 index, kindex;
1316     guint32 seg_idx;
1317     GstClockTime media_start;
1318     GstClockTime media_time;
1319     GstClockTime seg_time;
1320     QtDemuxSegment *seg;
1321     gboolean empty_segment = FALSE;
1322
1323     str = QTDEMUX_STREAM (iter->data);
1324
1325     if (CUR_STREAM (str)->sparse && !use_sparse)
1326       continue;
1327
1328     seg_idx = gst_qtdemux_find_segment (qtdemux, str, desired_time);
1329     GST_DEBUG_OBJECT (qtdemux, "align segment %d", seg_idx);
1330
1331     /* get segment and time in the segment */
1332     seg = &str->segments[seg_idx];
1333     seg_time = (desired_time - seg->time) * seg->rate;
1334
1335     while (QTSEGMENT_IS_EMPTY (seg)) {
1336       seg_time = 0;
1337       empty_segment = TRUE;
1338       GST_DEBUG_OBJECT (str->pad, "Segment %d is empty, moving to next one",
1339           seg_idx);
1340       seg_idx++;
1341       if (seg_idx == str->n_segments)
1342         break;
1343       seg = &str->segments[seg_idx];
1344     }
1345
1346     if (seg_idx == str->n_segments) {
1347       /* FIXME track shouldn't have the last segment as empty, but if it
1348        * happens we better handle it */
1349       continue;
1350     }
1351
1352     /* get the media time in the segment */
1353     media_start = seg->media_start + seg_time;
1354
1355     /* get the index of the sample with media time */
1356     index = gst_qtdemux_find_index_linear (qtdemux, str, media_start);
1357     GST_DEBUG_OBJECT (qtdemux, "sample for %" GST_TIME_FORMAT " at %u"
1358         " at offset %" G_GUINT64_FORMAT " (empty segment: %d)",
1359         GST_TIME_ARGS (media_start), index, str->samples[index].offset,
1360         empty_segment);
1361
1362     /* shift to next frame if we are looking for next keyframe */
1363     if (next && QTSAMPLE_PTS_NO_CSLG (str, &str->samples[index]) < media_start
1364         && index < str->stbl_index)
1365       index++;
1366
1367     if (!empty_segment) {
1368       /* find previous keyframe */
1369       kindex = gst_qtdemux_find_keyframe (qtdemux, str, index, next);
1370
1371       /* we will settle for one before if none found after */
1372       if (next && kindex == -1)
1373         kindex = gst_qtdemux_find_keyframe (qtdemux, str, index, FALSE);
1374
1375       /* if the keyframe is at a different position, we need to update the
1376        * requested seek time */
1377       if (index != kindex) {
1378         index = kindex;
1379
1380         /* get timestamp of keyframe */
1381         media_time = QTSAMPLE_PTS_NO_CSLG (str, &str->samples[kindex]);
1382         GST_DEBUG_OBJECT (qtdemux,
1383             "keyframe at %u with time %" GST_TIME_FORMAT " at offset %"
1384             G_GUINT64_FORMAT, kindex, GST_TIME_ARGS (media_time),
1385             str->samples[kindex].offset);
1386
1387         /* keyframes in the segment get a chance to change the
1388          * desired_offset. keyframes out of the segment are
1389          * ignored. */
1390         if (media_time >= seg->media_start) {
1391           GstClockTime seg_time;
1392
1393           /* this keyframe is inside the segment, convert back to
1394            * segment time */
1395           seg_time = (media_time - seg->media_start) + seg->time;
1396           if ((!next && (seg_time < min_offset)) ||
1397               (next && (seg_time > min_offset)))
1398             min_offset = seg_time;
1399         }
1400       }
1401     }
1402
1403     if (min_byte_offset < 0 || str->samples[index].offset < min_byte_offset)
1404       min_byte_offset = str->samples[index].offset;
1405   }
1406
1407   if (key_time)
1408     *key_time = min_offset;
1409   if (key_offset)
1410     *key_offset = min_byte_offset;
1411 }
1412
1413 static gboolean
1414 gst_qtdemux_convert_seek (GstPad * pad, GstFormat * format,
1415     GstSeekType cur_type, gint64 * cur, GstSeekType stop_type, gint64 * stop)
1416 {
1417   gboolean res;
1418
1419   g_return_val_if_fail (format != NULL, FALSE);
1420   g_return_val_if_fail (cur != NULL, FALSE);
1421   g_return_val_if_fail (stop != NULL, FALSE);
1422
1423   if (*format == GST_FORMAT_TIME)
1424     return TRUE;
1425
1426   res = TRUE;
1427   if (cur_type != GST_SEEK_TYPE_NONE)
1428     res = gst_pad_query_convert (pad, *format, *cur, GST_FORMAT_TIME, cur);
1429   if (res && stop_type != GST_SEEK_TYPE_NONE)
1430     res = gst_pad_query_convert (pad, *format, *stop, GST_FORMAT_TIME, stop);
1431
1432   if (res)
1433     *format = GST_FORMAT_TIME;
1434
1435   return res;
1436 }
1437
1438 /* perform seek in push based mode:
1439    find BYTE position to move to based on time and delegate to upstream
1440 */
1441 static gboolean
1442 gst_qtdemux_do_push_seek (GstQTDemux * qtdemux, GstPad * pad, GstEvent * event)
1443 {
1444   gdouble rate;
1445   GstFormat format;
1446   GstSeekFlags flags;
1447   GstSeekType cur_type, stop_type;
1448   gint64 cur, stop, key_cur;
1449   gboolean res;
1450   gint64 byte_cur;
1451   gint64 original_stop;
1452   guint32 seqnum;
1453
1454   GST_DEBUG_OBJECT (qtdemux, "doing push-based seek");
1455
1456   gst_event_parse_seek (event, &rate, &format, &flags,
1457       &cur_type, &cur, &stop_type, &stop);
1458   seqnum = gst_event_get_seqnum (event);
1459
1460   /* only forward streaming and seeking is possible */
1461   if (rate <= 0)
1462     goto unsupported_seek;
1463
1464   /* convert to TIME if needed and possible */
1465   if (!gst_qtdemux_convert_seek (pad, &format, cur_type, &cur,
1466           stop_type, &stop))
1467     goto no_format;
1468
1469   /* Upstream seek in bytes will have undefined stop, but qtdemux stores
1470    * the original stop position to use when upstream pushes the new segment
1471    * for this seek */
1472   original_stop = stop;
1473   stop = -1;
1474
1475   /* find reasonable corresponding BYTE position,
1476    * also try to mind about keyframes, since we can not go back a bit for them
1477    * later on */
1478   /* determining @next here based on SNAP_BEFORE/SNAP_AFTER should
1479    * mostly just work, but let's not yet boldly go there  ... */
1480   gst_qtdemux_adjust_seek (qtdemux, cur, FALSE, FALSE, &key_cur, &byte_cur);
1481
1482   if (byte_cur == -1)
1483     goto abort_seek;
1484
1485   GST_DEBUG_OBJECT (qtdemux, "Pushing BYTE seek rate %g, "
1486       "start %" G_GINT64_FORMAT ", stop %" G_GINT64_FORMAT, rate, byte_cur,
1487       stop);
1488
1489   GST_OBJECT_LOCK (qtdemux);
1490   qtdemux->seek_offset = byte_cur;
1491   if (!(flags & GST_SEEK_FLAG_KEY_UNIT)) {
1492     qtdemux->push_seek_start = cur;
1493   } else {
1494     qtdemux->push_seek_start = key_cur;
1495   }
1496
1497   if (stop_type == GST_SEEK_TYPE_NONE) {
1498     qtdemux->push_seek_stop = qtdemux->segment.stop;
1499   } else {
1500     qtdemux->push_seek_stop = original_stop;
1501   }
1502   GST_OBJECT_UNLOCK (qtdemux);
1503
1504   qtdemux->segment_seqnum = seqnum;
1505   /* BYTE seek event */
1506   event = gst_event_new_seek (rate, GST_FORMAT_BYTES, flags, cur_type, byte_cur,
1507       stop_type, stop);
1508   gst_event_set_seqnum (event, seqnum);
1509   res = gst_pad_push_event (qtdemux->sinkpad, event);
1510
1511   return res;
1512
1513   /* ERRORS */
1514 abort_seek:
1515   {
1516     GST_DEBUG_OBJECT (qtdemux, "could not determine byte position to seek to, "
1517         "seek aborted.");
1518     return FALSE;
1519   }
1520 unsupported_seek:
1521   {
1522     GST_DEBUG_OBJECT (qtdemux, "unsupported seek, seek aborted.");
1523     return FALSE;
1524   }
1525 no_format:
1526   {
1527     GST_DEBUG_OBJECT (qtdemux, "unsupported format given, seek aborted.");
1528     return FALSE;
1529   }
1530 }
1531
1532 /* perform the seek.
1533  *
1534  * We set all segment_indexes in the streams to unknown and
1535  * adjust the time_position to the desired position. this is enough
1536  * to trigger a segment switch in the streaming thread to start
1537  * streaming from the desired position.
1538  *
1539  * Keyframe seeking is a little more complicated when dealing with
1540  * segments. Ideally we want to move to the previous keyframe in
1541  * the segment but there might not be a keyframe in the segment. In
1542  * fact, none of the segments could contain a keyframe. We take a
1543  * practical approach: seek to the previous keyframe in the segment,
1544  * if there is none, seek to the beginning of the segment.
1545  *
1546  * Called with STREAM_LOCK
1547  */
1548 static gboolean
1549 gst_qtdemux_perform_seek (GstQTDemux * qtdemux, GstSegment * segment,
1550     guint32 seqnum, GstSeekFlags flags)
1551 {
1552   gint64 desired_offset;
1553   GList *iter;
1554
1555   desired_offset = segment->position;
1556
1557   GST_DEBUG_OBJECT (qtdemux, "seeking to %" GST_TIME_FORMAT,
1558       GST_TIME_ARGS (desired_offset));
1559
1560   /* may not have enough fragmented info to do this adjustment,
1561    * and we can't scan (and probably should not) at this time with
1562    * possibly flushing upstream */
1563   if ((flags & GST_SEEK_FLAG_KEY_UNIT) && !qtdemux->fragmented) {
1564     gint64 min_offset;
1565     gboolean next, before, after;
1566
1567     before = ! !(flags & GST_SEEK_FLAG_SNAP_BEFORE);
1568     after = ! !(flags & GST_SEEK_FLAG_SNAP_AFTER);
1569     next = after && !before;
1570     if (segment->rate < 0)
1571       next = !next;
1572
1573     gst_qtdemux_adjust_seek (qtdemux, desired_offset, TRUE, next, &min_offset,
1574         NULL);
1575     GST_DEBUG_OBJECT (qtdemux, "keyframe seek, align to %"
1576         GST_TIME_FORMAT, GST_TIME_ARGS (min_offset));
1577     desired_offset = min_offset;
1578   }
1579
1580   /* and set all streams to the final position */
1581   gst_flow_combiner_reset (qtdemux->flowcombiner);
1582   qtdemux->segment_seqnum = seqnum;
1583   for (iter = qtdemux->active_streams; iter; iter = g_list_next (iter)) {
1584     QtDemuxStream *stream = QTDEMUX_STREAM (iter->data);
1585
1586     stream->time_position = desired_offset;
1587     stream->accumulated_base = 0;
1588     stream->sample_index = -1;
1589     stream->offset_in_sample = 0;
1590     stream->segment_index = -1;
1591     stream->sent_eos = FALSE;
1592
1593     if (segment->flags & GST_SEEK_FLAG_FLUSH)
1594       gst_segment_init (&stream->segment, GST_FORMAT_TIME);
1595   }
1596   segment->position = desired_offset;
1597   segment->time = desired_offset;
1598   if (segment->rate >= 0) {
1599     segment->start = desired_offset;
1600
1601     /* we stop at the end */
1602     if (segment->stop == -1)
1603       segment->stop = segment->duration;
1604   } else {
1605     segment->stop = desired_offset;
1606   }
1607
1608   if (qtdemux->fragmented)
1609     qtdemux->fragmented_seek_pending = TRUE;
1610
1611   return TRUE;
1612 }
1613
1614 /* do a seek in pull based mode */
1615 static gboolean
1616 gst_qtdemux_do_seek (GstQTDemux * qtdemux, GstPad * pad, GstEvent * event)
1617 {
1618   gdouble rate;
1619   GstFormat format;
1620   GstSeekFlags flags;
1621   GstSeekType cur_type, stop_type;
1622   gint64 cur, stop;
1623   gboolean flush;
1624   gboolean update;
1625   GstSegment seeksegment;
1626   guint32 seqnum = GST_SEQNUM_INVALID;
1627   GstEvent *flush_event;
1628   gboolean ret;
1629
1630   if (event) {
1631     GST_DEBUG_OBJECT (qtdemux, "doing seek with event");
1632
1633     gst_event_parse_seek (event, &rate, &format, &flags,
1634         &cur_type, &cur, &stop_type, &stop);
1635     seqnum = gst_event_get_seqnum (event);
1636
1637     /* we have to have a format as the segment format. Try to convert
1638      * if not. */
1639     if (!gst_qtdemux_convert_seek (pad, &format, cur_type, &cur,
1640             stop_type, &stop))
1641       goto no_format;
1642
1643     GST_DEBUG_OBJECT (qtdemux, "seek format %s", gst_format_get_name (format));
1644   } else {
1645     GST_DEBUG_OBJECT (qtdemux, "doing seek without event");
1646     flags = 0;
1647   }
1648
1649   flush = flags & GST_SEEK_FLAG_FLUSH;
1650
1651   /* stop streaming, either by flushing or by pausing the task */
1652   if (flush) {
1653     flush_event = gst_event_new_flush_start ();
1654     if (seqnum != GST_SEQNUM_INVALID)
1655       gst_event_set_seqnum (flush_event, seqnum);
1656     /* unlock upstream pull_range */
1657     gst_pad_push_event (qtdemux->sinkpad, gst_event_ref (flush_event));
1658     /* make sure out loop function exits */
1659     gst_qtdemux_push_event (qtdemux, flush_event);
1660   } else {
1661     /* non flushing seek, pause the task */
1662     gst_pad_pause_task (qtdemux->sinkpad);
1663   }
1664
1665   /* wait for streaming to finish */
1666   GST_PAD_STREAM_LOCK (qtdemux->sinkpad);
1667
1668   /* copy segment, we need this because we still need the old
1669    * segment when we close the current segment. */
1670   memcpy (&seeksegment, &qtdemux->segment, sizeof (GstSegment));
1671
1672   if (event) {
1673     /* configure the segment with the seek variables */
1674     GST_DEBUG_OBJECT (qtdemux, "configuring seek");
1675     if (!gst_segment_do_seek (&seeksegment, rate, format, flags,
1676             cur_type, cur, stop_type, stop, &update)) {
1677       ret = FALSE;
1678       GST_ERROR_OBJECT (qtdemux, "inconsistent seek values, doing nothing");
1679     } else {
1680       /* now do the seek */
1681       ret = gst_qtdemux_perform_seek (qtdemux, &seeksegment, seqnum, flags);
1682     }
1683   } else {
1684     /* now do the seek */
1685     ret = gst_qtdemux_perform_seek (qtdemux, &seeksegment, seqnum, flags);
1686   }
1687
1688   /* prepare for streaming again */
1689   if (flush) {
1690     flush_event = gst_event_new_flush_stop (TRUE);
1691     if (seqnum != GST_SEQNUM_INVALID)
1692       gst_event_set_seqnum (flush_event, seqnum);
1693
1694     gst_pad_push_event (qtdemux->sinkpad, gst_event_ref (flush_event));
1695     gst_qtdemux_push_event (qtdemux, flush_event);
1696   }
1697
1698   /* commit the new segment */
1699   memcpy (&qtdemux->segment, &seeksegment, sizeof (GstSegment));
1700
1701   if (qtdemux->segment.flags & GST_SEEK_FLAG_SEGMENT) {
1702     GstMessage *msg = gst_message_new_segment_start (GST_OBJECT_CAST (qtdemux),
1703         qtdemux->segment.format, qtdemux->segment.position);
1704     if (seqnum != GST_SEQNUM_INVALID)
1705       gst_message_set_seqnum (msg, seqnum);
1706     gst_element_post_message (GST_ELEMENT_CAST (qtdemux), msg);
1707   }
1708
1709   /* restart streaming, NEWSEGMENT will be sent from the streaming thread. */
1710   gst_pad_start_task (qtdemux->sinkpad, (GstTaskFunction) gst_qtdemux_loop,
1711       qtdemux->sinkpad, NULL);
1712
1713   GST_PAD_STREAM_UNLOCK (qtdemux->sinkpad);
1714
1715   return ret;
1716
1717   /* ERRORS */
1718 no_format:
1719   {
1720     GST_DEBUG_OBJECT (qtdemux, "unsupported format given, seek aborted.");
1721     return FALSE;
1722   }
1723 }
1724
1725 static gboolean
1726 qtdemux_ensure_index (GstQTDemux * qtdemux)
1727 {
1728   GList *iter;
1729
1730   GST_DEBUG_OBJECT (qtdemux, "collecting all metadata for all streams");
1731
1732   /* Build complete index */
1733   for (iter = qtdemux->active_streams; iter; iter = g_list_next (iter)) {
1734     QtDemuxStream *stream = QTDEMUX_STREAM (iter->data);
1735
1736     if (!qtdemux_parse_samples (qtdemux, stream, stream->n_samples - 1)) {
1737       GST_LOG_OBJECT (qtdemux,
1738           "Building complete index of track-id %u for seeking failed!",
1739           stream->track_id);
1740       return FALSE;
1741     }
1742   }
1743
1744   return TRUE;
1745 }
1746
1747 static gboolean
1748 gst_qtdemux_handle_src_event (GstPad * pad, GstObject * parent,
1749     GstEvent * event)
1750 {
1751   gboolean res = TRUE;
1752   GstQTDemux *qtdemux = GST_QTDEMUX (parent);
1753
1754   switch (GST_EVENT_TYPE (event)) {
1755     case GST_EVENT_SEEK:
1756     {
1757 #ifndef GST_DISABLE_GST_DEBUG
1758       GstClockTime ts = gst_util_get_timestamp ();
1759 #endif
1760       guint32 seqnum = gst_event_get_seqnum (event);
1761
1762       qtdemux->received_seek = TRUE;
1763
1764       if (seqnum == qtdemux->segment_seqnum) {
1765         GST_LOG_OBJECT (pad,
1766             "Drop duplicated SEEK event seqnum %" G_GUINT32_FORMAT, seqnum);
1767         gst_event_unref (event);
1768         return TRUE;
1769       }
1770
1771       if (qtdemux->upstream_format_is_time && qtdemux->fragmented) {
1772         /* seek should be handled by upstream, we might need to re-download fragments */
1773         GST_DEBUG_OBJECT (qtdemux,
1774             "let upstream handle seek for fragmented playback");
1775         goto upstream;
1776       }
1777
1778       /* Build complete index for seeking;
1779        * if not a fragmented file at least */
1780       if (!qtdemux->fragmented)
1781         if (!qtdemux_ensure_index (qtdemux))
1782           goto index_failed;
1783 #ifndef GST_DISABLE_GST_DEBUG
1784       ts = gst_util_get_timestamp () - ts;
1785       GST_INFO_OBJECT (qtdemux,
1786           "Time taken to parse index %" GST_TIME_FORMAT, GST_TIME_ARGS (ts));
1787 #endif
1788     }
1789       if (qtdemux->pullbased) {
1790         res = gst_qtdemux_do_seek (qtdemux, pad, event);
1791       } else if (gst_pad_push_event (qtdemux->sinkpad, gst_event_ref (event))) {
1792         GST_DEBUG_OBJECT (qtdemux, "Upstream successfully seeked");
1793         res = TRUE;
1794       } else if (qtdemux->state == QTDEMUX_STATE_MOVIE && qtdemux->n_streams
1795           && !qtdemux->fragmented) {
1796         res = gst_qtdemux_do_push_seek (qtdemux, pad, event);
1797       } else {
1798         GST_DEBUG_OBJECT (qtdemux,
1799             "ignoring seek in push mode in current state");
1800         res = FALSE;
1801       }
1802       gst_event_unref (event);
1803       break;
1804     default:
1805     upstream:
1806       res = gst_pad_event_default (pad, parent, event);
1807       break;
1808   }
1809
1810 done:
1811   return res;
1812
1813   /* ERRORS */
1814 index_failed:
1815   {
1816     GST_ERROR_OBJECT (qtdemux, "Index failed");
1817     gst_event_unref (event);
1818     res = FALSE;
1819     goto done;
1820   }
1821 }
1822
1823 /* Find, for each track, the first sample in coding order that has a file offset >= @byte_pos.
1824  *
1825  * If @fw is false, the coding order is explored backwards.
1826  *
1827  * If @set is true, each stream will be moved to its matched sample, or EOS if no matching
1828  * sample is found for that track.
1829  *
1830  * The stream and sample index of the sample with the minimum offset in the direction explored
1831  * (see @fw) is returned in the output parameters @_stream and @_index respectively.
1832  *
1833  * @_time is set to the QTSAMPLE_PTS of the matched sample with the minimum QTSAMPLE_PTS in the
1834  * direction explored, which may not always match the QTSAMPLE_PTS of the sample returned in
1835  * @_stream and @_index. */
1836 static void
1837 gst_qtdemux_find_sample (GstQTDemux * qtdemux, gint64 byte_pos, gboolean fw,
1838     gboolean set, QtDemuxStream ** _stream, gint * _index, gint64 * _time)
1839 {
1840   gint i, index;
1841   gint64 time, min_time;
1842   QtDemuxStream *stream;
1843   GList *iter;
1844
1845   min_time = -1;
1846   stream = NULL;
1847   index = -1;
1848
1849   for (iter = qtdemux->active_streams; iter; iter = g_list_next (iter)) {
1850     QtDemuxStream *str;
1851     gint inc;
1852     gboolean set_sample;
1853
1854     str = QTDEMUX_STREAM (iter->data);
1855     set_sample = !set;
1856
1857     if (fw) {
1858       i = 0;
1859       inc = 1;
1860     } else {
1861       i = str->n_samples - 1;
1862       inc = -1;
1863     }
1864
1865     for (; (i >= 0) && (i < str->n_samples); i += inc) {
1866       if (str->samples[i].size == 0)
1867         continue;
1868
1869       if (fw && (str->samples[i].offset < byte_pos))
1870         continue;
1871
1872       if (!fw && (str->samples[i].offset + str->samples[i].size > byte_pos))
1873         continue;
1874
1875       /* move stream to first available sample */
1876       if (set) {
1877         gst_qtdemux_move_stream (qtdemux, str, i);
1878         set_sample = TRUE;
1879       }
1880
1881       /* avoid index from sparse streams since they might be far away */
1882       if (!CUR_STREAM (str)->sparse) {
1883         /* determine min/max time */
1884         time = QTSAMPLE_PTS (str, &str->samples[i]);
1885         if (min_time == -1 || (!fw && time > min_time) ||
1886             (fw && time < min_time)) {
1887           min_time = time;
1888         }
1889
1890         /* determine stream with leading sample, to get its position */
1891         if (!stream ||
1892             (fw && (str->samples[i].offset < stream->samples[index].offset)) ||
1893             (!fw && (str->samples[i].offset > stream->samples[index].offset))) {
1894           stream = str;
1895           index = i;
1896         }
1897       }
1898       break;
1899     }
1900
1901     /* no sample for this stream, mark eos */
1902     if (!set_sample)
1903       gst_qtdemux_move_stream (qtdemux, str, str->n_samples);
1904   }
1905
1906   if (_time)
1907     *_time = min_time;
1908   if (_stream)
1909     *_stream = stream;
1910   if (_index)
1911     *_index = index;
1912 }
1913
1914 /* Copied from mpegtsbase code */
1915 /* FIXME: replace this function when we add new util function for stream-id creation */
1916 static gchar *
1917 _get_upstream_id (GstQTDemux * demux)
1918 {
1919   gchar *upstream_id = gst_pad_get_stream_id (demux->sinkpad);
1920
1921   if (!upstream_id) {
1922     /* Try to create one from the upstream URI, else use a randome number */
1923     GstQuery *query;
1924     gchar *uri = NULL;
1925
1926     /* Try to generate one from the URI query and
1927      * if it fails take a random number instead */
1928     query = gst_query_new_uri ();
1929     if (gst_element_query (GST_ELEMENT_CAST (demux), query)) {
1930       gst_query_parse_uri (query, &uri);
1931     }
1932
1933     if (uri) {
1934       GChecksum *cs;
1935
1936       /* And then generate an SHA256 sum of the URI */
1937       cs = g_checksum_new (G_CHECKSUM_SHA256);
1938       g_checksum_update (cs, (const guchar *) uri, strlen (uri));
1939       g_free (uri);
1940       upstream_id = g_strdup (g_checksum_get_string (cs));
1941       g_checksum_free (cs);
1942     } else {
1943       /* Just get some random number if the URI query fails */
1944       GST_FIXME_OBJECT (demux, "Creating random stream-id, consider "
1945           "implementing a deterministic way of creating a stream-id");
1946       upstream_id =
1947           g_strdup_printf ("%08x%08x%08x%08x", g_random_int (), g_random_int (),
1948           g_random_int (), g_random_int ());
1949     }
1950
1951     gst_query_unref (query);
1952   }
1953   return upstream_id;
1954 }
1955
1956 static QtDemuxStream *
1957 _create_stream (GstQTDemux * demux, guint32 track_id)
1958 {
1959   QtDemuxStream *stream;
1960   gchar *upstream_id;
1961
1962   stream = g_new0 (QtDemuxStream, 1);
1963   stream->demux = demux;
1964   stream->track_id = track_id;
1965   upstream_id = _get_upstream_id (demux);
1966   stream->stream_id = g_strdup_printf ("%s/%03u", upstream_id, track_id);
1967   g_free (upstream_id);
1968   /* new streams always need a discont */
1969   stream->discont = TRUE;
1970   /* we enable clipping for raw audio/video streams */
1971   stream->need_clip = FALSE;
1972   stream->need_process = FALSE;
1973   stream->segment_index = -1;
1974   stream->time_position = 0;
1975   stream->sample_index = -1;
1976   stream->offset_in_sample = 0;
1977   stream->new_stream = TRUE;
1978   stream->multiview_mode = GST_VIDEO_MULTIVIEW_MODE_NONE;
1979   stream->multiview_flags = GST_VIDEO_MULTIVIEW_FLAGS_NONE;
1980   stream->protected = FALSE;
1981   stream->protection_scheme_type = 0;
1982   stream->protection_scheme_version = 0;
1983   stream->protection_scheme_info = NULL;
1984   stream->n_samples_moof = 0;
1985   stream->duration_moof = 0;
1986   stream->duration_last_moof = 0;
1987   stream->alignment = 1;
1988   stream->stream_tags = gst_tag_list_new_empty ();
1989   gst_tag_list_set_scope (stream->stream_tags, GST_TAG_SCOPE_STREAM);
1990   g_queue_init (&stream->protection_scheme_event_queue);
1991   return stream;
1992 }
1993
1994 static gboolean
1995 gst_qtdemux_setcaps (GstQTDemux * demux, GstCaps * caps)
1996 {
1997   GstStructure *structure;
1998   const gchar *variant;
1999   const GstCaps *mediacaps = NULL;
2000
2001   GST_DEBUG_OBJECT (demux, "Sink set caps: %" GST_PTR_FORMAT, caps);
2002
2003   structure = gst_caps_get_structure (caps, 0);
2004   variant = gst_structure_get_string (structure, "variant");
2005
2006   if (variant && strcmp (variant, "mss-fragmented") == 0) {
2007     QtDemuxStream *stream;
2008     const GValue *value;
2009
2010     demux->fragmented = TRUE;
2011     demux->mss_mode = TRUE;
2012
2013     if (demux->n_streams > 1) {
2014       /* can't do this, we can only renegotiate for another mss format */
2015       return FALSE;
2016     }
2017
2018     value = gst_structure_get_value (structure, "media-caps");
2019     /* create stream */
2020     if (value) {
2021       const GValue *timescale_v;
2022
2023       /* TODO update when stream changes during playback */
2024
2025       if (demux->n_streams == 0) {
2026         stream = _create_stream (demux, 1);
2027         demux->active_streams = g_list_append (demux->active_streams, stream);
2028         demux->n_streams = 1;
2029         /* mss has no stsd/stsd entry, use id 0 as default */
2030         stream->stsd_entries_length = 1;
2031         stream->stsd_sample_description_id = stream->cur_stsd_entry_index = 0;
2032         stream->stsd_entries = g_new0 (QtDemuxStreamStsdEntry, 1);
2033       } else {
2034         stream = QTDEMUX_FIRST_STREAM (demux);
2035       }
2036
2037       timescale_v = gst_structure_get_value (structure, "timescale");
2038       if (timescale_v) {
2039         stream->timescale = g_value_get_uint64 (timescale_v);
2040       } else {
2041         /* default mss timescale */
2042         stream->timescale = 10000000;
2043       }
2044       demux->timescale = stream->timescale;
2045
2046       mediacaps = gst_value_get_caps (value);
2047       if (!CUR_STREAM (stream)->caps
2048           || !gst_caps_is_equal_fixed (mediacaps, CUR_STREAM (stream)->caps)) {
2049         GST_DEBUG_OBJECT (demux, "We have a new caps %" GST_PTR_FORMAT,
2050             mediacaps);
2051         stream->new_caps = TRUE;
2052       }
2053       gst_caps_replace (&CUR_STREAM (stream)->caps, (GstCaps *) mediacaps);
2054       structure = gst_caps_get_structure (mediacaps, 0);
2055       if (g_str_has_prefix (gst_structure_get_name (structure), "video")) {
2056         stream->subtype = FOURCC_vide;
2057
2058         gst_structure_get_int (structure, "width", &CUR_STREAM (stream)->width);
2059         gst_structure_get_int (structure, "height",
2060             &CUR_STREAM (stream)->height);
2061         gst_structure_get_fraction (structure, "framerate",
2062             &CUR_STREAM (stream)->fps_n, &CUR_STREAM (stream)->fps_d);
2063       } else if (g_str_has_prefix (gst_structure_get_name (structure), "audio")) {
2064         gint rate = 0;
2065         stream->subtype = FOURCC_soun;
2066         gst_structure_get_int (structure, "channels",
2067             &CUR_STREAM (stream)->n_channels);
2068         gst_structure_get_int (structure, "rate", &rate);
2069         CUR_STREAM (stream)->rate = rate;
2070       }
2071     }
2072     gst_caps_replace (&demux->media_caps, (GstCaps *) mediacaps);
2073   } else {
2074     demux->mss_mode = FALSE;
2075   }
2076
2077   return TRUE;
2078 }
2079
2080 static void
2081 gst_qtdemux_reset (GstQTDemux * qtdemux, gboolean hard)
2082 {
2083   GList *iter;
2084
2085   GST_DEBUG_OBJECT (qtdemux, "Resetting demux");
2086   gst_pad_stop_task (qtdemux->sinkpad);
2087
2088   if (hard || qtdemux->upstream_format_is_time) {
2089     qtdemux->state = QTDEMUX_STATE_INITIAL;
2090     qtdemux->neededbytes = 16;
2091     qtdemux->todrop = 0;
2092     qtdemux->pullbased = FALSE;
2093     qtdemux->posted_redirect = FALSE;
2094     qtdemux->first_mdat = -1;
2095     qtdemux->header_size = 0;
2096     qtdemux->mdatoffset = -1;
2097     qtdemux->restoredata_offset = -1;
2098     if (qtdemux->mdatbuffer)
2099       gst_buffer_unref (qtdemux->mdatbuffer);
2100     if (qtdemux->restoredata_buffer)
2101       gst_buffer_unref (qtdemux->restoredata_buffer);
2102     qtdemux->mdatbuffer = NULL;
2103     qtdemux->restoredata_buffer = NULL;
2104     qtdemux->mdatleft = 0;
2105     qtdemux->mdatsize = 0;
2106     if (qtdemux->comp_brands)
2107       gst_buffer_unref (qtdemux->comp_brands);
2108     qtdemux->comp_brands = NULL;
2109     qtdemux->last_moov_offset = -1;
2110     if (qtdemux->moov_node_compressed) {
2111       g_node_destroy (qtdemux->moov_node_compressed);
2112       if (qtdemux->moov_node)
2113         g_free (qtdemux->moov_node->data);
2114     }
2115     qtdemux->moov_node_compressed = NULL;
2116     if (qtdemux->moov_node)
2117       g_node_destroy (qtdemux->moov_node);
2118     qtdemux->moov_node = NULL;
2119     if (qtdemux->tag_list)
2120       gst_mini_object_unref (GST_MINI_OBJECT_CAST (qtdemux->tag_list));
2121     qtdemux->tag_list = gst_tag_list_new_empty ();
2122     gst_tag_list_set_scope (qtdemux->tag_list, GST_TAG_SCOPE_GLOBAL);
2123 #if 0
2124     if (qtdemux->element_index)
2125       gst_object_unref (qtdemux->element_index);
2126     qtdemux->element_index = NULL;
2127 #endif
2128     qtdemux->major_brand = 0;
2129     qtdemux->upstream_format_is_time = FALSE;
2130     qtdemux->upstream_seekable = FALSE;
2131     qtdemux->upstream_size = 0;
2132
2133     qtdemux->fragment_start = -1;
2134     qtdemux->fragment_start_offset = -1;
2135     qtdemux->duration = 0;
2136     qtdemux->moof_offset = 0;
2137     qtdemux->chapters_track_id = 0;
2138     qtdemux->have_group_id = FALSE;
2139     qtdemux->group_id = G_MAXUINT;
2140
2141     g_queue_foreach (&qtdemux->protection_event_queue, (GFunc) gst_event_unref,
2142         NULL);
2143     g_queue_clear (&qtdemux->protection_event_queue);
2144
2145     qtdemux->received_seek = FALSE;
2146     qtdemux->first_moof_already_parsed = FALSE;
2147   }
2148   qtdemux->offset = 0;
2149   gst_adapter_clear (qtdemux->adapter);
2150   gst_segment_init (&qtdemux->segment, GST_FORMAT_TIME);
2151   qtdemux->need_segment = TRUE;
2152
2153   if (hard) {
2154     qtdemux->segment_seqnum = GST_SEQNUM_INVALID;
2155     g_list_free_full (qtdemux->active_streams,
2156         (GDestroyNotify) gst_qtdemux_stream_free);
2157     g_list_free_full (qtdemux->old_streams,
2158         (GDestroyNotify) gst_qtdemux_stream_free);
2159     qtdemux->active_streams = NULL;
2160     qtdemux->old_streams = NULL;
2161     qtdemux->n_streams = 0;
2162     qtdemux->n_video_streams = 0;
2163     qtdemux->n_audio_streams = 0;
2164     qtdemux->n_sub_streams = 0;
2165     qtdemux->exposed = FALSE;
2166     qtdemux->fragmented = FALSE;
2167     qtdemux->mss_mode = FALSE;
2168     gst_caps_replace (&qtdemux->media_caps, NULL);
2169     qtdemux->timescale = 0;
2170     qtdemux->got_moov = FALSE;
2171     qtdemux->cenc_aux_info_offset = 0;
2172     qtdemux->cenc_aux_info_sizes = NULL;
2173     qtdemux->cenc_aux_sample_count = 0;
2174     if (qtdemux->protection_system_ids) {
2175       g_ptr_array_free (qtdemux->protection_system_ids, TRUE);
2176       qtdemux->protection_system_ids = NULL;
2177     }
2178     qtdemux->streams_aware = GST_OBJECT_PARENT (qtdemux)
2179         && GST_OBJECT_FLAG_IS_SET (GST_OBJECT_PARENT (qtdemux),
2180         GST_BIN_FLAG_STREAMS_AWARE);
2181
2182     if (qtdemux->preferred_protection_system_id) {
2183       g_free (qtdemux->preferred_protection_system_id);
2184       qtdemux->preferred_protection_system_id = NULL;
2185     }
2186   } else if (qtdemux->mss_mode) {
2187     gst_flow_combiner_reset (qtdemux->flowcombiner);
2188     g_list_foreach (qtdemux->active_streams,
2189         (GFunc) gst_qtdemux_stream_clear, NULL);
2190   } else {
2191     gst_flow_combiner_reset (qtdemux->flowcombiner);
2192     for (iter = qtdemux->active_streams; iter; iter = g_list_next (iter)) {
2193       QtDemuxStream *stream = QTDEMUX_STREAM (iter->data);
2194       stream->sent_eos = FALSE;
2195       stream->time_position = 0;
2196       stream->accumulated_base = 0;
2197     }
2198   }
2199 }
2200
2201
2202 /* Maps the @segment to the qt edts internal segments and pushes
2203  * the correspnding segment event.
2204  *
2205  * If it ends up being at a empty segment, a gap will be pushed and the next
2206  * edts segment will be activated in sequence.
2207  *
2208  * To be used in push-mode only */
2209 static void
2210 gst_qtdemux_map_and_push_segments (GstQTDemux * qtdemux, GstSegment * segment)
2211 {
2212   gint i;
2213   GList *iter;
2214
2215   for (iter = qtdemux->active_streams; iter; iter = g_list_next (iter)) {
2216     QtDemuxStream *stream = QTDEMUX_STREAM (iter->data);
2217
2218     stream->time_position = segment->start;
2219
2220     /* in push mode we should be guaranteed that we will have empty segments
2221      * at the beginning and then one segment after, other scenarios are not
2222      * supported and are discarded when parsing the edts */
2223     for (i = 0; i < stream->n_segments; i++) {
2224       if (stream->segments[i].stop_time > segment->start) {
2225         /* push the empty segment and move to the next one */
2226         gst_qtdemux_activate_segment (qtdemux, stream, i,
2227             stream->time_position);
2228         if (QTSEGMENT_IS_EMPTY (&stream->segments[i])) {
2229           gst_qtdemux_send_gap_for_segment (qtdemux, stream, i,
2230               stream->time_position);
2231
2232           /* accumulate previous segments */
2233           if (GST_CLOCK_TIME_IS_VALID (stream->segment.stop))
2234             stream->accumulated_base +=
2235                 (stream->segment.stop -
2236                 stream->segment.start) / ABS (stream->segment.rate);
2237           continue;
2238         }
2239
2240         g_assert (i == stream->n_segments - 1);
2241       }
2242     }
2243   }
2244 }
2245
2246 static gboolean
2247 gst_qtdemux_handle_sink_event (GstPad * sinkpad, GstObject * parent,
2248     GstEvent * event)
2249 {
2250   GstQTDemux *demux = GST_QTDEMUX (parent);
2251   gboolean res = TRUE;
2252
2253   GST_LOG_OBJECT (demux, "handling %s event", GST_EVENT_TYPE_NAME (event));
2254
2255   switch (GST_EVENT_TYPE (event)) {
2256     case GST_EVENT_SEGMENT:
2257     {
2258       gint64 offset = 0;
2259       QtDemuxStream *stream;
2260       gint idx;
2261       GstSegment segment;
2262
2263       /* some debug output */
2264       gst_event_copy_segment (event, &segment);
2265       GST_DEBUG_OBJECT (demux, "received newsegment %" GST_SEGMENT_FORMAT,
2266           &segment);
2267
2268       if (segment.format == GST_FORMAT_TIME) {
2269         demux->upstream_format_is_time = TRUE;
2270         demux->segment_seqnum = gst_event_get_seqnum (event);
2271       } else {
2272         GST_DEBUG_OBJECT (demux, "Not storing upstream newsegment, "
2273             "not in time format");
2274
2275         /* chain will send initial newsegment after pads have been added */
2276         if (demux->state != QTDEMUX_STATE_MOVIE || !demux->n_streams) {
2277           GST_DEBUG_OBJECT (demux, "still starting, eating event");
2278           goto exit;
2279         }
2280       }
2281
2282       /* check if this matches a time seek we received previously
2283        * FIXME for backwards compatibility reasons we use the
2284        * seek_offset here to compare. In the future we might want to
2285        * change this to use the seqnum as it uniquely should identify
2286        * the segment that corresponds to the seek. */
2287       GST_DEBUG_OBJECT (demux, "Stored seek offset: %" G_GINT64_FORMAT
2288           ", received segment offset %" G_GINT64_FORMAT,
2289           demux->seek_offset, segment.start);
2290       if (segment.format == GST_FORMAT_BYTES
2291           && demux->seek_offset == segment.start) {
2292         GST_OBJECT_LOCK (demux);
2293         offset = segment.start;
2294
2295         segment.format = GST_FORMAT_TIME;
2296         segment.start = demux->push_seek_start;
2297         segment.stop = demux->push_seek_stop;
2298         GST_DEBUG_OBJECT (demux, "Replaced segment with stored seek "
2299             "segment %" GST_TIME_FORMAT " - %" GST_TIME_FORMAT,
2300             GST_TIME_ARGS (segment.start), GST_TIME_ARGS (segment.stop));
2301         GST_OBJECT_UNLOCK (demux);
2302       }
2303
2304       /* we only expect a BYTE segment, e.g. following a seek */
2305       if (segment.format == GST_FORMAT_BYTES) {
2306         if (GST_CLOCK_TIME_IS_VALID (segment.start)) {
2307           offset = segment.start;
2308
2309           gst_qtdemux_find_sample (demux, segment.start, TRUE, FALSE, NULL,
2310               NULL, (gint64 *) & segment.start);
2311           if ((gint64) segment.start < 0)
2312             segment.start = 0;
2313         }
2314         if (GST_CLOCK_TIME_IS_VALID (segment.stop)) {
2315           gst_qtdemux_find_sample (demux, segment.stop, FALSE, FALSE, NULL,
2316               NULL, (gint64 *) & segment.stop);
2317           /* keyframe seeking should already arrange for start >= stop,
2318            * but make sure in other rare cases */
2319           segment.stop = MAX (segment.stop, segment.start);
2320         }
2321       } else if (segment.format == GST_FORMAT_TIME) {
2322         /* push all data on the adapter before starting this
2323          * new segment */
2324         gst_qtdemux_process_adapter (demux, TRUE);
2325       } else {
2326         GST_DEBUG_OBJECT (demux, "unsupported segment format, ignoring");
2327         goto exit;
2328       }
2329
2330       /* We shouldn't modify upstream driven TIME FORMAT segment */
2331       if (!demux->upstream_format_is_time) {
2332         /* accept upstream's notion of segment and distribute along */
2333         segment.format = GST_FORMAT_TIME;
2334         segment.position = segment.time = segment.start;
2335         segment.duration = demux->segment.duration;
2336         segment.base = gst_segment_to_running_time (&demux->segment,
2337             GST_FORMAT_TIME, demux->segment.position);
2338       }
2339
2340       gst_segment_copy_into (&segment, &demux->segment);
2341       GST_DEBUG_OBJECT (demux, "Pushing newseg %" GST_SEGMENT_FORMAT, &segment);
2342
2343       /* map segment to internal qt segments and push on each stream */
2344       if (demux->n_streams) {
2345         demux->need_segment = TRUE;
2346         gst_qtdemux_check_send_pending_segment (demux);
2347       }
2348
2349       /* clear leftover in current segment, if any */
2350       gst_adapter_clear (demux->adapter);
2351
2352       /* set up streaming thread */
2353       demux->offset = offset;
2354       if (demux->upstream_format_is_time) {
2355         GST_DEBUG_OBJECT (demux, "Upstream is driving in time format, "
2356             "set values to restart reading from a new atom");
2357         demux->neededbytes = 16;
2358         demux->todrop = 0;
2359       } else {
2360         gst_qtdemux_find_sample (demux, offset, TRUE, TRUE, &stream, &idx,
2361             NULL);
2362         if (stream) {
2363           demux->todrop = stream->samples[idx].offset - offset;
2364           demux->neededbytes = demux->todrop + stream->samples[idx].size;
2365         } else {
2366           /* set up for EOS */
2367           demux->neededbytes = -1;
2368           demux->todrop = 0;
2369         }
2370       }
2371     exit:
2372       gst_event_unref (event);
2373       res = TRUE;
2374       goto drop;
2375     }
2376     case GST_EVENT_FLUSH_START:
2377     {
2378       if (gst_event_get_seqnum (event) == demux->offset_seek_seqnum) {
2379         gst_event_unref (event);
2380         goto drop;
2381       }
2382       QTDEMUX_EXPOSE_LOCK (demux);
2383       res = gst_pad_event_default (demux->sinkpad, parent, event);
2384       QTDEMUX_EXPOSE_UNLOCK (demux);
2385       goto drop;
2386     }
2387     case GST_EVENT_FLUSH_STOP:
2388     {
2389       guint64 dur;
2390
2391       dur = demux->segment.duration;
2392       gst_qtdemux_reset (demux, FALSE);
2393       demux->segment.duration = dur;
2394
2395       if (gst_event_get_seqnum (event) == demux->offset_seek_seqnum) {
2396         gst_event_unref (event);
2397         goto drop;
2398       }
2399       break;
2400     }
2401     case GST_EVENT_EOS:
2402       /* If we are in push mode, and get an EOS before we've seen any streams,
2403        * then error out - we have nowhere to send the EOS */
2404       if (!demux->pullbased) {
2405         GList *iter;
2406         gboolean has_valid_stream = FALSE;
2407         for (iter = demux->active_streams; iter; iter = g_list_next (iter)) {
2408           if (QTDEMUX_STREAM (iter->data)->pad != NULL) {
2409             has_valid_stream = TRUE;
2410             break;
2411           }
2412         }
2413         if (!has_valid_stream)
2414           gst_qtdemux_post_no_playable_stream_error (demux);
2415         else {
2416           GST_DEBUG_OBJECT (demux, "Data still available after EOS: %u",
2417               (guint) gst_adapter_available (demux->adapter));
2418           if (gst_qtdemux_process_adapter (demux, TRUE) != GST_FLOW_OK) {
2419             res = FALSE;
2420           }
2421         }
2422       }
2423       break;
2424     case GST_EVENT_CAPS:{
2425       GstCaps *caps = NULL;
2426
2427       gst_event_parse_caps (event, &caps);
2428       gst_qtdemux_setcaps (demux, caps);
2429       res = TRUE;
2430       gst_event_unref (event);
2431       goto drop;
2432     }
2433     case GST_EVENT_PROTECTION:
2434     {
2435       const gchar *system_id = NULL;
2436
2437       gst_event_parse_protection (event, &system_id, NULL, NULL);
2438       GST_DEBUG_OBJECT (demux, "Received protection event for system ID %s",
2439           system_id);
2440       gst_qtdemux_append_protection_system_id (demux, system_id);
2441       /* save the event for later, for source pads that have not been created */
2442       g_queue_push_tail (&demux->protection_event_queue, gst_event_ref (event));
2443       /* send it to all pads that already exist */
2444       gst_qtdemux_push_event (demux, event);
2445       res = TRUE;
2446       goto drop;
2447     }
2448     case GST_EVENT_STREAM_START:
2449     {
2450       res = TRUE;
2451       gst_event_unref (event);
2452
2453       /* Drain all the buffers */
2454       gst_qtdemux_process_adapter (demux, TRUE);
2455       gst_qtdemux_reset (demux, FALSE);
2456       /* We expect new moov box after new stream-start event */
2457       demux->old_streams =
2458           g_list_concat (demux->old_streams, demux->active_streams);
2459       demux->active_streams = NULL;
2460
2461       goto drop;
2462     }
2463     default:
2464       break;
2465   }
2466
2467   res = gst_pad_event_default (demux->sinkpad, parent, event) & res;
2468
2469 drop:
2470   return res;
2471 }
2472
2473 #if 0
2474 static void
2475 gst_qtdemux_set_index (GstElement * element, GstIndex * index)
2476 {
2477   GstQTDemux *demux = GST_QTDEMUX (element);
2478
2479   GST_OBJECT_LOCK (demux);
2480   if (demux->element_index)
2481     gst_object_unref (demux->element_index);
2482   if (index) {
2483     demux->element_index = gst_object_ref (index);
2484   } else {
2485     demux->element_index = NULL;
2486   }
2487   GST_OBJECT_UNLOCK (demux);
2488   /* object lock might be taken again */
2489   if (index)
2490     gst_index_get_writer_id (index, GST_OBJECT (element), &demux->index_id);
2491   GST_DEBUG_OBJECT (demux, "Set index %" GST_PTR_FORMAT "for writer id %d",
2492       demux->element_index, demux->index_id);
2493 }
2494
2495 static GstIndex *
2496 gst_qtdemux_get_index (GstElement * element)
2497 {
2498   GstIndex *result = NULL;
2499   GstQTDemux *demux = GST_QTDEMUX (element);
2500
2501   GST_OBJECT_LOCK (demux);
2502   if (demux->element_index)
2503     result = gst_object_ref (demux->element_index);
2504   GST_OBJECT_UNLOCK (demux);
2505
2506   GST_DEBUG_OBJECT (demux, "Returning index %" GST_PTR_FORMAT, result);
2507
2508   return result;
2509 }
2510 #endif
2511
2512 static void
2513 gst_qtdemux_stbl_free (QtDemuxStream * stream)
2514 {
2515   g_free ((gpointer) stream->stco.data);
2516   stream->stco.data = NULL;
2517   g_free ((gpointer) stream->stsz.data);
2518   stream->stsz.data = NULL;
2519   g_free ((gpointer) stream->stsc.data);
2520   stream->stsc.data = NULL;
2521   g_free ((gpointer) stream->stts.data);
2522   stream->stts.data = NULL;
2523   g_free ((gpointer) stream->stss.data);
2524   stream->stss.data = NULL;
2525   g_free ((gpointer) stream->stps.data);
2526   stream->stps.data = NULL;
2527   g_free ((gpointer) stream->ctts.data);
2528   stream->ctts.data = NULL;
2529 }
2530
2531 static void
2532 gst_qtdemux_stream_flush_segments_data (QtDemuxStream * stream)
2533 {
2534   g_free (stream->segments);
2535   stream->segments = NULL;
2536   stream->segment_index = -1;
2537   stream->accumulated_base = 0;
2538 }
2539
2540 static void
2541 gst_qtdemux_stream_flush_samples_data (QtDemuxStream * stream)
2542 {
2543   g_free (stream->samples);
2544   stream->samples = NULL;
2545   gst_qtdemux_stbl_free (stream);
2546
2547   /* fragments */
2548   g_free (stream->ra_entries);
2549   stream->ra_entries = NULL;
2550   stream->n_ra_entries = 0;
2551
2552   stream->sample_index = -1;
2553   stream->stbl_index = -1;
2554   stream->n_samples = 0;
2555   stream->time_position = 0;
2556
2557   stream->n_samples_moof = 0;
2558   stream->duration_moof = 0;
2559   stream->duration_last_moof = 0;
2560 }
2561
2562 static void
2563 gst_qtdemux_stream_clear (QtDemuxStream * stream)
2564 {
2565   gint i;
2566   if (stream->allocator)
2567     gst_object_unref (stream->allocator);
2568   while (stream->buffers) {
2569     gst_buffer_unref (GST_BUFFER_CAST (stream->buffers->data));
2570     stream->buffers = g_slist_delete_link (stream->buffers, stream->buffers);
2571   }
2572   for (i = 0; i < stream->stsd_entries_length; i++) {
2573     QtDemuxStreamStsdEntry *entry = &stream->stsd_entries[i];
2574     if (entry->rgb8_palette) {
2575       gst_memory_unref (entry->rgb8_palette);
2576       entry->rgb8_palette = NULL;
2577     }
2578     entry->sparse = FALSE;
2579   }
2580
2581   if (stream->stream_tags)
2582     gst_tag_list_unref (stream->stream_tags);
2583
2584   stream->stream_tags = gst_tag_list_new_empty ();
2585   gst_tag_list_set_scope (stream->stream_tags, GST_TAG_SCOPE_STREAM);
2586   g_free (stream->redirect_uri);
2587   stream->redirect_uri = NULL;
2588   stream->sent_eos = FALSE;
2589   stream->protected = FALSE;
2590   if (stream->protection_scheme_info) {
2591     if (stream->protection_scheme_type == FOURCC_cenc) {
2592       QtDemuxCencSampleSetInfo *info =
2593           (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
2594       if (info->default_properties)
2595         gst_structure_free (info->default_properties);
2596       if (info->crypto_info)
2597         g_ptr_array_free (info->crypto_info, TRUE);
2598     }
2599     g_free (stream->protection_scheme_info);
2600     stream->protection_scheme_info = NULL;
2601   }
2602   stream->protection_scheme_type = 0;
2603   stream->protection_scheme_version = 0;
2604   g_queue_foreach (&stream->protection_scheme_event_queue,
2605       (GFunc) gst_event_unref, NULL);
2606   g_queue_clear (&stream->protection_scheme_event_queue);
2607   gst_qtdemux_stream_flush_segments_data (stream);
2608   gst_qtdemux_stream_flush_samples_data (stream);
2609 }
2610
2611 static void
2612 gst_qtdemux_stream_reset (QtDemuxStream * stream)
2613 {
2614   gint i;
2615   gst_qtdemux_stream_clear (stream);
2616   for (i = 0; i < stream->stsd_entries_length; i++) {
2617     QtDemuxStreamStsdEntry *entry = &stream->stsd_entries[i];
2618     if (entry->caps) {
2619       gst_caps_unref (entry->caps);
2620       entry->caps = NULL;
2621     }
2622   }
2623   g_free (stream->stsd_entries);
2624   stream->stsd_entries = NULL;
2625   stream->stsd_entries_length = 0;
2626 }
2627
2628
2629 static void
2630 gst_qtdemux_stream_free (QtDemuxStream * stream)
2631 {
2632   gst_qtdemux_stream_reset (stream);
2633   gst_tag_list_unref (stream->stream_tags);
2634   if (stream->pad) {
2635     GstQTDemux *demux = stream->demux;
2636     gst_element_remove_pad (GST_ELEMENT_CAST (demux), stream->pad);
2637     gst_flow_combiner_remove_pad (demux->flowcombiner, stream->pad);
2638   }
2639   g_free (stream->stream_id);
2640   g_free (stream);
2641 }
2642
2643 static void
2644 gst_qtdemux_remove_stream (GstQTDemux * qtdemux, QtDemuxStream * stream)
2645 {
2646   qtdemux->active_streams = g_list_remove (qtdemux->active_streams, stream);
2647   gst_qtdemux_stream_free (stream);
2648   qtdemux->n_streams--;
2649 }
2650
2651 static GstStateChangeReturn
2652 gst_qtdemux_change_state (GstElement * element, GstStateChange transition)
2653 {
2654   GstQTDemux *qtdemux = GST_QTDEMUX (element);
2655   GstStateChangeReturn result = GST_STATE_CHANGE_FAILURE;
2656
2657   switch (transition) {
2658     case GST_STATE_CHANGE_READY_TO_PAUSED:
2659       gst_qtdemux_reset (qtdemux, TRUE);
2660       break;
2661     default:
2662       break;
2663   }
2664
2665   result = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
2666
2667   switch (transition) {
2668     case GST_STATE_CHANGE_PAUSED_TO_READY:{
2669       gst_qtdemux_reset (qtdemux, TRUE);
2670       break;
2671     }
2672     default:
2673       break;
2674   }
2675
2676   return result;
2677 }
2678
2679 static void
2680 gst_qtdemux_set_context (GstElement * element, GstContext * context)
2681 {
2682   GstQTDemux *qtdemux = GST_QTDEMUX (element);
2683
2684   g_return_if_fail (GST_IS_CONTEXT (context));
2685
2686   if (gst_context_has_context_type (context,
2687           "drm-preferred-decryption-system-id")) {
2688     const GstStructure *s;
2689
2690     s = gst_context_get_structure (context);
2691     g_free (qtdemux->preferred_protection_system_id);
2692     qtdemux->preferred_protection_system_id =
2693         g_strdup (gst_structure_get_string (s, "decryption-system-id"));
2694     GST_DEBUG_OBJECT (element, "set preferred decryption system to %s",
2695         qtdemux->preferred_protection_system_id);
2696   }
2697
2698   GST_ELEMENT_CLASS (parent_class)->set_context (element, context);
2699 }
2700
2701 static void
2702 qtdemux_parse_ftyp (GstQTDemux * qtdemux, const guint8 * buffer, gint length)
2703 {
2704   /* counts as header data */
2705   qtdemux->header_size += length;
2706
2707   /* only consider at least a sufficiently complete ftyp atom */
2708   if (length >= 20) {
2709     GstBuffer *buf;
2710
2711     qtdemux->major_brand = QT_FOURCC (buffer + 8);
2712     GST_DEBUG_OBJECT (qtdemux, "major brand: %" GST_FOURCC_FORMAT,
2713         GST_FOURCC_ARGS (qtdemux->major_brand));
2714     if (qtdemux->comp_brands)
2715       gst_buffer_unref (qtdemux->comp_brands);
2716     buf = qtdemux->comp_brands = gst_buffer_new_and_alloc (length - 16);
2717     gst_buffer_fill (buf, 0, buffer + 16, length - 16);
2718   }
2719 }
2720
2721 static void
2722 qtdemux_handle_xmp_taglist (GstQTDemux * qtdemux, GstTagList * taglist,
2723     GstTagList * xmptaglist)
2724 {
2725   /* Strip out bogus fields */
2726   if (xmptaglist) {
2727     if (gst_tag_list_get_scope (taglist) == GST_TAG_SCOPE_GLOBAL) {
2728       gst_tag_list_remove_tag (xmptaglist, GST_TAG_VIDEO_CODEC);
2729       gst_tag_list_remove_tag (xmptaglist, GST_TAG_AUDIO_CODEC);
2730     } else {
2731       gst_tag_list_remove_tag (xmptaglist, GST_TAG_CONTAINER_FORMAT);
2732     }
2733
2734     GST_DEBUG_OBJECT (qtdemux, "Found XMP tags %" GST_PTR_FORMAT, xmptaglist);
2735
2736     /* prioritize native tags using _KEEP mode */
2737     gst_tag_list_insert (taglist, xmptaglist, GST_TAG_MERGE_KEEP);
2738     gst_tag_list_unref (xmptaglist);
2739   }
2740 }
2741
2742 static void
2743 qtdemux_parse_piff (GstQTDemux * qtdemux, const guint8 * buffer, gint length,
2744     guint offset)
2745 {
2746   GstByteReader br;
2747   guint8 version;
2748   guint32 flags = 0;
2749   guint i;
2750   guint8 iv_size = 8;
2751   QtDemuxStream *stream;
2752   GstStructure *structure;
2753   QtDemuxCencSampleSetInfo *ss_info = NULL;
2754   const gchar *system_id;
2755   gboolean uses_sub_sample_encryption = FALSE;
2756   guint32 sample_count;
2757
2758   stream = QTDEMUX_FIRST_STREAM (qtdemux);
2759   if (!stream)
2760     return;
2761
2762   structure = gst_caps_get_structure (CUR_STREAM (stream)->caps, 0);
2763   if (!gst_structure_has_name (structure, "application/x-cenc")) {
2764     GST_WARNING_OBJECT (qtdemux,
2765         "Attempting PIFF box parsing on an unencrypted stream.");
2766     return;
2767   }
2768
2769   gst_structure_get (structure, GST_PROTECTION_SYSTEM_ID_CAPS_FIELD,
2770       G_TYPE_STRING, &system_id, NULL);
2771   gst_qtdemux_append_protection_system_id (qtdemux, system_id);
2772
2773   stream->protected = TRUE;
2774   stream->protection_scheme_type = FOURCC_cenc;
2775
2776   if (!stream->protection_scheme_info)
2777     stream->protection_scheme_info = g_new0 (QtDemuxCencSampleSetInfo, 1);
2778
2779   ss_info = (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
2780
2781   if (ss_info->default_properties)
2782     gst_structure_free (ss_info->default_properties);
2783
2784   ss_info->default_properties =
2785       gst_structure_new ("application/x-cenc",
2786       "iv_size", G_TYPE_UINT, iv_size, "encrypted", G_TYPE_BOOLEAN, TRUE, NULL);
2787
2788   if (ss_info->crypto_info) {
2789     GST_LOG_OBJECT (qtdemux, "unreffing existing crypto_info");
2790     g_ptr_array_free (ss_info->crypto_info, TRUE);
2791     ss_info->crypto_info = NULL;
2792   }
2793
2794   /* skip UUID */
2795   gst_byte_reader_init (&br, buffer + offset + 16, length - offset - 16);
2796
2797   if (!gst_byte_reader_get_uint8 (&br, &version)) {
2798     GST_ERROR_OBJECT (qtdemux, "Error getting box's version field");
2799     return;
2800   }
2801
2802   if (!gst_byte_reader_get_uint24_be (&br, &flags)) {
2803     GST_ERROR_OBJECT (qtdemux, "Error getting box's flags field");
2804     return;
2805   }
2806
2807   if ((flags & 0x000001)) {
2808     guint32 algorithm_id = 0;
2809     const guint8 *kid;
2810     GstBuffer *kid_buf;
2811     gboolean is_encrypted = TRUE;
2812
2813     if (!gst_byte_reader_get_uint24_le (&br, &algorithm_id)) {
2814       GST_ERROR_OBJECT (qtdemux, "Error getting box's algorithm ID field");
2815       return;
2816     }
2817
2818     algorithm_id >>= 8;
2819     if (algorithm_id == 0) {
2820       is_encrypted = FALSE;
2821     } else if (algorithm_id == 1) {
2822       /* FIXME: maybe store this in properties? */
2823       GST_DEBUG_OBJECT (qtdemux, "AES 128-bits CTR encrypted stream");
2824     } else if (algorithm_id == 2) {
2825       /* FIXME: maybe store this in properties? */
2826       GST_DEBUG_OBJECT (qtdemux, "AES 128-bits CBC encrypted stream");
2827     }
2828
2829     if (!gst_byte_reader_get_uint8 (&br, &iv_size))
2830       return;
2831
2832     if (!gst_byte_reader_get_data (&br, 16, &kid))
2833       return;
2834
2835     kid_buf = gst_buffer_new_allocate (NULL, 16, NULL);
2836     gst_buffer_fill (kid_buf, 0, kid, 16);
2837     if (ss_info->default_properties)
2838       gst_structure_free (ss_info->default_properties);
2839     ss_info->default_properties =
2840         gst_structure_new ("application/x-cenc",
2841         "iv_size", G_TYPE_UINT, iv_size,
2842         "encrypted", G_TYPE_BOOLEAN, is_encrypted,
2843         "kid", GST_TYPE_BUFFER, kid_buf, NULL);
2844     GST_DEBUG_OBJECT (qtdemux, "default sample properties: "
2845         "is_encrypted=%u, iv_size=%u", is_encrypted, iv_size);
2846     gst_buffer_unref (kid_buf);
2847   } else if ((flags & 0x000002)) {
2848     uses_sub_sample_encryption = TRUE;
2849   }
2850
2851   if (!gst_byte_reader_get_uint32_be (&br, &sample_count)) {
2852     GST_ERROR_OBJECT (qtdemux, "Error getting box's sample count field");
2853     return;
2854   }
2855
2856   ss_info->crypto_info =
2857       g_ptr_array_new_full (sample_count,
2858       (GDestroyNotify) qtdemux_gst_structure_free);
2859
2860   for (i = 0; i < sample_count; ++i) {
2861     GstStructure *properties;
2862     guint8 *data;
2863     GstBuffer *buf;
2864
2865     properties = qtdemux_get_cenc_sample_properties (qtdemux, stream, i);
2866     if (properties == NULL) {
2867       GST_ERROR_OBJECT (qtdemux, "failed to get properties for sample %u", i);
2868       qtdemux->cenc_aux_sample_count = i;
2869       return;
2870     }
2871
2872     if (!gst_byte_reader_dup_data (&br, iv_size, &data)) {
2873       GST_ERROR_OBJECT (qtdemux, "IV data not present for sample %u", i);
2874       gst_structure_free (properties);
2875       qtdemux->cenc_aux_sample_count = i;
2876       return;
2877     }
2878     buf = gst_buffer_new_wrapped (data, iv_size);
2879     gst_structure_set (properties, "iv", GST_TYPE_BUFFER, buf, NULL);
2880     gst_buffer_unref (buf);
2881
2882     if (uses_sub_sample_encryption) {
2883       guint16 n_subsamples;
2884
2885       if (!gst_byte_reader_get_uint16_be (&br, &n_subsamples)
2886           || n_subsamples == 0) {
2887         GST_ERROR_OBJECT (qtdemux,
2888             "failed to get subsample count for sample %u", i);
2889         gst_structure_free (properties);
2890         qtdemux->cenc_aux_sample_count = i;
2891         return;
2892       }
2893       GST_LOG_OBJECT (qtdemux, "subsample count: %u", n_subsamples);
2894       if (!gst_byte_reader_dup_data (&br, n_subsamples * 6, &data)) {
2895         GST_ERROR_OBJECT (qtdemux, "failed to get subsample data for sample %u",
2896             i);
2897         gst_structure_free (properties);
2898         qtdemux->cenc_aux_sample_count = i;
2899         return;
2900       }
2901       buf = gst_buffer_new_wrapped (data, n_subsamples * 6);
2902       gst_structure_set (properties,
2903           "subsample_count", G_TYPE_UINT, n_subsamples,
2904           "subsamples", GST_TYPE_BUFFER, buf, NULL);
2905       gst_buffer_unref (buf);
2906     } else {
2907       gst_structure_set (properties, "subsample_count", G_TYPE_UINT, 0, NULL);
2908     }
2909
2910     g_ptr_array_add (ss_info->crypto_info, properties);
2911   }
2912
2913   qtdemux->cenc_aux_sample_count = sample_count;
2914 }
2915
2916 static void
2917 qtdemux_parse_uuid (GstQTDemux * qtdemux, const guint8 * buffer, gint length)
2918 {
2919   static const guint8 xmp_uuid[] = { 0xBE, 0x7A, 0xCF, 0xCB,
2920     0x97, 0xA9, 0x42, 0xE8,
2921     0x9C, 0x71, 0x99, 0x94,
2922     0x91, 0xE3, 0xAF, 0xAC
2923   };
2924   static const guint8 playready_uuid[] = {
2925     0xd0, 0x8a, 0x4f, 0x18, 0x10, 0xf3, 0x4a, 0x82,
2926     0xb6, 0xc8, 0x32, 0xd8, 0xab, 0xa1, 0x83, 0xd3
2927   };
2928
2929   static const guint8 piff_sample_encryption_uuid[] = {
2930     0xa2, 0x39, 0x4f, 0x52, 0x5a, 0x9b, 0x4f, 0x14,
2931     0xa2, 0x44, 0x6c, 0x42, 0x7c, 0x64, 0x8d, 0xf4
2932   };
2933
2934   guint offset;
2935
2936   /* counts as header data */
2937   qtdemux->header_size += length;
2938
2939   offset = (QT_UINT32 (buffer) == 0) ? 16 : 8;
2940
2941   if (length <= offset + 16) {
2942     GST_DEBUG_OBJECT (qtdemux, "uuid atom is too short, skipping");
2943     return;
2944   }
2945
2946   if (memcmp (buffer + offset, xmp_uuid, 16) == 0) {
2947     GstBuffer *buf;
2948     GstTagList *taglist;
2949
2950     buf = _gst_buffer_new_wrapped ((guint8 *) buffer + offset + 16,
2951         length - offset - 16, NULL);
2952     taglist = gst_tag_list_from_xmp_buffer (buf);
2953     gst_buffer_unref (buf);
2954
2955     /* make sure we have a usable taglist */
2956     qtdemux->tag_list = gst_tag_list_make_writable (qtdemux->tag_list);
2957
2958     qtdemux_handle_xmp_taglist (qtdemux, qtdemux->tag_list, taglist);
2959
2960   } else if (memcmp (buffer + offset, playready_uuid, 16) == 0) {
2961     int len;
2962     const gunichar2 *s_utf16;
2963     char *contents;
2964
2965     len = GST_READ_UINT16_LE (buffer + offset + 0x30);
2966     s_utf16 = (const gunichar2 *) (buffer + offset + 0x32);
2967     contents = g_utf16_to_utf8 (s_utf16, len / 2, NULL, NULL, NULL);
2968     GST_ERROR_OBJECT (qtdemux, "contents: %s", contents);
2969
2970     g_free (contents);
2971
2972     GST_ELEMENT_ERROR (qtdemux, STREAM, DECRYPT,
2973         (_("Cannot play stream because it is encrypted with PlayReady DRM.")),
2974         (NULL));
2975   } else if (memcmp (buffer + offset, piff_sample_encryption_uuid, 16) == 0) {
2976     qtdemux_parse_piff (qtdemux, buffer, length, offset);
2977   } else {
2978     GST_DEBUG_OBJECT (qtdemux, "Ignoring unknown uuid: %08x-%08x-%08x-%08x",
2979         GST_READ_UINT32_LE (buffer + offset),
2980         GST_READ_UINT32_LE (buffer + offset + 4),
2981         GST_READ_UINT32_LE (buffer + offset + 8),
2982         GST_READ_UINT32_LE (buffer + offset + 12));
2983   }
2984 }
2985
2986 static void
2987 qtdemux_parse_sidx (GstQTDemux * qtdemux, const guint8 * buffer, gint length)
2988 {
2989   GstSidxParser sidx_parser;
2990   GstIsoffParserResult res;
2991   guint consumed;
2992
2993   gst_isoff_qt_sidx_parser_init (&sidx_parser);
2994
2995   res =
2996       gst_isoff_qt_sidx_parser_add_data (&sidx_parser, buffer, length,
2997       &consumed);
2998   GST_DEBUG_OBJECT (qtdemux, "sidx parse result: %d", res);
2999   if (res == GST_ISOFF_QT_PARSER_DONE) {
3000     check_update_duration (qtdemux, sidx_parser.cumulative_pts);
3001   }
3002   gst_isoff_qt_sidx_parser_clear (&sidx_parser);
3003 }
3004
3005 /* caller verifies at least 8 bytes in buf */
3006 static void
3007 extract_initial_length_and_fourcc (const guint8 * data, guint size,
3008     guint64 * plength, guint32 * pfourcc)
3009 {
3010   guint64 length;
3011   guint32 fourcc;
3012
3013   length = QT_UINT32 (data);
3014   GST_DEBUG ("length 0x%08" G_GINT64_MODIFIER "x", length);
3015   fourcc = QT_FOURCC (data + 4);
3016   GST_DEBUG ("atom type %" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (fourcc));
3017
3018   if (length == 0) {
3019     length = G_MAXUINT64;
3020   } else if (length == 1 && size >= 16) {
3021     /* this means we have an extended size, which is the 64 bit value of
3022      * the next 8 bytes */
3023     length = QT_UINT64 (data + 8);
3024     GST_DEBUG ("length 0x%08" G_GINT64_MODIFIER "x", length);
3025   }
3026
3027   if (plength)
3028     *plength = length;
3029   if (pfourcc)
3030     *pfourcc = fourcc;
3031 }
3032
3033 static gboolean
3034 qtdemux_parse_mehd (GstQTDemux * qtdemux, GstByteReader * br)
3035 {
3036   guint32 version = 0;
3037   GstClockTime duration = 0;
3038
3039   if (!gst_byte_reader_get_uint32_be (br, &version))
3040     goto failed;
3041
3042   version >>= 24;
3043   if (version == 1) {
3044     if (!gst_byte_reader_get_uint64_be (br, &duration))
3045       goto failed;
3046   } else {
3047     guint32 dur = 0;
3048
3049     if (!gst_byte_reader_get_uint32_be (br, &dur))
3050       goto failed;
3051     duration = dur;
3052   }
3053
3054   GST_INFO_OBJECT (qtdemux, "mehd duration: %" G_GUINT64_FORMAT, duration);
3055   qtdemux->duration = duration;
3056
3057   return TRUE;
3058
3059 failed:
3060   {
3061     GST_DEBUG_OBJECT (qtdemux, "parsing mehd failed");
3062     return FALSE;
3063   }
3064 }
3065
3066 static gboolean
3067 qtdemux_parse_trex (GstQTDemux * qtdemux, QtDemuxStream * stream,
3068     guint32 * ds_duration, guint32 * ds_size, guint32 * ds_flags)
3069 {
3070   if (!stream->parsed_trex && qtdemux->moov_node) {
3071     GNode *mvex, *trex;
3072     GstByteReader trex_data;
3073
3074     mvex = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_mvex);
3075     if (mvex) {
3076       trex = qtdemux_tree_get_child_by_type_full (mvex, FOURCC_trex,
3077           &trex_data);
3078       while (trex) {
3079         guint32 id = 0, sdi = 0, dur = 0, size = 0, flags = 0;
3080
3081         /* skip version/flags */
3082         if (!gst_byte_reader_skip (&trex_data, 4))
3083           goto next;
3084         if (!gst_byte_reader_get_uint32_be (&trex_data, &id))
3085           goto next;
3086         if (id != stream->track_id)
3087           goto next;
3088         if (!gst_byte_reader_get_uint32_be (&trex_data, &sdi))
3089           goto next;
3090         if (!gst_byte_reader_get_uint32_be (&trex_data, &dur))
3091           goto next;
3092         if (!gst_byte_reader_get_uint32_be (&trex_data, &size))
3093           goto next;
3094         if (!gst_byte_reader_get_uint32_be (&trex_data, &flags))
3095           goto next;
3096
3097         GST_DEBUG_OBJECT (qtdemux, "fragment defaults for stream %d; "
3098             "duration %d,  size %d, flags 0x%x", stream->track_id,
3099             dur, size, flags);
3100
3101         stream->parsed_trex = TRUE;
3102         stream->def_sample_description_index = sdi;
3103         stream->def_sample_duration = dur;
3104         stream->def_sample_size = size;
3105         stream->def_sample_flags = flags;
3106
3107       next:
3108         /* iterate all siblings */
3109         trex = qtdemux_tree_get_sibling_by_type_full (trex, FOURCC_trex,
3110             &trex_data);
3111       }
3112     }
3113   }
3114
3115   *ds_duration = stream->def_sample_duration;
3116   *ds_size = stream->def_sample_size;
3117   *ds_flags = stream->def_sample_flags;
3118
3119   /* even then, above values are better than random ... */
3120   if (G_UNLIKELY (!stream->parsed_trex)) {
3121     GST_WARNING_OBJECT (qtdemux,
3122         "failed to find fragment defaults for stream %d", stream->track_id);
3123     return FALSE;
3124   }
3125
3126   return TRUE;
3127 }
3128
3129 /* This method should be called whenever a more accurate duration might
3130  * have been found. It will update all relevant variables if/where needed
3131  */
3132 static void
3133 check_update_duration (GstQTDemux * qtdemux, GstClockTime duration)
3134 {
3135   guint i;
3136   guint64 movdur;
3137   GstClockTime prevdur;
3138   GList *iter;
3139
3140   movdur = GSTTIME_TO_QTTIME (qtdemux, duration);
3141
3142   if (movdur > qtdemux->duration) {
3143     prevdur = QTTIME_TO_GSTTIME (qtdemux, qtdemux->duration);
3144     GST_DEBUG_OBJECT (qtdemux,
3145         "Updating total duration to %" GST_TIME_FORMAT " was %" GST_TIME_FORMAT,
3146         GST_TIME_ARGS (duration), GST_TIME_ARGS (prevdur));
3147     qtdemux->duration = movdur;
3148     GST_DEBUG_OBJECT (qtdemux,
3149         "qtdemux->segment.duration: %" GST_TIME_FORMAT " .stop: %"
3150         GST_TIME_FORMAT, GST_TIME_ARGS (qtdemux->segment.duration),
3151         GST_TIME_ARGS (qtdemux->segment.stop));
3152     if (qtdemux->segment.duration == prevdur) {
3153       /* If the current segment has duration/stop identical to previous duration
3154        * update them also (because they were set at that point in time with
3155        * the wrong duration */
3156       /* We convert the value *from* the timescale version to avoid rounding errors */
3157       GstClockTime fixeddur = QTTIME_TO_GSTTIME (qtdemux, movdur);
3158       GST_DEBUG_OBJECT (qtdemux, "Updated segment.duration and segment.stop");
3159       qtdemux->segment.duration = fixeddur;
3160       qtdemux->segment.stop = fixeddur;
3161     }
3162   }
3163   for (iter = qtdemux->active_streams, i = 0; iter;
3164       iter = g_list_next (iter), i++) {
3165     QtDemuxStream *stream = QTDEMUX_STREAM (iter->data);
3166
3167     movdur = GSTTIME_TO_QTSTREAMTIME (stream, duration);
3168     if (movdur > stream->duration) {
3169       GST_DEBUG_OBJECT (qtdemux,
3170           "Updating stream #%d duration to %" GST_TIME_FORMAT, i,
3171           GST_TIME_ARGS (duration));
3172       stream->duration = movdur;
3173       /* internal duration tracking state has been updated above, so */
3174       /* preserve an open-ended dummy segment rather than repeatedly updating
3175        * it and spamming downstream accordingly with segment events */
3176       if (stream->dummy_segment &&
3177           GST_CLOCK_TIME_IS_VALID (stream->segments[0].duration)) {
3178         /* Update all dummy values to new duration */
3179         stream->segments[0].stop_time = duration;
3180         stream->segments[0].duration = duration;
3181         stream->segments[0].media_stop = duration;
3182
3183         /* let downstream know we possibly have a new stop time */
3184         if (stream->segment_index != -1) {
3185           GstClockTime pos;
3186
3187           if (qtdemux->segment.rate >= 0) {
3188             pos = stream->segment.start;
3189           } else {
3190             pos = stream->segment.stop;
3191           }
3192
3193           gst_qtdemux_stream_update_segment (qtdemux, stream,
3194               stream->segment_index, pos, NULL, NULL);
3195         }
3196       }
3197     }
3198   }
3199 }
3200
3201 static gboolean
3202 qtdemux_parse_trun (GstQTDemux * qtdemux, GstByteReader * trun,
3203     QtDemuxStream * stream, guint32 d_sample_duration, guint32 d_sample_size,
3204     guint32 d_sample_flags, gint64 moof_offset, gint64 moof_length,
3205     gint64 * base_offset, gint64 * running_offset, gint64 decode_ts,
3206     gboolean has_tfdt)
3207 {
3208   GstClockTime gst_ts = GST_CLOCK_TIME_NONE;
3209   guint64 timestamp;
3210   gint32 data_offset = 0;
3211   guint32 flags = 0, first_flags = 0, samples_count = 0;
3212   gint i;
3213   guint8 *data;
3214   guint entry_size, dur_offset, size_offset, flags_offset = 0, ct_offset = 0;
3215   QtDemuxSample *sample;
3216   gboolean ismv = FALSE;
3217   gint64 initial_offset;
3218
3219   GST_LOG_OBJECT (qtdemux, "parsing trun track-id %d; "
3220       "default dur %d, size %d, flags 0x%x, base offset %" G_GINT64_FORMAT ", "
3221       "decode ts %" G_GINT64_FORMAT, stream->track_id, d_sample_duration,
3222       d_sample_size, d_sample_flags, *base_offset, decode_ts);
3223
3224   if (stream->pending_seek && moof_offset < stream->pending_seek->moof_offset) {
3225     GST_INFO_OBJECT (stream->pad, "skipping trun before seek target fragment");
3226     return TRUE;
3227   }
3228
3229   /* presence of stss or not can't really tell us much,
3230    * and flags and so on tend to be marginally reliable in these files */
3231   if (stream->subtype == FOURCC_soun) {
3232     GST_DEBUG_OBJECT (qtdemux,
3233         "sound track in fragmented file; marking all keyframes");
3234     stream->all_keyframe = TRUE;
3235   }
3236
3237   if (!gst_byte_reader_skip (trun, 1) ||
3238       !gst_byte_reader_get_uint24_be (trun, &flags))
3239     goto fail;
3240
3241   if (!gst_byte_reader_get_uint32_be (trun, &samples_count))
3242     goto fail;
3243
3244   if (flags & TR_DATA_OFFSET) {
3245     /* note this is really signed */
3246     if (!gst_byte_reader_get_int32_be (trun, &data_offset))
3247       goto fail;
3248     GST_LOG_OBJECT (qtdemux, "trun data offset %d", data_offset);
3249     /* default base offset = first byte of moof */
3250     if (*base_offset == -1) {
3251       GST_LOG_OBJECT (qtdemux, "base_offset at moof");
3252       *base_offset = moof_offset;
3253     }
3254     *running_offset = *base_offset + data_offset;
3255   } else {
3256     /* if no offset at all, that would mean data starts at moof start,
3257      * which is a bit wrong and is ismv crappy way, so compensate
3258      * assuming data is in mdat following moof */
3259     if (*base_offset == -1) {
3260       *base_offset = moof_offset + moof_length + 8;
3261       GST_LOG_OBJECT (qtdemux, "base_offset assumed in mdat after moof");
3262       ismv = TRUE;
3263     }
3264     if (*running_offset == -1)
3265       *running_offset = *base_offset;
3266   }
3267
3268   GST_LOG_OBJECT (qtdemux, "running offset now %" G_GINT64_FORMAT,
3269       *running_offset);
3270   GST_LOG_OBJECT (qtdemux, "trun offset %d, flags 0x%x, entries %d",
3271       data_offset, flags, samples_count);
3272
3273   if (flags & TR_FIRST_SAMPLE_FLAGS) {
3274     if (G_UNLIKELY (flags & TR_SAMPLE_FLAGS)) {
3275       GST_DEBUG_OBJECT (qtdemux,
3276           "invalid flags; SAMPLE and FIRST_SAMPLE present, discarding latter");
3277       flags ^= TR_FIRST_SAMPLE_FLAGS;
3278     } else {
3279       if (!gst_byte_reader_get_uint32_be (trun, &first_flags))
3280         goto fail;
3281       GST_LOG_OBJECT (qtdemux, "first flags: 0x%x", first_flags);
3282     }
3283   }
3284
3285   /* FIXME ? spec says other bits should also be checked to determine
3286    * entry size (and prefix size for that matter) */
3287   entry_size = 0;
3288   dur_offset = size_offset = 0;
3289   if (flags & TR_SAMPLE_DURATION) {
3290     GST_LOG_OBJECT (qtdemux, "entry duration present");
3291     dur_offset = entry_size;
3292     entry_size += 4;
3293   }
3294   if (flags & TR_SAMPLE_SIZE) {
3295     GST_LOG_OBJECT (qtdemux, "entry size present");
3296     size_offset = entry_size;
3297     entry_size += 4;
3298   }
3299   if (flags & TR_SAMPLE_FLAGS) {
3300     GST_LOG_OBJECT (qtdemux, "entry flags present");
3301     flags_offset = entry_size;
3302     entry_size += 4;
3303   }
3304   if (flags & TR_COMPOSITION_TIME_OFFSETS) {
3305     GST_LOG_OBJECT (qtdemux, "entry ct offset present");
3306     ct_offset = entry_size;
3307     entry_size += 4;
3308   }
3309
3310   if (!qt_atom_parser_has_chunks (trun, samples_count, entry_size))
3311     goto fail;
3312   data = (guint8 *) gst_byte_reader_peek_data_unchecked (trun);
3313
3314   if (stream->n_samples + samples_count >=
3315       QTDEMUX_MAX_SAMPLE_INDEX_SIZE / sizeof (QtDemuxSample))
3316     goto index_too_big;
3317
3318   GST_DEBUG_OBJECT (qtdemux, "allocating n_samples %u * %u (%.2f MB)",
3319       stream->n_samples + samples_count, (guint) sizeof (QtDemuxSample),
3320       (stream->n_samples + samples_count) *
3321       sizeof (QtDemuxSample) / (1024.0 * 1024.0));
3322
3323   /* create a new array of samples if it's the first sample parsed */
3324   if (stream->n_samples == 0) {
3325     g_assert (stream->samples == NULL);
3326     stream->samples = g_try_new0 (QtDemuxSample, samples_count);
3327     /* or try to reallocate it with space enough to insert the new samples */
3328   } else
3329     stream->samples = g_try_renew (QtDemuxSample, stream->samples,
3330         stream->n_samples + samples_count);
3331   if (stream->samples == NULL)
3332     goto out_of_memory;
3333
3334   if (qtdemux->fragment_start != -1) {
3335     timestamp = GSTTIME_TO_QTSTREAMTIME (stream, qtdemux->fragment_start);
3336     qtdemux->fragment_start = -1;
3337   } else {
3338     if (stream->n_samples == 0) {
3339       if (decode_ts > 0) {
3340         timestamp = decode_ts;
3341       } else if (stream->pending_seek != NULL) {
3342         /* if we don't have a timestamp from a tfdt box, we'll use the one
3343          * from the mfra seek table */
3344         GST_INFO_OBJECT (stream->pad, "pending seek ts = %" GST_TIME_FORMAT,
3345             GST_TIME_ARGS (stream->pending_seek->ts));
3346
3347         /* FIXME: this is not fully correct, the timestamp refers to the random
3348          * access sample refered to in the tfra entry, which may not necessarily
3349          * be the first sample in the tfrag/trun (but hopefully/usually is) */
3350         timestamp = GSTTIME_TO_QTSTREAMTIME (stream, stream->pending_seek->ts);
3351       } else {
3352         timestamp = 0;
3353       }
3354
3355       gst_ts = QTSTREAMTIME_TO_GSTTIME (stream, timestamp);
3356       GST_INFO_OBJECT (stream->pad, "first sample ts %" GST_TIME_FORMAT,
3357           GST_TIME_ARGS (gst_ts));
3358     } else {
3359       /* subsequent fragments extend stream */
3360       timestamp =
3361           stream->samples[stream->n_samples - 1].timestamp +
3362           stream->samples[stream->n_samples - 1].duration;
3363
3364       /* If this is a GST_FORMAT_BYTES stream and there's a significant
3365        * difference (1 sec.) between decode_ts and timestamp, prefer the
3366        * former */
3367       if (has_tfdt && !qtdemux->upstream_format_is_time
3368           && ABSDIFF (decode_ts, timestamp) >
3369           MAX (stream->duration_last_moof / 2,
3370               GSTTIME_TO_QTSTREAMTIME (stream, GST_SECOND))) {
3371         GST_INFO_OBJECT (qtdemux,
3372             "decode_ts (%" GST_TIME_FORMAT ") and timestamp (%" GST_TIME_FORMAT
3373             ") are significantly different (more than %" GST_TIME_FORMAT
3374             "), using decode_ts",
3375             GST_TIME_ARGS (QTSTREAMTIME_TO_GSTTIME (stream, decode_ts)),
3376             GST_TIME_ARGS (QTSTREAMTIME_TO_GSTTIME (stream, timestamp)),
3377             GST_TIME_ARGS (QTSTREAMTIME_TO_GSTTIME (stream,
3378                     MAX (stream->duration_last_moof / 2,
3379                         GSTTIME_TO_QTSTREAMTIME (stream, GST_SECOND)))));
3380         timestamp = decode_ts;
3381       }
3382
3383       gst_ts = QTSTREAMTIME_TO_GSTTIME (stream, timestamp);
3384       GST_INFO_OBJECT (qtdemux, "first sample ts %" GST_TIME_FORMAT
3385           " (extends previous samples)", GST_TIME_ARGS (gst_ts));
3386     }
3387   }
3388
3389   initial_offset = *running_offset;
3390
3391   sample = stream->samples + stream->n_samples;
3392   for (i = 0; i < samples_count; i++) {
3393     guint32 dur, size, sflags, ct;
3394
3395     /* first read sample data */
3396     if (flags & TR_SAMPLE_DURATION) {
3397       dur = QT_UINT32 (data + dur_offset);
3398     } else {
3399       dur = d_sample_duration;
3400     }
3401     if (flags & TR_SAMPLE_SIZE) {
3402       size = QT_UINT32 (data + size_offset);
3403     } else {
3404       size = d_sample_size;
3405     }
3406     if (flags & TR_FIRST_SAMPLE_FLAGS) {
3407       if (i == 0) {
3408         sflags = first_flags;
3409       } else {
3410         sflags = d_sample_flags;
3411       }
3412     } else if (flags & TR_SAMPLE_FLAGS) {
3413       sflags = QT_UINT32 (data + flags_offset);
3414     } else {
3415       sflags = d_sample_flags;
3416     }
3417     if (flags & TR_COMPOSITION_TIME_OFFSETS) {
3418       ct = QT_UINT32 (data + ct_offset);
3419     } else {
3420       ct = 0;
3421     }
3422     data += entry_size;
3423
3424     /* fill the sample information */
3425     sample->offset = *running_offset;
3426     sample->pts_offset = ct;
3427     sample->size = size;
3428     sample->timestamp = timestamp;
3429     sample->duration = dur;
3430     /* sample-is-difference-sample */
3431     /* ismv seems to use 0x40 for keyframe, 0xc0 for non-keyframe,
3432      * now idea how it relates to bitfield other than massive LE/BE confusion */
3433     sample->keyframe = ismv ? ((sflags & 0xff) == 0x40) : !(sflags & 0x10000);
3434     *running_offset += size;
3435     timestamp += dur;
3436     stream->duration_moof += dur;
3437     sample++;
3438   }
3439
3440   /* Update total duration if needed */
3441   check_update_duration (qtdemux, QTSTREAMTIME_TO_GSTTIME (stream, timestamp));
3442
3443   /* Pre-emptively figure out size of mdat based on trun information.
3444    * If the [mdat] atom is effectivelly read, it will be replaced by the actual
3445    * size, else we will still be able to use this when dealing with gap'ed
3446    * input */
3447   qtdemux->mdatleft = *running_offset - initial_offset;
3448   qtdemux->mdatoffset = initial_offset;
3449   qtdemux->mdatsize = qtdemux->mdatleft;
3450
3451   stream->n_samples += samples_count;
3452   stream->n_samples_moof += samples_count;
3453
3454   if (stream->pending_seek != NULL)
3455     stream->pending_seek = NULL;
3456
3457   return TRUE;
3458
3459 fail:
3460   {
3461     GST_WARNING_OBJECT (qtdemux, "failed to parse trun");
3462     return FALSE;
3463   }
3464 out_of_memory:
3465   {
3466     GST_WARNING_OBJECT (qtdemux, "failed to allocate %d samples",
3467         stream->n_samples);
3468     return FALSE;
3469   }
3470 index_too_big:
3471   {
3472     GST_WARNING_OBJECT (qtdemux, "not allocating index of %d samples, would "
3473         "be larger than %uMB (broken file?)", stream->n_samples,
3474         QTDEMUX_MAX_SAMPLE_INDEX_SIZE >> 20);
3475     return FALSE;
3476   }
3477 }
3478
3479 /* find stream with @id */
3480 static inline QtDemuxStream *
3481 qtdemux_find_stream (GstQTDemux * qtdemux, guint32 id)
3482 {
3483   QtDemuxStream *stream;
3484   GList *iter;
3485
3486   /* check */
3487   if (G_UNLIKELY (!id)) {
3488     GST_DEBUG_OBJECT (qtdemux, "invalid track id 0");
3489     return NULL;
3490   }
3491
3492   for (iter = qtdemux->active_streams; iter; iter = g_list_next (iter)) {
3493     stream = QTDEMUX_STREAM (iter->data);
3494     if (stream->track_id == id)
3495       return stream;
3496   }
3497   if (qtdemux->mss_mode) {
3498     /* mss should have only 1 stream anyway */
3499     return QTDEMUX_FIRST_STREAM (qtdemux);
3500   }
3501
3502   return NULL;
3503 }
3504
3505 static gboolean
3506 qtdemux_parse_mfhd (GstQTDemux * qtdemux, GstByteReader * mfhd,
3507     guint32 * fragment_number)
3508 {
3509   if (!gst_byte_reader_skip (mfhd, 4))
3510     goto fail;
3511   if (!gst_byte_reader_get_uint32_be (mfhd, fragment_number))
3512     goto fail;
3513   return TRUE;
3514 fail:
3515   {
3516     GST_WARNING_OBJECT (qtdemux, "Failed to parse mfhd atom");
3517     return FALSE;
3518   }
3519 }
3520
3521 static gboolean
3522 qtdemux_parse_tfhd (GstQTDemux * qtdemux, GstByteReader * tfhd,
3523     QtDemuxStream ** stream, guint32 * default_sample_duration,
3524     guint32 * default_sample_size, guint32 * default_sample_flags,
3525     gint64 * base_offset)
3526 {
3527   guint32 flags = 0;
3528   guint32 track_id = 0;
3529
3530   if (!gst_byte_reader_skip (tfhd, 1) ||
3531       !gst_byte_reader_get_uint24_be (tfhd, &flags))
3532     goto invalid_track;
3533
3534   if (!gst_byte_reader_get_uint32_be (tfhd, &track_id))
3535     goto invalid_track;
3536
3537   *stream = qtdemux_find_stream (qtdemux, track_id);
3538   if (G_UNLIKELY (!*stream))
3539     goto unknown_stream;
3540
3541   if (flags & TF_DEFAULT_BASE_IS_MOOF)
3542     *base_offset = qtdemux->moof_offset;
3543
3544   if (flags & TF_BASE_DATA_OFFSET)
3545     if (!gst_byte_reader_get_uint64_be (tfhd, (guint64 *) base_offset))
3546       goto invalid_track;
3547
3548   /* obtain stream defaults */
3549   qtdemux_parse_trex (qtdemux, *stream,
3550       default_sample_duration, default_sample_size, default_sample_flags);
3551
3552   (*stream)->stsd_sample_description_id =
3553       (*stream)->def_sample_description_index - 1;
3554
3555   if (flags & TF_SAMPLE_DESCRIPTION_INDEX) {
3556     guint32 sample_description_index;
3557     if (!gst_byte_reader_get_uint32_be (tfhd, &sample_description_index))
3558       goto invalid_track;
3559     (*stream)->stsd_sample_description_id = sample_description_index - 1;
3560   }
3561
3562   if (qtdemux->mss_mode) {
3563     /* mss has no stsd entry */
3564     (*stream)->stsd_sample_description_id = 0;
3565   }
3566
3567   if (flags & TF_DEFAULT_SAMPLE_DURATION)
3568     if (!gst_byte_reader_get_uint32_be (tfhd, default_sample_duration))
3569       goto invalid_track;
3570
3571   if (flags & TF_DEFAULT_SAMPLE_SIZE)
3572     if (!gst_byte_reader_get_uint32_be (tfhd, default_sample_size))
3573       goto invalid_track;
3574
3575   if (flags & TF_DEFAULT_SAMPLE_FLAGS)
3576     if (!gst_byte_reader_get_uint32_be (tfhd, default_sample_flags))
3577       goto invalid_track;
3578
3579   return TRUE;
3580
3581 invalid_track:
3582   {
3583     GST_WARNING_OBJECT (qtdemux, "invalid track fragment header");
3584     return FALSE;
3585   }
3586 unknown_stream:
3587   {
3588     GST_DEBUG_OBJECT (qtdemux, "unknown stream in tfhd");
3589     return TRUE;
3590   }
3591 }
3592
3593 static gboolean
3594 qtdemux_parse_tfdt (GstQTDemux * qtdemux, GstByteReader * br,
3595     guint64 * decode_time)
3596 {
3597   guint32 version = 0;
3598
3599   if (!gst_byte_reader_get_uint32_be (br, &version))
3600     return FALSE;
3601
3602   version >>= 24;
3603   if (version == 1) {
3604     if (!gst_byte_reader_get_uint64_be (br, decode_time))
3605       goto failed;
3606   } else {
3607     guint32 dec_time = 0;
3608     if (!gst_byte_reader_get_uint32_be (br, &dec_time))
3609       goto failed;
3610     *decode_time = dec_time;
3611   }
3612
3613   GST_INFO_OBJECT (qtdemux, "Track fragment decode time: %" G_GUINT64_FORMAT,
3614       *decode_time);
3615
3616   return TRUE;
3617
3618 failed:
3619   {
3620     GST_DEBUG_OBJECT (qtdemux, "parsing tfdt failed");
3621     return FALSE;
3622   }
3623 }
3624
3625 /* Returns a pointer to a GstStructure containing the properties of
3626  * the stream sample identified by @sample_index. The caller must unref
3627  * the returned object after use. Returns NULL if unsuccessful. */
3628 static GstStructure *
3629 qtdemux_get_cenc_sample_properties (GstQTDemux * qtdemux,
3630     QtDemuxStream * stream, guint sample_index)
3631 {
3632   QtDemuxCencSampleSetInfo *info = NULL;
3633
3634   g_return_val_if_fail (stream != NULL, NULL);
3635   g_return_val_if_fail (stream->protected, NULL);
3636   g_return_val_if_fail (stream->protection_scheme_info != NULL, NULL);
3637
3638   info = (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
3639
3640   /* Currently, cenc properties for groups of samples are not supported, so
3641    * simply return a copy of the default sample properties */
3642   return gst_structure_copy (info->default_properties);
3643 }
3644
3645 /* Parses the sizes of sample auxiliary information contained within a stream,
3646  * as given in a saiz box. Returns array of sample_count guint8 size values,
3647  * or NULL on failure */
3648 static guint8 *
3649 qtdemux_parse_saiz (GstQTDemux * qtdemux, QtDemuxStream * stream,
3650     GstByteReader * br, guint32 * sample_count)
3651 {
3652   guint32 flags = 0;
3653   guint8 *info_sizes;
3654   guint8 default_info_size;
3655
3656   g_return_val_if_fail (qtdemux != NULL, NULL);
3657   g_return_val_if_fail (stream != NULL, NULL);
3658   g_return_val_if_fail (br != NULL, NULL);
3659   g_return_val_if_fail (sample_count != NULL, NULL);
3660
3661   if (!gst_byte_reader_get_uint32_be (br, &flags))
3662     return NULL;
3663
3664   if (flags & 0x1) {
3665     /* aux_info_type and aux_info_type_parameter are ignored */
3666     if (!gst_byte_reader_skip (br, 8))
3667       return NULL;
3668   }
3669
3670   if (!gst_byte_reader_get_uint8 (br, &default_info_size))
3671     return NULL;
3672   GST_DEBUG_OBJECT (qtdemux, "default_info_size: %u", default_info_size);
3673
3674   if (!gst_byte_reader_get_uint32_be (br, sample_count))
3675     return NULL;
3676   GST_DEBUG_OBJECT (qtdemux, "sample_count: %u", *sample_count);
3677
3678
3679   if (default_info_size == 0) {
3680     if (!gst_byte_reader_dup_data (br, *sample_count, &info_sizes)) {
3681       return NULL;
3682     }
3683   } else {
3684     info_sizes = g_new (guint8, *sample_count);
3685     memset (info_sizes, default_info_size, *sample_count);
3686   }
3687
3688   return info_sizes;
3689 }
3690
3691 /* Parses the offset of sample auxiliary information contained within a stream,
3692  * as given in a saio box. Returns TRUE if successful; FALSE otherwise. */
3693 static gboolean
3694 qtdemux_parse_saio (GstQTDemux * qtdemux, QtDemuxStream * stream,
3695     GstByteReader * br, guint32 * info_type, guint32 * info_type_parameter,
3696     guint64 * offset)
3697 {
3698   guint8 version = 0;
3699   guint32 flags = 0;
3700   guint32 aux_info_type = 0;
3701   guint32 aux_info_type_parameter = 0;
3702   guint32 entry_count;
3703   guint32 off_32;
3704   guint64 off_64;
3705   const guint8 *aux_info_type_data = NULL;
3706
3707   g_return_val_if_fail (qtdemux != NULL, FALSE);
3708   g_return_val_if_fail (stream != NULL, FALSE);
3709   g_return_val_if_fail (br != NULL, FALSE);
3710   g_return_val_if_fail (offset != NULL, FALSE);
3711
3712   if (!gst_byte_reader_get_uint8 (br, &version))
3713     return FALSE;
3714
3715   if (!gst_byte_reader_get_uint24_be (br, &flags))
3716     return FALSE;
3717
3718   if (flags & 0x1) {
3719
3720     if (!gst_byte_reader_get_data (br, 4, &aux_info_type_data))
3721       return FALSE;
3722     aux_info_type = QT_FOURCC (aux_info_type_data);
3723
3724     if (!gst_byte_reader_get_uint32_be (br, &aux_info_type_parameter))
3725       return FALSE;
3726   } else if (stream->protected) {
3727     aux_info_type = stream->protection_scheme_type;
3728   } else {
3729     aux_info_type = CUR_STREAM (stream)->fourcc;
3730   }
3731
3732   if (info_type)
3733     *info_type = aux_info_type;
3734   if (info_type_parameter)
3735     *info_type_parameter = aux_info_type_parameter;
3736
3737   GST_DEBUG_OBJECT (qtdemux, "aux_info_type: '%" GST_FOURCC_FORMAT "', "
3738       "aux_info_type_parameter:  %#06x",
3739       GST_FOURCC_ARGS (aux_info_type), aux_info_type_parameter);
3740
3741   if (!gst_byte_reader_get_uint32_be (br, &entry_count))
3742     return FALSE;
3743
3744   if (entry_count != 1) {
3745     GST_ERROR_OBJECT (qtdemux, "multiple offsets are not supported");
3746     return FALSE;
3747   }
3748
3749   if (version == 0) {
3750     if (!gst_byte_reader_get_uint32_be (br, &off_32))
3751       return FALSE;
3752     *offset = (guint64) off_32;
3753   } else {
3754     if (!gst_byte_reader_get_uint64_be (br, &off_64))
3755       return FALSE;
3756     *offset = off_64;
3757   }
3758
3759   GST_DEBUG_OBJECT (qtdemux, "offset: %" G_GUINT64_FORMAT, *offset);
3760   return TRUE;
3761 }
3762
3763 static void
3764 qtdemux_gst_structure_free (GstStructure * gststructure)
3765 {
3766   if (gststructure) {
3767     gst_structure_free (gststructure);
3768   }
3769 }
3770
3771 /* Parses auxiliary information relating to samples protected using Common
3772  * Encryption (cenc); the format of this information is defined in
3773  * ISO/IEC 23001-7. Returns TRUE if successful; FALSE otherwise. */
3774 static gboolean
3775 qtdemux_parse_cenc_aux_info (GstQTDemux * qtdemux, QtDemuxStream * stream,
3776     GstByteReader * br, guint8 * info_sizes, guint32 sample_count)
3777 {
3778   QtDemuxCencSampleSetInfo *ss_info = NULL;
3779   guint8 size;
3780   gint i;
3781   GPtrArray *old_crypto_info = NULL;
3782   guint old_entries = 0;
3783
3784   g_return_val_if_fail (qtdemux != NULL, FALSE);
3785   g_return_val_if_fail (stream != NULL, FALSE);
3786   g_return_val_if_fail (br != NULL, FALSE);
3787   g_return_val_if_fail (stream->protected, FALSE);
3788   g_return_val_if_fail (stream->protection_scheme_info != NULL, FALSE);
3789
3790   ss_info = (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
3791
3792   if (ss_info->crypto_info) {
3793     old_crypto_info = ss_info->crypto_info;
3794     /* Count number of non-null entries remaining at the tail end */
3795     for (i = old_crypto_info->len - 1; i >= 0; i--) {
3796       if (g_ptr_array_index (old_crypto_info, i) == NULL)
3797         break;
3798       old_entries++;
3799     }
3800   }
3801
3802   ss_info->crypto_info =
3803       g_ptr_array_new_full (sample_count + old_entries,
3804       (GDestroyNotify) qtdemux_gst_structure_free);
3805
3806   /* We preserve old entries because we parse the next moof in advance
3807    * of consuming all samples from the previous moof, and otherwise
3808    * we'd discard the corresponding crypto info for the samples
3809    * from the previous fragment. */
3810   if (old_entries) {
3811     GST_DEBUG_OBJECT (qtdemux, "Preserving %d old crypto info entries",
3812         old_entries);
3813     for (i = old_crypto_info->len - old_entries; i < old_crypto_info->len; i++) {
3814       g_ptr_array_add (ss_info->crypto_info, g_ptr_array_index (old_crypto_info,
3815               i));
3816       g_ptr_array_index (old_crypto_info, i) = NULL;
3817     }
3818   }
3819
3820   if (old_crypto_info) {
3821     /* Everything now belongs to the new array */
3822     g_ptr_array_free (old_crypto_info, TRUE);
3823   }
3824
3825   for (i = 0; i < sample_count; ++i) {
3826     GstStructure *properties;
3827     guint16 n_subsamples = 0;
3828     guint8 *data;
3829     guint iv_size;
3830     GstBuffer *buf;
3831
3832     properties = qtdemux_get_cenc_sample_properties (qtdemux, stream, i);
3833     if (properties == NULL) {
3834       GST_ERROR_OBJECT (qtdemux, "failed to get properties for sample %u", i);
3835       return FALSE;
3836     }
3837     if (!gst_structure_get_uint (properties, "iv_size", &iv_size)) {
3838       GST_ERROR_OBJECT (qtdemux, "failed to get iv_size for sample %u", i);
3839       gst_structure_free (properties);
3840       return FALSE;
3841     }
3842     if (!gst_byte_reader_dup_data (br, iv_size, &data)) {
3843       GST_ERROR_OBJECT (qtdemux, "failed to get IV for sample %u", i);
3844       gst_structure_free (properties);
3845       return FALSE;
3846     }
3847     buf = gst_buffer_new_wrapped (data, iv_size);
3848     gst_structure_set (properties, "iv", GST_TYPE_BUFFER, buf, NULL);
3849     gst_buffer_unref (buf);
3850     size = info_sizes[i];
3851     if (size > iv_size) {
3852       if (!gst_byte_reader_get_uint16_be (br, &n_subsamples)
3853           || !(n_subsamples > 0)) {
3854         gst_structure_free (properties);
3855         GST_ERROR_OBJECT (qtdemux,
3856             "failed to get subsample count for sample %u", i);
3857         return FALSE;
3858       }
3859       GST_LOG_OBJECT (qtdemux, "subsample count: %u", n_subsamples);
3860       if (!gst_byte_reader_dup_data (br, n_subsamples * 6, &data)) {
3861         GST_ERROR_OBJECT (qtdemux, "failed to get subsample data for sample %u",
3862             i);
3863         gst_structure_free (properties);
3864         return FALSE;
3865       }
3866       buf = gst_buffer_new_wrapped (data, n_subsamples * 6);
3867       if (!buf) {
3868         gst_structure_free (properties);
3869         return FALSE;
3870       }
3871       gst_structure_set (properties,
3872           "subsample_count", G_TYPE_UINT, n_subsamples,
3873           "subsamples", GST_TYPE_BUFFER, buf, NULL);
3874       gst_buffer_unref (buf);
3875     } else {
3876       gst_structure_set (properties, "subsample_count", G_TYPE_UINT, 0, NULL);
3877     }
3878     g_ptr_array_add (ss_info->crypto_info, properties);
3879   }
3880   return TRUE;
3881 }
3882
3883 /* Converts a UUID in raw byte form to a string representation, as defined in
3884  * RFC 4122. The caller takes ownership of the returned string and is
3885  * responsible for freeing it after use. */
3886 static gchar *
3887 qtdemux_uuid_bytes_to_string (gconstpointer uuid_bytes)
3888 {
3889   const guint8 *uuid = (const guint8 *) uuid_bytes;
3890
3891   return g_strdup_printf ("%02x%02x%02x%02x-%02x%02x-%02x%02x-"
3892       "%02x%02x-%02x%02x%02x%02x%02x%02x",
3893       uuid[0], uuid[1], uuid[2], uuid[3],
3894       uuid[4], uuid[5], uuid[6], uuid[7],
3895       uuid[8], uuid[9], uuid[10], uuid[11],
3896       uuid[12], uuid[13], uuid[14], uuid[15]);
3897 }
3898
3899 /* Parses a Protection System Specific Header box (pssh), as defined in the
3900  * Common Encryption (cenc) standard (ISO/IEC 23001-7), which contains
3901  * information needed by a specific content protection system in order to
3902  * decrypt cenc-protected tracks. Returns TRUE if successful; FALSE
3903  * otherwise. */
3904 static gboolean
3905 qtdemux_parse_pssh (GstQTDemux * qtdemux, GNode * node)
3906 {
3907   gchar *sysid_string;
3908   guint32 pssh_size = QT_UINT32 (node->data);
3909   GstBuffer *pssh = NULL;
3910   GstEvent *event = NULL;
3911   guint32 parent_box_type;
3912   GList *iter;
3913
3914   if (G_UNLIKELY (pssh_size < 32U)) {
3915     GST_ERROR_OBJECT (qtdemux, "invalid box size");
3916     return FALSE;
3917   }
3918
3919   sysid_string =
3920       qtdemux_uuid_bytes_to_string ((const guint8 *) node->data + 12);
3921
3922   gst_qtdemux_append_protection_system_id (qtdemux, sysid_string);
3923
3924   pssh = gst_buffer_new_wrapped (g_memdup (node->data, pssh_size), pssh_size);
3925   GST_LOG_OBJECT (qtdemux, "cenc pssh size: %" G_GSIZE_FORMAT,
3926       gst_buffer_get_size (pssh));
3927
3928   parent_box_type = QT_FOURCC ((const guint8 *) node->parent->data + 4);
3929
3930   /* Push an event containing the pssh box onto the queues of all streams. */
3931   event = gst_event_new_protection (sysid_string, pssh,
3932       (parent_box_type == FOURCC_moov) ? "isobmff/moov" : "isobmff/moof");
3933   for (iter = qtdemux->active_streams; iter; iter = g_list_next (iter)) {
3934     QtDemuxStream *stream = QTDEMUX_STREAM (iter->data);
3935     GST_TRACE_OBJECT (qtdemux,
3936         "adding protection event for stream %s and system %s",
3937         stream->stream_id, sysid_string);
3938     g_queue_push_tail (&stream->protection_scheme_event_queue,
3939         gst_event_ref (event));
3940   }
3941   g_free (sysid_string);
3942   gst_event_unref (event);
3943   gst_buffer_unref (pssh);
3944   return TRUE;
3945 }
3946
3947 static gboolean
3948 qtdemux_parse_moof (GstQTDemux * qtdemux, const guint8 * buffer, guint length,
3949     guint64 moof_offset, QtDemuxStream * stream)
3950 {
3951   GNode *moof_node, *traf_node, *tfhd_node, *trun_node, *tfdt_node, *mfhd_node;
3952   GNode *uuid_node;
3953   GstByteReader mfhd_data, trun_data, tfhd_data, tfdt_data;
3954   GNode *saiz_node, *saio_node, *pssh_node;
3955   GstByteReader saiz_data, saio_data;
3956   guint32 ds_size = 0, ds_duration = 0, ds_flags = 0;
3957   gint64 base_offset, running_offset;
3958   guint32 frag_num;
3959   GstClockTime min_dts = GST_CLOCK_TIME_NONE;
3960
3961   /* NOTE @stream ignored */
3962
3963   moof_node = g_node_new ((guint8 *) buffer);
3964   qtdemux_parse_node (qtdemux, moof_node, buffer, length);
3965   qtdemux_node_dump (qtdemux, moof_node);
3966
3967   /* Get fragment number from mfhd and check it's valid */
3968   mfhd_node =
3969       qtdemux_tree_get_child_by_type_full (moof_node, FOURCC_mfhd, &mfhd_data);
3970   if (mfhd_node == NULL)
3971     goto missing_mfhd;
3972   if (!qtdemux_parse_mfhd (qtdemux, &mfhd_data, &frag_num))
3973     goto fail;
3974   GST_DEBUG_OBJECT (qtdemux, "Fragment #%d", frag_num);
3975
3976   /* unknown base_offset to start with */
3977   base_offset = running_offset = -1;
3978   traf_node = qtdemux_tree_get_child_by_type (moof_node, FOURCC_traf);
3979   while (traf_node) {
3980     guint64 decode_time = 0;
3981
3982     /* Fragment Header node */
3983     tfhd_node =
3984         qtdemux_tree_get_child_by_type_full (traf_node, FOURCC_tfhd,
3985         &tfhd_data);
3986     if (!tfhd_node)
3987       goto missing_tfhd;
3988     if (!qtdemux_parse_tfhd (qtdemux, &tfhd_data, &stream, &ds_duration,
3989             &ds_size, &ds_flags, &base_offset))
3990       goto missing_tfhd;
3991
3992     /* The following code assumes at most a single set of sample auxiliary
3993      * data in the fragment (consisting of a saiz box and a corresponding saio
3994      * box); in theory, however, there could be multiple sets of sample
3995      * auxiliary data in a fragment. */
3996     saiz_node =
3997         qtdemux_tree_get_child_by_type_full (traf_node, FOURCC_saiz,
3998         &saiz_data);
3999     if (saiz_node) {
4000       guint32 info_type = 0;
4001       guint64 offset = 0;
4002       guint32 info_type_parameter = 0;
4003
4004       g_free (qtdemux->cenc_aux_info_sizes);
4005
4006       qtdemux->cenc_aux_info_sizes =
4007           qtdemux_parse_saiz (qtdemux, stream, &saiz_data,
4008           &qtdemux->cenc_aux_sample_count);
4009       if (qtdemux->cenc_aux_info_sizes == NULL) {
4010         GST_ERROR_OBJECT (qtdemux, "failed to parse saiz box");
4011         goto fail;
4012       }
4013       saio_node =
4014           qtdemux_tree_get_child_by_type_full (traf_node, FOURCC_saio,
4015           &saio_data);
4016       if (!saio_node) {
4017         GST_ERROR_OBJECT (qtdemux, "saiz box without a corresponding saio box");
4018         g_free (qtdemux->cenc_aux_info_sizes);
4019         qtdemux->cenc_aux_info_sizes = NULL;
4020         goto fail;
4021       }
4022
4023       if (G_UNLIKELY (!qtdemux_parse_saio (qtdemux, stream, &saio_data,
4024                   &info_type, &info_type_parameter, &offset))) {
4025         GST_ERROR_OBJECT (qtdemux, "failed to parse saio box");
4026         g_free (qtdemux->cenc_aux_info_sizes);
4027         qtdemux->cenc_aux_info_sizes = NULL;
4028         goto fail;
4029       }
4030       if (base_offset > -1 && base_offset > qtdemux->moof_offset)
4031         offset += (guint64) (base_offset - qtdemux->moof_offset);
4032       if (info_type == FOURCC_cenc && info_type_parameter == 0U) {
4033         GstByteReader br;
4034         if (offset > length) {
4035           GST_DEBUG_OBJECT (qtdemux, "cenc auxiliary info stored out of moof");
4036           qtdemux->cenc_aux_info_offset = offset;
4037         } else {
4038           gst_byte_reader_init (&br, buffer + offset, length - offset);
4039           if (!qtdemux_parse_cenc_aux_info (qtdemux, stream, &br,
4040                   qtdemux->cenc_aux_info_sizes,
4041                   qtdemux->cenc_aux_sample_count)) {
4042             GST_ERROR_OBJECT (qtdemux, "failed to parse cenc auxiliary info");
4043             g_free (qtdemux->cenc_aux_info_sizes);
4044             qtdemux->cenc_aux_info_sizes = NULL;
4045             goto fail;
4046           }
4047         }
4048       }
4049     }
4050
4051     tfdt_node =
4052         qtdemux_tree_get_child_by_type_full (traf_node, FOURCC_tfdt,
4053         &tfdt_data);
4054     if (tfdt_node) {
4055       /* We'll use decode_time to interpolate timestamps
4056        * in case the input timestamps are missing */
4057       qtdemux_parse_tfdt (qtdemux, &tfdt_data, &decode_time);
4058
4059       GST_DEBUG_OBJECT (qtdemux, "decode time %" G_GINT64_FORMAT
4060           " (%" GST_TIME_FORMAT ")", decode_time,
4061           GST_TIME_ARGS (stream ? QTSTREAMTIME_TO_GSTTIME (stream,
4062                   decode_time) : GST_CLOCK_TIME_NONE));
4063
4064       /* Discard the fragment buffer timestamp info to avoid using it.
4065        * Rely on tfdt instead as it is more accurate than the timestamp
4066        * that is fetched from a manifest/playlist and is usually
4067        * less accurate. */
4068       qtdemux->fragment_start = -1;
4069     }
4070
4071     if (G_UNLIKELY (!stream)) {
4072       /* we lost track of offset, we'll need to regain it,
4073        * but can delay complaining until later or avoid doing so altogether */
4074       base_offset = -2;
4075       goto next;
4076     }
4077     if (G_UNLIKELY (base_offset < -1))
4078       goto lost_offset;
4079
4080     min_dts = MIN (min_dts, QTSTREAMTIME_TO_GSTTIME (stream, decode_time));
4081
4082     if (qtdemux->upstream_format_is_time)
4083       gst_qtdemux_stream_flush_samples_data (stream);
4084
4085     /* initialise moof sample data */
4086     stream->n_samples_moof = 0;
4087     stream->duration_last_moof = stream->duration_moof;
4088     stream->duration_moof = 0;
4089
4090     /* Track Run node */
4091     trun_node =
4092         qtdemux_tree_get_child_by_type_full (traf_node, FOURCC_trun,
4093         &trun_data);
4094     while (trun_node) {
4095       qtdemux_parse_trun (qtdemux, &trun_data, stream,
4096           ds_duration, ds_size, ds_flags, moof_offset, length, &base_offset,
4097           &running_offset, decode_time, (tfdt_node != NULL));
4098       /* iterate all siblings */
4099       trun_node = qtdemux_tree_get_sibling_by_type_full (trun_node, FOURCC_trun,
4100           &trun_data);
4101     }
4102
4103     uuid_node = qtdemux_tree_get_child_by_type (traf_node, FOURCC_uuid);
4104     if (uuid_node) {
4105       guint8 *uuid_buffer = (guint8 *) uuid_node->data;
4106       guint32 box_length = QT_UINT32 (uuid_buffer);
4107
4108       qtdemux_parse_uuid (qtdemux, uuid_buffer, box_length);
4109     }
4110
4111     /* if no new base_offset provided for next traf,
4112      * base is end of current traf */
4113     base_offset = running_offset;
4114     running_offset = -1;
4115
4116     if (stream->n_samples_moof && stream->duration_moof)
4117       stream->new_caps = TRUE;
4118
4119   next:
4120     /* iterate all siblings */
4121     traf_node = qtdemux_tree_get_sibling_by_type (traf_node, FOURCC_traf);
4122   }
4123
4124   /* parse any protection system info */
4125   pssh_node = qtdemux_tree_get_child_by_type (moof_node, FOURCC_pssh);
4126   while (pssh_node) {
4127     GST_LOG_OBJECT (qtdemux, "Parsing pssh box.");
4128     qtdemux_parse_pssh (qtdemux, pssh_node);
4129     pssh_node = qtdemux_tree_get_sibling_by_type (pssh_node, FOURCC_pssh);
4130   }
4131
4132   if (!qtdemux->upstream_format_is_time && !qtdemux->first_moof_already_parsed
4133       && !qtdemux->received_seek && GST_CLOCK_TIME_IS_VALID (min_dts)
4134       && min_dts != 0) {
4135     /* Unless the user has explictly requested another seek, perform an
4136      * internal seek to the time specified in the tfdt.
4137      *
4138      * This way if the user opens a file where the first tfdt is 1 hour
4139      * into the presentation, they will not have to wait 1 hour for run
4140      * time to catch up and actual playback to start. */
4141     GList *iter;
4142
4143     GST_DEBUG_OBJECT (qtdemux, "First fragment has a non-zero tfdt, "
4144         "performing an internal seek to %" GST_TIME_FORMAT,
4145         GST_TIME_ARGS (min_dts));
4146
4147     qtdemux->segment.start = min_dts;
4148     qtdemux->segment.time = qtdemux->segment.position = min_dts;
4149
4150     for (iter = qtdemux->active_streams; iter; iter = g_list_next (iter)) {
4151       QtDemuxStream *stream = QTDEMUX_STREAM (iter->data);
4152       stream->time_position = min_dts;
4153     }
4154
4155     /* Before this code was run a segment was already sent when the moov was
4156      * parsed... which is OK -- some apps (mostly tests) expect a segment to
4157      * be emitted after a moov, and we can emit a second segment anyway for
4158      * special cases like this. */
4159     qtdemux->need_segment = TRUE;
4160   }
4161
4162   qtdemux->first_moof_already_parsed = TRUE;
4163
4164   g_node_destroy (moof_node);
4165   return TRUE;
4166
4167 missing_tfhd:
4168   {
4169     GST_DEBUG_OBJECT (qtdemux, "missing tfhd box");
4170     goto fail;
4171   }
4172 missing_mfhd:
4173   {
4174     GST_DEBUG_OBJECT (qtdemux, "Missing mfhd box");
4175     goto fail;
4176   }
4177 lost_offset:
4178   {
4179     GST_DEBUG_OBJECT (qtdemux, "lost offset");
4180     goto fail;
4181   }
4182 fail:
4183   {
4184     g_node_destroy (moof_node);
4185     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
4186         (_("This file is corrupt and cannot be played.")), (NULL));
4187     return FALSE;
4188   }
4189 }
4190
4191 #if 0
4192 /* might be used if some day we actually use mfra & co
4193  * for random access to fragments,
4194  * but that will require quite some modifications and much less relying
4195  * on a sample array */
4196 #endif
4197
4198 static gboolean
4199 qtdemux_parse_tfra (GstQTDemux * qtdemux, GNode * tfra_node)
4200 {
4201   QtDemuxStream *stream;
4202   guint32 ver_flags, track_id, len, num_entries, i;
4203   guint value_size, traf_size, trun_size, sample_size;
4204   guint64 time = 0, moof_offset = 0;
4205 #if 0
4206   GstBuffer *buf = NULL;
4207   GstFlowReturn ret;
4208 #endif
4209   GstByteReader tfra;
4210
4211   gst_byte_reader_init (&tfra, tfra_node->data, QT_UINT32 (tfra_node->data));
4212
4213   if (!gst_byte_reader_skip (&tfra, 8))
4214     return FALSE;
4215
4216   if (!gst_byte_reader_get_uint32_be (&tfra, &ver_flags))
4217     return FALSE;
4218
4219   if (!gst_byte_reader_get_uint32_be (&tfra, &track_id)
4220       || !gst_byte_reader_get_uint32_be (&tfra, &len)
4221       || !gst_byte_reader_get_uint32_be (&tfra, &num_entries))
4222     return FALSE;
4223
4224   GST_DEBUG_OBJECT (qtdemux, "parsing tfra box for track id %u", track_id);
4225
4226   stream = qtdemux_find_stream (qtdemux, track_id);
4227   if (stream == NULL)
4228     goto unknown_trackid;
4229
4230   value_size = ((ver_flags >> 24) == 1) ? sizeof (guint64) : sizeof (guint32);
4231   sample_size = (len & 3) + 1;
4232   trun_size = ((len & 12) >> 2) + 1;
4233   traf_size = ((len & 48) >> 4) + 1;
4234
4235   GST_DEBUG_OBJECT (qtdemux, "%u entries, sizes: value %u, traf %u, trun %u, "
4236       "sample %u", num_entries, value_size, traf_size, trun_size, sample_size);
4237
4238   if (num_entries == 0)
4239     goto no_samples;
4240
4241   if (!qt_atom_parser_has_chunks (&tfra, num_entries,
4242           value_size + value_size + traf_size + trun_size + sample_size))
4243     goto corrupt_file;
4244
4245   g_free (stream->ra_entries);
4246   stream->ra_entries = g_new (QtDemuxRandomAccessEntry, num_entries);
4247   stream->n_ra_entries = num_entries;
4248
4249   for (i = 0; i < num_entries; i++) {
4250     qt_atom_parser_get_offset (&tfra, value_size, &time);
4251     qt_atom_parser_get_offset (&tfra, value_size, &moof_offset);
4252     qt_atom_parser_get_uint_with_size_unchecked (&tfra, traf_size);
4253     qt_atom_parser_get_uint_with_size_unchecked (&tfra, trun_size);
4254     qt_atom_parser_get_uint_with_size_unchecked (&tfra, sample_size);
4255
4256     time = QTSTREAMTIME_TO_GSTTIME (stream, time);
4257
4258     GST_LOG_OBJECT (qtdemux, "fragment time: %" GST_TIME_FORMAT ", "
4259         " moof_offset: %" G_GUINT64_FORMAT, GST_TIME_ARGS (time), moof_offset);
4260
4261     stream->ra_entries[i].ts = time;
4262     stream->ra_entries[i].moof_offset = moof_offset;
4263
4264     /* don't want to go through the entire file and read all moofs at startup */
4265 #if 0
4266     ret = gst_qtdemux_pull_atom (qtdemux, moof_offset, 0, &buf);
4267     if (ret != GST_FLOW_OK)
4268       goto corrupt_file;
4269     qtdemux_parse_moof (qtdemux, GST_BUFFER_DATA (buf), GST_BUFFER_SIZE (buf),
4270         moof_offset, stream);
4271     gst_buffer_unref (buf);
4272 #endif
4273   }
4274
4275   check_update_duration (qtdemux, time);
4276
4277   return TRUE;
4278
4279 /* ERRORS */
4280 unknown_trackid:
4281   {
4282     GST_WARNING_OBJECT (qtdemux, "Couldn't find stream for track %u", track_id);
4283     return FALSE;
4284   }
4285 corrupt_file:
4286   {
4287     GST_WARNING_OBJECT (qtdemux, "broken traf box, ignoring");
4288     return FALSE;
4289   }
4290 no_samples:
4291   {
4292     GST_WARNING_OBJECT (qtdemux, "stream has no samples");
4293     return FALSE;
4294   }
4295 }
4296
4297 static gboolean
4298 qtdemux_pull_mfro_mfra (GstQTDemux * qtdemux)
4299 {
4300   GstMapInfo mfro_map = GST_MAP_INFO_INIT;
4301   GstMapInfo mfra_map = GST_MAP_INFO_INIT;
4302   GstBuffer *mfro = NULL, *mfra = NULL;
4303   GstFlowReturn flow;
4304   gboolean ret = FALSE;
4305   GNode *mfra_node, *tfra_node;
4306   guint64 mfra_offset = 0;
4307   guint32 fourcc, mfra_size;
4308   gint64 len;
4309
4310   /* query upstream size in bytes */
4311   if (!gst_pad_peer_query_duration (qtdemux->sinkpad, GST_FORMAT_BYTES, &len))
4312     goto size_query_failed;
4313
4314   /* mfro box should be at the very end of the file */
4315   flow = gst_qtdemux_pull_atom (qtdemux, len - 16, 16, &mfro);
4316   if (flow != GST_FLOW_OK)
4317     goto exit;
4318
4319   gst_buffer_map (mfro, &mfro_map, GST_MAP_READ);
4320
4321   fourcc = QT_FOURCC (mfro_map.data + 4);
4322   if (fourcc != FOURCC_mfro)
4323     goto exit;
4324
4325   GST_INFO_OBJECT (qtdemux, "Found mfro box");
4326   if (mfro_map.size < 16)
4327     goto invalid_mfro_size;
4328
4329   mfra_size = QT_UINT32 (mfro_map.data + 12);
4330   if (mfra_size >= len)
4331     goto invalid_mfra_size;
4332
4333   mfra_offset = len - mfra_size;
4334
4335   GST_INFO_OBJECT (qtdemux, "mfra offset: %" G_GUINT64_FORMAT ", size %u",
4336       mfra_offset, mfra_size);
4337
4338   /* now get and parse mfra box */
4339   flow = gst_qtdemux_pull_atom (qtdemux, mfra_offset, mfra_size, &mfra);
4340   if (flow != GST_FLOW_OK)
4341     goto broken_file;
4342
4343   gst_buffer_map (mfra, &mfra_map, GST_MAP_READ);
4344
4345   mfra_node = g_node_new ((guint8 *) mfra_map.data);
4346   qtdemux_parse_node (qtdemux, mfra_node, mfra_map.data, mfra_map.size);
4347
4348   tfra_node = qtdemux_tree_get_child_by_type (mfra_node, FOURCC_tfra);
4349
4350   while (tfra_node) {
4351     qtdemux_parse_tfra (qtdemux, tfra_node);
4352     /* iterate all siblings */
4353     tfra_node = qtdemux_tree_get_sibling_by_type (tfra_node, FOURCC_tfra);
4354   }
4355   g_node_destroy (mfra_node);
4356
4357   GST_INFO_OBJECT (qtdemux, "parsed movie fragment random access box (mfra)");
4358   ret = TRUE;
4359
4360 exit:
4361
4362   if (mfro) {
4363     if (mfro_map.memory != NULL)
4364       gst_buffer_unmap (mfro, &mfro_map);
4365     gst_buffer_unref (mfro);
4366   }
4367   if (mfra) {
4368     if (mfra_map.memory != NULL)
4369       gst_buffer_unmap (mfra, &mfra_map);
4370     gst_buffer_unref (mfra);
4371   }
4372   return ret;
4373
4374 /* ERRORS */
4375 size_query_failed:
4376   {
4377     GST_WARNING_OBJECT (qtdemux, "could not query upstream size");
4378     goto exit;
4379   }
4380 invalid_mfro_size:
4381   {
4382     GST_WARNING_OBJECT (qtdemux, "mfro size is too small");
4383     goto exit;
4384   }
4385 invalid_mfra_size:
4386   {
4387     GST_WARNING_OBJECT (qtdemux, "mfra_size in mfro box is invalid");
4388     goto exit;
4389   }
4390 broken_file:
4391   {
4392     GST_WARNING_OBJECT (qtdemux, "bogus mfra offset or size, broken file");
4393     goto exit;
4394   }
4395 }
4396
4397 static guint64
4398 add_offset (guint64 offset, guint64 advance)
4399 {
4400   /* Avoid 64-bit overflow by clamping */
4401   if (offset > G_MAXUINT64 - advance)
4402     return G_MAXUINT64;
4403   return offset + advance;
4404 }
4405
4406 static GstFlowReturn
4407 gst_qtdemux_loop_state_header (GstQTDemux * qtdemux)
4408 {
4409   guint64 length = 0;
4410   guint32 fourcc = 0;
4411   GstBuffer *buf = NULL;
4412   GstFlowReturn ret = GST_FLOW_OK;
4413   guint64 cur_offset = qtdemux->offset;
4414   GstMapInfo map;
4415
4416   ret = gst_pad_pull_range (qtdemux->sinkpad, cur_offset, 16, &buf);
4417   if (G_UNLIKELY (ret != GST_FLOW_OK))
4418     goto beach;
4419   gst_buffer_map (buf, &map, GST_MAP_READ);
4420   if (G_LIKELY (map.size >= 8))
4421     extract_initial_length_and_fourcc (map.data, map.size, &length, &fourcc);
4422   gst_buffer_unmap (buf, &map);
4423   gst_buffer_unref (buf);
4424
4425   /* maybe we already got most we needed, so only consider this eof */
4426   if (G_UNLIKELY (length == 0)) {
4427     GST_ELEMENT_WARNING (qtdemux, STREAM, DEMUX,
4428         (_("Invalid atom size.")),
4429         ("Header atom '%" GST_FOURCC_FORMAT "' has empty length",
4430             GST_FOURCC_ARGS (fourcc)));
4431     ret = GST_FLOW_EOS;
4432     goto beach;
4433   }
4434
4435   switch (fourcc) {
4436     case FOURCC_moof:
4437       /* record for later parsing when needed */
4438       if (!qtdemux->moof_offset) {
4439         qtdemux->moof_offset = qtdemux->offset;
4440       }
4441       if (qtdemux_pull_mfro_mfra (qtdemux)) {
4442         /* FIXME */
4443       } else {
4444         qtdemux->offset += length;      /* skip moof and keep going */
4445       }
4446       if (qtdemux->got_moov) {
4447         GST_INFO_OBJECT (qtdemux, "moof header, got moov, done with headers");
4448         ret = GST_FLOW_EOS;
4449         goto beach;
4450       }
4451       break;
4452     case FOURCC_mdat:
4453     case FOURCC_free:
4454     case FOURCC_skip:
4455     case FOURCC_wide:
4456     case FOURCC_PICT:
4457     case FOURCC_pnot:
4458     {
4459       GST_LOG_OBJECT (qtdemux,
4460           "skipping atom '%" GST_FOURCC_FORMAT "' at %" G_GUINT64_FORMAT,
4461           GST_FOURCC_ARGS (fourcc), cur_offset);
4462       qtdemux->offset = add_offset (qtdemux->offset, length);
4463       break;
4464     }
4465     case FOURCC_moov:
4466     {
4467       GstBuffer *moov = NULL;
4468
4469       if (qtdemux->got_moov) {
4470         GST_DEBUG_OBJECT (qtdemux, "Skipping moov atom as we have one already");
4471         qtdemux->offset = add_offset (qtdemux->offset, length);
4472         goto beach;
4473       }
4474
4475       ret = gst_pad_pull_range (qtdemux->sinkpad, cur_offset, length, &moov);
4476       if (ret != GST_FLOW_OK)
4477         goto beach;
4478       gst_buffer_map (moov, &map, GST_MAP_READ);
4479
4480       if (length != map.size) {
4481         /* Some files have a 'moov' atom at the end of the file which contains
4482          * a terminal 'free' atom where the body of the atom is missing.
4483          * Check for, and permit, this special case.
4484          */
4485         if (map.size >= 8) {
4486           guint8 *final_data = map.data + (map.size - 8);
4487           guint32 final_length = QT_UINT32 (final_data);
4488           guint32 final_fourcc = QT_FOURCC (final_data + 4);
4489
4490           if (final_fourcc == FOURCC_free
4491               && map.size + final_length - 8 == length) {
4492             /* Ok, we've found that special case. Allocate a new buffer with
4493              * that free atom actually present. */
4494             GstBuffer *newmoov = gst_buffer_new_and_alloc (length);
4495             gst_buffer_fill (newmoov, 0, map.data, map.size);
4496             gst_buffer_memset (newmoov, map.size, 0, final_length - 8);
4497             gst_buffer_unmap (moov, &map);
4498             gst_buffer_unref (moov);
4499             moov = newmoov;
4500             gst_buffer_map (moov, &map, GST_MAP_READ);
4501           }
4502         }
4503       }
4504
4505       if (length != map.size) {
4506         GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
4507             (_("This file is incomplete and cannot be played.")),
4508             ("We got less than expected (received %" G_GSIZE_FORMAT
4509                 ", wanted %u, offset %" G_GUINT64_FORMAT ")", map.size,
4510                 (guint) length, cur_offset));
4511         gst_buffer_unmap (moov, &map);
4512         gst_buffer_unref (moov);
4513         ret = GST_FLOW_ERROR;
4514         goto beach;
4515       }
4516       qtdemux->offset += length;
4517
4518       qtdemux_parse_moov (qtdemux, map.data, length);
4519       qtdemux_node_dump (qtdemux, qtdemux->moov_node);
4520
4521       qtdemux_parse_tree (qtdemux);
4522       if (qtdemux->moov_node_compressed) {
4523         g_node_destroy (qtdemux->moov_node_compressed);
4524         g_free (qtdemux->moov_node->data);
4525       }
4526       qtdemux->moov_node_compressed = NULL;
4527       g_node_destroy (qtdemux->moov_node);
4528       qtdemux->moov_node = NULL;
4529       gst_buffer_unmap (moov, &map);
4530       gst_buffer_unref (moov);
4531       qtdemux->got_moov = TRUE;
4532
4533       break;
4534     }
4535     case FOURCC_ftyp:
4536     {
4537       GstBuffer *ftyp = NULL;
4538
4539       /* extract major brand; might come in handy for ISO vs QT issues */
4540       ret = gst_qtdemux_pull_atom (qtdemux, cur_offset, length, &ftyp);
4541       if (ret != GST_FLOW_OK)
4542         goto beach;
4543       qtdemux->offset += length;
4544       gst_buffer_map (ftyp, &map, GST_MAP_READ);
4545       qtdemux_parse_ftyp (qtdemux, map.data, map.size);
4546       gst_buffer_unmap (ftyp, &map);
4547       gst_buffer_unref (ftyp);
4548       break;
4549     }
4550     case FOURCC_uuid:
4551     {
4552       GstBuffer *uuid = NULL;
4553
4554       /* uuid are extension atoms */
4555       ret = gst_qtdemux_pull_atom (qtdemux, cur_offset, length, &uuid);
4556       if (ret != GST_FLOW_OK)
4557         goto beach;
4558       qtdemux->offset += length;
4559       gst_buffer_map (uuid, &map, GST_MAP_READ);
4560       qtdemux_parse_uuid (qtdemux, map.data, map.size);
4561       gst_buffer_unmap (uuid, &map);
4562       gst_buffer_unref (uuid);
4563       break;
4564     }
4565     case FOURCC_sidx:
4566     {
4567       GstBuffer *sidx = NULL;
4568       ret = gst_qtdemux_pull_atom (qtdemux, cur_offset, length, &sidx);
4569       if (ret != GST_FLOW_OK)
4570         goto beach;
4571       qtdemux->offset += length;
4572       gst_buffer_map (sidx, &map, GST_MAP_READ);
4573       qtdemux_parse_sidx (qtdemux, map.data, map.size);
4574       gst_buffer_unmap (sidx, &map);
4575       gst_buffer_unref (sidx);
4576       break;
4577     }
4578     default:
4579     {
4580       GstBuffer *unknown = NULL;
4581
4582       GST_LOG_OBJECT (qtdemux,
4583           "unknown %08x '%" GST_FOURCC_FORMAT "' of size %" G_GUINT64_FORMAT
4584           " at %" G_GUINT64_FORMAT, fourcc, GST_FOURCC_ARGS (fourcc), length,
4585           cur_offset);
4586       ret = gst_qtdemux_pull_atom (qtdemux, cur_offset, length, &unknown);
4587       if (ret != GST_FLOW_OK)
4588         goto beach;
4589       gst_buffer_map (unknown, &map, GST_MAP_READ);
4590       GST_MEMDUMP ("Unknown tag", map.data, map.size);
4591       gst_buffer_unmap (unknown, &map);
4592       gst_buffer_unref (unknown);
4593       qtdemux->offset += length;
4594       break;
4595     }
4596   }
4597
4598 beach:
4599   if (ret == GST_FLOW_EOS && (qtdemux->got_moov || qtdemux->media_caps)) {
4600     /* digested all data, show what we have */
4601     qtdemux_prepare_streams (qtdemux);
4602     QTDEMUX_EXPOSE_LOCK (qtdemux);
4603     ret = qtdemux_expose_streams (qtdemux);
4604     QTDEMUX_EXPOSE_UNLOCK (qtdemux);
4605
4606     qtdemux->state = QTDEMUX_STATE_MOVIE;
4607     GST_DEBUG_OBJECT (qtdemux, "switching state to STATE_MOVIE (%d)",
4608         qtdemux->state);
4609     return ret;
4610   }
4611   return ret;
4612 }
4613
4614 /* Seeks to the previous keyframe of the indexed stream and
4615  * aligns other streams with respect to the keyframe timestamp
4616  * of indexed stream. Only called in case of Reverse Playback
4617  */
4618 static GstFlowReturn
4619 gst_qtdemux_seek_to_previous_keyframe (GstQTDemux * qtdemux)
4620 {
4621   guint32 seg_idx = 0, k_index = 0;
4622   guint32 ref_seg_idx, ref_k_index;
4623   GstClockTime k_pos = 0, last_stop = 0;
4624   QtDemuxSegment *seg = NULL;
4625   QtDemuxStream *ref_str = NULL;
4626   guint64 seg_media_start_mov;  /* segment media start time in mov format */
4627   guint64 target_ts;
4628   GList *iter;
4629
4630   /* Now we choose an arbitrary stream, get the previous keyframe timestamp
4631    * and finally align all the other streams on that timestamp with their
4632    * respective keyframes */
4633   for (iter = qtdemux->active_streams; iter; iter = g_list_next (iter)) {
4634     QtDemuxStream *str = QTDEMUX_STREAM (iter->data);
4635
4636     /* No candidate yet, take the first stream */
4637     if (!ref_str) {
4638       ref_str = str;
4639       continue;
4640     }
4641
4642     /* So that stream has a segment, we prefer video streams */
4643     if (str->subtype == FOURCC_vide) {
4644       ref_str = str;
4645       break;
4646     }
4647   }
4648
4649   if (G_UNLIKELY (!ref_str)) {
4650     GST_DEBUG_OBJECT (qtdemux, "couldn't find any stream");
4651     goto eos;
4652   }
4653
4654   if (G_UNLIKELY (!ref_str->from_sample)) {
4655     GST_DEBUG_OBJECT (qtdemux, "reached the beginning of the file");
4656     goto eos;
4657   }
4658
4659   /* So that stream has been playing from from_sample to to_sample. We will
4660    * get the timestamp of the previous sample and search for a keyframe before
4661    * that. For audio streams we do an arbitrary jump in the past (10 samples) */
4662   if (ref_str->subtype == FOURCC_vide) {
4663     k_index = gst_qtdemux_find_keyframe (qtdemux, ref_str,
4664         ref_str->from_sample - 1, FALSE);
4665   } else {
4666     if (ref_str->from_sample >= 10)
4667       k_index = ref_str->from_sample - 10;
4668     else
4669       k_index = 0;
4670   }
4671
4672   target_ts =
4673       ref_str->samples[k_index].timestamp +
4674       ref_str->samples[k_index].pts_offset;
4675
4676   /* get current segment for that stream */
4677   seg = &ref_str->segments[ref_str->segment_index];
4678   /* Use segment start in original timescale for comparisons */
4679   seg_media_start_mov = seg->trak_media_start;
4680
4681   GST_LOG_OBJECT (qtdemux, "keyframe index %u ts %" G_GUINT64_FORMAT
4682       " seg start %" G_GUINT64_FORMAT " %" GST_TIME_FORMAT "\n",
4683       k_index, target_ts, seg_media_start_mov,
4684       GST_TIME_ARGS (seg->media_start));
4685
4686   /* Crawl back through segments to find the one containing this I frame */
4687   while (target_ts < seg_media_start_mov) {
4688     GST_DEBUG_OBJECT (qtdemux,
4689         "keyframe position (sample %u) is out of segment %u " " target %"
4690         G_GUINT64_FORMAT " seg start %" G_GUINT64_FORMAT, k_index,
4691         ref_str->segment_index, target_ts, seg_media_start_mov);
4692
4693     if (G_UNLIKELY (!ref_str->segment_index)) {
4694       /* Reached first segment, let's consider it's EOS */
4695       goto eos;
4696     }
4697     ref_str->segment_index--;
4698     seg = &ref_str->segments[ref_str->segment_index];
4699     /* Use segment start in original timescale for comparisons */
4700     seg_media_start_mov = seg->trak_media_start;
4701   }
4702   /* Calculate time position of the keyframe and where we should stop */
4703   k_pos =
4704       QTSTREAMTIME_TO_GSTTIME (ref_str,
4705       target_ts - seg->trak_media_start) + seg->time;
4706   last_stop =
4707       QTSTREAMTIME_TO_GSTTIME (ref_str,
4708       ref_str->samples[ref_str->from_sample].timestamp -
4709       seg->trak_media_start) + seg->time;
4710
4711   GST_DEBUG_OBJECT (qtdemux, "preferred stream played from sample %u, "
4712       "now going to sample %u (pts %" GST_TIME_FORMAT ")", ref_str->from_sample,
4713       k_index, GST_TIME_ARGS (k_pos));
4714
4715   /* Set last_stop with the keyframe timestamp we pushed of that stream */
4716   qtdemux->segment.position = last_stop;
4717   GST_DEBUG_OBJECT (qtdemux, "last_stop now is %" GST_TIME_FORMAT,
4718       GST_TIME_ARGS (last_stop));
4719
4720   if (G_UNLIKELY (last_stop < qtdemux->segment.start)) {
4721     GST_DEBUG_OBJECT (qtdemux, "reached the beginning of segment");
4722     goto eos;
4723   }
4724
4725   ref_seg_idx = ref_str->segment_index;
4726   ref_k_index = k_index;
4727
4728   /* Align them all on this */
4729   for (iter = qtdemux->active_streams; iter; iter = g_list_next (iter)) {
4730     guint32 index = 0;
4731     GstClockTime seg_time = 0;
4732     QtDemuxStream *str = QTDEMUX_STREAM (iter->data);
4733
4734     /* aligning reference stream again might lead to backing up to yet another
4735      * keyframe (due to timestamp rounding issues),
4736      * potentially putting more load on downstream; so let's try to avoid */
4737     if (str == ref_str) {
4738       seg_idx = ref_seg_idx;
4739       seg = &str->segments[seg_idx];
4740       k_index = ref_k_index;
4741       GST_DEBUG_OBJECT (qtdemux, "reference track-id %u segment %d, "
4742           "sample at index %d", str->track_id, ref_str->segment_index, k_index);
4743     } else {
4744       seg_idx = gst_qtdemux_find_segment (qtdemux, str, k_pos);
4745       GST_DEBUG_OBJECT (qtdemux,
4746           "track-id %u align segment %d for keyframe pos %" GST_TIME_FORMAT,
4747           str->track_id, seg_idx, GST_TIME_ARGS (k_pos));
4748
4749       /* get segment and time in the segment */
4750       seg = &str->segments[seg_idx];
4751       seg_time = k_pos - seg->time;
4752
4753       /* get the media time in the segment.
4754        * No adjustment for empty "filler" segments */
4755       if (seg->media_start != GST_CLOCK_TIME_NONE)
4756         seg_time += seg->media_start;
4757
4758       /* get the index of the sample with media time */
4759       index = gst_qtdemux_find_index_linear (qtdemux, str, seg_time);
4760       GST_DEBUG_OBJECT (qtdemux,
4761           "track-id %u sample for %" GST_TIME_FORMAT " at %u", str->track_id,
4762           GST_TIME_ARGS (seg_time), index);
4763
4764       /* find previous keyframe */
4765       k_index = gst_qtdemux_find_keyframe (qtdemux, str, index, FALSE);
4766     }
4767
4768     /* Remember until where we want to go */
4769     str->to_sample = str->from_sample - 1;
4770     /* Define our time position */
4771     target_ts =
4772         str->samples[k_index].timestamp + str->samples[k_index].pts_offset;
4773     str->time_position = QTSTREAMTIME_TO_GSTTIME (str, target_ts) + seg->time;
4774     if (seg->media_start != GST_CLOCK_TIME_NONE)
4775       str->time_position -= seg->media_start;
4776
4777     /* Now seek back in time */
4778     gst_qtdemux_move_stream (qtdemux, str, k_index);
4779     GST_DEBUG_OBJECT (qtdemux, "track-id %u keyframe at %u, time position %"
4780         GST_TIME_FORMAT " playing from sample %u to %u", str->track_id, k_index,
4781         GST_TIME_ARGS (str->time_position), str->from_sample, str->to_sample);
4782   }
4783
4784   return GST_FLOW_OK;
4785
4786 eos:
4787   return GST_FLOW_EOS;
4788 }
4789
4790 /*
4791  * Gets the current qt segment start, stop and position for the
4792  * given time offset. This is used in update_segment()
4793  */
4794 static void
4795 gst_qtdemux_stream_segment_get_boundaries (GstQTDemux * qtdemux,
4796     QtDemuxStream * stream, GstClockTime offset,
4797     GstClockTime * _start, GstClockTime * _stop, GstClockTime * _time)
4798 {
4799   GstClockTime seg_time;
4800   GstClockTime start, stop, time;
4801   QtDemuxSegment *segment;
4802
4803   segment = &stream->segments[stream->segment_index];
4804
4805   /* get time in this segment */
4806   seg_time = (offset - segment->time) * segment->rate;
4807
4808   GST_LOG_OBJECT (stream->pad, "seg_time %" GST_TIME_FORMAT,
4809       GST_TIME_ARGS (seg_time));
4810
4811   if (G_UNLIKELY (seg_time > segment->duration)) {
4812     GST_LOG_OBJECT (stream->pad,
4813         "seg_time > segment->duration %" GST_TIME_FORMAT,
4814         GST_TIME_ARGS (segment->duration));
4815     seg_time = segment->duration;
4816   }
4817
4818   /* qtdemux->segment.stop is in outside-time-realm, whereas
4819    * segment->media_stop is in track-time-realm.
4820    *
4821    * In order to compare the two, we need to bring segment.stop
4822    * into the track-time-realm
4823    *
4824    * FIXME - does this comment still hold? Don't see any conversion here */
4825
4826   stop = qtdemux->segment.stop;
4827   if (stop == GST_CLOCK_TIME_NONE)
4828     stop = qtdemux->segment.duration;
4829   if (stop == GST_CLOCK_TIME_NONE)
4830     stop = segment->media_stop;
4831   else
4832     stop =
4833         MIN (segment->media_stop, stop - segment->time + segment->media_start);
4834
4835   if (G_UNLIKELY (QTSEGMENT_IS_EMPTY (segment))) {
4836     start = segment->time + seg_time;
4837     time = offset;
4838     stop = start - seg_time + segment->duration;
4839   } else if (qtdemux->segment.rate >= 0) {
4840     start = MIN (segment->media_start + seg_time, stop);
4841     time = offset;
4842   } else {
4843     if (segment->media_start >= qtdemux->segment.start) {
4844       time = segment->time;
4845     } else {
4846       time = segment->time + (qtdemux->segment.start - segment->media_start);
4847     }
4848
4849     start = MAX (segment->media_start, qtdemux->segment.start);
4850     stop = MIN (segment->media_start + seg_time, stop);
4851   }
4852
4853   *_start = start;
4854   *_stop = stop;
4855   *_time = time;
4856 }
4857
4858 /*
4859  * Updates the qt segment used for the stream and pushes a new segment event
4860  * downstream on this stream's pad.
4861  */
4862 static gboolean
4863 gst_qtdemux_stream_update_segment (GstQTDemux * qtdemux, QtDemuxStream * stream,
4864     gint seg_idx, GstClockTime offset, GstClockTime * _start,
4865     GstClockTime * _stop)
4866 {
4867   QtDemuxSegment *segment;
4868   GstClockTime start = 0, stop = GST_CLOCK_TIME_NONE, time = 0;
4869   gdouble rate;
4870   GstEvent *event;
4871
4872   /* update the current segment */
4873   stream->segment_index = seg_idx;
4874
4875   /* get the segment */
4876   segment = &stream->segments[seg_idx];
4877
4878   if (G_UNLIKELY (offset < segment->time)) {
4879     GST_WARNING_OBJECT (stream->pad, "offset < segment->time %" GST_TIME_FORMAT,
4880         GST_TIME_ARGS (segment->time));
4881     return FALSE;
4882   }
4883
4884   /* segment lies beyond total indicated duration */
4885   if (G_UNLIKELY (qtdemux->segment.duration != GST_CLOCK_TIME_NONE &&
4886           segment->time > qtdemux->segment.duration)) {
4887     GST_WARNING_OBJECT (stream->pad, "file duration %" GST_TIME_FORMAT
4888         " < segment->time %" GST_TIME_FORMAT,
4889         GST_TIME_ARGS (qtdemux->segment.duration),
4890         GST_TIME_ARGS (segment->time));
4891     return FALSE;
4892   }
4893
4894   gst_qtdemux_stream_segment_get_boundaries (qtdemux, stream, offset,
4895       &start, &stop, &time);
4896
4897   GST_DEBUG_OBJECT (stream->pad, "new segment %d from %" GST_TIME_FORMAT
4898       " to %" GST_TIME_FORMAT ", time %" GST_TIME_FORMAT, seg_idx,
4899       GST_TIME_ARGS (start), GST_TIME_ARGS (stop), GST_TIME_ARGS (time));
4900
4901   /* combine global rate with that of the segment */
4902   rate = segment->rate * qtdemux->segment.rate;
4903
4904   /* Copy flags from main segment */
4905   stream->segment.flags = qtdemux->segment.flags;
4906
4907   /* update the segment values used for clipping */
4908   stream->segment.offset = qtdemux->segment.offset;
4909   stream->segment.base = qtdemux->segment.base + stream->accumulated_base;
4910   stream->segment.applied_rate = qtdemux->segment.applied_rate;
4911   stream->segment.rate = rate;
4912   stream->segment.start = start + QTSTREAMTIME_TO_GSTTIME (stream,
4913       stream->cslg_shift);
4914   stream->segment.stop = stop + QTSTREAMTIME_TO_GSTTIME (stream,
4915       stream->cslg_shift);
4916   stream->segment.time = time;
4917   stream->segment.position = stream->segment.start;
4918
4919   GST_DEBUG_OBJECT (stream->pad, "New segment: %" GST_SEGMENT_FORMAT,
4920       &stream->segment);
4921
4922   /* now prepare and send the segment */
4923   if (stream->pad) {
4924     event = gst_event_new_segment (&stream->segment);
4925     if (qtdemux->segment_seqnum != GST_SEQNUM_INVALID) {
4926       gst_event_set_seqnum (event, qtdemux->segment_seqnum);
4927     }
4928     gst_pad_push_event (stream->pad, event);
4929     /* assume we can send more data now */
4930     GST_PAD_LAST_FLOW_RETURN (stream->pad) = GST_FLOW_OK;
4931     /* clear to send tags on this pad now */
4932     gst_qtdemux_push_tags (qtdemux, stream);
4933   }
4934
4935   if (_start)
4936     *_start = start;
4937   if (_stop)
4938     *_stop = stop;
4939
4940   return TRUE;
4941 }
4942
4943 /* activate the given segment number @seg_idx of @stream at time @offset.
4944  * @offset is an absolute global position over all the segments.
4945  *
4946  * This will push out a NEWSEGMENT event with the right values and
4947  * position the stream index to the first decodable sample before
4948  * @offset.
4949  */
4950 static gboolean
4951 gst_qtdemux_activate_segment (GstQTDemux * qtdemux, QtDemuxStream * stream,
4952     guint32 seg_idx, GstClockTime offset)
4953 {
4954   QtDemuxSegment *segment;
4955   guint32 index, kf_index;
4956   GstClockTime start = 0, stop = GST_CLOCK_TIME_NONE;
4957
4958   GST_LOG_OBJECT (stream->pad, "activate segment %d, offset %" GST_TIME_FORMAT,
4959       seg_idx, GST_TIME_ARGS (offset));
4960
4961   if (!gst_qtdemux_stream_update_segment (qtdemux, stream, seg_idx, offset,
4962           &start, &stop))
4963     return FALSE;
4964
4965   segment = &stream->segments[stream->segment_index];
4966
4967   /* in the fragmented case, we pick a fragment that starts before our
4968    * desired position and rely on downstream to wait for a keyframe
4969    * (FIXME: doesn't seem to work so well with ismv and wmv, as no parser; the
4970    * tfra entries tells us which trun/sample the key unit is in, but we don't
4971    * make use of this additional information at the moment) */
4972   if (qtdemux->fragmented && !qtdemux->fragmented_seek_pending) {
4973     stream->to_sample = G_MAXUINT32;
4974     return TRUE;
4975   } else {
4976     /* well, it will be taken care of below */
4977     qtdemux->fragmented_seek_pending = FALSE;
4978     /* FIXME ideally the do_fragmented_seek can be done right here,
4979      * rather than at loop level
4980      * (which might even allow handling edit lists in a fragmented file) */
4981   }
4982
4983   /* We don't need to look for a sample in push-based */
4984   if (!qtdemux->pullbased)
4985     return TRUE;
4986
4987   /* and move to the keyframe before the indicated media time of the
4988    * segment */
4989   if (G_LIKELY (!QTSEGMENT_IS_EMPTY (segment))) {
4990     if (qtdemux->segment.rate >= 0) {
4991       index = gst_qtdemux_find_index_linear (qtdemux, stream, start);
4992       stream->to_sample = G_MAXUINT32;
4993       GST_DEBUG_OBJECT (stream->pad,
4994           "moving data pointer to %" GST_TIME_FORMAT ", index: %u, pts %"
4995           GST_TIME_FORMAT, GST_TIME_ARGS (start), index,
4996           GST_TIME_ARGS (QTSAMPLE_PTS (stream, &stream->samples[index])));
4997     } else {
4998       index = gst_qtdemux_find_index_linear (qtdemux, stream, stop);
4999       stream->to_sample = index;
5000       GST_DEBUG_OBJECT (stream->pad,
5001           "moving data pointer to %" GST_TIME_FORMAT ", index: %u, pts %"
5002           GST_TIME_FORMAT, GST_TIME_ARGS (stop), index,
5003           GST_TIME_ARGS (QTSAMPLE_PTS (stream, &stream->samples[index])));
5004     }
5005   } else {
5006     GST_DEBUG_OBJECT (stream->pad, "No need to look for keyframe, "
5007         "this is an empty segment");
5008     return TRUE;
5009   }
5010
5011   /* gst_qtdemux_parse_sample () called from gst_qtdemux_find_index_linear ()
5012    * encountered an error and printed a message so we return appropriately */
5013   if (index == -1)
5014     return FALSE;
5015
5016   /* we're at the right spot */
5017   if (index == stream->sample_index) {
5018     GST_DEBUG_OBJECT (stream->pad, "we are at the right index");
5019     return TRUE;
5020   }
5021
5022   /* find keyframe of the target index */
5023   kf_index = gst_qtdemux_find_keyframe (qtdemux, stream, index, FALSE);
5024
5025 /* *INDENT-OFF* */
5026 /* indent does stupid stuff with stream->samples[].timestamp */
5027
5028   /* if we move forwards, we don't have to go back to the previous
5029    * keyframe since we already sent that. We can also just jump to
5030    * the keyframe right before the target index if there is one. */
5031   if (index > stream->sample_index) {
5032     /* moving forwards check if we move past a keyframe */
5033     if (kf_index > stream->sample_index) {
5034       GST_DEBUG_OBJECT (stream->pad,
5035            "moving forwards to keyframe at %u (pts %" GST_TIME_FORMAT " dts %"GST_TIME_FORMAT" )", kf_index,
5036            GST_TIME_ARGS (QTSAMPLE_PTS(stream, &stream->samples[kf_index])),
5037            GST_TIME_ARGS (QTSAMPLE_DTS(stream, &stream->samples[kf_index])));
5038       gst_qtdemux_move_stream (qtdemux, stream, kf_index);
5039     } else {
5040       GST_DEBUG_OBJECT (stream->pad,
5041           "moving forwards, keyframe at %u (pts %" GST_TIME_FORMAT " dts %"GST_TIME_FORMAT" ) already sent", kf_index,
5042           GST_TIME_ARGS (QTSAMPLE_PTS (stream, &stream->samples[kf_index])),
5043           GST_TIME_ARGS (QTSAMPLE_DTS (stream, &stream->samples[kf_index])));
5044     }
5045   } else {
5046     GST_DEBUG_OBJECT (stream->pad,
5047         "moving backwards to keyframe at %u (pts %" GST_TIME_FORMAT " dts %"GST_TIME_FORMAT" )", kf_index,
5048         GST_TIME_ARGS (QTSAMPLE_PTS(stream, &stream->samples[kf_index])),
5049         GST_TIME_ARGS (QTSAMPLE_DTS(stream, &stream->samples[kf_index])));
5050     gst_qtdemux_move_stream (qtdemux, stream, kf_index);
5051   }
5052
5053 /* *INDENT-ON* */
5054
5055   return TRUE;
5056 }
5057
5058 /* prepare to get the current sample of @stream, getting essential values.
5059  *
5060  * This function will also prepare and send the segment when needed.
5061  *
5062  * Return FALSE if the stream is EOS.
5063  *
5064  * PULL-BASED
5065  */
5066 static gboolean
5067 gst_qtdemux_prepare_current_sample (GstQTDemux * qtdemux,
5068     QtDemuxStream * stream, gboolean * empty, guint64 * offset, guint * size,
5069     GstClockTime * dts, GstClockTime * pts, GstClockTime * duration,
5070     gboolean * keyframe)
5071 {
5072   QtDemuxSample *sample;
5073   GstClockTime time_position;
5074   guint32 seg_idx;
5075
5076   g_return_val_if_fail (stream != NULL, FALSE);
5077
5078   time_position = stream->time_position;
5079   if (G_UNLIKELY (time_position == GST_CLOCK_TIME_NONE))
5080     goto eos;
5081
5082   seg_idx = stream->segment_index;
5083   if (G_UNLIKELY (seg_idx == -1)) {
5084     /* find segment corresponding to time_position if we are looking
5085      * for a segment. */
5086     seg_idx = gst_qtdemux_find_segment (qtdemux, stream, time_position);
5087   }
5088
5089   /* different segment, activate it, sample_index will be set. */
5090   if (G_UNLIKELY (stream->segment_index != seg_idx))
5091     gst_qtdemux_activate_segment (qtdemux, stream, seg_idx, time_position);
5092
5093   if (G_UNLIKELY (QTSEGMENT_IS_EMPTY (&stream->segments[stream->
5094                   segment_index]))) {
5095     QtDemuxSegment *seg = &stream->segments[stream->segment_index];
5096
5097     GST_LOG_OBJECT (qtdemux, "Empty segment activated,"
5098         " prepare empty sample");
5099
5100     *empty = TRUE;
5101     *pts = *dts = time_position;
5102     *duration = seg->duration - (time_position - seg->time);
5103
5104     return TRUE;
5105   }
5106
5107   *empty = FALSE;
5108
5109   if (stream->sample_index == -1)
5110     stream->sample_index = 0;
5111
5112   GST_LOG_OBJECT (qtdemux, "segment active, index = %u of %u",
5113       stream->sample_index, stream->n_samples);
5114
5115   if (G_UNLIKELY (stream->sample_index >= stream->n_samples)) {
5116     if (!qtdemux->fragmented)
5117       goto eos;
5118
5119     GST_INFO_OBJECT (qtdemux, "out of samples, trying to add more");
5120     do {
5121       GstFlowReturn flow;
5122
5123       GST_OBJECT_LOCK (qtdemux);
5124       flow = qtdemux_add_fragmented_samples (qtdemux);
5125       GST_OBJECT_UNLOCK (qtdemux);
5126
5127       if (flow != GST_FLOW_OK)
5128         goto eos;
5129     }
5130     while (stream->sample_index >= stream->n_samples);
5131   }
5132
5133   if (!qtdemux_parse_samples (qtdemux, stream, stream->sample_index)) {
5134     GST_LOG_OBJECT (qtdemux, "Parsing of index %u failed!",
5135         stream->sample_index);
5136     return FALSE;
5137   }
5138
5139   /* now get the info for the sample we're at */
5140   sample = &stream->samples[stream->sample_index];
5141
5142   *dts = QTSAMPLE_DTS (stream, sample);
5143   *pts = QTSAMPLE_PTS (stream, sample);
5144   *offset = sample->offset;
5145   *size = sample->size;
5146   *duration = QTSAMPLE_DUR_DTS (stream, sample, *dts);
5147   *keyframe = QTSAMPLE_KEYFRAME (stream, sample);
5148
5149   return TRUE;
5150
5151   /* special cases */
5152 eos:
5153   {
5154     stream->time_position = GST_CLOCK_TIME_NONE;
5155     return FALSE;
5156   }
5157 }
5158
5159 /* move to the next sample in @stream.
5160  *
5161  * Moves to the next segment when needed.
5162  */
5163 static void
5164 gst_qtdemux_advance_sample (GstQTDemux * qtdemux, QtDemuxStream * stream)
5165 {
5166   QtDemuxSample *sample;
5167   QtDemuxSegment *segment;
5168
5169   /* get current segment */
5170   segment = &stream->segments[stream->segment_index];
5171
5172   if (G_UNLIKELY (QTSEGMENT_IS_EMPTY (segment))) {
5173     GST_DEBUG_OBJECT (qtdemux, "Empty segment, no samples to advance");
5174     goto next_segment;
5175   }
5176
5177   if (G_UNLIKELY (stream->sample_index >= stream->to_sample)) {
5178     /* Mark the stream as EOS */
5179     GST_DEBUG_OBJECT (qtdemux,
5180         "reached max allowed sample %u, mark EOS", stream->to_sample);
5181     stream->time_position = GST_CLOCK_TIME_NONE;
5182     return;
5183   }
5184
5185   /* move to next sample */
5186   stream->sample_index++;
5187   stream->offset_in_sample = 0;
5188
5189   /* reached the last sample, we need the next segment */
5190   if (G_UNLIKELY (stream->sample_index >= stream->n_samples))
5191     goto next_segment;
5192
5193   if (!qtdemux_parse_samples (qtdemux, stream, stream->sample_index)) {
5194     GST_LOG_OBJECT (qtdemux, "Parsing of index %u failed!",
5195         stream->sample_index);
5196     return;
5197   }
5198
5199   /* get next sample */
5200   sample = &stream->samples[stream->sample_index];
5201
5202   /* see if we are past the segment */
5203   if (G_UNLIKELY (QTSAMPLE_DTS (stream, sample) >= segment->media_stop))
5204     goto next_segment;
5205
5206   if (QTSAMPLE_DTS (stream, sample) >= segment->media_start) {
5207     /* inside the segment, update time_position, looks very familiar to
5208      * GStreamer segments, doesn't it? */
5209     stream->time_position =
5210         QTSAMPLE_DTS (stream, sample) - segment->media_start + segment->time;
5211   } else {
5212     /* not yet in segment, time does not yet increment. This means
5213      * that we are still prerolling keyframes to the decoder so it can
5214      * decode the first sample of the segment. */
5215     stream->time_position = segment->time;
5216   }
5217   return;
5218
5219   /* move to the next segment */
5220 next_segment:
5221   {
5222     GST_DEBUG_OBJECT (qtdemux, "segment %d ended ", stream->segment_index);
5223
5224     if (stream->segment_index == stream->n_segments - 1) {
5225       /* are we at the end of the last segment, we're EOS */
5226       stream->time_position = GST_CLOCK_TIME_NONE;
5227     } else {
5228       /* else we're only at the end of the current segment */
5229       stream->time_position = segment->stop_time;
5230     }
5231     /* make sure we select a new segment */
5232
5233     /* accumulate previous segments */
5234     if (GST_CLOCK_TIME_IS_VALID (stream->segment.stop))
5235       stream->accumulated_base +=
5236           (stream->segment.stop -
5237           stream->segment.start) / ABS (stream->segment.rate);
5238
5239     stream->segment_index = -1;
5240   }
5241 }
5242
5243 static void
5244 gst_qtdemux_sync_streams (GstQTDemux * demux)
5245 {
5246   GList *iter;
5247
5248   if (demux->n_streams <= 1)
5249     return;
5250
5251   for (iter = demux->active_streams; iter; iter = g_list_next (iter)) {
5252     QtDemuxStream *stream;
5253     GstClockTime end_time;
5254
5255     stream = QTDEMUX_STREAM (iter->data);
5256
5257     if (!stream->pad)
5258       continue;
5259
5260     /* TODO advance time on subtitle streams here, if any some day */
5261
5262     /* some clips/trailers may have unbalanced streams at the end,
5263      * so send EOS on shorter stream to prevent stalling others */
5264
5265     /* do not mess with EOS if SEGMENT seeking */
5266     if (demux->segment.flags & GST_SEEK_FLAG_SEGMENT)
5267       continue;
5268
5269     if (demux->pullbased) {
5270       /* loop mode is sample time based */
5271       if (!STREAM_IS_EOS (stream))
5272         continue;
5273     } else {
5274       /* push mode is byte position based */
5275       if (stream->n_samples &&
5276           stream->samples[stream->n_samples - 1].offset >= demux->offset)
5277         continue;
5278     }
5279
5280     if (stream->sent_eos)
5281       continue;
5282
5283     /* only act if some gap */
5284     end_time = stream->segments[stream->n_segments - 1].stop_time;
5285     GST_LOG_OBJECT (demux, "current position: %" GST_TIME_FORMAT
5286         ", stream end: %" GST_TIME_FORMAT,
5287         GST_TIME_ARGS (demux->segment.position), GST_TIME_ARGS (end_time));
5288     if (GST_CLOCK_TIME_IS_VALID (end_time)
5289         && (end_time + 2 * GST_SECOND < demux->segment.position)) {
5290       GstEvent *event;
5291
5292       GST_DEBUG_OBJECT (demux, "sending EOS for stream %s",
5293           GST_PAD_NAME (stream->pad));
5294       stream->sent_eos = TRUE;
5295       event = gst_event_new_eos ();
5296       if (demux->segment_seqnum != GST_SEQNUM_INVALID)
5297         gst_event_set_seqnum (event, demux->segment_seqnum);
5298       gst_pad_push_event (stream->pad, event);
5299     }
5300   }
5301 }
5302
5303 /* EOS and NOT_LINKED need to be combined. This means that we return:
5304  *
5305  *  GST_FLOW_NOT_LINKED: when all pads NOT_LINKED.
5306  *  GST_FLOW_EOS: when all pads EOS or NOT_LINKED.
5307  */
5308 static GstFlowReturn
5309 gst_qtdemux_combine_flows (GstQTDemux * demux, QtDemuxStream * stream,
5310     GstFlowReturn ret)
5311 {
5312   GST_LOG_OBJECT (demux, "flow return: %s", gst_flow_get_name (ret));
5313
5314   if (stream->pad)
5315     ret = gst_flow_combiner_update_pad_flow (demux->flowcombiner, stream->pad,
5316         ret);
5317   else
5318     ret = gst_flow_combiner_update_flow (demux->flowcombiner, ret);
5319
5320   GST_LOG_OBJECT (demux, "combined flow return: %s", gst_flow_get_name (ret));
5321   return ret;
5322 }
5323
5324 /* the input buffer metadata must be writable. Returns NULL when the buffer is
5325  * completely clipped
5326  *
5327  * Should be used only with raw buffers */
5328 static GstBuffer *
5329 gst_qtdemux_clip_buffer (GstQTDemux * qtdemux, QtDemuxStream * stream,
5330     GstBuffer * buf)
5331 {
5332   guint64 start, stop, cstart, cstop, diff;
5333   GstClockTime pts, duration;
5334   gsize size, osize;
5335   gint num_rate, denom_rate;
5336   gint frame_size;
5337   gboolean clip_data;
5338   guint offset;
5339
5340   osize = size = gst_buffer_get_size (buf);
5341   offset = 0;
5342
5343   /* depending on the type, setup the clip parameters */
5344   if (stream->subtype == FOURCC_soun) {
5345     frame_size = CUR_STREAM (stream)->bytes_per_frame;
5346     num_rate = GST_SECOND;
5347     denom_rate = (gint) CUR_STREAM (stream)->rate;
5348     clip_data = TRUE;
5349   } else if (stream->subtype == FOURCC_vide) {
5350     frame_size = size;
5351     num_rate = CUR_STREAM (stream)->fps_n;
5352     denom_rate = CUR_STREAM (stream)->fps_d;
5353     clip_data = FALSE;
5354   } else
5355     goto wrong_type;
5356
5357   if (frame_size <= 0)
5358     goto bad_frame_size;
5359
5360   /* we can only clip if we have a valid pts */
5361   pts = GST_BUFFER_PTS (buf);
5362   if (G_UNLIKELY (!GST_CLOCK_TIME_IS_VALID (pts)))
5363     goto no_pts;
5364
5365   duration = GST_BUFFER_DURATION (buf);
5366
5367   if (G_UNLIKELY (!GST_CLOCK_TIME_IS_VALID (duration))) {
5368     duration =
5369         gst_util_uint64_scale_int (size / frame_size, num_rate, denom_rate);
5370   }
5371
5372   start = pts;
5373   stop = start + duration;
5374
5375   if (G_UNLIKELY (!gst_segment_clip (&stream->segment,
5376               GST_FORMAT_TIME, start, stop, &cstart, &cstop)))
5377     goto clipped;
5378
5379   /* see if some clipping happened */
5380   diff = cstart - start;
5381   if (diff > 0) {
5382     pts += diff;
5383     duration -= diff;
5384
5385     if (clip_data) {
5386       /* bring clipped time to samples and to bytes */
5387       diff = gst_util_uint64_scale_int (diff, denom_rate, num_rate);
5388       diff *= frame_size;
5389
5390       GST_DEBUG_OBJECT (qtdemux,
5391           "clipping start to %" GST_TIME_FORMAT " %"
5392           G_GUINT64_FORMAT " bytes", GST_TIME_ARGS (cstart), diff);
5393
5394       offset = diff;
5395       size -= diff;
5396     }
5397   }
5398   diff = stop - cstop;
5399   if (diff > 0) {
5400     duration -= diff;
5401
5402     if (clip_data) {
5403       /* bring clipped time to samples and then to bytes */
5404       diff = gst_util_uint64_scale_int (diff, denom_rate, num_rate);
5405       diff *= frame_size;
5406       GST_DEBUG_OBJECT (qtdemux,
5407           "clipping stop to %" GST_TIME_FORMAT " %" G_GUINT64_FORMAT
5408           " bytes", GST_TIME_ARGS (cstop), diff);
5409       size -= diff;
5410     }
5411   }
5412
5413   if (offset != 0 || size != osize)
5414     gst_buffer_resize (buf, offset, size);
5415
5416   GST_BUFFER_DTS (buf) = GST_CLOCK_TIME_NONE;
5417   GST_BUFFER_PTS (buf) = pts;
5418   GST_BUFFER_DURATION (buf) = duration;
5419
5420   return buf;
5421
5422   /* dropped buffer */
5423 wrong_type:
5424   {
5425     GST_DEBUG_OBJECT (qtdemux, "unknown stream type");
5426     return buf;
5427   }
5428 bad_frame_size:
5429   {
5430     GST_DEBUG_OBJECT (qtdemux, "bad frame size");
5431     return buf;
5432   }
5433 no_pts:
5434   {
5435     GST_DEBUG_OBJECT (qtdemux, "no pts on buffer");
5436     return buf;
5437   }
5438 clipped:
5439   {
5440     GST_DEBUG_OBJECT (qtdemux, "clipped buffer");
5441     gst_buffer_unref (buf);
5442     return NULL;
5443   }
5444 }
5445
5446 static GstBuffer *
5447 gst_qtdemux_align_buffer (GstQTDemux * demux,
5448     GstBuffer * buffer, gsize alignment)
5449 {
5450   GstMapInfo map;
5451
5452   gst_buffer_map (buffer, &map, GST_MAP_READ);
5453
5454   if (map.size < sizeof (guintptr)) {
5455     gst_buffer_unmap (buffer, &map);
5456     return buffer;
5457   }
5458
5459   if (((guintptr) map.data) & (alignment - 1)) {
5460     GstBuffer *new_buffer;
5461     GstAllocationParams params = { 0, alignment - 1, 0, 0, };
5462
5463     new_buffer = gst_buffer_new_allocate (NULL,
5464         gst_buffer_get_size (buffer), &params);
5465
5466     /* Copy data "by hand", so ensure alignment is kept: */
5467     gst_buffer_fill (new_buffer, 0, map.data, map.size);
5468
5469     gst_buffer_copy_into (new_buffer, buffer, GST_BUFFER_COPY_METADATA, 0, -1);
5470     GST_DEBUG_OBJECT (demux,
5471         "We want output aligned on %" G_GSIZE_FORMAT ", reallocated",
5472         alignment);
5473
5474     gst_buffer_unmap (buffer, &map);
5475     gst_buffer_unref (buffer);
5476
5477     return new_buffer;
5478   }
5479
5480   gst_buffer_unmap (buffer, &map);
5481   return buffer;
5482 }
5483
5484 static guint8 *
5485 convert_to_ccdata (const guint8 * ccpair, guint8 ccpair_size, guint field,
5486     gsize * res)
5487 {
5488   guint8 *storage;
5489   gsize i;
5490
5491   /* We are converting from pairs to triplets */
5492   *res = ccpair_size / 2 * 3;
5493   storage = g_malloc (*res);
5494   for (i = 0; i * 2 < ccpair_size; i += 1) {
5495     if (field == 1)
5496       storage[i * 3] = 0xfc;
5497     else
5498       storage[i * 3] = 0xfd;
5499     storage[i * 3 + 1] = ccpair[i * 2];
5500     storage[i * 3 + 2] = ccpair[i * 2 + 1];
5501   }
5502
5503   return storage;
5504 }
5505
5506 static guint8 *
5507 extract_cc_from_data (QtDemuxStream * stream, const guint8 * data, gsize size,
5508     gsize * cclen)
5509 {
5510   guint8 *res = NULL;
5511   guint32 atom_length, fourcc;
5512   QtDemuxStreamStsdEntry *stsd_entry;
5513
5514   GST_MEMDUMP ("caption atom", data, size);
5515
5516   /* There might be multiple atoms */
5517
5518   *cclen = 0;
5519   if (size < 8)
5520     goto invalid_cdat;
5521   atom_length = QT_UINT32 (data);
5522   fourcc = QT_FOURCC (data + 4);
5523   if (G_UNLIKELY (atom_length > size || atom_length == 8))
5524     goto invalid_cdat;
5525
5526   GST_DEBUG_OBJECT (stream->pad, "here");
5527
5528   /* Check if we have somethig compatible */
5529   stsd_entry = CUR_STREAM (stream);
5530   switch (stsd_entry->fourcc) {
5531     case FOURCC_c608:{
5532       guint8 *cdat = NULL, *cdt2 = NULL;
5533       gsize cdat_size = 0, cdt2_size = 0;
5534       /* Should be cdat or cdt2 */
5535       if (fourcc != FOURCC_cdat && fourcc != FOURCC_cdt2) {
5536         GST_WARNING_OBJECT (stream->pad,
5537             "Unknown data atom (%" GST_FOURCC_FORMAT ") for CEA608",
5538             GST_FOURCC_ARGS (fourcc));
5539         goto invalid_cdat;
5540       }
5541
5542       /* Convert to cc_data triplet */
5543       if (fourcc == FOURCC_cdat)
5544         cdat = convert_to_ccdata (data + 8, atom_length - 8, 1, &cdat_size);
5545       else
5546         cdt2 = convert_to_ccdata (data + 8, atom_length - 8, 2, &cdt2_size);
5547       GST_DEBUG_OBJECT (stream->pad, "size:%" G_GSIZE_FORMAT " atom_length:%u",
5548           size, atom_length);
5549
5550       /* Check for another atom ? */
5551       if (size > atom_length + 8) {
5552         guint32 new_atom_length = QT_UINT32 (data + atom_length);
5553         if (size >= atom_length + new_atom_length) {
5554           fourcc = QT_FOURCC (data + atom_length + 4);
5555           if (fourcc == FOURCC_cdat) {
5556             if (cdat == NULL)
5557               cdat =
5558                   convert_to_ccdata (data + atom_length + 8,
5559                   new_atom_length - 8, 1, &cdat_size);
5560             else
5561               GST_WARNING_OBJECT (stream->pad,
5562                   "Got multiple [cdat] atoms in a c608 sample. This is unsupported for now. Please file a bug");
5563           } else {
5564             if (cdt2 == NULL)
5565               cdt2 =
5566                   convert_to_ccdata (data + atom_length + 8,
5567                   new_atom_length - 8, 2, &cdt2_size);
5568             else
5569               GST_WARNING_OBJECT (stream->pad,
5570                   "Got multiple [cdt2] atoms in a c608 sample. This is unsupported for now. Please file a bug");
5571           }
5572         }
5573       }
5574
5575       *cclen = cdat_size + cdt2_size;
5576       res = g_malloc (*cclen);
5577       if (cdat_size)
5578         memcpy (res, cdat, cdat_size);
5579       if (cdt2_size)
5580         memcpy (res + cdat_size, cdt2, cdt2_size);
5581       g_free (cdat);
5582       g_free (cdt2);
5583     }
5584       break;
5585     case FOURCC_c708:
5586       if (fourcc != FOURCC_ccdp) {
5587         GST_WARNING_OBJECT (stream->pad,
5588             "Unknown data atom (%" GST_FOURCC_FORMAT ") for CEA708",
5589             GST_FOURCC_ARGS (fourcc));
5590         goto invalid_cdat;
5591       }
5592       *cclen = atom_length - 8;
5593       res = g_memdup (data + 8, *cclen);
5594       break;
5595     default:
5596       /* Keep this here in case other closed caption formats are added */
5597       g_assert_not_reached ();
5598       break;
5599   }
5600
5601   GST_MEMDUMP ("Output", res, *cclen);
5602   return res;
5603
5604   /* Errors */
5605 invalid_cdat:
5606   GST_WARNING ("[cdat] atom is too small or invalid");
5607   return NULL;
5608 }
5609
5610 /* the input buffer metadata must be writable,
5611  * but time/duration etc not yet set and need not be preserved */
5612 static GstBuffer *
5613 gst_qtdemux_process_buffer (GstQTDemux * qtdemux, QtDemuxStream * stream,
5614     GstBuffer * buf)
5615 {
5616   GstMapInfo map;
5617   guint nsize = 0;
5618   gchar *str;
5619
5620   /* not many cases for now */
5621   if (G_UNLIKELY (CUR_STREAM (stream)->fourcc == FOURCC_mp4s)) {
5622     /* send a one time dvd clut event */
5623     if (stream->pending_event && stream->pad)
5624       gst_pad_push_event (stream->pad, stream->pending_event);
5625     stream->pending_event = NULL;
5626   }
5627
5628   if (G_UNLIKELY (stream->subtype != FOURCC_text
5629           && stream->subtype != FOURCC_sbtl &&
5630           stream->subtype != FOURCC_subp && stream->subtype != FOURCC_clcp)) {
5631     return buf;
5632   }
5633
5634   gst_buffer_map (buf, &map, GST_MAP_READ);
5635
5636   /* empty buffer is sent to terminate previous subtitle */
5637   if (map.size <= 2) {
5638     gst_buffer_unmap (buf, &map);
5639     gst_buffer_unref (buf);
5640     return NULL;
5641   }
5642   if (stream->subtype == FOURCC_subp) {
5643     /* That's all the processing needed for subpictures */
5644     gst_buffer_unmap (buf, &map);
5645     return buf;
5646   }
5647
5648   if (stream->subtype == FOURCC_clcp) {
5649     guint8 *cc;
5650     gsize cclen = 0;
5651     /* For closed caption, we need to extract the information from the
5652      * [cdat],[cdt2] or [ccdp] atom */
5653     cc = extract_cc_from_data (stream, map.data, map.size, &cclen);
5654     gst_buffer_unmap (buf, &map);
5655     gst_buffer_unref (buf);
5656     if (cc) {
5657       buf = _gst_buffer_new_wrapped (cc, cclen, g_free);
5658     } else {
5659       /* Conversion failed or there's nothing */
5660       buf = NULL;
5661     }
5662     return buf;
5663   }
5664
5665   nsize = GST_READ_UINT16_BE (map.data);
5666   nsize = MIN (nsize, map.size - 2);
5667
5668   GST_LOG_OBJECT (qtdemux, "3GPP timed text subtitle: %d/%" G_GSIZE_FORMAT "",
5669       nsize, map.size);
5670
5671   /* takes care of UTF-8 validation or UTF-16 recognition,
5672    * no other encoding expected */
5673   str = gst_tag_freeform_string_to_utf8 ((gchar *) map.data + 2, nsize, NULL);
5674   gst_buffer_unmap (buf, &map);
5675   if (str) {
5676     gst_buffer_unref (buf);
5677     buf = _gst_buffer_new_wrapped (str, strlen (str), g_free);
5678   } else {
5679     /* this should not really happen unless the subtitle is corrupted */
5680     gst_buffer_unref (buf);
5681     buf = NULL;
5682   }
5683
5684   /* FIXME ? convert optional subsequent style info to markup */
5685
5686   return buf;
5687 }
5688
5689 /* Sets a buffer's attributes properly and pushes it downstream.
5690  * Also checks for additional actions and custom processing that may
5691  * need to be done first.
5692  */
5693 static GstFlowReturn
5694 gst_qtdemux_decorate_and_push_buffer (GstQTDemux * qtdemux,
5695     QtDemuxStream * stream, GstBuffer * buf,
5696     GstClockTime dts, GstClockTime pts, GstClockTime duration,
5697     gboolean keyframe, GstClockTime position, guint64 byte_position)
5698 {
5699   GstFlowReturn ret = GST_FLOW_OK;
5700
5701   /* offset the timestamps according to the edit list */
5702
5703   if (G_UNLIKELY (CUR_STREAM (stream)->fourcc == FOURCC_rtsp)) {
5704     gchar *url;
5705     GstMapInfo map;
5706
5707     gst_buffer_map (buf, &map, GST_MAP_READ);
5708     url = g_strndup ((gchar *) map.data, map.size);
5709     gst_buffer_unmap (buf, &map);
5710     if (url != NULL && strlen (url) != 0) {
5711       /* we have RTSP redirect now */
5712       gst_element_post_message (GST_ELEMENT_CAST (qtdemux),
5713           gst_message_new_element (GST_OBJECT_CAST (qtdemux),
5714               gst_structure_new ("redirect",
5715                   "new-location", G_TYPE_STRING, url, NULL)));
5716       qtdemux->posted_redirect = TRUE;
5717     } else {
5718       GST_WARNING_OBJECT (qtdemux, "Redirect URI of stream is empty, not "
5719           "posting");
5720     }
5721     g_free (url);
5722   }
5723
5724   /* position reporting */
5725   if (qtdemux->segment.rate >= 0) {
5726     qtdemux->segment.position = position;
5727     gst_qtdemux_sync_streams (qtdemux);
5728   }
5729
5730   if (G_UNLIKELY (!stream->pad)) {
5731     GST_DEBUG_OBJECT (qtdemux, "No output pad for stream, ignoring");
5732     gst_buffer_unref (buf);
5733     goto exit;
5734   }
5735
5736   /* send out pending buffers */
5737   while (stream->buffers) {
5738     GstBuffer *buffer = (GstBuffer *) stream->buffers->data;
5739
5740     if (G_UNLIKELY (stream->discont)) {
5741       GST_LOG_OBJECT (qtdemux, "marking discont buffer");
5742       GST_BUFFER_FLAG_SET (buffer, GST_BUFFER_FLAG_DISCONT);
5743       stream->discont = FALSE;
5744     } else {
5745       GST_BUFFER_FLAG_UNSET (buf, GST_BUFFER_FLAG_DISCONT);
5746     }
5747
5748     if (stream->alignment > 1)
5749       buffer = gst_qtdemux_align_buffer (qtdemux, buffer, stream->alignment);
5750     gst_pad_push (stream->pad, buffer);
5751
5752     stream->buffers = g_slist_delete_link (stream->buffers, stream->buffers);
5753   }
5754
5755   /* we're going to modify the metadata */
5756   buf = gst_buffer_make_writable (buf);
5757
5758   if (G_UNLIKELY (stream->need_process))
5759     buf = gst_qtdemux_process_buffer (qtdemux, stream, buf);
5760
5761   if (!buf) {
5762     goto exit;
5763   }
5764
5765   GST_BUFFER_DTS (buf) = dts;
5766   GST_BUFFER_PTS (buf) = pts;
5767   GST_BUFFER_DURATION (buf) = duration;
5768   GST_BUFFER_OFFSET (buf) = -1;
5769   GST_BUFFER_OFFSET_END (buf) = -1;
5770
5771   if (G_UNLIKELY (CUR_STREAM (stream)->rgb8_palette))
5772     gst_buffer_append_memory (buf,
5773         gst_memory_ref (CUR_STREAM (stream)->rgb8_palette));
5774
5775   if (G_UNLIKELY (CUR_STREAM (stream)->padding)) {
5776     gst_buffer_resize (buf, CUR_STREAM (stream)->padding, -1);
5777   }
5778 #if 0
5779   if (G_UNLIKELY (qtdemux->element_index)) {
5780     GstClockTime stream_time;
5781
5782     stream_time =
5783         gst_segment_to_stream_time (&stream->segment, GST_FORMAT_TIME,
5784         timestamp);
5785     if (GST_CLOCK_TIME_IS_VALID (stream_time)) {
5786       GST_LOG_OBJECT (qtdemux,
5787           "adding association %" GST_TIME_FORMAT "-> %"
5788           G_GUINT64_FORMAT, GST_TIME_ARGS (stream_time), byte_position);
5789       gst_index_add_association (qtdemux->element_index,
5790           qtdemux->index_id,
5791           keyframe ? GST_ASSOCIATION_FLAG_KEY_UNIT :
5792           GST_ASSOCIATION_FLAG_DELTA_UNIT, GST_FORMAT_TIME, stream_time,
5793           GST_FORMAT_BYTES, byte_position, NULL);
5794     }
5795   }
5796 #endif
5797
5798   if (stream->need_clip)
5799     buf = gst_qtdemux_clip_buffer (qtdemux, stream, buf);
5800
5801   if (G_UNLIKELY (buf == NULL))
5802     goto exit;
5803
5804   if (G_UNLIKELY (stream->discont)) {
5805     GST_LOG_OBJECT (qtdemux, "marking discont buffer");
5806     GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_DISCONT);
5807     stream->discont = FALSE;
5808   } else {
5809     GST_BUFFER_FLAG_UNSET (buf, GST_BUFFER_FLAG_DISCONT);
5810   }
5811
5812   if (!keyframe) {
5813     GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_DELTA_UNIT);
5814     stream->on_keyframe = FALSE;
5815   } else {
5816     stream->on_keyframe = TRUE;
5817   }
5818
5819
5820   GST_LOG_OBJECT (qtdemux,
5821       "Pushing buffer with dts %" GST_TIME_FORMAT ", pts %" GST_TIME_FORMAT
5822       ", duration %" GST_TIME_FORMAT " on pad %s", GST_TIME_ARGS (dts),
5823       GST_TIME_ARGS (pts), GST_TIME_ARGS (duration),
5824       GST_PAD_NAME (stream->pad));
5825
5826   if (stream->protected && stream->protection_scheme_type == FOURCC_cenc) {
5827     GstStructure *crypto_info;
5828     QtDemuxCencSampleSetInfo *info =
5829         (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
5830     gint index;
5831     GstEvent *event;
5832
5833     while ((event = g_queue_pop_head (&stream->protection_scheme_event_queue))) {
5834       GST_TRACE_OBJECT (stream->pad, "pushing protection event: %"
5835           GST_PTR_FORMAT, event);
5836       gst_pad_push_event (stream->pad, event);
5837     }
5838
5839     if (info->crypto_info == NULL) {
5840       GST_DEBUG_OBJECT (qtdemux,
5841           "cenc metadata hasn't been parsed yet, pushing buffer as if it wasn't encrypted");
5842     } else {
5843       /* The end of the crypto_info array matches our n_samples position,
5844        * so count backward from there */
5845       index = stream->sample_index - stream->n_samples + info->crypto_info->len;
5846       if (G_LIKELY (index >= 0 && index < info->crypto_info->len)) {
5847         /* steal structure from array */
5848         crypto_info = g_ptr_array_index (info->crypto_info, index);
5849         g_ptr_array_index (info->crypto_info, index) = NULL;
5850         GST_LOG_OBJECT (qtdemux, "attaching cenc metadata [%u/%u]", index,
5851             info->crypto_info->len);
5852         if (!crypto_info || !gst_buffer_add_protection_meta (buf, crypto_info))
5853           GST_ERROR_OBJECT (qtdemux,
5854               "failed to attach cenc metadata to buffer");
5855       } else {
5856         GST_INFO_OBJECT (qtdemux, "No crypto info with index %d and sample %d",
5857             index, stream->sample_index);
5858       }
5859     }
5860   }
5861
5862   if (stream->alignment > 1)
5863     buf = gst_qtdemux_align_buffer (qtdemux, buf, stream->alignment);
5864
5865   ret = gst_pad_push (stream->pad, buf);
5866
5867   if (GST_CLOCK_TIME_IS_VALID (pts) && GST_CLOCK_TIME_IS_VALID (duration)) {
5868     /* mark position in stream, we'll need this to know when to send GAP event */
5869     stream->segment.position = pts + duration;
5870   }
5871
5872 exit:
5873   return ret;
5874 }
5875
5876 static const QtDemuxRandomAccessEntry *
5877 gst_qtdemux_stream_seek_fragment (GstQTDemux * qtdemux, QtDemuxStream * stream,
5878     GstClockTime pos, gboolean after)
5879 {
5880   QtDemuxRandomAccessEntry *entries = stream->ra_entries;
5881   guint n_entries = stream->n_ra_entries;
5882   guint i;
5883
5884   /* we assume the table is sorted */
5885   for (i = 0; i < n_entries; ++i) {
5886     if (entries[i].ts > pos)
5887       break;
5888   }
5889
5890   /* FIXME: maybe save first moof_offset somewhere instead, but for now it's
5891    * probably okay to assume that the index lists the very first fragment */
5892   if (i == 0)
5893     return &entries[0];
5894
5895   if (after)
5896     return &entries[i];
5897   else
5898     return &entries[i - 1];
5899 }
5900
5901 static gboolean
5902 gst_qtdemux_do_fragmented_seek (GstQTDemux * qtdemux)
5903 {
5904   const QtDemuxRandomAccessEntry *best_entry = NULL;
5905   GList *iter;
5906
5907   GST_OBJECT_LOCK (qtdemux);
5908
5909   g_assert (qtdemux->n_streams > 0);
5910
5911   /* first see if we can determine where to go to using mfra,
5912    * before we start clearing things */
5913   for (iter = qtdemux->active_streams; iter; iter = g_list_next (iter)) {
5914     const QtDemuxRandomAccessEntry *entry;
5915     QtDemuxStream *stream;
5916     gboolean is_audio_or_video;
5917
5918     stream = QTDEMUX_STREAM (iter->data);
5919
5920     if (stream->ra_entries == NULL)
5921       continue;
5922
5923     if (stream->subtype == FOURCC_vide || stream->subtype == FOURCC_soun)
5924       is_audio_or_video = TRUE;
5925     else
5926       is_audio_or_video = FALSE;
5927
5928     entry =
5929         gst_qtdemux_stream_seek_fragment (qtdemux, stream,
5930         stream->time_position, !is_audio_or_video);
5931
5932     GST_INFO_OBJECT (stream->pad, "%" GST_TIME_FORMAT " at offset "
5933         "%" G_GUINT64_FORMAT, GST_TIME_ARGS (entry->ts), entry->moof_offset);
5934
5935     stream->pending_seek = entry;
5936
5937     /* decide position to jump to just based on audio/video tracks, not subs */
5938     if (!is_audio_or_video)
5939       continue;
5940
5941     if (best_entry == NULL || entry->moof_offset < best_entry->moof_offset)
5942       best_entry = entry;
5943   }
5944
5945   /* no luck, will handle seek otherwise */
5946   if (best_entry == NULL) {
5947     GST_OBJECT_UNLOCK (qtdemux);
5948     return FALSE;
5949   }
5950
5951   /* ok, now we can prepare for processing as of located moof */
5952   for (iter = qtdemux->active_streams; iter; iter = g_list_next (iter)) {
5953     QtDemuxStream *stream;
5954
5955     stream = QTDEMUX_STREAM (iter->data);
5956
5957     g_free (stream->samples);
5958     stream->samples = NULL;
5959     stream->n_samples = 0;
5960     stream->stbl_index = -1;    /* no samples have yet been parsed */
5961     stream->sample_index = -1;
5962
5963     if (stream->protection_scheme_info) {
5964       /* Clear out any old cenc crypto info entries as we'll move to a new moof */
5965       if (stream->protection_scheme_type == FOURCC_cenc) {
5966         QtDemuxCencSampleSetInfo *info =
5967             (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
5968         if (info->crypto_info) {
5969           g_ptr_array_free (info->crypto_info, TRUE);
5970           info->crypto_info = NULL;
5971         }
5972       }
5973     }
5974   }
5975
5976   GST_INFO_OBJECT (qtdemux, "seek to %" GST_TIME_FORMAT ", best fragment "
5977       "moof offset: %" G_GUINT64_FORMAT ", ts %" GST_TIME_FORMAT,
5978       GST_TIME_ARGS (QTDEMUX_FIRST_STREAM (qtdemux)->time_position),
5979       best_entry->moof_offset, GST_TIME_ARGS (best_entry->ts));
5980
5981   qtdemux->moof_offset = best_entry->moof_offset;
5982
5983   qtdemux_add_fragmented_samples (qtdemux);
5984
5985   GST_OBJECT_UNLOCK (qtdemux);
5986   return TRUE;
5987 }
5988
5989 static GstFlowReturn
5990 gst_qtdemux_loop_state_movie (GstQTDemux * qtdemux)
5991 {
5992   GstFlowReturn ret = GST_FLOW_OK;
5993   GstBuffer *buf = NULL;
5994   QtDemuxStream *stream, *target_stream = NULL;
5995   GstClockTime min_time;
5996   guint64 offset = 0;
5997   GstClockTime dts = GST_CLOCK_TIME_NONE;
5998   GstClockTime pts = GST_CLOCK_TIME_NONE;
5999   GstClockTime duration = 0;
6000   gboolean keyframe = FALSE;
6001   guint sample_size = 0;
6002   gboolean empty = 0;
6003   guint size;
6004   GList *iter;
6005
6006   if (qtdemux->fragmented_seek_pending) {
6007     GST_INFO_OBJECT (qtdemux, "pending fragmented seek");
6008     if (gst_qtdemux_do_fragmented_seek (qtdemux)) {
6009       GST_INFO_OBJECT (qtdemux, "fragmented seek done!");
6010       qtdemux->fragmented_seek_pending = FALSE;
6011     } else {
6012       GST_INFO_OBJECT (qtdemux, "fragmented seek still pending");
6013     }
6014   }
6015
6016   /* Figure out the next stream sample to output, min_time is expressed in
6017    * global time and runs over the edit list segments. */
6018   min_time = G_MAXUINT64;
6019   for (iter = qtdemux->active_streams; iter; iter = g_list_next (iter)) {
6020     GstClockTime position;
6021
6022     stream = QTDEMUX_STREAM (iter->data);
6023     position = stream->time_position;
6024
6025     /* position of -1 is EOS */
6026     if (position != GST_CLOCK_TIME_NONE && position < min_time) {
6027       min_time = position;
6028       target_stream = stream;
6029     }
6030   }
6031   /* all are EOS */
6032   if (G_UNLIKELY (target_stream == NULL)) {
6033     GST_DEBUG_OBJECT (qtdemux, "all streams are EOS");
6034     goto eos;
6035   }
6036
6037   /* check for segment end */
6038   if (G_UNLIKELY (qtdemux->segment.stop != -1
6039           && ((qtdemux->segment.rate >= 0 && qtdemux->segment.stop <= min_time)
6040               || (qtdemux->segment.rate < 0
6041                   && qtdemux->segment.start > min_time))
6042           && target_stream->on_keyframe)) {
6043     GST_DEBUG_OBJECT (qtdemux, "we reached the end of our segment.");
6044     target_stream->time_position = GST_CLOCK_TIME_NONE;
6045     goto eos_stream;
6046   }
6047
6048   /* gap events for subtitle streams */
6049   for (iter = qtdemux->active_streams; iter; iter = g_list_next (iter)) {
6050     stream = QTDEMUX_STREAM (iter->data);
6051     if (stream->pad && (stream->subtype == FOURCC_subp
6052             || stream->subtype == FOURCC_text
6053             || stream->subtype == FOURCC_sbtl)) {
6054       /* send one second gap events until the stream catches up */
6055       /* gaps can only be sent after segment is activated (segment.stop is no longer -1) */
6056       while (GST_CLOCK_TIME_IS_VALID (stream->segment.stop) &&
6057           GST_CLOCK_TIME_IS_VALID (stream->segment.position) &&
6058           stream->segment.position + GST_SECOND < min_time) {
6059         GstEvent *gap =
6060             gst_event_new_gap (stream->segment.position, GST_SECOND);
6061         gst_pad_push_event (stream->pad, gap);
6062         stream->segment.position += GST_SECOND;
6063       }
6064     }
6065   }
6066
6067   stream = target_stream;
6068   /* fetch info for the current sample of this stream */
6069   if (G_UNLIKELY (!gst_qtdemux_prepare_current_sample (qtdemux, stream, &empty,
6070               &offset, &sample_size, &dts, &pts, &duration, &keyframe)))
6071     goto eos_stream;
6072
6073   gst_qtdemux_stream_check_and_change_stsd_index (qtdemux, stream);
6074   if (stream->new_caps) {
6075     gst_qtdemux_configure_stream (qtdemux, stream);
6076     qtdemux_do_allocation (qtdemux, stream);
6077   }
6078
6079   /* If we're doing a keyframe-only trickmode, only push keyframes on video streams */
6080   if (G_UNLIKELY (qtdemux->
6081           segment.flags & GST_SEGMENT_FLAG_TRICKMODE_KEY_UNITS)) {
6082     if (stream->subtype == FOURCC_vide && !keyframe) {
6083       GST_LOG_OBJECT (qtdemux, "Skipping non-keyframe on track-id %u",
6084           stream->track_id);
6085       goto next;
6086     }
6087   }
6088
6089   GST_DEBUG_OBJECT (qtdemux,
6090       "pushing from track-id %u, empty %d offset %" G_GUINT64_FORMAT
6091       ", size %d, dts=%" GST_TIME_FORMAT ", pts=%" GST_TIME_FORMAT
6092       ", duration %" GST_TIME_FORMAT, stream->track_id, empty, offset,
6093       sample_size, GST_TIME_ARGS (dts), GST_TIME_ARGS (pts),
6094       GST_TIME_ARGS (duration));
6095
6096   if (G_UNLIKELY (empty)) {
6097     /* empty segment, push a gap if there's a second or more
6098      * difference and move to the next one */
6099     if ((pts + duration - stream->segment.position) >= GST_SECOND)
6100       gst_pad_push_event (stream->pad, gst_event_new_gap (pts, duration));
6101     stream->segment.position = pts + duration;
6102     goto next;
6103   }
6104
6105   /* hmm, empty sample, skip and move to next sample */
6106   if (G_UNLIKELY (sample_size <= 0))
6107     goto next;
6108
6109   /* last pushed sample was out of boundary, goto next sample */
6110   if (G_UNLIKELY (GST_PAD_LAST_FLOW_RETURN (stream->pad) == GST_FLOW_EOS))
6111     goto next;
6112
6113   if (stream->max_buffer_size == 0 || sample_size <= stream->max_buffer_size) {
6114     size = sample_size;
6115   } else {
6116     GST_DEBUG_OBJECT (qtdemux,
6117         "size %d larger than stream max_buffer_size %d, trimming",
6118         sample_size, stream->max_buffer_size);
6119     size =
6120         MIN (sample_size - stream->offset_in_sample, stream->max_buffer_size);
6121   }
6122
6123   if (qtdemux->cenc_aux_info_offset > 0) {
6124     GstMapInfo map;
6125     GstByteReader br;
6126     GstBuffer *aux_info = NULL;
6127
6128     /* pull the data stored before the sample */
6129     ret =
6130         gst_qtdemux_pull_atom (qtdemux, qtdemux->offset,
6131         offset + stream->offset_in_sample - qtdemux->offset, &aux_info);
6132     if (G_UNLIKELY (ret != GST_FLOW_OK))
6133       goto beach;
6134     gst_buffer_map (aux_info, &map, GST_MAP_READ);
6135     GST_DEBUG_OBJECT (qtdemux, "parsing cenc auxiliary info");
6136     gst_byte_reader_init (&br, map.data + 8, map.size);
6137     if (!qtdemux_parse_cenc_aux_info (qtdemux, stream, &br,
6138             qtdemux->cenc_aux_info_sizes, qtdemux->cenc_aux_sample_count)) {
6139       GST_ERROR_OBJECT (qtdemux, "failed to parse cenc auxiliary info");
6140       gst_buffer_unmap (aux_info, &map);
6141       gst_buffer_unref (aux_info);
6142       ret = GST_FLOW_ERROR;
6143       goto beach;
6144     }
6145     gst_buffer_unmap (aux_info, &map);
6146     gst_buffer_unref (aux_info);
6147   }
6148
6149   GST_LOG_OBJECT (qtdemux, "reading %d bytes @ %" G_GUINT64_FORMAT, size,
6150       offset);
6151
6152   if (stream->use_allocator) {
6153     /* if we have a per-stream allocator, use it */
6154     buf = gst_buffer_new_allocate (stream->allocator, size, &stream->params);
6155   }
6156
6157   ret = gst_qtdemux_pull_atom (qtdemux, offset + stream->offset_in_sample,
6158       size, &buf);
6159   if (G_UNLIKELY (ret != GST_FLOW_OK))
6160     goto beach;
6161
6162   if (size != sample_size) {
6163     pts += gst_util_uint64_scale_int (GST_SECOND,
6164         stream->offset_in_sample / CUR_STREAM (stream)->bytes_per_frame,
6165         stream->timescale);
6166     dts +=
6167         gst_util_uint64_scale_int (GST_SECOND,
6168         stream->offset_in_sample / CUR_STREAM (stream)->bytes_per_frame,
6169         stream->timescale);
6170     duration =
6171         gst_util_uint64_scale_int (GST_SECOND,
6172         size / CUR_STREAM (stream)->bytes_per_frame, stream->timescale);
6173   }
6174
6175   ret = gst_qtdemux_decorate_and_push_buffer (qtdemux, stream, buf,
6176       dts, pts, duration, keyframe, min_time, offset);
6177
6178   if (size != sample_size) {
6179     QtDemuxSample *sample = &stream->samples[stream->sample_index];
6180     QtDemuxSegment *segment = &stream->segments[stream->segment_index];
6181
6182     GstClockTime time_position = QTSTREAMTIME_TO_GSTTIME (stream,
6183         sample->timestamp +
6184         stream->offset_in_sample / CUR_STREAM (stream)->bytes_per_frame);
6185     if (time_position >= segment->media_start) {
6186       /* inside the segment, update time_position, looks very familiar to
6187        * GStreamer segments, doesn't it? */
6188       stream->time_position = (time_position - segment->media_start) +
6189           segment->time;
6190     } else {
6191       /* not yet in segment, time does not yet increment. This means
6192        * that we are still prerolling keyframes to the decoder so it can
6193        * decode the first sample of the segment. */
6194       stream->time_position = segment->time;
6195     }
6196   }
6197
6198   /* combine flows */
6199   ret = gst_qtdemux_combine_flows (qtdemux, stream, ret);
6200   /* ignore unlinked, we will not push on the pad anymore and we will EOS when
6201    * we have no more data for the pad to push */
6202   if (ret == GST_FLOW_EOS)
6203     ret = GST_FLOW_OK;
6204
6205   stream->offset_in_sample += size;
6206   if (stream->offset_in_sample >= sample_size) {
6207     gst_qtdemux_advance_sample (qtdemux, stream);
6208   }
6209   goto beach;
6210
6211 next:
6212   gst_qtdemux_advance_sample (qtdemux, stream);
6213
6214 beach:
6215   return ret;
6216
6217   /* special cases */
6218 eos:
6219   {
6220     GST_DEBUG_OBJECT (qtdemux, "No samples left for any streams - EOS");
6221     ret = GST_FLOW_EOS;
6222     goto beach;
6223   }
6224 eos_stream:
6225   {
6226     GST_DEBUG_OBJECT (qtdemux, "No samples left for stream");
6227     /* EOS will be raised if all are EOS */
6228     ret = GST_FLOW_OK;
6229     goto beach;
6230   }
6231 }
6232
6233 static void
6234 gst_qtdemux_loop (GstPad * pad)
6235 {
6236   GstQTDemux *qtdemux;
6237   guint64 cur_offset;
6238   GstFlowReturn ret;
6239
6240   qtdemux = GST_QTDEMUX (gst_pad_get_parent (pad));
6241
6242   cur_offset = qtdemux->offset;
6243   GST_LOG_OBJECT (qtdemux, "loop at position %" G_GUINT64_FORMAT ", state %s",
6244       cur_offset, qt_demux_state_string (qtdemux->state));
6245
6246   switch (qtdemux->state) {
6247     case QTDEMUX_STATE_INITIAL:
6248     case QTDEMUX_STATE_HEADER:
6249       ret = gst_qtdemux_loop_state_header (qtdemux);
6250       break;
6251     case QTDEMUX_STATE_MOVIE:
6252       ret = gst_qtdemux_loop_state_movie (qtdemux);
6253       if (qtdemux->segment.rate < 0 && ret == GST_FLOW_EOS) {
6254         ret = gst_qtdemux_seek_to_previous_keyframe (qtdemux);
6255       }
6256       break;
6257     default:
6258       /* ouch */
6259       goto invalid_state;
6260   }
6261
6262   /* if something went wrong, pause */
6263   if (ret != GST_FLOW_OK)
6264     goto pause;
6265
6266 done:
6267   gst_object_unref (qtdemux);
6268   return;
6269
6270   /* ERRORS */
6271 invalid_state:
6272   {
6273     GST_ELEMENT_ERROR (qtdemux, STREAM, FAILED,
6274         (NULL), ("streaming stopped, invalid state"));
6275     gst_pad_pause_task (pad);
6276     gst_qtdemux_push_event (qtdemux, gst_event_new_eos ());
6277     goto done;
6278   }
6279 pause:
6280   {
6281     const gchar *reason = gst_flow_get_name (ret);
6282
6283     GST_LOG_OBJECT (qtdemux, "pausing task, reason %s", reason);
6284
6285     gst_pad_pause_task (pad);
6286
6287     /* fatal errors need special actions */
6288     /* check EOS */
6289     if (ret == GST_FLOW_EOS) {
6290       if (qtdemux->n_streams == 0) {
6291         /* we have no streams, post an error */
6292         gst_qtdemux_post_no_playable_stream_error (qtdemux);
6293       }
6294       if (qtdemux->segment.flags & GST_SEEK_FLAG_SEGMENT) {
6295         gint64 stop;
6296
6297         if ((stop = qtdemux->segment.stop) == -1)
6298           stop = qtdemux->segment.duration;
6299
6300         if (qtdemux->segment.rate >= 0) {
6301           GstMessage *message;
6302           GstEvent *event;
6303
6304           GST_LOG_OBJECT (qtdemux, "Sending segment done, at end of segment");
6305           message = gst_message_new_segment_done (GST_OBJECT_CAST (qtdemux),
6306               GST_FORMAT_TIME, stop);
6307           event = gst_event_new_segment_done (GST_FORMAT_TIME, stop);
6308           if (qtdemux->segment_seqnum != GST_SEQNUM_INVALID) {
6309             gst_message_set_seqnum (message, qtdemux->segment_seqnum);
6310             gst_event_set_seqnum (event, qtdemux->segment_seqnum);
6311           }
6312           gst_element_post_message (GST_ELEMENT_CAST (qtdemux), message);
6313           gst_qtdemux_push_event (qtdemux, event);
6314         } else {
6315           GstMessage *message;
6316           GstEvent *event;
6317
6318           /*  For Reverse Playback */
6319           GST_LOG_OBJECT (qtdemux, "Sending segment done, at start of segment");
6320           message = gst_message_new_segment_done (GST_OBJECT_CAST (qtdemux),
6321               GST_FORMAT_TIME, qtdemux->segment.start);
6322           event = gst_event_new_segment_done (GST_FORMAT_TIME,
6323               qtdemux->segment.start);
6324           if (qtdemux->segment_seqnum != GST_SEQNUM_INVALID) {
6325             gst_message_set_seqnum (message, qtdemux->segment_seqnum);
6326             gst_event_set_seqnum (event, qtdemux->segment_seqnum);
6327           }
6328           gst_element_post_message (GST_ELEMENT_CAST (qtdemux), message);
6329           gst_qtdemux_push_event (qtdemux, event);
6330         }
6331       } else {
6332         GstEvent *event;
6333
6334         GST_LOG_OBJECT (qtdemux, "Sending EOS at end of segment");
6335         event = gst_event_new_eos ();
6336         if (qtdemux->segment_seqnum != GST_SEQNUM_INVALID)
6337           gst_event_set_seqnum (event, qtdemux->segment_seqnum);
6338         gst_qtdemux_push_event (qtdemux, event);
6339       }
6340     } else if (ret == GST_FLOW_NOT_LINKED || ret < GST_FLOW_EOS) {
6341       GST_ELEMENT_FLOW_ERROR (qtdemux, ret);
6342       gst_qtdemux_push_event (qtdemux, gst_event_new_eos ());
6343     }
6344     goto done;
6345   }
6346 }
6347
6348 /*
6349  * has_next_entry
6350  *
6351  * Returns if there are samples to be played.
6352  */
6353 static gboolean
6354 has_next_entry (GstQTDemux * demux)
6355 {
6356   QtDemuxStream *stream;
6357   GList *iter;
6358
6359   GST_DEBUG_OBJECT (demux, "Checking if there are samples not played yet");
6360
6361   for (iter = demux->active_streams; iter; iter = g_list_next (iter)) {
6362     stream = QTDEMUX_STREAM (iter->data);
6363
6364     if (stream->sample_index == -1) {
6365       stream->sample_index = 0;
6366       stream->offset_in_sample = 0;
6367     }
6368
6369     if (stream->sample_index >= stream->n_samples) {
6370       GST_LOG_OBJECT (demux, "track-id %u samples exhausted", stream->track_id);
6371       continue;
6372     }
6373     GST_DEBUG_OBJECT (demux, "Found a sample");
6374     return TRUE;
6375   }
6376
6377   GST_DEBUG_OBJECT (demux, "There wasn't any next sample");
6378   return FALSE;
6379 }
6380
6381 /*
6382  * next_entry_size
6383  *
6384  * Returns the size of the first entry at the current offset.
6385  * If -1, there are none (which means EOS or empty file).
6386  */
6387 static guint64
6388 next_entry_size (GstQTDemux * demux)
6389 {
6390   QtDemuxStream *stream, *target_stream = NULL;
6391   guint64 smalloffs = (guint64) - 1;
6392   QtDemuxSample *sample;
6393   GList *iter;
6394
6395   GST_LOG_OBJECT (demux, "Finding entry at offset %" G_GUINT64_FORMAT,
6396       demux->offset);
6397
6398   for (iter = demux->active_streams; iter; iter = g_list_next (iter)) {
6399     stream = QTDEMUX_STREAM (iter->data);
6400
6401     if (stream->sample_index == -1) {
6402       stream->sample_index = 0;
6403       stream->offset_in_sample = 0;
6404     }
6405
6406     if (stream->sample_index >= stream->n_samples) {
6407       GST_LOG_OBJECT (demux, "track-id %u samples exhausted", stream->track_id);
6408       continue;
6409     }
6410
6411     if (!qtdemux_parse_samples (demux, stream, stream->sample_index)) {
6412       GST_LOG_OBJECT (demux, "Parsing of index %u from stbl atom failed!",
6413           stream->sample_index);
6414       return -1;
6415     }
6416
6417     sample = &stream->samples[stream->sample_index];
6418
6419     GST_LOG_OBJECT (demux,
6420         "Checking track-id %u (sample_index:%d / offset:%" G_GUINT64_FORMAT
6421         " / size:%" G_GUINT32_FORMAT ")", stream->track_id,
6422         stream->sample_index, sample->offset, sample->size);
6423
6424     if (((smalloffs == -1)
6425             || (sample->offset < smalloffs)) && (sample->size)) {
6426       smalloffs = sample->offset;
6427       target_stream = stream;
6428     }
6429   }
6430
6431   if (!target_stream)
6432     return -1;
6433
6434   GST_LOG_OBJECT (demux,
6435       "track-id %u offset %" G_GUINT64_FORMAT " demux->offset :%"
6436       G_GUINT64_FORMAT, target_stream->track_id, smalloffs, demux->offset);
6437
6438   stream = target_stream;
6439   sample = &stream->samples[stream->sample_index];
6440
6441   if (sample->offset >= demux->offset) {
6442     demux->todrop = sample->offset - demux->offset;
6443     return sample->size + demux->todrop;
6444   }
6445
6446   GST_DEBUG_OBJECT (demux,
6447       "There wasn't any entry at offset %" G_GUINT64_FORMAT, demux->offset);
6448   return -1;
6449 }
6450
6451 static void
6452 gst_qtdemux_post_progress (GstQTDemux * demux, gint num, gint denom)
6453 {
6454   gint perc = (gint) ((gdouble) num * 100.0 / (gdouble) denom);
6455
6456   gst_element_post_message (GST_ELEMENT_CAST (demux),
6457       gst_message_new_element (GST_OBJECT_CAST (demux),
6458           gst_structure_new ("progress", "percent", G_TYPE_INT, perc, NULL)));
6459 }
6460
6461 static gboolean
6462 qtdemux_seek_offset (GstQTDemux * demux, guint64 offset)
6463 {
6464   GstEvent *event;
6465   gboolean res = 0;
6466
6467   GST_DEBUG_OBJECT (demux, "Seeking to %" G_GUINT64_FORMAT, offset);
6468
6469   event =
6470       gst_event_new_seek (1.0, GST_FORMAT_BYTES,
6471       GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_ACCURATE, GST_SEEK_TYPE_SET, offset,
6472       GST_SEEK_TYPE_NONE, -1);
6473
6474   /* store seqnum to drop flush events, they don't need to reach downstream */
6475   demux->offset_seek_seqnum = gst_event_get_seqnum (event);
6476   res = gst_pad_push_event (demux->sinkpad, event);
6477   demux->offset_seek_seqnum = GST_SEQNUM_INVALID;
6478
6479   return res;
6480 }
6481
6482 /* check for seekable upstream, above and beyond a mere query */
6483 static void
6484 gst_qtdemux_check_seekability (GstQTDemux * demux)
6485 {
6486   GstQuery *query;
6487   gboolean seekable = FALSE;
6488   gint64 start = -1, stop = -1;
6489
6490   if (demux->upstream_size)
6491     return;
6492
6493   if (demux->upstream_format_is_time)
6494     return;
6495
6496   query = gst_query_new_seeking (GST_FORMAT_BYTES);
6497   if (!gst_pad_peer_query (demux->sinkpad, query)) {
6498     GST_DEBUG_OBJECT (demux, "seeking query failed");
6499     goto done;
6500   }
6501
6502   gst_query_parse_seeking (query, NULL, &seekable, &start, &stop);
6503
6504   /* try harder to query upstream size if we didn't get it the first time */
6505   if (seekable && stop == -1) {
6506     GST_DEBUG_OBJECT (demux, "doing duration query to fix up unset stop");
6507     gst_pad_peer_query_duration (demux->sinkpad, GST_FORMAT_BYTES, &stop);
6508   }
6509
6510   /* if upstream doesn't know the size, it's likely that it's not seekable in
6511    * practice even if it technically may be seekable */
6512   if (seekable && (start != 0 || stop <= start)) {
6513     GST_DEBUG_OBJECT (demux, "seekable but unknown start/stop -> disable");
6514     seekable = FALSE;
6515   }
6516
6517 done:
6518   gst_query_unref (query);
6519
6520   GST_DEBUG_OBJECT (demux, "seekable: %d (%" G_GUINT64_FORMAT " - %"
6521       G_GUINT64_FORMAT ")", seekable, start, stop);
6522   demux->upstream_seekable = seekable;
6523   demux->upstream_size = seekable ? stop : -1;
6524 }
6525
6526 static void
6527 gst_qtdemux_drop_data (GstQTDemux * demux, gint bytes)
6528 {
6529   g_return_if_fail (bytes <= demux->todrop);
6530
6531   GST_LOG_OBJECT (demux, "Dropping %d bytes", bytes);
6532   gst_adapter_flush (demux->adapter, bytes);
6533   demux->neededbytes -= bytes;
6534   demux->offset += bytes;
6535   demux->todrop -= bytes;
6536 }
6537
6538 /* PUSH-MODE only: Send a segment, if not done already. */
6539 static void
6540 gst_qtdemux_check_send_pending_segment (GstQTDemux * demux)
6541 {
6542   if (G_UNLIKELY (demux->need_segment)) {
6543     gint i;
6544     GList *iter;
6545
6546     if (!demux->upstream_format_is_time) {
6547       gst_qtdemux_map_and_push_segments (demux, &demux->segment);
6548     } else {
6549       GstEvent *segment_event;
6550       segment_event = gst_event_new_segment (&demux->segment);
6551       if (demux->segment_seqnum != GST_SEQNUM_INVALID)
6552         gst_event_set_seqnum (segment_event, demux->segment_seqnum);
6553       gst_qtdemux_push_event (demux, segment_event);
6554     }
6555
6556     demux->need_segment = FALSE;
6557
6558     /* clear to send tags on all streams */
6559     for (iter = demux->active_streams, i = 0; iter;
6560         iter = g_list_next (iter), i++) {
6561       QtDemuxStream *stream = QTDEMUX_STREAM (iter->data);
6562       gst_qtdemux_push_tags (demux, stream);
6563       if (CUR_STREAM (stream)->sparse) {
6564         GST_INFO_OBJECT (demux, "Sending gap event on stream %d", i);
6565         gst_pad_push_event (stream->pad,
6566             gst_event_new_gap (stream->segment.position, GST_CLOCK_TIME_NONE));
6567       }
6568     }
6569   }
6570 }
6571
6572 /* Used for push mode only. */
6573 static void
6574 gst_qtdemux_send_gap_for_segment (GstQTDemux * demux,
6575     QtDemuxStream * stream, gint segment_index, GstClockTime pos)
6576 {
6577   GstClockTime ts, dur;
6578
6579   ts = pos;
6580   dur =
6581       stream->segments[segment_index].duration - (pos -
6582       stream->segments[segment_index].time);
6583   stream->time_position += dur;
6584
6585   /* Only gaps with a duration of at least one second are propagated.
6586    * Same workaround as in pull mode.
6587    * (See 2e45926a96ec5298c6ef29bf912e5e6a06dc3e0e) */
6588   if (dur >= GST_SECOND) {
6589     GstEvent *gap;
6590     gap = gst_event_new_gap (ts, dur);
6591
6592     GST_DEBUG_OBJECT (stream->pad, "Pushing gap for empty "
6593         "segment: %" GST_PTR_FORMAT, gap);
6594     gst_pad_push_event (stream->pad, gap);
6595   }
6596 }
6597
6598 static GstFlowReturn
6599 gst_qtdemux_chain (GstPad * sinkpad, GstObject * parent, GstBuffer * inbuf)
6600 {
6601   GstQTDemux *demux;
6602
6603   demux = GST_QTDEMUX (parent);
6604
6605   GST_DEBUG_OBJECT (demux,
6606       "Received buffer pts:%" GST_TIME_FORMAT " dts:%" GST_TIME_FORMAT
6607       " offset:%" G_GUINT64_FORMAT " size:%" G_GSIZE_FORMAT " demux offset:%"
6608       G_GUINT64_FORMAT, GST_TIME_ARGS (GST_BUFFER_PTS (inbuf)),
6609       GST_TIME_ARGS (GST_BUFFER_DTS (inbuf)), GST_BUFFER_OFFSET (inbuf),
6610       gst_buffer_get_size (inbuf), demux->offset);
6611
6612   if (GST_BUFFER_FLAG_IS_SET (inbuf, GST_BUFFER_FLAG_DISCONT)) {
6613     gboolean is_gap_input = FALSE;
6614     GList *iter;
6615
6616     GST_DEBUG_OBJECT (demux, "Got DISCONT, marking all streams as DISCONT");
6617
6618     for (iter = demux->active_streams; iter; iter = g_list_next (iter)) {
6619       QTDEMUX_STREAM (iter->data)->discont = TRUE;
6620     }
6621
6622     /* Check if we can land back on our feet in the case where upstream is
6623      * handling the seeking/pushing of samples with gaps in between (like
6624      * in the case of trick-mode DASH for example) */
6625     if (demux->upstream_format_is_time
6626         && GST_BUFFER_OFFSET (inbuf) != GST_BUFFER_OFFSET_NONE) {
6627       for (iter = demux->active_streams; iter; iter = g_list_next (iter)) {
6628         guint32 res;
6629         QtDemuxStream *stream = QTDEMUX_STREAM (iter->data);
6630         GST_LOG_OBJECT (demux,
6631             "track-id #%u , checking if offset %" G_GUINT64_FORMAT
6632             " is a sample start", stream->track_id, GST_BUFFER_OFFSET (inbuf));
6633         res =
6634             gst_qtdemux_find_index_for_given_media_offset_linear (demux,
6635             stream, GST_BUFFER_OFFSET (inbuf));
6636         if (res != -1) {
6637           QtDemuxSample *sample = &stream->samples[res];
6638           GST_LOG_OBJECT (demux,
6639               "Checking if sample %d from track-id %u is valid (offset:%"
6640               G_GUINT64_FORMAT " size:%" G_GUINT32_FORMAT ")", res,
6641               stream->track_id, sample->offset, sample->size);
6642           if (sample->offset == GST_BUFFER_OFFSET (inbuf)) {
6643             GST_LOG_OBJECT (demux,
6644                 "new buffer corresponds to a valid sample : %" G_GUINT32_FORMAT,
6645                 res);
6646             is_gap_input = TRUE;
6647             /* We can go back to standard playback mode */
6648             demux->state = QTDEMUX_STATE_MOVIE;
6649             /* Remember which sample this stream is at */
6650             stream->sample_index = res;
6651             /* Finally update all push-based values to the expected values */
6652             demux->neededbytes = stream->samples[res].size;
6653             demux->offset = GST_BUFFER_OFFSET (inbuf);
6654             demux->mdatleft =
6655                 demux->mdatsize - demux->offset + demux->mdatoffset;
6656             demux->todrop = 0;
6657           }
6658         }
6659       }
6660       if (!is_gap_input) {
6661         GST_DEBUG_OBJECT (demux, "Resetting, actual DISCONT");
6662         /* Reset state if it's a real discont */
6663         demux->neededbytes = 16;
6664         demux->state = QTDEMUX_STATE_INITIAL;
6665         demux->offset = GST_BUFFER_OFFSET (inbuf);
6666         gst_adapter_clear (demux->adapter);
6667       }
6668     }
6669     /* Reverse fragmented playback, need to flush all we have before
6670      * consuming a new fragment.
6671      * The samples array have the timestamps calculated by accumulating the
6672      * durations but this won't work for reverse playback of fragments as
6673      * the timestamps of a subsequent fragment should be smaller than the
6674      * previously received one. */
6675     if (!is_gap_input && demux->fragmented && demux->segment.rate < 0) {
6676       gst_qtdemux_process_adapter (demux, TRUE);
6677       g_list_foreach (demux->active_streams,
6678           (GFunc) gst_qtdemux_stream_flush_samples_data, NULL);
6679     }
6680   }
6681
6682   gst_adapter_push (demux->adapter, inbuf);
6683
6684   GST_DEBUG_OBJECT (demux,
6685       "pushing in inbuf %p, neededbytes:%u, available:%" G_GSIZE_FORMAT, inbuf,
6686       demux->neededbytes, gst_adapter_available (demux->adapter));
6687
6688   return gst_qtdemux_process_adapter (demux, FALSE);
6689 }
6690
6691 static GstFlowReturn
6692 gst_qtdemux_process_adapter (GstQTDemux * demux, gboolean force)
6693 {
6694   GstFlowReturn ret = GST_FLOW_OK;
6695
6696   /* we never really mean to buffer that much */
6697   if (demux->neededbytes == -1) {
6698     goto eos;
6699   }
6700
6701   while (((gst_adapter_available (demux->adapter)) >= demux->neededbytes) &&
6702       (ret == GST_FLOW_OK || (ret == GST_FLOW_NOT_LINKED && force))) {
6703
6704 #ifndef GST_DISABLE_GST_DEBUG
6705     {
6706       guint64 discont_offset, distance_from_discont;
6707
6708       discont_offset = gst_adapter_offset_at_discont (demux->adapter);
6709       distance_from_discont =
6710           gst_adapter_distance_from_discont (demux->adapter);
6711
6712       GST_DEBUG_OBJECT (demux,
6713           "state:%s , demux->neededbytes:%d, demux->offset:%" G_GUINT64_FORMAT
6714           " adapter offset :%" G_GUINT64_FORMAT " (+ %" G_GUINT64_FORMAT
6715           " bytes)", qt_demux_state_string (demux->state), demux->neededbytes,
6716           demux->offset, discont_offset, distance_from_discont);
6717     }
6718 #endif
6719
6720     switch (demux->state) {
6721       case QTDEMUX_STATE_INITIAL:{
6722         const guint8 *data;
6723         guint32 fourcc;
6724         guint64 size;
6725
6726         gst_qtdemux_check_seekability (demux);
6727
6728         data = gst_adapter_map (demux->adapter, demux->neededbytes);
6729
6730         /* get fourcc/length, set neededbytes */
6731         extract_initial_length_and_fourcc ((guint8 *) data, demux->neededbytes,
6732             &size, &fourcc);
6733         gst_adapter_unmap (demux->adapter);
6734         data = NULL;
6735         GST_DEBUG_OBJECT (demux, "Peeking found [%" GST_FOURCC_FORMAT "] "
6736             "size: %" G_GUINT64_FORMAT, GST_FOURCC_ARGS (fourcc), size);
6737         if (size == 0) {
6738           GST_ELEMENT_ERROR (demux, STREAM, DEMUX,
6739               (_("This file is invalid and cannot be played.")),
6740               ("initial atom '%" GST_FOURCC_FORMAT "' has empty length",
6741                   GST_FOURCC_ARGS (fourcc)));
6742           ret = GST_FLOW_ERROR;
6743           break;
6744         }
6745         if (fourcc == FOURCC_mdat) {
6746           gint next_entry = next_entry_size (demux);
6747           if (demux->n_streams > 0 && (next_entry != -1 || !demux->fragmented)) {
6748             /* we have the headers, start playback */
6749             demux->state = QTDEMUX_STATE_MOVIE;
6750             demux->neededbytes = next_entry;
6751             demux->mdatleft = size;
6752             demux->mdatsize = demux->mdatleft;
6753           } else {
6754             /* no headers yet, try to get them */
6755             guint bs;
6756             gboolean res;
6757             guint64 old, target;
6758
6759           buffer_data:
6760             old = demux->offset;
6761             target = old + size;
6762
6763             /* try to jump over the atom with a seek */
6764             /* only bother if it seems worth doing so,
6765              * and avoids possible upstream/server problems */
6766             if (demux->upstream_seekable &&
6767                 demux->upstream_size > 4 * (1 << 20)) {
6768               res = qtdemux_seek_offset (demux, target);
6769             } else {
6770               GST_DEBUG_OBJECT (demux, "skipping seek");
6771               res = FALSE;
6772             }
6773
6774             if (res) {
6775               GST_DEBUG_OBJECT (demux, "seek success");
6776               /* remember the offset fo the first mdat so we can seek back to it
6777                * after we have the headers */
6778               if (fourcc == FOURCC_mdat && demux->first_mdat == -1) {
6779                 demux->first_mdat = old;
6780                 GST_DEBUG_OBJECT (demux, "first mdat at %" G_GUINT64_FORMAT,
6781                     demux->first_mdat);
6782               }
6783               /* seek worked, continue reading */
6784               demux->offset = target;
6785               demux->neededbytes = 16;
6786               demux->state = QTDEMUX_STATE_INITIAL;
6787             } else {
6788               /* seek failed, need to buffer */
6789               demux->offset = old;
6790               GST_DEBUG_OBJECT (demux, "seek failed/skipped");
6791               /* there may be multiple mdat (or alike) buffers */
6792               /* sanity check */
6793               if (demux->mdatbuffer)
6794                 bs = gst_buffer_get_size (demux->mdatbuffer);
6795               else
6796                 bs = 0;
6797               if (size + bs > 10 * (1 << 20))
6798                 goto no_moov;
6799               demux->state = QTDEMUX_STATE_BUFFER_MDAT;
6800               demux->neededbytes = size;
6801               if (!demux->mdatbuffer)
6802                 demux->mdatoffset = demux->offset;
6803             }
6804           }
6805         } else if (G_UNLIKELY (size > QTDEMUX_MAX_ATOM_SIZE)) {
6806           GST_ELEMENT_ERROR (demux, STREAM, DEMUX,
6807               (_("This file is invalid and cannot be played.")),
6808               ("atom %" GST_FOURCC_FORMAT " has bogus size %" G_GUINT64_FORMAT,
6809                   GST_FOURCC_ARGS (fourcc), size));
6810           ret = GST_FLOW_ERROR;
6811           break;
6812         } else {
6813           /* this means we already started buffering and still no moov header,
6814            * let's continue buffering everything till we get moov */
6815           if (demux->mdatbuffer && !(fourcc == FOURCC_moov
6816                   || fourcc == FOURCC_moof))
6817             goto buffer_data;
6818           demux->neededbytes = size;
6819           demux->state = QTDEMUX_STATE_HEADER;
6820         }
6821         break;
6822       }
6823       case QTDEMUX_STATE_HEADER:{
6824         const guint8 *data;
6825         guint32 fourcc;
6826
6827         GST_DEBUG_OBJECT (demux, "In header");
6828
6829         data = gst_adapter_map (demux->adapter, demux->neededbytes);
6830
6831         /* parse the header */
6832         extract_initial_length_and_fourcc (data, demux->neededbytes, NULL,
6833             &fourcc);
6834         if (fourcc == FOURCC_moov) {
6835           /* in usual fragmented setup we could try to scan for more
6836            * and end up at the the moov (after mdat) again */
6837           if (demux->got_moov && demux->n_streams > 0 &&
6838               (!demux->fragmented
6839                   || demux->last_moov_offset == demux->offset)) {
6840             GST_DEBUG_OBJECT (demux,
6841                 "Skipping moov atom as we have (this) one already");
6842           } else {
6843             GST_DEBUG_OBJECT (demux, "Parsing [moov]");
6844
6845             if (demux->got_moov && demux->fragmented) {
6846               GST_DEBUG_OBJECT (demux,
6847                   "Got a second moov, clean up data from old one");
6848               if (demux->moov_node_compressed) {
6849                 g_node_destroy (demux->moov_node_compressed);
6850                 if (demux->moov_node)
6851                   g_free (demux->moov_node->data);
6852               }
6853               demux->moov_node_compressed = NULL;
6854               if (demux->moov_node)
6855                 g_node_destroy (demux->moov_node);
6856               demux->moov_node = NULL;
6857             }
6858
6859             demux->last_moov_offset = demux->offset;
6860
6861             /* Update streams with new moov */
6862             demux->old_streams =
6863                 g_list_concat (demux->old_streams, demux->active_streams);
6864             demux->active_streams = NULL;
6865
6866             qtdemux_parse_moov (demux, data, demux->neededbytes);
6867             qtdemux_node_dump (demux, demux->moov_node);
6868             qtdemux_parse_tree (demux);
6869             qtdemux_prepare_streams (demux);
6870             QTDEMUX_EXPOSE_LOCK (demux);
6871             qtdemux_expose_streams (demux);
6872             QTDEMUX_EXPOSE_UNLOCK (demux);
6873
6874             demux->got_moov = TRUE;
6875
6876             gst_qtdemux_check_send_pending_segment (demux);
6877
6878             if (demux->moov_node_compressed) {
6879               g_node_destroy (demux->moov_node_compressed);
6880               g_free (demux->moov_node->data);
6881             }
6882             demux->moov_node_compressed = NULL;
6883             g_node_destroy (demux->moov_node);
6884             demux->moov_node = NULL;
6885             GST_DEBUG_OBJECT (demux, "Finished parsing the header");
6886           }
6887         } else if (fourcc == FOURCC_moof) {
6888           if ((demux->got_moov || demux->media_caps) && demux->fragmented) {
6889             guint64 dist = 0;
6890             GstClockTime prev_pts;
6891             guint64 prev_offset;
6892             guint64 adapter_discont_offset, adapter_discont_dist;
6893
6894             GST_DEBUG_OBJECT (demux, "Parsing [moof]");
6895
6896             /*
6897              * The timestamp of the moof buffer is relevant as some scenarios
6898              * won't have the initial timestamp in the atoms. Whenever a new
6899              * buffer has started, we get that buffer's PTS and use it as a base
6900              * timestamp for the trun entries.
6901              *
6902              * To keep track of the current buffer timestamp and starting point
6903              * we use gst_adapter_prev_pts that gives us the PTS and the distance
6904              * from the beggining of the buffer, with the distance and demux->offset
6905              * we know if it is still the same buffer or not.
6906              */
6907             prev_pts = gst_adapter_prev_pts (demux->adapter, &dist);
6908             prev_offset = demux->offset - dist;
6909             if (demux->fragment_start_offset == -1
6910                 || prev_offset > demux->fragment_start_offset) {
6911               demux->fragment_start_offset = prev_offset;
6912               demux->fragment_start = prev_pts;
6913               GST_DEBUG_OBJECT (demux,
6914                   "New fragment start found at: %" G_GUINT64_FORMAT " : %"
6915                   GST_TIME_FORMAT, demux->fragment_start_offset,
6916                   GST_TIME_ARGS (demux->fragment_start));
6917             }
6918
6919             /* We can't use prev_offset() here because this would require
6920              * upstream to set consistent and correct offsets on all buffers
6921              * since the discont. Nothing ever did that in the past and we
6922              * would break backwards compatibility here then.
6923              * Instead take the offset we had at the last discont and count
6924              * the bytes from there. This works with old code as there would
6925              * be no discont between moov and moof, and also works with
6926              * adaptivedemux which correctly sets offset and will set the
6927              * DISCONT flag accordingly when needed.
6928              *
6929              * We also only do this for upstream TIME segments as otherwise
6930              * there are potential backwards compatibility problems with
6931              * seeking in PUSH mode and upstream providing inconsistent
6932              * timestamps. */
6933             adapter_discont_offset =
6934                 gst_adapter_offset_at_discont (demux->adapter);
6935             adapter_discont_dist =
6936                 gst_adapter_distance_from_discont (demux->adapter);
6937
6938             GST_DEBUG_OBJECT (demux,
6939                 "demux offset %" G_GUINT64_FORMAT " adapter offset %"
6940                 G_GUINT64_FORMAT " (+ %" G_GUINT64_FORMAT " bytes)",
6941                 demux->offset, adapter_discont_offset, adapter_discont_dist);
6942
6943             if (demux->upstream_format_is_time) {
6944               demux->moof_offset = adapter_discont_offset;
6945               if (demux->moof_offset != GST_BUFFER_OFFSET_NONE)
6946                 demux->moof_offset += adapter_discont_dist;
6947               if (demux->moof_offset == GST_BUFFER_OFFSET_NONE)
6948                 demux->moof_offset = demux->offset;
6949             } else {
6950               demux->moof_offset = demux->offset;
6951             }
6952
6953             if (!qtdemux_parse_moof (demux, data, demux->neededbytes,
6954                     demux->moof_offset, NULL)) {
6955               gst_adapter_unmap (demux->adapter);
6956               ret = GST_FLOW_ERROR;
6957               goto done;
6958             }
6959
6960             /* in MSS we need to expose the pads after the first moof as we won't get a moov */
6961             if (demux->mss_mode && !demux->exposed) {
6962               QTDEMUX_EXPOSE_LOCK (demux);
6963               qtdemux_expose_streams (demux);
6964               QTDEMUX_EXPOSE_UNLOCK (demux);
6965             }
6966
6967             gst_qtdemux_check_send_pending_segment (demux);
6968           } else {
6969             GST_DEBUG_OBJECT (demux, "Discarding [moof]");
6970           }
6971         } else if (fourcc == FOURCC_ftyp) {
6972           GST_DEBUG_OBJECT (demux, "Parsing [ftyp]");
6973           qtdemux_parse_ftyp (demux, data, demux->neededbytes);
6974         } else if (fourcc == FOURCC_uuid) {
6975           GST_DEBUG_OBJECT (demux, "Parsing [uuid]");
6976           qtdemux_parse_uuid (demux, data, demux->neededbytes);
6977         } else if (fourcc == FOURCC_sidx) {
6978           GST_DEBUG_OBJECT (demux, "Parsing [sidx]");
6979           qtdemux_parse_sidx (demux, data, demux->neededbytes);
6980         } else {
6981           switch (fourcc) {
6982             case FOURCC_styp:
6983               /* [styp] is like a [ftyp], but in fragment header. We ignore it for now
6984                * FALLTHROUGH */
6985             case FOURCC_skip:
6986             case FOURCC_free:
6987               /* [free] and [skip] are padding atoms */
6988               GST_DEBUG_OBJECT (demux,
6989                   "Skipping fourcc while parsing header : %" GST_FOURCC_FORMAT,
6990                   GST_FOURCC_ARGS (fourcc));
6991               break;
6992             default:
6993               GST_WARNING_OBJECT (demux,
6994                   "Unknown fourcc while parsing header : %" GST_FOURCC_FORMAT,
6995                   GST_FOURCC_ARGS (fourcc));
6996               /* Let's jump that one and go back to initial state */
6997               break;
6998           }
6999         }
7000         gst_adapter_unmap (demux->adapter);
7001         data = NULL;
7002
7003         if (demux->mdatbuffer && demux->n_streams) {
7004           gsize remaining_data_size = 0;
7005
7006           /* the mdat was before the header */
7007           GST_DEBUG_OBJECT (demux, "We have n_streams:%d and mdatbuffer:%p",
7008               demux->n_streams, demux->mdatbuffer);
7009           /* restore our adapter/offset view of things with upstream;
7010            * put preceding buffered data ahead of current moov data.
7011            * This should also handle evil mdat, moov, mdat cases and alike */
7012           gst_adapter_flush (demux->adapter, demux->neededbytes);
7013
7014           /* Store any remaining data after the mdat for later usage */
7015           remaining_data_size = gst_adapter_available (demux->adapter);
7016           if (remaining_data_size > 0) {
7017             g_assert (demux->restoredata_buffer == NULL);
7018             demux->restoredata_buffer =
7019                 gst_adapter_take_buffer (demux->adapter, remaining_data_size);
7020             demux->restoredata_offset = demux->offset + demux->neededbytes;
7021             GST_DEBUG_OBJECT (demux,
7022                 "Stored %" G_GSIZE_FORMAT " post mdat bytes at offset %"
7023                 G_GUINT64_FORMAT, remaining_data_size,
7024                 demux->restoredata_offset);
7025           }
7026
7027           gst_adapter_push (demux->adapter, demux->mdatbuffer);
7028           demux->mdatbuffer = NULL;
7029           demux->offset = demux->mdatoffset;
7030           demux->neededbytes = next_entry_size (demux);
7031           demux->state = QTDEMUX_STATE_MOVIE;
7032           demux->mdatleft = gst_adapter_available (demux->adapter);
7033           demux->mdatsize = demux->mdatleft;
7034         } else {
7035           GST_DEBUG_OBJECT (demux, "Carrying on normally");
7036           gst_adapter_flush (demux->adapter, demux->neededbytes);
7037
7038           /* only go back to the mdat if there are samples to play */
7039           if (demux->got_moov && demux->first_mdat != -1
7040               && has_next_entry (demux)) {
7041             gboolean res;
7042
7043             /* we need to seek back */
7044             res = qtdemux_seek_offset (demux, demux->first_mdat);
7045             if (res) {
7046               demux->offset = demux->first_mdat;
7047             } else {
7048               GST_DEBUG_OBJECT (demux, "Seek back failed");
7049             }
7050           } else {
7051             demux->offset += demux->neededbytes;
7052           }
7053           demux->neededbytes = 16;
7054           demux->state = QTDEMUX_STATE_INITIAL;
7055         }
7056
7057         break;
7058       }
7059       case QTDEMUX_STATE_BUFFER_MDAT:{
7060         GstBuffer *buf;
7061         guint8 fourcc[4];
7062
7063         GST_DEBUG_OBJECT (demux, "Got our buffer at offset %" G_GUINT64_FORMAT,
7064             demux->offset);
7065         buf = gst_adapter_take_buffer (demux->adapter, demux->neededbytes);
7066         gst_buffer_extract (buf, 0, fourcc, 4);
7067         GST_DEBUG_OBJECT (demux, "mdatbuffer starts with %" GST_FOURCC_FORMAT,
7068             GST_FOURCC_ARGS (QT_FOURCC (fourcc)));
7069         if (demux->mdatbuffer)
7070           demux->mdatbuffer = gst_buffer_append (demux->mdatbuffer, buf);
7071         else
7072           demux->mdatbuffer = buf;
7073         demux->offset += demux->neededbytes;
7074         demux->neededbytes = 16;
7075         demux->state = QTDEMUX_STATE_INITIAL;
7076         gst_qtdemux_post_progress (demux, 1, 1);
7077
7078         break;
7079       }
7080       case QTDEMUX_STATE_MOVIE:{
7081         QtDemuxStream *stream = NULL;
7082         QtDemuxSample *sample;
7083         GstClockTime dts, pts, duration;
7084         gboolean keyframe;
7085         GList *iter;
7086
7087         GST_DEBUG_OBJECT (demux,
7088             "BEGIN // in MOVIE for offset %" G_GUINT64_FORMAT, demux->offset);
7089
7090         if (demux->fragmented) {
7091           GST_DEBUG_OBJECT (demux, "mdat remaining %" G_GUINT64_FORMAT,
7092               demux->mdatleft);
7093           if (G_LIKELY (demux->todrop < demux->mdatleft)) {
7094             /* if needed data starts within this atom,
7095              * then it should not exceed this atom */
7096             if (G_UNLIKELY (demux->neededbytes > demux->mdatleft)) {
7097               GST_ELEMENT_ERROR (demux, STREAM, DEMUX,
7098                   (_("This file is invalid and cannot be played.")),
7099                   ("sample data crosses atom boundary"));
7100               ret = GST_FLOW_ERROR;
7101               break;
7102             }
7103             demux->mdatleft -= demux->neededbytes;
7104           } else {
7105             GST_DEBUG_OBJECT (demux, "data atom emptied; resuming atom scan");
7106             /* so we are dropping more than left in this atom */
7107             gst_qtdemux_drop_data (demux, demux->mdatleft);
7108             demux->mdatleft = 0;
7109
7110             /* need to resume atom parsing so we do not miss any other pieces */
7111             demux->state = QTDEMUX_STATE_INITIAL;
7112             demux->neededbytes = 16;
7113
7114             /* check if there was any stored post mdat data from previous buffers */
7115             if (demux->restoredata_buffer) {
7116               g_assert (gst_adapter_available (demux->adapter) == 0);
7117
7118               gst_adapter_push (demux->adapter, demux->restoredata_buffer);
7119               demux->restoredata_buffer = NULL;
7120               demux->offset = demux->restoredata_offset;
7121             }
7122
7123             break;
7124           }
7125         }
7126
7127         if (demux->todrop) {
7128           if (demux->cenc_aux_info_offset > 0) {
7129             GstByteReader br;
7130             const guint8 *data;
7131
7132             GST_DEBUG_OBJECT (demux, "parsing cenc auxiliary info");
7133             data = gst_adapter_map (demux->adapter, demux->todrop);
7134             gst_byte_reader_init (&br, data + 8, demux->todrop);
7135             if (!qtdemux_parse_cenc_aux_info (demux,
7136                     QTDEMUX_FIRST_STREAM (demux), &br,
7137                     demux->cenc_aux_info_sizes, demux->cenc_aux_sample_count)) {
7138               GST_ERROR_OBJECT (demux, "failed to parse cenc auxiliary info");
7139               ret = GST_FLOW_ERROR;
7140               gst_adapter_unmap (demux->adapter);
7141               g_free (demux->cenc_aux_info_sizes);
7142               demux->cenc_aux_info_sizes = NULL;
7143               goto done;
7144             }
7145             demux->cenc_aux_info_offset = 0;
7146             g_free (demux->cenc_aux_info_sizes);
7147             demux->cenc_aux_info_sizes = NULL;
7148             gst_adapter_unmap (demux->adapter);
7149           }
7150           gst_qtdemux_drop_data (demux, demux->todrop);
7151         }
7152
7153         /* first buffer? */
7154         /* initial newsegment sent here after having added pads,
7155          * possible others in sink_event */
7156         gst_qtdemux_check_send_pending_segment (demux);
7157
7158         /* Figure out which stream this packet belongs to */
7159         for (iter = demux->active_streams; iter; iter = g_list_next (iter)) {
7160           stream = QTDEMUX_STREAM (iter->data);
7161           if (stream->sample_index >= stream->n_samples) {
7162             /* reset to be checked below G_UNLIKELY (stream == NULL) */
7163             stream = NULL;
7164             continue;
7165           }
7166           GST_LOG_OBJECT (demux,
7167               "Checking track-id %u (sample_index:%d / offset:%"
7168               G_GUINT64_FORMAT " / size:%d)", stream->track_id,
7169               stream->sample_index,
7170               stream->samples[stream->sample_index].offset,
7171               stream->samples[stream->sample_index].size);
7172
7173           if (stream->samples[stream->sample_index].offset == demux->offset)
7174             break;
7175         }
7176
7177         if (G_UNLIKELY (stream == NULL))
7178           goto unknown_stream;
7179
7180         gst_qtdemux_stream_check_and_change_stsd_index (demux, stream);
7181
7182         if (stream->new_caps) {
7183           gst_qtdemux_configure_stream (demux, stream);
7184         }
7185
7186         /* Put data in a buffer, set timestamps, caps, ... */
7187         sample = &stream->samples[stream->sample_index];
7188
7189         if (G_LIKELY (!(STREAM_IS_EOS (stream)))) {
7190           GST_DEBUG_OBJECT (demux, "stream : %" GST_FOURCC_FORMAT,
7191               GST_FOURCC_ARGS (CUR_STREAM (stream)->fourcc));
7192
7193           dts = QTSAMPLE_DTS (stream, sample);
7194           pts = QTSAMPLE_PTS (stream, sample);
7195           duration = QTSAMPLE_DUR_DTS (stream, sample, dts);
7196           keyframe = QTSAMPLE_KEYFRAME (stream, sample);
7197
7198           /* check for segment end */
7199           if (G_UNLIKELY (demux->segment.stop != -1
7200                   && demux->segment.stop <= pts && stream->on_keyframe)
7201               && !(demux->upstream_format_is_time && demux->segment.rate < 0)) {
7202             GST_DEBUG_OBJECT (demux, "we reached the end of our segment.");
7203             stream->time_position = GST_CLOCK_TIME_NONE;        /* this means EOS */
7204
7205             /* skip this data, stream is EOS */
7206             gst_adapter_flush (demux->adapter, demux->neededbytes);
7207             demux->offset += demux->neededbytes;
7208
7209             /* check if all streams are eos */
7210             ret = GST_FLOW_EOS;
7211             for (iter = demux->active_streams; iter; iter = g_list_next (iter)) {
7212               if (!STREAM_IS_EOS (QTDEMUX_STREAM (iter->data))) {
7213                 ret = GST_FLOW_OK;
7214                 break;
7215               }
7216             }
7217           } else {
7218             GstBuffer *outbuf;
7219
7220             outbuf =
7221                 gst_adapter_take_buffer (demux->adapter, demux->neededbytes);
7222
7223             /* FIXME: should either be an assert or a plain check */
7224             g_return_val_if_fail (outbuf != NULL, GST_FLOW_ERROR);
7225
7226             ret = gst_qtdemux_decorate_and_push_buffer (demux, stream, outbuf,
7227                 dts, pts, duration, keyframe, dts, demux->offset);
7228           }
7229
7230           /* combine flows */
7231           ret = gst_qtdemux_combine_flows (demux, stream, ret);
7232         } else {
7233           /* skip this data, stream is EOS */
7234           gst_adapter_flush (demux->adapter, demux->neededbytes);
7235         }
7236
7237         stream->sample_index++;
7238         stream->offset_in_sample = 0;
7239
7240         /* update current offset and figure out size of next buffer */
7241         GST_LOG_OBJECT (demux, "increasing offset %" G_GUINT64_FORMAT " by %u",
7242             demux->offset, demux->neededbytes);
7243         demux->offset += demux->neededbytes;
7244         GST_LOG_OBJECT (demux, "offset is now %" G_GUINT64_FORMAT,
7245             demux->offset);
7246
7247
7248         if (ret == GST_FLOW_EOS) {
7249           GST_DEBUG_OBJECT (demux, "All streams are EOS, signal upstream");
7250           demux->neededbytes = -1;
7251           goto eos;
7252         }
7253
7254         if ((demux->neededbytes = next_entry_size (demux)) == -1) {
7255           if (demux->fragmented) {
7256             GST_DEBUG_OBJECT (demux, "(temporarily) out of fragmented samples");
7257             /* there may be more to follow, only finish this atom */
7258             demux->todrop = demux->mdatleft;
7259             demux->neededbytes = demux->todrop;
7260             break;
7261           }
7262           goto eos;
7263         }
7264         if (ret != GST_FLOW_OK && ret != GST_FLOW_NOT_LINKED) {
7265           goto non_ok_unlinked_flow;
7266         }
7267         break;
7268       }
7269       default:
7270         goto invalid_state;
7271     }
7272   }
7273
7274   /* when buffering movie data, at least show user something is happening */
7275   if (ret == GST_FLOW_OK && demux->state == QTDEMUX_STATE_BUFFER_MDAT &&
7276       gst_adapter_available (demux->adapter) <= demux->neededbytes) {
7277     gst_qtdemux_post_progress (demux, gst_adapter_available (demux->adapter),
7278         demux->neededbytes);
7279   }
7280 done:
7281
7282   return ret;
7283
7284   /* ERRORS */
7285 non_ok_unlinked_flow:
7286   {
7287     GST_DEBUG_OBJECT (demux, "Stopping, combined return flow %s",
7288         gst_flow_get_name (ret));
7289     return ret;
7290   }
7291 unknown_stream:
7292   {
7293     GST_ELEMENT_ERROR (demux, STREAM, FAILED, (NULL), ("unknown stream found"));
7294     ret = GST_FLOW_ERROR;
7295     goto done;
7296   }
7297 eos:
7298   {
7299     GST_DEBUG_OBJECT (demux, "no next entry, EOS");
7300     ret = GST_FLOW_EOS;
7301     goto done;
7302   }
7303 invalid_state:
7304   {
7305     GST_ELEMENT_ERROR (demux, STREAM, FAILED,
7306         (NULL), ("qtdemuxer invalid state %d", demux->state));
7307     ret = GST_FLOW_ERROR;
7308     goto done;
7309   }
7310 no_moov:
7311   {
7312     GST_ELEMENT_ERROR (demux, STREAM, FAILED,
7313         (NULL), ("no 'moov' atom within the first 10 MB"));
7314     ret = GST_FLOW_ERROR;
7315     goto done;
7316   }
7317 }
7318
7319 static gboolean
7320 qtdemux_sink_activate (GstPad * sinkpad, GstObject * parent)
7321 {
7322   GstQuery *query;
7323   gboolean pull_mode;
7324
7325   query = gst_query_new_scheduling ();
7326
7327   if (!gst_pad_peer_query (sinkpad, query)) {
7328     gst_query_unref (query);
7329     goto activate_push;
7330   }
7331
7332   pull_mode = gst_query_has_scheduling_mode_with_flags (query,
7333       GST_PAD_MODE_PULL, GST_SCHEDULING_FLAG_SEEKABLE);
7334   gst_query_unref (query);
7335
7336   if (!pull_mode)
7337     goto activate_push;
7338
7339   GST_DEBUG_OBJECT (sinkpad, "activating pull");
7340   return gst_pad_activate_mode (sinkpad, GST_PAD_MODE_PULL, TRUE);
7341
7342 activate_push:
7343   {
7344     GST_DEBUG_OBJECT (sinkpad, "activating push");
7345     return gst_pad_activate_mode (sinkpad, GST_PAD_MODE_PUSH, TRUE);
7346   }
7347 }
7348
7349 static gboolean
7350 qtdemux_sink_activate_mode (GstPad * sinkpad, GstObject * parent,
7351     GstPadMode mode, gboolean active)
7352 {
7353   gboolean res;
7354   GstQTDemux *demux = GST_QTDEMUX (parent);
7355
7356   switch (mode) {
7357     case GST_PAD_MODE_PUSH:
7358       demux->pullbased = FALSE;
7359       res = TRUE;
7360       break;
7361     case GST_PAD_MODE_PULL:
7362       if (active) {
7363         demux->pullbased = TRUE;
7364         res = gst_pad_start_task (sinkpad, (GstTaskFunction) gst_qtdemux_loop,
7365             sinkpad, NULL);
7366       } else {
7367         res = gst_pad_stop_task (sinkpad);
7368       }
7369       break;
7370     default:
7371       res = FALSE;
7372       break;
7373   }
7374   return res;
7375 }
7376
7377 #ifdef HAVE_ZLIB
7378 static void *
7379 qtdemux_inflate (void *z_buffer, guint z_length, guint * length)
7380 {
7381   guint8 *buffer;
7382   z_stream z;
7383   int ret;
7384
7385   memset (&z, 0, sizeof (z));
7386   z.zalloc = NULL;
7387   z.zfree = NULL;
7388   z.opaque = NULL;
7389
7390   if ((ret = inflateInit (&z)) != Z_OK) {
7391     GST_ERROR ("inflateInit() returned %d", ret);
7392     return NULL;
7393   }
7394
7395   z.next_in = z_buffer;
7396   z.avail_in = z_length;
7397
7398   buffer = (guint8 *) g_malloc (*length);
7399   z.avail_out = *length;
7400   z.next_out = (Bytef *) buffer;
7401   do {
7402     ret = inflate (&z, Z_NO_FLUSH);
7403     if (ret == Z_STREAM_END) {
7404       break;
7405     } else if (ret != Z_OK) {
7406       GST_WARNING ("inflate() returned %d", ret);
7407       break;
7408     }
7409
7410     *length += 4096;
7411     buffer = (guint8 *) g_realloc (buffer, *length);
7412     z.next_out = (Bytef *) (buffer + z.total_out);
7413     z.avail_out += 4096;
7414   } while (z.avail_in > 0);
7415
7416   if (ret != Z_STREAM_END) {
7417     g_free (buffer);
7418     buffer = NULL;
7419     *length = 0;
7420   } else {
7421     *length = z.total_out;
7422   }
7423
7424   inflateEnd (&z);
7425
7426   return buffer;
7427 }
7428 #endif /* HAVE_ZLIB */
7429
7430 static gboolean
7431 qtdemux_parse_moov (GstQTDemux * qtdemux, const guint8 * buffer, guint length)
7432 {
7433   GNode *cmov;
7434
7435   qtdemux->moov_node = g_node_new ((guint8 *) buffer);
7436
7437   /* counts as header data */
7438   qtdemux->header_size += length;
7439
7440   GST_DEBUG_OBJECT (qtdemux, "parsing 'moov' atom");
7441   qtdemux_parse_node (qtdemux, qtdemux->moov_node, buffer, length);
7442
7443   cmov = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_cmov);
7444   if (cmov) {
7445     guint32 method;
7446     GNode *dcom;
7447     GNode *cmvd;
7448     guint32 dcom_len;
7449
7450     dcom = qtdemux_tree_get_child_by_type (cmov, FOURCC_dcom);
7451     cmvd = qtdemux_tree_get_child_by_type (cmov, FOURCC_cmvd);
7452     if (dcom == NULL || cmvd == NULL)
7453       goto invalid_compression;
7454
7455     dcom_len = QT_UINT32 (dcom->data);
7456     if (dcom_len < 12)
7457       goto invalid_compression;
7458
7459     method = QT_FOURCC ((guint8 *) dcom->data + 8);
7460     switch (method) {
7461 #ifdef HAVE_ZLIB
7462       case FOURCC_zlib:{
7463         guint uncompressed_length;
7464         guint compressed_length;
7465         guint8 *buf;
7466         guint32 cmvd_len;
7467
7468         cmvd_len = QT_UINT32 ((guint8 *) cmvd->data);
7469         if (cmvd_len < 12)
7470           goto invalid_compression;
7471
7472         uncompressed_length = QT_UINT32 ((guint8 *) cmvd->data + 8);
7473         compressed_length = cmvd_len - 12;
7474         GST_LOG ("length = %u", uncompressed_length);
7475
7476         buf =
7477             (guint8 *) qtdemux_inflate ((guint8 *) cmvd->data + 12,
7478             compressed_length, &uncompressed_length);
7479
7480         if (buf) {
7481           qtdemux->moov_node_compressed = qtdemux->moov_node;
7482           qtdemux->moov_node = g_node_new (buf);
7483
7484           qtdemux_parse_node (qtdemux, qtdemux->moov_node, buf,
7485               uncompressed_length);
7486         }
7487         break;
7488       }
7489 #endif /* HAVE_ZLIB */
7490       default:
7491         GST_WARNING_OBJECT (qtdemux, "unknown or unhandled header compression "
7492             "type %" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (method));
7493         break;
7494     }
7495   }
7496   return TRUE;
7497
7498   /* ERRORS */
7499 invalid_compression:
7500   {
7501     GST_ERROR_OBJECT (qtdemux, "invalid compressed header");
7502     return FALSE;
7503   }
7504 }
7505
7506 static gboolean
7507 qtdemux_parse_container (GstQTDemux * qtdemux, GNode * node, const guint8 * buf,
7508     const guint8 * end)
7509 {
7510   while (G_UNLIKELY (buf < end)) {
7511     GNode *child;
7512     guint32 len;
7513
7514     if (G_UNLIKELY (buf + 4 > end)) {
7515       GST_LOG_OBJECT (qtdemux, "buffer overrun");
7516       break;
7517     }
7518     len = QT_UINT32 (buf);
7519     if (G_UNLIKELY (len == 0)) {
7520       GST_LOG_OBJECT (qtdemux, "empty container");
7521       break;
7522     }
7523     if (G_UNLIKELY (len < 8)) {
7524       GST_WARNING_OBJECT (qtdemux, "length too short (%d < 8)", len);
7525       break;
7526     }
7527     if (G_UNLIKELY (len > (end - buf))) {
7528       GST_WARNING_OBJECT (qtdemux, "length too long (%d > %d)", len,
7529           (gint) (end - buf));
7530       break;
7531     }
7532
7533     child = g_node_new ((guint8 *) buf);
7534     g_node_append (node, child);
7535     GST_LOG_OBJECT (qtdemux, "adding new node of len %d", len);
7536     qtdemux_parse_node (qtdemux, child, buf, len);
7537
7538     buf += len;
7539   }
7540   return TRUE;
7541 }
7542
7543 static gboolean
7544 qtdemux_parse_theora_extension (GstQTDemux * qtdemux, QtDemuxStream * stream,
7545     GNode * xdxt)
7546 {
7547   int len = QT_UINT32 (xdxt->data);
7548   guint8 *buf = xdxt->data;
7549   guint8 *end = buf + len;
7550   GstBuffer *buffer;
7551
7552   /* skip size and type */
7553   buf += 8;
7554   end -= 8;
7555
7556   while (buf < end) {
7557     gint size;
7558     guint32 type;
7559
7560     size = QT_UINT32 (buf);
7561     type = QT_FOURCC (buf + 4);
7562
7563     GST_LOG_OBJECT (qtdemux, "%p %p", buf, end);
7564
7565     if (buf + size > end || size <= 0)
7566       break;
7567
7568     buf += 8;
7569     size -= 8;
7570
7571     GST_WARNING_OBJECT (qtdemux, "have cookie %" GST_FOURCC_FORMAT,
7572         GST_FOURCC_ARGS (type));
7573
7574     switch (type) {
7575       case FOURCC_tCtH:
7576         buffer = gst_buffer_new_and_alloc (size);
7577         gst_buffer_fill (buffer, 0, buf, size);
7578         stream->buffers = g_slist_append (stream->buffers, buffer);
7579         GST_LOG_OBJECT (qtdemux, "parsing theora header");
7580         break;
7581       case FOURCC_tCt_:
7582         buffer = gst_buffer_new_and_alloc (size);
7583         gst_buffer_fill (buffer, 0, buf, size);
7584         stream->buffers = g_slist_append (stream->buffers, buffer);
7585         GST_LOG_OBJECT (qtdemux, "parsing theora comment");
7586         break;
7587       case FOURCC_tCtC:
7588         buffer = gst_buffer_new_and_alloc (size);
7589         gst_buffer_fill (buffer, 0, buf, size);
7590         stream->buffers = g_slist_append (stream->buffers, buffer);
7591         GST_LOG_OBJECT (qtdemux, "parsing theora codebook");
7592         break;
7593       default:
7594         GST_WARNING_OBJECT (qtdemux,
7595             "unknown theora cookie %" GST_FOURCC_FORMAT,
7596             GST_FOURCC_ARGS (type));
7597         break;
7598     }
7599     buf += size;
7600   }
7601   return TRUE;
7602 }
7603
7604 static gboolean
7605 qtdemux_parse_node (GstQTDemux * qtdemux, GNode * node, const guint8 * buffer,
7606     guint length)
7607 {
7608   guint32 fourcc = 0;
7609   guint32 node_length = 0;
7610   const QtNodeType *type;
7611   const guint8 *end;
7612
7613   GST_LOG_OBJECT (qtdemux, "qtdemux_parse buffer %p length %u", buffer, length);
7614
7615   if (G_UNLIKELY (length < 8))
7616     goto not_enough_data;
7617
7618   node_length = QT_UINT32 (buffer);
7619   fourcc = QT_FOURCC (buffer + 4);
7620
7621   /* ignore empty nodes */
7622   if (G_UNLIKELY (fourcc == 0 || node_length == 8))
7623     return TRUE;
7624
7625   type = qtdemux_type_get (fourcc);
7626
7627   end = buffer + length;
7628
7629   GST_LOG_OBJECT (qtdemux,
7630       "parsing '%" GST_FOURCC_FORMAT "', length=%u, name '%s'",
7631       GST_FOURCC_ARGS (fourcc), node_length, type->name);
7632
7633   if (node_length > length)
7634     goto broken_atom_size;
7635
7636   if (type->flags & QT_FLAG_CONTAINER) {
7637     qtdemux_parse_container (qtdemux, node, buffer + 8, end);
7638   } else {
7639     switch (fourcc) {
7640       case FOURCC_stsd:
7641       {
7642         if (node_length < 20) {
7643           GST_LOG_OBJECT (qtdemux, "skipping small stsd box");
7644           break;
7645         }
7646         GST_DEBUG_OBJECT (qtdemux,
7647             "parsing stsd (sample table, sample description) atom");
7648         /* Skip over 8 byte atom hdr + 1 byte version, 3 bytes flags, 4 byte num_entries */
7649         qtdemux_parse_container (qtdemux, node, buffer + 16, end);
7650         break;
7651       }
7652       case FOURCC_mp4a:
7653       case FOURCC_alac:
7654       case FOURCC_fLaC:
7655       {
7656         guint32 version;
7657         guint32 offset;
7658         guint min_size;
7659
7660         /* also read alac (or whatever) in stead of mp4a in the following,
7661          * since a similar layout is used in other cases as well */
7662         if (fourcc == FOURCC_mp4a)
7663           min_size = 20;
7664         else if (fourcc == FOURCC_fLaC)
7665           min_size = 86;
7666         else
7667           min_size = 40;
7668
7669         /* There are two things we might encounter here: a true mp4a atom, and
7670            an mp4a entry in an stsd atom. The latter is what we're interested
7671            in, and it looks like an atom, but isn't really one. The true mp4a
7672            atom is short, so we detect it based on length here. */
7673         if (length < min_size) {
7674           GST_LOG_OBJECT (qtdemux, "skipping small %" GST_FOURCC_FORMAT " box",
7675               GST_FOURCC_ARGS (fourcc));
7676           break;
7677         }
7678
7679         /* 'version' here is the sound sample description version. Types 0 and
7680            1 are documented in the QTFF reference, but type 2 is not: it's
7681            described in Apple header files instead (struct SoundDescriptionV2
7682            in Movies.h) */
7683         version = QT_UINT16 (buffer + 16);
7684
7685         GST_DEBUG_OBJECT (qtdemux, "%" GST_FOURCC_FORMAT " version 0x%08x",
7686             GST_FOURCC_ARGS (fourcc), version);
7687
7688         /* parse any esds descriptors */
7689         switch (version) {
7690           case 0:
7691             offset = 0x24;
7692             break;
7693           case 1:
7694             offset = 0x34;
7695             break;
7696           case 2:
7697             offset = 0x48;
7698             break;
7699           default:
7700             GST_WARNING_OBJECT (qtdemux,
7701                 "unhandled %" GST_FOURCC_FORMAT " version 0x%08x",
7702                 GST_FOURCC_ARGS (fourcc), version);
7703             offset = 0;
7704             break;
7705         }
7706         if (offset)
7707           qtdemux_parse_container (qtdemux, node, buffer + offset, end);
7708         break;
7709       }
7710       case FOURCC_mp4v:
7711       case FOURCC_MP4V:
7712       case FOURCC_fmp4:
7713       case FOURCC_FMP4:
7714       case FOURCC_apcs:
7715       case FOURCC_apch:
7716       case FOURCC_apcn:
7717       case FOURCC_apco:
7718       case FOURCC_ap4h:
7719       case FOURCC_xvid:
7720       case FOURCC_XVID:
7721       case FOURCC_H264:
7722       case FOURCC_avc1:
7723       case FOURCC_avc3:
7724       case FOURCC_H265:
7725       case FOURCC_hvc1:
7726       case FOURCC_hev1:
7727       case FOURCC_mjp2:
7728       case FOURCC_encv:
7729       {
7730         guint32 version;
7731         guint32 str_len;
7732
7733         /* codec_data is contained inside these atoms, which all have
7734          * the same format. */
7735         /* video sample description size is 86 bytes without extension.
7736          * node_length have to be bigger than 86 bytes because video sample
7737          * description can include extenstions such as esds, fiel, glbl, etc. */
7738         if (node_length < 86) {
7739           GST_WARNING_OBJECT (qtdemux, "%" GST_FOURCC_FORMAT
7740               " sample description length too short (%u < 86)",
7741               GST_FOURCC_ARGS (fourcc), node_length);
7742           break;
7743         }
7744
7745         GST_DEBUG_OBJECT (qtdemux, "parsing in %" GST_FOURCC_FORMAT,
7746             GST_FOURCC_ARGS (fourcc));
7747
7748         /* version (2 bytes) : this is set to 0, unless a compressor has changed
7749          *              its data format.
7750          * revision level (2 bytes) : must be set to 0. */
7751         version = QT_UINT32 (buffer + 16);
7752         GST_DEBUG_OBJECT (qtdemux, "version %08x", version);
7753
7754         /* compressor name : PASCAL string and informative purposes
7755          * first byte : the number of bytes to be displayed.
7756          *              it has to be less than 32 because it is reserved
7757          *              space of 32 bytes total including itself. */
7758         str_len = QT_UINT8 (buffer + 50);
7759         if (str_len < 32)
7760           GST_DEBUG_OBJECT (qtdemux, "compressorname = %.*s", str_len,
7761               (char *) buffer + 51);
7762         else
7763           GST_WARNING_OBJECT (qtdemux,
7764               "compressorname length too big (%u > 31)", str_len);
7765
7766         GST_MEMDUMP_OBJECT (qtdemux, "video sample description", buffer,
7767             end - buffer);
7768         qtdemux_parse_container (qtdemux, node, buffer + 86, end);
7769         break;
7770       }
7771       case FOURCC_meta:
7772       {
7773         GST_DEBUG_OBJECT (qtdemux, "parsing meta atom");
7774
7775         /* You are reading this correctly. QTFF specifies that the
7776          * metadata atom is a short atom, whereas ISO BMFF specifies
7777          * it's a full atom. But since so many people are doing things
7778          * differently, we actually peek into the atom to see which
7779          * variant it is */
7780         if (length < 16) {
7781           GST_LOG_OBJECT (qtdemux, "skipping small %" GST_FOURCC_FORMAT " box",
7782               GST_FOURCC_ARGS (fourcc));
7783           break;
7784         }
7785         if (QT_FOURCC (buffer + 12) == FOURCC_hdlr) {
7786           /* Variant 1: What QTFF specifies. 'meta' is a short header which
7787            * starts with a 'hdlr' atom */
7788           qtdemux_parse_container (qtdemux, node, buffer + 8, end);
7789         } else if (QT_UINT32 (buffer + 8) == 0x00000000) {
7790           /* Variant 2: What ISO BMFF specifies. 'meta' is a _full_ atom
7791            * with version/flags both set to zero */
7792           qtdemux_parse_container (qtdemux, node, buffer + 12, end);
7793         } else
7794           GST_WARNING_OBJECT (qtdemux, "Unknown 'meta' atom format");
7795         break;
7796       }
7797       case FOURCC_mp4s:
7798       {
7799         GST_MEMDUMP_OBJECT (qtdemux, "mp4s", buffer, end - buffer);
7800         /* Skip 8 byte header, plus 8 byte version + flags + entry_count */
7801         qtdemux_parse_container (qtdemux, node, buffer + 16, end);
7802         break;
7803       }
7804       case FOURCC_XiTh:
7805       {
7806         guint32 version;
7807         guint32 offset;
7808
7809         if (length < 16) {
7810           GST_LOG_OBJECT (qtdemux, "skipping small %" GST_FOURCC_FORMAT " box",
7811               GST_FOURCC_ARGS (fourcc));
7812           break;
7813         }
7814
7815         version = QT_UINT32 (buffer + 12);
7816         GST_DEBUG_OBJECT (qtdemux, "parsing XiTh atom version 0x%08x", version);
7817
7818         switch (version) {
7819           case 0x00000001:
7820             offset = 0x62;
7821             break;
7822           default:
7823             GST_DEBUG_OBJECT (qtdemux, "unknown version 0x%08x", version);
7824             offset = 0;
7825             break;
7826         }
7827         if (offset) {
7828           if (length < offset) {
7829             GST_WARNING_OBJECT (qtdemux,
7830                 "skipping too small %" GST_FOURCC_FORMAT " box",
7831                 GST_FOURCC_ARGS (fourcc));
7832             break;
7833           }
7834           qtdemux_parse_container (qtdemux, node, buffer + offset, end);
7835         }
7836         break;
7837       }
7838       case FOURCC_in24:
7839       {
7840         qtdemux_parse_container (qtdemux, node, buffer + 0x34, end);
7841         break;
7842       }
7843       case FOURCC_uuid:
7844       {
7845         qtdemux_parse_uuid (qtdemux, buffer, end - buffer);
7846         break;
7847       }
7848       case FOURCC_enca:
7849       {
7850         qtdemux_parse_container (qtdemux, node, buffer + 36, end);
7851         break;
7852       }
7853       default:
7854         if (!strcmp (type->name, "unknown"))
7855           GST_MEMDUMP ("Unknown tag", buffer + 4, end - buffer - 4);
7856         break;
7857     }
7858   }
7859   GST_LOG_OBJECT (qtdemux, "parsed '%" GST_FOURCC_FORMAT "'",
7860       GST_FOURCC_ARGS (fourcc));
7861   return TRUE;
7862
7863 /* ERRORS */
7864 not_enough_data:
7865   {
7866     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
7867         (_("This file is corrupt and cannot be played.")),
7868         ("Not enough data for an atom header, got only %u bytes", length));
7869     return FALSE;
7870   }
7871 broken_atom_size:
7872   {
7873     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
7874         (_("This file is corrupt and cannot be played.")),
7875         ("Atom '%" GST_FOURCC_FORMAT "' has size of %u bytes, but we have only "
7876             "%u bytes available.", GST_FOURCC_ARGS (fourcc), node_length,
7877             length));
7878     return FALSE;
7879   }
7880 }
7881
7882 static GNode *
7883 qtdemux_tree_get_child_by_type (GNode * node, guint32 fourcc)
7884 {
7885   GNode *child;
7886   guint8 *buffer;
7887   guint32 child_fourcc;
7888
7889   for (child = g_node_first_child (node); child;
7890       child = g_node_next_sibling (child)) {
7891     buffer = (guint8 *) child->data;
7892
7893     child_fourcc = QT_FOURCC (buffer + 4);
7894
7895     if (G_UNLIKELY (child_fourcc == fourcc)) {
7896       return child;
7897     }
7898   }
7899   return NULL;
7900 }
7901
7902 static GNode *
7903 qtdemux_tree_get_child_by_type_full (GNode * node, guint32 fourcc,
7904     GstByteReader * parser)
7905 {
7906   GNode *child;
7907   guint8 *buffer;
7908   guint32 child_fourcc, child_len;
7909
7910   for (child = g_node_first_child (node); child;
7911       child = g_node_next_sibling (child)) {
7912     buffer = (guint8 *) child->data;
7913
7914     child_len = QT_UINT32 (buffer);
7915     child_fourcc = QT_FOURCC (buffer + 4);
7916
7917     if (G_UNLIKELY (child_fourcc == fourcc)) {
7918       if (G_UNLIKELY (child_len < (4 + 4)))
7919         return NULL;
7920       /* FIXME: must verify if atom length < parent atom length */
7921       gst_byte_reader_init (parser, buffer + (4 + 4), child_len - (4 + 4));
7922       return child;
7923     }
7924   }
7925   return NULL;
7926 }
7927
7928 static GNode *
7929 qtdemux_tree_get_child_by_index (GNode * node, guint index)
7930 {
7931   return g_node_nth_child (node, index);
7932 }
7933
7934 static GNode *
7935 qtdemux_tree_get_sibling_by_type_full (GNode * node, guint32 fourcc,
7936     GstByteReader * parser)
7937 {
7938   GNode *child;
7939   guint8 *buffer;
7940   guint32 child_fourcc, child_len;
7941
7942   for (child = g_node_next_sibling (node); child;
7943       child = g_node_next_sibling (child)) {
7944     buffer = (guint8 *) child->data;
7945
7946     child_fourcc = QT_FOURCC (buffer + 4);
7947
7948     if (child_fourcc == fourcc) {
7949       if (parser) {
7950         child_len = QT_UINT32 (buffer);
7951         if (G_UNLIKELY (child_len < (4 + 4)))
7952           return NULL;
7953         /* FIXME: must verify if atom length < parent atom length */
7954         gst_byte_reader_init (parser, buffer + (4 + 4), child_len - (4 + 4));
7955       }
7956       return child;
7957     }
7958   }
7959   return NULL;
7960 }
7961
7962 static GNode *
7963 qtdemux_tree_get_sibling_by_type (GNode * node, guint32 fourcc)
7964 {
7965   return qtdemux_tree_get_sibling_by_type_full (node, fourcc, NULL);
7966 }
7967
7968 static void
7969 qtdemux_do_allocation (GstQTDemux * qtdemux, QtDemuxStream * stream)
7970 {
7971 /* FIXME: This can only reliably work if demuxers have a
7972  * separate streaming thread per srcpad. This should be
7973  * done in a demuxer base class, which integrates parts
7974  * of multiqueue
7975  *
7976  * https://bugzilla.gnome.org/show_bug.cgi?id=701856
7977  */
7978 #if 0
7979   GstQuery *query;
7980
7981   query = gst_query_new_allocation (stream->caps, FALSE);
7982
7983   if (!gst_pad_peer_query (stream->pad, query)) {
7984     /* not a problem, just debug a little */
7985     GST_DEBUG_OBJECT (qtdemux, "peer ALLOCATION query failed");
7986   }
7987
7988   if (stream->allocator)
7989     gst_object_unref (stream->allocator);
7990
7991   if (gst_query_get_n_allocation_params (query) > 0) {
7992     /* try the allocator */
7993     gst_query_parse_nth_allocation_param (query, 0, &stream->allocator,
7994         &stream->params);
7995     stream->use_allocator = TRUE;
7996   } else {
7997     stream->allocator = NULL;
7998     gst_allocation_params_init (&stream->params);
7999     stream->use_allocator = FALSE;
8000   }
8001   gst_query_unref (query);
8002 #endif
8003 }
8004
8005 static gboolean
8006 pad_query (const GValue * item, GValue * value, gpointer user_data)
8007 {
8008   GstPad *pad = g_value_get_object (item);
8009   GstQuery *query = user_data;
8010   gboolean res;
8011
8012   res = gst_pad_peer_query (pad, query);
8013
8014   if (res) {
8015     g_value_set_boolean (value, TRUE);
8016     return FALSE;
8017   }
8018
8019   GST_INFO_OBJECT (pad, "pad peer query failed");
8020   return TRUE;
8021 }
8022
8023 static gboolean
8024 gst_qtdemux_run_query (GstElement * element, GstQuery * query,
8025     GstPadDirection direction)
8026 {
8027   GstIterator *it;
8028   GstIteratorFoldFunction func = pad_query;
8029   GValue res = { 0, };
8030
8031   g_value_init (&res, G_TYPE_BOOLEAN);
8032   g_value_set_boolean (&res, FALSE);
8033
8034   /* Ask neighbor */
8035   if (direction == GST_PAD_SRC)
8036     it = gst_element_iterate_src_pads (element);
8037   else
8038     it = gst_element_iterate_sink_pads (element);
8039
8040   while (gst_iterator_fold (it, func, &res, query) == GST_ITERATOR_RESYNC)
8041     gst_iterator_resync (it);
8042
8043   gst_iterator_free (it);
8044
8045   return g_value_get_boolean (&res);
8046 }
8047
8048 static void
8049 gst_qtdemux_request_protection_context (GstQTDemux * qtdemux,
8050     QtDemuxStream * stream)
8051 {
8052   GstQuery *query;
8053   GstContext *ctxt;
8054   GstElement *element = GST_ELEMENT (qtdemux);
8055   GstStructure *st;
8056   gchar **filtered_sys_ids;
8057   GValue event_list = G_VALUE_INIT;
8058   GList *walk;
8059
8060   /* 1. Check if we already have the context. */
8061   if (qtdemux->preferred_protection_system_id != NULL) {
8062     GST_LOG_OBJECT (element,
8063         "already have the protection context, no need to request it again");
8064     return;
8065   }
8066
8067   g_ptr_array_add (qtdemux->protection_system_ids, NULL);
8068   filtered_sys_ids = gst_protection_filter_systems_by_available_decryptors (
8069       (const gchar **) qtdemux->protection_system_ids->pdata);
8070
8071   g_ptr_array_remove_index (qtdemux->protection_system_ids,
8072       qtdemux->protection_system_ids->len - 1);
8073   GST_TRACE_OBJECT (qtdemux, "detected %u protection systems, we have "
8074       "decryptors for %u of them, running context request",
8075       qtdemux->protection_system_ids->len, g_strv_length (filtered_sys_ids));
8076
8077   if (stream->protection_scheme_event_queue.length) {
8078     GST_TRACE_OBJECT (qtdemux, "using stream event queue, length %u",
8079         stream->protection_scheme_event_queue.length);
8080     walk = stream->protection_scheme_event_queue.tail;
8081   } else {
8082     GST_TRACE_OBJECT (qtdemux, "using demuxer event queue, length %u",
8083         qtdemux->protection_event_queue.length);
8084     walk = qtdemux->protection_event_queue.tail;
8085   }
8086
8087   g_value_init (&event_list, GST_TYPE_LIST);
8088   for (; walk; walk = g_list_previous (walk)) {
8089     GValue *event_value = g_new0 (GValue, 1);
8090     g_value_init (event_value, GST_TYPE_EVENT);
8091     g_value_set_boxed (event_value, walk->data);
8092     gst_value_list_append_and_take_value (&event_list, event_value);
8093   }
8094
8095   /*  2a) Query downstream with GST_QUERY_CONTEXT for the context and
8096    *      check if downstream already has a context of the specific type
8097    *  2b) Query upstream as above.
8098    */
8099   query = gst_query_new_context ("drm-preferred-decryption-system-id");
8100   st = gst_query_writable_structure (query);
8101   gst_structure_set (st, "track-id", G_TYPE_UINT, stream->track_id,
8102       "available-stream-encryption-systems", G_TYPE_STRV, filtered_sys_ids,
8103       NULL);
8104   gst_structure_set_value (st, "stream-encryption-events", &event_list);
8105   if (gst_qtdemux_run_query (element, query, GST_PAD_SRC)) {
8106     gst_query_parse_context (query, &ctxt);
8107     GST_INFO_OBJECT (element, "found context (%p) in downstream query", ctxt);
8108     gst_element_set_context (element, ctxt);
8109   } else if (gst_qtdemux_run_query (element, query, GST_PAD_SINK)) {
8110     gst_query_parse_context (query, &ctxt);
8111     GST_INFO_OBJECT (element, "found context (%p) in upstream query", ctxt);
8112     gst_element_set_context (element, ctxt);
8113   } else {
8114     /* 3) Post a GST_MESSAGE_NEED_CONTEXT message on the bus with
8115      *    the required context type and afterwards check if a
8116      *    usable context was set now as in 1). The message could
8117      *    be handled by the parent bins of the element and the
8118      *    application.
8119      */
8120     GstMessage *msg;
8121
8122     GST_INFO_OBJECT (element, "posting need context message");
8123     msg = gst_message_new_need_context (GST_OBJECT_CAST (element),
8124         "drm-preferred-decryption-system-id");
8125     st = (GstStructure *) gst_message_get_structure (msg);
8126     gst_structure_set (st, "track-id", G_TYPE_UINT, stream->track_id,
8127         "available-stream-encryption-systems", G_TYPE_STRV, filtered_sys_ids,
8128         NULL);
8129
8130     gst_structure_set_value (st, "stream-encryption-events", &event_list);
8131     gst_element_post_message (element, msg);
8132   }
8133
8134   g_strfreev (filtered_sys_ids);
8135   g_value_unset (&event_list);
8136   gst_query_unref (query);
8137 }
8138
8139 static gboolean
8140 gst_qtdemux_configure_protected_caps (GstQTDemux * qtdemux,
8141     QtDemuxStream * stream)
8142 {
8143   GstStructure *s;
8144   const gchar *selected_system = NULL;
8145
8146   g_return_val_if_fail (qtdemux != NULL, FALSE);
8147   g_return_val_if_fail (stream != NULL, FALSE);
8148   g_return_val_if_fail (gst_caps_get_size (CUR_STREAM (stream)->caps) == 1,
8149       FALSE);
8150
8151   if (stream->protection_scheme_type != FOURCC_cenc) {
8152     GST_ERROR_OBJECT (qtdemux, "unsupported protection scheme");
8153     return FALSE;
8154   }
8155   if (qtdemux->protection_system_ids == NULL) {
8156     GST_ERROR_OBJECT (qtdemux, "stream is protected using cenc, but no "
8157         "cenc protection system information has been found");
8158     return FALSE;
8159   }
8160
8161   gst_qtdemux_request_protection_context (qtdemux, stream);
8162   if (qtdemux->preferred_protection_system_id != NULL) {
8163     const gchar *preferred_system_array[] =
8164         { qtdemux->preferred_protection_system_id, NULL };
8165
8166     selected_system = gst_protection_select_system (preferred_system_array);
8167
8168     if (selected_system) {
8169       GST_TRACE_OBJECT (qtdemux, "selected preferred system %s",
8170           qtdemux->preferred_protection_system_id);
8171     } else {
8172       GST_WARNING_OBJECT (qtdemux, "could not select preferred system %s "
8173           "because there is no available decryptor",
8174           qtdemux->preferred_protection_system_id);
8175     }
8176   }
8177
8178   if (!selected_system) {
8179     g_ptr_array_add (qtdemux->protection_system_ids, NULL);
8180     selected_system = gst_protection_select_system ((const gchar **)
8181         qtdemux->protection_system_ids->pdata);
8182     g_ptr_array_remove_index (qtdemux->protection_system_ids,
8183         qtdemux->protection_system_ids->len - 1);
8184   }
8185
8186   if (!selected_system) {
8187     GST_ERROR_OBJECT (qtdemux, "stream is protected, but no "
8188         "suitable decryptor element has been found");
8189     return FALSE;
8190   }
8191
8192   GST_DEBUG_OBJECT (qtdemux, "selected protection system is %s",
8193       selected_system);
8194
8195   s = gst_caps_get_structure (CUR_STREAM (stream)->caps, 0);
8196   if (!gst_structure_has_name (s, "application/x-cenc")) {
8197     gst_structure_set (s,
8198         "original-media-type", G_TYPE_STRING, gst_structure_get_name (s),
8199         GST_PROTECTION_SYSTEM_ID_CAPS_FIELD, G_TYPE_STRING, selected_system,
8200         NULL);
8201     gst_structure_set_name (s, "application/x-cenc");
8202   }
8203   return TRUE;
8204 }
8205
8206 static gboolean
8207 gst_qtdemux_configure_stream (GstQTDemux * qtdemux, QtDemuxStream * stream)
8208 {
8209   if (stream->subtype == FOURCC_vide) {
8210     /* fps is calculated base on the duration of the average framerate since
8211      * qt does not have a fixed framerate. */
8212     gboolean fps_available = TRUE;
8213     guint32 first_duration = 0;
8214
8215     if (stream->n_samples > 0)
8216       first_duration = stream->samples[0].duration;
8217
8218     if ((stream->n_samples == 1 && first_duration == 0)
8219         || (qtdemux->fragmented && stream->n_samples_moof == 1)) {
8220       /* still frame */
8221       CUR_STREAM (stream)->fps_n = 0;
8222       CUR_STREAM (stream)->fps_d = 1;
8223     } else {
8224       if (stream->duration == 0 || stream->n_samples < 2) {
8225         CUR_STREAM (stream)->fps_n = stream->timescale;
8226         CUR_STREAM (stream)->fps_d = 1;
8227         fps_available = FALSE;
8228       } else {
8229         GstClockTime avg_duration;
8230         guint64 duration;
8231         guint32 n_samples;
8232
8233         /* duration and n_samples can be updated for fragmented format
8234          * so, framerate of fragmented format is calculated using data in a moof */
8235         if (qtdemux->fragmented && stream->n_samples_moof > 0
8236             && stream->duration_moof > 0) {
8237           n_samples = stream->n_samples_moof;
8238           duration = stream->duration_moof;
8239         } else {
8240           n_samples = stream->n_samples;
8241           duration = stream->duration;
8242         }
8243
8244         /* Calculate a framerate, ignoring the first sample which is sometimes truncated */
8245         /* stream->duration is guint64, timescale, n_samples are guint32 */
8246         avg_duration =
8247             gst_util_uint64_scale_round (duration -
8248             first_duration, GST_SECOND,
8249             (guint64) (stream->timescale) * (n_samples - 1));
8250
8251         GST_LOG_OBJECT (qtdemux,
8252             "Calculating avg sample duration based on stream (or moof) duration %"
8253             G_GUINT64_FORMAT
8254             " minus first sample %u, leaving %d samples gives %"
8255             GST_TIME_FORMAT, duration, first_duration,
8256             n_samples - 1, GST_TIME_ARGS (avg_duration));
8257
8258         gst_video_guess_framerate (avg_duration, &CUR_STREAM (stream)->fps_n,
8259             &CUR_STREAM (stream)->fps_d);
8260
8261         GST_DEBUG_OBJECT (qtdemux,
8262             "Calculating framerate, timescale %u gave fps_n %d fps_d %d",
8263             stream->timescale, CUR_STREAM (stream)->fps_n,
8264             CUR_STREAM (stream)->fps_d);
8265       }
8266     }
8267
8268     if (CUR_STREAM (stream)->caps) {
8269       CUR_STREAM (stream)->caps =
8270           gst_caps_make_writable (CUR_STREAM (stream)->caps);
8271
8272       gst_caps_set_simple (CUR_STREAM (stream)->caps,
8273           "width", G_TYPE_INT, CUR_STREAM (stream)->width,
8274           "height", G_TYPE_INT, CUR_STREAM (stream)->height, NULL);
8275
8276       /* set framerate if calculated framerate is reliable */
8277       if (fps_available) {
8278         gst_caps_set_simple (CUR_STREAM (stream)->caps,
8279             "framerate", GST_TYPE_FRACTION, CUR_STREAM (stream)->fps_n,
8280             CUR_STREAM (stream)->fps_d, NULL);
8281       }
8282
8283       /* calculate pixel-aspect-ratio using display width and height */
8284       GST_DEBUG_OBJECT (qtdemux,
8285           "video size %dx%d, target display size %dx%d",
8286           CUR_STREAM (stream)->width, CUR_STREAM (stream)->height,
8287           stream->display_width, stream->display_height);
8288       /* qt file might have pasp atom */
8289       if (CUR_STREAM (stream)->par_w > 0 && CUR_STREAM (stream)->par_h > 0) {
8290         GST_DEBUG_OBJECT (qtdemux, "par %d:%d", CUR_STREAM (stream)->par_w,
8291             CUR_STREAM (stream)->par_h);
8292         gst_caps_set_simple (CUR_STREAM (stream)->caps, "pixel-aspect-ratio",
8293             GST_TYPE_FRACTION, CUR_STREAM (stream)->par_w,
8294             CUR_STREAM (stream)->par_h, NULL);
8295       } else if (stream->display_width > 0 && stream->display_height > 0
8296           && CUR_STREAM (stream)->width > 0
8297           && CUR_STREAM (stream)->height > 0) {
8298         gint n, d;
8299
8300         /* calculate the pixel aspect ratio using the display and pixel w/h */
8301         n = stream->display_width * CUR_STREAM (stream)->height;
8302         d = stream->display_height * CUR_STREAM (stream)->width;
8303         if (n == d)
8304           n = d = 1;
8305         GST_DEBUG_OBJECT (qtdemux, "setting PAR to %d/%d", n, d);
8306         CUR_STREAM (stream)->par_w = n;
8307         CUR_STREAM (stream)->par_h = d;
8308         gst_caps_set_simple (CUR_STREAM (stream)->caps, "pixel-aspect-ratio",
8309             GST_TYPE_FRACTION, CUR_STREAM (stream)->par_w,
8310             CUR_STREAM (stream)->par_h, NULL);
8311       }
8312
8313       if (CUR_STREAM (stream)->interlace_mode > 0) {
8314         if (CUR_STREAM (stream)->interlace_mode == 1) {
8315           gst_caps_set_simple (CUR_STREAM (stream)->caps, "interlace-mode",
8316               G_TYPE_STRING, "progressive", NULL);
8317         } else if (CUR_STREAM (stream)->interlace_mode == 2) {
8318           gst_caps_set_simple (CUR_STREAM (stream)->caps, "interlace-mode",
8319               G_TYPE_STRING, "interleaved", NULL);
8320           if (CUR_STREAM (stream)->field_order == 9) {
8321             gst_caps_set_simple (CUR_STREAM (stream)->caps, "field-order",
8322                 G_TYPE_STRING, "top-field-first", NULL);
8323           } else if (CUR_STREAM (stream)->field_order == 14) {
8324             gst_caps_set_simple (CUR_STREAM (stream)->caps, "field-order",
8325                 G_TYPE_STRING, "bottom-field-first", NULL);
8326           }
8327         }
8328       }
8329
8330       /* Create incomplete colorimetry here if needed */
8331       if (CUR_STREAM (stream)->colorimetry.range ||
8332           CUR_STREAM (stream)->colorimetry.matrix ||
8333           CUR_STREAM (stream)->colorimetry.transfer
8334           || CUR_STREAM (stream)->colorimetry.primaries) {
8335         gchar *colorimetry =
8336             gst_video_colorimetry_to_string (&CUR_STREAM (stream)->colorimetry);
8337         gst_caps_set_simple (CUR_STREAM (stream)->caps, "colorimetry",
8338             G_TYPE_STRING, colorimetry, NULL);
8339         g_free (colorimetry);
8340       }
8341
8342       if (stream->multiview_mode != GST_VIDEO_MULTIVIEW_MODE_NONE) {
8343         guint par_w = 1, par_h = 1;
8344
8345         if (CUR_STREAM (stream)->par_w > 0 && CUR_STREAM (stream)->par_h > 0) {
8346           par_w = CUR_STREAM (stream)->par_w;
8347           par_h = CUR_STREAM (stream)->par_h;
8348         }
8349
8350         if (gst_video_multiview_guess_half_aspect (stream->multiview_mode,
8351                 CUR_STREAM (stream)->width, CUR_STREAM (stream)->height, par_w,
8352                 par_h)) {
8353           stream->multiview_flags |= GST_VIDEO_MULTIVIEW_FLAGS_HALF_ASPECT;
8354         }
8355
8356         gst_caps_set_simple (CUR_STREAM (stream)->caps,
8357             "multiview-mode", G_TYPE_STRING,
8358             gst_video_multiview_mode_to_caps_string (stream->multiview_mode),
8359             "multiview-flags", GST_TYPE_VIDEO_MULTIVIEW_FLAGSET,
8360             stream->multiview_flags, GST_FLAG_SET_MASK_EXACT, NULL);
8361       }
8362     }
8363   }
8364
8365   else if (stream->subtype == FOURCC_soun) {
8366     if (CUR_STREAM (stream)->caps) {
8367       CUR_STREAM (stream)->caps =
8368           gst_caps_make_writable (CUR_STREAM (stream)->caps);
8369       if (CUR_STREAM (stream)->rate > 0)
8370         gst_caps_set_simple (CUR_STREAM (stream)->caps,
8371             "rate", G_TYPE_INT, (int) CUR_STREAM (stream)->rate, NULL);
8372       if (CUR_STREAM (stream)->n_channels > 0)
8373         gst_caps_set_simple (CUR_STREAM (stream)->caps,
8374             "channels", G_TYPE_INT, CUR_STREAM (stream)->n_channels, NULL);
8375       if (CUR_STREAM (stream)->n_channels > 2) {
8376         /* FIXME: Need to parse the 'chan' atom to get channel layouts
8377          * correctly; this is just the minimum we can do - assume
8378          * we don't actually have any channel positions. */
8379         gst_caps_set_simple (CUR_STREAM (stream)->caps,
8380             "channel-mask", GST_TYPE_BITMASK, G_GUINT64_CONSTANT (0), NULL);
8381       }
8382     }
8383   }
8384
8385   if (stream->pad) {
8386     GstCaps *prev_caps = NULL;
8387
8388     GST_PAD_ELEMENT_PRIVATE (stream->pad) = stream;
8389     gst_pad_set_event_function (stream->pad, gst_qtdemux_handle_src_event);
8390     gst_pad_set_query_function (stream->pad, gst_qtdemux_handle_src_query);
8391     gst_pad_set_active (stream->pad, TRUE);
8392
8393     gst_pad_use_fixed_caps (stream->pad);
8394
8395     if (stream->protected) {
8396       if (!gst_qtdemux_configure_protected_caps (qtdemux, stream)) {
8397         GST_ERROR_OBJECT (qtdemux,
8398             "Failed to configure protected stream caps.");
8399         return FALSE;
8400       }
8401     }
8402
8403     GST_DEBUG_OBJECT (qtdemux, "setting caps %" GST_PTR_FORMAT,
8404         CUR_STREAM (stream)->caps);
8405     if (stream->new_stream) {
8406       GstEvent *event;
8407       GstStreamFlags stream_flags = GST_STREAM_FLAG_NONE;
8408
8409       event =
8410           gst_pad_get_sticky_event (qtdemux->sinkpad, GST_EVENT_STREAM_START,
8411           0);
8412       if (event) {
8413         gst_event_parse_stream_flags (event, &stream_flags);
8414         if (gst_event_parse_group_id (event, &qtdemux->group_id))
8415           qtdemux->have_group_id = TRUE;
8416         else
8417           qtdemux->have_group_id = FALSE;
8418         gst_event_unref (event);
8419       } else if (!qtdemux->have_group_id) {
8420         qtdemux->have_group_id = TRUE;
8421         qtdemux->group_id = gst_util_group_id_next ();
8422       }
8423
8424       stream->new_stream = FALSE;
8425       event = gst_event_new_stream_start (stream->stream_id);
8426       if (qtdemux->have_group_id)
8427         gst_event_set_group_id (event, qtdemux->group_id);
8428       if (stream->disabled)
8429         stream_flags |= GST_STREAM_FLAG_UNSELECT;
8430       if (CUR_STREAM (stream)->sparse) {
8431         stream_flags |= GST_STREAM_FLAG_SPARSE;
8432       } else {
8433         stream_flags &= ~GST_STREAM_FLAG_SPARSE;
8434       }
8435       gst_event_set_stream_flags (event, stream_flags);
8436       gst_pad_push_event (stream->pad, event);
8437     }
8438
8439     prev_caps = gst_pad_get_current_caps (stream->pad);
8440
8441     if (CUR_STREAM (stream)->caps) {
8442       if (!prev_caps
8443           || !gst_caps_is_equal_fixed (prev_caps, CUR_STREAM (stream)->caps)) {
8444         GST_DEBUG_OBJECT (qtdemux, "setting caps %" GST_PTR_FORMAT,
8445             CUR_STREAM (stream)->caps);
8446         gst_pad_set_caps (stream->pad, CUR_STREAM (stream)->caps);
8447       } else {
8448         GST_DEBUG_OBJECT (qtdemux, "ignore duplicated caps");
8449       }
8450     } else {
8451       GST_WARNING_OBJECT (qtdemux, "stream without caps");
8452     }
8453
8454     if (prev_caps)
8455       gst_caps_unref (prev_caps);
8456     stream->new_caps = FALSE;
8457   }
8458   return TRUE;
8459 }
8460
8461 static void
8462 gst_qtdemux_stream_check_and_change_stsd_index (GstQTDemux * demux,
8463     QtDemuxStream * stream)
8464 {
8465   if (stream->cur_stsd_entry_index == stream->stsd_sample_description_id)
8466     return;
8467
8468   GST_DEBUG_OBJECT (stream->pad, "Changing stsd index from '%u' to '%u'",
8469       stream->cur_stsd_entry_index, stream->stsd_sample_description_id);
8470   if (G_UNLIKELY (stream->stsd_sample_description_id >=
8471           stream->stsd_entries_length)) {
8472     GST_ELEMENT_ERROR (demux, STREAM, DEMUX,
8473         (_("This file is invalid and cannot be played.")),
8474         ("New sample description id is out of bounds (%d >= %d)",
8475             stream->stsd_sample_description_id, stream->stsd_entries_length));
8476   } else {
8477     stream->cur_stsd_entry_index = stream->stsd_sample_description_id;
8478     stream->new_caps = TRUE;
8479   }
8480 }
8481
8482 static gboolean
8483 gst_qtdemux_add_stream (GstQTDemux * qtdemux,
8484     QtDemuxStream * stream, GstTagList * list)
8485 {
8486   gboolean ret = TRUE;
8487   /* consistent default for push based mode */
8488   gst_segment_init (&stream->segment, GST_FORMAT_TIME);
8489
8490   if (stream->subtype == FOURCC_vide) {
8491     gchar *name = g_strdup_printf ("video_%u", qtdemux->n_video_streams);
8492
8493     stream->pad =
8494         gst_pad_new_from_static_template (&gst_qtdemux_videosrc_template, name);
8495     g_free (name);
8496
8497     if (!gst_qtdemux_configure_stream (qtdemux, stream)) {
8498       gst_object_unref (stream->pad);
8499       stream->pad = NULL;
8500       ret = FALSE;
8501       goto done;
8502     }
8503
8504     qtdemux->n_video_streams++;
8505   } else if (stream->subtype == FOURCC_soun) {
8506     gchar *name = g_strdup_printf ("audio_%u", qtdemux->n_audio_streams);
8507
8508     stream->pad =
8509         gst_pad_new_from_static_template (&gst_qtdemux_audiosrc_template, name);
8510     g_free (name);
8511     if (!gst_qtdemux_configure_stream (qtdemux, stream)) {
8512       gst_object_unref (stream->pad);
8513       stream->pad = NULL;
8514       ret = FALSE;
8515       goto done;
8516     }
8517     qtdemux->n_audio_streams++;
8518   } else if (stream->subtype == FOURCC_strm) {
8519     GST_DEBUG_OBJECT (qtdemux, "stream type, not creating pad");
8520   } else if (stream->subtype == FOURCC_subp || stream->subtype == FOURCC_text
8521       || stream->subtype == FOURCC_sbtl || stream->subtype == FOURCC_subt) {
8522     gchar *name = g_strdup_printf ("subtitle_%u", qtdemux->n_sub_streams);
8523
8524     stream->pad =
8525         gst_pad_new_from_static_template (&gst_qtdemux_subsrc_template, name);
8526     g_free (name);
8527     if (!gst_qtdemux_configure_stream (qtdemux, stream)) {
8528       gst_object_unref (stream->pad);
8529       stream->pad = NULL;
8530       ret = FALSE;
8531       goto done;
8532     }
8533     qtdemux->n_sub_streams++;
8534   } else if (CUR_STREAM (stream)->caps) {
8535     gchar *name = g_strdup_printf ("video_%u", qtdemux->n_video_streams);
8536
8537     stream->pad =
8538         gst_pad_new_from_static_template (&gst_qtdemux_videosrc_template, name);
8539     g_free (name);
8540     if (!gst_qtdemux_configure_stream (qtdemux, stream)) {
8541       gst_object_unref (stream->pad);
8542       stream->pad = NULL;
8543       ret = FALSE;
8544       goto done;
8545     }
8546     qtdemux->n_video_streams++;
8547   } else {
8548     GST_DEBUG_OBJECT (qtdemux, "unknown stream type");
8549     goto done;
8550   }
8551
8552   if (stream->pad) {
8553     GList *l;
8554
8555     GST_DEBUG_OBJECT (qtdemux, "adding pad %s %p to qtdemux %p",
8556         GST_OBJECT_NAME (stream->pad), stream->pad, qtdemux);
8557     gst_element_add_pad (GST_ELEMENT_CAST (qtdemux), stream->pad);
8558     gst_flow_combiner_add_pad (qtdemux->flowcombiner, stream->pad);
8559
8560     if (stream->stream_tags)
8561       gst_tag_list_unref (stream->stream_tags);
8562     stream->stream_tags = list;
8563     list = NULL;
8564     /* global tags go on each pad anyway */
8565     stream->send_global_tags = TRUE;
8566     /* send upstream GST_EVENT_PROTECTION events that were received before
8567        this source pad was created */
8568     for (l = qtdemux->protection_event_queue.head; l != NULL; l = l->next)
8569       gst_pad_push_event (stream->pad, gst_event_ref (l->data));
8570   }
8571 done:
8572   if (list)
8573     gst_tag_list_unref (list);
8574   return ret;
8575 }
8576
8577 /* find next atom with @fourcc starting at @offset */
8578 static GstFlowReturn
8579 qtdemux_find_atom (GstQTDemux * qtdemux, guint64 * offset,
8580     guint64 * length, guint32 fourcc)
8581 {
8582   GstFlowReturn ret;
8583   guint32 lfourcc;
8584   GstBuffer *buf;
8585
8586   GST_LOG_OBJECT (qtdemux, "finding fourcc %" GST_FOURCC_FORMAT " at offset %"
8587       G_GUINT64_FORMAT, GST_FOURCC_ARGS (fourcc), *offset);
8588
8589   while (TRUE) {
8590     GstMapInfo map;
8591
8592     buf = NULL;
8593     ret = gst_pad_pull_range (qtdemux->sinkpad, *offset, 16, &buf);
8594     if (G_UNLIKELY (ret != GST_FLOW_OK))
8595       goto locate_failed;
8596     if (G_UNLIKELY (gst_buffer_get_size (buf) != 16)) {
8597       /* likely EOF */
8598       ret = GST_FLOW_EOS;
8599       gst_buffer_unref (buf);
8600       goto locate_failed;
8601     }
8602     gst_buffer_map (buf, &map, GST_MAP_READ);
8603     extract_initial_length_and_fourcc (map.data, 16, length, &lfourcc);
8604     gst_buffer_unmap (buf, &map);
8605     gst_buffer_unref (buf);
8606
8607     if (G_UNLIKELY (*length == 0)) {
8608       GST_DEBUG_OBJECT (qtdemux, "invalid length 0");
8609       ret = GST_FLOW_ERROR;
8610       goto locate_failed;
8611     }
8612
8613     if (lfourcc == fourcc) {
8614       GST_DEBUG_OBJECT (qtdemux, "found fourcc at offset %" G_GUINT64_FORMAT,
8615           *offset);
8616       break;
8617     } else {
8618       GST_LOG_OBJECT (qtdemux,
8619           "skipping atom '%" GST_FOURCC_FORMAT "' at %" G_GUINT64_FORMAT,
8620           GST_FOURCC_ARGS (fourcc), *offset);
8621       *offset += *length;
8622     }
8623   }
8624
8625   return GST_FLOW_OK;
8626
8627 locate_failed:
8628   {
8629     /* might simply have had last one */
8630     GST_DEBUG_OBJECT (qtdemux, "fourcc not found");
8631     return ret;
8632   }
8633 }
8634
8635 /* should only do something in pull mode */
8636 /* call with OBJECT lock */
8637 static GstFlowReturn
8638 qtdemux_add_fragmented_samples (GstQTDemux * qtdemux)
8639 {
8640   guint64 length, offset;
8641   GstBuffer *buf = NULL;
8642   GstFlowReturn ret = GST_FLOW_OK;
8643   GstFlowReturn res = GST_FLOW_OK;
8644   GstMapInfo map;
8645
8646   offset = qtdemux->moof_offset;
8647   GST_DEBUG_OBJECT (qtdemux, "next moof at offset %" G_GUINT64_FORMAT, offset);
8648
8649   if (!offset) {
8650     GST_DEBUG_OBJECT (qtdemux, "no next moof");
8651     return GST_FLOW_EOS;
8652   }
8653
8654   /* best not do pull etc with lock held */
8655   GST_OBJECT_UNLOCK (qtdemux);
8656
8657   ret = qtdemux_find_atom (qtdemux, &offset, &length, FOURCC_moof);
8658   if (ret != GST_FLOW_OK)
8659     goto flow_failed;
8660
8661   ret = gst_qtdemux_pull_atom (qtdemux, offset, length, &buf);
8662   if (G_UNLIKELY (ret != GST_FLOW_OK))
8663     goto flow_failed;
8664   gst_buffer_map (buf, &map, GST_MAP_READ);
8665   if (!qtdemux_parse_moof (qtdemux, map.data, map.size, offset, NULL)) {
8666     gst_buffer_unmap (buf, &map);
8667     gst_buffer_unref (buf);
8668     buf = NULL;
8669     goto parse_failed;
8670   }
8671
8672   gst_buffer_unmap (buf, &map);
8673   gst_buffer_unref (buf);
8674   buf = NULL;
8675
8676   offset += length;
8677   /* look for next moof */
8678   ret = qtdemux_find_atom (qtdemux, &offset, &length, FOURCC_moof);
8679   if (G_UNLIKELY (ret != GST_FLOW_OK))
8680     goto flow_failed;
8681
8682 exit:
8683   GST_OBJECT_LOCK (qtdemux);
8684
8685   qtdemux->moof_offset = offset;
8686
8687   return res;
8688
8689 parse_failed:
8690   {
8691     GST_DEBUG_OBJECT (qtdemux, "failed to parse moof");
8692     offset = 0;
8693     res = GST_FLOW_ERROR;
8694     goto exit;
8695   }
8696 flow_failed:
8697   {
8698     /* maybe upstream temporarily flushing */
8699     if (ret != GST_FLOW_FLUSHING) {
8700       GST_DEBUG_OBJECT (qtdemux, "no next moof");
8701       offset = 0;
8702     } else {
8703       GST_DEBUG_OBJECT (qtdemux, "upstream WRONG_STATE");
8704       /* resume at current position next time */
8705     }
8706     res = ret;
8707     goto exit;
8708   }
8709 }
8710
8711 /* initialise bytereaders for stbl sub-atoms */
8712 static gboolean
8713 qtdemux_stbl_init (GstQTDemux * qtdemux, QtDemuxStream * stream, GNode * stbl)
8714 {
8715   stream->stbl_index = -1;      /* no samples have yet been parsed */
8716   stream->sample_index = -1;
8717
8718   /* time-to-sample atom */
8719   if (!qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stts, &stream->stts))
8720     goto corrupt_file;
8721
8722   /* copy atom data into a new buffer for later use */
8723   stream->stts.data = g_memdup (stream->stts.data, stream->stts.size);
8724
8725   /* skip version + flags */
8726   if (!gst_byte_reader_skip (&stream->stts, 1 + 3) ||
8727       !gst_byte_reader_get_uint32_be (&stream->stts, &stream->n_sample_times))
8728     goto corrupt_file;
8729   GST_LOG_OBJECT (qtdemux, "%u timestamp blocks", stream->n_sample_times);
8730
8731   /* make sure there's enough data */
8732   if (!qt_atom_parser_has_chunks (&stream->stts, stream->n_sample_times, 8)) {
8733     stream->n_sample_times = gst_byte_reader_get_remaining (&stream->stts) / 8;
8734     GST_LOG_OBJECT (qtdemux, "overriding to %u timestamp blocks",
8735         stream->n_sample_times);
8736     if (!stream->n_sample_times)
8737       goto corrupt_file;
8738   }
8739
8740   /* sync sample atom */
8741   stream->stps_present = FALSE;
8742   if ((stream->stss_present =
8743           ! !qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stss,
8744               &stream->stss) ? TRUE : FALSE) == TRUE) {
8745     /* copy atom data into a new buffer for later use */
8746     stream->stss.data = g_memdup (stream->stss.data, stream->stss.size);
8747
8748     /* skip version + flags */
8749     if (!gst_byte_reader_skip (&stream->stss, 1 + 3) ||
8750         !gst_byte_reader_get_uint32_be (&stream->stss, &stream->n_sample_syncs))
8751       goto corrupt_file;
8752
8753     if (stream->n_sample_syncs) {
8754       /* make sure there's enough data */
8755       if (!qt_atom_parser_has_chunks (&stream->stss, stream->n_sample_syncs, 4))
8756         goto corrupt_file;
8757     }
8758
8759     /* partial sync sample atom */
8760     if ((stream->stps_present =
8761             ! !qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stps,
8762                 &stream->stps) ? TRUE : FALSE) == TRUE) {
8763       /* copy atom data into a new buffer for later use */
8764       stream->stps.data = g_memdup (stream->stps.data, stream->stps.size);
8765
8766       /* skip version + flags */
8767       if (!gst_byte_reader_skip (&stream->stps, 1 + 3) ||
8768           !gst_byte_reader_get_uint32_be (&stream->stps,
8769               &stream->n_sample_partial_syncs))
8770         goto corrupt_file;
8771
8772       /* if there are no entries, the stss table contains the real
8773        * sync samples */
8774       if (stream->n_sample_partial_syncs) {
8775         /* make sure there's enough data */
8776         if (!qt_atom_parser_has_chunks (&stream->stps,
8777                 stream->n_sample_partial_syncs, 4))
8778           goto corrupt_file;
8779       }
8780     }
8781   }
8782
8783   /* sample size */
8784   if (!qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stsz, &stream->stsz))
8785     goto no_samples;
8786
8787   /* copy atom data into a new buffer for later use */
8788   stream->stsz.data = g_memdup (stream->stsz.data, stream->stsz.size);
8789
8790   /* skip version + flags */
8791   if (!gst_byte_reader_skip (&stream->stsz, 1 + 3) ||
8792       !gst_byte_reader_get_uint32_be (&stream->stsz, &stream->sample_size))
8793     goto corrupt_file;
8794
8795   if (!gst_byte_reader_get_uint32_be (&stream->stsz, &stream->n_samples))
8796     goto corrupt_file;
8797
8798   if (!stream->n_samples)
8799     goto no_samples;
8800
8801   /* sample-to-chunk atom */
8802   if (!qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stsc, &stream->stsc))
8803     goto corrupt_file;
8804
8805   /* copy atom data into a new buffer for later use */
8806   stream->stsc.data = g_memdup (stream->stsc.data, stream->stsc.size);
8807
8808   /* skip version + flags */
8809   if (!gst_byte_reader_skip (&stream->stsc, 1 + 3) ||
8810       !gst_byte_reader_get_uint32_be (&stream->stsc,
8811           &stream->n_samples_per_chunk))
8812     goto corrupt_file;
8813
8814   GST_DEBUG_OBJECT (qtdemux, "n_samples_per_chunk %u",
8815       stream->n_samples_per_chunk);
8816
8817   /* make sure there's enough data */
8818   if (!qt_atom_parser_has_chunks (&stream->stsc, stream->n_samples_per_chunk,
8819           12))
8820     goto corrupt_file;
8821
8822
8823   /* chunk offset */
8824   if (qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stco, &stream->stco))
8825     stream->co_size = sizeof (guint32);
8826   else if (qtdemux_tree_get_child_by_type_full (stbl, FOURCC_co64,
8827           &stream->stco))
8828     stream->co_size = sizeof (guint64);
8829   else
8830     goto corrupt_file;
8831
8832   /* copy atom data into a new buffer for later use */
8833   stream->stco.data = g_memdup (stream->stco.data, stream->stco.size);
8834
8835   /* skip version + flags */
8836   if (!gst_byte_reader_skip (&stream->stco, 1 + 3))
8837     goto corrupt_file;
8838
8839   /* chunks_are_samples == TRUE means treat chunks as samples */
8840   stream->chunks_are_samples = stream->sample_size
8841       && !CUR_STREAM (stream)->sampled;
8842   if (stream->chunks_are_samples) {
8843     /* treat chunks as samples */
8844     if (!gst_byte_reader_get_uint32_be (&stream->stco, &stream->n_samples))
8845       goto corrupt_file;
8846   } else {
8847     /* skip number of entries */
8848     if (!gst_byte_reader_skip (&stream->stco, 4))
8849       goto corrupt_file;
8850
8851     /* make sure there are enough data in the stsz atom */
8852     if (!stream->sample_size) {
8853       /* different sizes for each sample */
8854       if (!qt_atom_parser_has_chunks (&stream->stsz, stream->n_samples, 4))
8855         goto corrupt_file;
8856     }
8857   }
8858
8859   GST_DEBUG_OBJECT (qtdemux, "allocating n_samples %u * %u (%.2f MB)",
8860       stream->n_samples, (guint) sizeof (QtDemuxSample),
8861       stream->n_samples * sizeof (QtDemuxSample) / (1024.0 * 1024.0));
8862
8863   if (stream->n_samples >=
8864       QTDEMUX_MAX_SAMPLE_INDEX_SIZE / sizeof (QtDemuxSample)) {
8865     GST_WARNING_OBJECT (qtdemux, "not allocating index of %d samples, would "
8866         "be larger than %uMB (broken file?)", stream->n_samples,
8867         QTDEMUX_MAX_SAMPLE_INDEX_SIZE >> 20);
8868     return FALSE;
8869   }
8870
8871   g_assert (stream->samples == NULL);
8872   stream->samples = g_try_new0 (QtDemuxSample, stream->n_samples);
8873   if (!stream->samples) {
8874     GST_WARNING_OBJECT (qtdemux, "failed to allocate %d samples",
8875         stream->n_samples);
8876     return FALSE;
8877   }
8878
8879   /* composition time-to-sample */
8880   if ((stream->ctts_present =
8881           ! !qtdemux_tree_get_child_by_type_full (stbl, FOURCC_ctts,
8882               &stream->ctts) ? TRUE : FALSE) == TRUE) {
8883     GstByteReader cslg = GST_BYTE_READER_INIT (NULL, 0);
8884
8885     /* copy atom data into a new buffer for later use */
8886     stream->ctts.data = g_memdup (stream->ctts.data, stream->ctts.size);
8887
8888     /* skip version + flags */
8889     if (!gst_byte_reader_skip (&stream->ctts, 1 + 3)
8890         || !gst_byte_reader_get_uint32_be (&stream->ctts,
8891             &stream->n_composition_times))
8892       goto corrupt_file;
8893
8894     /* make sure there's enough data */
8895     if (!qt_atom_parser_has_chunks (&stream->ctts, stream->n_composition_times,
8896             4 + 4))
8897       goto corrupt_file;
8898
8899     /* This is optional, if missing we iterate the ctts */
8900     if (qtdemux_tree_get_child_by_type_full (stbl, FOURCC_cslg, &cslg)) {
8901       if (!gst_byte_reader_skip (&cslg, 1 + 3)
8902           || !gst_byte_reader_get_uint32_be (&cslg, &stream->cslg_shift)) {
8903         g_free ((gpointer) cslg.data);
8904         goto corrupt_file;
8905       }
8906     } else {
8907       gint32 cslg_least = 0;
8908       guint num_entries, pos;
8909       gint i;
8910
8911       pos = gst_byte_reader_get_pos (&stream->ctts);
8912       num_entries = stream->n_composition_times;
8913
8914       stream->cslg_shift = 0;
8915
8916       for (i = 0; i < num_entries; i++) {
8917         gint32 offset;
8918
8919         gst_byte_reader_skip_unchecked (&stream->ctts, 4);
8920         offset = gst_byte_reader_get_int32_be_unchecked (&stream->ctts);
8921
8922         if (offset < cslg_least)
8923           cslg_least = offset;
8924       }
8925
8926       if (cslg_least < 0)
8927         stream->cslg_shift = ABS (cslg_least);
8928       else
8929         stream->cslg_shift = 0;
8930
8931       /* reset the reader so we can generate sample table */
8932       gst_byte_reader_set_pos (&stream->ctts, pos);
8933     }
8934   } else {
8935     /* Ensure the cslg_shift value is consistent so we can use it
8936      * unconditionnally to produce TS and Segment */
8937     stream->cslg_shift = 0;
8938   }
8939
8940   return TRUE;
8941
8942 corrupt_file:
8943   {
8944     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
8945         (_("This file is corrupt and cannot be played.")), (NULL));
8946     return FALSE;
8947   }
8948 no_samples:
8949   {
8950     gst_qtdemux_stbl_free (stream);
8951     if (!qtdemux->fragmented) {
8952       /* not quite good */
8953       GST_WARNING_OBJECT (qtdemux, "stream has no samples");
8954       return FALSE;
8955     } else {
8956       /* may pick up samples elsewhere */
8957       return TRUE;
8958     }
8959   }
8960 }
8961
8962 /* collect samples from the next sample to be parsed up to sample @n for @stream
8963  * by reading the info from @stbl
8964  *
8965  * This code can be executed from both the streaming thread and the seeking
8966  * thread so it takes the object lock to protect itself
8967  */
8968 static gboolean
8969 qtdemux_parse_samples (GstQTDemux * qtdemux, QtDemuxStream * stream, guint32 n)
8970 {
8971   gint i, j, k;
8972   QtDemuxSample *samples, *first, *cur, *last;
8973   guint32 n_samples_per_chunk;
8974   guint32 n_samples;
8975
8976   GST_LOG_OBJECT (qtdemux, "parsing samples for stream fourcc %"
8977       GST_FOURCC_FORMAT ", pad %s",
8978       GST_FOURCC_ARGS (CUR_STREAM (stream)->fourcc),
8979       stream->pad ? GST_PAD_NAME (stream->pad) : "(NULL)");
8980
8981   n_samples = stream->n_samples;
8982
8983   if (n >= n_samples)
8984     goto out_of_samples;
8985
8986   GST_OBJECT_LOCK (qtdemux);
8987   if (n <= stream->stbl_index)
8988     goto already_parsed;
8989
8990   GST_DEBUG_OBJECT (qtdemux, "parsing up to sample %u", n);
8991
8992   if (!stream->stsz.data) {
8993     /* so we already parsed and passed all the moov samples;
8994      * onto fragmented ones */
8995     g_assert (qtdemux->fragmented);
8996     goto done;
8997   }
8998
8999   /* pointer to the sample table */
9000   samples = stream->samples;
9001
9002   /* starts from -1, moves to the next sample index to parse */
9003   stream->stbl_index++;
9004
9005   /* keep track of the first and last sample to fill */
9006   first = &samples[stream->stbl_index];
9007   last = &samples[n];
9008
9009   if (!stream->chunks_are_samples) {
9010     /* set the sample sizes */
9011     if (stream->sample_size == 0) {
9012       /* different sizes for each sample */
9013       for (cur = first; cur <= last; cur++) {
9014         cur->size = gst_byte_reader_get_uint32_be_unchecked (&stream->stsz);
9015         GST_LOG_OBJECT (qtdemux, "sample %d has size %u",
9016             (guint) (cur - samples), cur->size);
9017       }
9018     } else {
9019       /* samples have the same size */
9020       GST_LOG_OBJECT (qtdemux, "all samples have size %u", stream->sample_size);
9021       for (cur = first; cur <= last; cur++)
9022         cur->size = stream->sample_size;
9023     }
9024   }
9025
9026   n_samples_per_chunk = stream->n_samples_per_chunk;
9027   cur = first;
9028
9029   for (i = stream->stsc_index; i < n_samples_per_chunk; i++) {
9030     guint32 last_chunk;
9031
9032     if (stream->stsc_chunk_index >= stream->last_chunk
9033         || stream->stsc_chunk_index < stream->first_chunk) {
9034       stream->first_chunk =
9035           gst_byte_reader_get_uint32_be_unchecked (&stream->stsc);
9036       stream->samples_per_chunk =
9037           gst_byte_reader_get_uint32_be_unchecked (&stream->stsc);
9038       /* starts from 1 */
9039       stream->stsd_sample_description_id =
9040           gst_byte_reader_get_uint32_be_unchecked (&stream->stsc) - 1;
9041
9042       /* chunk numbers are counted from 1 it seems */
9043       if (G_UNLIKELY (stream->first_chunk == 0))
9044         goto corrupt_file;
9045
9046       --stream->first_chunk;
9047
9048       /* the last chunk of each entry is calculated by taking the first chunk
9049        * of the next entry; except if there is no next, where we fake it with
9050        * INT_MAX */
9051       if (G_UNLIKELY (i == (stream->n_samples_per_chunk - 1))) {
9052         stream->last_chunk = G_MAXUINT32;
9053       } else {
9054         stream->last_chunk =
9055             gst_byte_reader_peek_uint32_be_unchecked (&stream->stsc);
9056         if (G_UNLIKELY (stream->last_chunk == 0))
9057           goto corrupt_file;
9058
9059         --stream->last_chunk;
9060       }
9061
9062       GST_LOG_OBJECT (qtdemux,
9063           "entry %d has first_chunk %d, last_chunk %d, samples_per_chunk %d"
9064           "sample desc ID: %d", i, stream->first_chunk, stream->last_chunk,
9065           stream->samples_per_chunk, stream->stsd_sample_description_id);
9066
9067       if (G_UNLIKELY (stream->last_chunk < stream->first_chunk))
9068         goto corrupt_file;
9069
9070       if (stream->last_chunk != G_MAXUINT32) {
9071         if (!qt_atom_parser_peek_sub (&stream->stco,
9072                 stream->first_chunk * stream->co_size,
9073                 (stream->last_chunk - stream->first_chunk) * stream->co_size,
9074                 &stream->co_chunk))
9075           goto corrupt_file;
9076
9077       } else {
9078         stream->co_chunk = stream->stco;
9079         if (!gst_byte_reader_skip (&stream->co_chunk,
9080                 stream->first_chunk * stream->co_size))
9081           goto corrupt_file;
9082       }
9083
9084       stream->stsc_chunk_index = stream->first_chunk;
9085     }
9086
9087     last_chunk = stream->last_chunk;
9088
9089     if (stream->chunks_are_samples) {
9090       cur = &samples[stream->stsc_chunk_index];
9091
9092       for (j = stream->stsc_chunk_index; j < last_chunk; j++) {
9093         if (j > n) {
9094           /* save state */
9095           stream->stsc_chunk_index = j;
9096           goto done;
9097         }
9098
9099         cur->offset =
9100             qt_atom_parser_get_offset_unchecked (&stream->co_chunk,
9101             stream->co_size);
9102
9103         GST_LOG_OBJECT (qtdemux, "Created entry %d with offset "
9104             "%" G_GUINT64_FORMAT, j, cur->offset);
9105
9106         if (CUR_STREAM (stream)->samples_per_frame > 0 &&
9107             CUR_STREAM (stream)->bytes_per_frame > 0) {
9108           cur->size =
9109               (stream->samples_per_chunk * CUR_STREAM (stream)->n_channels) /
9110               CUR_STREAM (stream)->samples_per_frame *
9111               CUR_STREAM (stream)->bytes_per_frame;
9112         } else {
9113           cur->size = stream->samples_per_chunk;
9114         }
9115
9116         GST_DEBUG_OBJECT (qtdemux,
9117             "keyframe sample %d: timestamp %" GST_TIME_FORMAT ", size %u",
9118             j, GST_TIME_ARGS (QTSTREAMTIME_TO_GSTTIME (stream,
9119                     stream->stco_sample_index)), cur->size);
9120
9121         cur->timestamp = stream->stco_sample_index;
9122         cur->duration = stream->samples_per_chunk;
9123         cur->keyframe = TRUE;
9124         cur++;
9125
9126         stream->stco_sample_index += stream->samples_per_chunk;
9127       }
9128       stream->stsc_chunk_index = j;
9129     } else {
9130       for (j = stream->stsc_chunk_index; j < last_chunk; j++) {
9131         guint32 samples_per_chunk;
9132         guint64 chunk_offset;
9133
9134         if (!stream->stsc_sample_index
9135             && !qt_atom_parser_get_offset (&stream->co_chunk, stream->co_size,
9136                 &stream->chunk_offset))
9137           goto corrupt_file;
9138
9139         samples_per_chunk = stream->samples_per_chunk;
9140         chunk_offset = stream->chunk_offset;
9141
9142         for (k = stream->stsc_sample_index; k < samples_per_chunk; k++) {
9143           GST_LOG_OBJECT (qtdemux, "creating entry %d with offset %"
9144               G_GUINT64_FORMAT " and size %d",
9145               (guint) (cur - samples), chunk_offset, cur->size);
9146
9147           cur->offset = chunk_offset;
9148           chunk_offset += cur->size;
9149           cur++;
9150
9151           if (G_UNLIKELY (cur > last)) {
9152             /* save state */
9153             stream->stsc_sample_index = k + 1;
9154             stream->chunk_offset = chunk_offset;
9155             stream->stsc_chunk_index = j;
9156             goto done2;
9157           }
9158         }
9159         stream->stsc_sample_index = 0;
9160       }
9161       stream->stsc_chunk_index = j;
9162     }
9163     stream->stsc_index++;
9164   }
9165
9166   if (stream->chunks_are_samples)
9167     goto ctts;
9168 done2:
9169   {
9170     guint32 n_sample_times;
9171
9172     n_sample_times = stream->n_sample_times;
9173     cur = first;
9174
9175     for (i = stream->stts_index; i < n_sample_times; i++) {
9176       guint32 stts_samples;
9177       gint32 stts_duration;
9178       gint64 stts_time;
9179
9180       if (stream->stts_sample_index >= stream->stts_samples
9181           || !stream->stts_sample_index) {
9182
9183         stream->stts_samples =
9184             gst_byte_reader_get_uint32_be_unchecked (&stream->stts);
9185         stream->stts_duration =
9186             gst_byte_reader_get_uint32_be_unchecked (&stream->stts);
9187
9188         GST_LOG_OBJECT (qtdemux, "block %d, %u timestamps, duration %u",
9189             i, stream->stts_samples, stream->stts_duration);
9190
9191         stream->stts_sample_index = 0;
9192       }
9193
9194       stts_samples = stream->stts_samples;
9195       stts_duration = stream->stts_duration;
9196       stts_time = stream->stts_time;
9197
9198       for (j = stream->stts_sample_index; j < stts_samples; j++) {
9199         GST_DEBUG_OBJECT (qtdemux,
9200             "sample %d: index %d, timestamp %" GST_TIME_FORMAT,
9201             (guint) (cur - samples), j,
9202             GST_TIME_ARGS (QTSTREAMTIME_TO_GSTTIME (stream, stts_time)));
9203
9204         cur->timestamp = stts_time;
9205         cur->duration = stts_duration;
9206
9207         /* avoid 32-bit wrap-around,
9208          * but still mind possible 'negative' duration */
9209         stts_time += (gint64) stts_duration;
9210         cur++;
9211
9212         if (G_UNLIKELY (cur > last)) {
9213           /* save values */
9214           stream->stts_time = stts_time;
9215           stream->stts_sample_index = j + 1;
9216           if (stream->stts_sample_index >= stream->stts_samples)
9217             stream->stts_index++;
9218           goto done3;
9219         }
9220       }
9221       stream->stts_sample_index = 0;
9222       stream->stts_time = stts_time;
9223       stream->stts_index++;
9224     }
9225     /* fill up empty timestamps with the last timestamp, this can happen when
9226      * the last samples do not decode and so we don't have timestamps for them.
9227      * We however look at the last timestamp to estimate the track length so we
9228      * need something in here. */
9229     for (; cur < last; cur++) {
9230       GST_DEBUG_OBJECT (qtdemux,
9231           "fill sample %d: timestamp %" GST_TIME_FORMAT,
9232           (guint) (cur - samples),
9233           GST_TIME_ARGS (QTSTREAMTIME_TO_GSTTIME (stream, stream->stts_time)));
9234       cur->timestamp = stream->stts_time;
9235       cur->duration = -1;
9236     }
9237   }
9238 done3:
9239   {
9240     /* sample sync, can be NULL */
9241     if (stream->stss_present == TRUE) {
9242       guint32 n_sample_syncs;
9243
9244       n_sample_syncs = stream->n_sample_syncs;
9245
9246       if (!n_sample_syncs) {
9247         GST_DEBUG_OBJECT (qtdemux, "all samples are keyframes");
9248         stream->all_keyframe = TRUE;
9249       } else {
9250         for (i = stream->stss_index; i < n_sample_syncs; i++) {
9251           /* note that the first sample is index 1, not 0 */
9252           guint32 index;
9253
9254           index = gst_byte_reader_get_uint32_be_unchecked (&stream->stss);
9255
9256           if (G_LIKELY (index > 0 && index <= n_samples)) {
9257             index -= 1;
9258             samples[index].keyframe = TRUE;
9259             GST_DEBUG_OBJECT (qtdemux, "samples at %u is keyframe", index);
9260             /* and exit if we have enough samples */
9261             if (G_UNLIKELY (index >= n)) {
9262               i++;
9263               break;
9264             }
9265           }
9266         }
9267         /* save state */
9268         stream->stss_index = i;
9269       }
9270
9271       /* stps marks partial sync frames like open GOP I-Frames */
9272       if (stream->stps_present == TRUE) {
9273         guint32 n_sample_partial_syncs;
9274
9275         n_sample_partial_syncs = stream->n_sample_partial_syncs;
9276
9277         /* if there are no entries, the stss table contains the real
9278          * sync samples */
9279         if (n_sample_partial_syncs) {
9280           for (i = stream->stps_index; i < n_sample_partial_syncs; i++) {
9281             /* note that the first sample is index 1, not 0 */
9282             guint32 index;
9283
9284             index = gst_byte_reader_get_uint32_be_unchecked (&stream->stps);
9285
9286             if (G_LIKELY (index > 0 && index <= n_samples)) {
9287               index -= 1;
9288               samples[index].keyframe = TRUE;
9289               GST_DEBUG_OBJECT (qtdemux, "samples at %u is keyframe", index);
9290               /* and exit if we have enough samples */
9291               if (G_UNLIKELY (index >= n)) {
9292                 i++;
9293                 break;
9294               }
9295             }
9296           }
9297           /* save state */
9298           stream->stps_index = i;
9299         }
9300       }
9301     } else {
9302       /* no stss, all samples are keyframes */
9303       stream->all_keyframe = TRUE;
9304       GST_DEBUG_OBJECT (qtdemux, "setting all keyframes");
9305     }
9306   }
9307
9308 ctts:
9309   /* composition time to sample */
9310   if (stream->ctts_present == TRUE) {
9311     guint32 n_composition_times;
9312     guint32 ctts_count;
9313     gint32 ctts_soffset;
9314
9315     /* Fill in the pts_offsets */
9316     cur = first;
9317     n_composition_times = stream->n_composition_times;
9318
9319     for (i = stream->ctts_index; i < n_composition_times; i++) {
9320       if (stream->ctts_sample_index >= stream->ctts_count
9321           || !stream->ctts_sample_index) {
9322         stream->ctts_count =
9323             gst_byte_reader_get_uint32_be_unchecked (&stream->ctts);
9324         stream->ctts_soffset =
9325             gst_byte_reader_get_int32_be_unchecked (&stream->ctts);
9326         stream->ctts_sample_index = 0;
9327       }
9328
9329       ctts_count = stream->ctts_count;
9330       ctts_soffset = stream->ctts_soffset;
9331
9332       for (j = stream->ctts_sample_index; j < ctts_count; j++) {
9333         cur->pts_offset = ctts_soffset;
9334         cur++;
9335
9336         if (G_UNLIKELY (cur > last)) {
9337           /* save state */
9338           stream->ctts_sample_index = j + 1;
9339           goto done;
9340         }
9341       }
9342       stream->ctts_sample_index = 0;
9343       stream->ctts_index++;
9344     }
9345   }
9346 done:
9347   stream->stbl_index = n;
9348   /* if index has been completely parsed, free data that is no-longer needed */
9349   if (n + 1 == stream->n_samples) {
9350     gst_qtdemux_stbl_free (stream);
9351     GST_DEBUG_OBJECT (qtdemux, "parsed all available samples;");
9352     if (qtdemux->pullbased) {
9353       GST_DEBUG_OBJECT (qtdemux, "checking for more samples");
9354       while (n + 1 == stream->n_samples)
9355         if (qtdemux_add_fragmented_samples (qtdemux) != GST_FLOW_OK)
9356           break;
9357     }
9358   }
9359   GST_OBJECT_UNLOCK (qtdemux);
9360
9361   return TRUE;
9362
9363   /* SUCCESS */
9364 already_parsed:
9365   {
9366     GST_LOG_OBJECT (qtdemux,
9367         "Tried to parse up to sample %u but this sample has already been parsed",
9368         n);
9369     /* if fragmented, there may be more */
9370     if (qtdemux->fragmented && n == stream->stbl_index)
9371       goto done;
9372     GST_OBJECT_UNLOCK (qtdemux);
9373     return TRUE;
9374   }
9375   /* ERRORS */
9376 out_of_samples:
9377   {
9378     GST_LOG_OBJECT (qtdemux,
9379         "Tried to parse up to sample %u but there are only %u samples", n + 1,
9380         stream->n_samples);
9381     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
9382         (_("This file is corrupt and cannot be played.")), (NULL));
9383     return FALSE;
9384   }
9385 corrupt_file:
9386   {
9387     GST_OBJECT_UNLOCK (qtdemux);
9388     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
9389         (_("This file is corrupt and cannot be played.")), (NULL));
9390     return FALSE;
9391   }
9392 }
9393
9394 /* collect all segment info for @stream.
9395  */
9396 static gboolean
9397 qtdemux_parse_segments (GstQTDemux * qtdemux, QtDemuxStream * stream,
9398     GNode * trak)
9399 {
9400   GNode *edts;
9401   /* accept edts if they contain gaps at start and there is only
9402    * one media segment */
9403   gboolean allow_pushbased_edts = TRUE;
9404   gint media_segments_count = 0;
9405
9406   /* parse and prepare segment info from the edit list */
9407   GST_DEBUG_OBJECT (qtdemux, "looking for edit list container");
9408   stream->n_segments = 0;
9409   stream->segments = NULL;
9410   if ((edts = qtdemux_tree_get_child_by_type (trak, FOURCC_edts))) {
9411     GNode *elst;
9412     gint n_segments;
9413     gint segment_number, entry_size;
9414     guint64 time;
9415     GstClockTime stime;
9416     const guint8 *buffer;
9417     guint8 version;
9418     guint32 size;
9419
9420     GST_DEBUG_OBJECT (qtdemux, "looking for edit list");
9421     if (!(elst = qtdemux_tree_get_child_by_type (edts, FOURCC_elst)))
9422       goto done;
9423
9424     buffer = elst->data;
9425
9426     size = QT_UINT32 (buffer);
9427     /* version, flags, n_segments */
9428     if (size < 16) {
9429       GST_WARNING_OBJECT (qtdemux, "Invalid edit list");
9430       goto done;
9431     }
9432     version = QT_UINT8 (buffer + 8);
9433     entry_size = (version == 1) ? 20 : 12;
9434
9435     n_segments = QT_UINT32 (buffer + 12);
9436
9437     if (n_segments > 100000 || size < 16 + n_segments * entry_size) {
9438       GST_WARNING_OBJECT (qtdemux, "Invalid edit list");
9439       goto done;
9440     }
9441
9442     /* we might allocate a bit too much, at least allocate 1 segment */
9443     stream->segments = g_new (QtDemuxSegment, MAX (n_segments, 1));
9444
9445     /* segments always start from 0 */
9446     time = 0;
9447     stime = 0;
9448     buffer += 16;
9449     for (segment_number = 0; segment_number < n_segments; segment_number++) {
9450       guint64 duration;
9451       guint64 media_time;
9452       gboolean empty_edit = FALSE;
9453       QtDemuxSegment *segment;
9454       guint32 rate_int;
9455       GstClockTime media_start = GST_CLOCK_TIME_NONE;
9456
9457       if (version == 1) {
9458         media_time = QT_UINT64 (buffer + 8);
9459         duration = QT_UINT64 (buffer);
9460         if (media_time == G_MAXUINT64)
9461           empty_edit = TRUE;
9462       } else {
9463         media_time = QT_UINT32 (buffer + 4);
9464         duration = QT_UINT32 (buffer);
9465         if (media_time == G_MAXUINT32)
9466           empty_edit = TRUE;
9467       }
9468
9469       if (!empty_edit)
9470         media_start = QTSTREAMTIME_TO_GSTTIME (stream, media_time);
9471
9472       segment = &stream->segments[segment_number];
9473
9474       /* time and duration expressed in global timescale */
9475       segment->time = stime;
9476       if (duration != 0 || empty_edit) {
9477         /* edge case: empty edits with duration=zero are treated here.
9478          * (files should not have these anyway). */
9479
9480         /* add non scaled values so we don't cause roundoff errors */
9481         time += duration;
9482         stime = QTTIME_TO_GSTTIME (qtdemux, time);
9483         segment->duration = stime - segment->time;
9484       } else {
9485         /* zero duration does not imply media_start == media_stop
9486          * but, only specify media_start. The edit ends with the track. */
9487         stime = segment->duration = GST_CLOCK_TIME_NONE;
9488         /* Don't allow more edits after this one. */
9489         n_segments = segment_number + 1;
9490       }
9491       segment->stop_time = stime;
9492
9493       segment->trak_media_start = media_time;
9494       /* media_time expressed in stream timescale */
9495       if (!empty_edit) {
9496         segment->media_start = media_start;
9497         segment->media_stop = GST_CLOCK_TIME_IS_VALID (segment->duration)
9498             ? segment->media_start + segment->duration : GST_CLOCK_TIME_NONE;
9499         media_segments_count++;
9500       } else {
9501         segment->media_start = GST_CLOCK_TIME_NONE;
9502         segment->media_stop = GST_CLOCK_TIME_NONE;
9503       }
9504       rate_int = QT_UINT32 (buffer + ((version == 1) ? 16 : 8));
9505
9506       if (rate_int <= 1) {
9507         /* 0 is not allowed, some programs write 1 instead of the floating point
9508          * value */
9509         GST_WARNING_OBJECT (qtdemux, "found suspicious rate %" G_GUINT32_FORMAT,
9510             rate_int);
9511         segment->rate = 1;
9512       } else {
9513         segment->rate = rate_int / 65536.0;
9514       }
9515
9516       GST_DEBUG_OBJECT (qtdemux, "created segment %d time %" GST_TIME_FORMAT
9517           ", duration %" GST_TIME_FORMAT ", media_start %" GST_TIME_FORMAT
9518           " (%" G_GUINT64_FORMAT ") , media_stop %" GST_TIME_FORMAT
9519           " stop_time %" GST_TIME_FORMAT " rate %g, (%d) timescale %u",
9520           segment_number, GST_TIME_ARGS (segment->time),
9521           GST_TIME_ARGS (segment->duration),
9522           GST_TIME_ARGS (segment->media_start), media_time,
9523           GST_TIME_ARGS (segment->media_stop),
9524           GST_TIME_ARGS (segment->stop_time), segment->rate, rate_int,
9525           stream->timescale);
9526       if (segment->stop_time > qtdemux->segment.stop &&
9527           !qtdemux->upstream_format_is_time) {
9528         GST_WARNING_OBJECT (qtdemux, "Segment %d "
9529             " extends to %" GST_TIME_FORMAT
9530             " past the end of the declared movie duration %" GST_TIME_FORMAT
9531             " movie segment will be extended", segment_number,
9532             GST_TIME_ARGS (segment->stop_time),
9533             GST_TIME_ARGS (qtdemux->segment.stop));
9534         qtdemux->segment.stop = qtdemux->segment.duration = segment->stop_time;
9535       }
9536
9537       buffer += entry_size;
9538     }
9539     GST_DEBUG_OBJECT (qtdemux, "found %d segments", n_segments);
9540     stream->n_segments = n_segments;
9541     if (media_segments_count != 1)
9542       allow_pushbased_edts = FALSE;
9543   }
9544 done:
9545
9546   /* push based does not handle segments, so act accordingly here,
9547    * and warn if applicable */
9548   if (!qtdemux->pullbased && !allow_pushbased_edts) {
9549     GST_WARNING_OBJECT (qtdemux, "streaming; discarding edit list segments");
9550     /* remove and use default one below, we stream like it anyway */
9551     g_free (stream->segments);
9552     stream->segments = NULL;
9553     stream->n_segments = 0;
9554   }
9555
9556   /* no segments, create one to play the complete trak */
9557   if (stream->n_segments == 0) {
9558     GstClockTime stream_duration =
9559         QTSTREAMTIME_TO_GSTTIME (stream, stream->duration);
9560
9561     if (stream->segments == NULL)
9562       stream->segments = g_new (QtDemuxSegment, 1);
9563
9564     /* represent unknown our way */
9565     if (stream_duration == 0)
9566       stream_duration = GST_CLOCK_TIME_NONE;
9567
9568     stream->segments[0].time = 0;
9569     stream->segments[0].stop_time = stream_duration;
9570     stream->segments[0].duration = stream_duration;
9571     stream->segments[0].media_start = 0;
9572     stream->segments[0].media_stop = stream_duration;
9573     stream->segments[0].rate = 1.0;
9574     stream->segments[0].trak_media_start = 0;
9575
9576     GST_DEBUG_OBJECT (qtdemux, "created dummy segment %" GST_TIME_FORMAT,
9577         GST_TIME_ARGS (stream_duration));
9578     stream->n_segments = 1;
9579     stream->dummy_segment = TRUE;
9580   }
9581   GST_DEBUG_OBJECT (qtdemux, "using %d segments", stream->n_segments);
9582
9583   return TRUE;
9584 }
9585
9586 /*
9587  * Parses the stsd atom of a svq3 trak looking for
9588  * the SMI and gama atoms.
9589  */
9590 static void
9591 qtdemux_parse_svq3_stsd_data (GstQTDemux * qtdemux,
9592     const guint8 * stsd_entry_data, const guint8 ** gamma, GstBuffer ** seqh)
9593 {
9594   const guint8 *_gamma = NULL;
9595   GstBuffer *_seqh = NULL;
9596   const guint8 *stsd_data = stsd_entry_data;
9597   guint32 length = QT_UINT32 (stsd_data);
9598   guint16 version;
9599
9600   if (length < 32) {
9601     GST_WARNING_OBJECT (qtdemux, "stsd too short");
9602     goto end;
9603   }
9604
9605   stsd_data += 16;
9606   length -= 16;
9607   version = QT_UINT16 (stsd_data);
9608   if (version == 3) {
9609     if (length >= 70) {
9610       length -= 70;
9611       stsd_data += 70;
9612       while (length > 8) {
9613         guint32 fourcc, size;
9614         const guint8 *data;
9615         size = QT_UINT32 (stsd_data);
9616         fourcc = QT_FOURCC (stsd_data + 4);
9617         data = stsd_data + 8;
9618
9619         if (size == 0) {
9620           GST_WARNING_OBJECT (qtdemux, "Atom of size 0 found, aborting "
9621               "svq3 atom parsing");
9622           goto end;
9623         }
9624
9625         switch (fourcc) {
9626           case FOURCC_gama:{
9627             if (size == 12) {
9628               _gamma = data;
9629             } else {
9630               GST_WARNING_OBJECT (qtdemux, "Unexpected size %" G_GUINT32_FORMAT
9631                   " for gama atom, expected 12", size);
9632             }
9633             break;
9634           }
9635           case FOURCC_SMI_:{
9636             if (size > 16 && QT_FOURCC (data) == FOURCC_SEQH) {
9637               guint32 seqh_size;
9638               if (_seqh != NULL) {
9639                 GST_WARNING_OBJECT (qtdemux, "Unexpected second SEQH SMI atom "
9640                     " found, ignoring");
9641               } else {
9642                 seqh_size = QT_UINT32 (data + 4);
9643                 if (seqh_size > 0) {
9644                   _seqh = gst_buffer_new_and_alloc (seqh_size);
9645                   gst_buffer_fill (_seqh, 0, data + 8, seqh_size);
9646                 }
9647               }
9648             }
9649             break;
9650           }
9651           default:{
9652             GST_WARNING_OBJECT (qtdemux, "Unhandled atom %" GST_FOURCC_FORMAT
9653                 " in SVQ3 entry in stsd atom", GST_FOURCC_ARGS (fourcc));
9654           }
9655         }
9656
9657         if (size <= length) {
9658           length -= size;
9659           stsd_data += size;
9660         }
9661       }
9662     } else {
9663       GST_WARNING_OBJECT (qtdemux, "SVQ3 entry too short in stsd atom");
9664     }
9665   } else {
9666     GST_WARNING_OBJECT (qtdemux, "Unexpected version for SVQ3 entry %"
9667         G_GUINT16_FORMAT, version);
9668     goto end;
9669   }
9670
9671 end:
9672   if (gamma) {
9673     *gamma = _gamma;
9674   }
9675   if (seqh) {
9676     *seqh = _seqh;
9677   } else if (_seqh) {
9678     gst_buffer_unref (_seqh);
9679   }
9680 }
9681
9682 static gchar *
9683 qtdemux_get_rtsp_uri_from_hndl (GstQTDemux * qtdemux, GNode * minf)
9684 {
9685   GNode *dinf;
9686   GstByteReader dref;
9687   gchar *uri = NULL;
9688
9689   /*
9690    * Get 'dinf', to get its child 'dref', that might contain a 'hndl'
9691    * atom that might contain a 'data' atom with the rtsp uri.
9692    * This case was reported in bug #597497, some info about
9693    * the hndl atom can be found in TN1195
9694    */
9695   dinf = qtdemux_tree_get_child_by_type (minf, FOURCC_dinf);
9696   GST_DEBUG_OBJECT (qtdemux, "Trying to obtain rtsp URI for stream trak");
9697
9698   if (dinf) {
9699     guint32 dref_num_entries = 0;
9700     if (qtdemux_tree_get_child_by_type_full (dinf, FOURCC_dref, &dref) &&
9701         gst_byte_reader_skip (&dref, 4) &&
9702         gst_byte_reader_get_uint32_be (&dref, &dref_num_entries)) {
9703       gint i;
9704
9705       /* search dref entries for hndl atom */
9706       for (i = 0; i < dref_num_entries; i++) {
9707         guint32 size = 0, type;
9708         guint8 string_len = 0;
9709         if (gst_byte_reader_get_uint32_be (&dref, &size) &&
9710             qt_atom_parser_get_fourcc (&dref, &type)) {
9711           if (type == FOURCC_hndl) {
9712             GST_DEBUG_OBJECT (qtdemux, "Found hndl atom");
9713
9714             /* skip data reference handle bytes and the
9715              * following pascal string and some extra 4
9716              * bytes I have no idea what are */
9717             if (!gst_byte_reader_skip (&dref, 4) ||
9718                 !gst_byte_reader_get_uint8 (&dref, &string_len) ||
9719                 !gst_byte_reader_skip (&dref, string_len + 4)) {
9720               GST_WARNING_OBJECT (qtdemux, "Failed to parse hndl atom");
9721               break;
9722             }
9723
9724             /* iterate over the atoms to find the data atom */
9725             while (gst_byte_reader_get_remaining (&dref) >= 8) {
9726               guint32 atom_size;
9727               guint32 atom_type;
9728
9729               if (gst_byte_reader_get_uint32_be (&dref, &atom_size) &&
9730                   qt_atom_parser_get_fourcc (&dref, &atom_type)) {
9731                 if (atom_type == FOURCC_data) {
9732                   const guint8 *uri_aux = NULL;
9733
9734                   /* found the data atom that might contain the rtsp uri */
9735                   GST_DEBUG_OBJECT (qtdemux, "Found data atom inside "
9736                       "hndl atom, interpreting it as an URI");
9737                   if (gst_byte_reader_peek_data (&dref, atom_size - 8,
9738                           &uri_aux)) {
9739                     if (g_strstr_len ((gchar *) uri_aux, 7, "rtsp://") != NULL)
9740                       uri = g_strndup ((gchar *) uri_aux, atom_size - 8);
9741                     else
9742                       GST_WARNING_OBJECT (qtdemux, "Data atom in hndl atom "
9743                           "didn't contain a rtsp address");
9744                   } else {
9745                     GST_WARNING_OBJECT (qtdemux, "Failed to get the data "
9746                         "atom contents");
9747                   }
9748                   break;
9749                 }
9750                 /* skipping to the next entry */
9751                 if (!gst_byte_reader_skip (&dref, atom_size - 8))
9752                   break;
9753               } else {
9754                 GST_WARNING_OBJECT (qtdemux, "Failed to parse hndl child "
9755                     "atom header");
9756                 break;
9757               }
9758             }
9759             break;
9760           }
9761           /* skip to the next entry */
9762           if (!gst_byte_reader_skip (&dref, size - 8))
9763             break;
9764         } else {
9765           GST_WARNING_OBJECT (qtdemux, "Error parsing dref atom");
9766         }
9767       }
9768       GST_DEBUG_OBJECT (qtdemux, "Finished parsing dref atom");
9769     }
9770   }
9771   return uri;
9772 }
9773
9774 #define AMR_NB_ALL_MODES        0x81ff
9775 #define AMR_WB_ALL_MODES        0x83ff
9776 static guint
9777 qtdemux_parse_amr_bitrate (GstBuffer * buf, gboolean wb)
9778 {
9779   /* The 'damr' atom is of the form:
9780    *
9781    * | vendor | decoder_ver | mode_set | mode_change_period | frames/sample |
9782    *    32 b       8 b          16 b           8 b                 8 b
9783    *
9784    * The highest set bit of the first 7 (AMR-NB) or 8 (AMR-WB) bits of mode_set
9785    * represents the highest mode used in the stream (and thus the maximum
9786    * bitrate), with a couple of special cases as seen below.
9787    */
9788
9789   /* Map of frame type ID -> bitrate */
9790   static const guint nb_bitrates[] = {
9791     4750, 5150, 5900, 6700, 7400, 7950, 10200, 12200
9792   };
9793   static const guint wb_bitrates[] = {
9794     6600, 8850, 12650, 14250, 15850, 18250, 19850, 23050, 23850
9795   };
9796   GstMapInfo map;
9797   gsize max_mode;
9798   guint16 mode_set;
9799
9800   gst_buffer_map (buf, &map, GST_MAP_READ);
9801
9802   if (map.size != 0x11) {
9803     GST_DEBUG ("Atom should have size 0x11, not %" G_GSIZE_FORMAT, map.size);
9804     goto bad_data;
9805   }
9806
9807   if (QT_FOURCC (map.data + 4) != FOURCC_damr) {
9808     GST_DEBUG ("Unknown atom in %" GST_FOURCC_FORMAT,
9809         GST_FOURCC_ARGS (QT_UINT32 (map.data + 4)));
9810     goto bad_data;
9811   }
9812
9813   mode_set = QT_UINT16 (map.data + 13);
9814
9815   if (mode_set == (wb ? AMR_WB_ALL_MODES : AMR_NB_ALL_MODES))
9816     max_mode = 7 + (wb ? 1 : 0);
9817   else
9818     /* AMR-NB modes fo from 0-7, and AMR-WB modes go from 0-8 */
9819     max_mode = g_bit_nth_msf ((gulong) mode_set & (wb ? 0x1ff : 0xff), -1);
9820
9821   if (max_mode == -1) {
9822     GST_DEBUG ("No mode indication was found (mode set) = %x",
9823         (guint) mode_set);
9824     goto bad_data;
9825   }
9826
9827   gst_buffer_unmap (buf, &map);
9828   return wb ? wb_bitrates[max_mode] : nb_bitrates[max_mode];
9829
9830 bad_data:
9831   gst_buffer_unmap (buf, &map);
9832   return 0;
9833 }
9834
9835 static gboolean
9836 qtdemux_parse_transformation_matrix (GstQTDemux * qtdemux,
9837     GstByteReader * reader, guint32 * matrix, const gchar * atom)
9838 {
9839   /*
9840    * 9 values of 32 bits (fixed point 16.16, except 2 5 and 8 that are 2.30)
9841    * [0 1 2]
9842    * [3 4 5]
9843    * [6 7 8]
9844    */
9845
9846   if (gst_byte_reader_get_remaining (reader) < 36)
9847     return FALSE;
9848
9849   matrix[0] = gst_byte_reader_get_uint32_be_unchecked (reader);
9850   matrix[1] = gst_byte_reader_get_uint32_be_unchecked (reader);
9851   matrix[2] = gst_byte_reader_get_uint32_be_unchecked (reader);
9852   matrix[3] = gst_byte_reader_get_uint32_be_unchecked (reader);
9853   matrix[4] = gst_byte_reader_get_uint32_be_unchecked (reader);
9854   matrix[5] = gst_byte_reader_get_uint32_be_unchecked (reader);
9855   matrix[6] = gst_byte_reader_get_uint32_be_unchecked (reader);
9856   matrix[7] = gst_byte_reader_get_uint32_be_unchecked (reader);
9857   matrix[8] = gst_byte_reader_get_uint32_be_unchecked (reader);
9858
9859   GST_DEBUG_OBJECT (qtdemux, "Transformation matrix from atom %s", atom);
9860   GST_DEBUG_OBJECT (qtdemux, "%u.%u %u.%u %u.%u", matrix[0] >> 16,
9861       matrix[0] & 0xFFFF, matrix[1] >> 16, matrix[1] & 0xFF, matrix[2] >> 16,
9862       matrix[2] & 0xFF);
9863   GST_DEBUG_OBJECT (qtdemux, "%u.%u %u.%u %u.%u", matrix[3] >> 16,
9864       matrix[3] & 0xFFFF, matrix[4] >> 16, matrix[4] & 0xFF, matrix[5] >> 16,
9865       matrix[5] & 0xFF);
9866   GST_DEBUG_OBJECT (qtdemux, "%u.%u %u.%u %u.%u", matrix[6] >> 16,
9867       matrix[6] & 0xFFFF, matrix[7] >> 16, matrix[7] & 0xFF, matrix[8] >> 16,
9868       matrix[8] & 0xFF);
9869
9870   return TRUE;
9871 }
9872
9873 static void
9874 qtdemux_inspect_transformation_matrix (GstQTDemux * qtdemux,
9875     QtDemuxStream * stream, guint32 * matrix, GstTagList ** taglist)
9876 {
9877
9878 /* [a b c]
9879  * [d e f]
9880  * [g h i]
9881  *
9882  * This macro will only compare value abdegh, it expects cfi to have already
9883  * been checked
9884  */
9885 #define QTCHECK_MATRIX(m,a,b,d,e) ((m)[0] == (a << 16) && (m)[1] == (b << 16) && \
9886                                    (m)[3] == (d << 16) && (m)[4] == (e << 16))
9887
9888   /* only handle the cases where the last column has standard values */
9889   if (matrix[2] == 0 && matrix[5] == 0 && matrix[8] == 1 << 30) {
9890     const gchar *rotation_tag = NULL;
9891
9892     /* no rotation needed */
9893     if (QTCHECK_MATRIX (matrix, 1, 0, 0, 1)) {
9894       /* NOP */
9895     } else if (QTCHECK_MATRIX (matrix, 0, 1, G_MAXUINT16, 0)) {
9896       rotation_tag = "rotate-90";
9897     } else if (QTCHECK_MATRIX (matrix, G_MAXUINT16, 0, 0, G_MAXUINT16)) {
9898       rotation_tag = "rotate-180";
9899     } else if (QTCHECK_MATRIX (matrix, 0, G_MAXUINT16, 1, 0)) {
9900       rotation_tag = "rotate-270";
9901     } else {
9902       GST_FIXME_OBJECT (qtdemux, "Unhandled transformation matrix values");
9903     }
9904
9905     GST_DEBUG_OBJECT (qtdemux, "Transformation matrix rotation %s",
9906         rotation_tag);
9907     if (rotation_tag != NULL) {
9908       if (*taglist == NULL)
9909         *taglist = gst_tag_list_new_empty ();
9910       gst_tag_list_add (*taglist, GST_TAG_MERGE_REPLACE,
9911           GST_TAG_IMAGE_ORIENTATION, rotation_tag, NULL);
9912     }
9913   } else {
9914     GST_FIXME_OBJECT (qtdemux, "Unhandled transformation matrix values");
9915   }
9916 }
9917
9918 /* Parses the boxes defined in ISO/IEC 14496-12 that enable support for
9919  * protected streams (sinf, frma, schm and schi); if the protection scheme is
9920  * Common Encryption (cenc), the function will also parse the tenc box (defined
9921  * in ISO/IEC 23001-7). @container points to the node that contains these boxes
9922  * (typically an enc[v|a|t|s] sample entry); the function will set
9923  * @original_fmt to the fourcc of the original unencrypted stream format.
9924  * Returns TRUE if successful; FALSE otherwise. */
9925 static gboolean
9926 qtdemux_parse_protection_scheme_info (GstQTDemux * qtdemux,
9927     QtDemuxStream * stream, GNode * container, guint32 * original_fmt)
9928 {
9929   GNode *sinf;
9930   GNode *frma;
9931   GNode *schm;
9932   GNode *schi;
9933
9934   g_return_val_if_fail (qtdemux != NULL, FALSE);
9935   g_return_val_if_fail (stream != NULL, FALSE);
9936   g_return_val_if_fail (container != NULL, FALSE);
9937   g_return_val_if_fail (original_fmt != NULL, FALSE);
9938
9939   sinf = qtdemux_tree_get_child_by_type (container, FOURCC_sinf);
9940   if (G_UNLIKELY (!sinf)) {
9941     if (stream->protection_scheme_type == FOURCC_cenc) {
9942       GST_ERROR_OBJECT (qtdemux, "sinf box does not contain schi box, which is "
9943           "mandatory for Common Encryption");
9944       return FALSE;
9945     }
9946     return TRUE;
9947   }
9948
9949   frma = qtdemux_tree_get_child_by_type (sinf, FOURCC_frma);
9950   if (G_UNLIKELY (!frma)) {
9951     GST_ERROR_OBJECT (qtdemux, "sinf box does not contain mandatory frma box");
9952     return FALSE;
9953   }
9954
9955   *original_fmt = QT_FOURCC ((const guint8 *) frma->data + 8);
9956   GST_DEBUG_OBJECT (qtdemux, "original stream format: '%" GST_FOURCC_FORMAT "'",
9957       GST_FOURCC_ARGS (*original_fmt));
9958
9959   schm = qtdemux_tree_get_child_by_type (sinf, FOURCC_schm);
9960   if (!schm) {
9961     GST_DEBUG_OBJECT (qtdemux, "sinf box does not contain schm box");
9962     return FALSE;
9963   }
9964   stream->protection_scheme_type = QT_FOURCC ((const guint8 *) schm->data + 12);
9965   stream->protection_scheme_version =
9966       QT_UINT32 ((const guint8 *) schm->data + 16);
9967
9968   GST_DEBUG_OBJECT (qtdemux,
9969       "protection_scheme_type: %" GST_FOURCC_FORMAT ", "
9970       "protection_scheme_version: %#010x",
9971       GST_FOURCC_ARGS (stream->protection_scheme_type),
9972       stream->protection_scheme_version);
9973
9974   schi = qtdemux_tree_get_child_by_type (sinf, FOURCC_schi);
9975   if (!schi) {
9976     GST_DEBUG_OBJECT (qtdemux, "sinf box does not contain schi box");
9977     return FALSE;
9978   }
9979   if (stream->protection_scheme_type == FOURCC_cenc) {
9980     QtDemuxCencSampleSetInfo *info;
9981     GNode *tenc;
9982     const guint8 *tenc_data;
9983     guint32 isEncrypted;
9984     guint8 iv_size;
9985     const guint8 *default_kid;
9986     GstBuffer *kid_buf;
9987
9988     if (G_UNLIKELY (!stream->protection_scheme_info))
9989       stream->protection_scheme_info =
9990           g_malloc0 (sizeof (QtDemuxCencSampleSetInfo));
9991
9992     info = (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
9993
9994     tenc = qtdemux_tree_get_child_by_type (schi, FOURCC_tenc);
9995     if (!tenc) {
9996       GST_ERROR_OBJECT (qtdemux, "schi box does not contain tenc box, "
9997           "which is mandatory for Common Encryption");
9998       return FALSE;
9999     }
10000     tenc_data = (const guint8 *) tenc->data + 12;
10001     isEncrypted = QT_UINT24 (tenc_data);
10002     iv_size = QT_UINT8 (tenc_data + 3);
10003     default_kid = (tenc_data + 4);
10004     kid_buf = gst_buffer_new_allocate (NULL, 16, NULL);
10005     gst_buffer_fill (kid_buf, 0, default_kid, 16);
10006     if (info->default_properties)
10007       gst_structure_free (info->default_properties);
10008     info->default_properties =
10009         gst_structure_new ("application/x-cenc",
10010         "iv_size", G_TYPE_UINT, iv_size,
10011         "encrypted", G_TYPE_BOOLEAN, (isEncrypted == 1),
10012         "kid", GST_TYPE_BUFFER, kid_buf, NULL);
10013     GST_DEBUG_OBJECT (qtdemux, "default sample properties: "
10014         "is_encrypted=%u, iv_size=%u", isEncrypted, iv_size);
10015     gst_buffer_unref (kid_buf);
10016   }
10017   return TRUE;
10018 }
10019
10020 static gint
10021 qtdemux_track_id_compare_func (QtDemuxStream * stream1, QtDemuxStream * stream2)
10022 {
10023   return (gint) stream1->track_id - (gint) stream2->track_id;
10024 }
10025
10026 /* parse the traks.
10027  * With each track we associate a new QtDemuxStream that contains all the info
10028  * about the trak.
10029  * traks that do not decode to something (like strm traks) will not have a pad.
10030  */
10031 static gboolean
10032 qtdemux_parse_trak (GstQTDemux * qtdemux, GNode * trak)
10033 {
10034   GstByteReader tkhd;
10035   int offset;
10036   GNode *mdia;
10037   GNode *mdhd;
10038   GNode *hdlr;
10039   GNode *minf;
10040   GNode *stbl;
10041   GNode *stsd;
10042   GNode *mp4a;
10043   GNode *mp4v;
10044   GNode *esds;
10045   GNode *tref;
10046   GNode *udta;
10047   GNode *svmi;
10048
10049   QtDemuxStream *stream = NULL;
10050   const guint8 *stsd_data;
10051   const guint8 *stsd_entry_data;
10052   guint remaining_stsd_len;
10053   guint stsd_entry_count;
10054   guint stsd_index;
10055   guint16 lang_code;            /* quicktime lang code or packed iso code */
10056   guint32 version;
10057   guint32 tkhd_flags = 0;
10058   guint8 tkhd_version = 0;
10059   guint32 w = 0, h = 0;
10060   guint value_size, stsd_len, len;
10061   guint32 track_id;
10062   guint32 dummy;
10063
10064   GST_DEBUG_OBJECT (qtdemux, "parse_trak");
10065
10066   if (!qtdemux_tree_get_child_by_type_full (trak, FOURCC_tkhd, &tkhd)
10067       || !gst_byte_reader_get_uint8 (&tkhd, &tkhd_version)
10068       || !gst_byte_reader_get_uint24_be (&tkhd, &tkhd_flags))
10069     goto corrupt_file;
10070
10071   /* pick between 64 or 32 bits */
10072   value_size = tkhd_version == 1 ? 8 : 4;
10073   if (!gst_byte_reader_skip (&tkhd, value_size * 2) ||
10074       !gst_byte_reader_get_uint32_be (&tkhd, &track_id))
10075     goto corrupt_file;
10076
10077   /* Check if current moov has duplicated track_id */
10078   if (qtdemux_find_stream (qtdemux, track_id))
10079     goto existing_stream;
10080
10081   stream = _create_stream (qtdemux, track_id);
10082   stream->stream_tags = gst_tag_list_make_writable (stream->stream_tags);
10083
10084   /* need defaults for fragments */
10085   qtdemux_parse_trex (qtdemux, stream, &dummy, &dummy, &dummy);
10086
10087   if ((tkhd_flags & 1) == 0)
10088     stream->disabled = TRUE;
10089
10090   GST_LOG_OBJECT (qtdemux, "track[tkhd] version/flags/id: 0x%02x/%06x/%u",
10091       tkhd_version, tkhd_flags, stream->track_id);
10092
10093   if (!(mdia = qtdemux_tree_get_child_by_type (trak, FOURCC_mdia)))
10094     goto corrupt_file;
10095
10096   if (!(mdhd = qtdemux_tree_get_child_by_type (mdia, FOURCC_mdhd))) {
10097     /* be nice for some crooked mjp2 files that use mhdr for mdhd */
10098     if (qtdemux->major_brand != FOURCC_mjp2 ||
10099         !(mdhd = qtdemux_tree_get_child_by_type (mdia, FOURCC_mhdr)))
10100       goto corrupt_file;
10101   }
10102
10103   len = QT_UINT32 ((guint8 *) mdhd->data);
10104   version = QT_UINT32 ((guint8 *) mdhd->data + 8);
10105   GST_LOG_OBJECT (qtdemux, "track version/flags: %08x", version);
10106   if (version == 0x01000000) {
10107     if (len < 38)
10108       goto corrupt_file;
10109     stream->timescale = QT_UINT32 ((guint8 *) mdhd->data + 28);
10110     stream->duration = QT_UINT64 ((guint8 *) mdhd->data + 32);
10111     lang_code = QT_UINT16 ((guint8 *) mdhd->data + 36);
10112   } else {
10113     if (len < 30)
10114       goto corrupt_file;
10115     stream->timescale = QT_UINT32 ((guint8 *) mdhd->data + 20);
10116     stream->duration = QT_UINT32 ((guint8 *) mdhd->data + 24);
10117     lang_code = QT_UINT16 ((guint8 *) mdhd->data + 28);
10118   }
10119
10120   if (lang_code < 0x400) {
10121     qtdemux_lang_map_qt_code_to_iso (stream->lang_id, lang_code);
10122   } else if (lang_code == 0x7fff) {
10123     stream->lang_id[0] = 0;     /* unspecified */
10124   } else {
10125     stream->lang_id[0] = 0x60 + ((lang_code >> 10) & 0x1F);
10126     stream->lang_id[1] = 0x60 + ((lang_code >> 5) & 0x1F);
10127     stream->lang_id[2] = 0x60 + (lang_code & 0x1F);
10128     stream->lang_id[3] = 0;
10129   }
10130
10131   GST_LOG_OBJECT (qtdemux, "track timescale: %" G_GUINT32_FORMAT,
10132       stream->timescale);
10133   GST_LOG_OBJECT (qtdemux, "track duration: %" G_GUINT64_FORMAT,
10134       stream->duration);
10135   GST_LOG_OBJECT (qtdemux, "track language code/id: 0x%04x/%s",
10136       lang_code, stream->lang_id);
10137
10138   if (G_UNLIKELY (stream->timescale == 0 || qtdemux->timescale == 0))
10139     goto corrupt_file;
10140
10141   if ((tref = qtdemux_tree_get_child_by_type (trak, FOURCC_tref))) {
10142     /* chapters track reference */
10143     GNode *chap = qtdemux_tree_get_child_by_type (tref, FOURCC_chap);
10144     if (chap) {
10145       gsize length = GST_READ_UINT32_BE (chap->data);
10146       if (qtdemux->chapters_track_id)
10147         GST_FIXME_OBJECT (qtdemux, "Multiple CHAP tracks");
10148
10149       if (length >= 12) {
10150         qtdemux->chapters_track_id =
10151             GST_READ_UINT32_BE ((gint8 *) chap->data + 8);
10152       }
10153     }
10154   }
10155
10156   /* fragmented files may have bogus duration in moov */
10157   if (!qtdemux->fragmented &&
10158       qtdemux->duration != G_MAXINT64 && stream->duration != G_MAXINT32) {
10159     guint64 tdur1, tdur2;
10160
10161     /* don't overflow */
10162     tdur1 = stream->timescale * (guint64) qtdemux->duration;
10163     tdur2 = qtdemux->timescale * (guint64) stream->duration;
10164
10165     /* HACK:
10166      * some of those trailers, nowadays, have prologue images that are
10167      * themselves video tracks as well. I haven't really found a way to
10168      * identify those yet, except for just looking at their duration. */
10169     if (tdur1 != 0 && (tdur2 * 10 / tdur1) < 2) {
10170       GST_WARNING_OBJECT (qtdemux,
10171           "Track shorter than 20%% (%" G_GUINT64_FORMAT "/%" G_GUINT32_FORMAT
10172           " vs. %" G_GUINT64_FORMAT "/%" G_GUINT32_FORMAT ") of the stream "
10173           "found, assuming preview image or something; skipping track",
10174           stream->duration, stream->timescale, qtdemux->duration,
10175           qtdemux->timescale);
10176       gst_qtdemux_stream_free (stream);
10177       return TRUE;
10178     }
10179   }
10180
10181   if (!(hdlr = qtdemux_tree_get_child_by_type (mdia, FOURCC_hdlr)))
10182     goto corrupt_file;
10183
10184   GST_LOG_OBJECT (qtdemux, "track type: %" GST_FOURCC_FORMAT,
10185       GST_FOURCC_ARGS (QT_FOURCC ((guint8 *) hdlr->data + 12)));
10186
10187   len = QT_UINT32 ((guint8 *) hdlr->data);
10188   if (len >= 20)
10189     stream->subtype = QT_FOURCC ((guint8 *) hdlr->data + 16);
10190   GST_LOG_OBJECT (qtdemux, "track subtype: %" GST_FOURCC_FORMAT,
10191       GST_FOURCC_ARGS (stream->subtype));
10192
10193   if (!(minf = qtdemux_tree_get_child_by_type (mdia, FOURCC_minf)))
10194     goto corrupt_file;
10195
10196   if (!(stbl = qtdemux_tree_get_child_by_type (minf, FOURCC_stbl)))
10197     goto corrupt_file;
10198
10199   /*parse svmi header if existing */
10200   svmi = qtdemux_tree_get_child_by_type (stbl, FOURCC_svmi);
10201   if (svmi) {
10202     len = QT_UINT32 ((guint8 *) svmi->data);
10203     version = QT_UINT32 ((guint8 *) svmi->data + 8);
10204     if (!version) {
10205       GstVideoMultiviewMode mode = GST_VIDEO_MULTIVIEW_MODE_NONE;
10206       GstVideoMultiviewFlags flags = GST_VIDEO_MULTIVIEW_FLAGS_NONE;
10207       guint8 frame_type, frame_layout;
10208
10209       /* MPEG-A stereo video */
10210       if (qtdemux->major_brand == FOURCC_ss02)
10211         flags |= GST_VIDEO_MULTIVIEW_FLAGS_MIXED_MONO;
10212
10213       frame_type = QT_UINT8 ((guint8 *) svmi->data + 12);
10214       frame_layout = QT_UINT8 ((guint8 *) svmi->data + 13) & 0x01;
10215       switch (frame_type) {
10216         case 0:
10217           mode = GST_VIDEO_MULTIVIEW_MODE_SIDE_BY_SIDE;
10218           break;
10219         case 1:
10220           mode = GST_VIDEO_MULTIVIEW_MODE_ROW_INTERLEAVED;
10221           break;
10222         case 2:
10223           mode = GST_VIDEO_MULTIVIEW_MODE_FRAME_BY_FRAME;
10224           break;
10225         case 3:
10226           /* mode 3 is primary/secondary view sequence, ie
10227            * left/right views in separate tracks. See section 7.2
10228            * of ISO/IEC 23000-11:2009 */
10229           GST_FIXME_OBJECT (qtdemux,
10230               "Implement stereo video in separate streams");
10231       }
10232
10233       if ((frame_layout & 0x1) == 0)
10234         flags |= GST_VIDEO_MULTIVIEW_FLAGS_RIGHT_VIEW_FIRST;
10235
10236       GST_LOG_OBJECT (qtdemux,
10237           "StereoVideo: composition type: %u, is_left_first: %u",
10238           frame_type, frame_layout);
10239       stream->multiview_mode = mode;
10240       stream->multiview_flags = flags;
10241     }
10242   }
10243
10244   /* parse rest of tkhd */
10245   if (stream->subtype == FOURCC_vide) {
10246     guint32 matrix[9];
10247
10248     /* version 1 uses some 64-bit ints */
10249     if (!gst_byte_reader_skip (&tkhd, 20 + value_size))
10250       goto corrupt_file;
10251
10252     if (!qtdemux_parse_transformation_matrix (qtdemux, &tkhd, matrix, "tkhd"))
10253       goto corrupt_file;
10254
10255     if (!gst_byte_reader_get_uint32_be (&tkhd, &w)
10256         || !gst_byte_reader_get_uint32_be (&tkhd, &h))
10257       goto corrupt_file;
10258
10259     qtdemux_inspect_transformation_matrix (qtdemux, stream, matrix,
10260         &stream->stream_tags);
10261   }
10262
10263   /* parse stsd */
10264   if (!(stsd = qtdemux_tree_get_child_by_type (stbl, FOURCC_stsd)))
10265     goto corrupt_file;
10266   stsd_data = (const guint8 *) stsd->data;
10267
10268   /* stsd should at least have one entry */
10269   stsd_len = QT_UINT32 (stsd_data);
10270   if (stsd_len < 24) {
10271     /* .. but skip stream with empty stsd produced by some Vivotek cameras */
10272     if (stream->subtype == FOURCC_vivo) {
10273       gst_qtdemux_stream_free (stream);
10274       return TRUE;
10275     } else {
10276       goto corrupt_file;
10277     }
10278   }
10279
10280   stream->stsd_entries_length = stsd_entry_count = QT_UINT32 (stsd_data + 12);
10281   stream->stsd_entries = g_new0 (QtDemuxStreamStsdEntry, stsd_entry_count);
10282   GST_LOG_OBJECT (qtdemux, "stsd len:           %d", stsd_len);
10283   GST_LOG_OBJECT (qtdemux, "stsd entry count:   %u", stsd_entry_count);
10284
10285   stsd_entry_data = stsd_data + 16;
10286   remaining_stsd_len = stsd_len - 16;
10287   for (stsd_index = 0; stsd_index < stsd_entry_count; stsd_index++) {
10288     guint32 fourcc;
10289     gchar *codec = NULL;
10290     QtDemuxStreamStsdEntry *entry = &stream->stsd_entries[stsd_index];
10291
10292     /* and that entry should fit within stsd */
10293     len = QT_UINT32 (stsd_entry_data);
10294     if (len > remaining_stsd_len)
10295       goto corrupt_file;
10296
10297     entry->fourcc = fourcc = QT_FOURCC (stsd_entry_data + 4);
10298     GST_LOG_OBJECT (qtdemux, "stsd type:          %" GST_FOURCC_FORMAT,
10299         GST_FOURCC_ARGS (entry->fourcc));
10300     GST_LOG_OBJECT (qtdemux, "stsd type len:      %d", len);
10301
10302     if ((fourcc == FOURCC_drms) || (fourcc == FOURCC_drmi))
10303       goto error_encrypted;
10304
10305     if (fourcc == FOURCC_encv || fourcc == FOURCC_enca) {
10306       /* FIXME this looks wrong, there might be multiple children
10307        * with the same type */
10308       GNode *enc = qtdemux_tree_get_child_by_type (stsd, fourcc);
10309       stream->protected = TRUE;
10310       if (!qtdemux_parse_protection_scheme_info (qtdemux, stream, enc, &fourcc))
10311         GST_ERROR_OBJECT (qtdemux, "Failed to parse protection scheme info");
10312     }
10313
10314     if (stream->subtype == FOURCC_vide) {
10315       GNode *colr;
10316       GNode *fiel;
10317       GNode *pasp;
10318       gboolean gray;
10319       gint depth, palette_size, palette_count;
10320       guint32 *palette_data = NULL;
10321
10322       entry->sampled = TRUE;
10323
10324       stream->display_width = w >> 16;
10325       stream->display_height = h >> 16;
10326
10327       offset = 16;
10328       if (len < 86)             /* TODO verify */
10329         goto corrupt_file;
10330
10331       entry->width = QT_UINT16 (stsd_entry_data + offset + 16);
10332       entry->height = QT_UINT16 (stsd_entry_data + offset + 18);
10333       entry->fps_n = 0;         /* this is filled in later */
10334       entry->fps_d = 0;         /* this is filled in later */
10335       entry->bits_per_sample = QT_UINT16 (stsd_entry_data + offset + 66);
10336       entry->color_table_id = QT_UINT16 (stsd_entry_data + offset + 68);
10337
10338       /* if color_table_id is 0, ctab atom must follow; however some files
10339        * produced by TMPEGEnc have color_table_id = 0 and no ctab atom, so
10340        * if color table is not present we'll correct the value */
10341       if (entry->color_table_id == 0 &&
10342           (len < 90
10343               || QT_FOURCC (stsd_entry_data + offset + 70) != FOURCC_ctab)) {
10344         entry->color_table_id = -1;
10345       }
10346
10347       GST_LOG_OBJECT (qtdemux, "width %d, height %d, bps %d, color table id %d",
10348           entry->width, entry->height, entry->bits_per_sample,
10349           entry->color_table_id);
10350
10351       depth = entry->bits_per_sample;
10352
10353       /* more than 32 bits means grayscale */
10354       gray = (depth > 32);
10355       /* low 32 bits specify the depth  */
10356       depth &= 0x1F;
10357
10358       /* different number of palette entries is determined by depth. */
10359       palette_count = 0;
10360       if ((depth == 1) || (depth == 2) || (depth == 4) || (depth == 8))
10361         palette_count = (1 << depth);
10362       palette_size = palette_count * 4;
10363
10364       if (entry->color_table_id) {
10365         switch (palette_count) {
10366           case 0:
10367             break;
10368           case 2:
10369             palette_data = g_memdup (ff_qt_default_palette_2, palette_size);
10370             break;
10371           case 4:
10372             palette_data = g_memdup (ff_qt_default_palette_4, palette_size);
10373             break;
10374           case 16:
10375             if (gray)
10376               palette_data =
10377                   g_memdup (ff_qt_grayscale_palette_16, palette_size);
10378             else
10379               palette_data = g_memdup (ff_qt_default_palette_16, palette_size);
10380             break;
10381           case 256:
10382             if (gray)
10383               palette_data =
10384                   g_memdup (ff_qt_grayscale_palette_256, palette_size);
10385             else
10386               palette_data = g_memdup (ff_qt_default_palette_256, palette_size);
10387             break;
10388           default:
10389             GST_ELEMENT_WARNING (qtdemux, STREAM, DEMUX,
10390                 (_("The video in this file might not play correctly.")),
10391                 ("unsupported palette depth %d", depth));
10392             break;
10393         }
10394       } else {
10395         gint i, j, start, end;
10396
10397         if (len < 94)
10398           goto corrupt_file;
10399
10400         /* read table */
10401         start = QT_UINT32 (stsd_entry_data + offset + 70);
10402         palette_count = QT_UINT16 (stsd_entry_data + offset + 74);
10403         end = QT_UINT16 (stsd_entry_data + offset + 76);
10404
10405         GST_LOG_OBJECT (qtdemux, "start %d, end %d, palette_count %d",
10406             start, end, palette_count);
10407
10408         if (end > 255)
10409           end = 255;
10410         if (start > end)
10411           start = end;
10412
10413         if (len < 94 + (end - start) * 8)
10414           goto corrupt_file;
10415
10416         /* palette is always the same size */
10417         palette_data = g_malloc0 (256 * 4);
10418         palette_size = 256 * 4;
10419
10420         for (j = 0, i = start; i <= end; j++, i++) {
10421           guint32 a, r, g, b;
10422
10423           a = QT_UINT16 (stsd_entry_data + offset + 78 + (j * 8));
10424           r = QT_UINT16 (stsd_entry_data + offset + 80 + (j * 8));
10425           g = QT_UINT16 (stsd_entry_data + offset + 82 + (j * 8));
10426           b = QT_UINT16 (stsd_entry_data + offset + 84 + (j * 8));
10427
10428           palette_data[i] = ((a & 0xff00) << 16) | ((r & 0xff00) << 8) |
10429               (g & 0xff00) | (b >> 8);
10430         }
10431       }
10432
10433       if (entry->caps)
10434         gst_caps_unref (entry->caps);
10435
10436       entry->caps =
10437           qtdemux_video_caps (qtdemux, stream, entry, fourcc, stsd_entry_data,
10438           &codec);
10439       if (G_UNLIKELY (!entry->caps)) {
10440         g_free (palette_data);
10441         goto unknown_stream;
10442       }
10443
10444       if (codec) {
10445         gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
10446             GST_TAG_VIDEO_CODEC, codec, NULL);
10447         g_free (codec);
10448         codec = NULL;
10449       }
10450
10451       if (palette_data) {
10452         GstStructure *s;
10453
10454         if (entry->rgb8_palette)
10455           gst_memory_unref (entry->rgb8_palette);
10456         entry->rgb8_palette = gst_memory_new_wrapped (GST_MEMORY_FLAG_READONLY,
10457             palette_data, palette_size, 0, palette_size, palette_data, g_free);
10458
10459         s = gst_caps_get_structure (entry->caps, 0);
10460
10461         /* non-raw video has a palette_data property. raw video has the palette as
10462          * an extra plane that we append to the output buffers before we push
10463          * them*/
10464         if (!gst_structure_has_name (s, "video/x-raw")) {
10465           GstBuffer *palette;
10466
10467           palette = gst_buffer_new ();
10468           gst_buffer_append_memory (palette, entry->rgb8_palette);
10469           entry->rgb8_palette = NULL;
10470
10471           gst_caps_set_simple (entry->caps, "palette_data",
10472               GST_TYPE_BUFFER, palette, NULL);
10473           gst_buffer_unref (palette);
10474         }
10475       } else if (palette_count != 0) {
10476         GST_ELEMENT_WARNING (qtdemux, STREAM, NOT_IMPLEMENTED,
10477             (NULL), ("Unsupported palette depth %d", depth));
10478       }
10479
10480       GST_LOG_OBJECT (qtdemux, "frame count:   %u",
10481           QT_UINT16 (stsd_entry_data + offset + 32));
10482
10483       esds = NULL;
10484       pasp = NULL;
10485       colr = NULL;
10486       fiel = NULL;
10487       /* pick 'the' stsd child */
10488       mp4v = qtdemux_tree_get_child_by_index (stsd, stsd_index);
10489       if (!stream->protected) {
10490         if (QTDEMUX_TREE_NODE_FOURCC (mp4v) != fourcc) {
10491           mp4v = NULL;
10492         }
10493       } else {
10494         if (QTDEMUX_TREE_NODE_FOURCC (mp4v) != FOURCC_encv) {
10495           mp4v = NULL;
10496         }
10497       }
10498
10499       if (mp4v) {
10500         esds = qtdemux_tree_get_child_by_type (mp4v, FOURCC_esds);
10501         pasp = qtdemux_tree_get_child_by_type (mp4v, FOURCC_pasp);
10502         colr = qtdemux_tree_get_child_by_type (mp4v, FOURCC_colr);
10503         fiel = qtdemux_tree_get_child_by_type (mp4v, FOURCC_fiel);
10504       }
10505
10506       if (pasp) {
10507         const guint8 *pasp_data = (const guint8 *) pasp->data;
10508         gint len = QT_UINT32 (pasp_data);
10509
10510         if (len == 16) {
10511           CUR_STREAM (stream)->par_w = QT_UINT32 (pasp_data + 8);
10512           CUR_STREAM (stream)->par_h = QT_UINT32 (pasp_data + 12);
10513         } else {
10514           CUR_STREAM (stream)->par_w = 0;
10515           CUR_STREAM (stream)->par_h = 0;
10516         }
10517       } else {
10518         CUR_STREAM (stream)->par_w = 0;
10519         CUR_STREAM (stream)->par_h = 0;
10520       }
10521
10522       if (fiel) {
10523         const guint8 *fiel_data = (const guint8 *) fiel->data;
10524         gint len = QT_UINT32 (fiel_data);
10525
10526         if (len == 10) {
10527           CUR_STREAM (stream)->interlace_mode = GST_READ_UINT8 (fiel_data + 8);
10528           CUR_STREAM (stream)->field_order = GST_READ_UINT8 (fiel_data + 9);
10529         }
10530       }
10531
10532       if (colr) {
10533         const guint8 *colr_data = (const guint8 *) colr->data;
10534         gint len = QT_UINT32 (colr_data);
10535
10536         if (len == 19 || len == 18) {
10537           guint32 color_type = GST_READ_UINT32_LE (colr_data + 8);
10538
10539           if (color_type == FOURCC_nclx || color_type == FOURCC_nclc) {
10540             guint16 primaries = GST_READ_UINT16_BE (colr_data + 12);
10541             guint16 transfer_function = GST_READ_UINT16_BE (colr_data + 14);
10542             guint16 matrix = GST_READ_UINT16_BE (colr_data + 16);
10543             gboolean full_range = len == 19 ? colr_data[17] >> 7 : FALSE;
10544
10545             switch (primaries) {
10546               case 1:
10547                 CUR_STREAM (stream)->colorimetry.primaries =
10548                     GST_VIDEO_COLOR_PRIMARIES_BT709;
10549                 break;
10550               case 5:
10551                 CUR_STREAM (stream)->colorimetry.primaries =
10552                     GST_VIDEO_COLOR_PRIMARIES_BT470BG;
10553                 break;
10554               case 6:
10555                 CUR_STREAM (stream)->colorimetry.primaries =
10556                     GST_VIDEO_COLOR_PRIMARIES_SMPTE170M;
10557                 break;
10558               case 9:
10559                 CUR_STREAM (stream)->colorimetry.primaries =
10560                     GST_VIDEO_COLOR_PRIMARIES_BT2020;
10561                 break;
10562               default:
10563                 break;
10564             }
10565
10566             switch (transfer_function) {
10567               case 1:
10568                 CUR_STREAM (stream)->colorimetry.transfer =
10569                     GST_VIDEO_TRANSFER_BT709;
10570                 break;
10571               case 7:
10572                 CUR_STREAM (stream)->colorimetry.transfer =
10573                     GST_VIDEO_TRANSFER_SMPTE240M;
10574                 break;
10575               default:
10576                 break;
10577             }
10578
10579             switch (matrix) {
10580               case 1:
10581                 CUR_STREAM (stream)->colorimetry.matrix =
10582                     GST_VIDEO_COLOR_MATRIX_BT709;
10583                 break;
10584               case 6:
10585                 CUR_STREAM (stream)->colorimetry.matrix =
10586                     GST_VIDEO_COLOR_MATRIX_BT601;
10587                 break;
10588               case 7:
10589                 CUR_STREAM (stream)->colorimetry.matrix =
10590                     GST_VIDEO_COLOR_MATRIX_SMPTE240M;
10591                 break;
10592               case 9:
10593                 CUR_STREAM (stream)->colorimetry.matrix =
10594                     GST_VIDEO_COLOR_MATRIX_BT2020;
10595                 break;
10596               default:
10597                 break;
10598             }
10599
10600             CUR_STREAM (stream)->colorimetry.range =
10601                 full_range ? GST_VIDEO_COLOR_RANGE_0_255 :
10602                 GST_VIDEO_COLOR_RANGE_16_235;
10603           } else {
10604             GST_DEBUG_OBJECT (qtdemux, "Unsupported color type");
10605           }
10606         } else {
10607           GST_WARNING_OBJECT (qtdemux, "Invalid colr atom size");
10608         }
10609       }
10610
10611       if (esds) {
10612         gst_qtdemux_handle_esds (qtdemux, stream, entry, esds,
10613             stream->stream_tags);
10614       } else {
10615         switch (fourcc) {
10616           case FOURCC_H264:
10617           case FOURCC_avc1:
10618           case FOURCC_avc3:
10619           {
10620             gint len = QT_UINT32 (stsd_entry_data) - 0x56;
10621             const guint8 *avc_data = stsd_entry_data + 0x56;
10622
10623             /* find avcC */
10624             while (len >= 0x8) {
10625               gint size;
10626
10627               if (QT_UINT32 (avc_data) <= len)
10628                 size = QT_UINT32 (avc_data) - 0x8;
10629               else
10630                 size = len - 0x8;
10631
10632               if (size < 1)
10633                 /* No real data, so break out */
10634                 break;
10635
10636               switch (QT_FOURCC (avc_data + 0x4)) {
10637                 case FOURCC_avcC:
10638                 {
10639                   /* parse, if found */
10640                   GstBuffer *buf;
10641
10642                   GST_DEBUG_OBJECT (qtdemux, "found avcC codec_data in stsd");
10643
10644                   /* First 4 bytes are the length of the atom, the next 4 bytes
10645                    * are the fourcc, the next 1 byte is the version, and the
10646                    * subsequent bytes are profile_tier_level structure like data. */
10647                   gst_codec_utils_h264_caps_set_level_and_profile (entry->caps,
10648                       avc_data + 8 + 1, size - 1);
10649                   buf = gst_buffer_new_and_alloc (size);
10650                   gst_buffer_fill (buf, 0, avc_data + 0x8, size);
10651                   gst_caps_set_simple (entry->caps,
10652                       "codec_data", GST_TYPE_BUFFER, buf, NULL);
10653                   gst_buffer_unref (buf);
10654
10655                   break;
10656                 }
10657                 case FOURCC_strf:
10658                 {
10659                   GstBuffer *buf;
10660
10661                   GST_DEBUG_OBJECT (qtdemux, "found strf codec_data in stsd");
10662
10663                   /* First 4 bytes are the length of the atom, the next 4 bytes
10664                    * are the fourcc, next 40 bytes are BITMAPINFOHEADER,
10665                    * next 1 byte is the version, and the
10666                    * subsequent bytes are sequence parameter set like data. */
10667
10668                   size -= 40;   /* we'll be skipping BITMAPINFOHEADER */
10669                   if (size > 1) {
10670                     gst_codec_utils_h264_caps_set_level_and_profile
10671                         (entry->caps, avc_data + 8 + 40 + 1, size - 1);
10672
10673                     buf = gst_buffer_new_and_alloc (size);
10674                     gst_buffer_fill (buf, 0, avc_data + 8 + 40, size);
10675                     gst_caps_set_simple (entry->caps,
10676                         "codec_data", GST_TYPE_BUFFER, buf, NULL);
10677                     gst_buffer_unref (buf);
10678                   }
10679                   break;
10680                 }
10681                 case FOURCC_btrt:
10682                 {
10683                   guint avg_bitrate, max_bitrate;
10684
10685                   /* bufferSizeDB, maxBitrate and avgBitrate - 4 bytes each */
10686                   if (size < 12)
10687                     break;
10688
10689                   max_bitrate = QT_UINT32 (avc_data + 0xc);
10690                   avg_bitrate = QT_UINT32 (avc_data + 0x10);
10691
10692                   if (!max_bitrate && !avg_bitrate)
10693                     break;
10694
10695                   /* Some muxers seem to swap the average and maximum bitrates
10696                    * (I'm looking at you, YouTube), so we swap for sanity. */
10697                   if (max_bitrate > 0 && max_bitrate < avg_bitrate) {
10698                     guint temp = avg_bitrate;
10699
10700                     avg_bitrate = max_bitrate;
10701                     max_bitrate = temp;
10702                   }
10703
10704                   if (max_bitrate > 0 && max_bitrate < G_MAXUINT32) {
10705                     gst_tag_list_add (stream->stream_tags,
10706                         GST_TAG_MERGE_REPLACE, GST_TAG_MAXIMUM_BITRATE,
10707                         max_bitrate, NULL);
10708                   }
10709                   if (avg_bitrate > 0 && avg_bitrate < G_MAXUINT32) {
10710                     gst_tag_list_add (stream->stream_tags,
10711                         GST_TAG_MERGE_REPLACE, GST_TAG_BITRATE, avg_bitrate,
10712                         NULL);
10713                   }
10714
10715                   break;
10716                 }
10717
10718                 default:
10719                   break;
10720               }
10721
10722               len -= size + 8;
10723               avc_data += size + 8;
10724             }
10725
10726             break;
10727           }
10728           case FOURCC_H265:
10729           case FOURCC_hvc1:
10730           case FOURCC_hev1:
10731           {
10732             gint len = QT_UINT32 (stsd_entry_data) - 0x56;
10733             const guint8 *hevc_data = stsd_entry_data + 0x56;
10734
10735             /* find hevc */
10736             while (len >= 0x8) {
10737               gint size;
10738
10739               if (QT_UINT32 (hevc_data) <= len)
10740                 size = QT_UINT32 (hevc_data) - 0x8;
10741               else
10742                 size = len - 0x8;
10743
10744               if (size < 1)
10745                 /* No real data, so break out */
10746                 break;
10747
10748               switch (QT_FOURCC (hevc_data + 0x4)) {
10749                 case FOURCC_hvcC:
10750                 {
10751                   /* parse, if found */
10752                   GstBuffer *buf;
10753
10754                   GST_DEBUG_OBJECT (qtdemux, "found hvcC codec_data in stsd");
10755
10756                   /* First 4 bytes are the length of the atom, the next 4 bytes
10757                    * are the fourcc, the next 1 byte is the version, and the
10758                    * subsequent bytes are sequence parameter set like data. */
10759                   gst_codec_utils_h265_caps_set_level_tier_and_profile
10760                       (entry->caps, hevc_data + 8 + 1, size - 1);
10761
10762                   buf = gst_buffer_new_and_alloc (size);
10763                   gst_buffer_fill (buf, 0, hevc_data + 0x8, size);
10764                   gst_caps_set_simple (entry->caps,
10765                       "codec_data", GST_TYPE_BUFFER, buf, NULL);
10766                   gst_buffer_unref (buf);
10767                   break;
10768                 }
10769                 default:
10770                   break;
10771               }
10772               len -= size + 8;
10773               hevc_data += size + 8;
10774             }
10775             break;
10776           }
10777           case FOURCC_mp4v:
10778           case FOURCC_MP4V:
10779           case FOURCC_fmp4:
10780           case FOURCC_FMP4:
10781           case FOURCC_xvid:
10782           case FOURCC_XVID:
10783           {
10784             GNode *glbl;
10785
10786             GST_DEBUG_OBJECT (qtdemux, "found %" GST_FOURCC_FORMAT,
10787                 GST_FOURCC_ARGS (fourcc));
10788
10789             /* codec data might be in glbl extension atom */
10790             glbl = mp4v ?
10791                 qtdemux_tree_get_child_by_type (mp4v, FOURCC_glbl) : NULL;
10792             if (glbl) {
10793               guint8 *data;
10794               GstBuffer *buf;
10795               gint len;
10796
10797               GST_DEBUG_OBJECT (qtdemux, "found glbl data in stsd");
10798               data = glbl->data;
10799               len = QT_UINT32 (data);
10800               if (len > 0x8) {
10801                 len -= 0x8;
10802                 buf = gst_buffer_new_and_alloc (len);
10803                 gst_buffer_fill (buf, 0, data + 8, len);
10804                 gst_caps_set_simple (entry->caps,
10805                     "codec_data", GST_TYPE_BUFFER, buf, NULL);
10806                 gst_buffer_unref (buf);
10807               }
10808             }
10809             break;
10810           }
10811           case FOURCC_mjp2:
10812           {
10813             /* see annex I of the jpeg2000 spec */
10814             GNode *jp2h, *ihdr, *colr, *mjp2, *field, *prefix, *cmap, *cdef;
10815             const guint8 *data;
10816             const gchar *colorspace = NULL;
10817             gint ncomp = 0;
10818             guint32 ncomp_map = 0;
10819             gint32 *comp_map = NULL;
10820             guint32 nchan_def = 0;
10821             gint32 *chan_def = NULL;
10822
10823             GST_DEBUG_OBJECT (qtdemux, "found mjp2");
10824             /* some required atoms */
10825             mjp2 = qtdemux_tree_get_child_by_index (stsd, stsd_index);
10826             if (!mjp2)
10827               break;
10828             jp2h = qtdemux_tree_get_child_by_type (mjp2, FOURCC_jp2h);
10829             if (!jp2h)
10830               break;
10831
10832             /* number of components; redundant with info in codestream, but useful
10833                to a muxer */
10834             ihdr = qtdemux_tree_get_child_by_type (jp2h, FOURCC_ihdr);
10835             if (!ihdr || QT_UINT32 (ihdr->data) != 22)
10836               break;
10837             ncomp = QT_UINT16 (((guint8 *) ihdr->data) + 16);
10838
10839             colr = qtdemux_tree_get_child_by_type (jp2h, FOURCC_colr);
10840             if (!colr)
10841               break;
10842             GST_DEBUG_OBJECT (qtdemux, "found colr");
10843             /* extract colour space info */
10844             if (QT_UINT8 ((guint8 *) colr->data + 8) == 1) {
10845               switch (QT_UINT32 ((guint8 *) colr->data + 11)) {
10846                 case 16:
10847                   colorspace = "sRGB";
10848                   break;
10849                 case 17:
10850                   colorspace = "GRAY";
10851                   break;
10852                 case 18:
10853                   colorspace = "sYUV";
10854                   break;
10855                 default:
10856                   colorspace = NULL;
10857                   break;
10858               }
10859             }
10860             if (!colorspace)
10861               /* colr is required, and only values 16, 17, and 18 are specified,
10862                  so error if we have no colorspace */
10863               break;
10864
10865             /* extract component mapping */
10866             cmap = qtdemux_tree_get_child_by_type (jp2h, FOURCC_cmap);
10867             if (cmap) {
10868               guint32 cmap_len = 0;
10869               int i;
10870               cmap_len = QT_UINT32 (cmap->data);
10871               if (cmap_len >= 8) {
10872                 /* normal box, subtract off header */
10873                 cmap_len -= 8;
10874                 /* cmap: { u16 cmp; u8 mtyp; u8 pcol; }* */
10875                 if (cmap_len % 4 == 0) {
10876                   ncomp_map = (cmap_len / 4);
10877                   comp_map = g_new0 (gint32, ncomp_map);
10878                   for (i = 0; i < ncomp_map; i++) {
10879                     guint16 cmp;
10880                     guint8 mtyp, pcol;
10881                     cmp = QT_UINT16 (((guint8 *) cmap->data) + 8 + i * 4);
10882                     mtyp = QT_UINT8 (((guint8 *) cmap->data) + 8 + i * 4 + 2);
10883                     pcol = QT_UINT8 (((guint8 *) cmap->data) + 8 + i * 4 + 3);
10884                     comp_map[i] = (mtyp << 24) | (pcol << 16) | cmp;
10885                   }
10886                 }
10887               }
10888             }
10889             /* extract channel definitions */
10890             cdef = qtdemux_tree_get_child_by_type (jp2h, FOURCC_cdef);
10891             if (cdef) {
10892               guint32 cdef_len = 0;
10893               int i;
10894               cdef_len = QT_UINT32 (cdef->data);
10895               if (cdef_len >= 10) {
10896                 /* normal box, subtract off header and len */
10897                 cdef_len -= 10;
10898                 /* cdef: u16 n; { u16 cn; u16 typ; u16 asoc; }* */
10899                 if (cdef_len % 6 == 0) {
10900                   nchan_def = (cdef_len / 6);
10901                   chan_def = g_new0 (gint32, nchan_def);
10902                   for (i = 0; i < nchan_def; i++)
10903                     chan_def[i] = -1;
10904                   for (i = 0; i < nchan_def; i++) {
10905                     guint16 cn, typ, asoc;
10906                     cn = QT_UINT16 (((guint8 *) cdef->data) + 10 + i * 6);
10907                     typ = QT_UINT16 (((guint8 *) cdef->data) + 10 + i * 6 + 2);
10908                     asoc = QT_UINT16 (((guint8 *) cdef->data) + 10 + i * 6 + 4);
10909                     if (cn < nchan_def) {
10910                       switch (typ) {
10911                         case 0:
10912                           chan_def[cn] = asoc;
10913                           break;
10914                         case 1:
10915                           chan_def[cn] = 0;     /* alpha */
10916                           break;
10917                         default:
10918                           chan_def[cn] = -typ;
10919                       }
10920                     }
10921                   }
10922                 }
10923               }
10924             }
10925
10926             gst_caps_set_simple (entry->caps,
10927                 "num-components", G_TYPE_INT, ncomp, NULL);
10928             gst_caps_set_simple (entry->caps,
10929                 "colorspace", G_TYPE_STRING, colorspace, NULL);
10930
10931             if (comp_map) {
10932               GValue arr = { 0, };
10933               GValue elt = { 0, };
10934               int i;
10935               g_value_init (&arr, GST_TYPE_ARRAY);
10936               g_value_init (&elt, G_TYPE_INT);
10937               for (i = 0; i < ncomp_map; i++) {
10938                 g_value_set_int (&elt, comp_map[i]);
10939                 gst_value_array_append_value (&arr, &elt);
10940               }
10941               gst_structure_set_value (gst_caps_get_structure (entry->caps, 0),
10942                   "component-map", &arr);
10943               g_value_unset (&elt);
10944               g_value_unset (&arr);
10945               g_free (comp_map);
10946             }
10947
10948             if (chan_def) {
10949               GValue arr = { 0, };
10950               GValue elt = { 0, };
10951               int i;
10952               g_value_init (&arr, GST_TYPE_ARRAY);
10953               g_value_init (&elt, G_TYPE_INT);
10954               for (i = 0; i < nchan_def; i++) {
10955                 g_value_set_int (&elt, chan_def[i]);
10956                 gst_value_array_append_value (&arr, &elt);
10957               }
10958               gst_structure_set_value (gst_caps_get_structure (entry->caps, 0),
10959                   "channel-definitions", &arr);
10960               g_value_unset (&elt);
10961               g_value_unset (&arr);
10962               g_free (chan_def);
10963             }
10964
10965             /* some optional atoms */
10966             field = qtdemux_tree_get_child_by_type (mjp2, FOURCC_fiel);
10967             prefix = qtdemux_tree_get_child_by_type (mjp2, FOURCC_jp2x);
10968
10969             /* indicate possible fields in caps */
10970             if (field) {
10971               data = (guint8 *) field->data + 8;
10972               if (*data != 1)
10973                 gst_caps_set_simple (entry->caps, "fields", G_TYPE_INT,
10974                     (gint) * data, NULL);
10975             }
10976             /* add codec_data if provided */
10977             if (prefix) {
10978               GstBuffer *buf;
10979               gint len;
10980
10981               GST_DEBUG_OBJECT (qtdemux, "found prefix data in stsd");
10982               data = prefix->data;
10983               len = QT_UINT32 (data);
10984               if (len > 0x8) {
10985                 len -= 0x8;
10986                 buf = gst_buffer_new_and_alloc (len);
10987                 gst_buffer_fill (buf, 0, data + 8, len);
10988                 gst_caps_set_simple (entry->caps,
10989                     "codec_data", GST_TYPE_BUFFER, buf, NULL);
10990                 gst_buffer_unref (buf);
10991               }
10992             }
10993             break;
10994           }
10995           case FOURCC_SVQ3:
10996           case FOURCC_VP31:
10997           {
10998             GstBuffer *buf;
10999             GstBuffer *seqh = NULL;
11000             const guint8 *gamma_data = NULL;
11001             gint len = QT_UINT32 (stsd_data);   /* FIXME review - why put the whole stsd in codec data? */
11002
11003             qtdemux_parse_svq3_stsd_data (qtdemux, stsd_entry_data, &gamma_data,
11004                 &seqh);
11005             if (gamma_data) {
11006               gst_caps_set_simple (entry->caps, "applied-gamma", G_TYPE_DOUBLE,
11007                   QT_FP32 (gamma_data), NULL);
11008             }
11009             if (seqh) {
11010               /* sorry for the bad name, but we don't know what this is, other
11011                * than its own fourcc */
11012               gst_caps_set_simple (entry->caps, "seqh", GST_TYPE_BUFFER, seqh,
11013                   NULL);
11014               gst_buffer_unref (seqh);
11015             }
11016
11017             GST_DEBUG_OBJECT (qtdemux, "found codec_data in stsd");
11018             buf = gst_buffer_new_and_alloc (len);
11019             gst_buffer_fill (buf, 0, stsd_data, len);
11020             gst_caps_set_simple (entry->caps,
11021                 "codec_data", GST_TYPE_BUFFER, buf, NULL);
11022             gst_buffer_unref (buf);
11023             break;
11024           }
11025           case FOURCC_jpeg:
11026           {
11027             /* https://developer.apple.com/standards/qtff-2001.pdf,
11028              * page 92, "Video Sample Description", under table 3.1 */
11029             GstByteReader br;
11030
11031             const gint compressor_offset =
11032                 16 + 4 + 4 * 3 + 2 * 2 + 2 * 4 + 4 + 2;
11033             const gint min_size = compressor_offset + 32 + 2 + 2;
11034             GNode *jpeg;
11035             guint32 len;
11036             guint16 color_table_id = 0;
11037             gboolean ok;
11038
11039             GST_DEBUG_OBJECT (qtdemux, "found jpeg");
11040
11041             /* recover information on interlaced/progressive */
11042             jpeg = qtdemux_tree_get_child_by_type (stsd, FOURCC_jpeg);
11043             if (!jpeg)
11044               break;
11045
11046             len = QT_UINT32 (jpeg->data);
11047             GST_DEBUG_OBJECT (qtdemux, "Found jpeg: len %u, need %d", len,
11048                 min_size);
11049             if (len >= min_size) {
11050               gst_byte_reader_init (&br, jpeg->data, len);
11051
11052               gst_byte_reader_skip (&br, compressor_offset + 32 + 2);
11053               gst_byte_reader_get_uint16_le (&br, &color_table_id);
11054               if (color_table_id != 0) {
11055                 /* the spec says there can be concatenated chunks in the data, and we want
11056                  * to find one called field. Walk through them. */
11057                 gint offset = min_size;
11058                 while (offset + 8 < len) {
11059                   guint32 size = 0, tag;
11060                   ok = gst_byte_reader_get_uint32_le (&br, &size);
11061                   ok &= gst_byte_reader_get_uint32_le (&br, &tag);
11062                   if (!ok || size < 8) {
11063                     GST_WARNING_OBJECT (qtdemux,
11064                         "Failed to walk optional chunk list");
11065                     break;
11066                   }
11067                   GST_DEBUG_OBJECT (qtdemux,
11068                       "Found optional %4.4s chunk, size %u",
11069                       (const char *) &tag, size);
11070                   if (tag == FOURCC_fiel) {
11071                     guint8 n_fields = 0, ordering = 0;
11072                     gst_byte_reader_get_uint8 (&br, &n_fields);
11073                     gst_byte_reader_get_uint8 (&br, &ordering);
11074                     if (n_fields == 1 || n_fields == 2) {
11075                       GST_DEBUG_OBJECT (qtdemux,
11076                           "Found fiel tag with %u fields, ordering %u",
11077                           n_fields, ordering);
11078                       if (n_fields == 2)
11079                         gst_caps_set_simple (CUR_STREAM (stream)->caps,
11080                             "interlace-mode", G_TYPE_STRING, "interleaved",
11081                             NULL);
11082                     } else {
11083                       GST_WARNING_OBJECT (qtdemux,
11084                           "Found fiel tag with invalid fields (%u)", n_fields);
11085                     }
11086                   }
11087                   offset += size;
11088                 }
11089               } else {
11090                 GST_DEBUG_OBJECT (qtdemux,
11091                     "Color table ID is 0, not trying to get interlacedness");
11092               }
11093             } else {
11094               GST_WARNING_OBJECT (qtdemux,
11095                   "Length of jpeg chunk is too small, not trying to get interlacedness");
11096             }
11097
11098             break;
11099           }
11100           case FOURCC_rle_:
11101           case FOURCC_WRLE:
11102           {
11103             gst_caps_set_simple (entry->caps,
11104                 "depth", G_TYPE_INT, QT_UINT16 (stsd_entry_data + offset + 66),
11105                 NULL);
11106             break;
11107           }
11108           case FOURCC_XiTh:
11109           {
11110             GNode *xith, *xdxt;
11111
11112             GST_DEBUG_OBJECT (qtdemux, "found XiTh");
11113             xith = qtdemux_tree_get_child_by_index (stsd, stsd_index);
11114             if (!xith)
11115               break;
11116
11117             xdxt = qtdemux_tree_get_child_by_type (xith, FOURCC_XdxT);
11118             if (!xdxt)
11119               break;
11120
11121             GST_DEBUG_OBJECT (qtdemux, "found XdxT node");
11122             /* collect the headers and store them in a stream list so that we can
11123              * send them out first */
11124             qtdemux_parse_theora_extension (qtdemux, stream, xdxt);
11125             break;
11126           }
11127           case FOURCC_ovc1:
11128           {
11129             GNode *ovc1;
11130             guint8 *ovc1_data;
11131             guint ovc1_len;
11132             GstBuffer *buf;
11133
11134             GST_DEBUG_OBJECT (qtdemux, "parse ovc1 header");
11135             ovc1 = qtdemux_tree_get_child_by_index (stsd, stsd_index);
11136             if (!ovc1)
11137               break;
11138             ovc1_data = ovc1->data;
11139             ovc1_len = QT_UINT32 (ovc1_data);
11140             if (ovc1_len <= 198) {
11141               GST_WARNING_OBJECT (qtdemux, "Too small ovc1 header, skipping");
11142               break;
11143             }
11144             buf = gst_buffer_new_and_alloc (ovc1_len - 198);
11145             gst_buffer_fill (buf, 0, ovc1_data + 198, ovc1_len - 198);
11146             gst_caps_set_simple (entry->caps,
11147                 "codec_data", GST_TYPE_BUFFER, buf, NULL);
11148             gst_buffer_unref (buf);
11149             break;
11150           }
11151           case FOURCC_vc_1:
11152           {
11153             gint len = QT_UINT32 (stsd_entry_data) - 0x56;
11154             const guint8 *vc1_data = stsd_entry_data + 0x56;
11155
11156             /* find dvc1 */
11157             while (len >= 8) {
11158               gint size;
11159
11160               if (QT_UINT32 (vc1_data) <= len)
11161                 size = QT_UINT32 (vc1_data) - 8;
11162               else
11163                 size = len - 8;
11164
11165               if (size < 1)
11166                 /* No real data, so break out */
11167                 break;
11168
11169               switch (QT_FOURCC (vc1_data + 0x4)) {
11170                 case GST_MAKE_FOURCC ('d', 'v', 'c', '1'):
11171                 {
11172                   GstBuffer *buf;
11173
11174                   GST_DEBUG_OBJECT (qtdemux, "found dvc1 codec_data in stsd");
11175                   buf = gst_buffer_new_and_alloc (size);
11176                   gst_buffer_fill (buf, 0, vc1_data + 8, size);
11177                   gst_caps_set_simple (entry->caps,
11178                       "codec_data", GST_TYPE_BUFFER, buf, NULL);
11179                   gst_buffer_unref (buf);
11180                   break;
11181                 }
11182                 default:
11183                   break;
11184               }
11185               len -= size + 8;
11186               vc1_data += size + 8;
11187             }
11188             break;
11189           }
11190           case FOURCC_av01:
11191           {
11192             gint len = QT_UINT32 (stsd_entry_data) - 0x56;
11193             const guint8 *av1_data = stsd_entry_data + 0x56;
11194
11195             /* find av1C */
11196             while (len >= 0x8) {
11197               gint size;
11198
11199               if (QT_UINT32 (av1_data) <= len)
11200                 size = QT_UINT32 (av1_data) - 0x8;
11201               else
11202                 size = len - 0x8;
11203
11204               if (size < 1)
11205                 /* No real data, so break out */
11206                 break;
11207
11208               switch (QT_FOURCC (av1_data + 0x4)) {
11209                 case FOURCC_av1C:
11210                 {
11211                   /* parse, if found */
11212                   GstBuffer *buf;
11213                   guint8 pres_delay_field;
11214
11215                   GST_DEBUG_OBJECT (qtdemux,
11216                       "found av1C codec_data in stsd of size %d", size);
11217
11218                   /* not enough data, just ignore and hope for the best */
11219                   if (size < 5)
11220                     break;
11221
11222                   /* Content is:
11223                    * 4 bytes: atom length
11224                    * 4 bytes: fourcc
11225                    * 1 byte: version
11226                    * 3 bytes: flags
11227                    * 3 bits: reserved
11228                    * 1 bits:  initial_presentation_delay_present
11229                    * 4 bits: initial_presentation_delay (if present else reserved
11230                    * rest: OBUs.
11231                    */
11232
11233                   if (av1_data[9] != 0) {
11234                     GST_WARNING ("Unknown version %d of av1C box", av1_data[9]);
11235                     break;
11236                   }
11237
11238                   /* We skip initial_presentation_delay* for now */
11239                   pres_delay_field = *(av1_data + 12);
11240                   if (pres_delay_field & (1 << 5)) {
11241                     gst_caps_set_simple (entry->caps,
11242                         "presentation-delay", G_TYPE_INT,
11243                         (gint) (pres_delay_field & 0x0F) + 1, NULL);
11244                   }
11245                   if (size > 5) {
11246                     buf = gst_buffer_new_and_alloc (size - 5);
11247                     GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_HEADER);
11248                     gst_buffer_fill (buf, 0, av1_data + 13, size - 5);
11249                     gst_caps_set_simple (entry->caps,
11250                         "codec_data", GST_TYPE_BUFFER, buf, NULL);
11251                     gst_buffer_unref (buf);
11252                   }
11253                   break;
11254                 }
11255                 default:
11256                   break;
11257               }
11258
11259               len -= size + 8;
11260               av1_data += size + 8;
11261             }
11262
11263             break;
11264           }
11265           default:
11266             break;
11267         }
11268       }
11269
11270       GST_INFO_OBJECT (qtdemux,
11271           "type %" GST_FOURCC_FORMAT " caps %" GST_PTR_FORMAT,
11272           GST_FOURCC_ARGS (fourcc), entry->caps);
11273
11274     } else if (stream->subtype == FOURCC_soun) {
11275       GNode *wave;
11276       int version, samplesize;
11277       guint16 compression_id;
11278       gboolean amrwb = FALSE;
11279
11280       offset = 16;
11281       /* sample description entry (16) + sound sample description v0 (20) */
11282       if (len < 36)
11283         goto corrupt_file;
11284
11285       version = QT_UINT32 (stsd_entry_data + offset);
11286       entry->n_channels = QT_UINT16 (stsd_entry_data + offset + 8);
11287       samplesize = QT_UINT16 (stsd_entry_data + offset + 10);
11288       compression_id = QT_UINT16 (stsd_entry_data + offset + 12);
11289       entry->rate = QT_FP32 (stsd_entry_data + offset + 16);
11290
11291       GST_LOG_OBJECT (qtdemux, "version/rev:      %08x", version);
11292       GST_LOG_OBJECT (qtdemux, "vendor:           %08x",
11293           QT_UINT32 (stsd_entry_data + offset + 4));
11294       GST_LOG_OBJECT (qtdemux, "n_channels:       %d", entry->n_channels);
11295       GST_LOG_OBJECT (qtdemux, "sample_size:      %d", samplesize);
11296       GST_LOG_OBJECT (qtdemux, "compression_id:   %d", compression_id);
11297       GST_LOG_OBJECT (qtdemux, "packet size:      %d",
11298           QT_UINT16 (stsd_entry_data + offset + 14));
11299       GST_LOG_OBJECT (qtdemux, "sample rate:      %g", entry->rate);
11300
11301       if (compression_id == 0xfffe)
11302         entry->sampled = TRUE;
11303
11304       /* first assume uncompressed audio */
11305       entry->bytes_per_sample = samplesize / 8;
11306       entry->samples_per_frame = entry->n_channels;
11307       entry->bytes_per_frame = entry->n_channels * entry->bytes_per_sample;
11308       entry->samples_per_packet = entry->samples_per_frame;
11309       entry->bytes_per_packet = entry->bytes_per_sample;
11310
11311       offset = 36;
11312       switch (fourcc) {
11313           /* Yes, these have to be hard-coded */
11314         case FOURCC_MAC6:
11315         {
11316           entry->samples_per_packet = 6;
11317           entry->bytes_per_packet = 1;
11318           entry->bytes_per_frame = 1 * entry->n_channels;
11319           entry->bytes_per_sample = 1;
11320           entry->samples_per_frame = 6 * entry->n_channels;
11321           break;
11322         }
11323         case FOURCC_MAC3:
11324         {
11325           entry->samples_per_packet = 3;
11326           entry->bytes_per_packet = 1;
11327           entry->bytes_per_frame = 1 * entry->n_channels;
11328           entry->bytes_per_sample = 1;
11329           entry->samples_per_frame = 3 * entry->n_channels;
11330           break;
11331         }
11332         case FOURCC_ima4:
11333         {
11334           entry->samples_per_packet = 64;
11335           entry->bytes_per_packet = 34;
11336           entry->bytes_per_frame = 34 * entry->n_channels;
11337           entry->bytes_per_sample = 2;
11338           entry->samples_per_frame = 64 * entry->n_channels;
11339           break;
11340         }
11341         case FOURCC_ulaw:
11342         case FOURCC_alaw:
11343         {
11344           entry->samples_per_packet = 1;
11345           entry->bytes_per_packet = 1;
11346           entry->bytes_per_frame = 1 * entry->n_channels;
11347           entry->bytes_per_sample = 1;
11348           entry->samples_per_frame = 1 * entry->n_channels;
11349           break;
11350         }
11351         case FOURCC_agsm:
11352         {
11353           entry->samples_per_packet = 160;
11354           entry->bytes_per_packet = 33;
11355           entry->bytes_per_frame = 33 * entry->n_channels;
11356           entry->bytes_per_sample = 2;
11357           entry->samples_per_frame = 160 * entry->n_channels;
11358           break;
11359         }
11360         default:
11361           break;
11362       }
11363
11364       if (version == 0x00010000) {
11365         /* sample description entry (16) + sound sample description v1 (20+16) */
11366         if (len < 52)
11367           goto corrupt_file;
11368
11369         switch (fourcc) {
11370           case FOURCC_twos:
11371           case FOURCC_sowt:
11372           case FOURCC_raw_:
11373           case FOURCC_lpcm:
11374             break;
11375           default:
11376           {
11377             /* only parse extra decoding config for non-pcm audio */
11378             entry->samples_per_packet = QT_UINT32 (stsd_entry_data + offset);
11379             entry->bytes_per_packet = QT_UINT32 (stsd_entry_data + offset + 4);
11380             entry->bytes_per_frame = QT_UINT32 (stsd_entry_data + offset + 8);
11381             entry->bytes_per_sample = QT_UINT32 (stsd_entry_data + offset + 12);
11382
11383             GST_LOG_OBJECT (qtdemux, "samples/packet:   %d",
11384                 entry->samples_per_packet);
11385             GST_LOG_OBJECT (qtdemux, "bytes/packet:     %d",
11386                 entry->bytes_per_packet);
11387             GST_LOG_OBJECT (qtdemux, "bytes/frame:      %d",
11388                 entry->bytes_per_frame);
11389             GST_LOG_OBJECT (qtdemux, "bytes/sample:     %d",
11390                 entry->bytes_per_sample);
11391
11392             if (!entry->sampled && entry->bytes_per_packet) {
11393               entry->samples_per_frame = (entry->bytes_per_frame /
11394                   entry->bytes_per_packet) * entry->samples_per_packet;
11395               GST_LOG_OBJECT (qtdemux, "samples/frame:    %d",
11396                   entry->samples_per_frame);
11397             }
11398             break;
11399           }
11400         }
11401       } else if (version == 0x00020000) {
11402         union
11403         {
11404           gdouble fp;
11405           guint64 val;
11406         } qtfp;
11407
11408         /* sample description entry (16) + sound sample description v2 (56) */
11409         if (len < 72)
11410           goto corrupt_file;
11411
11412         qtfp.val = QT_UINT64 (stsd_entry_data + offset + 4);
11413         entry->rate = qtfp.fp;
11414         entry->n_channels = QT_UINT32 (stsd_entry_data + offset + 12);
11415
11416         GST_LOG_OBJECT (qtdemux, "Sound sample description Version 2");
11417         GST_LOG_OBJECT (qtdemux, "sample rate:        %g", entry->rate);
11418         GST_LOG_OBJECT (qtdemux, "n_channels:         %d", entry->n_channels);
11419         GST_LOG_OBJECT (qtdemux, "bits/channel:       %d",
11420             QT_UINT32 (stsd_entry_data + offset + 20));
11421         GST_LOG_OBJECT (qtdemux, "format flags:       %X",
11422             QT_UINT32 (stsd_entry_data + offset + 24));
11423         GST_LOG_OBJECT (qtdemux, "bytes/packet:       %d",
11424             QT_UINT32 (stsd_entry_data + offset + 28));
11425         GST_LOG_OBJECT (qtdemux, "LPCM frames/packet: %d",
11426             QT_UINT32 (stsd_entry_data + offset + 32));
11427       } else if (version != 0x00000) {
11428         GST_WARNING_OBJECT (qtdemux, "unknown audio STSD version %08x",
11429             version);
11430       }
11431
11432       if (entry->caps)
11433         gst_caps_unref (entry->caps);
11434
11435       entry->caps = qtdemux_audio_caps (qtdemux, stream, entry, fourcc,
11436           stsd_entry_data + 32, len - 16, &codec);
11437
11438       switch (fourcc) {
11439         case FOURCC_in24:
11440         {
11441           GNode *enda;
11442           GNode *in24;
11443
11444           in24 = qtdemux_tree_get_child_by_type (stsd, FOURCC_in24);
11445
11446           enda = qtdemux_tree_get_child_by_type (in24, FOURCC_enda);
11447           if (!enda) {
11448             wave = qtdemux_tree_get_child_by_type (in24, FOURCC_wave);
11449             if (wave)
11450               enda = qtdemux_tree_get_child_by_type (wave, FOURCC_enda);
11451           }
11452           if (enda) {
11453             int enda_value = QT_UINT16 ((guint8 *) enda->data + 8);
11454             gst_caps_set_simple (entry->caps,
11455                 "format", G_TYPE_STRING, (enda_value) ? "S24LE" : "S24BE",
11456                 NULL);
11457           }
11458           break;
11459         }
11460         case FOURCC_owma:
11461         {
11462           const guint8 *owma_data;
11463           const gchar *codec_name = NULL;
11464           guint owma_len;
11465           GstBuffer *buf;
11466           gint version = 1;
11467           /* from http://msdn.microsoft.com/en-us/library/dd757720(VS.85).aspx */
11468           /* FIXME this should also be gst_riff_strf_auds,
11469            * but the latter one is actually missing bits-per-sample :( */
11470           typedef struct
11471           {
11472             gint16 wFormatTag;
11473             gint16 nChannels;
11474             gint32 nSamplesPerSec;
11475             gint32 nAvgBytesPerSec;
11476             gint16 nBlockAlign;
11477             gint16 wBitsPerSample;
11478             gint16 cbSize;
11479           } WAVEFORMATEX;
11480           WAVEFORMATEX *wfex;
11481
11482           GST_DEBUG_OBJECT (qtdemux, "parse owma");
11483           owma_data = stsd_entry_data;
11484           owma_len = QT_UINT32 (owma_data);
11485           if (owma_len <= 54) {
11486             GST_WARNING_OBJECT (qtdemux, "Too small owma header, skipping");
11487             break;
11488           }
11489           wfex = (WAVEFORMATEX *) (owma_data + 36);
11490           buf = gst_buffer_new_and_alloc (owma_len - 54);
11491           gst_buffer_fill (buf, 0, owma_data + 54, owma_len - 54);
11492           if (wfex->wFormatTag == 0x0161) {
11493             codec_name = "Windows Media Audio";
11494             version = 2;
11495           } else if (wfex->wFormatTag == 0x0162) {
11496             codec_name = "Windows Media Audio 9 Pro";
11497             version = 3;
11498           } else if (wfex->wFormatTag == 0x0163) {
11499             codec_name = "Windows Media Audio 9 Lossless";
11500             /* is that correct? gstffmpegcodecmap.c is missing it, but
11501              * fluendo codec seems to support it */
11502             version = 4;
11503           }
11504
11505           gst_caps_set_simple (entry->caps,
11506               "codec_data", GST_TYPE_BUFFER, buf,
11507               "wmaversion", G_TYPE_INT, version,
11508               "block_align", G_TYPE_INT,
11509               GST_READ_UINT16_LE (&wfex->nBlockAlign), "bitrate", G_TYPE_INT,
11510               GST_READ_UINT32_LE (&wfex->nAvgBytesPerSec), "width", G_TYPE_INT,
11511               GST_READ_UINT16_LE (&wfex->wBitsPerSample), "depth", G_TYPE_INT,
11512               GST_READ_UINT16_LE (&wfex->wBitsPerSample), NULL);
11513           gst_buffer_unref (buf);
11514
11515           if (codec_name) {
11516             g_free (codec);
11517             codec = g_strdup (codec_name);
11518           }
11519           break;
11520         }
11521         case FOURCC_wma_:
11522         {
11523           gint len = QT_UINT32 (stsd_entry_data) - offset;
11524           const guint8 *wfex_data = stsd_entry_data + offset;
11525           const gchar *codec_name = NULL;
11526           gint version = 1;
11527           /* from http://msdn.microsoft.com/en-us/library/dd757720(VS.85).aspx */
11528           /* FIXME this should also be gst_riff_strf_auds,
11529            * but the latter one is actually missing bits-per-sample :( */
11530           typedef struct
11531           {
11532             gint16 wFormatTag;
11533             gint16 nChannels;
11534             gint32 nSamplesPerSec;
11535             gint32 nAvgBytesPerSec;
11536             gint16 nBlockAlign;
11537             gint16 wBitsPerSample;
11538             gint16 cbSize;
11539           } WAVEFORMATEX;
11540           WAVEFORMATEX wfex;
11541
11542           /* FIXME: unify with similar wavformatex parsing code above */
11543           GST_DEBUG_OBJECT (qtdemux, "parse wma, looking for wfex");
11544
11545           /* find wfex */
11546           while (len >= 8) {
11547             gint size;
11548
11549             if (QT_UINT32 (wfex_data) <= len)
11550               size = QT_UINT32 (wfex_data) - 8;
11551             else
11552               size = len - 8;
11553
11554             if (size < 1)
11555               /* No real data, so break out */
11556               break;
11557
11558             switch (QT_FOURCC (wfex_data + 4)) {
11559               case GST_MAKE_FOURCC ('w', 'f', 'e', 'x'):
11560               {
11561                 GST_DEBUG_OBJECT (qtdemux, "found wfex in stsd");
11562
11563                 if (size < 8 + 18)
11564                   break;
11565
11566                 wfex.wFormatTag = GST_READ_UINT16_LE (wfex_data + 8 + 0);
11567                 wfex.nChannels = GST_READ_UINT16_LE (wfex_data + 8 + 2);
11568                 wfex.nSamplesPerSec = GST_READ_UINT32_LE (wfex_data + 8 + 4);
11569                 wfex.nAvgBytesPerSec = GST_READ_UINT32_LE (wfex_data + 8 + 8);
11570                 wfex.nBlockAlign = GST_READ_UINT16_LE (wfex_data + 8 + 12);
11571                 wfex.wBitsPerSample = GST_READ_UINT16_LE (wfex_data + 8 + 14);
11572                 wfex.cbSize = GST_READ_UINT16_LE (wfex_data + 8 + 16);
11573
11574                 GST_LOG_OBJECT (qtdemux, "Found wfex box in stsd:");
11575                 GST_LOG_OBJECT (qtdemux, "FormatTag = 0x%04x, Channels = %u, "
11576                     "SamplesPerSec = %u, AvgBytesPerSec = %u, BlockAlign = %u, "
11577                     "BitsPerSample = %u, Size = %u", wfex.wFormatTag,
11578                     wfex.nChannels, wfex.nSamplesPerSec, wfex.nAvgBytesPerSec,
11579                     wfex.nBlockAlign, wfex.wBitsPerSample, wfex.cbSize);
11580
11581                 if (wfex.wFormatTag == 0x0161) {
11582                   codec_name = "Windows Media Audio";
11583                   version = 2;
11584                 } else if (wfex.wFormatTag == 0x0162) {
11585                   codec_name = "Windows Media Audio 9 Pro";
11586                   version = 3;
11587                 } else if (wfex.wFormatTag == 0x0163) {
11588                   codec_name = "Windows Media Audio 9 Lossless";
11589                   /* is that correct? gstffmpegcodecmap.c is missing it, but
11590                    * fluendo codec seems to support it */
11591                   version = 4;
11592                 }
11593
11594                 gst_caps_set_simple (entry->caps,
11595                     "wmaversion", G_TYPE_INT, version,
11596                     "block_align", G_TYPE_INT, wfex.nBlockAlign,
11597                     "bitrate", G_TYPE_INT, wfex.nAvgBytesPerSec,
11598                     "width", G_TYPE_INT, wfex.wBitsPerSample,
11599                     "depth", G_TYPE_INT, wfex.wBitsPerSample, NULL);
11600
11601                 if (size > wfex.cbSize) {
11602                   GstBuffer *buf;
11603
11604                   buf = gst_buffer_new_and_alloc (size - wfex.cbSize);
11605                   gst_buffer_fill (buf, 0, wfex_data + 8 + wfex.cbSize,
11606                       size - wfex.cbSize);
11607                   gst_caps_set_simple (entry->caps,
11608                       "codec_data", GST_TYPE_BUFFER, buf, NULL);
11609                   gst_buffer_unref (buf);
11610                 } else {
11611                   GST_WARNING_OBJECT (qtdemux, "no codec data");
11612                 }
11613
11614                 if (codec_name) {
11615                   g_free (codec);
11616                   codec = g_strdup (codec_name);
11617                 }
11618                 break;
11619               }
11620               default:
11621                 break;
11622             }
11623             len -= size + 8;
11624             wfex_data += size + 8;
11625           }
11626           break;
11627         }
11628         case FOURCC_opus:
11629         {
11630           const guint8 *opus_data;
11631           guint8 *channel_mapping = NULL;
11632           guint32 rate;
11633           guint8 channels;
11634           guint8 channel_mapping_family;
11635           guint8 stream_count;
11636           guint8 coupled_count;
11637           guint8 i;
11638
11639           opus_data = stsd_entry_data;
11640
11641           channels = GST_READ_UINT8 (opus_data + 45);
11642           rate = GST_READ_UINT32_LE (opus_data + 48);
11643           channel_mapping_family = GST_READ_UINT8 (opus_data + 54);
11644           stream_count = GST_READ_UINT8 (opus_data + 55);
11645           coupled_count = GST_READ_UINT8 (opus_data + 56);
11646
11647           if (channels > 0) {
11648             channel_mapping = g_malloc (channels * sizeof (guint8));
11649             for (i = 0; i < channels; i++)
11650               channel_mapping[i] = GST_READ_UINT8 (opus_data + i + 57);
11651           }
11652
11653           entry->caps = gst_codec_utils_opus_create_caps (rate, channels,
11654               channel_mapping_family, stream_count, coupled_count,
11655               channel_mapping);
11656           break;
11657         }
11658         default:
11659           break;
11660       }
11661
11662       if (codec) {
11663         GstStructure *s;
11664         gint bitrate = 0;
11665
11666         gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
11667             GST_TAG_AUDIO_CODEC, codec, NULL);
11668         g_free (codec);
11669         codec = NULL;
11670
11671         /* some bitrate info may have ended up in caps */
11672         s = gst_caps_get_structure (entry->caps, 0);
11673         gst_structure_get_int (s, "bitrate", &bitrate);
11674         if (bitrate > 0)
11675           gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
11676               GST_TAG_BITRATE, bitrate, NULL);
11677       }
11678
11679       mp4a = qtdemux_tree_get_child_by_index (stsd, stsd_index);
11680       if (!stream->protected) {
11681       } else {
11682         if (QTDEMUX_TREE_NODE_FOURCC (mp4v) != FOURCC_encv) {
11683           mp4v = NULL;
11684         }
11685       }
11686       if (stream->protected && fourcc == FOURCC_mp4a) {
11687         if (QTDEMUX_TREE_NODE_FOURCC (mp4a) != FOURCC_enca) {
11688           mp4a = NULL;
11689         }
11690       } else {
11691         if (QTDEMUX_TREE_NODE_FOURCC (mp4a) != FOURCC_mp4a) {
11692           mp4a = NULL;
11693         }
11694       }
11695
11696       wave = NULL;
11697       esds = NULL;
11698       if (mp4a) {
11699         wave = qtdemux_tree_get_child_by_type (mp4a, FOURCC_wave);
11700         if (wave)
11701           esds = qtdemux_tree_get_child_by_type (wave, FOURCC_esds);
11702         if (!esds)
11703           esds = qtdemux_tree_get_child_by_type (mp4a, FOURCC_esds);
11704       }
11705
11706
11707       /* If the fourcc's bottom 16 bits gives 'sm', then the top
11708          16 bits is a byte-swapped wave-style codec identifier,
11709          and we can find a WAVE header internally to a 'wave' atom here.
11710          This can more clearly be thought of as 'ms' as the top 16 bits, and a
11711          codec id as the bottom 16 bits - but byte-swapped to store in QT (which
11712          is big-endian).
11713        */
11714       if ((fourcc & 0xffff) == (('s' << 8) | 'm')) {
11715         if (len < offset + 20) {
11716           GST_WARNING_OBJECT (qtdemux, "No wave atom in MS-style audio");
11717         } else {
11718           guint32 datalen = QT_UINT32 (stsd_entry_data + offset + 16);
11719           const guint8 *data = stsd_entry_data + offset + 16;
11720           GNode *wavenode;
11721           GNode *waveheadernode;
11722
11723           wavenode = g_node_new ((guint8 *) data);
11724           if (qtdemux_parse_node (qtdemux, wavenode, data, datalen)) {
11725             const guint8 *waveheader;
11726             guint32 headerlen;
11727
11728             waveheadernode = qtdemux_tree_get_child_by_type (wavenode, fourcc);
11729             if (waveheadernode) {
11730               waveheader = (const guint8 *) waveheadernode->data;
11731               headerlen = QT_UINT32 (waveheader);
11732
11733               if (headerlen > 8) {
11734                 gst_riff_strf_auds *header = NULL;
11735                 GstBuffer *headerbuf;
11736                 GstBuffer *extra;
11737
11738                 waveheader += 8;
11739                 headerlen -= 8;
11740
11741                 headerbuf = gst_buffer_new_and_alloc (headerlen);
11742                 gst_buffer_fill (headerbuf, 0, waveheader, headerlen);
11743
11744                 if (gst_riff_parse_strf_auds (GST_ELEMENT_CAST (qtdemux),
11745                         headerbuf, &header, &extra)) {
11746                   gst_caps_unref (entry->caps);
11747                   /* FIXME: Need to do something with the channel reorder map */
11748                   entry->caps =
11749                       gst_riff_create_audio_caps (header->format, NULL, header,
11750                       extra, NULL, NULL, NULL);
11751
11752                   if (extra)
11753                     gst_buffer_unref (extra);
11754                   g_free (header);
11755                 }
11756               }
11757             } else
11758               GST_DEBUG ("Didn't find waveheadernode for this codec");
11759           }
11760           g_node_destroy (wavenode);
11761         }
11762       } else if (esds) {
11763         gst_qtdemux_handle_esds (qtdemux, stream, entry, esds,
11764             stream->stream_tags);
11765       } else {
11766         switch (fourcc) {
11767 #if 0
11768             /* FIXME: what is in the chunk? */
11769           case FOURCC_QDMC:
11770           {
11771             gint len = QT_UINT32 (stsd_data);
11772
11773             /* seems to be always = 116 = 0x74 */
11774             break;
11775           }
11776 #endif
11777           case FOURCC_QDM2:
11778           {
11779             gint len = QT_UINT32 (stsd_entry_data);
11780
11781             if (len > 0x3C) {
11782               GstBuffer *buf = gst_buffer_new_and_alloc (len - 0x3C);
11783
11784               gst_buffer_fill (buf, 0, stsd_entry_data + 0x3C, len - 0x3C);
11785               gst_caps_set_simple (entry->caps,
11786                   "codec_data", GST_TYPE_BUFFER, buf, NULL);
11787               gst_buffer_unref (buf);
11788             }
11789             gst_caps_set_simple (entry->caps,
11790                 "samplesize", G_TYPE_INT, samplesize, NULL);
11791             break;
11792           }
11793           case FOURCC_alac:
11794           {
11795             GNode *alac, *wave = NULL;
11796
11797             /* apparently, m4a has this atom appended directly in the stsd entry,
11798              * while mov has it in a wave atom */
11799             alac = qtdemux_tree_get_child_by_type (stsd, FOURCC_alac);
11800             if (alac) {
11801               /* alac now refers to stsd entry atom */
11802               wave = qtdemux_tree_get_child_by_type (alac, FOURCC_wave);
11803               if (wave)
11804                 alac = qtdemux_tree_get_child_by_type (wave, FOURCC_alac);
11805               else
11806                 alac = qtdemux_tree_get_child_by_type (alac, FOURCC_alac);
11807             }
11808             if (alac) {
11809               const guint8 *alac_data = alac->data;
11810               gint len = QT_UINT32 (alac->data);
11811               GstBuffer *buf;
11812
11813               if (len < 36) {
11814                 GST_DEBUG_OBJECT (qtdemux,
11815                     "discarding alac atom with unexpected len %d", len);
11816               } else {
11817                 /* codec-data contains alac atom size and prefix,
11818                  * ffmpeg likes it that way, not quite gst-ish though ...*/
11819                 buf = gst_buffer_new_and_alloc (len);
11820                 gst_buffer_fill (buf, 0, alac->data, len);
11821                 gst_caps_set_simple (entry->caps,
11822                     "codec_data", GST_TYPE_BUFFER, buf, NULL);
11823                 gst_buffer_unref (buf);
11824
11825                 entry->bytes_per_frame = QT_UINT32 (alac_data + 12);
11826                 entry->n_channels = QT_UINT8 (alac_data + 21);
11827                 entry->rate = QT_UINT32 (alac_data + 32);
11828               }
11829             }
11830             gst_caps_set_simple (entry->caps,
11831                 "samplesize", G_TYPE_INT, samplesize, NULL);
11832             break;
11833           }
11834           case FOURCC_fLaC:
11835           {
11836             /* The codingname of the sample entry is 'fLaC' */
11837             GNode *flac = qtdemux_tree_get_child_by_type (stsd, FOURCC_fLaC);
11838
11839             if (flac) {
11840               /* The 'dfLa' box is added to the sample entry to convey
11841                  initializing information for the decoder. */
11842               const GNode *dfla =
11843                   qtdemux_tree_get_child_by_type (flac, FOURCC_dfLa);
11844
11845               if (dfla) {
11846                 const guint32 len = QT_UINT32 (dfla->data);
11847
11848                 /* Must contain at least dfLa box header (12),
11849                  * METADATA_BLOCK_HEADER (4), METADATA_BLOCK_STREAMINFO (34) */
11850                 if (len < 50) {
11851                   GST_DEBUG_OBJECT (qtdemux,
11852                       "discarding dfla atom with unexpected len %d", len);
11853                 } else {
11854                   /* skip dfLa header to get the METADATA_BLOCKs */
11855                   const guint8 *metadata_blocks = (guint8 *) dfla->data + 12;
11856                   const guint32 metadata_blocks_len = len - 12;
11857
11858                   gchar *stream_marker = g_strdup ("fLaC");
11859                   GstBuffer *block = gst_buffer_new_wrapped (stream_marker,
11860                       strlen (stream_marker));
11861
11862                   guint32 index = 0;
11863                   guint32 remainder = 0;
11864                   guint32 block_size = 0;
11865                   gboolean is_last = FALSE;
11866
11867                   GValue array = G_VALUE_INIT;
11868                   GValue value = G_VALUE_INIT;
11869
11870                   g_value_init (&array, GST_TYPE_ARRAY);
11871                   g_value_init (&value, GST_TYPE_BUFFER);
11872
11873                   gst_value_set_buffer (&value, block);
11874                   gst_value_array_append_value (&array, &value);
11875                   g_value_reset (&value);
11876
11877                   gst_buffer_unref (block);
11878
11879                   /* check there's at least one METADATA_BLOCK_HEADER's worth
11880                    * of data, and we haven't already finished parsing */
11881                   while (!is_last && ((index + 3) < metadata_blocks_len)) {
11882                     remainder = metadata_blocks_len - index;
11883
11884                     /* add the METADATA_BLOCK_HEADER size to the signalled size */
11885                     block_size = 4 +
11886                         (metadata_blocks[index + 1] << 16) +
11887                         (metadata_blocks[index + 2] << 8) +
11888                         metadata_blocks[index + 3];
11889
11890                     /* be careful not to read off end of box */
11891                     if (block_size > remainder) {
11892                       break;
11893                     }
11894
11895                     is_last = metadata_blocks[index] >> 7;
11896
11897                     block = gst_buffer_new_and_alloc (block_size);
11898
11899                     gst_buffer_fill (block, 0, &metadata_blocks[index],
11900                         block_size);
11901
11902                     gst_value_set_buffer (&value, block);
11903                     gst_value_array_append_value (&array, &value);
11904                     g_value_reset (&value);
11905
11906                     gst_buffer_unref (block);
11907
11908                     index += block_size;
11909                   }
11910
11911                   /* only append the metadata if we successfully read all of it */
11912                   if (is_last) {
11913                     gst_structure_set_value (gst_caps_get_structure (CUR_STREAM
11914                             (stream)->caps, 0), "streamheader", &array);
11915                   } else {
11916                     GST_WARNING_OBJECT (qtdemux,
11917                         "discarding all METADATA_BLOCKs due to invalid "
11918                         "block_size %d at idx %d, rem %d", block_size, index,
11919                         remainder);
11920                   }
11921
11922                   g_value_unset (&value);
11923                   g_value_unset (&array);
11924
11925                   /* The sample rate obtained from the stsd may not be accurate
11926                    * since it cannot represent rates greater than 65535Hz, so
11927                    * override that value with the sample rate from the
11928                    * METADATA_BLOCK_STREAMINFO block */
11929                   CUR_STREAM (stream)->rate =
11930                       (QT_UINT32 (metadata_blocks + 14) >> 12) & 0xFFFFF;
11931                 }
11932               }
11933             }
11934             break;
11935           }
11936           case FOURCC_sawb:
11937             /* Fallthrough! */
11938             amrwb = TRUE;
11939           case FOURCC_samr:
11940           {
11941             gint len = QT_UINT32 (stsd_entry_data);
11942
11943             if (len > 0x24) {
11944               GstBuffer *buf = gst_buffer_new_and_alloc (len - 0x24);
11945               guint bitrate;
11946
11947               gst_buffer_fill (buf, 0, stsd_entry_data + 0x24, len - 0x24);
11948
11949               /* If we have enough data, let's try to get the 'damr' atom. See
11950                * the 3GPP container spec (26.244) for more details. */
11951               if ((len - 0x34) > 8 &&
11952                   (bitrate = qtdemux_parse_amr_bitrate (buf, amrwb))) {
11953                 gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
11954                     GST_TAG_MAXIMUM_BITRATE, bitrate, NULL);
11955               }
11956
11957               gst_caps_set_simple (entry->caps,
11958                   "codec_data", GST_TYPE_BUFFER, buf, NULL);
11959               gst_buffer_unref (buf);
11960             }
11961             break;
11962           }
11963           case FOURCC_mp4a:
11964           {
11965             /* mp4a atom withtout ESDS; Attempt to build codec data from atom */
11966             gint len = QT_UINT32 (stsd_entry_data);
11967
11968             if (len >= 34) {
11969               guint16 sound_version = QT_UINT16 (stsd_entry_data + 16);
11970
11971               if (sound_version == 1) {
11972                 guint16 channels = QT_UINT16 (stsd_entry_data + 24);
11973                 guint32 time_scale = QT_UINT32 (stsd_entry_data + 30);
11974                 guint8 codec_data[2];
11975                 GstBuffer *buf;
11976                 gint profile = 2;       /* FIXME: Can this be determined somehow? There doesn't seem to be anything in mp4a atom that specifis compression */
11977
11978                 gint sample_rate_index =
11979                     gst_codec_utils_aac_get_index_from_sample_rate (time_scale);
11980
11981                 /* build AAC codec data */
11982                 codec_data[0] = profile << 3;
11983                 codec_data[0] |= ((sample_rate_index >> 1) & 0x7);
11984                 codec_data[1] = (sample_rate_index & 0x01) << 7;
11985                 codec_data[1] |= (channels & 0xF) << 3;
11986
11987                 buf = gst_buffer_new_and_alloc (2);
11988                 gst_buffer_fill (buf, 0, codec_data, 2);
11989                 gst_caps_set_simple (entry->caps,
11990                     "codec_data", GST_TYPE_BUFFER, buf, NULL);
11991                 gst_buffer_unref (buf);
11992               }
11993             }
11994             break;
11995           }
11996           case FOURCC_lpcm:
11997             /* Fully handled elsewhere */
11998             break;
11999           default:
12000             GST_INFO_OBJECT (qtdemux,
12001                 "unhandled type %" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (fourcc));
12002             break;
12003         }
12004       }
12005       GST_INFO_OBJECT (qtdemux,
12006           "type %" GST_FOURCC_FORMAT " caps %" GST_PTR_FORMAT,
12007           GST_FOURCC_ARGS (fourcc), entry->caps);
12008
12009     } else if (stream->subtype == FOURCC_strm) {
12010       if (fourcc == FOURCC_rtsp) {
12011         stream->redirect_uri = qtdemux_get_rtsp_uri_from_hndl (qtdemux, minf);
12012       } else {
12013         GST_INFO_OBJECT (qtdemux, "unhandled stream type %" GST_FOURCC_FORMAT,
12014             GST_FOURCC_ARGS (fourcc));
12015         goto unknown_stream;
12016       }
12017       entry->sampled = TRUE;
12018     } else if (stream->subtype == FOURCC_subp || stream->subtype == FOURCC_text
12019         || stream->subtype == FOURCC_sbtl || stream->subtype == FOURCC_subt
12020         || stream->subtype == FOURCC_clcp) {
12021
12022       entry->sampled = TRUE;
12023       entry->sparse = TRUE;
12024
12025       entry->caps =
12026           qtdemux_sub_caps (qtdemux, stream, entry, fourcc, stsd_entry_data,
12027           &codec);
12028       if (codec) {
12029         gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
12030             GST_TAG_SUBTITLE_CODEC, codec, NULL);
12031         g_free (codec);
12032         codec = NULL;
12033       }
12034
12035       /* hunt for sort-of codec data */
12036       switch (fourcc) {
12037         case FOURCC_mp4s:
12038         {
12039           GNode *mp4s = NULL;
12040           GNode *esds = NULL;
12041
12042           /* look for palette in a stsd->mp4s->esds sub-atom */
12043           mp4s = qtdemux_tree_get_child_by_type (stsd, FOURCC_mp4s);
12044           if (mp4s)
12045             esds = qtdemux_tree_get_child_by_type (mp4s, FOURCC_esds);
12046           if (esds == NULL) {
12047             /* Invalid STSD */
12048             GST_LOG_OBJECT (qtdemux, "Skipping invalid stsd: no esds child");
12049             break;
12050           }
12051
12052           gst_qtdemux_handle_esds (qtdemux, stream, entry, esds,
12053               stream->stream_tags);
12054           break;
12055         }
12056         default:
12057           GST_INFO_OBJECT (qtdemux,
12058               "unhandled type %" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (fourcc));
12059           break;
12060       }
12061       GST_INFO_OBJECT (qtdemux,
12062           "type %" GST_FOURCC_FORMAT " caps %" GST_PTR_FORMAT,
12063           GST_FOURCC_ARGS (fourcc), entry->caps);
12064     } else {
12065       /* everything in 1 sample */
12066       entry->sampled = TRUE;
12067
12068       entry->caps =
12069           qtdemux_generic_caps (qtdemux, stream, entry, fourcc, stsd_entry_data,
12070           &codec);
12071
12072       if (entry->caps == NULL)
12073         goto unknown_stream;
12074
12075       if (codec) {
12076         gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
12077             GST_TAG_SUBTITLE_CODEC, codec, NULL);
12078         g_free (codec);
12079         codec = NULL;
12080       }
12081     }
12082
12083     /* promote to sampled format */
12084     if (entry->fourcc == FOURCC_samr) {
12085       /* force mono 8000 Hz for AMR */
12086       entry->sampled = TRUE;
12087       entry->n_channels = 1;
12088       entry->rate = 8000;
12089     } else if (entry->fourcc == FOURCC_sawb) {
12090       /* force mono 16000 Hz for AMR-WB */
12091       entry->sampled = TRUE;
12092       entry->n_channels = 1;
12093       entry->rate = 16000;
12094     } else if (entry->fourcc == FOURCC_mp4a) {
12095       entry->sampled = TRUE;
12096     }
12097
12098
12099     stsd_entry_data += len;
12100     remaining_stsd_len -= len;
12101
12102   }
12103
12104   /* collect sample information */
12105   if (!qtdemux_stbl_init (qtdemux, stream, stbl))
12106     goto samples_failed;
12107
12108   if (qtdemux->fragmented) {
12109     guint64 offset;
12110
12111     /* need all moov samples as basis; probably not many if any at all */
12112     /* prevent moof parsing taking of at this time */
12113     offset = qtdemux->moof_offset;
12114     qtdemux->moof_offset = 0;
12115     if (stream->n_samples &&
12116         !qtdemux_parse_samples (qtdemux, stream, stream->n_samples - 1)) {
12117       qtdemux->moof_offset = offset;
12118       goto samples_failed;
12119     }
12120     qtdemux->moof_offset = 0;
12121     /* movie duration more reliable in this case (e.g. mehd) */
12122     if (qtdemux->segment.duration &&
12123         GST_CLOCK_TIME_IS_VALID (qtdemux->segment.duration))
12124       stream->duration =
12125           GSTTIME_TO_QTSTREAMTIME (stream, qtdemux->segment.duration);
12126   }
12127
12128   /* configure segments */
12129   if (!qtdemux_parse_segments (qtdemux, stream, trak))
12130     goto segments_failed;
12131
12132   /* add some language tag, if useful */
12133   if (stream->lang_id[0] != '\0' && strcmp (stream->lang_id, "unk") &&
12134       strcmp (stream->lang_id, "und")) {
12135     const gchar *lang_code;
12136
12137     /* convert ISO 639-2 code to ISO 639-1 */
12138     lang_code = gst_tag_get_language_code (stream->lang_id);
12139     gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
12140         GST_TAG_LANGUAGE_CODE, (lang_code) ? lang_code : stream->lang_id, NULL);
12141   }
12142
12143   /* Check for UDTA tags */
12144   if ((udta = qtdemux_tree_get_child_by_type (trak, FOURCC_udta))) {
12145     qtdemux_parse_udta (qtdemux, stream->stream_tags, udta);
12146   }
12147
12148   /* Insert and sort new stream in track-id order.
12149    * This will help in comparing old/new streams during stream update check */
12150   qtdemux->active_streams =
12151       g_list_insert_sorted (qtdemux->active_streams, stream,
12152       (GCompareFunc) qtdemux_track_id_compare_func);
12153   qtdemux->n_streams++;
12154   GST_DEBUG_OBJECT (qtdemux, "n_streams is now %d", qtdemux->n_streams);
12155
12156   return TRUE;
12157
12158 /* ERRORS */
12159 corrupt_file:
12160   {
12161     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
12162         (_("This file is corrupt and cannot be played.")), (NULL));
12163     if (stream)
12164       gst_qtdemux_stream_free (stream);
12165     return FALSE;
12166   }
12167 error_encrypted:
12168   {
12169     GST_ELEMENT_ERROR (qtdemux, STREAM, DECRYPT, (NULL), (NULL));
12170     gst_qtdemux_stream_free (stream);
12171     return FALSE;
12172   }
12173 samples_failed:
12174 segments_failed:
12175   {
12176     /* we posted an error already */
12177     /* free stbl sub-atoms */
12178     gst_qtdemux_stbl_free (stream);
12179     gst_qtdemux_stream_free (stream);
12180     return FALSE;
12181   }
12182 existing_stream:
12183   {
12184     GST_INFO_OBJECT (qtdemux, "stream with track id %i already exists",
12185         track_id);
12186     return TRUE;
12187   }
12188 unknown_stream:
12189   {
12190     GST_INFO_OBJECT (qtdemux, "unknown subtype %" GST_FOURCC_FORMAT,
12191         GST_FOURCC_ARGS (stream->subtype));
12192     gst_qtdemux_stream_free (stream);
12193     return TRUE;
12194   }
12195 }
12196
12197 /* If we can estimate the overall bitrate, and don't have information about the
12198  * stream bitrate for exactly one stream, this guesses the stream bitrate as
12199  * the overall bitrate minus the sum of the bitrates of all other streams. This
12200  * should be useful for the common case where we have one audio and one video
12201  * stream and can estimate the bitrate of one, but not the other. */
12202 static void
12203 gst_qtdemux_guess_bitrate (GstQTDemux * qtdemux)
12204 {
12205   QtDemuxStream *stream = NULL;
12206   gint64 size, sys_bitrate, sum_bitrate = 0;
12207   GstClockTime duration;
12208   guint bitrate;
12209   GList *iter;
12210
12211   if (qtdemux->fragmented)
12212     return;
12213
12214   GST_DEBUG_OBJECT (qtdemux, "Looking for streams with unknown bitrate");
12215
12216   if (!gst_pad_peer_query_duration (qtdemux->sinkpad, GST_FORMAT_BYTES, &size)
12217       || size <= 0) {
12218     GST_DEBUG_OBJECT (qtdemux,
12219         "Size in bytes of the stream not known - bailing");
12220     return;
12221   }
12222
12223   /* Subtract the header size */
12224   GST_DEBUG_OBJECT (qtdemux, "Total size %" G_GINT64_FORMAT ", header size %u",
12225       size, qtdemux->header_size);
12226
12227   if (size < qtdemux->header_size)
12228     return;
12229
12230   size = size - qtdemux->header_size;
12231
12232   if (!gst_qtdemux_get_duration (qtdemux, &duration)) {
12233     GST_DEBUG_OBJECT (qtdemux, "Stream duration not known - bailing");
12234     return;
12235   }
12236
12237   for (iter = qtdemux->active_streams; iter; iter = g_list_next (iter)) {
12238     QtDemuxStream *str = QTDEMUX_STREAM (iter->data);
12239     switch (str->subtype) {
12240       case FOURCC_soun:
12241       case FOURCC_vide:
12242         GST_DEBUG_OBJECT (qtdemux, "checking bitrate for %" GST_PTR_FORMAT,
12243             CUR_STREAM (str)->caps);
12244         /* retrieve bitrate, prefer avg then max */
12245         bitrate = 0;
12246         if (str->stream_tags) {
12247           if (gst_tag_list_get_uint (str->stream_tags,
12248                   GST_TAG_MAXIMUM_BITRATE, &bitrate))
12249             GST_DEBUG_OBJECT (qtdemux, "max-bitrate: %u", bitrate);
12250           if (gst_tag_list_get_uint (str->stream_tags,
12251                   GST_TAG_NOMINAL_BITRATE, &bitrate))
12252             GST_DEBUG_OBJECT (qtdemux, "nominal-bitrate: %u", bitrate);
12253           if (gst_tag_list_get_uint (str->stream_tags,
12254                   GST_TAG_BITRATE, &bitrate))
12255             GST_DEBUG_OBJECT (qtdemux, "bitrate: %u", bitrate);
12256         }
12257         if (bitrate)
12258           sum_bitrate += bitrate;
12259         else {
12260           if (stream) {
12261             GST_DEBUG_OBJECT (qtdemux,
12262                 ">1 stream with unknown bitrate - bailing");
12263             return;
12264           } else
12265             stream = str;
12266         }
12267
12268       default:
12269         /* For other subtypes, we assume no significant impact on bitrate */
12270         break;
12271     }
12272   }
12273
12274   if (!stream) {
12275     GST_DEBUG_OBJECT (qtdemux, "All stream bitrates are known");
12276     return;
12277   }
12278
12279   sys_bitrate = gst_util_uint64_scale (size, GST_SECOND * 8, duration);
12280
12281   if (sys_bitrate < sum_bitrate) {
12282     /* This can happen, since sum_bitrate might be derived from maximum
12283      * bitrates and not average bitrates */
12284     GST_DEBUG_OBJECT (qtdemux,
12285         "System bitrate less than sum bitrate - bailing");
12286     return;
12287   }
12288
12289   bitrate = sys_bitrate - sum_bitrate;
12290   GST_DEBUG_OBJECT (qtdemux, "System bitrate = %" G_GINT64_FORMAT
12291       ", Stream bitrate = %u", sys_bitrate, bitrate);
12292
12293   if (!stream->stream_tags)
12294     stream->stream_tags = gst_tag_list_new_empty ();
12295   else
12296     stream->stream_tags = gst_tag_list_make_writable (stream->stream_tags);
12297
12298   gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
12299       GST_TAG_BITRATE, bitrate, NULL);
12300 }
12301
12302 static GstFlowReturn
12303 qtdemux_prepare_streams (GstQTDemux * qtdemux)
12304 {
12305   GstFlowReturn ret = GST_FLOW_OK;
12306   GList *iter, *next;
12307
12308   GST_DEBUG_OBJECT (qtdemux, "prepare streams");
12309
12310   for (iter = qtdemux->active_streams; ret == GST_FLOW_OK && iter; iter = next) {
12311     QtDemuxStream *stream = QTDEMUX_STREAM (iter->data);
12312     guint32 sample_num = 0;
12313
12314     next = iter->next;
12315
12316     GST_DEBUG_OBJECT (qtdemux, "track-id %u, fourcc %" GST_FOURCC_FORMAT,
12317         stream->track_id, GST_FOURCC_ARGS (CUR_STREAM (stream)->fourcc));
12318
12319     if (qtdemux->fragmented) {
12320       /* need all moov samples first */
12321       GST_OBJECT_LOCK (qtdemux);
12322       while (stream->n_samples == 0)
12323         if ((ret = qtdemux_add_fragmented_samples (qtdemux)) != GST_FLOW_OK)
12324           break;
12325       GST_OBJECT_UNLOCK (qtdemux);
12326     } else {
12327       /* discard any stray moof */
12328       qtdemux->moof_offset = 0;
12329     }
12330
12331     /* prepare braking */
12332     if (ret != GST_FLOW_ERROR)
12333       ret = GST_FLOW_OK;
12334
12335     /* in pull mode, we should have parsed some sample info by now;
12336      * and quite some code will not handle no samples.
12337      * in push mode, we'll just have to deal with it */
12338     if (G_UNLIKELY (qtdemux->pullbased && !stream->n_samples)) {
12339       GST_DEBUG_OBJECT (qtdemux, "no samples for stream; discarding");
12340       gst_qtdemux_remove_stream (qtdemux, stream);
12341       continue;
12342     } else if (stream->track_id == qtdemux->chapters_track_id &&
12343         (stream->subtype == FOURCC_text || stream->subtype == FOURCC_sbtl)) {
12344       /* TODO - parse chapters track and expose it as GstToc; For now just ignore it
12345          so that it doesn't look like a subtitle track */
12346       gst_qtdemux_remove_stream (qtdemux, stream);
12347       continue;
12348     }
12349
12350     /* parse the initial sample for use in setting the frame rate cap */
12351     while (sample_num == 0 && sample_num < stream->n_samples) {
12352       if (!qtdemux_parse_samples (qtdemux, stream, sample_num))
12353         break;
12354       ++sample_num;
12355     }
12356   }
12357
12358   return ret;
12359 }
12360
12361 static GList *
12362 _stream_in_list (GList * list, QtDemuxStream * stream)
12363 {
12364   GList *iter;
12365
12366   for (iter = list; iter; iter = g_list_next (iter)) {
12367     QtDemuxStream *tmp = QTDEMUX_STREAM (iter->data);
12368     if (!g_strcmp0 (tmp->stream_id, stream->stream_id))
12369       return iter;
12370   }
12371
12372   return NULL;
12373 }
12374
12375 static gboolean
12376 qtdemux_is_streams_update (GstQTDemux * qtdemux)
12377 {
12378   GList *new, *old;
12379
12380   if (!qtdemux->active_streams)
12381     return FALSE;
12382
12383   /* streams in list are sorted in track-id order */
12384   for (new = qtdemux->active_streams, old = qtdemux->old_streams; new && old;
12385       new = g_list_next (new), old = g_list_next (old)) {
12386
12387     /* Different stream-id, updated */
12388     if (g_strcmp0 (QTDEMUX_STREAM (new->data)->stream_id,
12389             QTDEMUX_STREAM (old->data)->stream_id))
12390       return TRUE;
12391   }
12392
12393   /* Different length, updated */
12394   if (new != NULL || old != NULL)
12395     return TRUE;
12396
12397   return FALSE;
12398 }
12399
12400 static gboolean
12401 qtdemux_reuse_and_configure_stream (GstQTDemux * qtdemux,
12402     QtDemuxStream * oldstream, QtDemuxStream * newstream)
12403 {
12404   /* Connect old stream's srcpad to new stream */
12405   newstream->pad = oldstream->pad;
12406   oldstream->pad = NULL;
12407
12408   /* unset new_stream to prevent stream-start event */
12409   newstream->new_stream = FALSE;
12410
12411   return gst_qtdemux_configure_stream (qtdemux, newstream);
12412 }
12413
12414 static gboolean
12415 qtdemux_update_streams (GstQTDemux * qtdemux)
12416 {
12417   GList *iter, *next;
12418
12419   /* At below, figure out which stream in active_streams has identical stream-id
12420    * with that of in old_streams. If there is matching stream-id,
12421    * corresponding newstream will not be exposed again,
12422    * but demux will reuse srcpad of matched old stream
12423    *
12424    * active_streams : newly created streams from the latest moov
12425    * old_streams : existing streams (belong to previous moov)
12426    */
12427
12428   /* Count n_streams again */
12429   qtdemux->n_streams = 0;
12430
12431   for (iter = qtdemux->active_streams; iter; iter = next) {
12432     GList *tmp;
12433     QtDemuxStream *stream = QTDEMUX_STREAM (iter->data);
12434
12435     next = iter->next;
12436
12437     GST_DEBUG_OBJECT (qtdemux, "track-id %u, fourcc %" GST_FOURCC_FORMAT,
12438         stream->track_id, GST_FOURCC_ARGS (CUR_STREAM (stream)->fourcc));
12439
12440     qtdemux->n_streams++;
12441
12442     if (qtdemux->streams_aware
12443         && (tmp = _stream_in_list (qtdemux->old_streams, stream)) != NULL
12444         && QTDEMUX_STREAM (tmp->data)->pad) {
12445       QtDemuxStream *oldstream = QTDEMUX_STREAM (tmp->data);
12446
12447       GST_DEBUG_OBJECT (qtdemux, "Reuse track-id %d", oldstream->track_id);
12448
12449       if (!qtdemux_reuse_and_configure_stream (qtdemux, oldstream, stream))
12450         return FALSE;
12451
12452       qtdemux->old_streams = g_list_remove (qtdemux->old_streams, oldstream);
12453       gst_qtdemux_stream_free (oldstream);
12454     } else {
12455       GstTagList *list;
12456
12457       /* now we have all info and can expose */
12458       list = stream->stream_tags;
12459       stream->stream_tags = NULL;
12460       if (!gst_qtdemux_add_stream (qtdemux, stream, list))
12461         return FALSE;
12462     }
12463   }
12464
12465   return TRUE;
12466 }
12467
12468 /* Must be called with expose lock */
12469 static GstFlowReturn
12470 qtdemux_expose_streams (GstQTDemux * qtdemux)
12471 {
12472   GList *iter, *next;
12473
12474   GST_DEBUG_OBJECT (qtdemux, "exposing streams");
12475
12476   if (!qtdemux_is_streams_update (qtdemux)) {
12477     GList *new, *old;
12478
12479     GST_DEBUG_OBJECT (qtdemux, "Reuse all streams");
12480     for (new = qtdemux->active_streams, old = qtdemux->old_streams; new && old;
12481         new = g_list_next (new), old = g_list_next (old)) {
12482       if (!qtdemux_reuse_and_configure_stream (qtdemux,
12483               QTDEMUX_STREAM (old->data), QTDEMUX_STREAM (new->data)))
12484         return GST_FLOW_ERROR;
12485     }
12486
12487     g_list_free_full (qtdemux->old_streams,
12488         (GDestroyNotify) gst_qtdemux_stream_free);
12489     qtdemux->old_streams = NULL;
12490
12491     return GST_FLOW_OK;
12492   }
12493
12494   if (qtdemux->streams_aware) {
12495     if (!qtdemux_update_streams (qtdemux))
12496       return GST_FLOW_ERROR;
12497   } else {
12498     for (iter = qtdemux->active_streams; iter; iter = g_list_next (iter)) {
12499       QtDemuxStream *stream = QTDEMUX_STREAM (iter->data);
12500       GstTagList *list;
12501
12502       /* now we have all info and can expose */
12503       list = stream->stream_tags;
12504       stream->stream_tags = NULL;
12505       if (!gst_qtdemux_add_stream (qtdemux, stream, list))
12506         return GST_FLOW_ERROR;
12507
12508     }
12509   }
12510
12511   gst_qtdemux_guess_bitrate (qtdemux);
12512
12513   gst_element_no_more_pads (GST_ELEMENT_CAST (qtdemux));
12514
12515   /* If we have still old_streams, it's no more used stream */
12516   for (iter = qtdemux->old_streams; iter; iter = next) {
12517     QtDemuxStream *stream = QTDEMUX_STREAM (iter->data);
12518     next = g_list_next (iter);
12519
12520     if (stream->pad) {
12521       GstEvent *event;
12522
12523       event = gst_event_new_eos ();
12524       if (qtdemux->segment_seqnum)
12525         gst_event_set_seqnum (event, qtdemux->segment_seqnum);
12526
12527       gst_pad_push_event (stream->pad, event);
12528     }
12529
12530     qtdemux->old_streams = g_list_remove (qtdemux->old_streams, stream);
12531     gst_qtdemux_stream_free (stream);
12532   }
12533
12534   /* check if we should post a redirect in case there is a single trak
12535    * and it is a redirecting trak */
12536   if (qtdemux->n_streams == 1 &&
12537       QTDEMUX_FIRST_STREAM (qtdemux)->redirect_uri != NULL) {
12538     GstMessage *m;
12539
12540     GST_INFO_OBJECT (qtdemux, "Issuing a redirect due to a single track with "
12541         "an external content");
12542     m = gst_message_new_element (GST_OBJECT_CAST (qtdemux),
12543         gst_structure_new ("redirect",
12544             "new-location", G_TYPE_STRING,
12545             QTDEMUX_FIRST_STREAM (qtdemux)->redirect_uri, NULL));
12546     gst_element_post_message (GST_ELEMENT_CAST (qtdemux), m);
12547     qtdemux->posted_redirect = TRUE;
12548   }
12549
12550   for (iter = qtdemux->active_streams; iter; iter = g_list_next (iter)) {
12551     qtdemux_do_allocation (qtdemux, QTDEMUX_STREAM (iter->data));
12552   }
12553
12554   qtdemux->need_segment = TRUE;
12555
12556   qtdemux->exposed = TRUE;
12557   return GST_FLOW_OK;
12558 }
12559
12560 /* check if major or compatible brand is 3GP */
12561 static inline gboolean
12562 qtdemux_is_brand_3gp (GstQTDemux * qtdemux, gboolean major)
12563 {
12564   if (major) {
12565     return ((qtdemux->major_brand & GST_MAKE_FOURCC (255, 255, 0, 0)) ==
12566         FOURCC_3g__);
12567   } else if (qtdemux->comp_brands != NULL) {
12568     GstMapInfo map;
12569     guint8 *data;
12570     gsize size;
12571     gboolean res = FALSE;
12572
12573     gst_buffer_map (qtdemux->comp_brands, &map, GST_MAP_READ);
12574     data = map.data;
12575     size = map.size;
12576     while (size >= 4) {
12577       res = res || ((QT_FOURCC (data) & GST_MAKE_FOURCC (255, 255, 0, 0)) ==
12578           FOURCC_3g__);
12579       data += 4;
12580       size -= 4;
12581     }
12582     gst_buffer_unmap (qtdemux->comp_brands, &map);
12583     return res;
12584   } else {
12585     return FALSE;
12586   }
12587 }
12588
12589 /* check if tag is a spec'ed 3GP tag keyword storing a string */
12590 static inline gboolean
12591 qtdemux_is_string_tag_3gp (GstQTDemux * qtdemux, guint32 fourcc)
12592 {
12593   return fourcc == FOURCC_cprt || fourcc == FOURCC_gnre || fourcc == FOURCC_titl
12594       || fourcc == FOURCC_dscp || fourcc == FOURCC_perf || fourcc == FOURCC_auth
12595       || fourcc == FOURCC_albm;
12596 }
12597
12598 static void
12599 qtdemux_tag_add_location (GstQTDemux * qtdemux, GstTagList * taglist,
12600     const char *tag, const char *dummy, GNode * node)
12601 {
12602   const gchar *env_vars[] = { "GST_QT_TAG_ENCODING", "GST_TAG_ENCODING", NULL };
12603   int offset;
12604   char *name;
12605   gchar *data;
12606   gdouble longitude, latitude, altitude;
12607   gint len;
12608
12609   len = QT_UINT32 (node->data);
12610   if (len <= 14)
12611     goto short_read;
12612
12613   data = node->data;
12614   offset = 14;
12615
12616   /* TODO: language code skipped */
12617
12618   name = gst_tag_freeform_string_to_utf8 (data + offset, -1, env_vars);
12619
12620   if (!name) {
12621     /* do not alarm in trivial case, but bail out otherwise */
12622     if (*(data + offset) != 0) {
12623       GST_DEBUG_OBJECT (qtdemux, "failed to convert %s tag to UTF-8, "
12624           "giving up", tag);
12625     }
12626   } else {
12627     gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE,
12628         GST_TAG_GEO_LOCATION_NAME, name, NULL);
12629     offset += strlen (name);
12630     g_free (name);
12631   }
12632
12633   if (len < offset + 2 + 4 + 4 + 4)
12634     goto short_read;
12635
12636   /* +1 +1 = skip null-terminator and location role byte */
12637   offset += 1 + 1;
12638   /* table in spec says unsigned, semantics say negative has meaning ... */
12639   longitude = QT_SFP32 (data + offset);
12640
12641   offset += 4;
12642   latitude = QT_SFP32 (data + offset);
12643
12644   offset += 4;
12645   altitude = QT_SFP32 (data + offset);
12646
12647   /* one invalid means all are invalid */
12648   if (longitude >= -180.0 && longitude <= 180.0 &&
12649       latitude >= -90.0 && latitude <= 90.0) {
12650     gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE,
12651         GST_TAG_GEO_LOCATION_LATITUDE, latitude,
12652         GST_TAG_GEO_LOCATION_LONGITUDE, longitude,
12653         GST_TAG_GEO_LOCATION_ELEVATION, altitude, NULL);
12654   }
12655
12656   /* TODO: no GST_TAG_, so astronomical body and additional notes skipped */
12657
12658   return;
12659
12660   /* ERRORS */
12661 short_read:
12662   {
12663     GST_DEBUG_OBJECT (qtdemux, "short read parsing 3GP location");
12664     return;
12665   }
12666 }
12667
12668
12669 static void
12670 qtdemux_tag_add_year (GstQTDemux * qtdemux, GstTagList * taglist,
12671     const char *tag, const char *dummy, GNode * node)
12672 {
12673   guint16 y;
12674   GDate *date;
12675   gint len;
12676
12677   len = QT_UINT32 (node->data);
12678   if (len < 14)
12679     return;
12680
12681   y = QT_UINT16 ((guint8 *) node->data + 12);
12682   if (y == 0) {
12683     GST_DEBUG_OBJECT (qtdemux, "year: %u is not a valid year", y);
12684     return;
12685   }
12686   GST_DEBUG_OBJECT (qtdemux, "year: %u", y);
12687
12688   date = g_date_new_dmy (1, 1, y);
12689   gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag, date, NULL);
12690   g_date_free (date);
12691 }
12692
12693 static void
12694 qtdemux_tag_add_classification (GstQTDemux * qtdemux, GstTagList * taglist,
12695     const char *tag, const char *dummy, GNode * node)
12696 {
12697   int offset;
12698   char *tag_str = NULL;
12699   guint8 *entity;
12700   guint16 table;
12701   gint len;
12702
12703   len = QT_UINT32 (node->data);
12704   if (len <= 20)
12705     goto short_read;
12706
12707   offset = 12;
12708   entity = (guint8 *) node->data + offset;
12709   if (entity[0] == 0 || entity[1] == 0 || entity[2] == 0 || entity[3] == 0) {
12710     GST_DEBUG_OBJECT (qtdemux,
12711         "classification info: %c%c%c%c invalid classification entity",
12712         entity[0], entity[1], entity[2], entity[3]);
12713     return;
12714   }
12715
12716   offset += 4;
12717   table = QT_UINT16 ((guint8 *) node->data + offset);
12718
12719   /* Language code skipped */
12720
12721   offset += 4;
12722
12723   /* Tag format: "XXXX://Y[YYYY]/classification info string"
12724    * XXXX: classification entity, fixed length 4 chars.
12725    * Y[YYYY]: classification table, max 5 chars.
12726    */
12727   tag_str = g_strdup_printf ("----://%u/%s",
12728       table, (char *) node->data + offset);
12729
12730   /* memcpy To be sure we're preserving byte order */
12731   memcpy (tag_str, entity, 4);
12732   GST_DEBUG_OBJECT (qtdemux, "classification info: %s", tag_str);
12733
12734   gst_tag_list_add (taglist, GST_TAG_MERGE_APPEND, tag, tag_str, NULL);
12735
12736   g_free (tag_str);
12737
12738   return;
12739
12740   /* ERRORS */
12741 short_read:
12742   {
12743     GST_DEBUG_OBJECT (qtdemux, "short read parsing 3GP classification");
12744     return;
12745   }
12746 }
12747
12748 static gboolean
12749 qtdemux_tag_add_str_full (GstQTDemux * qtdemux, GstTagList * taglist,
12750     const char *tag, const char *dummy, GNode * node)
12751 {
12752   const gchar *env_vars[] = { "GST_QT_TAG_ENCODING", "GST_TAG_ENCODING", NULL };
12753   GNode *data;
12754   char *s;
12755   int len;
12756   guint32 type;
12757   int offset;
12758   gboolean ret = TRUE;
12759   const gchar *charset = NULL;
12760
12761   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
12762   if (data) {
12763     len = QT_UINT32 (data->data);
12764     type = QT_UINT32 ((guint8 *) data->data + 8);
12765     if (type == 0x00000001 && len > 16) {
12766       s = gst_tag_freeform_string_to_utf8 ((char *) data->data + 16, len - 16,
12767           env_vars);
12768       if (s) {
12769         GST_DEBUG_OBJECT (qtdemux, "adding tag %s", GST_STR_NULL (s));
12770         gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag, s, NULL);
12771         g_free (s);
12772       } else {
12773         GST_DEBUG_OBJECT (qtdemux, "failed to convert %s tag to UTF-8", tag);
12774       }
12775     }
12776   } else {
12777     len = QT_UINT32 (node->data);
12778     type = QT_UINT32 ((guint8 *) node->data + 4);
12779     if ((type >> 24) == 0xa9 && len > 8 + 4) {
12780       gint str_len;
12781       gint lang_code;
12782
12783       /* Type starts with the (C) symbol, so the next data is a list
12784        * of (string size(16), language code(16), string) */
12785
12786       str_len = QT_UINT16 ((guint8 *) node->data + 8);
12787       lang_code = QT_UINT16 ((guint8 *) node->data + 10);
12788
12789       /* the string + fourcc + size + 2 16bit fields,
12790        * means that there are more tags in this atom */
12791       if (len > str_len + 8 + 4) {
12792         /* TODO how to represent the same tag in different languages? */
12793         GST_WARNING_OBJECT (qtdemux, "Ignoring metadata entry with multiple "
12794             "text alternatives, reading only first one");
12795       }
12796
12797       offset = 12;
12798       len = MIN (len, str_len + 8 + 4); /* remove trailing strings that we don't use */
12799       GST_DEBUG_OBJECT (qtdemux, "found international text tag");
12800
12801       if (lang_code < 0x800) {  /* MAC encoded string */
12802         charset = "mac";
12803       }
12804     } else if (len > 14 && qtdemux_is_string_tag_3gp (qtdemux,
12805             QT_FOURCC ((guint8 *) node->data + 4))) {
12806       guint32 type = QT_UINT32 ((guint8 *) node->data + 8);
12807
12808       /* we go for 3GP style encoding if major brands claims so,
12809        * or if no hope for data be ok UTF-8, and compatible 3GP brand present */
12810       if (qtdemux_is_brand_3gp (qtdemux, TRUE) ||
12811           (qtdemux_is_brand_3gp (qtdemux, FALSE) &&
12812               ((type & 0x00FFFFFF) == 0x0) && (type >> 24 <= 0xF))) {
12813         offset = 14;
12814         /* 16-bit Language code is ignored here as well */
12815         GST_DEBUG_OBJECT (qtdemux, "found 3gpp text tag");
12816       } else {
12817         goto normal;
12818       }
12819     } else {
12820     normal:
12821       offset = 8;
12822       GST_DEBUG_OBJECT (qtdemux, "found normal text tag");
12823       ret = FALSE;              /* may have to fallback */
12824     }
12825     if (charset) {
12826       GError *err = NULL;
12827
12828       s = g_convert ((gchar *) node->data + offset, len - offset, "utf8",
12829           charset, NULL, NULL, &err);
12830       if (err) {
12831         GST_DEBUG_OBJECT (qtdemux, "Failed to convert string from charset %s:"
12832             " %s(%d): %s", charset, g_quark_to_string (err->domain), err->code,
12833             err->message);
12834         g_error_free (err);
12835       }
12836     } else {
12837       s = gst_tag_freeform_string_to_utf8 ((char *) node->data + offset,
12838           len - offset, env_vars);
12839     }
12840     if (s) {
12841       GST_DEBUG_OBJECT (qtdemux, "adding tag %s", GST_STR_NULL (s));
12842       gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag, s, NULL);
12843       g_free (s);
12844       ret = TRUE;
12845     } else {
12846       GST_DEBUG_OBJECT (qtdemux, "failed to convert %s tag to UTF-8", tag);
12847     }
12848   }
12849   return ret;
12850 }
12851
12852 static void
12853 qtdemux_tag_add_str (GstQTDemux * qtdemux, GstTagList * taglist,
12854     const char *tag, const char *dummy, GNode * node)
12855 {
12856   qtdemux_tag_add_str_full (qtdemux, taglist, tag, dummy, node);
12857 }
12858
12859 static void
12860 qtdemux_tag_add_keywords (GstQTDemux * qtdemux, GstTagList * taglist,
12861     const char *tag, const char *dummy, GNode * node)
12862 {
12863   const gchar *env_vars[] = { "GST_QT_TAG_ENCODING", "GST_TAG_ENCODING", NULL };
12864   guint8 *data;
12865   char *s, *t, *k = NULL;
12866   int len;
12867   int offset;
12868   int count;
12869
12870   /* first try normal string tag if major brand not 3GP */
12871   if (!qtdemux_is_brand_3gp (qtdemux, TRUE)) {
12872     if (!qtdemux_tag_add_str_full (qtdemux, taglist, tag, dummy, node)) {
12873       /* hm, that did not work, maybe 3gpp storage in non-3gpp major brand;
12874        * let's try it 3gpp way after minor safety check */
12875       data = node->data;
12876       if (QT_UINT32 (data) < 15 || !qtdemux_is_brand_3gp (qtdemux, FALSE))
12877         return;
12878     } else
12879       return;
12880   }
12881
12882   GST_DEBUG_OBJECT (qtdemux, "found 3gpp keyword tag");
12883
12884   data = node->data;
12885
12886   len = QT_UINT32 (data);
12887   if (len < 15)
12888     goto short_read;
12889
12890   count = QT_UINT8 (data + 14);
12891   offset = 15;
12892   for (; count; count--) {
12893     gint slen;
12894
12895     if (offset + 1 > len)
12896       goto short_read;
12897     slen = QT_UINT8 (data + offset);
12898     offset += 1;
12899     if (offset + slen > len)
12900       goto short_read;
12901     s = gst_tag_freeform_string_to_utf8 ((char *) node->data + offset,
12902         slen, env_vars);
12903     if (s) {
12904       GST_DEBUG_OBJECT (qtdemux, "adding keyword %s", GST_STR_NULL (s));
12905       if (k) {
12906         t = g_strjoin (",", k, s, NULL);
12907         g_free (s);
12908         g_free (k);
12909         k = t;
12910       } else {
12911         k = s;
12912       }
12913     } else {
12914       GST_DEBUG_OBJECT (qtdemux, "failed to convert keyword to UTF-8");
12915     }
12916     offset += slen;
12917   }
12918
12919 done:
12920   if (k) {
12921     GST_DEBUG_OBJECT (qtdemux, "adding tag %s", GST_STR_NULL (k));
12922     gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag, k, NULL);
12923   }
12924   g_free (k);
12925
12926   return;
12927
12928   /* ERRORS */
12929 short_read:
12930   {
12931     GST_DEBUG_OBJECT (qtdemux, "short read parsing 3GP keywords");
12932     goto done;
12933   }
12934 }
12935
12936 static void
12937 qtdemux_tag_add_num (GstQTDemux * qtdemux, GstTagList * taglist,
12938     const char *tag1, const char *tag2, GNode * node)
12939 {
12940   GNode *data;
12941   int len;
12942   int type;
12943   int n1, n2;
12944
12945   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
12946   if (data) {
12947     len = QT_UINT32 (data->data);
12948     type = QT_UINT32 ((guint8 *) data->data + 8);
12949     if (type == 0x00000000 && len >= 22) {
12950       n1 = QT_UINT16 ((guint8 *) data->data + 18);
12951       n2 = QT_UINT16 ((guint8 *) data->data + 20);
12952       if (n1 > 0) {
12953         GST_DEBUG_OBJECT (qtdemux, "adding tag %s=%d", tag1, n1);
12954         gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag1, n1, NULL);
12955       }
12956       if (n2 > 0) {
12957         GST_DEBUG_OBJECT (qtdemux, "adding tag %s=%d", tag2, n2);
12958         gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag2, n2, NULL);
12959       }
12960     }
12961   }
12962 }
12963
12964 static void
12965 qtdemux_tag_add_tmpo (GstQTDemux * qtdemux, GstTagList * taglist,
12966     const char *tag1, const char *dummy, GNode * node)
12967 {
12968   GNode *data;
12969   int len;
12970   int type;
12971   int n1;
12972
12973   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
12974   if (data) {
12975     len = QT_UINT32 (data->data);
12976     type = QT_UINT32 ((guint8 *) data->data + 8);
12977     GST_DEBUG_OBJECT (qtdemux, "have tempo tag, type=%d,len=%d", type, len);
12978     /* some files wrongly have a type 0x0f=15, but it should be 0x15 */
12979     if ((type == 0x00000015 || type == 0x0000000f) && len >= 18) {
12980       n1 = QT_UINT16 ((guint8 *) data->data + 16);
12981       if (n1) {
12982         /* do not add bpm=0 */
12983         GST_DEBUG_OBJECT (qtdemux, "adding tag %d", n1);
12984         gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag1, (gdouble) n1,
12985             NULL);
12986       }
12987     }
12988   }
12989 }
12990
12991 static void
12992 qtdemux_tag_add_uint32 (GstQTDemux * qtdemux, GstTagList * taglist,
12993     const char *tag1, const char *dummy, GNode * node)
12994 {
12995   GNode *data;
12996   int len;
12997   int type;
12998   guint32 num;
12999
13000   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
13001   if (data) {
13002     len = QT_UINT32 (data->data);
13003     type = QT_UINT32 ((guint8 *) data->data + 8);
13004     GST_DEBUG_OBJECT (qtdemux, "have %s tag, type=%d,len=%d", tag1, type, len);
13005     /* some files wrongly have a type 0x0f=15, but it should be 0x15 */
13006     if ((type == 0x00000015 || type == 0x0000000f) && len >= 20) {
13007       num = QT_UINT32 ((guint8 *) data->data + 16);
13008       if (num) {
13009         /* do not add num=0 */
13010         GST_DEBUG_OBJECT (qtdemux, "adding tag %d", num);
13011         gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag1, num, NULL);
13012       }
13013     }
13014   }
13015 }
13016
13017 static void
13018 qtdemux_tag_add_covr (GstQTDemux * qtdemux, GstTagList * taglist,
13019     const char *tag1, const char *dummy, GNode * node)
13020 {
13021   GNode *data;
13022   int len;
13023   int type;
13024   GstSample *sample;
13025
13026   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
13027   if (data) {
13028     len = QT_UINT32 (data->data);
13029     type = QT_UINT32 ((guint8 *) data->data + 8);
13030     GST_DEBUG_OBJECT (qtdemux, "have covr tag, type=%d,len=%d", type, len);
13031     if ((type == 0x0000000d || type == 0x0000000e) && len > 16) {
13032       GstTagImageType image_type;
13033
13034       if (gst_tag_list_get_tag_size (taglist, GST_TAG_IMAGE) == 0)
13035         image_type = GST_TAG_IMAGE_TYPE_FRONT_COVER;
13036       else
13037         image_type = GST_TAG_IMAGE_TYPE_NONE;
13038
13039       if ((sample =
13040               gst_tag_image_data_to_image_sample ((guint8 *) data->data + 16,
13041                   len - 16, image_type))) {
13042         GST_DEBUG_OBJECT (qtdemux, "adding tag size %d", len - 16);
13043         gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag1, sample, NULL);
13044         gst_sample_unref (sample);
13045       }
13046     }
13047   }
13048 }
13049
13050 static void
13051 qtdemux_tag_add_date (GstQTDemux * qtdemux, GstTagList * taglist,
13052     const char *tag, const char *dummy, GNode * node)
13053 {
13054   GNode *data;
13055   GstDateTime *datetime = NULL;
13056   char *s;
13057   int len;
13058   int type;
13059
13060   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
13061   if (data) {
13062     len = QT_UINT32 (data->data);
13063     type = QT_UINT32 ((guint8 *) data->data + 8);
13064     if (type == 0x00000001 && len > 16) {
13065       guint y, m = 1, d = 1;
13066       gint ret;
13067
13068       s = g_strndup ((char *) data->data + 16, len - 16);
13069       GST_DEBUG_OBJECT (qtdemux, "adding date '%s'", s);
13070       datetime = gst_date_time_new_from_iso8601_string (s);
13071       if (datetime != NULL) {
13072         gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, GST_TAG_DATE_TIME,
13073             datetime, NULL);
13074         gst_date_time_unref (datetime);
13075       }
13076
13077       ret = sscanf (s, "%u-%u-%u", &y, &m, &d);
13078       if (ret >= 1 && y > 1500 && y < 3000) {
13079         GDate *date;
13080
13081         date = g_date_new_dmy (d, m, y);
13082         gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag, date, NULL);
13083         g_date_free (date);
13084       } else {
13085         GST_DEBUG_OBJECT (qtdemux, "could not parse date string '%s'", s);
13086       }
13087       g_free (s);
13088     }
13089   }
13090 }
13091
13092 static void
13093 qtdemux_tag_add_gnre (GstQTDemux * qtdemux, GstTagList * taglist,
13094     const char *tag, const char *dummy, GNode * node)
13095 {
13096   GNode *data;
13097
13098   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
13099
13100   /* re-route to normal string tag if major brand says so
13101    * or no data atom and compatible brand suggests so */
13102   if (qtdemux_is_brand_3gp (qtdemux, TRUE) ||
13103       (qtdemux_is_brand_3gp (qtdemux, FALSE) && !data)) {
13104     qtdemux_tag_add_str (qtdemux, taglist, tag, dummy, node);
13105     return;
13106   }
13107
13108   if (data) {
13109     guint len, type, n;
13110
13111     len = QT_UINT32 (data->data);
13112     type = QT_UINT32 ((guint8 *) data->data + 8);
13113     if (type == 0x00000000 && len >= 18) {
13114       n = QT_UINT16 ((guint8 *) data->data + 16);
13115       if (n > 0) {
13116         const gchar *genre;
13117
13118         genre = gst_tag_id3_genre_get (n - 1);
13119         if (genre != NULL) {
13120           GST_DEBUG_OBJECT (qtdemux, "adding %d [%s]", n, genre);
13121           gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag, genre, NULL);
13122         }
13123       }
13124     }
13125   }
13126 }
13127
13128 static void
13129 qtdemux_add_double_tag_from_str (GstQTDemux * demux, GstTagList * taglist,
13130     const gchar * tag, guint8 * data, guint32 datasize)
13131 {
13132   gdouble value;
13133   gchar *datacopy;
13134
13135   /* make a copy to have \0 at the end */
13136   datacopy = g_strndup ((gchar *) data, datasize);
13137
13138   /* convert the str to double */
13139   if (sscanf (datacopy, "%lf", &value) == 1) {
13140     GST_DEBUG_OBJECT (demux, "adding tag: %s [%s]", tag, datacopy);
13141     gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag, value, NULL);
13142   } else {
13143     GST_WARNING_OBJECT (demux, "Failed to parse double from string: %s",
13144         datacopy);
13145   }
13146   g_free (datacopy);
13147 }
13148
13149
13150 static void
13151 qtdemux_tag_add_revdns (GstQTDemux * demux, GstTagList * taglist,
13152     const char *tag, const char *tag_bis, GNode * node)
13153 {
13154   GNode *mean;
13155   GNode *name;
13156   GNode *data;
13157   guint32 meansize;
13158   guint32 namesize;
13159   guint32 datatype;
13160   guint32 datasize;
13161   const gchar *meanstr;
13162   const gchar *namestr;
13163
13164   /* checking the whole ---- atom size for consistency */
13165   if (QT_UINT32 (node->data) <= 4 + 12 + 12 + 16) {
13166     GST_WARNING_OBJECT (demux, "Tag ---- atom is too small, ignoring");
13167     return;
13168   }
13169
13170   mean = qtdemux_tree_get_child_by_type (node, FOURCC_mean);
13171   if (!mean) {
13172     GST_WARNING_OBJECT (demux, "No 'mean' atom found");
13173     return;
13174   }
13175
13176   meansize = QT_UINT32 (mean->data);
13177   if (meansize <= 12) {
13178     GST_WARNING_OBJECT (demux, "Small mean atom, ignoring the whole tag");
13179     return;
13180   }
13181   meanstr = ((gchar *) mean->data) + 12;
13182   meansize -= 12;
13183
13184   name = qtdemux_tree_get_child_by_type (node, FOURCC_name);
13185   if (!name) {
13186     GST_WARNING_OBJECT (demux, "'name' atom not found, ignoring tag");
13187     return;
13188   }
13189
13190   namesize = QT_UINT32 (name->data);
13191   if (namesize <= 12) {
13192     GST_WARNING_OBJECT (demux, "'name' atom is too small, ignoring tag");
13193     return;
13194   }
13195   namestr = ((gchar *) name->data) + 12;
13196   namesize -= 12;
13197
13198   /*
13199    * Data atom is:
13200    * uint32 - size
13201    * uint32 - name
13202    * uint8  - version
13203    * uint24 - data type
13204    * uint32 - all 0
13205    * rest   - the data
13206    */
13207   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
13208   if (!data) {
13209     GST_WARNING_OBJECT (demux, "No data atom in this tag");
13210     return;
13211   }
13212   datasize = QT_UINT32 (data->data);
13213   if (datasize <= 16) {
13214     GST_WARNING_OBJECT (demux, "Data atom too small");
13215     return;
13216   }
13217   datatype = QT_UINT32 (((gchar *) data->data) + 8) & 0xFFFFFF;
13218
13219   if ((strncmp (meanstr, "com.apple.iTunes", meansize) == 0) ||
13220       (strncmp (meanstr, "org.hydrogenaudio.replaygain", meansize) == 0)) {
13221     static const struct
13222     {
13223       const gchar name[28];
13224       const gchar tag[28];
13225     } tags[] = {
13226       {
13227       "replaygain_track_gain", GST_TAG_TRACK_GAIN}, {
13228       "replaygain_track_peak", GST_TAG_TRACK_PEAK}, {
13229       "replaygain_album_gain", GST_TAG_ALBUM_GAIN}, {
13230       "replaygain_album_peak", GST_TAG_ALBUM_PEAK}, {
13231       "MusicBrainz Track Id", GST_TAG_MUSICBRAINZ_TRACKID}, {
13232       "MusicBrainz Artist Id", GST_TAG_MUSICBRAINZ_ARTISTID}, {
13233       "MusicBrainz Album Id", GST_TAG_MUSICBRAINZ_ALBUMID}, {
13234       "MusicBrainz Album Artist Id", GST_TAG_MUSICBRAINZ_ALBUMARTISTID}
13235     };
13236     int i;
13237
13238     for (i = 0; i < G_N_ELEMENTS (tags); ++i) {
13239       if (!g_ascii_strncasecmp (tags[i].name, namestr, namesize)) {
13240         switch (gst_tag_get_type (tags[i].tag)) {
13241           case G_TYPE_DOUBLE:
13242             qtdemux_add_double_tag_from_str (demux, taglist, tags[i].tag,
13243                 ((guint8 *) data->data) + 16, datasize - 16);
13244             break;
13245           case G_TYPE_STRING:
13246             qtdemux_tag_add_str (demux, taglist, tags[i].tag, NULL, node);
13247             break;
13248           default:
13249             /* not reached */
13250             break;
13251         }
13252         break;
13253       }
13254     }
13255     if (i == G_N_ELEMENTS (tags))
13256       goto unknown_tag;
13257   } else {
13258     goto unknown_tag;
13259   }
13260
13261   return;
13262
13263 /* errors */
13264 unknown_tag:
13265 #ifndef GST_DISABLE_GST_DEBUG
13266   {
13267     gchar *namestr_dbg;
13268     gchar *meanstr_dbg;
13269
13270     meanstr_dbg = g_strndup (meanstr, meansize);
13271     namestr_dbg = g_strndup (namestr, namesize);
13272
13273     GST_WARNING_OBJECT (demux, "This tag %s:%s type:%u is not mapped, "
13274         "file a bug at bugzilla.gnome.org", meanstr_dbg, namestr_dbg, datatype);
13275
13276     g_free (namestr_dbg);
13277     g_free (meanstr_dbg);
13278   }
13279 #endif
13280   return;
13281 }
13282
13283 static void
13284 qtdemux_tag_add_id32 (GstQTDemux * demux, GstTagList * taglist, const char *tag,
13285     const char *tag_bis, GNode * node)
13286 {
13287   guint8 *data;
13288   GstBuffer *buf;
13289   guint len;
13290   GstTagList *id32_taglist = NULL;
13291
13292   GST_LOG_OBJECT (demux, "parsing ID32");
13293
13294   data = node->data;
13295   len = GST_READ_UINT32_BE (data);
13296
13297   /* need at least full box and language tag */
13298   if (len < 12 + 2)
13299     return;
13300
13301   buf = gst_buffer_new_allocate (NULL, len - 14, NULL);
13302   gst_buffer_fill (buf, 0, data + 14, len - 14);
13303
13304   id32_taglist = gst_tag_list_from_id3v2_tag (buf);
13305   if (id32_taglist) {
13306     GST_LOG_OBJECT (demux, "parsing ok");
13307     gst_tag_list_insert (taglist, id32_taglist, GST_TAG_MERGE_KEEP);
13308     gst_tag_list_unref (id32_taglist);
13309   } else {
13310     GST_LOG_OBJECT (demux, "parsing failed");
13311   }
13312
13313   gst_buffer_unref (buf);
13314 }
13315
13316 typedef void (*GstQTDemuxAddTagFunc) (GstQTDemux * demux, GstTagList * taglist,
13317     const char *tag, const char *tag_bis, GNode * node);
13318
13319 /* unmapped tags
13320 FOURCC_pcst -> if media is a podcast -> bool
13321 FOURCC_cpil -> if media is part of a compilation -> bool
13322 FOURCC_pgap -> if media is part of a gapless context -> bool
13323 FOURCC_tven -> the tv episode id e.g. S01E23 -> str
13324 */
13325
13326 static const struct
13327 {
13328   guint32 fourcc;
13329   const gchar *gst_tag;
13330   const gchar *gst_tag_bis;
13331   const GstQTDemuxAddTagFunc func;
13332 } add_funcs[] = {
13333   {
13334   FOURCC__nam, GST_TAG_TITLE, NULL, qtdemux_tag_add_str}, {
13335   FOURCC_titl, GST_TAG_TITLE, NULL, qtdemux_tag_add_str}, {
13336   FOURCC__grp, GST_TAG_GROUPING, NULL, qtdemux_tag_add_str}, {
13337   FOURCC__wrt, GST_TAG_COMPOSER, NULL, qtdemux_tag_add_str}, {
13338   FOURCC__ART, GST_TAG_ARTIST, NULL, qtdemux_tag_add_str}, {
13339   FOURCC_aART, GST_TAG_ALBUM_ARTIST, NULL, qtdemux_tag_add_str}, {
13340   FOURCC_perf, GST_TAG_ARTIST, NULL, qtdemux_tag_add_str}, {
13341   FOURCC_auth, GST_TAG_COMPOSER, NULL, qtdemux_tag_add_str}, {
13342   FOURCC__alb, GST_TAG_ALBUM, NULL, qtdemux_tag_add_str}, {
13343   FOURCC_albm, GST_TAG_ALBUM, NULL, qtdemux_tag_add_str}, {
13344   FOURCC_cprt, GST_TAG_COPYRIGHT, NULL, qtdemux_tag_add_str}, {
13345   FOURCC__cpy, GST_TAG_COPYRIGHT, NULL, qtdemux_tag_add_str}, {
13346   FOURCC__cmt, GST_TAG_COMMENT, NULL, qtdemux_tag_add_str}, {
13347   FOURCC__des, GST_TAG_DESCRIPTION, NULL, qtdemux_tag_add_str}, {
13348   FOURCC_desc, GST_TAG_DESCRIPTION, NULL, qtdemux_tag_add_str}, {
13349   FOURCC_dscp, GST_TAG_DESCRIPTION, NULL, qtdemux_tag_add_str}, {
13350   FOURCC__lyr, GST_TAG_LYRICS, NULL, qtdemux_tag_add_str}, {
13351   FOURCC__day, GST_TAG_DATE, NULL, qtdemux_tag_add_date}, {
13352   FOURCC_yrrc, GST_TAG_DATE, NULL, qtdemux_tag_add_year}, {
13353   FOURCC__too, GST_TAG_ENCODER, NULL, qtdemux_tag_add_str}, {
13354   FOURCC__inf, GST_TAG_COMMENT, NULL, qtdemux_tag_add_str}, {
13355   FOURCC_trkn, GST_TAG_TRACK_NUMBER, GST_TAG_TRACK_COUNT, qtdemux_tag_add_num}, {
13356   FOURCC_disk, GST_TAG_ALBUM_VOLUME_NUMBER, GST_TAG_ALBUM_VOLUME_COUNT,
13357         qtdemux_tag_add_num}, {
13358   FOURCC_disc, GST_TAG_ALBUM_VOLUME_NUMBER, GST_TAG_ALBUM_VOLUME_COUNT,
13359         qtdemux_tag_add_num}, {
13360   FOURCC__gen, GST_TAG_GENRE, NULL, qtdemux_tag_add_str}, {
13361   FOURCC_gnre, GST_TAG_GENRE, NULL, qtdemux_tag_add_gnre}, {
13362   FOURCC_tmpo, GST_TAG_BEATS_PER_MINUTE, NULL, qtdemux_tag_add_tmpo}, {
13363   FOURCC_covr, GST_TAG_IMAGE, NULL, qtdemux_tag_add_covr}, {
13364   FOURCC_sonm, GST_TAG_TITLE_SORTNAME, NULL, qtdemux_tag_add_str}, {
13365   FOURCC_soal, GST_TAG_ALBUM_SORTNAME, NULL, qtdemux_tag_add_str}, {
13366   FOURCC_soar, GST_TAG_ARTIST_SORTNAME, NULL, qtdemux_tag_add_str}, {
13367   FOURCC_soaa, GST_TAG_ALBUM_ARTIST_SORTNAME, NULL, qtdemux_tag_add_str}, {
13368   FOURCC_soco, GST_TAG_COMPOSER_SORTNAME, NULL, qtdemux_tag_add_str}, {
13369   FOURCC_sosn, GST_TAG_SHOW_SORTNAME, NULL, qtdemux_tag_add_str}, {
13370   FOURCC_tvsh, GST_TAG_SHOW_NAME, NULL, qtdemux_tag_add_str}, {
13371   FOURCC_tvsn, GST_TAG_SHOW_SEASON_NUMBER, NULL, qtdemux_tag_add_uint32}, {
13372   FOURCC_tves, GST_TAG_SHOW_EPISODE_NUMBER, NULL, qtdemux_tag_add_uint32}, {
13373   FOURCC_kywd, GST_TAG_KEYWORDS, NULL, qtdemux_tag_add_keywords}, {
13374   FOURCC_keyw, GST_TAG_KEYWORDS, NULL, qtdemux_tag_add_str}, {
13375   FOURCC__enc, GST_TAG_ENCODER, NULL, qtdemux_tag_add_str}, {
13376   FOURCC_loci, GST_TAG_GEO_LOCATION_NAME, NULL, qtdemux_tag_add_location}, {
13377   FOURCC_clsf, GST_QT_DEMUX_CLASSIFICATION_TAG, NULL,
13378         qtdemux_tag_add_classification}, {
13379   FOURCC__mak, GST_TAG_DEVICE_MANUFACTURER, NULL, qtdemux_tag_add_str}, {
13380   FOURCC__mod, GST_TAG_DEVICE_MODEL, NULL, qtdemux_tag_add_str}, {
13381   FOURCC__swr, GST_TAG_APPLICATION_NAME, NULL, qtdemux_tag_add_str}, {
13382
13383     /* This is a special case, some tags are stored in this
13384      * 'reverse dns naming', according to:
13385      * http://atomicparsley.sourceforge.net/mpeg-4files.html and
13386      * bug #614471
13387      */
13388   FOURCC_____, "", NULL, qtdemux_tag_add_revdns}, {
13389     /* see http://www.mp4ra.org/specs.html for ID32 in meta box */
13390   FOURCC_ID32, "", NULL, qtdemux_tag_add_id32}
13391 };
13392
13393 struct _GstQtDemuxTagList
13394 {
13395   GstQTDemux *demux;
13396   GstTagList *taglist;
13397 };
13398 typedef struct _GstQtDemuxTagList GstQtDemuxTagList;
13399
13400 static void
13401 qtdemux_tag_add_blob (GNode * node, GstQtDemuxTagList * qtdemuxtaglist)
13402 {
13403   gint len;
13404   guint8 *data;
13405   GstBuffer *buf;
13406   gchar *media_type;
13407   const gchar *style;
13408   GstSample *sample;
13409   GstStructure *s;
13410   guint i;
13411   guint8 ndata[4];
13412   GstQTDemux *demux = qtdemuxtaglist->demux;
13413   GstTagList *taglist = qtdemuxtaglist->taglist;
13414
13415   data = node->data;
13416   len = QT_UINT32 (data);
13417   buf = gst_buffer_new_and_alloc (len);
13418   gst_buffer_fill (buf, 0, data, len);
13419
13420   /* heuristic to determine style of tag */
13421   if (QT_FOURCC (data + 4) == FOURCC_____ ||
13422       (len > 8 + 12 && QT_FOURCC (data + 12) == FOURCC_data))
13423     style = "itunes";
13424   else if (demux->major_brand == FOURCC_qt__)
13425     style = "quicktime";
13426   /* fall back to assuming iso/3gp tag style */
13427   else
13428     style = "iso";
13429
13430   /* santize the name for the caps. */
13431   for (i = 0; i < 4; i++) {
13432     guint8 d = data[4 + i];
13433     if (g_ascii_isalnum (d))
13434       ndata[i] = g_ascii_tolower (d);
13435     else
13436       ndata[i] = '_';
13437   }
13438
13439   media_type = g_strdup_printf ("application/x-gst-qt-%c%c%c%c-tag",
13440       ndata[0], ndata[1], ndata[2], ndata[3]);
13441   GST_DEBUG_OBJECT (demux, "media type %s", media_type);
13442
13443   s = gst_structure_new (media_type, "style", G_TYPE_STRING, style, NULL);
13444   sample = gst_sample_new (buf, NULL, NULL, s);
13445   gst_buffer_unref (buf);
13446   g_free (media_type);
13447
13448   GST_DEBUG_OBJECT (demux, "adding private tag; size %d, info %" GST_PTR_FORMAT,
13449       len, s);
13450
13451   gst_tag_list_add (taglist, GST_TAG_MERGE_APPEND,
13452       GST_QT_DEMUX_PRIVATE_TAG, sample, NULL);
13453
13454   gst_sample_unref (sample);
13455 }
13456
13457 static void
13458 qtdemux_parse_udta (GstQTDemux * qtdemux, GstTagList * taglist, GNode * udta)
13459 {
13460   GNode *meta;
13461   GNode *ilst;
13462   GNode *xmp_;
13463   GNode *node;
13464   gint i;
13465   GstQtDemuxTagList demuxtaglist;
13466
13467   demuxtaglist.demux = qtdemux;
13468   demuxtaglist.taglist = taglist;
13469
13470   meta = qtdemux_tree_get_child_by_type (udta, FOURCC_meta);
13471   if (meta != NULL) {
13472     ilst = qtdemux_tree_get_child_by_type (meta, FOURCC_ilst);
13473     if (ilst == NULL) {
13474       GST_LOG_OBJECT (qtdemux, "no ilst");
13475       return;
13476     }
13477   } else {
13478     ilst = udta;
13479     GST_LOG_OBJECT (qtdemux, "no meta so using udta itself");
13480   }
13481
13482   i = 0;
13483   while (i < G_N_ELEMENTS (add_funcs)) {
13484     node = qtdemux_tree_get_child_by_type (ilst, add_funcs[i].fourcc);
13485     if (node) {
13486       gint len;
13487
13488       len = QT_UINT32 (node->data);
13489       if (len < 12) {
13490         GST_DEBUG_OBJECT (qtdemux, "too small tag atom %" GST_FOURCC_FORMAT,
13491             GST_FOURCC_ARGS (add_funcs[i].fourcc));
13492       } else {
13493         add_funcs[i].func (qtdemux, taglist, add_funcs[i].gst_tag,
13494             add_funcs[i].gst_tag_bis, node);
13495       }
13496       g_node_destroy (node);
13497     } else {
13498       i++;
13499     }
13500   }
13501
13502   /* parsed nodes have been removed, pass along remainder as blob */
13503   g_node_children_foreach (ilst, G_TRAVERSE_ALL,
13504       (GNodeForeachFunc) qtdemux_tag_add_blob, &demuxtaglist);
13505
13506   /* parse up XMP_ node if existing */
13507   xmp_ = qtdemux_tree_get_child_by_type (udta, FOURCC_XMP_);
13508   if (xmp_ != NULL) {
13509     GstBuffer *buf;
13510     GstTagList *xmptaglist;
13511
13512     buf = _gst_buffer_new_wrapped (((guint8 *) xmp_->data) + 8,
13513         QT_UINT32 ((guint8 *) xmp_->data) - 8, NULL);
13514     xmptaglist = gst_tag_list_from_xmp_buffer (buf);
13515     gst_buffer_unref (buf);
13516
13517     qtdemux_handle_xmp_taglist (qtdemux, taglist, xmptaglist);
13518   } else {
13519     GST_DEBUG_OBJECT (qtdemux, "No XMP_ node found");
13520   }
13521 }
13522
13523 typedef struct
13524 {
13525   GstStructure *structure;      /* helper for sort function */
13526   gchar *location;
13527   guint min_req_bitrate;
13528   guint min_req_qt_version;
13529 } GstQtReference;
13530
13531 static gint
13532 qtdemux_redirects_sort_func (gconstpointer a, gconstpointer b)
13533 {
13534   GstQtReference *ref_a = (GstQtReference *) a;
13535   GstQtReference *ref_b = (GstQtReference *) b;
13536
13537   if (ref_b->min_req_qt_version != ref_a->min_req_qt_version)
13538     return ref_b->min_req_qt_version - ref_a->min_req_qt_version;
13539
13540   /* known bitrates go before unknown; higher bitrates go first */
13541   return ref_b->min_req_bitrate - ref_a->min_req_bitrate;
13542 }
13543
13544 /* sort the redirects and post a message for the application.
13545  */
13546 static void
13547 qtdemux_process_redirects (GstQTDemux * qtdemux, GList * references)
13548 {
13549   GstQtReference *best;
13550   GstStructure *s;
13551   GstMessage *msg;
13552   GValue list_val = { 0, };
13553   GList *l;
13554
13555   g_assert (references != NULL);
13556
13557   references = g_list_sort (references, qtdemux_redirects_sort_func);
13558
13559   best = (GstQtReference *) references->data;
13560
13561   g_value_init (&list_val, GST_TYPE_LIST);
13562
13563   for (l = references; l != NULL; l = l->next) {
13564     GstQtReference *ref = (GstQtReference *) l->data;
13565     GValue struct_val = { 0, };
13566
13567     ref->structure = gst_structure_new ("redirect",
13568         "new-location", G_TYPE_STRING, ref->location, NULL);
13569
13570     if (ref->min_req_bitrate > 0) {
13571       gst_structure_set (ref->structure, "minimum-bitrate", G_TYPE_INT,
13572           ref->min_req_bitrate, NULL);
13573     }
13574
13575     g_value_init (&struct_val, GST_TYPE_STRUCTURE);
13576     g_value_set_boxed (&struct_val, ref->structure);
13577     gst_value_list_append_value (&list_val, &struct_val);
13578     g_value_unset (&struct_val);
13579     /* don't free anything here yet, since we need best->structure below */
13580   }
13581
13582   g_assert (best != NULL);
13583   s = gst_structure_copy (best->structure);
13584
13585   if (g_list_length (references) > 1) {
13586     gst_structure_set_value (s, "locations", &list_val);
13587   }
13588
13589   g_value_unset (&list_val);
13590
13591   for (l = references; l != NULL; l = l->next) {
13592     GstQtReference *ref = (GstQtReference *) l->data;
13593
13594     gst_structure_free (ref->structure);
13595     g_free (ref->location);
13596     g_free (ref);
13597   }
13598   g_list_free (references);
13599
13600   GST_INFO_OBJECT (qtdemux, "posting redirect message: %" GST_PTR_FORMAT, s);
13601   msg = gst_message_new_element (GST_OBJECT_CAST (qtdemux), s);
13602   gst_element_post_message (GST_ELEMENT_CAST (qtdemux), msg);
13603   qtdemux->posted_redirect = TRUE;
13604 }
13605
13606 /* look for redirect nodes, collect all redirect information and
13607  * process it.
13608  */
13609 static gboolean
13610 qtdemux_parse_redirects (GstQTDemux * qtdemux)
13611 {
13612   GNode *rmra, *rmda, *rdrf;
13613
13614   rmra = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_rmra);
13615   if (rmra) {
13616     GList *redirects = NULL;
13617
13618     rmda = qtdemux_tree_get_child_by_type (rmra, FOURCC_rmda);
13619     while (rmda) {
13620       GstQtReference ref = { NULL, NULL, 0, 0 };
13621       GNode *rmdr, *rmvc;
13622
13623       if ((rmdr = qtdemux_tree_get_child_by_type (rmda, FOURCC_rmdr))) {
13624         ref.min_req_bitrate = QT_UINT32 ((guint8 *) rmdr->data + 12);
13625         GST_LOG_OBJECT (qtdemux, "data rate atom, required bitrate = %u",
13626             ref.min_req_bitrate);
13627       }
13628
13629       if ((rmvc = qtdemux_tree_get_child_by_type (rmda, FOURCC_rmvc))) {
13630         guint32 package = QT_FOURCC ((guint8 *) rmvc->data + 12);
13631         guint version = QT_UINT32 ((guint8 *) rmvc->data + 16);
13632
13633 #ifndef GST_DISABLE_GST_DEBUG
13634         guint bitmask = QT_UINT32 ((guint8 *) rmvc->data + 20);
13635 #endif
13636         guint check_type = QT_UINT16 ((guint8 *) rmvc->data + 24);
13637
13638         GST_LOG_OBJECT (qtdemux,
13639             "version check atom [%" GST_FOURCC_FORMAT "], version=0x%08x"
13640             ", mask=%08x, check_type=%u", GST_FOURCC_ARGS (package), version,
13641             bitmask, check_type);
13642         if (package == FOURCC_qtim && check_type == 0) {
13643           ref.min_req_qt_version = version;
13644         }
13645       }
13646
13647       rdrf = qtdemux_tree_get_child_by_type (rmda, FOURCC_rdrf);
13648       if (rdrf) {
13649         guint32 ref_type;
13650         guint8 *ref_data;
13651         guint ref_len;
13652
13653         ref_len = QT_UINT32 ((guint8 *) rdrf->data);
13654         if (ref_len > 20) {
13655           ref_type = QT_FOURCC ((guint8 *) rdrf->data + 12);
13656           ref_data = (guint8 *) rdrf->data + 20;
13657           if (ref_type == FOURCC_alis) {
13658             guint record_len, record_version, fn_len;
13659
13660             if (ref_len > 70) {
13661               /* MacOSX alias record, google for alias-layout.txt */
13662               record_len = QT_UINT16 (ref_data + 4);
13663               record_version = QT_UINT16 (ref_data + 4 + 2);
13664               fn_len = QT_UINT8 (ref_data + 50);
13665               if (record_len > 50 && record_version == 2 && fn_len > 0) {
13666                 ref.location = g_strndup ((gchar *) ref_data + 51, fn_len);
13667               }
13668             } else {
13669               GST_WARNING_OBJECT (qtdemux, "Invalid rdrf/alis size (%u < 70)",
13670                   ref_len);
13671             }
13672           } else if (ref_type == FOURCC_url_) {
13673             ref.location = g_strndup ((gchar *) ref_data, ref_len - 8);
13674           } else {
13675             GST_DEBUG_OBJECT (qtdemux,
13676                 "unknown rdrf reference type %" GST_FOURCC_FORMAT,
13677                 GST_FOURCC_ARGS (ref_type));
13678           }
13679           if (ref.location != NULL) {
13680             GST_INFO_OBJECT (qtdemux, "New location: %s", ref.location);
13681             redirects =
13682                 g_list_prepend (redirects, g_memdup (&ref, sizeof (ref)));
13683           } else {
13684             GST_WARNING_OBJECT (qtdemux,
13685                 "Failed to extract redirect location from rdrf atom");
13686           }
13687         } else {
13688           GST_WARNING_OBJECT (qtdemux, "Invalid rdrf size (%u < 20)", ref_len);
13689         }
13690       }
13691
13692       /* look for others */
13693       rmda = qtdemux_tree_get_sibling_by_type (rmda, FOURCC_rmda);
13694     }
13695
13696     if (redirects != NULL) {
13697       qtdemux_process_redirects (qtdemux, redirects);
13698     }
13699   }
13700   return TRUE;
13701 }
13702
13703 static GstTagList *
13704 qtdemux_add_container_format (GstQTDemux * qtdemux, GstTagList * tags)
13705 {
13706   const gchar *fmt;
13707
13708   if (tags == NULL) {
13709     tags = gst_tag_list_new_empty ();
13710     gst_tag_list_set_scope (tags, GST_TAG_SCOPE_GLOBAL);
13711   }
13712
13713   if (qtdemux->major_brand == FOURCC_mjp2)
13714     fmt = "Motion JPEG 2000";
13715   else if ((qtdemux->major_brand & 0xffff) == FOURCC_3g__)
13716     fmt = "3GP";
13717   else if (qtdemux->major_brand == FOURCC_qt__)
13718     fmt = "Quicktime";
13719   else if (qtdemux->fragmented)
13720     fmt = "ISO fMP4";
13721   else
13722     fmt = "ISO MP4/M4A";
13723
13724   GST_LOG_OBJECT (qtdemux, "mapped %" GST_FOURCC_FORMAT " to '%s'",
13725       GST_FOURCC_ARGS (qtdemux->major_brand), fmt);
13726
13727   gst_tag_list_add (tags, GST_TAG_MERGE_REPLACE, GST_TAG_CONTAINER_FORMAT,
13728       fmt, NULL);
13729
13730   return tags;
13731 }
13732
13733 /* we have read the complete moov node now.
13734  * This function parses all of the relevant info, creates the traks and
13735  * prepares all data structures for playback
13736  */
13737 static gboolean
13738 qtdemux_parse_tree (GstQTDemux * qtdemux)
13739 {
13740   GNode *mvhd;
13741   GNode *trak;
13742   GNode *udta;
13743   GNode *mvex;
13744   GNode *pssh;
13745   guint64 creation_time;
13746   GstDateTime *datetime = NULL;
13747   gint version;
13748
13749   /* make sure we have a usable taglist */
13750   qtdemux->tag_list = gst_tag_list_make_writable (qtdemux->tag_list);
13751
13752   mvhd = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_mvhd);
13753   if (mvhd == NULL) {
13754     GST_LOG_OBJECT (qtdemux, "No mvhd node found, looking for redirects.");
13755     return qtdemux_parse_redirects (qtdemux);
13756   }
13757
13758   version = QT_UINT8 ((guint8 *) mvhd->data + 8);
13759   if (version == 1) {
13760     creation_time = QT_UINT64 ((guint8 *) mvhd->data + 12);
13761     qtdemux->timescale = QT_UINT32 ((guint8 *) mvhd->data + 28);
13762     qtdemux->duration = QT_UINT64 ((guint8 *) mvhd->data + 32);
13763   } else if (version == 0) {
13764     creation_time = QT_UINT32 ((guint8 *) mvhd->data + 12);
13765     qtdemux->timescale = QT_UINT32 ((guint8 *) mvhd->data + 20);
13766     qtdemux->duration = QT_UINT32 ((guint8 *) mvhd->data + 24);
13767   } else {
13768     GST_WARNING_OBJECT (qtdemux, "Unhandled mvhd version %d", version);
13769     return FALSE;
13770   }
13771
13772   /* Moving qt creation time (secs since 1904) to unix time */
13773   if (creation_time != 0) {
13774     /* Try to use epoch first as it should be faster and more commonly found */
13775     if (creation_time >= QTDEMUX_SECONDS_FROM_1904_TO_1970) {
13776       GTimeVal now;
13777
13778       creation_time -= QTDEMUX_SECONDS_FROM_1904_TO_1970;
13779       /* some data cleansing sanity */
13780       g_get_current_time (&now);
13781       if (now.tv_sec + 24 * 3600 < creation_time) {
13782         GST_DEBUG_OBJECT (qtdemux, "discarding bogus future creation time");
13783       } else {
13784         datetime = gst_date_time_new_from_unix_epoch_utc (creation_time);
13785       }
13786     } else {
13787       GDateTime *base_dt = g_date_time_new_utc (1904, 1, 1, 0, 0, 0);
13788       GDateTime *dt, *dt_local;
13789
13790       dt = g_date_time_add_seconds (base_dt, creation_time);
13791       dt_local = g_date_time_to_local (dt);
13792       datetime = gst_date_time_new_from_g_date_time (dt_local);
13793
13794       g_date_time_unref (base_dt);
13795       g_date_time_unref (dt);
13796     }
13797   }
13798   if (datetime) {
13799     /* Use KEEP as explicit tags should have a higher priority than mvhd tag */
13800     gst_tag_list_add (qtdemux->tag_list, GST_TAG_MERGE_KEEP, GST_TAG_DATE_TIME,
13801         datetime, NULL);
13802     gst_date_time_unref (datetime);
13803   }
13804
13805   GST_INFO_OBJECT (qtdemux, "timescale: %u", qtdemux->timescale);
13806   GST_INFO_OBJECT (qtdemux, "duration: %" G_GUINT64_FORMAT, qtdemux->duration);
13807
13808   /* check for fragmented file and get some (default) data */
13809   mvex = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_mvex);
13810   if (mvex) {
13811     GNode *mehd;
13812     GstByteReader mehd_data;
13813
13814     /* let track parsing or anyone know weird stuff might happen ... */
13815     qtdemux->fragmented = TRUE;
13816
13817     /* compensate for total duration */
13818     mehd = qtdemux_tree_get_child_by_type_full (mvex, FOURCC_mehd, &mehd_data);
13819     if (mehd)
13820       qtdemux_parse_mehd (qtdemux, &mehd_data);
13821   }
13822
13823   /* Update the movie segment duration, unless it was directly given to us
13824    * by upstream. Otherwise let it as is, as we don't want to mangle the
13825    * duration provided by upstream that may come e.g. from a MPD file. */
13826   if (!qtdemux->upstream_format_is_time) {
13827     GstClockTime duration;
13828     /* set duration in the segment info */
13829     gst_qtdemux_get_duration (qtdemux, &duration);
13830     qtdemux->segment.duration = duration;
13831     /* also do not exceed duration; stop is set that way post seek anyway,
13832      * and segment activation falls back to duration,
13833      * whereas loop only checks stop, so let's align this here as well */
13834     qtdemux->segment.stop = duration;
13835   }
13836
13837   /* parse all traks */
13838   trak = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_trak);
13839   while (trak) {
13840     qtdemux_parse_trak (qtdemux, trak);
13841     /* iterate all siblings */
13842     trak = qtdemux_tree_get_sibling_by_type (trak, FOURCC_trak);
13843   }
13844
13845   qtdemux->tag_list = gst_tag_list_make_writable (qtdemux->tag_list);
13846
13847   /* find tags */
13848   udta = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_udta);
13849   if (udta) {
13850     qtdemux_parse_udta (qtdemux, qtdemux->tag_list, udta);
13851   } else {
13852     GST_LOG_OBJECT (qtdemux, "No udta node found.");
13853   }
13854
13855   /* maybe also some tags in meta box */
13856   udta = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_meta);
13857   if (udta) {
13858     GST_DEBUG_OBJECT (qtdemux, "Parsing meta box for tags.");
13859     qtdemux_parse_udta (qtdemux, qtdemux->tag_list, udta);
13860   } else {
13861     GST_LOG_OBJECT (qtdemux, "No meta node found.");
13862   }
13863
13864   /* parse any protection system info */
13865   pssh = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_pssh);
13866   while (pssh) {
13867     GST_LOG_OBJECT (qtdemux, "Parsing pssh box.");
13868     qtdemux_parse_pssh (qtdemux, pssh);
13869     pssh = qtdemux_tree_get_sibling_by_type (pssh, FOURCC_pssh);
13870   }
13871
13872   qtdemux->tag_list = qtdemux_add_container_format (qtdemux, qtdemux->tag_list);
13873
13874   return TRUE;
13875 }
13876
13877 /* taken from ffmpeg */
13878 static int
13879 read_descr_size (guint8 * ptr, guint8 * end, guint8 ** end_out)
13880 {
13881   int count = 4;
13882   int len = 0;
13883
13884   while (count--) {
13885     int c;
13886
13887     if (ptr >= end)
13888       return -1;
13889
13890     c = *ptr++;
13891     len = (len << 7) | (c & 0x7f);
13892     if (!(c & 0x80))
13893       break;
13894   }
13895   *end_out = ptr;
13896   return len;
13897 }
13898
13899 static GList *
13900 parse_xiph_stream_headers (GstQTDemux * qtdemux, gpointer codec_data,
13901     gsize codec_data_size)
13902 {
13903   GList *list = NULL;
13904   guint8 *p = codec_data;
13905   gint i, offset, num_packets;
13906   guint *length, last;
13907
13908   GST_MEMDUMP_OBJECT (qtdemux, "xiph codec data", codec_data, codec_data_size);
13909
13910   if (codec_data == NULL || codec_data_size == 0)
13911     goto error;
13912
13913   /* start of the stream and vorbis audio or theora video, need to
13914    * send the codec_priv data as first three packets */
13915   num_packets = p[0] + 1;
13916   GST_DEBUG_OBJECT (qtdemux,
13917       "%u stream headers, total length=%" G_GSIZE_FORMAT " bytes",
13918       (guint) num_packets, codec_data_size);
13919
13920   /* Let's put some limits, Don't think there even is a xiph codec
13921    * with more than 3-4 headers */
13922   if (G_UNLIKELY (num_packets > 16)) {
13923     GST_WARNING_OBJECT (qtdemux,
13924         "Unlikely number of xiph headers, most likely not valid");
13925     goto error;
13926   }
13927
13928   length = g_alloca (num_packets * sizeof (guint));
13929   last = 0;
13930   offset = 1;
13931
13932   /* first packets, read length values */
13933   for (i = 0; i < num_packets - 1; i++) {
13934     length[i] = 0;
13935     while (offset < codec_data_size) {
13936       length[i] += p[offset];
13937       if (p[offset++] != 0xff)
13938         break;
13939     }
13940     last += length[i];
13941   }
13942   if (offset + last > codec_data_size)
13943     goto error;
13944
13945   /* last packet is the remaining size */
13946   length[i] = codec_data_size - offset - last;
13947
13948   for (i = 0; i < num_packets; i++) {
13949     GstBuffer *hdr;
13950
13951     GST_DEBUG_OBJECT (qtdemux, "buffer %d: %u bytes", i, (guint) length[i]);
13952
13953     if (offset + length[i] > codec_data_size)
13954       goto error;
13955
13956     hdr = gst_buffer_new_wrapped (g_memdup (p + offset, length[i]), length[i]);
13957     list = g_list_append (list, hdr);
13958
13959     offset += length[i];
13960   }
13961
13962   return list;
13963
13964   /* ERRORS */
13965 error:
13966   {
13967     if (list != NULL)
13968       g_list_free_full (list, (GDestroyNotify) gst_buffer_unref);
13969     return NULL;
13970   }
13971
13972 }
13973
13974 /* this can change the codec originally present in @list */
13975 static void
13976 gst_qtdemux_handle_esds (GstQTDemux * qtdemux, QtDemuxStream * stream,
13977     QtDemuxStreamStsdEntry * entry, GNode * esds, GstTagList * list)
13978 {
13979   int len = QT_UINT32 (esds->data);
13980   guint8 *ptr = esds->data;
13981   guint8 *end = ptr + len;
13982   int tag;
13983   guint8 *data_ptr = NULL;
13984   int data_len = 0;
13985   guint8 object_type_id = 0;
13986   guint8 stream_type = 0;
13987   const char *codec_name = NULL;
13988   GstCaps *caps = NULL;
13989
13990   GST_MEMDUMP_OBJECT (qtdemux, "esds", ptr, len);
13991   ptr += 8;
13992   GST_DEBUG_OBJECT (qtdemux, "version/flags = %08x", QT_UINT32 (ptr));
13993   ptr += 4;
13994   while (ptr + 1 < end) {
13995     tag = QT_UINT8 (ptr);
13996     GST_DEBUG_OBJECT (qtdemux, "tag = %02x", tag);
13997     ptr++;
13998     len = read_descr_size (ptr, end, &ptr);
13999     GST_DEBUG_OBJECT (qtdemux, "len = %d", len);
14000
14001     /* Check the stated amount of data is available for reading */
14002     if (len < 0 || ptr + len > end)
14003       break;
14004
14005     switch (tag) {
14006       case ES_DESCRIPTOR_TAG:
14007         GST_DEBUG_OBJECT (qtdemux, "ID 0x%04x", QT_UINT16 (ptr));
14008         GST_DEBUG_OBJECT (qtdemux, "priority 0x%04x", QT_UINT8 (ptr + 2));
14009         ptr += 3;
14010         break;
14011       case DECODER_CONFIG_DESC_TAG:{
14012         guint max_bitrate, avg_bitrate;
14013
14014         object_type_id = QT_UINT8 (ptr);
14015         stream_type = QT_UINT8 (ptr + 1) >> 2;
14016         max_bitrate = QT_UINT32 (ptr + 5);
14017         avg_bitrate = QT_UINT32 (ptr + 9);
14018         GST_DEBUG_OBJECT (qtdemux, "object_type_id %02x", object_type_id);
14019         GST_DEBUG_OBJECT (qtdemux, "stream_type %02x", stream_type);
14020         GST_DEBUG_OBJECT (qtdemux, "buffer_size_db %02x", QT_UINT24 (ptr + 2));
14021         GST_DEBUG_OBJECT (qtdemux, "max bitrate %u", max_bitrate);
14022         GST_DEBUG_OBJECT (qtdemux, "avg bitrate %u", avg_bitrate);
14023         if (max_bitrate > 0 && max_bitrate < G_MAXUINT32) {
14024           gst_tag_list_add (list, GST_TAG_MERGE_REPLACE,
14025               GST_TAG_MAXIMUM_BITRATE, max_bitrate, NULL);
14026         }
14027         if (avg_bitrate > 0 && avg_bitrate < G_MAXUINT32) {
14028           gst_tag_list_add (list, GST_TAG_MERGE_REPLACE, GST_TAG_BITRATE,
14029               avg_bitrate, NULL);
14030         }
14031         ptr += 13;
14032         break;
14033       }
14034       case DECODER_SPECIFIC_INFO_TAG:
14035         GST_MEMDUMP_OBJECT (qtdemux, "data", ptr, len);
14036         if (object_type_id == 0xe0 && len == 0x40) {
14037           guint8 *data;
14038           GstStructure *s;
14039           guint32 clut[16];
14040           gint i;
14041
14042           GST_DEBUG_OBJECT (qtdemux,
14043               "Have VOBSUB palette. Creating palette event");
14044           /* move to decConfigDescr data and read palette */
14045           data = ptr;
14046           for (i = 0; i < 16; i++) {
14047             clut[i] = QT_UINT32 (data);
14048             data += 4;
14049           }
14050
14051           s = gst_structure_new ("application/x-gst-dvd", "event",
14052               G_TYPE_STRING, "dvd-spu-clut-change",
14053               "clut00", G_TYPE_INT, clut[0], "clut01", G_TYPE_INT, clut[1],
14054               "clut02", G_TYPE_INT, clut[2], "clut03", G_TYPE_INT, clut[3],
14055               "clut04", G_TYPE_INT, clut[4], "clut05", G_TYPE_INT, clut[5],
14056               "clut06", G_TYPE_INT, clut[6], "clut07", G_TYPE_INT, clut[7],
14057               "clut08", G_TYPE_INT, clut[8], "clut09", G_TYPE_INT, clut[9],
14058               "clut10", G_TYPE_INT, clut[10], "clut11", G_TYPE_INT, clut[11],
14059               "clut12", G_TYPE_INT, clut[12], "clut13", G_TYPE_INT, clut[13],
14060               "clut14", G_TYPE_INT, clut[14], "clut15", G_TYPE_INT, clut[15],
14061               NULL);
14062
14063           /* store event and trigger custom processing */
14064           stream->pending_event =
14065               gst_event_new_custom (GST_EVENT_CUSTOM_DOWNSTREAM, s);
14066         } else {
14067           /* Generic codec_data handler puts it on the caps */
14068           data_ptr = ptr;
14069           data_len = len;
14070         }
14071
14072         ptr += len;
14073         break;
14074       case SL_CONFIG_DESC_TAG:
14075         GST_DEBUG_OBJECT (qtdemux, "data %02x", QT_UINT8 (ptr));
14076         ptr += 1;
14077         break;
14078       default:
14079         GST_DEBUG_OBJECT (qtdemux, "Unknown/unhandled descriptor tag %02x",
14080             tag);
14081         GST_MEMDUMP_OBJECT (qtdemux, "descriptor data", ptr, len);
14082         ptr += len;
14083         break;
14084     }
14085   }
14086
14087   /* object_type_id in the esds atom in mp4a and mp4v tells us which codec is
14088    * in use, and should also be used to override some other parameters for some
14089    * codecs. */
14090   switch (object_type_id) {
14091     case 0x20:                 /* MPEG-4 */
14092       /* 4 bytes for the visual_object_sequence_start_code and 1 byte for the
14093        * profile_and_level_indication */
14094       if (data_ptr != NULL && data_len >= 5 &&
14095           GST_READ_UINT32_BE (data_ptr) == 0x000001b0) {
14096         gst_codec_utils_mpeg4video_caps_set_level_and_profile (entry->caps,
14097             data_ptr + 4, data_len - 4);
14098       }
14099       break;                    /* Nothing special needed here */
14100     case 0x21:                 /* H.264 */
14101       codec_name = "H.264 / AVC";
14102       caps = gst_caps_new_simple ("video/x-h264",
14103           "stream-format", G_TYPE_STRING, "avc",
14104           "alignment", G_TYPE_STRING, "au", NULL);
14105       break;
14106     case 0x40:                 /* AAC (any) */
14107     case 0x66:                 /* AAC Main */
14108     case 0x67:                 /* AAC LC */
14109     case 0x68:                 /* AAC SSR */
14110       /* Override channels and rate based on the codec_data, as it's often
14111        * wrong. */
14112       /* Only do so for basic setup without HE-AAC extension */
14113       if (data_ptr && data_len == 2) {
14114         guint channels, rate;
14115
14116         channels = gst_codec_utils_aac_get_channels (data_ptr, data_len);
14117         if (channels > 0)
14118           entry->n_channels = channels;
14119
14120         rate = gst_codec_utils_aac_get_sample_rate (data_ptr, data_len);
14121         if (rate > 0)
14122           entry->rate = rate;
14123       }
14124
14125       /* Set level and profile if possible */
14126       if (data_ptr != NULL && data_len >= 2) {
14127         gst_codec_utils_aac_caps_set_level_and_profile (entry->caps,
14128             data_ptr, data_len);
14129       } else {
14130         const gchar *profile_str = NULL;
14131         GstBuffer *buffer;
14132         GstMapInfo map;
14133         guint8 *codec_data;
14134         gint rate_idx, profile;
14135
14136         /* No codec_data, let's invent something.
14137          * FIXME: This is wrong for SBR! */
14138
14139         GST_WARNING_OBJECT (qtdemux, "No codec_data for AAC available");
14140
14141         buffer = gst_buffer_new_and_alloc (2);
14142         gst_buffer_map (buffer, &map, GST_MAP_WRITE);
14143         codec_data = map.data;
14144
14145         rate_idx =
14146             gst_codec_utils_aac_get_index_from_sample_rate (CUR_STREAM
14147             (stream)->rate);
14148
14149         switch (object_type_id) {
14150           case 0x66:
14151             profile_str = "main";
14152             profile = 0;
14153             break;
14154           case 0x67:
14155             profile_str = "lc";
14156             profile = 1;
14157             break;
14158           case 0x68:
14159             profile_str = "ssr";
14160             profile = 2;
14161             break;
14162           default:
14163             profile = 3;
14164             break;
14165         }
14166
14167         codec_data[0] = ((profile + 1) << 3) | ((rate_idx & 0xE) >> 1);
14168         codec_data[1] =
14169             ((rate_idx & 0x1) << 7) | (CUR_STREAM (stream)->n_channels << 3);
14170
14171         gst_buffer_unmap (buffer, &map);
14172         gst_caps_set_simple (CUR_STREAM (stream)->caps, "codec_data",
14173             GST_TYPE_BUFFER, buffer, NULL);
14174         gst_buffer_unref (buffer);
14175
14176         if (profile_str) {
14177           gst_caps_set_simple (CUR_STREAM (stream)->caps, "profile",
14178               G_TYPE_STRING, profile_str, NULL);
14179         }
14180       }
14181       break;
14182     case 0x60:                 /* MPEG-2, various profiles */
14183     case 0x61:
14184     case 0x62:
14185     case 0x63:
14186     case 0x64:
14187     case 0x65:
14188       codec_name = "MPEG-2 video";
14189       caps = gst_caps_new_simple ("video/mpeg",
14190           "mpegversion", G_TYPE_INT, 2,
14191           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
14192       break;
14193     case 0x69:                 /* MPEG-2 BC audio */
14194     case 0x6B:                 /* MPEG-1 audio */
14195       caps = gst_caps_new_simple ("audio/mpeg",
14196           "mpegversion", G_TYPE_INT, 1, NULL);
14197       codec_name = "MPEG-1 audio";
14198       break;
14199     case 0x6A:                 /* MPEG-1 */
14200       codec_name = "MPEG-1 video";
14201       caps = gst_caps_new_simple ("video/mpeg",
14202           "mpegversion", G_TYPE_INT, 1,
14203           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
14204       break;
14205     case 0x6C:                 /* MJPEG */
14206       caps =
14207           gst_caps_new_simple ("image/jpeg", "parsed", G_TYPE_BOOLEAN, TRUE,
14208           NULL);
14209       codec_name = "Motion-JPEG";
14210       break;
14211     case 0x6D:                 /* PNG */
14212       caps =
14213           gst_caps_new_simple ("image/png", "parsed", G_TYPE_BOOLEAN, TRUE,
14214           NULL);
14215       codec_name = "PNG still images";
14216       break;
14217     case 0x6E:                 /* JPEG2000 */
14218       codec_name = "JPEG-2000";
14219       caps = gst_caps_new_simple ("image/x-j2c", "fields", G_TYPE_INT, 1, NULL);
14220       break;
14221     case 0xA4:                 /* Dirac */
14222       codec_name = "Dirac";
14223       caps = gst_caps_new_empty_simple ("video/x-dirac");
14224       break;
14225     case 0xA5:                 /* AC3 */
14226       codec_name = "AC-3 audio";
14227       caps = gst_caps_new_simple ("audio/x-ac3",
14228           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
14229       break;
14230     case 0xA9:                 /* AC3 */
14231       codec_name = "DTS audio";
14232       caps = gst_caps_new_simple ("audio/x-dts",
14233           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
14234       break;
14235     case 0xDD:
14236       if (stream_type == 0x05 && data_ptr) {
14237         GList *headers =
14238             parse_xiph_stream_headers (qtdemux, data_ptr, data_len);
14239         if (headers) {
14240           GList *tmp;
14241           GValue arr_val = G_VALUE_INIT;
14242           GValue buf_val = G_VALUE_INIT;
14243           GstStructure *s;
14244
14245           /* Let's assume it's vorbis if it's an audio stream of type 0xdd and we have codec data that extracts properly */
14246           codec_name = "Vorbis";
14247           caps = gst_caps_new_empty_simple ("audio/x-vorbis");
14248           g_value_init (&arr_val, GST_TYPE_ARRAY);
14249           g_value_init (&buf_val, GST_TYPE_BUFFER);
14250           for (tmp = headers; tmp; tmp = tmp->next) {
14251             g_value_set_boxed (&buf_val, (GstBuffer *) tmp->data);
14252             gst_value_array_append_value (&arr_val, &buf_val);
14253           }
14254           s = gst_caps_get_structure (caps, 0);
14255           gst_structure_take_value (s, "streamheader", &arr_val);
14256           g_value_unset (&buf_val);
14257           g_list_free (headers);
14258
14259           data_ptr = NULL;
14260           data_len = 0;
14261         }
14262       }
14263       break;
14264     case 0xE1:                 /* QCELP */
14265       /* QCELP, the codec_data is a riff tag (little endian) with
14266        * 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). */
14267       caps = gst_caps_new_empty_simple ("audio/qcelp");
14268       codec_name = "QCELP";
14269       break;
14270     default:
14271       break;
14272   }
14273
14274   /* If we have a replacement caps, then change our caps for this stream */
14275   if (caps) {
14276     gst_caps_unref (entry->caps);
14277     entry->caps = caps;
14278   }
14279
14280   if (codec_name && list)
14281     gst_tag_list_add (list, GST_TAG_MERGE_REPLACE,
14282         GST_TAG_AUDIO_CODEC, codec_name, NULL);
14283
14284   /* Add the codec_data attribute to caps, if we have it */
14285   if (data_ptr) {
14286     GstBuffer *buffer;
14287
14288     buffer = gst_buffer_new_and_alloc (data_len);
14289     gst_buffer_fill (buffer, 0, data_ptr, data_len);
14290
14291     GST_DEBUG_OBJECT (qtdemux, "setting codec_data from esds");
14292     GST_MEMDUMP_OBJECT (qtdemux, "codec_data from esds", data_ptr, data_len);
14293
14294     gst_caps_set_simple (entry->caps, "codec_data", GST_TYPE_BUFFER,
14295         buffer, NULL);
14296     gst_buffer_unref (buffer);
14297   }
14298
14299 }
14300
14301 static inline GstCaps *
14302 _get_unknown_codec_name (const gchar * type, guint32 fourcc)
14303 {
14304   GstCaps *caps;
14305   guint i;
14306   char *s, fourstr[5];
14307
14308   g_snprintf (fourstr, 5, "%" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (fourcc));
14309   for (i = 0; i < 4; i++) {
14310     if (!g_ascii_isalnum (fourstr[i]))
14311       fourstr[i] = '_';
14312   }
14313   s = g_strdup_printf ("%s/x-gst-fourcc-%s", type, g_strstrip (fourstr));
14314   caps = gst_caps_new_empty_simple (s);
14315   g_free (s);
14316   return caps;
14317 }
14318
14319 #define _codec(name) \
14320   do { \
14321     if (codec_name) { \
14322       *codec_name = g_strdup (name); \
14323     } \
14324   } while (0)
14325
14326 static GstCaps *
14327 qtdemux_video_caps (GstQTDemux * qtdemux, QtDemuxStream * stream,
14328     QtDemuxStreamStsdEntry * entry, guint32 fourcc,
14329     const guint8 * stsd_entry_data, gchar ** codec_name)
14330 {
14331   GstCaps *caps = NULL;
14332   GstVideoFormat format = GST_VIDEO_FORMAT_UNKNOWN;
14333
14334   switch (fourcc) {
14335     case FOURCC_png:
14336       _codec ("PNG still images");
14337       caps = gst_caps_new_empty_simple ("image/png");
14338       break;
14339     case FOURCC_jpeg:
14340       _codec ("JPEG still images");
14341       caps =
14342           gst_caps_new_simple ("image/jpeg", "parsed", G_TYPE_BOOLEAN, TRUE,
14343           NULL);
14344       break;
14345     case GST_MAKE_FOURCC ('m', 'j', 'p', 'a'):
14346     case GST_MAKE_FOURCC ('A', 'V', 'D', 'J'):
14347     case GST_MAKE_FOURCC ('M', 'J', 'P', 'G'):
14348     case GST_MAKE_FOURCC ('d', 'm', 'b', '1'):
14349       _codec ("Motion-JPEG");
14350       caps =
14351           gst_caps_new_simple ("image/jpeg", "parsed", G_TYPE_BOOLEAN, TRUE,
14352           NULL);
14353       break;
14354     case GST_MAKE_FOURCC ('m', 'j', 'p', 'b'):
14355       _codec ("Motion-JPEG format B");
14356       caps = gst_caps_new_empty_simple ("video/x-mjpeg-b");
14357       break;
14358     case FOURCC_mjp2:
14359       _codec ("JPEG-2000");
14360       /* override to what it should be according to spec, avoid palette_data */
14361       entry->bits_per_sample = 24;
14362       caps = gst_caps_new_simple ("image/x-j2c", "fields", G_TYPE_INT, 1, NULL);
14363       break;
14364     case FOURCC_SVQ3:
14365       _codec ("Sorensen video v.3");
14366       caps = gst_caps_new_simple ("video/x-svq",
14367           "svqversion", G_TYPE_INT, 3, NULL);
14368       break;
14369     case GST_MAKE_FOURCC ('s', 'v', 'q', 'i'):
14370     case GST_MAKE_FOURCC ('S', 'V', 'Q', '1'):
14371       _codec ("Sorensen video v.1");
14372       caps = gst_caps_new_simple ("video/x-svq",
14373           "svqversion", G_TYPE_INT, 1, NULL);
14374       break;
14375     case GST_MAKE_FOURCC ('W', 'R', 'A', 'W'):
14376       caps = gst_caps_new_empty_simple ("video/x-raw");
14377       gst_caps_set_simple (caps, "format", G_TYPE_STRING, "RGB8P", NULL);
14378       _codec ("Windows Raw RGB");
14379       stream->alignment = 32;
14380       break;
14381     case FOURCC_raw_:
14382     {
14383       guint16 bps;
14384
14385       bps = QT_UINT16 (stsd_entry_data + 82);
14386       switch (bps) {
14387         case 15:
14388           format = GST_VIDEO_FORMAT_RGB15;
14389           break;
14390         case 16:
14391           format = GST_VIDEO_FORMAT_RGB16;
14392           break;
14393         case 24:
14394           format = GST_VIDEO_FORMAT_RGB;
14395           break;
14396         case 32:
14397           format = GST_VIDEO_FORMAT_ARGB;
14398           break;
14399         default:
14400           /* unknown */
14401           break;
14402       }
14403       break;
14404     }
14405     case GST_MAKE_FOURCC ('y', 'v', '1', '2'):
14406       format = GST_VIDEO_FORMAT_I420;
14407       break;
14408     case GST_MAKE_FOURCC ('y', 'u', 'v', '2'):
14409     case GST_MAKE_FOURCC ('Y', 'u', 'v', '2'):
14410       format = GST_VIDEO_FORMAT_I420;
14411       break;
14412     case FOURCC_2vuy:
14413     case GST_MAKE_FOURCC ('2', 'V', 'u', 'y'):
14414       format = GST_VIDEO_FORMAT_UYVY;
14415       break;
14416     case GST_MAKE_FOURCC ('v', '3', '0', '8'):
14417       format = GST_VIDEO_FORMAT_v308;
14418       break;
14419     case GST_MAKE_FOURCC ('v', '2', '1', '6'):
14420       format = GST_VIDEO_FORMAT_v216;
14421       break;
14422     case FOURCC_v210:
14423       format = GST_VIDEO_FORMAT_v210;
14424       break;
14425     case GST_MAKE_FOURCC ('r', '2', '1', '0'):
14426       format = GST_VIDEO_FORMAT_r210;
14427       break;
14428       /* Packed YUV 4:4:4 10 bit in 32 bits, complex
14429          case GST_MAKE_FOURCC ('v', '4', '1', '0'):
14430          format = GST_VIDEO_FORMAT_v410;
14431          break;
14432        */
14433       /* Packed YUV 4:4:4:4 8 bit in 32 bits
14434        * but different order than AYUV
14435        case GST_MAKE_FOURCC ('v', '4', '0', '8'):
14436        format = GST_VIDEO_FORMAT_v408;
14437        break;
14438        */
14439     case GST_MAKE_FOURCC ('m', 'p', 'e', 'g'):
14440     case GST_MAKE_FOURCC ('m', 'p', 'g', '1'):
14441       _codec ("MPEG-1 video");
14442       caps = gst_caps_new_simple ("video/mpeg", "mpegversion", G_TYPE_INT, 1,
14443           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
14444       break;
14445     case GST_MAKE_FOURCC ('h', 'd', 'v', '1'): /* HDV 720p30 */
14446     case GST_MAKE_FOURCC ('h', 'd', 'v', '2'): /* HDV 1080i60 */
14447     case GST_MAKE_FOURCC ('h', 'd', 'v', '3'): /* HDV 1080i50 */
14448     case GST_MAKE_FOURCC ('h', 'd', 'v', '4'): /* HDV 720p24 */
14449     case GST_MAKE_FOURCC ('h', 'd', 'v', '5'): /* HDV 720p25 */
14450     case GST_MAKE_FOURCC ('h', 'd', 'v', '6'): /* HDV 1080p24 */
14451     case GST_MAKE_FOURCC ('h', 'd', 'v', '7'): /* HDV 1080p25 */
14452     case GST_MAKE_FOURCC ('h', 'd', 'v', '8'): /* HDV 1080p30 */
14453     case GST_MAKE_FOURCC ('h', 'd', 'v', '9'): /* HDV 720p60 */
14454     case GST_MAKE_FOURCC ('h', 'd', 'v', 'a'): /* HDV 720p50 */
14455     case GST_MAKE_FOURCC ('m', 'x', '5', 'n'): /* MPEG2 IMX NTSC 525/60 50mb/s produced by FCP */
14456     case GST_MAKE_FOURCC ('m', 'x', '5', 'p'): /* MPEG2 IMX PAL 625/60 50mb/s produced by FCP */
14457     case GST_MAKE_FOURCC ('m', 'x', '4', 'n'): /* MPEG2 IMX NTSC 525/60 40mb/s produced by FCP */
14458     case GST_MAKE_FOURCC ('m', 'x', '4', 'p'): /* MPEG2 IMX PAL 625/60 40mb/s produced by FCP */
14459     case GST_MAKE_FOURCC ('m', 'x', '3', 'n'): /* MPEG2 IMX NTSC 525/60 30mb/s produced by FCP */
14460     case GST_MAKE_FOURCC ('m', 'x', '3', 'p'): /* MPEG2 IMX PAL 625/50 30mb/s produced by FCP */
14461     case GST_MAKE_FOURCC ('x', 'd', 'v', '1'): /* XDCAM HD 720p30 35Mb/s */
14462     case GST_MAKE_FOURCC ('x', 'd', 'v', '2'): /* XDCAM HD 1080i60 35Mb/s */
14463     case GST_MAKE_FOURCC ('x', 'd', 'v', '3'): /* XDCAM HD 1080i50 35Mb/s */
14464     case GST_MAKE_FOURCC ('x', 'd', 'v', '4'): /* XDCAM HD 720p24 35Mb/s */
14465     case GST_MAKE_FOURCC ('x', 'd', 'v', '5'): /* XDCAM HD 720p25 35Mb/s */
14466     case GST_MAKE_FOURCC ('x', 'd', 'v', '6'): /* XDCAM HD 1080p24 35Mb/s */
14467     case GST_MAKE_FOURCC ('x', 'd', 'v', '7'): /* XDCAM HD 1080p25 35Mb/s */
14468     case GST_MAKE_FOURCC ('x', 'd', 'v', '8'): /* XDCAM HD 1080p30 35Mb/s */
14469     case GST_MAKE_FOURCC ('x', 'd', 'v', '9'): /* XDCAM HD 720p60 35Mb/s */
14470     case GST_MAKE_FOURCC ('x', 'd', 'v', 'a'): /* XDCAM HD 720p50 35Mb/s */
14471     case GST_MAKE_FOURCC ('x', 'd', 'v', 'b'): /* XDCAM EX 1080i60 50Mb/s CBR */
14472     case GST_MAKE_FOURCC ('x', 'd', 'v', 'c'): /* XDCAM EX 1080i50 50Mb/s CBR */
14473     case GST_MAKE_FOURCC ('x', 'd', 'v', 'd'): /* XDCAM HD 1080p24 50Mb/s CBR */
14474     case GST_MAKE_FOURCC ('x', 'd', 'v', 'e'): /* XDCAM HD 1080p25 50Mb/s CBR */
14475     case GST_MAKE_FOURCC ('x', 'd', 'v', 'f'): /* XDCAM HD 1080p30 50Mb/s CBR */
14476     case GST_MAKE_FOURCC ('x', 'd', '5', '1'): /* XDCAM HD422 720p30 50Mb/s CBR */
14477     case GST_MAKE_FOURCC ('x', 'd', '5', '4'): /* XDCAM HD422 720p24 50Mb/s CBR */
14478     case GST_MAKE_FOURCC ('x', 'd', '5', '5'): /* XDCAM HD422 720p25 50Mb/s CBR */
14479     case GST_MAKE_FOURCC ('x', 'd', '5', '9'): /* XDCAM HD422 720p60 50Mb/s CBR */
14480     case GST_MAKE_FOURCC ('x', 'd', '5', 'a'): /* XDCAM HD422 720p50 50Mb/s CBR */
14481     case GST_MAKE_FOURCC ('x', 'd', '5', 'b'): /* XDCAM HD422 1080i50 50Mb/s CBR */
14482     case GST_MAKE_FOURCC ('x', 'd', '5', 'c'): /* XDCAM HD422 1080i50 50Mb/s CBR */
14483     case GST_MAKE_FOURCC ('x', 'd', '5', 'd'): /* XDCAM HD422 1080p24 50Mb/s CBR */
14484     case GST_MAKE_FOURCC ('x', 'd', '5', 'e'): /* XDCAM HD422 1080p25 50Mb/s CBR */
14485     case GST_MAKE_FOURCC ('x', 'd', '5', 'f'): /* XDCAM HD422 1080p30 50Mb/s CBR */
14486     case GST_MAKE_FOURCC ('x', 'd', 'h', 'd'): /* XDCAM HD 540p */
14487     case GST_MAKE_FOURCC ('x', 'd', 'h', '2'): /* XDCAM HD422 540p */
14488     case GST_MAKE_FOURCC ('A', 'V', 'm', 'p'): /* AVID IMX PAL */
14489     case GST_MAKE_FOURCC ('m', 'p', 'g', '2'): /* AVID IMX PAL */
14490     case GST_MAKE_FOURCC ('m', 'p', '2', 'v'): /* AVID IMX PAL */
14491     case GST_MAKE_FOURCC ('m', '2', 'v', '1'):
14492       _codec ("MPEG-2 video");
14493       caps = gst_caps_new_simple ("video/mpeg", "mpegversion", G_TYPE_INT, 2,
14494           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
14495       break;
14496     case GST_MAKE_FOURCC ('g', 'i', 'f', ' '):
14497       _codec ("GIF still images");
14498       caps = gst_caps_new_empty_simple ("image/gif");
14499       break;
14500     case FOURCC_h263:
14501     case GST_MAKE_FOURCC ('H', '2', '6', '3'):
14502     case FOURCC_s263:
14503     case GST_MAKE_FOURCC ('U', '2', '6', '3'):
14504       _codec ("H.263");
14505       /* ffmpeg uses the height/width props, don't know why */
14506       caps = gst_caps_new_simple ("video/x-h263",
14507           "variant", G_TYPE_STRING, "itu", NULL);
14508       break;
14509     case FOURCC_mp4v:
14510     case FOURCC_MP4V:
14511       _codec ("MPEG-4 video");
14512       caps = gst_caps_new_simple ("video/mpeg", "mpegversion", G_TYPE_INT, 4,
14513           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
14514       break;
14515     case GST_MAKE_FOURCC ('3', 'i', 'v', 'd'):
14516     case GST_MAKE_FOURCC ('3', 'I', 'V', 'D'):
14517       _codec ("Microsoft MPEG-4 4.3");  /* FIXME? */
14518       caps = gst_caps_new_simple ("video/x-msmpeg",
14519           "msmpegversion", G_TYPE_INT, 43, NULL);
14520       break;
14521     case GST_MAKE_FOURCC ('D', 'I', 'V', '3'):
14522       _codec ("DivX 3");
14523       caps = gst_caps_new_simple ("video/x-divx",
14524           "divxversion", G_TYPE_INT, 3, NULL);
14525       break;
14526     case GST_MAKE_FOURCC ('D', 'I', 'V', 'X'):
14527     case GST_MAKE_FOURCC ('d', 'i', 'v', 'x'):
14528       _codec ("DivX 4");
14529       caps = gst_caps_new_simple ("video/x-divx",
14530           "divxversion", G_TYPE_INT, 4, NULL);
14531       break;
14532     case GST_MAKE_FOURCC ('D', 'X', '5', '0'):
14533       _codec ("DivX 5");
14534       caps = gst_caps_new_simple ("video/x-divx",
14535           "divxversion", G_TYPE_INT, 5, NULL);
14536       break;
14537
14538     case GST_MAKE_FOURCC ('F', 'F', 'V', '1'):
14539       _codec ("FFV1");
14540       caps = gst_caps_new_simple ("video/x-ffv",
14541           "ffvversion", G_TYPE_INT, 1, NULL);
14542       break;
14543
14544     case GST_MAKE_FOURCC ('3', 'I', 'V', '1'):
14545     case GST_MAKE_FOURCC ('3', 'I', 'V', '2'):
14546     case FOURCC_XVID:
14547     case FOURCC_xvid:
14548     case FOURCC_FMP4:
14549     case FOURCC_fmp4:
14550     case GST_MAKE_FOURCC ('U', 'M', 'P', '4'):
14551       caps = gst_caps_new_simple ("video/mpeg", "mpegversion", G_TYPE_INT, 4,
14552           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
14553       _codec ("MPEG-4");
14554       break;
14555
14556     case GST_MAKE_FOURCC ('c', 'v', 'i', 'd'):
14557       _codec ("Cinepak");
14558       caps = gst_caps_new_empty_simple ("video/x-cinepak");
14559       break;
14560     case GST_MAKE_FOURCC ('q', 'd', 'r', 'w'):
14561       _codec ("Apple QuickDraw");
14562       caps = gst_caps_new_empty_simple ("video/x-qdrw");
14563       break;
14564     case GST_MAKE_FOURCC ('r', 'p', 'z', 'a'):
14565       _codec ("Apple video");
14566       caps = gst_caps_new_empty_simple ("video/x-apple-video");
14567       break;
14568     case FOURCC_H264:
14569     case FOURCC_avc1:
14570       _codec ("H.264 / AVC");
14571       caps = gst_caps_new_simple ("video/x-h264",
14572           "stream-format", G_TYPE_STRING, "avc",
14573           "alignment", G_TYPE_STRING, "au", NULL);
14574       break;
14575     case FOURCC_avc3:
14576       _codec ("H.264 / AVC");
14577       caps = gst_caps_new_simple ("video/x-h264",
14578           "stream-format", G_TYPE_STRING, "avc3",
14579           "alignment", G_TYPE_STRING, "au", NULL);
14580       break;
14581     case FOURCC_H265:
14582     case FOURCC_hvc1:
14583       _codec ("H.265 / HEVC");
14584       caps = gst_caps_new_simple ("video/x-h265",
14585           "stream-format", G_TYPE_STRING, "hvc1",
14586           "alignment", G_TYPE_STRING, "au", NULL);
14587       break;
14588     case FOURCC_hev1:
14589       _codec ("H.265 / HEVC");
14590       caps = gst_caps_new_simple ("video/x-h265",
14591           "stream-format", G_TYPE_STRING, "hev1",
14592           "alignment", G_TYPE_STRING, "au", NULL);
14593       break;
14594     case FOURCC_rle_:
14595       _codec ("Run-length encoding");
14596       caps = gst_caps_new_simple ("video/x-rle",
14597           "layout", G_TYPE_STRING, "quicktime", NULL);
14598       break;
14599     case FOURCC_WRLE:
14600       _codec ("Run-length encoding");
14601       caps = gst_caps_new_simple ("video/x-rle",
14602           "layout", G_TYPE_STRING, "microsoft", NULL);
14603       break;
14604     case GST_MAKE_FOURCC ('I', 'V', '3', '2'):
14605     case GST_MAKE_FOURCC ('i', 'v', '3', '2'):
14606       _codec ("Indeo Video 3");
14607       caps = gst_caps_new_simple ("video/x-indeo",
14608           "indeoversion", G_TYPE_INT, 3, NULL);
14609       break;
14610     case GST_MAKE_FOURCC ('I', 'V', '4', '1'):
14611     case GST_MAKE_FOURCC ('i', 'v', '4', '1'):
14612       _codec ("Intel Video 4");
14613       caps = gst_caps_new_simple ("video/x-indeo",
14614           "indeoversion", G_TYPE_INT, 4, NULL);
14615       break;
14616     case FOURCC_dvcp:
14617     case FOURCC_dvc_:
14618     case GST_MAKE_FOURCC ('d', 'v', 's', 'd'):
14619     case GST_MAKE_FOURCC ('D', 'V', 'S', 'D'):
14620     case GST_MAKE_FOURCC ('d', 'v', 'c', 's'):
14621     case GST_MAKE_FOURCC ('D', 'V', 'C', 'S'):
14622     case GST_MAKE_FOURCC ('d', 'v', '2', '5'):
14623     case GST_MAKE_FOURCC ('d', 'v', 'p', 'p'):
14624       _codec ("DV Video");
14625       caps = gst_caps_new_simple ("video/x-dv", "dvversion", G_TYPE_INT, 25,
14626           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
14627       break;
14628     case FOURCC_dv5n:          /* DVCPRO50 NTSC */
14629     case FOURCC_dv5p:          /* DVCPRO50 PAL */
14630       _codec ("DVCPro50 Video");
14631       caps = gst_caps_new_simple ("video/x-dv", "dvversion", G_TYPE_INT, 50,
14632           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
14633       break;
14634     case GST_MAKE_FOURCC ('d', 'v', 'h', '5'): /* DVCPRO HD 50i produced by FCP */
14635     case GST_MAKE_FOURCC ('d', 'v', 'h', '6'): /* DVCPRO HD 60i produced by FCP */
14636       _codec ("DVCProHD Video");
14637       caps = gst_caps_new_simple ("video/x-dv", "dvversion", G_TYPE_INT, 100,
14638           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
14639       break;
14640     case GST_MAKE_FOURCC ('s', 'm', 'c', ' '):
14641       _codec ("Apple Graphics (SMC)");
14642       caps = gst_caps_new_empty_simple ("video/x-smc");
14643       break;
14644     case GST_MAKE_FOURCC ('V', 'P', '3', '1'):
14645       _codec ("VP3");
14646       caps = gst_caps_new_empty_simple ("video/x-vp3");
14647       break;
14648     case GST_MAKE_FOURCC ('V', 'P', '6', 'F'):
14649       _codec ("VP6 Flash");
14650       caps = gst_caps_new_empty_simple ("video/x-vp6-flash");
14651       break;
14652     case FOURCC_XiTh:
14653       _codec ("Theora");
14654       caps = gst_caps_new_empty_simple ("video/x-theora");
14655       /* theora uses one byte of padding in the data stream because it does not
14656        * allow 0 sized packets while theora does */
14657       entry->padding = 1;
14658       break;
14659     case FOURCC_drac:
14660       _codec ("Dirac");
14661       caps = gst_caps_new_empty_simple ("video/x-dirac");
14662       break;
14663     case GST_MAKE_FOURCC ('t', 'i', 'f', 'f'):
14664       _codec ("TIFF still images");
14665       caps = gst_caps_new_empty_simple ("image/tiff");
14666       break;
14667     case GST_MAKE_FOURCC ('i', 'c', 'o', 'd'):
14668       _codec ("Apple Intermediate Codec");
14669       caps = gst_caps_from_string ("video/x-apple-intermediate-codec");
14670       break;
14671     case GST_MAKE_FOURCC ('A', 'V', 'd', 'n'):
14672       _codec ("AVID DNxHD");
14673       caps = gst_caps_from_string ("video/x-dnxhd");
14674       break;
14675     case FOURCC_VP80:
14676     case FOURCC_vp08:
14677       _codec ("On2 VP8");
14678       caps = gst_caps_from_string ("video/x-vp8");
14679       break;
14680     case FOURCC_vp09:
14681       _codec ("Google VP9");
14682       caps = gst_caps_from_string ("video/x-vp9");
14683       break;
14684     case FOURCC_apcs:
14685       _codec ("Apple ProRes LT");
14686       caps =
14687           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING, "lt",
14688           NULL);
14689       break;
14690     case FOURCC_apch:
14691       _codec ("Apple ProRes HQ");
14692       caps =
14693           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING, "hq",
14694           NULL);
14695       break;
14696     case FOURCC_apcn:
14697       _codec ("Apple ProRes");
14698       caps =
14699           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING,
14700           "standard", NULL);
14701       break;
14702     case FOURCC_apco:
14703       _codec ("Apple ProRes Proxy");
14704       caps =
14705           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING,
14706           "proxy", NULL);
14707       break;
14708     case FOURCC_ap4h:
14709       _codec ("Apple ProRes 4444");
14710       caps =
14711           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING,
14712           "4444", NULL);
14713       break;
14714     case FOURCC_ap4x:
14715       _codec ("Apple ProRes 4444 XQ");
14716       caps =
14717           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING,
14718           "4444xq", NULL);
14719       break;
14720     case FOURCC_cfhd:
14721       _codec ("GoPro CineForm");
14722       caps = gst_caps_from_string ("video/x-cineform");
14723       break;
14724     case FOURCC_vc_1:
14725     case FOURCC_ovc1:
14726       _codec ("VC-1");
14727       caps = gst_caps_new_simple ("video/x-wmv",
14728           "wmvversion", G_TYPE_INT, 3, "format", G_TYPE_STRING, "WVC1", NULL);
14729       break;
14730     case FOURCC_av01:
14731       _codec ("AV1");
14732       caps = gst_caps_new_empty_simple ("video/x-av1");
14733       break;
14734     case GST_MAKE_FOURCC ('k', 'p', 'c', 'd'):
14735     default:
14736     {
14737       caps = _get_unknown_codec_name ("video", fourcc);
14738       break;
14739     }
14740   }
14741
14742   if (format != GST_VIDEO_FORMAT_UNKNOWN) {
14743     GstVideoInfo info;
14744
14745     gst_video_info_init (&info);
14746     gst_video_info_set_format (&info, format, entry->width, entry->height);
14747
14748     caps = gst_video_info_to_caps (&info);
14749     *codec_name = gst_pb_utils_get_codec_description (caps);
14750
14751     /* enable clipping for raw video streams */
14752     stream->need_clip = TRUE;
14753     stream->alignment = 32;
14754   }
14755
14756   return caps;
14757 }
14758
14759 static guint
14760 round_up_pow2 (guint n)
14761 {
14762   n = n - 1;
14763   n = n | (n >> 1);
14764   n = n | (n >> 2);
14765   n = n | (n >> 4);
14766   n = n | (n >> 8);
14767   n = n | (n >> 16);
14768   return n + 1;
14769 }
14770
14771 static GstCaps *
14772 qtdemux_audio_caps (GstQTDemux * qtdemux, QtDemuxStream * stream,
14773     QtDemuxStreamStsdEntry * entry, guint32 fourcc, const guint8 * data,
14774     int len, gchar ** codec_name)
14775 {
14776   GstCaps *caps;
14777   const GstStructure *s;
14778   const gchar *name;
14779   gint endian = 0;
14780   GstAudioFormat format = 0;
14781   gint depth;
14782
14783   GST_DEBUG_OBJECT (qtdemux, "resolve fourcc 0x%08x", GUINT32_TO_BE (fourcc));
14784
14785   depth = entry->bytes_per_packet * 8;
14786
14787   switch (fourcc) {
14788     case GST_MAKE_FOURCC ('N', 'O', 'N', 'E'):
14789     case FOURCC_raw_:
14790       /* 8-bit audio is unsigned */
14791       if (depth == 8)
14792         format = GST_AUDIO_FORMAT_U8;
14793       /* otherwise it's signed and big-endian just like 'twos' */
14794     case FOURCC_twos:
14795       endian = G_BIG_ENDIAN;
14796       /* fall-through */
14797     case FOURCC_sowt:
14798     {
14799       gchar *str;
14800
14801       if (!endian)
14802         endian = G_LITTLE_ENDIAN;
14803
14804       if (!format)
14805         format = gst_audio_format_build_integer (TRUE, endian, depth, depth);
14806
14807       str = g_strdup_printf ("Raw %d-bit PCM audio", depth);
14808       _codec (str);
14809       g_free (str);
14810
14811       caps = gst_caps_new_simple ("audio/x-raw",
14812           "format", G_TYPE_STRING, gst_audio_format_to_string (format),
14813           "layout", G_TYPE_STRING, "interleaved", NULL);
14814       stream->alignment = GST_ROUND_UP_8 (depth);
14815       stream->alignment = round_up_pow2 (stream->alignment);
14816       break;
14817     }
14818     case GST_MAKE_FOURCC ('f', 'l', '6', '4'):
14819       _codec ("Raw 64-bit floating-point audio");
14820       caps = gst_caps_new_simple ("audio/x-raw",
14821           "format", G_TYPE_STRING, "F64BE",
14822           "layout", G_TYPE_STRING, "interleaved", NULL);
14823       stream->alignment = 8;
14824       break;
14825     case GST_MAKE_FOURCC ('f', 'l', '3', '2'):
14826       _codec ("Raw 32-bit floating-point audio");
14827       caps = gst_caps_new_simple ("audio/x-raw",
14828           "format", G_TYPE_STRING, "F32BE",
14829           "layout", G_TYPE_STRING, "interleaved", NULL);
14830       stream->alignment = 4;
14831       break;
14832     case FOURCC_in24:
14833       _codec ("Raw 24-bit PCM audio");
14834       /* we assume BIG ENDIAN, an enda box will tell us to change this to little
14835        * endian later */
14836       caps = gst_caps_new_simple ("audio/x-raw",
14837           "format", G_TYPE_STRING, "S24BE",
14838           "layout", G_TYPE_STRING, "interleaved", NULL);
14839       stream->alignment = 4;
14840       break;
14841     case GST_MAKE_FOURCC ('i', 'n', '3', '2'):
14842       _codec ("Raw 32-bit PCM audio");
14843       caps = gst_caps_new_simple ("audio/x-raw",
14844           "format", G_TYPE_STRING, "S32BE",
14845           "layout", G_TYPE_STRING, "interleaved", NULL);
14846       stream->alignment = 4;
14847       break;
14848     case GST_MAKE_FOURCC ('s', '1', '6', 'l'):
14849       _codec ("Raw 16-bit PCM audio");
14850       caps = gst_caps_new_simple ("audio/x-raw",
14851           "format", G_TYPE_STRING, "S16LE",
14852           "layout", G_TYPE_STRING, "interleaved", NULL);
14853       stream->alignment = 2;
14854       break;
14855     case FOURCC_ulaw:
14856       _codec ("Mu-law audio");
14857       caps = gst_caps_new_empty_simple ("audio/x-mulaw");
14858       break;
14859     case FOURCC_alaw:
14860       _codec ("A-law audio");
14861       caps = gst_caps_new_empty_simple ("audio/x-alaw");
14862       break;
14863     case 0x0200736d:
14864     case 0x6d730002:
14865       _codec ("Microsoft ADPCM");
14866       /* Microsoft ADPCM-ACM code 2 */
14867       caps = gst_caps_new_simple ("audio/x-adpcm",
14868           "layout", G_TYPE_STRING, "microsoft", NULL);
14869       break;
14870     case 0x1100736d:
14871     case 0x6d730011:
14872       _codec ("DVI/IMA ADPCM");
14873       caps = gst_caps_new_simple ("audio/x-adpcm",
14874           "layout", G_TYPE_STRING, "dvi", NULL);
14875       break;
14876     case 0x1700736d:
14877     case 0x6d730017:
14878       _codec ("DVI/Intel IMA ADPCM");
14879       /* FIXME DVI/Intel IMA ADPCM/ACM code 17 */
14880       caps = gst_caps_new_simple ("audio/x-adpcm",
14881           "layout", G_TYPE_STRING, "quicktime", NULL);
14882       break;
14883     case 0x5500736d:
14884     case 0x6d730055:
14885       /* MPEG layer 3, CBR only (pre QT4.1) */
14886     case FOURCC__mp3:
14887       _codec ("MPEG-1 layer 3");
14888       /* MPEG layer 3, CBR & VBR (QT4.1 and later) */
14889       caps = gst_caps_new_simple ("audio/mpeg", "layer", G_TYPE_INT, 3,
14890           "mpegversion", G_TYPE_INT, 1, NULL);
14891       break;
14892     case GST_MAKE_FOURCC ('.', 'm', 'p', '2'):
14893       _codec ("MPEG-1 layer 2");
14894       /* MPEG layer 2 */
14895       caps = gst_caps_new_simple ("audio/mpeg", "layer", G_TYPE_INT, 2,
14896           "mpegversion", G_TYPE_INT, 1, NULL);
14897       break;
14898     case 0x20736d:
14899     case GST_MAKE_FOURCC ('e', 'c', '-', '3'):
14900       _codec ("EAC-3 audio");
14901       caps = gst_caps_new_simple ("audio/x-eac3",
14902           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
14903       entry->sampled = TRUE;
14904       break;
14905     case GST_MAKE_FOURCC ('s', 'a', 'c', '3'): // Nero Recode
14906     case FOURCC_ac_3:
14907       _codec ("AC-3 audio");
14908       caps = gst_caps_new_simple ("audio/x-ac3",
14909           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
14910       entry->sampled = TRUE;
14911       break;
14912     case GST_MAKE_FOURCC ('d', 't', 's', 'c'):
14913     case GST_MAKE_FOURCC ('D', 'T', 'S', ' '):
14914       _codec ("DTS audio");
14915       caps = gst_caps_new_simple ("audio/x-dts",
14916           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
14917       entry->sampled = TRUE;
14918       break;
14919     case GST_MAKE_FOURCC ('d', 't', 's', 'h'): // DTS-HD
14920     case GST_MAKE_FOURCC ('d', 't', 's', 'l'): // DTS-HD Lossless
14921       _codec ("DTS-HD audio");
14922       caps = gst_caps_new_simple ("audio/x-dts",
14923           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
14924       entry->sampled = TRUE;
14925       break;
14926     case FOURCC_MAC3:
14927       _codec ("MACE-3");
14928       caps = gst_caps_new_simple ("audio/x-mace",
14929           "maceversion", G_TYPE_INT, 3, NULL);
14930       break;
14931     case FOURCC_MAC6:
14932       _codec ("MACE-6");
14933       caps = gst_caps_new_simple ("audio/x-mace",
14934           "maceversion", G_TYPE_INT, 6, NULL);
14935       break;
14936     case GST_MAKE_FOURCC ('O', 'g', 'g', 'V'):
14937       /* ogg/vorbis */
14938       caps = gst_caps_new_empty_simple ("application/ogg");
14939       break;
14940     case GST_MAKE_FOURCC ('d', 'v', 'c', 'a'):
14941       _codec ("DV audio");
14942       caps = gst_caps_new_empty_simple ("audio/x-dv");
14943       break;
14944     case FOURCC_mp4a:
14945       _codec ("MPEG-4 AAC audio");
14946       caps = gst_caps_new_simple ("audio/mpeg",
14947           "mpegversion", G_TYPE_INT, 4, "framed", G_TYPE_BOOLEAN, TRUE,
14948           "stream-format", G_TYPE_STRING, "raw", NULL);
14949       break;
14950     case GST_MAKE_FOURCC ('Q', 'D', 'M', 'C'):
14951       _codec ("QDesign Music");
14952       caps = gst_caps_new_empty_simple ("audio/x-qdm");
14953       break;
14954     case FOURCC_QDM2:
14955       _codec ("QDesign Music v.2");
14956       /* FIXME: QDesign music version 2 (no constant) */
14957       if (FALSE && data) {
14958         caps = gst_caps_new_simple ("audio/x-qdm2",
14959             "framesize", G_TYPE_INT, QT_UINT32 (data + 52),
14960             "bitrate", G_TYPE_INT, QT_UINT32 (data + 40),
14961             "blocksize", G_TYPE_INT, QT_UINT32 (data + 44), NULL);
14962       } else {
14963         caps = gst_caps_new_empty_simple ("audio/x-qdm2");
14964       }
14965       break;
14966     case FOURCC_agsm:
14967       _codec ("GSM audio");
14968       caps = gst_caps_new_empty_simple ("audio/x-gsm");
14969       break;
14970     case FOURCC_samr:
14971       _codec ("AMR audio");
14972       caps = gst_caps_new_empty_simple ("audio/AMR");
14973       break;
14974     case FOURCC_sawb:
14975       _codec ("AMR-WB audio");
14976       caps = gst_caps_new_empty_simple ("audio/AMR-WB");
14977       break;
14978     case FOURCC_ima4:
14979       _codec ("Quicktime IMA ADPCM");
14980       caps = gst_caps_new_simple ("audio/x-adpcm",
14981           "layout", G_TYPE_STRING, "quicktime", NULL);
14982       break;
14983     case FOURCC_alac:
14984       _codec ("Apple lossless audio");
14985       caps = gst_caps_new_empty_simple ("audio/x-alac");
14986       break;
14987     case FOURCC_fLaC:
14988       _codec ("Free Lossless Audio Codec");
14989       caps = gst_caps_new_simple ("audio/x-flac",
14990           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
14991       break;
14992     case GST_MAKE_FOURCC ('Q', 'c', 'l', 'p'):
14993       _codec ("QualComm PureVoice");
14994       caps = gst_caps_from_string ("audio/qcelp");
14995       break;
14996     case FOURCC_wma_:
14997     case FOURCC_owma:
14998       _codec ("WMA");
14999       caps = gst_caps_new_empty_simple ("audio/x-wma");
15000       break;
15001     case FOURCC_opus:
15002       _codec ("Opus");
15003       caps = gst_caps_new_empty_simple ("audio/x-opus");
15004       break;
15005     case FOURCC_lpcm:
15006     {
15007       guint32 flags = 0;
15008       guint32 depth = 0;
15009       guint32 width = 0;
15010       GstAudioFormat format;
15011       enum
15012       {
15013         FLAG_IS_FLOAT = 0x1,
15014         FLAG_IS_BIG_ENDIAN = 0x2,
15015         FLAG_IS_SIGNED = 0x4,
15016         FLAG_IS_PACKED = 0x8,
15017         FLAG_IS_ALIGNED_HIGH = 0x10,
15018         FLAG_IS_NON_INTERLEAVED = 0x20
15019       };
15020       _codec ("Raw LPCM audio");
15021
15022       if (data && len >= 36) {
15023         depth = QT_UINT32 (data + 24);
15024         flags = QT_UINT32 (data + 28);
15025         width = QT_UINT32 (data + 32) * 8 / entry->n_channels;
15026       }
15027       if ((flags & FLAG_IS_FLOAT) == 0) {
15028         if (depth == 0)
15029           depth = 16;
15030         if (width == 0)
15031           width = 16;
15032         if ((flags & FLAG_IS_ALIGNED_HIGH))
15033           depth = width;
15034
15035         format = gst_audio_format_build_integer ((flags & FLAG_IS_SIGNED) ?
15036             TRUE : FALSE, (flags & FLAG_IS_BIG_ENDIAN) ?
15037             G_BIG_ENDIAN : G_LITTLE_ENDIAN, width, depth);
15038         caps = gst_caps_new_simple ("audio/x-raw",
15039             "format", G_TYPE_STRING,
15040             format !=
15041             GST_AUDIO_FORMAT_UNKNOWN ? gst_audio_format_to_string (format) :
15042             "UNKNOWN", "layout", G_TYPE_STRING,
15043             (flags & FLAG_IS_NON_INTERLEAVED) ? "non-interleaved" :
15044             "interleaved", NULL);
15045         stream->alignment = GST_ROUND_UP_8 (depth);
15046         stream->alignment = round_up_pow2 (stream->alignment);
15047       } else {
15048         if (width == 0)
15049           width = 32;
15050         if (width == 64) {
15051           if (flags & FLAG_IS_BIG_ENDIAN)
15052             format = GST_AUDIO_FORMAT_F64BE;
15053           else
15054             format = GST_AUDIO_FORMAT_F64LE;
15055         } else {
15056           if (flags & FLAG_IS_BIG_ENDIAN)
15057             format = GST_AUDIO_FORMAT_F32BE;
15058           else
15059             format = GST_AUDIO_FORMAT_F32LE;
15060         }
15061         caps = gst_caps_new_simple ("audio/x-raw",
15062             "format", G_TYPE_STRING, gst_audio_format_to_string (format),
15063             "layout", G_TYPE_STRING, (flags & FLAG_IS_NON_INTERLEAVED) ?
15064             "non-interleaved" : "interleaved", NULL);
15065         stream->alignment = width / 8;
15066       }
15067       break;
15068     }
15069     case GST_MAKE_FOURCC ('q', 't', 'v', 'r'):
15070       /* ? */
15071     default:
15072     {
15073       caps = _get_unknown_codec_name ("audio", fourcc);
15074       break;
15075     }
15076   }
15077
15078   if (caps) {
15079     GstCaps *templ_caps =
15080         gst_static_pad_template_get_caps (&gst_qtdemux_audiosrc_template);
15081     GstCaps *intersection = gst_caps_intersect (caps, templ_caps);
15082     gst_caps_unref (caps);
15083     gst_caps_unref (templ_caps);
15084     caps = intersection;
15085   }
15086
15087   /* enable clipping for raw audio streams */
15088   s = gst_caps_get_structure (caps, 0);
15089   name = gst_structure_get_name (s);
15090   if (g_str_has_prefix (name, "audio/x-raw")) {
15091     stream->need_clip = TRUE;
15092     stream->max_buffer_size = 4096 * entry->bytes_per_frame;
15093     GST_DEBUG ("setting max buffer size to %d", stream->max_buffer_size);
15094   }
15095   return caps;
15096 }
15097
15098 static GstCaps *
15099 qtdemux_sub_caps (GstQTDemux * qtdemux, QtDemuxStream * stream,
15100     QtDemuxStreamStsdEntry * entry, guint32 fourcc,
15101     const guint8 * stsd_entry_data, gchar ** codec_name)
15102 {
15103   GstCaps *caps;
15104
15105   GST_DEBUG_OBJECT (qtdemux, "resolve fourcc 0x%08x", GUINT32_TO_BE (fourcc));
15106
15107   switch (fourcc) {
15108     case FOURCC_mp4s:
15109       _codec ("DVD subtitle");
15110       caps = gst_caps_new_empty_simple ("subpicture/x-dvd");
15111       stream->need_process = TRUE;
15112       break;
15113     case FOURCC_text:
15114       _codec ("Quicktime timed text");
15115       goto text;
15116     case FOURCC_tx3g:
15117       _codec ("3GPP timed text");
15118     text:
15119       caps = gst_caps_new_simple ("text/x-raw", "format", G_TYPE_STRING,
15120           "utf8", NULL);
15121       /* actual text piece needs to be extracted */
15122       stream->need_process = TRUE;
15123       break;
15124     case FOURCC_stpp:
15125       _codec ("XML subtitles");
15126       caps = gst_caps_new_empty_simple ("application/ttml+xml");
15127       break;
15128     case FOURCC_c608:
15129       _codec ("CEA 608 Closed Caption");
15130       caps =
15131           gst_caps_new_simple ("closedcaption/x-cea-608", "format",
15132           G_TYPE_STRING, "cc_data", NULL);
15133       stream->need_process = TRUE;
15134       break;
15135     case FOURCC_c708:
15136       _codec ("CEA 708 Closed Caption");
15137       caps =
15138           gst_caps_new_simple ("closedcaption/x-cea-708", "format",
15139           G_TYPE_STRING, "cdp", NULL);
15140       stream->need_process = TRUE;
15141       break;
15142
15143     default:
15144     {
15145       caps = _get_unknown_codec_name ("text", fourcc);
15146       break;
15147     }
15148   }
15149   return caps;
15150 }
15151
15152 static GstCaps *
15153 qtdemux_generic_caps (GstQTDemux * qtdemux, QtDemuxStream * stream,
15154     QtDemuxStreamStsdEntry * entry, guint32 fourcc,
15155     const guint8 * stsd_entry_data, gchar ** codec_name)
15156 {
15157   GstCaps *caps;
15158
15159   switch (fourcc) {
15160     case FOURCC_m1v:
15161       _codec ("MPEG 1 video");
15162       caps = gst_caps_new_simple ("video/mpeg", "mpegversion", G_TYPE_INT, 1,
15163           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
15164       break;
15165     default:
15166       caps = NULL;
15167       break;
15168   }
15169   return caps;
15170 }
15171
15172 static void
15173 gst_qtdemux_append_protection_system_id (GstQTDemux * qtdemux,
15174     const gchar * system_id)
15175 {
15176   gint i;
15177
15178   if (!qtdemux->protection_system_ids)
15179     qtdemux->protection_system_ids =
15180         g_ptr_array_new_with_free_func ((GDestroyNotify) g_free);
15181   /* Check whether we already have an entry for this system ID. */
15182   for (i = 0; i < qtdemux->protection_system_ids->len; ++i) {
15183     const gchar *id = g_ptr_array_index (qtdemux->protection_system_ids, i);
15184     if (g_ascii_strcasecmp (system_id, id) == 0) {
15185       return;
15186     }
15187   }
15188   GST_DEBUG_OBJECT (qtdemux, "Adding cenc protection system ID %s", system_id);
15189   g_ptr_array_add (qtdemux->protection_system_ids, g_ascii_strdown (system_id,
15190           -1));
15191 }