qtdemux: rework segment event pushing
[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 GstStaticPadTemplate gst_qtdemux_sink_template =
488     GST_STATIC_PAD_TEMPLATE ("sink",
489     GST_PAD_SINK,
490     GST_PAD_ALWAYS,
491     GST_STATIC_CAPS ("video/quicktime; video/mj2; audio/x-m4a; "
492         "application/x-3gp")
493     );
494
495 static GstStaticPadTemplate gst_qtdemux_videosrc_template =
496 GST_STATIC_PAD_TEMPLATE ("video_%u",
497     GST_PAD_SRC,
498     GST_PAD_SOMETIMES,
499     GST_STATIC_CAPS_ANY);
500
501 static GstStaticPadTemplate gst_qtdemux_audiosrc_template =
502 GST_STATIC_PAD_TEMPLATE ("audio_%u",
503     GST_PAD_SRC,
504     GST_PAD_SOMETIMES,
505     GST_STATIC_CAPS_ANY);
506
507 static GstStaticPadTemplate gst_qtdemux_subsrc_template =
508 GST_STATIC_PAD_TEMPLATE ("subtitle_%u",
509     GST_PAD_SRC,
510     GST_PAD_SOMETIMES,
511     GST_STATIC_CAPS_ANY);
512
513 #define gst_qtdemux_parent_class parent_class
514 G_DEFINE_TYPE (GstQTDemux, gst_qtdemux, GST_TYPE_ELEMENT);
515
516 static void gst_qtdemux_dispose (GObject * object);
517
518 static guint32
519 gst_qtdemux_find_index_linear (GstQTDemux * qtdemux, QtDemuxStream * str,
520     GstClockTime media_time);
521 static guint32
522 gst_qtdemux_find_index_for_given_media_offset_linear (GstQTDemux * qtdemux,
523     QtDemuxStream * str, gint64 media_offset);
524
525 #if 0
526 static void gst_qtdemux_set_index (GstElement * element, GstIndex * index);
527 static GstIndex *gst_qtdemux_get_index (GstElement * element);
528 #endif
529 static GstStateChangeReturn gst_qtdemux_change_state (GstElement * element,
530     GstStateChange transition);
531 static void gst_qtdemux_set_context (GstElement * element,
532     GstContext * context);
533 static gboolean qtdemux_sink_activate (GstPad * sinkpad, GstObject * parent);
534 static gboolean qtdemux_sink_activate_mode (GstPad * sinkpad,
535     GstObject * parent, GstPadMode mode, gboolean active);
536
537 static void gst_qtdemux_loop (GstPad * pad);
538 static GstFlowReturn gst_qtdemux_chain (GstPad * sinkpad, GstObject * parent,
539     GstBuffer * inbuf);
540 static gboolean gst_qtdemux_handle_sink_event (GstPad * pad, GstObject * parent,
541     GstEvent * event);
542 static gboolean gst_qtdemux_setcaps (GstQTDemux * qtdemux, GstCaps * caps);
543 static gboolean gst_qtdemux_configure_stream (GstQTDemux * qtdemux,
544     QtDemuxStream * stream);
545 static void gst_qtdemux_stream_check_and_change_stsd_index (GstQTDemux * demux,
546     QtDemuxStream * stream);
547 static GstFlowReturn gst_qtdemux_process_adapter (GstQTDemux * demux,
548     gboolean force);
549 static GstClockTime gst_qtdemux_streams_get_first_sample_ts (GstQTDemux *
550     demux);
551 static GstClockTime gst_qtdemux_streams_have_samples (GstQTDemux * demux);
552
553 static gboolean qtdemux_parse_moov (GstQTDemux * qtdemux,
554     const guint8 * buffer, guint length);
555 static gboolean qtdemux_parse_node (GstQTDemux * qtdemux, GNode * node,
556     const guint8 * buffer, guint length);
557 static gboolean qtdemux_parse_tree (GstQTDemux * qtdemux);
558 static void qtdemux_parse_udta (GstQTDemux * qtdemux, GstTagList * taglist,
559     GNode * udta);
560
561 static void gst_qtdemux_handle_esds (GstQTDemux * qtdemux,
562     QtDemuxStream * stream, QtDemuxStreamStsdEntry * entry, GNode * esds,
563     GstTagList * list);
564 static GstCaps *qtdemux_video_caps (GstQTDemux * qtdemux,
565     QtDemuxStream * stream, QtDemuxStreamStsdEntry * entry, guint32 fourcc,
566     const guint8 * stsd_entry_data, gchar ** codec_name);
567 static GstCaps *qtdemux_audio_caps (GstQTDemux * qtdemux,
568     QtDemuxStream * stream, QtDemuxStreamStsdEntry * entry, guint32 fourcc,
569     const guint8 * data, int len, gchar ** codec_name);
570 static GstCaps *qtdemux_sub_caps (GstQTDemux * qtdemux, QtDemuxStream * stream,
571     QtDemuxStreamStsdEntry * entry, guint32 fourcc, const guint8 * data,
572     gchar ** codec_name);
573 static GstCaps *qtdemux_generic_caps (GstQTDemux * qtdemux,
574     QtDemuxStream * stream, QtDemuxStreamStsdEntry * entry, guint32 fourcc,
575     const guint8 * stsd_entry_data, gchar ** codec_name);
576
577 static gboolean qtdemux_parse_samples (GstQTDemux * qtdemux,
578     QtDemuxStream * stream, guint32 n);
579 static GstFlowReturn qtdemux_expose_streams (GstQTDemux * qtdemux);
580 static void gst_qtdemux_stream_free (QtDemuxStream * stream);
581 static void gst_qtdemux_stream_clear (QtDemuxStream * stream);
582 static void gst_qtdemux_remove_stream (GstQTDemux * qtdemux,
583     QtDemuxStream * stream);
584 static GstFlowReturn qtdemux_prepare_streams (GstQTDemux * qtdemux);
585 static void qtdemux_do_allocation (GstQTDemux * qtdemux,
586     QtDemuxStream * stream);
587 static gboolean gst_qtdemux_activate_segment (GstQTDemux * qtdemux,
588     QtDemuxStream * stream, guint32 seg_idx, GstClockTime offset);
589 static gboolean gst_qtdemux_stream_update_segment (GstQTDemux * qtdemux,
590     QtDemuxStream * stream, gint seg_idx, GstClockTime offset,
591     GstClockTime * _start, GstClockTime * _stop);
592 static void gst_qtdemux_send_gap_for_segment (GstQTDemux * demux,
593     QtDemuxStream * stream, gint segment_index, GstClockTime pos);
594
595 static gboolean qtdemux_pull_mfro_mfra (GstQTDemux * qtdemux);
596 static void check_update_duration (GstQTDemux * qtdemux, GstClockTime duration);
597
598 static gchar *qtdemux_uuid_bytes_to_string (gconstpointer uuid_bytes);
599
600 static GstStructure *qtdemux_get_cenc_sample_properties (GstQTDemux * qtdemux,
601     QtDemuxStream * stream, guint sample_index);
602 static void gst_qtdemux_append_protection_system_id (GstQTDemux * qtdemux,
603     const gchar * id);
604 static void qtdemux_gst_structure_free (GstStructure * gststructure);
605 static void gst_qtdemux_reset (GstQTDemux * qtdemux, gboolean hard);
606
607 static void
608 gst_qtdemux_class_init (GstQTDemuxClass * klass)
609 {
610   GObjectClass *gobject_class;
611   GstElementClass *gstelement_class;
612
613   gobject_class = (GObjectClass *) klass;
614   gstelement_class = (GstElementClass *) klass;
615
616   parent_class = g_type_class_peek_parent (klass);
617
618   gobject_class->dispose = gst_qtdemux_dispose;
619
620   gstelement_class->change_state = GST_DEBUG_FUNCPTR (gst_qtdemux_change_state);
621 #if 0
622   gstelement_class->set_index = GST_DEBUG_FUNCPTR (gst_qtdemux_set_index);
623   gstelement_class->get_index = GST_DEBUG_FUNCPTR (gst_qtdemux_get_index);
624 #endif
625   gstelement_class->set_context = GST_DEBUG_FUNCPTR (gst_qtdemux_set_context);
626
627   gst_tag_register_musicbrainz_tags ();
628
629   gst_element_class_add_static_pad_template (gstelement_class,
630       &gst_qtdemux_sink_template);
631   gst_element_class_add_static_pad_template (gstelement_class,
632       &gst_qtdemux_videosrc_template);
633   gst_element_class_add_static_pad_template (gstelement_class,
634       &gst_qtdemux_audiosrc_template);
635   gst_element_class_add_static_pad_template (gstelement_class,
636       &gst_qtdemux_subsrc_template);
637   gst_element_class_set_static_metadata (gstelement_class, "QuickTime demuxer",
638       "Codec/Demuxer",
639       "Demultiplex a QuickTime file into audio and video streams",
640       "David Schleef <ds@schleef.org>, Wim Taymans <wim@fluendo.com>");
641
642   GST_DEBUG_CATEGORY_INIT (qtdemux_debug, "qtdemux", 0, "qtdemux plugin");
643   gst_riff_init ();
644 }
645
646 static void
647 gst_qtdemux_init (GstQTDemux * qtdemux)
648 {
649   qtdemux->sinkpad =
650       gst_pad_new_from_static_template (&gst_qtdemux_sink_template, "sink");
651   gst_pad_set_activate_function (qtdemux->sinkpad, qtdemux_sink_activate);
652   gst_pad_set_activatemode_function (qtdemux->sinkpad,
653       qtdemux_sink_activate_mode);
654   gst_pad_set_chain_function (qtdemux->sinkpad, gst_qtdemux_chain);
655   gst_pad_set_event_function (qtdemux->sinkpad, gst_qtdemux_handle_sink_event);
656   gst_element_add_pad (GST_ELEMENT_CAST (qtdemux), qtdemux->sinkpad);
657
658   qtdemux->adapter = gst_adapter_new ();
659   g_queue_init (&qtdemux->protection_event_queue);
660   qtdemux->flowcombiner = gst_flow_combiner_new ();
661   g_mutex_init (&qtdemux->expose_lock);
662
663   GST_OBJECT_FLAG_SET (qtdemux, GST_ELEMENT_FLAG_INDEXABLE);
664
665   gst_qtdemux_reset (qtdemux, TRUE);
666 }
667
668 static void
669 gst_qtdemux_dispose (GObject * object)
670 {
671   GstQTDemux *qtdemux = GST_QTDEMUX (object);
672
673   if (qtdemux->adapter) {
674     g_object_unref (G_OBJECT (qtdemux->adapter));
675     qtdemux->adapter = NULL;
676   }
677   gst_tag_list_unref (qtdemux->tag_list);
678   gst_flow_combiner_free (qtdemux->flowcombiner);
679   g_queue_foreach (&qtdemux->protection_event_queue, (GFunc) gst_event_unref,
680       NULL);
681   g_queue_clear (&qtdemux->protection_event_queue);
682
683   g_free (qtdemux->cenc_aux_info_sizes);
684   qtdemux->cenc_aux_info_sizes = NULL;
685   g_mutex_clear (&qtdemux->expose_lock);
686
687   G_OBJECT_CLASS (parent_class)->dispose (object);
688 }
689
690 static void
691 gst_qtdemux_post_no_playable_stream_error (GstQTDemux * qtdemux)
692 {
693   if (qtdemux->posted_redirect) {
694     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
695         (_("This file contains no playable streams.")),
696         ("no known streams found, a redirect message has been posted"));
697   } else {
698     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
699         (_("This file contains no playable streams.")),
700         ("no known streams found"));
701   }
702 }
703
704 static GstBuffer *
705 _gst_buffer_new_wrapped (gpointer mem, gsize size, GFreeFunc free_func)
706 {
707   return gst_buffer_new_wrapped_full (free_func ? 0 : GST_MEMORY_FLAG_READONLY,
708       mem, size, 0, size, mem, free_func);
709 }
710
711 static GstFlowReturn
712 gst_qtdemux_pull_atom (GstQTDemux * qtdemux, guint64 offset, guint64 size,
713     GstBuffer ** buf)
714 {
715   GstFlowReturn flow;
716   GstMapInfo map;
717   gsize bsize;
718
719   if (G_UNLIKELY (size == 0)) {
720     GstFlowReturn ret;
721     GstBuffer *tmp = NULL;
722
723     ret = gst_qtdemux_pull_atom (qtdemux, offset, sizeof (guint32), &tmp);
724     if (ret != GST_FLOW_OK)
725       return ret;
726
727     gst_buffer_map (tmp, &map, GST_MAP_READ);
728     size = QT_UINT32 (map.data);
729     GST_DEBUG_OBJECT (qtdemux, "size 0x%08" G_GINT64_MODIFIER "x", size);
730
731     gst_buffer_unmap (tmp, &map);
732     gst_buffer_unref (tmp);
733   }
734
735   /* Sanity check: catch bogus sizes (fuzzed/broken files) */
736   if (G_UNLIKELY (size > QTDEMUX_MAX_ATOM_SIZE)) {
737     if (qtdemux->state != QTDEMUX_STATE_MOVIE && qtdemux->got_moov) {
738       /* we're pulling header but already got most interesting bits,
739        * so never mind the rest (e.g. tags) (that much) */
740       GST_WARNING_OBJECT (qtdemux, "atom has bogus size %" G_GUINT64_FORMAT,
741           size);
742       return GST_FLOW_EOS;
743     } else {
744       GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
745           (_("This file is invalid and cannot be played.")),
746           ("atom has bogus size %" G_GUINT64_FORMAT, size));
747       return GST_FLOW_ERROR;
748     }
749   }
750
751   flow = gst_pad_pull_range (qtdemux->sinkpad, offset, size, buf);
752
753   if (G_UNLIKELY (flow != GST_FLOW_OK))
754     return flow;
755
756   bsize = gst_buffer_get_size (*buf);
757   /* Catch short reads - we don't want any partial atoms */
758   if (G_UNLIKELY (bsize < size)) {
759     GST_WARNING_OBJECT (qtdemux,
760         "short read: %" G_GSIZE_FORMAT " < %" G_GUINT64_FORMAT, bsize, size);
761     gst_buffer_unref (*buf);
762     *buf = NULL;
763     return GST_FLOW_EOS;
764   }
765
766   return flow;
767 }
768
769 #if 1
770 static gboolean
771 gst_qtdemux_src_convert (GstQTDemux * qtdemux, GstPad * pad,
772     GstFormat src_format, gint64 src_value, GstFormat dest_format,
773     gint64 * dest_value)
774 {
775   gboolean res = TRUE;
776   QtDemuxStream *stream = gst_pad_get_element_private (pad);
777   gint32 index;
778
779   if (stream->subtype != FOURCC_vide) {
780     res = FALSE;
781     goto done;
782   }
783
784   switch (src_format) {
785     case GST_FORMAT_TIME:
786       switch (dest_format) {
787         case GST_FORMAT_BYTES:{
788           index = gst_qtdemux_find_index_linear (qtdemux, stream, src_value);
789           if (-1 == index) {
790             res = FALSE;
791             goto done;
792           }
793
794           *dest_value = stream->samples[index].offset;
795
796           GST_DEBUG_OBJECT (qtdemux, "Format Conversion Time->Offset :%"
797               GST_TIME_FORMAT "->%" G_GUINT64_FORMAT,
798               GST_TIME_ARGS (src_value), *dest_value);
799           break;
800         }
801         default:
802           res = FALSE;
803           break;
804       }
805       break;
806     case GST_FORMAT_BYTES:
807       switch (dest_format) {
808         case GST_FORMAT_TIME:{
809           index =
810               gst_qtdemux_find_index_for_given_media_offset_linear (qtdemux,
811               stream, src_value);
812
813           if (-1 == index) {
814             res = FALSE;
815             goto done;
816           }
817
818           *dest_value =
819               QTSTREAMTIME_TO_GSTTIME (stream,
820               stream->samples[index].timestamp);
821           GST_DEBUG_OBJECT (qtdemux,
822               "Format Conversion Offset->Time :%" G_GUINT64_FORMAT "->%"
823               GST_TIME_FORMAT, src_value, GST_TIME_ARGS (*dest_value));
824           break;
825         }
826         default:
827           res = FALSE;
828           break;
829       }
830       break;
831     default:
832       res = FALSE;
833       break;
834   }
835
836 done:
837   return res;
838 }
839 #endif
840
841 static gboolean
842 gst_qtdemux_get_duration (GstQTDemux * qtdemux, GstClockTime * duration)
843 {
844   gboolean res = FALSE;
845
846   *duration = GST_CLOCK_TIME_NONE;
847
848   if (qtdemux->duration != 0 &&
849       qtdemux->duration != G_MAXINT64 && qtdemux->timescale != 0) {
850     *duration = QTTIME_TO_GSTTIME (qtdemux, qtdemux->duration);
851     res = TRUE;
852   } else {
853     *duration = GST_CLOCK_TIME_NONE;
854   }
855
856   return res;
857 }
858
859 static gboolean
860 gst_qtdemux_handle_src_query (GstPad * pad, GstObject * parent,
861     GstQuery * query)
862 {
863   gboolean res = FALSE;
864   GstQTDemux *qtdemux = GST_QTDEMUX (parent);
865
866   GST_LOG_OBJECT (pad, "%s query", GST_QUERY_TYPE_NAME (query));
867
868   switch (GST_QUERY_TYPE (query)) {
869     case GST_QUERY_POSITION:{
870       GstFormat fmt;
871
872       gst_query_parse_position (query, &fmt, NULL);
873       if (fmt == GST_FORMAT_TIME
874           && GST_CLOCK_TIME_IS_VALID (qtdemux->segment.position)) {
875         gst_query_set_position (query, GST_FORMAT_TIME,
876             qtdemux->segment.position);
877         res = TRUE;
878       }
879     }
880       break;
881     case GST_QUERY_DURATION:{
882       GstFormat fmt;
883
884       gst_query_parse_duration (query, &fmt, NULL);
885       if (fmt == GST_FORMAT_TIME) {
886         /* First try to query upstream */
887         res = gst_pad_query_default (pad, parent, query);
888         if (!res) {
889           GstClockTime duration;
890           if (gst_qtdemux_get_duration (qtdemux, &duration) && duration > 0) {
891             gst_query_set_duration (query, GST_FORMAT_TIME, duration);
892             res = TRUE;
893           }
894         }
895       }
896       break;
897     }
898     case GST_QUERY_CONVERT:{
899       GstFormat src_fmt, dest_fmt;
900       gint64 src_value, dest_value = 0;
901
902       gst_query_parse_convert (query, &src_fmt, &src_value, &dest_fmt, NULL);
903
904       res = gst_qtdemux_src_convert (qtdemux, pad,
905           src_fmt, src_value, dest_fmt, &dest_value);
906       if (res)
907         gst_query_set_convert (query, src_fmt, src_value, dest_fmt, dest_value);
908
909       break;
910     }
911     case GST_QUERY_FORMATS:
912       gst_query_set_formats (query, 2, GST_FORMAT_TIME, GST_FORMAT_BYTES);
913       res = TRUE;
914       break;
915     case GST_QUERY_SEEKING:{
916       GstFormat fmt;
917       gboolean seekable;
918
919       /* try upstream first */
920       res = gst_pad_query_default (pad, parent, query);
921
922       if (!res) {
923         gst_query_parse_seeking (query, &fmt, NULL, NULL, NULL);
924         if (fmt == GST_FORMAT_TIME) {
925           GstClockTime duration;
926
927           gst_qtdemux_get_duration (qtdemux, &duration);
928           seekable = TRUE;
929           if (!qtdemux->pullbased) {
930             GstQuery *q;
931
932             /* we might be able with help from upstream */
933             seekable = FALSE;
934             q = gst_query_new_seeking (GST_FORMAT_BYTES);
935             if (gst_pad_peer_query (qtdemux->sinkpad, q)) {
936               gst_query_parse_seeking (q, &fmt, &seekable, NULL, NULL);
937               GST_LOG_OBJECT (qtdemux, "upstream BYTE seekable %d", seekable);
938             }
939             gst_query_unref (q);
940           }
941           gst_query_set_seeking (query, GST_FORMAT_TIME, seekable, 0, duration);
942           res = TRUE;
943         }
944       }
945       break;
946     }
947     case GST_QUERY_SEGMENT:
948     {
949       GstFormat format;
950       gint64 start, stop;
951
952       format = qtdemux->segment.format;
953
954       start =
955           gst_segment_to_stream_time (&qtdemux->segment, format,
956           qtdemux->segment.start);
957       if ((stop = qtdemux->segment.stop) == -1)
958         stop = qtdemux->segment.duration;
959       else
960         stop = gst_segment_to_stream_time (&qtdemux->segment, format, stop);
961
962       gst_query_set_segment (query, qtdemux->segment.rate, format, start, stop);
963       res = TRUE;
964       break;
965     }
966     default:
967       res = gst_pad_query_default (pad, parent, query);
968       break;
969   }
970
971   return res;
972 }
973
974 static void
975 gst_qtdemux_push_tags (GstQTDemux * qtdemux, QtDemuxStream * stream)
976 {
977   if (G_LIKELY (stream->pad)) {
978     GST_DEBUG_OBJECT (qtdemux, "Checking pad %s:%s for tags",
979         GST_DEBUG_PAD_NAME (stream->pad));
980
981     if (!gst_tag_list_is_empty (stream->stream_tags)) {
982       GST_DEBUG_OBJECT (qtdemux, "Sending tags %" GST_PTR_FORMAT,
983           stream->stream_tags);
984       gst_pad_push_event (stream->pad,
985           gst_event_new_tag (gst_tag_list_ref (stream->stream_tags)));
986     }
987
988     if (G_UNLIKELY (stream->send_global_tags)) {
989       GST_DEBUG_OBJECT (qtdemux, "Sending global tags %" GST_PTR_FORMAT,
990           qtdemux->tag_list);
991       gst_pad_push_event (stream->pad,
992           gst_event_new_tag (gst_tag_list_ref (qtdemux->tag_list)));
993       stream->send_global_tags = FALSE;
994     }
995   }
996 }
997
998 /* push event on all source pads; takes ownership of the event */
999 static void
1000 gst_qtdemux_push_event (GstQTDemux * qtdemux, GstEvent * event)
1001 {
1002   gboolean has_valid_stream = FALSE;
1003   GstEventType etype = GST_EVENT_TYPE (event);
1004   GList *iter;
1005
1006   GST_DEBUG_OBJECT (qtdemux, "pushing %s event on all source pads",
1007       GST_EVENT_TYPE_NAME (event));
1008
1009   for (iter = qtdemux->active_streams; iter; iter = g_list_next (iter)) {
1010     GstPad *pad;
1011     QtDemuxStream *stream = QTDEMUX_STREAM (iter->data);
1012     GST_DEBUG_OBJECT (qtdemux, "pushing on track-id %u", stream->track_id);
1013
1014     if ((pad = stream->pad)) {
1015       has_valid_stream = TRUE;
1016
1017       if (etype == GST_EVENT_EOS) {
1018         /* let's not send twice */
1019         if (stream->sent_eos)
1020           continue;
1021         stream->sent_eos = TRUE;
1022       }
1023
1024       gst_pad_push_event (pad, gst_event_ref (event));
1025     }
1026   }
1027
1028   gst_event_unref (event);
1029
1030   /* if it is EOS and there are no pads, post an error */
1031   if (!has_valid_stream && etype == GST_EVENT_EOS) {
1032     gst_qtdemux_post_no_playable_stream_error (qtdemux);
1033   }
1034 }
1035
1036 /* push a pending newsegment event, if any from the streaming thread */
1037 static void
1038 gst_qtdemux_push_pending_newsegment (GstQTDemux * qtdemux)
1039 {
1040   if (G_UNLIKELY (qtdemux->need_segment)) {
1041     GstClockTime min_ts;
1042     GstEvent *newsegment;
1043
1044     if (!gst_qtdemux_streams_have_samples (qtdemux)) {
1045       /* No samples yet, can't decide on segment.start */
1046       GST_DEBUG_OBJECT (qtdemux, "No samples yet, postponing segment event");
1047       return;
1048     }
1049
1050     min_ts = gst_qtdemux_streams_get_first_sample_ts (qtdemux);
1051
1052     /* have_samples() above should guarantee we have a valid time */
1053     g_assert (GST_CLOCK_TIME_IS_VALID (min_ts));
1054
1055     qtdemux->segment.start = min_ts;
1056     newsegment = gst_event_new_segment (&qtdemux->segment);
1057     if (qtdemux->segment_seqnum != GST_SEQNUM_INVALID)
1058       gst_event_set_seqnum (newsegment, qtdemux->segment_seqnum);
1059     qtdemux->need_segment = FALSE;
1060     gst_qtdemux_push_event (qtdemux, newsegment);
1061   }
1062 }
1063
1064 typedef struct
1065 {
1066   guint64 media_time;
1067 } FindData;
1068
1069 static gint
1070 find_func (QtDemuxSample * s1, gint64 * media_time, gpointer user_data)
1071 {
1072   if ((gint64) s1->timestamp > *media_time)
1073     return 1;
1074   if ((gint64) s1->timestamp == *media_time)
1075     return 0;
1076
1077   return -1;
1078 }
1079
1080 /* find the index of the sample that includes the data for @media_time using a
1081  * binary search.  Only to be called in optimized cases of linear search below.
1082  *
1083  * Returns the index of the sample with the corresponding *DTS*.
1084  */
1085 static guint32
1086 gst_qtdemux_find_index (GstQTDemux * qtdemux, QtDemuxStream * str,
1087     guint64 media_time)
1088 {
1089   QtDemuxSample *result;
1090   guint32 index;
1091
1092   /* convert media_time to mov format */
1093   media_time =
1094       gst_util_uint64_scale_ceil (media_time, str->timescale, GST_SECOND);
1095
1096   result = gst_util_array_binary_search (str->samples, str->stbl_index + 1,
1097       sizeof (QtDemuxSample), (GCompareDataFunc) find_func,
1098       GST_SEARCH_MODE_BEFORE, &media_time, NULL);
1099
1100   if (G_LIKELY (result))
1101     index = result - str->samples;
1102   else
1103     index = 0;
1104
1105   return index;
1106 }
1107
1108
1109
1110 /* find the index of the sample that includes the data for @media_offset using a
1111  * linear search
1112  *
1113  * Returns the index of the sample.
1114  */
1115 static guint32
1116 gst_qtdemux_find_index_for_given_media_offset_linear (GstQTDemux * qtdemux,
1117     QtDemuxStream * str, gint64 media_offset)
1118 {
1119   QtDemuxSample *result = str->samples;
1120   guint32 index = 0;
1121
1122   if (result == NULL || str->n_samples == 0)
1123     return -1;
1124
1125   if (media_offset == result->offset)
1126     return index;
1127
1128   result++;
1129   while (index < str->n_samples - 1) {
1130     if (!qtdemux_parse_samples (qtdemux, str, index + 1))
1131       goto parse_failed;
1132
1133     if (media_offset < result->offset)
1134       break;
1135
1136     index++;
1137     result++;
1138   }
1139   return index;
1140
1141   /* ERRORS */
1142 parse_failed:
1143   {
1144     GST_LOG_OBJECT (qtdemux, "Parsing of index %u failed!", index + 1);
1145     return -1;
1146   }
1147 }
1148
1149 /* find the index of the sample that includes the data for @media_time using a
1150  * linear search, and keeping in mind that not all samples may have been parsed
1151  * yet.  If possible, it will delegate to binary search.
1152  *
1153  * Returns the index of the sample.
1154  */
1155 static guint32
1156 gst_qtdemux_find_index_linear (GstQTDemux * qtdemux, QtDemuxStream * str,
1157     GstClockTime media_time)
1158 {
1159   guint32 index = 0;
1160   guint64 mov_time;
1161   QtDemuxSample *sample;
1162
1163   /* convert media_time to mov format */
1164   mov_time =
1165       gst_util_uint64_scale_ceil (media_time, str->timescale, GST_SECOND);
1166
1167   sample = str->samples;
1168   if (mov_time == sample->timestamp + sample->pts_offset)
1169     return index;
1170
1171   /* use faster search if requested time in already parsed range */
1172   sample = str->samples + str->stbl_index;
1173   if (str->stbl_index >= 0 && mov_time <= sample->timestamp) {
1174     index = gst_qtdemux_find_index (qtdemux, str, media_time);
1175     sample = str->samples + index;
1176   } else {
1177     while (index < str->n_samples - 1) {
1178       if (!qtdemux_parse_samples (qtdemux, str, index + 1))
1179         goto parse_failed;
1180
1181       sample = str->samples + index + 1;
1182       if (mov_time < sample->timestamp) {
1183         sample = str->samples + index;
1184         break;
1185       }
1186
1187       index++;
1188     }
1189   }
1190
1191   /* sample->timestamp is now <= media_time, need to find the corresponding
1192    * PTS now by looking backwards */
1193   while (index > 0 && sample->timestamp + sample->pts_offset > mov_time) {
1194     index--;
1195     sample = str->samples + index;
1196   }
1197
1198   return index;
1199
1200   /* ERRORS */
1201 parse_failed:
1202   {
1203     GST_LOG_OBJECT (qtdemux, "Parsing of index %u failed!", index + 1);
1204     return -1;
1205   }
1206 }
1207
1208 /* find the index of the keyframe needed to decode the sample at @index
1209  * of stream @str, or of a subsequent keyframe (depending on @next)
1210  *
1211  * Returns the index of the keyframe.
1212  */
1213 static guint32
1214 gst_qtdemux_find_keyframe (GstQTDemux * qtdemux, QtDemuxStream * str,
1215     guint32 index, gboolean next)
1216 {
1217   guint32 new_index = index;
1218
1219   if (index >= str->n_samples) {
1220     new_index = str->n_samples;
1221     goto beach;
1222   }
1223
1224   /* all keyframes, return index */
1225   if (str->all_keyframe) {
1226     new_index = index;
1227     goto beach;
1228   }
1229
1230   /* else search until we have a keyframe */
1231   while (new_index < str->n_samples) {
1232     if (next && !qtdemux_parse_samples (qtdemux, str, new_index))
1233       goto parse_failed;
1234
1235     if (str->samples[new_index].keyframe)
1236       break;
1237
1238     if (new_index == 0)
1239       break;
1240
1241     if (next)
1242       new_index++;
1243     else
1244       new_index--;
1245   }
1246
1247   if (new_index == str->n_samples) {
1248     GST_DEBUG_OBJECT (qtdemux, "no next keyframe");
1249     new_index = -1;
1250   }
1251
1252 beach:
1253   GST_DEBUG_OBJECT (qtdemux, "searching for keyframe index %s index %u "
1254       "gave %u", next ? "after" : "before", index, new_index);
1255
1256   return new_index;
1257
1258   /* ERRORS */
1259 parse_failed:
1260   {
1261     GST_LOG_OBJECT (qtdemux, "Parsing of index %u failed!", new_index);
1262     return -1;
1263   }
1264 }
1265
1266 /* find the segment for @time_position for @stream
1267  *
1268  * Returns the index of the segment containing @time_position.
1269  * Returns the last segment and sets the @eos variable to TRUE
1270  * if the time is beyond the end. @eos may be NULL
1271  */
1272 static guint32
1273 gst_qtdemux_find_segment (GstQTDemux * qtdemux, QtDemuxStream * stream,
1274     GstClockTime time_position)
1275 {
1276   gint i;
1277   guint32 seg_idx;
1278
1279   GST_LOG_OBJECT (stream->pad, "finding segment for %" GST_TIME_FORMAT,
1280       GST_TIME_ARGS (time_position));
1281
1282   seg_idx = -1;
1283   for (i = 0; i < stream->n_segments; i++) {
1284     QtDemuxSegment *segment = &stream->segments[i];
1285
1286     GST_LOG_OBJECT (stream->pad,
1287         "looking at segment %" GST_TIME_FORMAT "-%" GST_TIME_FORMAT,
1288         GST_TIME_ARGS (segment->time), GST_TIME_ARGS (segment->stop_time));
1289
1290     /* For the last segment we include stop_time in the last segment */
1291     if (i < stream->n_segments - 1) {
1292       if (segment->time <= time_position && time_position < segment->stop_time) {
1293         GST_LOG_OBJECT (stream->pad, "segment %d matches", i);
1294         seg_idx = i;
1295         break;
1296       }
1297     } else {
1298       /* Last segment always matches */
1299       seg_idx = i;
1300       break;
1301     }
1302   }
1303   return seg_idx;
1304 }
1305
1306 /* move the stream @str to the sample position @index.
1307  *
1308  * Updates @str->sample_index and marks discontinuity if needed.
1309  */
1310 static void
1311 gst_qtdemux_move_stream (GstQTDemux * qtdemux, QtDemuxStream * str,
1312     guint32 index)
1313 {
1314   /* no change needed */
1315   if (index == str->sample_index)
1316     return;
1317
1318   GST_DEBUG_OBJECT (qtdemux, "moving to sample %u of %u", index,
1319       str->n_samples);
1320
1321   /* position changed, we have a discont */
1322   str->sample_index = index;
1323   str->offset_in_sample = 0;
1324   /* Each time we move in the stream we store the position where we are
1325    * starting from */
1326   str->from_sample = index;
1327   str->discont = TRUE;
1328 }
1329
1330 static void
1331 gst_qtdemux_adjust_seek (GstQTDemux * qtdemux, gint64 desired_time,
1332     gboolean use_sparse, gboolean next, gint64 * key_time, gint64 * key_offset)
1333 {
1334   guint64 min_offset;
1335   gint64 min_byte_offset = -1;
1336   GList *iter;
1337
1338   min_offset = desired_time;
1339
1340   /* for each stream, find the index of the sample in the segment
1341    * and move back to the previous keyframe. */
1342   for (iter = qtdemux->active_streams; iter; iter = g_list_next (iter)) {
1343     QtDemuxStream *str;
1344     guint32 index, kindex;
1345     guint32 seg_idx;
1346     GstClockTime media_start;
1347     GstClockTime media_time;
1348     GstClockTime seg_time;
1349     QtDemuxSegment *seg;
1350     gboolean empty_segment = FALSE;
1351
1352     str = QTDEMUX_STREAM (iter->data);
1353
1354     if (CUR_STREAM (str)->sparse && !use_sparse)
1355       continue;
1356
1357     seg_idx = gst_qtdemux_find_segment (qtdemux, str, desired_time);
1358     GST_DEBUG_OBJECT (qtdemux, "align segment %d", seg_idx);
1359
1360     /* get segment and time in the segment */
1361     seg = &str->segments[seg_idx];
1362     seg_time = (desired_time - seg->time) * seg->rate;
1363
1364     while (QTSEGMENT_IS_EMPTY (seg)) {
1365       seg_time = 0;
1366       empty_segment = TRUE;
1367       GST_DEBUG_OBJECT (str->pad, "Segment %d is empty, moving to next one",
1368           seg_idx);
1369       seg_idx++;
1370       if (seg_idx == str->n_segments)
1371         break;
1372       seg = &str->segments[seg_idx];
1373     }
1374
1375     if (seg_idx == str->n_segments) {
1376       /* FIXME track shouldn't have the last segment as empty, but if it
1377        * happens we better handle it */
1378       continue;
1379     }
1380
1381     /* get the media time in the segment */
1382     media_start = seg->media_start + seg_time;
1383
1384     /* get the index of the sample with media time */
1385     index = gst_qtdemux_find_index_linear (qtdemux, str, media_start);
1386     GST_DEBUG_OBJECT (qtdemux, "sample for %" GST_TIME_FORMAT " at %u"
1387         " at offset %" G_GUINT64_FORMAT " (empty segment: %d)",
1388         GST_TIME_ARGS (media_start), index, str->samples[index].offset,
1389         empty_segment);
1390
1391     /* shift to next frame if we are looking for next keyframe */
1392     if (next && QTSAMPLE_PTS_NO_CSLG (str, &str->samples[index]) < media_start
1393         && index < str->stbl_index)
1394       index++;
1395
1396     if (!empty_segment) {
1397       /* find previous keyframe */
1398       kindex = gst_qtdemux_find_keyframe (qtdemux, str, index, next);
1399
1400       /* we will settle for one before if none found after */
1401       if (next && kindex == -1)
1402         kindex = gst_qtdemux_find_keyframe (qtdemux, str, index, FALSE);
1403
1404       /* if the keyframe is at a different position, we need to update the
1405        * requested seek time */
1406       if (index != kindex) {
1407         index = kindex;
1408
1409         /* get timestamp of keyframe */
1410         media_time = QTSAMPLE_PTS_NO_CSLG (str, &str->samples[kindex]);
1411         GST_DEBUG_OBJECT (qtdemux,
1412             "keyframe at %u with time %" GST_TIME_FORMAT " at offset %"
1413             G_GUINT64_FORMAT, kindex, GST_TIME_ARGS (media_time),
1414             str->samples[kindex].offset);
1415
1416         /* keyframes in the segment get a chance to change the
1417          * desired_offset. keyframes out of the segment are
1418          * ignored. */
1419         if (media_time >= seg->media_start) {
1420           GstClockTime seg_time;
1421
1422           /* this keyframe is inside the segment, convert back to
1423            * segment time */
1424           seg_time = (media_time - seg->media_start) + seg->time;
1425           if ((!next && (seg_time < min_offset)) ||
1426               (next && (seg_time > min_offset)))
1427             min_offset = seg_time;
1428         }
1429       }
1430     }
1431
1432     if (min_byte_offset < 0 || str->samples[index].offset < min_byte_offset)
1433       min_byte_offset = str->samples[index].offset;
1434   }
1435
1436   if (key_time)
1437     *key_time = min_offset;
1438   if (key_offset)
1439     *key_offset = min_byte_offset;
1440 }
1441
1442 static gboolean
1443 gst_qtdemux_convert_seek (GstPad * pad, GstFormat * format,
1444     GstSeekType cur_type, gint64 * cur, GstSeekType stop_type, gint64 * stop)
1445 {
1446   gboolean res;
1447
1448   g_return_val_if_fail (format != NULL, FALSE);
1449   g_return_val_if_fail (cur != NULL, FALSE);
1450   g_return_val_if_fail (stop != NULL, FALSE);
1451
1452   if (*format == GST_FORMAT_TIME)
1453     return TRUE;
1454
1455   res = TRUE;
1456   if (cur_type != GST_SEEK_TYPE_NONE)
1457     res = gst_pad_query_convert (pad, *format, *cur, GST_FORMAT_TIME, cur);
1458   if (res && stop_type != GST_SEEK_TYPE_NONE)
1459     res = gst_pad_query_convert (pad, *format, *stop, GST_FORMAT_TIME, stop);
1460
1461   if (res)
1462     *format = GST_FORMAT_TIME;
1463
1464   return res;
1465 }
1466
1467 /* perform seek in push based mode:
1468    find BYTE position to move to based on time and delegate to upstream
1469 */
1470 static gboolean
1471 gst_qtdemux_do_push_seek (GstQTDemux * qtdemux, GstPad * pad, GstEvent * event)
1472 {
1473   gdouble rate;
1474   GstFormat format;
1475   GstSeekFlags flags;
1476   GstSeekType cur_type, stop_type;
1477   gint64 cur, stop, key_cur;
1478   gboolean res;
1479   gint64 byte_cur;
1480   gint64 original_stop;
1481   guint32 seqnum;
1482
1483   GST_DEBUG_OBJECT (qtdemux, "doing push-based seek");
1484
1485   gst_event_parse_seek (event, &rate, &format, &flags,
1486       &cur_type, &cur, &stop_type, &stop);
1487   seqnum = gst_event_get_seqnum (event);
1488
1489   /* only forward streaming and seeking is possible */
1490   if (rate <= 0)
1491     goto unsupported_seek;
1492
1493   /* convert to TIME if needed and possible */
1494   if (!gst_qtdemux_convert_seek (pad, &format, cur_type, &cur,
1495           stop_type, &stop))
1496     goto no_format;
1497
1498   /* Upstream seek in bytes will have undefined stop, but qtdemux stores
1499    * the original stop position to use when upstream pushes the new segment
1500    * for this seek */
1501   original_stop = stop;
1502   stop = -1;
1503
1504   /* find reasonable corresponding BYTE position,
1505    * also try to mind about keyframes, since we can not go back a bit for them
1506    * later on */
1507   /* determining @next here based on SNAP_BEFORE/SNAP_AFTER should
1508    * mostly just work, but let's not yet boldly go there  ... */
1509   gst_qtdemux_adjust_seek (qtdemux, cur, FALSE, FALSE, &key_cur, &byte_cur);
1510
1511   if (byte_cur == -1)
1512     goto abort_seek;
1513
1514   GST_DEBUG_OBJECT (qtdemux, "Pushing BYTE seek rate %g, "
1515       "start %" G_GINT64_FORMAT ", stop %" G_GINT64_FORMAT, rate, byte_cur,
1516       stop);
1517
1518   GST_OBJECT_LOCK (qtdemux);
1519   qtdemux->seek_offset = byte_cur;
1520   if (!(flags & GST_SEEK_FLAG_KEY_UNIT)) {
1521     qtdemux->push_seek_start = cur;
1522   } else {
1523     qtdemux->push_seek_start = key_cur;
1524   }
1525
1526   if (stop_type == GST_SEEK_TYPE_NONE) {
1527     qtdemux->push_seek_stop = qtdemux->segment.stop;
1528   } else {
1529     qtdemux->push_seek_stop = original_stop;
1530   }
1531   GST_OBJECT_UNLOCK (qtdemux);
1532
1533   /* BYTE seek event */
1534   event = gst_event_new_seek (rate, GST_FORMAT_BYTES, flags, cur_type, byte_cur,
1535       stop_type, stop);
1536   gst_event_set_seqnum (event, seqnum);
1537   res = gst_pad_push_event (qtdemux->sinkpad, event);
1538
1539   return res;
1540
1541   /* ERRORS */
1542 abort_seek:
1543   {
1544     GST_DEBUG_OBJECT (qtdemux, "could not determine byte position to seek to, "
1545         "seek aborted.");
1546     return FALSE;
1547   }
1548 unsupported_seek:
1549   {
1550     GST_DEBUG_OBJECT (qtdemux, "unsupported seek, seek aborted.");
1551     return FALSE;
1552   }
1553 no_format:
1554   {
1555     GST_DEBUG_OBJECT (qtdemux, "unsupported format given, seek aborted.");
1556     return FALSE;
1557   }
1558 }
1559
1560 /* perform the seek.
1561  *
1562  * We set all segment_indexes in the streams to unknown and
1563  * adjust the time_position to the desired position. this is enough
1564  * to trigger a segment switch in the streaming thread to start
1565  * streaming from the desired position.
1566  *
1567  * Keyframe seeking is a little more complicated when dealing with
1568  * segments. Ideally we want to move to the previous keyframe in
1569  * the segment but there might not be a keyframe in the segment. In
1570  * fact, none of the segments could contain a keyframe. We take a
1571  * practical approach: seek to the previous keyframe in the segment,
1572  * if there is none, seek to the beginning of the segment.
1573  *
1574  * Called with STREAM_LOCK
1575  */
1576 static gboolean
1577 gst_qtdemux_perform_seek (GstQTDemux * qtdemux, GstSegment * segment,
1578     guint32 seqnum, GstSeekFlags flags)
1579 {
1580   gint64 desired_offset;
1581   GList *iter;
1582
1583   desired_offset = segment->position;
1584
1585   GST_DEBUG_OBJECT (qtdemux, "seeking to %" GST_TIME_FORMAT,
1586       GST_TIME_ARGS (desired_offset));
1587
1588   /* may not have enough fragmented info to do this adjustment,
1589    * and we can't scan (and probably should not) at this time with
1590    * possibly flushing upstream */
1591   if ((flags & GST_SEEK_FLAG_KEY_UNIT) && !qtdemux->fragmented) {
1592     gint64 min_offset;
1593     gboolean next, before, after;
1594
1595     before = ! !(flags & GST_SEEK_FLAG_SNAP_BEFORE);
1596     after = ! !(flags & GST_SEEK_FLAG_SNAP_AFTER);
1597     next = after && !before;
1598     if (segment->rate < 0)
1599       next = !next;
1600
1601     gst_qtdemux_adjust_seek (qtdemux, desired_offset, TRUE, next, &min_offset,
1602         NULL);
1603     GST_DEBUG_OBJECT (qtdemux, "keyframe seek, align to %"
1604         GST_TIME_FORMAT, GST_TIME_ARGS (min_offset));
1605     desired_offset = min_offset;
1606   }
1607
1608   /* and set all streams to the final position */
1609   gst_flow_combiner_reset (qtdemux->flowcombiner);
1610   qtdemux->segment_seqnum = seqnum;
1611   for (iter = qtdemux->active_streams; iter; iter = g_list_next (iter)) {
1612     QtDemuxStream *stream = QTDEMUX_STREAM (iter->data);
1613
1614     stream->time_position = desired_offset;
1615     stream->accumulated_base = 0;
1616     stream->sample_index = -1;
1617     stream->offset_in_sample = 0;
1618     stream->segment_index = -1;
1619     stream->sent_eos = FALSE;
1620
1621     if (segment->flags & GST_SEEK_FLAG_FLUSH)
1622       gst_segment_init (&stream->segment, GST_FORMAT_TIME);
1623   }
1624   segment->position = desired_offset;
1625   segment->time = desired_offset;
1626   if (segment->rate >= 0) {
1627     segment->start = desired_offset;
1628
1629     /* we stop at the end */
1630     if (segment->stop == -1)
1631       segment->stop = segment->duration;
1632   } else {
1633     segment->stop = desired_offset;
1634   }
1635
1636   if (qtdemux->fragmented)
1637     qtdemux->fragmented_seek_pending = TRUE;
1638
1639   return TRUE;
1640 }
1641
1642 /* do a seek in pull based mode */
1643 static gboolean
1644 gst_qtdemux_do_seek (GstQTDemux * qtdemux, GstPad * pad, GstEvent * event)
1645 {
1646   gdouble rate;
1647   GstFormat format;
1648   GstSeekFlags flags;
1649   GstSeekType cur_type, stop_type;
1650   gint64 cur, stop;
1651   gboolean flush;
1652   gboolean update;
1653   GstSegment seeksegment;
1654   guint32 seqnum = GST_SEQNUM_INVALID;
1655   GstEvent *flush_event;
1656   gboolean ret;
1657
1658   if (event) {
1659     GST_DEBUG_OBJECT (qtdemux, "doing seek with event");
1660
1661     gst_event_parse_seek (event, &rate, &format, &flags,
1662         &cur_type, &cur, &stop_type, &stop);
1663     seqnum = gst_event_get_seqnum (event);
1664
1665     /* we have to have a format as the segment format. Try to convert
1666      * if not. */
1667     if (!gst_qtdemux_convert_seek (pad, &format, cur_type, &cur,
1668             stop_type, &stop))
1669       goto no_format;
1670
1671     GST_DEBUG_OBJECT (qtdemux, "seek format %s", gst_format_get_name (format));
1672   } else {
1673     GST_DEBUG_OBJECT (qtdemux, "doing seek without event");
1674     flags = 0;
1675   }
1676
1677   flush = flags & GST_SEEK_FLAG_FLUSH;
1678
1679   /* stop streaming, either by flushing or by pausing the task */
1680   if (flush) {
1681     flush_event = gst_event_new_flush_start ();
1682     if (seqnum != GST_SEQNUM_INVALID)
1683       gst_event_set_seqnum (flush_event, seqnum);
1684     /* unlock upstream pull_range */
1685     gst_pad_push_event (qtdemux->sinkpad, gst_event_ref (flush_event));
1686     /* make sure out loop function exits */
1687     gst_qtdemux_push_event (qtdemux, flush_event);
1688   } else {
1689     /* non flushing seek, pause the task */
1690     gst_pad_pause_task (qtdemux->sinkpad);
1691   }
1692
1693   /* wait for streaming to finish */
1694   GST_PAD_STREAM_LOCK (qtdemux->sinkpad);
1695
1696   /* copy segment, we need this because we still need the old
1697    * segment when we close the current segment. */
1698   memcpy (&seeksegment, &qtdemux->segment, sizeof (GstSegment));
1699
1700   if (event) {
1701     /* configure the segment with the seek variables */
1702     GST_DEBUG_OBJECT (qtdemux, "configuring seek");
1703     if (!gst_segment_do_seek (&seeksegment, rate, format, flags,
1704             cur_type, cur, stop_type, stop, &update)) {
1705       ret = FALSE;
1706       GST_ERROR_OBJECT (qtdemux, "inconsistent seek values, doing nothing");
1707     } else {
1708       /* now do the seek */
1709       ret = gst_qtdemux_perform_seek (qtdemux, &seeksegment, seqnum, flags);
1710     }
1711   } else {
1712     /* now do the seek */
1713     ret = gst_qtdemux_perform_seek (qtdemux, &seeksegment, seqnum, flags);
1714   }
1715
1716   /* prepare for streaming again */
1717   if (flush) {
1718     flush_event = gst_event_new_flush_stop (TRUE);
1719     if (seqnum != GST_SEQNUM_INVALID)
1720       gst_event_set_seqnum (flush_event, seqnum);
1721
1722     gst_pad_push_event (qtdemux->sinkpad, gst_event_ref (flush_event));
1723     gst_qtdemux_push_event (qtdemux, flush_event);
1724   }
1725
1726   /* commit the new segment */
1727   memcpy (&qtdemux->segment, &seeksegment, sizeof (GstSegment));
1728
1729   if (qtdemux->segment.flags & GST_SEEK_FLAG_SEGMENT) {
1730     GstMessage *msg = gst_message_new_segment_start (GST_OBJECT_CAST (qtdemux),
1731         qtdemux->segment.format, qtdemux->segment.position);
1732     if (seqnum != GST_SEQNUM_INVALID)
1733       gst_message_set_seqnum (msg, seqnum);
1734     gst_element_post_message (GST_ELEMENT_CAST (qtdemux), msg);
1735   }
1736
1737   /* restart streaming, NEWSEGMENT will be sent from the streaming thread. */
1738   gst_pad_start_task (qtdemux->sinkpad, (GstTaskFunction) gst_qtdemux_loop,
1739       qtdemux->sinkpad, NULL);
1740
1741   GST_PAD_STREAM_UNLOCK (qtdemux->sinkpad);
1742
1743   return ret;
1744
1745   /* ERRORS */
1746 no_format:
1747   {
1748     GST_DEBUG_OBJECT (qtdemux, "unsupported format given, seek aborted.");
1749     return FALSE;
1750   }
1751 }
1752
1753 static gboolean
1754 qtdemux_ensure_index (GstQTDemux * qtdemux)
1755 {
1756   GList *iter;
1757
1758   GST_DEBUG_OBJECT (qtdemux, "collecting all metadata for all streams");
1759
1760   /* Build complete index */
1761   for (iter = qtdemux->active_streams; iter; iter = g_list_next (iter)) {
1762     QtDemuxStream *stream = QTDEMUX_STREAM (iter->data);
1763
1764     if (!qtdemux_parse_samples (qtdemux, stream, stream->n_samples - 1)) {
1765       GST_LOG_OBJECT (qtdemux,
1766           "Building complete index of track-id %u for seeking failed!",
1767           stream->track_id);
1768       return FALSE;
1769     }
1770   }
1771
1772   return TRUE;
1773 }
1774
1775 static gboolean
1776 gst_qtdemux_handle_src_event (GstPad * pad, GstObject * parent,
1777     GstEvent * event)
1778 {
1779   gboolean res = TRUE;
1780   GstQTDemux *qtdemux = GST_QTDEMUX (parent);
1781
1782   switch (GST_EVENT_TYPE (event)) {
1783     case GST_EVENT_SEEK:
1784     {
1785 #ifndef GST_DISABLE_GST_DEBUG
1786       GstClockTime ts = gst_util_get_timestamp ();
1787 #endif
1788       guint32 seqnum = gst_event_get_seqnum (event);
1789
1790       if (seqnum == qtdemux->segment_seqnum) {
1791         GST_LOG_OBJECT (pad,
1792             "Drop duplicated SEEK event seqnum %" G_GUINT32_FORMAT, seqnum);
1793         gst_event_unref (event);
1794         return TRUE;
1795       }
1796
1797       if (qtdemux->upstream_format_is_time && qtdemux->fragmented) {
1798         /* seek should be handled by upstream, we might need to re-download fragments */
1799         GST_DEBUG_OBJECT (qtdemux,
1800             "let upstream handle seek for fragmented playback");
1801         goto upstream;
1802       }
1803
1804       /* Build complete index for seeking;
1805        * if not a fragmented file at least */
1806       if (!qtdemux->fragmented)
1807         if (!qtdemux_ensure_index (qtdemux))
1808           goto index_failed;
1809 #ifndef GST_DISABLE_GST_DEBUG
1810       ts = gst_util_get_timestamp () - ts;
1811       GST_INFO_OBJECT (qtdemux,
1812           "Time taken to parse index %" GST_TIME_FORMAT, GST_TIME_ARGS (ts));
1813 #endif
1814     }
1815       if (qtdemux->pullbased) {
1816         res = gst_qtdemux_do_seek (qtdemux, pad, event);
1817       } else if (gst_pad_push_event (qtdemux->sinkpad, gst_event_ref (event))) {
1818         GST_DEBUG_OBJECT (qtdemux, "Upstream successfully seeked");
1819         res = TRUE;
1820       } else if (qtdemux->state == QTDEMUX_STATE_MOVIE && qtdemux->n_streams
1821           && !qtdemux->fragmented) {
1822         res = gst_qtdemux_do_push_seek (qtdemux, pad, event);
1823       } else {
1824         GST_DEBUG_OBJECT (qtdemux,
1825             "ignoring seek in push mode in current state");
1826         res = FALSE;
1827       }
1828       gst_event_unref (event);
1829       break;
1830     default:
1831     upstream:
1832       res = gst_pad_event_default (pad, parent, event);
1833       break;
1834   }
1835
1836 done:
1837   return res;
1838
1839   /* ERRORS */
1840 index_failed:
1841   {
1842     GST_ERROR_OBJECT (qtdemux, "Index failed");
1843     gst_event_unref (event);
1844     res = FALSE;
1845     goto done;
1846   }
1847 }
1848
1849 /* Find, for each track, the first sample in coding order that has a file offset >= @byte_pos.
1850  *
1851  * If @fw is false, the coding order is explored backwards.
1852  *
1853  * If @set is true, each stream will be moved to its matched sample, or EOS if no matching
1854  * sample is found for that track.
1855  *
1856  * The stream and sample index of the sample with the minimum offset in the direction explored
1857  * (see @fw) is returned in the output parameters @_stream and @_index respectively.
1858  *
1859  * @_time is set to the QTSAMPLE_PTS of the matched sample with the minimum QTSAMPLE_PTS in the
1860  * direction explored, which may not always match the QTSAMPLE_PTS of the sample returned in
1861  * @_stream and @_index. */
1862 static void
1863 gst_qtdemux_find_sample (GstQTDemux * qtdemux, gint64 byte_pos, gboolean fw,
1864     gboolean set, QtDemuxStream ** _stream, gint * _index, gint64 * _time)
1865 {
1866   gint i, index;
1867   gint64 time, min_time;
1868   QtDemuxStream *stream;
1869   GList *iter;
1870
1871   min_time = -1;
1872   stream = NULL;
1873   index = -1;
1874
1875   for (iter = qtdemux->active_streams; iter; iter = g_list_next (iter)) {
1876     QtDemuxStream *str;
1877     gint inc;
1878     gboolean set_sample;
1879
1880     str = QTDEMUX_STREAM (iter->data);
1881     set_sample = !set;
1882
1883     if (fw) {
1884       i = 0;
1885       inc = 1;
1886     } else {
1887       i = str->n_samples - 1;
1888       inc = -1;
1889     }
1890
1891     for (; (i >= 0) && (i < str->n_samples); i += inc) {
1892       if (str->samples[i].size == 0)
1893         continue;
1894
1895       if (fw && (str->samples[i].offset < byte_pos))
1896         continue;
1897
1898       if (!fw && (str->samples[i].offset + str->samples[i].size > byte_pos))
1899         continue;
1900
1901       /* move stream to first available sample */
1902       if (set) {
1903         gst_qtdemux_move_stream (qtdemux, str, i);
1904         set_sample = TRUE;
1905       }
1906
1907       /* avoid index from sparse streams since they might be far away */
1908       if (!CUR_STREAM (str)->sparse) {
1909         /* determine min/max time */
1910         time = QTSAMPLE_PTS (str, &str->samples[i]);
1911         if (min_time == -1 || (!fw && time > min_time) ||
1912             (fw && time < min_time)) {
1913           min_time = time;
1914         }
1915
1916         /* determine stream with leading sample, to get its position */
1917         if (!stream ||
1918             (fw && (str->samples[i].offset < stream->samples[index].offset)) ||
1919             (!fw && (str->samples[i].offset > stream->samples[index].offset))) {
1920           stream = str;
1921           index = i;
1922         }
1923       }
1924       break;
1925     }
1926
1927     /* no sample for this stream, mark eos */
1928     if (!set_sample)
1929       gst_qtdemux_move_stream (qtdemux, str, str->n_samples);
1930   }
1931
1932   if (_time)
1933     *_time = min_time;
1934   if (_stream)
1935     *_stream = stream;
1936   if (_index)
1937     *_index = index;
1938 }
1939
1940 /* Copied from mpegtsbase code */
1941 /* FIXME: replace this function when we add new util function for stream-id creation */
1942 static gchar *
1943 _get_upstream_id (GstQTDemux * demux)
1944 {
1945   gchar *upstream_id = gst_pad_get_stream_id (demux->sinkpad);
1946
1947   if (!upstream_id) {
1948     /* Try to create one from the upstream URI, else use a randome number */
1949     GstQuery *query;
1950     gchar *uri = NULL;
1951
1952     /* Try to generate one from the URI query and
1953      * if it fails take a random number instead */
1954     query = gst_query_new_uri ();
1955     if (gst_element_query (GST_ELEMENT_CAST (demux), query)) {
1956       gst_query_parse_uri (query, &uri);
1957     }
1958
1959     if (uri) {
1960       GChecksum *cs;
1961
1962       /* And then generate an SHA256 sum of the URI */
1963       cs = g_checksum_new (G_CHECKSUM_SHA256);
1964       g_checksum_update (cs, (const guchar *) uri, strlen (uri));
1965       g_free (uri);
1966       upstream_id = g_strdup (g_checksum_get_string (cs));
1967       g_checksum_free (cs);
1968     } else {
1969       /* Just get some random number if the URI query fails */
1970       GST_FIXME_OBJECT (demux, "Creating random stream-id, consider "
1971           "implementing a deterministic way of creating a stream-id");
1972       upstream_id =
1973           g_strdup_printf ("%08x%08x%08x%08x", g_random_int (), g_random_int (),
1974           g_random_int (), g_random_int ());
1975     }
1976
1977     gst_query_unref (query);
1978   }
1979   return upstream_id;
1980 }
1981
1982 static QtDemuxStream *
1983 _create_stream (GstQTDemux * demux, guint32 track_id)
1984 {
1985   QtDemuxStream *stream;
1986   gchar *upstream_id;
1987
1988   stream = g_new0 (QtDemuxStream, 1);
1989   stream->demux = demux;
1990   stream->track_id = track_id;
1991   upstream_id = _get_upstream_id (demux);
1992   stream->stream_id = g_strdup_printf ("%s/%03u", upstream_id, track_id);
1993   g_free (upstream_id);
1994   /* new streams always need a discont */
1995   stream->discont = TRUE;
1996   /* we enable clipping for raw audio/video streams */
1997   stream->need_clip = FALSE;
1998   stream->need_process = FALSE;
1999   stream->segment_index = -1;
2000   stream->time_position = 0;
2001   stream->sample_index = -1;
2002   stream->offset_in_sample = 0;
2003   stream->new_stream = TRUE;
2004   stream->multiview_mode = GST_VIDEO_MULTIVIEW_MODE_NONE;
2005   stream->multiview_flags = GST_VIDEO_MULTIVIEW_FLAGS_NONE;
2006   stream->protected = FALSE;
2007   stream->protection_scheme_type = 0;
2008   stream->protection_scheme_version = 0;
2009   stream->protection_scheme_info = NULL;
2010   stream->n_samples_moof = 0;
2011   stream->duration_moof = 0;
2012   stream->duration_last_moof = 0;
2013   stream->alignment = 1;
2014   stream->stream_tags = gst_tag_list_new_empty ();
2015   gst_tag_list_set_scope (stream->stream_tags, GST_TAG_SCOPE_STREAM);
2016   g_queue_init (&stream->protection_scheme_event_queue);
2017   return stream;
2018 }
2019
2020 static gboolean
2021 gst_qtdemux_setcaps (GstQTDemux * demux, GstCaps * caps)
2022 {
2023   GstStructure *structure;
2024   const gchar *variant;
2025   const GstCaps *mediacaps = NULL;
2026
2027   GST_DEBUG_OBJECT (demux, "Sink set caps: %" GST_PTR_FORMAT, caps);
2028
2029   structure = gst_caps_get_structure (caps, 0);
2030   variant = gst_structure_get_string (structure, "variant");
2031
2032   if (variant && strcmp (variant, "mss-fragmented") == 0) {
2033     QtDemuxStream *stream;
2034     const GValue *value;
2035
2036     demux->fragmented = TRUE;
2037     demux->mss_mode = TRUE;
2038
2039     if (demux->n_streams > 1) {
2040       /* can't do this, we can only renegotiate for another mss format */
2041       return FALSE;
2042     }
2043
2044     value = gst_structure_get_value (structure, "media-caps");
2045     /* create stream */
2046     if (value) {
2047       const GValue *timescale_v;
2048
2049       /* TODO update when stream changes during playback */
2050
2051       if (demux->n_streams == 0) {
2052         stream = _create_stream (demux, 1);
2053         demux->active_streams = g_list_append (demux->active_streams, stream);
2054         demux->n_streams = 1;
2055         /* mss has no stsd/stsd entry, use id 0 as default */
2056         stream->stsd_entries_length = 1;
2057         stream->stsd_sample_description_id = stream->cur_stsd_entry_index = 0;
2058         stream->stsd_entries = g_new0 (QtDemuxStreamStsdEntry, 1);
2059       } else {
2060         stream = QTDEMUX_FIRST_STREAM (demux);
2061       }
2062
2063       timescale_v = gst_structure_get_value (structure, "timescale");
2064       if (timescale_v) {
2065         stream->timescale = g_value_get_uint64 (timescale_v);
2066       } else {
2067         /* default mss timescale */
2068         stream->timescale = 10000000;
2069       }
2070       demux->timescale = stream->timescale;
2071
2072       mediacaps = gst_value_get_caps (value);
2073       if (!CUR_STREAM (stream)->caps
2074           || !gst_caps_is_equal_fixed (mediacaps, CUR_STREAM (stream)->caps)) {
2075         GST_DEBUG_OBJECT (demux, "We have a new caps %" GST_PTR_FORMAT,
2076             mediacaps);
2077         stream->new_caps = TRUE;
2078       }
2079       gst_caps_replace (&CUR_STREAM (stream)->caps, (GstCaps *) mediacaps);
2080       structure = gst_caps_get_structure (mediacaps, 0);
2081       if (g_str_has_prefix (gst_structure_get_name (structure), "video")) {
2082         stream->subtype = FOURCC_vide;
2083
2084         gst_structure_get_int (structure, "width", &CUR_STREAM (stream)->width);
2085         gst_structure_get_int (structure, "height",
2086             &CUR_STREAM (stream)->height);
2087         gst_structure_get_fraction (structure, "framerate",
2088             &CUR_STREAM (stream)->fps_n, &CUR_STREAM (stream)->fps_d);
2089       } else if (g_str_has_prefix (gst_structure_get_name (structure), "audio")) {
2090         gint rate = 0;
2091         stream->subtype = FOURCC_soun;
2092         gst_structure_get_int (structure, "channels",
2093             &CUR_STREAM (stream)->n_channels);
2094         gst_structure_get_int (structure, "rate", &rate);
2095         CUR_STREAM (stream)->rate = rate;
2096       }
2097     }
2098     gst_caps_replace (&demux->media_caps, (GstCaps *) mediacaps);
2099   } else {
2100     demux->mss_mode = FALSE;
2101   }
2102
2103   return TRUE;
2104 }
2105
2106 static void
2107 gst_qtdemux_reset (GstQTDemux * qtdemux, gboolean hard)
2108 {
2109   GList *iter;
2110
2111   GST_DEBUG_OBJECT (qtdemux, "Resetting demux");
2112   gst_pad_stop_task (qtdemux->sinkpad);
2113
2114   if (hard || qtdemux->upstream_format_is_time) {
2115     qtdemux->state = QTDEMUX_STATE_INITIAL;
2116     qtdemux->neededbytes = 16;
2117     qtdemux->todrop = 0;
2118     qtdemux->pullbased = FALSE;
2119     qtdemux->posted_redirect = FALSE;
2120     qtdemux->first_mdat = -1;
2121     qtdemux->header_size = 0;
2122     qtdemux->mdatoffset = -1;
2123     qtdemux->restoredata_offset = -1;
2124     if (qtdemux->mdatbuffer)
2125       gst_buffer_unref (qtdemux->mdatbuffer);
2126     if (qtdemux->restoredata_buffer)
2127       gst_buffer_unref (qtdemux->restoredata_buffer);
2128     qtdemux->mdatbuffer = NULL;
2129     qtdemux->restoredata_buffer = NULL;
2130     qtdemux->mdatleft = 0;
2131     qtdemux->mdatsize = 0;
2132     if (qtdemux->comp_brands)
2133       gst_buffer_unref (qtdemux->comp_brands);
2134     qtdemux->comp_brands = NULL;
2135     qtdemux->last_moov_offset = -1;
2136     if (qtdemux->moov_node_compressed) {
2137       g_node_destroy (qtdemux->moov_node_compressed);
2138       if (qtdemux->moov_node)
2139         g_free (qtdemux->moov_node->data);
2140     }
2141     qtdemux->moov_node_compressed = NULL;
2142     if (qtdemux->moov_node)
2143       g_node_destroy (qtdemux->moov_node);
2144     qtdemux->moov_node = NULL;
2145     if (qtdemux->tag_list)
2146       gst_mini_object_unref (GST_MINI_OBJECT_CAST (qtdemux->tag_list));
2147     qtdemux->tag_list = gst_tag_list_new_empty ();
2148     gst_tag_list_set_scope (qtdemux->tag_list, GST_TAG_SCOPE_GLOBAL);
2149 #if 0
2150     if (qtdemux->element_index)
2151       gst_object_unref (qtdemux->element_index);
2152     qtdemux->element_index = NULL;
2153 #endif
2154     qtdemux->major_brand = 0;
2155     qtdemux->upstream_format_is_time = FALSE;
2156     qtdemux->upstream_seekable = FALSE;
2157     qtdemux->upstream_size = 0;
2158
2159     qtdemux->fragment_start = -1;
2160     qtdemux->fragment_start_offset = -1;
2161     qtdemux->duration = 0;
2162     qtdemux->moof_offset = 0;
2163     qtdemux->chapters_track_id = 0;
2164     qtdemux->have_group_id = FALSE;
2165     qtdemux->group_id = G_MAXUINT;
2166
2167     g_queue_foreach (&qtdemux->protection_event_queue, (GFunc) gst_event_unref,
2168         NULL);
2169     g_queue_clear (&qtdemux->protection_event_queue);
2170   }
2171   qtdemux->offset = 0;
2172   gst_adapter_clear (qtdemux->adapter);
2173   gst_segment_init (&qtdemux->segment, GST_FORMAT_TIME);
2174   qtdemux->segment_seqnum = GST_SEQNUM_INVALID;
2175   qtdemux->need_segment = TRUE;
2176
2177   if (hard) {
2178     g_list_free_full (qtdemux->active_streams,
2179         (GDestroyNotify) gst_qtdemux_stream_free);
2180     g_list_free_full (qtdemux->old_streams,
2181         (GDestroyNotify) gst_qtdemux_stream_free);
2182     qtdemux->active_streams = NULL;
2183     qtdemux->old_streams = NULL;
2184     qtdemux->n_streams = 0;
2185     qtdemux->n_video_streams = 0;
2186     qtdemux->n_audio_streams = 0;
2187     qtdemux->n_sub_streams = 0;
2188     qtdemux->exposed = FALSE;
2189     qtdemux->fragmented = FALSE;
2190     qtdemux->mss_mode = FALSE;
2191     gst_caps_replace (&qtdemux->media_caps, NULL);
2192     qtdemux->timescale = 0;
2193     qtdemux->got_moov = FALSE;
2194     qtdemux->cenc_aux_info_offset = 0;
2195     qtdemux->cenc_aux_info_sizes = NULL;
2196     qtdemux->cenc_aux_sample_count = 0;
2197     if (qtdemux->protection_system_ids) {
2198       g_ptr_array_free (qtdemux->protection_system_ids, TRUE);
2199       qtdemux->protection_system_ids = NULL;
2200     }
2201     qtdemux->streams_aware = GST_OBJECT_PARENT (qtdemux)
2202         && GST_OBJECT_FLAG_IS_SET (GST_OBJECT_PARENT (qtdemux),
2203         GST_BIN_FLAG_STREAMS_AWARE);
2204
2205     if (qtdemux->preferred_protection_system_id) {
2206       g_free (qtdemux->preferred_protection_system_id);
2207       qtdemux->preferred_protection_system_id = NULL;
2208     }
2209   } else if (qtdemux->mss_mode) {
2210     gst_flow_combiner_reset (qtdemux->flowcombiner);
2211     g_list_foreach (qtdemux->active_streams,
2212         (GFunc) gst_qtdemux_stream_clear, NULL);
2213   } else {
2214     gst_flow_combiner_reset (qtdemux->flowcombiner);
2215     for (iter = qtdemux->active_streams; iter; iter = g_list_next (iter)) {
2216       QtDemuxStream *stream = QTDEMUX_STREAM (iter->data);
2217       stream->sent_eos = FALSE;
2218       stream->time_position = 0;
2219       stream->accumulated_base = 0;
2220     }
2221   }
2222 }
2223
2224
2225 /* Maps the @segment to the qt edts internal segments and pushes
2226  * the correspnding segment event.
2227  *
2228  * If it ends up being at a empty segment, a gap will be pushed and the next
2229  * edts segment will be activated in sequence.
2230  *
2231  * To be used in push-mode only */
2232 static void
2233 gst_qtdemux_map_and_push_segments (GstQTDemux * qtdemux, GstSegment * segment)
2234 {
2235   gint i;
2236   GList *iter;
2237
2238   for (iter = qtdemux->active_streams; iter; iter = g_list_next (iter)) {
2239     QtDemuxStream *stream = QTDEMUX_STREAM (iter->data);
2240
2241     stream->time_position = segment->start;
2242
2243     /* in push mode we should be guaranteed that we will have empty segments
2244      * at the beginning and then one segment after, other scenarios are not
2245      * supported and are discarded when parsing the edts */
2246     for (i = 0; i < stream->n_segments; i++) {
2247       if (stream->segments[i].stop_time > segment->start) {
2248         /* push the empty segment and move to the next one */
2249         gst_qtdemux_activate_segment (qtdemux, stream, i,
2250             stream->time_position);
2251         if (QTSEGMENT_IS_EMPTY (&stream->segments[i])) {
2252           gst_qtdemux_send_gap_for_segment (qtdemux, stream, i,
2253               stream->time_position);
2254
2255           /* accumulate previous segments */
2256           if (GST_CLOCK_TIME_IS_VALID (stream->segment.stop))
2257             stream->accumulated_base +=
2258                 (stream->segment.stop -
2259                 stream->segment.start) / ABS (stream->segment.rate);
2260           continue;
2261         }
2262
2263         g_assert (i == stream->n_segments - 1);
2264       }
2265     }
2266   }
2267 }
2268
2269 static gboolean
2270 gst_qtdemux_handle_sink_event (GstPad * sinkpad, GstObject * parent,
2271     GstEvent * event)
2272 {
2273   GstQTDemux *demux = GST_QTDEMUX (parent);
2274   gboolean res = TRUE;
2275
2276   GST_LOG_OBJECT (demux, "handling %s event", GST_EVENT_TYPE_NAME (event));
2277
2278   switch (GST_EVENT_TYPE (event)) {
2279     case GST_EVENT_SEGMENT:
2280     {
2281       gint64 offset = 0;
2282       QtDemuxStream *stream;
2283       gint idx;
2284       GstSegment segment;
2285
2286       /* some debug output */
2287       gst_event_copy_segment (event, &segment);
2288       GST_DEBUG_OBJECT (demux, "received newsegment %" GST_SEGMENT_FORMAT,
2289           &segment);
2290
2291       if (segment.format == GST_FORMAT_TIME) {
2292         demux->upstream_format_is_time = TRUE;
2293       } else {
2294         GST_DEBUG_OBJECT (demux, "Not storing upstream newsegment, "
2295             "not in time format");
2296
2297         /* chain will send initial newsegment after pads have been added */
2298         if (demux->state != QTDEMUX_STATE_MOVIE || !demux->n_streams) {
2299           GST_DEBUG_OBJECT (demux, "still starting, eating event");
2300           goto exit;
2301         }
2302       }
2303
2304       /* check if this matches a time seek we received previously
2305        * FIXME for backwards compatibility reasons we use the
2306        * seek_offset here to compare. In the future we might want to
2307        * change this to use the seqnum as it uniquely should identify
2308        * the segment that corresponds to the seek. */
2309       GST_DEBUG_OBJECT (demux, "Stored seek offset: %" G_GINT64_FORMAT
2310           ", received segment offset %" G_GINT64_FORMAT,
2311           demux->seek_offset, segment.start);
2312       if (segment.format == GST_FORMAT_BYTES
2313           && demux->seek_offset == segment.start) {
2314         GST_OBJECT_LOCK (demux);
2315         offset = segment.start;
2316
2317         segment.format = GST_FORMAT_TIME;
2318         segment.start = demux->push_seek_start;
2319         segment.stop = demux->push_seek_stop;
2320         GST_DEBUG_OBJECT (demux, "Replaced segment with stored seek "
2321             "segment %" GST_TIME_FORMAT " - %" GST_TIME_FORMAT,
2322             GST_TIME_ARGS (segment.start), GST_TIME_ARGS (segment.stop));
2323         GST_OBJECT_UNLOCK (demux);
2324       }
2325
2326       /* we only expect a BYTE segment, e.g. following a seek */
2327       if (segment.format == GST_FORMAT_BYTES) {
2328         if (GST_CLOCK_TIME_IS_VALID (segment.start)) {
2329           offset = segment.start;
2330
2331           gst_qtdemux_find_sample (demux, segment.start, TRUE, FALSE, NULL,
2332               NULL, (gint64 *) & segment.start);
2333           if ((gint64) segment.start < 0)
2334             segment.start = 0;
2335         }
2336         if (GST_CLOCK_TIME_IS_VALID (segment.stop)) {
2337           gst_qtdemux_find_sample (demux, segment.stop, FALSE, FALSE, NULL,
2338               NULL, (gint64 *) & segment.stop);
2339           /* keyframe seeking should already arrange for start >= stop,
2340            * but make sure in other rare cases */
2341           segment.stop = MAX (segment.stop, segment.start);
2342         }
2343       } else if (segment.format == GST_FORMAT_TIME) {
2344         /* push all data on the adapter before starting this
2345          * new segment */
2346         gst_qtdemux_process_adapter (demux, TRUE);
2347       } else {
2348         GST_DEBUG_OBJECT (demux, "unsupported segment format, ignoring");
2349         goto exit;
2350       }
2351
2352       /* We shouldn't modify upstream driven TIME FORMAT segment */
2353       if (!demux->upstream_format_is_time) {
2354         /* accept upstream's notion of segment and distribute along */
2355         segment.format = GST_FORMAT_TIME;
2356         segment.position = segment.time = segment.start;
2357         segment.duration = demux->segment.duration;
2358         segment.base = gst_segment_to_running_time (&demux->segment,
2359             GST_FORMAT_TIME, demux->segment.position);
2360       }
2361
2362       gst_segment_copy_into (&segment, &demux->segment);
2363       GST_DEBUG_OBJECT (demux, "Pushing newseg %" GST_SEGMENT_FORMAT, &segment);
2364
2365       /* map segment to internal qt segments and push on each stream */
2366       if (demux->n_streams) {
2367         if (demux->fragmented) {
2368           GstEvent *segment_event = gst_event_new_segment (&segment);
2369
2370           gst_event_set_seqnum (segment_event, demux->segment_seqnum);
2371           gst_qtdemux_push_event (demux, segment_event);
2372         } else {
2373           gst_qtdemux_map_and_push_segments (demux, &segment);
2374         }
2375         /* keep need-segment as is in case this is the segment before
2376          * fragmented data, we might not have pads yet to push it */
2377         if (demux->exposed)
2378           demux->need_segment = FALSE;
2379       }
2380
2381       /* clear leftover in current segment, if any */
2382       gst_adapter_clear (demux->adapter);
2383
2384       /* set up streaming thread */
2385       demux->offset = offset;
2386       if (demux->upstream_format_is_time) {
2387         GST_DEBUG_OBJECT (demux, "Upstream is driving in time format, "
2388             "set values to restart reading from a new atom");
2389         demux->neededbytes = 16;
2390         demux->todrop = 0;
2391       } else {
2392         gst_qtdemux_find_sample (demux, offset, TRUE, TRUE, &stream, &idx,
2393             NULL);
2394         if (stream) {
2395           demux->todrop = stream->samples[idx].offset - offset;
2396           demux->neededbytes = demux->todrop + stream->samples[idx].size;
2397         } else {
2398           /* set up for EOS */
2399           demux->neededbytes = -1;
2400           demux->todrop = 0;
2401         }
2402       }
2403     exit:
2404       gst_event_unref (event);
2405       res = TRUE;
2406       goto drop;
2407     }
2408     case GST_EVENT_FLUSH_START:
2409     {
2410       if (gst_event_get_seqnum (event) == demux->offset_seek_seqnum) {
2411         gst_event_unref (event);
2412         goto drop;
2413       }
2414       QTDEMUX_EXPOSE_LOCK (demux);
2415       res = gst_pad_event_default (demux->sinkpad, parent, event);
2416       QTDEMUX_EXPOSE_UNLOCK (demux);
2417       goto drop;
2418     }
2419     case GST_EVENT_FLUSH_STOP:
2420     {
2421       guint64 dur;
2422
2423       dur = demux->segment.duration;
2424       gst_qtdemux_reset (demux, FALSE);
2425       demux->segment.duration = dur;
2426
2427       if (gst_event_get_seqnum (event) == demux->offset_seek_seqnum) {
2428         gst_event_unref (event);
2429         goto drop;
2430       }
2431       break;
2432     }
2433     case GST_EVENT_EOS:
2434       /* If we are in push mode, and get an EOS before we've seen any streams,
2435        * then error out - we have nowhere to send the EOS */
2436       if (!demux->pullbased) {
2437         GList *iter;
2438         gboolean has_valid_stream = FALSE;
2439         for (iter = demux->active_streams; iter; iter = g_list_next (iter)) {
2440           if (QTDEMUX_STREAM (iter->data)->pad != NULL) {
2441             has_valid_stream = TRUE;
2442             break;
2443           }
2444         }
2445         if (!has_valid_stream)
2446           gst_qtdemux_post_no_playable_stream_error (demux);
2447         else {
2448           GST_DEBUG_OBJECT (demux, "Data still available after EOS: %u",
2449               (guint) gst_adapter_available (demux->adapter));
2450           if (gst_qtdemux_process_adapter (demux, TRUE) != GST_FLOW_OK) {
2451             res = FALSE;
2452           }
2453         }
2454       }
2455       break;
2456     case GST_EVENT_CAPS:{
2457       GstCaps *caps = NULL;
2458
2459       gst_event_parse_caps (event, &caps);
2460       gst_qtdemux_setcaps (demux, caps);
2461       res = TRUE;
2462       gst_event_unref (event);
2463       goto drop;
2464     }
2465     case GST_EVENT_PROTECTION:
2466     {
2467       const gchar *system_id = NULL;
2468
2469       gst_event_parse_protection (event, &system_id, NULL, NULL);
2470       GST_DEBUG_OBJECT (demux, "Received protection event for system ID %s",
2471           system_id);
2472       gst_qtdemux_append_protection_system_id (demux, system_id);
2473       /* save the event for later, for source pads that have not been created */
2474       g_queue_push_tail (&demux->protection_event_queue, gst_event_ref (event));
2475       /* send it to all pads that already exist */
2476       gst_qtdemux_push_event (demux, event);
2477       res = TRUE;
2478       goto drop;
2479     }
2480     case GST_EVENT_STREAM_START:
2481     {
2482       res = TRUE;
2483       gst_event_unref (event);
2484
2485       /* Drain all the buffers */
2486       gst_qtdemux_process_adapter (demux, TRUE);
2487       gst_qtdemux_reset (demux, FALSE);
2488       /* We expect new moov box after new stream-start event */
2489       demux->old_streams =
2490           g_list_concat (demux->old_streams, demux->active_streams);
2491       demux->active_streams = NULL;
2492
2493       goto drop;
2494     }
2495     default:
2496       break;
2497   }
2498
2499   res = gst_pad_event_default (demux->sinkpad, parent, event) & res;
2500
2501 drop:
2502   return res;
2503 }
2504
2505 #if 0
2506 static void
2507 gst_qtdemux_set_index (GstElement * element, GstIndex * index)
2508 {
2509   GstQTDemux *demux = GST_QTDEMUX (element);
2510
2511   GST_OBJECT_LOCK (demux);
2512   if (demux->element_index)
2513     gst_object_unref (demux->element_index);
2514   if (index) {
2515     demux->element_index = gst_object_ref (index);
2516   } else {
2517     demux->element_index = NULL;
2518   }
2519   GST_OBJECT_UNLOCK (demux);
2520   /* object lock might be taken again */
2521   if (index)
2522     gst_index_get_writer_id (index, GST_OBJECT (element), &demux->index_id);
2523   GST_DEBUG_OBJECT (demux, "Set index %" GST_PTR_FORMAT "for writer id %d",
2524       demux->element_index, demux->index_id);
2525 }
2526
2527 static GstIndex *
2528 gst_qtdemux_get_index (GstElement * element)
2529 {
2530   GstIndex *result = NULL;
2531   GstQTDemux *demux = GST_QTDEMUX (element);
2532
2533   GST_OBJECT_LOCK (demux);
2534   if (demux->element_index)
2535     result = gst_object_ref (demux->element_index);
2536   GST_OBJECT_UNLOCK (demux);
2537
2538   GST_DEBUG_OBJECT (demux, "Returning index %" GST_PTR_FORMAT, result);
2539
2540   return result;
2541 }
2542 #endif
2543
2544 static void
2545 gst_qtdemux_stbl_free (QtDemuxStream * stream)
2546 {
2547   g_free ((gpointer) stream->stco.data);
2548   stream->stco.data = NULL;
2549   g_free ((gpointer) stream->stsz.data);
2550   stream->stsz.data = NULL;
2551   g_free ((gpointer) stream->stsc.data);
2552   stream->stsc.data = NULL;
2553   g_free ((gpointer) stream->stts.data);
2554   stream->stts.data = NULL;
2555   g_free ((gpointer) stream->stss.data);
2556   stream->stss.data = NULL;
2557   g_free ((gpointer) stream->stps.data);
2558   stream->stps.data = NULL;
2559   g_free ((gpointer) stream->ctts.data);
2560   stream->ctts.data = NULL;
2561 }
2562
2563 static void
2564 gst_qtdemux_stream_flush_segments_data (QtDemuxStream * stream)
2565 {
2566   g_free (stream->segments);
2567   stream->segments = NULL;
2568   stream->segment_index = -1;
2569   stream->accumulated_base = 0;
2570 }
2571
2572 static void
2573 gst_qtdemux_stream_flush_samples_data (QtDemuxStream * stream)
2574 {
2575   g_free (stream->samples);
2576   stream->samples = NULL;
2577   gst_qtdemux_stbl_free (stream);
2578
2579   /* fragments */
2580   g_free (stream->ra_entries);
2581   stream->ra_entries = NULL;
2582   stream->n_ra_entries = 0;
2583
2584   stream->sample_index = -1;
2585   stream->stbl_index = -1;
2586   stream->n_samples = 0;
2587   stream->time_position = 0;
2588
2589   stream->n_samples_moof = 0;
2590   stream->duration_moof = 0;
2591   stream->duration_last_moof = 0;
2592 }
2593
2594 static void
2595 gst_qtdemux_stream_clear (QtDemuxStream * stream)
2596 {
2597   gint i;
2598   if (stream->allocator)
2599     gst_object_unref (stream->allocator);
2600   while (stream->buffers) {
2601     gst_buffer_unref (GST_BUFFER_CAST (stream->buffers->data));
2602     stream->buffers = g_slist_delete_link (stream->buffers, stream->buffers);
2603   }
2604   for (i = 0; i < stream->stsd_entries_length; i++) {
2605     QtDemuxStreamStsdEntry *entry = &stream->stsd_entries[i];
2606     if (entry->rgb8_palette) {
2607       gst_memory_unref (entry->rgb8_palette);
2608       entry->rgb8_palette = NULL;
2609     }
2610     entry->sparse = FALSE;
2611   }
2612
2613   if (stream->stream_tags)
2614     gst_tag_list_unref (stream->stream_tags);
2615
2616   stream->stream_tags = gst_tag_list_new_empty ();
2617   gst_tag_list_set_scope (stream->stream_tags, GST_TAG_SCOPE_STREAM);
2618   g_free (stream->redirect_uri);
2619   stream->redirect_uri = NULL;
2620   stream->sent_eos = FALSE;
2621   stream->protected = FALSE;
2622   if (stream->protection_scheme_info) {
2623     if (stream->protection_scheme_type == FOURCC_cenc) {
2624       QtDemuxCencSampleSetInfo *info =
2625           (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
2626       if (info->default_properties)
2627         gst_structure_free (info->default_properties);
2628       if (info->crypto_info)
2629         g_ptr_array_free (info->crypto_info, TRUE);
2630     }
2631     g_free (stream->protection_scheme_info);
2632     stream->protection_scheme_info = NULL;
2633   }
2634   stream->protection_scheme_type = 0;
2635   stream->protection_scheme_version = 0;
2636   g_queue_foreach (&stream->protection_scheme_event_queue,
2637       (GFunc) gst_event_unref, NULL);
2638   g_queue_clear (&stream->protection_scheme_event_queue);
2639   gst_qtdemux_stream_flush_segments_data (stream);
2640   gst_qtdemux_stream_flush_samples_data (stream);
2641 }
2642
2643 static void
2644 gst_qtdemux_stream_reset (QtDemuxStream * stream)
2645 {
2646   gint i;
2647   gst_qtdemux_stream_clear (stream);
2648   for (i = 0; i < stream->stsd_entries_length; i++) {
2649     QtDemuxStreamStsdEntry *entry = &stream->stsd_entries[i];
2650     if (entry->caps) {
2651       gst_caps_unref (entry->caps);
2652       entry->caps = NULL;
2653     }
2654   }
2655   g_free (stream->stsd_entries);
2656   stream->stsd_entries = NULL;
2657   stream->stsd_entries_length = 0;
2658 }
2659
2660
2661 static void
2662 gst_qtdemux_stream_free (QtDemuxStream * stream)
2663 {
2664   gst_qtdemux_stream_reset (stream);
2665   gst_tag_list_unref (stream->stream_tags);
2666   if (stream->pad) {
2667     GstQTDemux *demux = stream->demux;
2668     gst_element_remove_pad (GST_ELEMENT_CAST (demux), stream->pad);
2669     gst_flow_combiner_remove_pad (demux->flowcombiner, stream->pad);
2670   }
2671   g_free (stream->stream_id);
2672   g_free (stream);
2673 }
2674
2675 static void
2676 gst_qtdemux_remove_stream (GstQTDemux * qtdemux, QtDemuxStream * stream)
2677 {
2678   qtdemux->active_streams = g_list_remove (qtdemux->active_streams, stream);
2679   gst_qtdemux_stream_free (stream);
2680   qtdemux->n_streams--;
2681 }
2682
2683 static GstStateChangeReturn
2684 gst_qtdemux_change_state (GstElement * element, GstStateChange transition)
2685 {
2686   GstQTDemux *qtdemux = GST_QTDEMUX (element);
2687   GstStateChangeReturn result = GST_STATE_CHANGE_FAILURE;
2688
2689   switch (transition) {
2690     case GST_STATE_CHANGE_READY_TO_PAUSED:
2691       gst_qtdemux_reset (qtdemux, TRUE);
2692       break;
2693     default:
2694       break;
2695   }
2696
2697   result = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
2698
2699   switch (transition) {
2700     case GST_STATE_CHANGE_PAUSED_TO_READY:{
2701       gst_qtdemux_reset (qtdemux, TRUE);
2702       break;
2703     }
2704     default:
2705       break;
2706   }
2707
2708   return result;
2709 }
2710
2711 static void
2712 gst_qtdemux_set_context (GstElement * element, GstContext * context)
2713 {
2714   GstQTDemux *qtdemux = GST_QTDEMUX (element);
2715
2716   g_return_if_fail (GST_IS_CONTEXT (context));
2717
2718   if (gst_context_has_context_type (context,
2719           "drm-preferred-decryption-system-id")) {
2720     const GstStructure *s;
2721
2722     s = gst_context_get_structure (context);
2723     g_free (qtdemux->preferred_protection_system_id);
2724     qtdemux->preferred_protection_system_id =
2725         g_strdup (gst_structure_get_string (s, "decryption-system-id"));
2726     GST_DEBUG_OBJECT (element, "set preferred decryption system to %s",
2727         qtdemux->preferred_protection_system_id);
2728   }
2729
2730   GST_ELEMENT_CLASS (parent_class)->set_context (element, context);
2731 }
2732
2733 static void
2734 qtdemux_parse_ftyp (GstQTDemux * qtdemux, const guint8 * buffer, gint length)
2735 {
2736   /* counts as header data */
2737   qtdemux->header_size += length;
2738
2739   /* only consider at least a sufficiently complete ftyp atom */
2740   if (length >= 20) {
2741     GstBuffer *buf;
2742
2743     qtdemux->major_brand = QT_FOURCC (buffer + 8);
2744     GST_DEBUG_OBJECT (qtdemux, "major brand: %" GST_FOURCC_FORMAT,
2745         GST_FOURCC_ARGS (qtdemux->major_brand));
2746     if (qtdemux->comp_brands)
2747       gst_buffer_unref (qtdemux->comp_brands);
2748     buf = qtdemux->comp_brands = gst_buffer_new_and_alloc (length - 16);
2749     gst_buffer_fill (buf, 0, buffer + 16, length - 16);
2750   }
2751 }
2752
2753 static void
2754 qtdemux_handle_xmp_taglist (GstQTDemux * qtdemux, GstTagList * taglist,
2755     GstTagList * xmptaglist)
2756 {
2757   /* Strip out bogus fields */
2758   if (xmptaglist) {
2759     if (gst_tag_list_get_scope (taglist) == GST_TAG_SCOPE_GLOBAL) {
2760       gst_tag_list_remove_tag (xmptaglist, GST_TAG_VIDEO_CODEC);
2761       gst_tag_list_remove_tag (xmptaglist, GST_TAG_AUDIO_CODEC);
2762     } else {
2763       gst_tag_list_remove_tag (xmptaglist, GST_TAG_CONTAINER_FORMAT);
2764     }
2765
2766     GST_DEBUG_OBJECT (qtdemux, "Found XMP tags %" GST_PTR_FORMAT, xmptaglist);
2767
2768     /* prioritize native tags using _KEEP mode */
2769     gst_tag_list_insert (taglist, xmptaglist, GST_TAG_MERGE_KEEP);
2770     gst_tag_list_unref (xmptaglist);
2771   }
2772 }
2773
2774 static void
2775 qtdemux_parse_piff (GstQTDemux * qtdemux, const guint8 * buffer, gint length,
2776     guint offset)
2777 {
2778   GstByteReader br;
2779   guint8 version;
2780   guint32 flags = 0;
2781   guint i;
2782   guint8 iv_size = 8;
2783   QtDemuxStream *stream;
2784   GstStructure *structure;
2785   QtDemuxCencSampleSetInfo *ss_info = NULL;
2786   const gchar *system_id;
2787   gboolean uses_sub_sample_encryption = FALSE;
2788   guint32 sample_count;
2789
2790   stream = QTDEMUX_FIRST_STREAM (qtdemux);
2791   if (!stream)
2792     return;
2793
2794   structure = gst_caps_get_structure (CUR_STREAM (stream)->caps, 0);
2795   if (!gst_structure_has_name (structure, "application/x-cenc")) {
2796     GST_WARNING_OBJECT (qtdemux,
2797         "Attempting PIFF box parsing on an unencrypted stream.");
2798     return;
2799   }
2800
2801   gst_structure_get (structure, GST_PROTECTION_SYSTEM_ID_CAPS_FIELD,
2802       G_TYPE_STRING, &system_id, NULL);
2803   gst_qtdemux_append_protection_system_id (qtdemux, system_id);
2804
2805   stream->protected = TRUE;
2806   stream->protection_scheme_type = FOURCC_cenc;
2807
2808   if (!stream->protection_scheme_info)
2809     stream->protection_scheme_info = g_new0 (QtDemuxCencSampleSetInfo, 1);
2810
2811   ss_info = (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
2812
2813   if (ss_info->default_properties)
2814     gst_structure_free (ss_info->default_properties);
2815
2816   ss_info->default_properties =
2817       gst_structure_new ("application/x-cenc",
2818       "iv_size", G_TYPE_UINT, iv_size, "encrypted", G_TYPE_BOOLEAN, TRUE, NULL);
2819
2820   if (ss_info->crypto_info) {
2821     GST_LOG_OBJECT (qtdemux, "unreffing existing crypto_info");
2822     g_ptr_array_free (ss_info->crypto_info, TRUE);
2823     ss_info->crypto_info = NULL;
2824   }
2825
2826   /* skip UUID */
2827   gst_byte_reader_init (&br, buffer + offset + 16, length - offset - 16);
2828
2829   if (!gst_byte_reader_get_uint8 (&br, &version)) {
2830     GST_ERROR_OBJECT (qtdemux, "Error getting box's version field");
2831     return;
2832   }
2833
2834   if (!gst_byte_reader_get_uint24_be (&br, &flags)) {
2835     GST_ERROR_OBJECT (qtdemux, "Error getting box's flags field");
2836     return;
2837   }
2838
2839   if ((flags & 0x000001)) {
2840     guint32 algorithm_id = 0;
2841     const guint8 *kid;
2842     GstBuffer *kid_buf;
2843     gboolean is_encrypted = TRUE;
2844
2845     if (!gst_byte_reader_get_uint24_le (&br, &algorithm_id)) {
2846       GST_ERROR_OBJECT (qtdemux, "Error getting box's algorithm ID field");
2847       return;
2848     }
2849
2850     algorithm_id >>= 8;
2851     if (algorithm_id == 0) {
2852       is_encrypted = FALSE;
2853     } else if (algorithm_id == 1) {
2854       /* FIXME: maybe store this in properties? */
2855       GST_DEBUG_OBJECT (qtdemux, "AES 128-bits CTR encrypted stream");
2856     } else if (algorithm_id == 2) {
2857       /* FIXME: maybe store this in properties? */
2858       GST_DEBUG_OBJECT (qtdemux, "AES 128-bits CBC encrypted stream");
2859     }
2860
2861     if (!gst_byte_reader_get_uint8 (&br, &iv_size))
2862       return;
2863
2864     if (!gst_byte_reader_get_data (&br, 16, &kid))
2865       return;
2866
2867     kid_buf = gst_buffer_new_allocate (NULL, 16, NULL);
2868     gst_buffer_fill (kid_buf, 0, kid, 16);
2869     if (ss_info->default_properties)
2870       gst_structure_free (ss_info->default_properties);
2871     ss_info->default_properties =
2872         gst_structure_new ("application/x-cenc",
2873         "iv_size", G_TYPE_UINT, iv_size,
2874         "encrypted", G_TYPE_BOOLEAN, is_encrypted,
2875         "kid", GST_TYPE_BUFFER, kid_buf, NULL);
2876     GST_DEBUG_OBJECT (qtdemux, "default sample properties: "
2877         "is_encrypted=%u, iv_size=%u", is_encrypted, iv_size);
2878     gst_buffer_unref (kid_buf);
2879   } else if ((flags & 0x000002)) {
2880     uses_sub_sample_encryption = TRUE;
2881   }
2882
2883   if (!gst_byte_reader_get_uint32_be (&br, &sample_count)) {
2884     GST_ERROR_OBJECT (qtdemux, "Error getting box's sample count field");
2885     return;
2886   }
2887
2888   ss_info->crypto_info =
2889       g_ptr_array_new_full (sample_count,
2890       (GDestroyNotify) qtdemux_gst_structure_free);
2891
2892   for (i = 0; i < sample_count; ++i) {
2893     GstStructure *properties;
2894     guint8 *data;
2895     GstBuffer *buf;
2896
2897     properties = qtdemux_get_cenc_sample_properties (qtdemux, stream, i);
2898     if (properties == NULL) {
2899       GST_ERROR_OBJECT (qtdemux, "failed to get properties for sample %u", i);
2900       qtdemux->cenc_aux_sample_count = i;
2901       return;
2902     }
2903
2904     if (!gst_byte_reader_dup_data (&br, iv_size, &data)) {
2905       GST_ERROR_OBJECT (qtdemux, "IV data not present for sample %u", i);
2906       gst_structure_free (properties);
2907       qtdemux->cenc_aux_sample_count = i;
2908       return;
2909     }
2910     buf = gst_buffer_new_wrapped (data, iv_size);
2911     gst_structure_set (properties, "iv", GST_TYPE_BUFFER, buf, NULL);
2912     gst_buffer_unref (buf);
2913
2914     if (uses_sub_sample_encryption) {
2915       guint16 n_subsamples;
2916
2917       if (!gst_byte_reader_get_uint16_be (&br, &n_subsamples)
2918           || n_subsamples == 0) {
2919         GST_ERROR_OBJECT (qtdemux,
2920             "failed to get subsample count for sample %u", i);
2921         gst_structure_free (properties);
2922         qtdemux->cenc_aux_sample_count = i;
2923         return;
2924       }
2925       GST_LOG_OBJECT (qtdemux, "subsample count: %u", n_subsamples);
2926       if (!gst_byte_reader_dup_data (&br, n_subsamples * 6, &data)) {
2927         GST_ERROR_OBJECT (qtdemux, "failed to get subsample data for sample %u",
2928             i);
2929         gst_structure_free (properties);
2930         qtdemux->cenc_aux_sample_count = i;
2931         return;
2932       }
2933       buf = gst_buffer_new_wrapped (data, n_subsamples * 6);
2934       gst_structure_set (properties,
2935           "subsample_count", G_TYPE_UINT, n_subsamples,
2936           "subsamples", GST_TYPE_BUFFER, buf, NULL);
2937       gst_buffer_unref (buf);
2938     } else {
2939       gst_structure_set (properties, "subsample_count", G_TYPE_UINT, 0, NULL);
2940     }
2941
2942     g_ptr_array_add (ss_info->crypto_info, properties);
2943   }
2944
2945   qtdemux->cenc_aux_sample_count = sample_count;
2946 }
2947
2948 static void
2949 qtdemux_parse_uuid (GstQTDemux * qtdemux, const guint8 * buffer, gint length)
2950 {
2951   static const guint8 xmp_uuid[] = { 0xBE, 0x7A, 0xCF, 0xCB,
2952     0x97, 0xA9, 0x42, 0xE8,
2953     0x9C, 0x71, 0x99, 0x94,
2954     0x91, 0xE3, 0xAF, 0xAC
2955   };
2956   static const guint8 playready_uuid[] = {
2957     0xd0, 0x8a, 0x4f, 0x18, 0x10, 0xf3, 0x4a, 0x82,
2958     0xb6, 0xc8, 0x32, 0xd8, 0xab, 0xa1, 0x83, 0xd3
2959   };
2960
2961   static const guint8 piff_sample_encryption_uuid[] = {
2962     0xa2, 0x39, 0x4f, 0x52, 0x5a, 0x9b, 0x4f, 0x14,
2963     0xa2, 0x44, 0x6c, 0x42, 0x7c, 0x64, 0x8d, 0xf4
2964   };
2965
2966   guint offset;
2967
2968   /* counts as header data */
2969   qtdemux->header_size += length;
2970
2971   offset = (QT_UINT32 (buffer) == 0) ? 16 : 8;
2972
2973   if (length <= offset + 16) {
2974     GST_DEBUG_OBJECT (qtdemux, "uuid atom is too short, skipping");
2975     return;
2976   }
2977
2978   if (memcmp (buffer + offset, xmp_uuid, 16) == 0) {
2979     GstBuffer *buf;
2980     GstTagList *taglist;
2981
2982     buf = _gst_buffer_new_wrapped ((guint8 *) buffer + offset + 16,
2983         length - offset - 16, NULL);
2984     taglist = gst_tag_list_from_xmp_buffer (buf);
2985     gst_buffer_unref (buf);
2986
2987     /* make sure we have a usable taglist */
2988     qtdemux->tag_list = gst_tag_list_make_writable (qtdemux->tag_list);
2989
2990     qtdemux_handle_xmp_taglist (qtdemux, qtdemux->tag_list, taglist);
2991
2992   } else if (memcmp (buffer + offset, playready_uuid, 16) == 0) {
2993     int len;
2994     const gunichar2 *s_utf16;
2995     char *contents;
2996
2997     len = GST_READ_UINT16_LE (buffer + offset + 0x30);
2998     s_utf16 = (const gunichar2 *) (buffer + offset + 0x32);
2999     contents = g_utf16_to_utf8 (s_utf16, len / 2, NULL, NULL, NULL);
3000     GST_ERROR_OBJECT (qtdemux, "contents: %s", contents);
3001
3002     g_free (contents);
3003
3004     GST_ELEMENT_ERROR (qtdemux, STREAM, DECRYPT,
3005         (_("Cannot play stream because it is encrypted with PlayReady DRM.")),
3006         (NULL));
3007   } else if (memcmp (buffer + offset, piff_sample_encryption_uuid, 16) == 0) {
3008     qtdemux_parse_piff (qtdemux, buffer, length, offset);
3009   } else {
3010     GST_DEBUG_OBJECT (qtdemux, "Ignoring unknown uuid: %08x-%08x-%08x-%08x",
3011         GST_READ_UINT32_LE (buffer + offset),
3012         GST_READ_UINT32_LE (buffer + offset + 4),
3013         GST_READ_UINT32_LE (buffer + offset + 8),
3014         GST_READ_UINT32_LE (buffer + offset + 12));
3015   }
3016 }
3017
3018 static void
3019 qtdemux_parse_sidx (GstQTDemux * qtdemux, const guint8 * buffer, gint length)
3020 {
3021   GstSidxParser sidx_parser;
3022   GstIsoffParserResult res;
3023   guint consumed;
3024
3025   gst_isoff_qt_sidx_parser_init (&sidx_parser);
3026
3027   res =
3028       gst_isoff_qt_sidx_parser_add_data (&sidx_parser, buffer, length,
3029       &consumed);
3030   GST_DEBUG_OBJECT (qtdemux, "sidx parse result: %d", res);
3031   if (res == GST_ISOFF_QT_PARSER_DONE) {
3032     check_update_duration (qtdemux, sidx_parser.cumulative_pts);
3033   }
3034   gst_isoff_qt_sidx_parser_clear (&sidx_parser);
3035 }
3036
3037 /* caller verifies at least 8 bytes in buf */
3038 static void
3039 extract_initial_length_and_fourcc (const guint8 * data, guint size,
3040     guint64 * plength, guint32 * pfourcc)
3041 {
3042   guint64 length;
3043   guint32 fourcc;
3044
3045   length = QT_UINT32 (data);
3046   GST_DEBUG ("length 0x%08" G_GINT64_MODIFIER "x", length);
3047   fourcc = QT_FOURCC (data + 4);
3048   GST_DEBUG ("atom type %" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (fourcc));
3049
3050   if (length == 0) {
3051     length = G_MAXUINT64;
3052   } else if (length == 1 && size >= 16) {
3053     /* this means we have an extended size, which is the 64 bit value of
3054      * the next 8 bytes */
3055     length = QT_UINT64 (data + 8);
3056     GST_DEBUG ("length 0x%08" G_GINT64_MODIFIER "x", length);
3057   }
3058
3059   if (plength)
3060     *plength = length;
3061   if (pfourcc)
3062     *pfourcc = fourcc;
3063 }
3064
3065 static gboolean
3066 qtdemux_parse_mehd (GstQTDemux * qtdemux, GstByteReader * br)
3067 {
3068   guint32 version = 0;
3069   GstClockTime duration = 0;
3070
3071   if (!gst_byte_reader_get_uint32_be (br, &version))
3072     goto failed;
3073
3074   version >>= 24;
3075   if (version == 1) {
3076     if (!gst_byte_reader_get_uint64_be (br, &duration))
3077       goto failed;
3078   } else {
3079     guint32 dur = 0;
3080
3081     if (!gst_byte_reader_get_uint32_be (br, &dur))
3082       goto failed;
3083     duration = dur;
3084   }
3085
3086   GST_INFO_OBJECT (qtdemux, "mehd duration: %" G_GUINT64_FORMAT, duration);
3087   qtdemux->duration = duration;
3088
3089   return TRUE;
3090
3091 failed:
3092   {
3093     GST_DEBUG_OBJECT (qtdemux, "parsing mehd failed");
3094     return FALSE;
3095   }
3096 }
3097
3098 static gboolean
3099 qtdemux_parse_trex (GstQTDemux * qtdemux, QtDemuxStream * stream,
3100     guint32 * ds_duration, guint32 * ds_size, guint32 * ds_flags)
3101 {
3102   if (!stream->parsed_trex && qtdemux->moov_node) {
3103     GNode *mvex, *trex;
3104     GstByteReader trex_data;
3105
3106     mvex = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_mvex);
3107     if (mvex) {
3108       trex = qtdemux_tree_get_child_by_type_full (mvex, FOURCC_trex,
3109           &trex_data);
3110       while (trex) {
3111         guint32 id = 0, sdi = 0, dur = 0, size = 0, flags = 0;
3112
3113         /* skip version/flags */
3114         if (!gst_byte_reader_skip (&trex_data, 4))
3115           goto next;
3116         if (!gst_byte_reader_get_uint32_be (&trex_data, &id))
3117           goto next;
3118         if (id != stream->track_id)
3119           goto next;
3120         if (!gst_byte_reader_get_uint32_be (&trex_data, &sdi))
3121           goto next;
3122         if (!gst_byte_reader_get_uint32_be (&trex_data, &dur))
3123           goto next;
3124         if (!gst_byte_reader_get_uint32_be (&trex_data, &size))
3125           goto next;
3126         if (!gst_byte_reader_get_uint32_be (&trex_data, &flags))
3127           goto next;
3128
3129         GST_DEBUG_OBJECT (qtdemux, "fragment defaults for stream %d; "
3130             "duration %d,  size %d, flags 0x%x", stream->track_id,
3131             dur, size, flags);
3132
3133         stream->parsed_trex = TRUE;
3134         stream->def_sample_description_index = sdi;
3135         stream->def_sample_duration = dur;
3136         stream->def_sample_size = size;
3137         stream->def_sample_flags = flags;
3138
3139       next:
3140         /* iterate all siblings */
3141         trex = qtdemux_tree_get_sibling_by_type_full (trex, FOURCC_trex,
3142             &trex_data);
3143       }
3144     }
3145   }
3146
3147   *ds_duration = stream->def_sample_duration;
3148   *ds_size = stream->def_sample_size;
3149   *ds_flags = stream->def_sample_flags;
3150
3151   /* even then, above values are better than random ... */
3152   if (G_UNLIKELY (!stream->parsed_trex)) {
3153     GST_WARNING_OBJECT (qtdemux,
3154         "failed to find fragment defaults for stream %d", stream->track_id);
3155     return FALSE;
3156   }
3157
3158   return TRUE;
3159 }
3160
3161 /* This method should be called whenever a more accurate duration might
3162  * have been found. It will update all relevant variables if/where needed
3163  */
3164 static void
3165 check_update_duration (GstQTDemux * qtdemux, GstClockTime duration)
3166 {
3167   guint i;
3168   guint64 movdur;
3169   GstClockTime prevdur;
3170   GList *iter;
3171
3172   movdur = GSTTIME_TO_QTTIME (qtdemux, duration);
3173
3174   if (movdur > qtdemux->duration) {
3175     prevdur = QTTIME_TO_GSTTIME (qtdemux, qtdemux->duration);
3176     GST_DEBUG_OBJECT (qtdemux,
3177         "Updating total duration to %" GST_TIME_FORMAT " was %" GST_TIME_FORMAT,
3178         GST_TIME_ARGS (duration), GST_TIME_ARGS (prevdur));
3179     qtdemux->duration = movdur;
3180     GST_DEBUG_OBJECT (qtdemux,
3181         "qtdemux->segment.duration: %" GST_TIME_FORMAT " .stop: %"
3182         GST_TIME_FORMAT, GST_TIME_ARGS (qtdemux->segment.duration),
3183         GST_TIME_ARGS (qtdemux->segment.stop));
3184     if (qtdemux->segment.duration == prevdur) {
3185       /* If the current segment has duration/stop identical to previous duration
3186        * update them also (because they were set at that point in time with
3187        * the wrong duration */
3188       /* We convert the value *from* the timescale version to avoid rounding errors */
3189       GstClockTime fixeddur = QTTIME_TO_GSTTIME (qtdemux, movdur);
3190       GST_DEBUG_OBJECT (qtdemux, "Updated segment.duration and segment.stop");
3191       qtdemux->segment.duration = fixeddur;
3192       qtdemux->segment.stop = fixeddur;
3193     }
3194   }
3195   for (iter = qtdemux->active_streams, i = 0; iter;
3196       iter = g_list_next (iter), i++) {
3197     QtDemuxStream *stream = QTDEMUX_STREAM (iter->data);
3198
3199     movdur = GSTTIME_TO_QTSTREAMTIME (stream, duration);
3200     if (movdur > stream->duration) {
3201       GST_DEBUG_OBJECT (qtdemux,
3202           "Updating stream #%d duration to %" GST_TIME_FORMAT, i,
3203           GST_TIME_ARGS (duration));
3204       stream->duration = movdur;
3205       /* internal duration tracking state has been updated above, so */
3206       /* preserve an open-ended dummy segment rather than repeatedly updating
3207        * it and spamming downstream accordingly with segment events */
3208       if (stream->dummy_segment &&
3209           GST_CLOCK_TIME_IS_VALID (stream->segments[0].duration)) {
3210         /* Update all dummy values to new duration */
3211         stream->segments[0].stop_time = duration;
3212         stream->segments[0].duration = duration;
3213         stream->segments[0].media_stop = duration;
3214
3215         /* let downstream know we possibly have a new stop time */
3216         if (stream->segment_index != -1) {
3217           GstClockTime pos;
3218
3219           if (qtdemux->segment.rate >= 0) {
3220             pos = stream->segment.start;
3221           } else {
3222             pos = stream->segment.stop;
3223           }
3224
3225           gst_qtdemux_stream_update_segment (qtdemux, stream,
3226               stream->segment_index, pos, NULL, NULL);
3227         }
3228       }
3229     }
3230   }
3231 }
3232
3233 static gboolean
3234 qtdemux_parse_trun (GstQTDemux * qtdemux, GstByteReader * trun,
3235     QtDemuxStream * stream, guint32 d_sample_duration, guint32 d_sample_size,
3236     guint32 d_sample_flags, gint64 moof_offset, gint64 moof_length,
3237     gint64 * base_offset, gint64 * running_offset, gint64 decode_ts,
3238     gboolean has_tfdt)
3239 {
3240   GstClockTime gst_ts = GST_CLOCK_TIME_NONE;
3241   guint64 timestamp;
3242   gint32 data_offset = 0;
3243   guint32 flags = 0, first_flags = 0, samples_count = 0;
3244   gint i;
3245   guint8 *data;
3246   guint entry_size, dur_offset, size_offset, flags_offset = 0, ct_offset = 0;
3247   QtDemuxSample *sample;
3248   gboolean ismv = FALSE;
3249   gint64 initial_offset;
3250
3251   GST_LOG_OBJECT (qtdemux, "parsing trun track-id %d; "
3252       "default dur %d, size %d, flags 0x%x, base offset %" G_GINT64_FORMAT ", "
3253       "decode ts %" G_GINT64_FORMAT, stream->track_id, d_sample_duration,
3254       d_sample_size, d_sample_flags, *base_offset, decode_ts);
3255
3256   if (stream->pending_seek && moof_offset < stream->pending_seek->moof_offset) {
3257     GST_INFO_OBJECT (stream->pad, "skipping trun before seek target fragment");
3258     return TRUE;
3259   }
3260
3261   /* presence of stss or not can't really tell us much,
3262    * and flags and so on tend to be marginally reliable in these files */
3263   if (stream->subtype == FOURCC_soun) {
3264     GST_DEBUG_OBJECT (qtdemux,
3265         "sound track in fragmented file; marking all keyframes");
3266     stream->all_keyframe = TRUE;
3267   }
3268
3269   if (!gst_byte_reader_skip (trun, 1) ||
3270       !gst_byte_reader_get_uint24_be (trun, &flags))
3271     goto fail;
3272
3273   if (!gst_byte_reader_get_uint32_be (trun, &samples_count))
3274     goto fail;
3275
3276   if (flags & TR_DATA_OFFSET) {
3277     /* note this is really signed */
3278     if (!gst_byte_reader_get_int32_be (trun, &data_offset))
3279       goto fail;
3280     GST_LOG_OBJECT (qtdemux, "trun data offset %d", data_offset);
3281     /* default base offset = first byte of moof */
3282     if (*base_offset == -1) {
3283       GST_LOG_OBJECT (qtdemux, "base_offset at moof");
3284       *base_offset = moof_offset;
3285     }
3286     *running_offset = *base_offset + data_offset;
3287   } else {
3288     /* if no offset at all, that would mean data starts at moof start,
3289      * which is a bit wrong and is ismv crappy way, so compensate
3290      * assuming data is in mdat following moof */
3291     if (*base_offset == -1) {
3292       *base_offset = moof_offset + moof_length + 8;
3293       GST_LOG_OBJECT (qtdemux, "base_offset assumed in mdat after moof");
3294       ismv = TRUE;
3295     }
3296     if (*running_offset == -1)
3297       *running_offset = *base_offset;
3298   }
3299
3300   GST_LOG_OBJECT (qtdemux, "running offset now %" G_GINT64_FORMAT,
3301       *running_offset);
3302   GST_LOG_OBJECT (qtdemux, "trun offset %d, flags 0x%x, entries %d",
3303       data_offset, flags, samples_count);
3304
3305   if (flags & TR_FIRST_SAMPLE_FLAGS) {
3306     if (G_UNLIKELY (flags & TR_SAMPLE_FLAGS)) {
3307       GST_DEBUG_OBJECT (qtdemux,
3308           "invalid flags; SAMPLE and FIRST_SAMPLE present, discarding latter");
3309       flags ^= TR_FIRST_SAMPLE_FLAGS;
3310     } else {
3311       if (!gst_byte_reader_get_uint32_be (trun, &first_flags))
3312         goto fail;
3313       GST_LOG_OBJECT (qtdemux, "first flags: 0x%x", first_flags);
3314     }
3315   }
3316
3317   /* FIXME ? spec says other bits should also be checked to determine
3318    * entry size (and prefix size for that matter) */
3319   entry_size = 0;
3320   dur_offset = size_offset = 0;
3321   if (flags & TR_SAMPLE_DURATION) {
3322     GST_LOG_OBJECT (qtdemux, "entry duration present");
3323     dur_offset = entry_size;
3324     entry_size += 4;
3325   }
3326   if (flags & TR_SAMPLE_SIZE) {
3327     GST_LOG_OBJECT (qtdemux, "entry size present");
3328     size_offset = entry_size;
3329     entry_size += 4;
3330   }
3331   if (flags & TR_SAMPLE_FLAGS) {
3332     GST_LOG_OBJECT (qtdemux, "entry flags present");
3333     flags_offset = entry_size;
3334     entry_size += 4;
3335   }
3336   if (flags & TR_COMPOSITION_TIME_OFFSETS) {
3337     GST_LOG_OBJECT (qtdemux, "entry ct offset present");
3338     ct_offset = entry_size;
3339     entry_size += 4;
3340   }
3341
3342   if (!qt_atom_parser_has_chunks (trun, samples_count, entry_size))
3343     goto fail;
3344   data = (guint8 *) gst_byte_reader_peek_data_unchecked (trun);
3345
3346   if (stream->n_samples + samples_count >=
3347       QTDEMUX_MAX_SAMPLE_INDEX_SIZE / sizeof (QtDemuxSample))
3348     goto index_too_big;
3349
3350   GST_DEBUG_OBJECT (qtdemux, "allocating n_samples %u * %u (%.2f MB)",
3351       stream->n_samples + samples_count, (guint) sizeof (QtDemuxSample),
3352       (stream->n_samples + samples_count) *
3353       sizeof (QtDemuxSample) / (1024.0 * 1024.0));
3354
3355   /* create a new array of samples if it's the first sample parsed */
3356   if (stream->n_samples == 0) {
3357     g_assert (stream->samples == NULL);
3358     stream->samples = g_try_new0 (QtDemuxSample, samples_count);
3359     /* or try to reallocate it with space enough to insert the new samples */
3360   } else
3361     stream->samples = g_try_renew (QtDemuxSample, stream->samples,
3362         stream->n_samples + samples_count);
3363   if (stream->samples == NULL)
3364     goto out_of_memory;
3365
3366   if (qtdemux->fragment_start != -1) {
3367     timestamp = GSTTIME_TO_QTSTREAMTIME (stream, qtdemux->fragment_start);
3368     qtdemux->fragment_start = -1;
3369   } else {
3370     if (stream->n_samples == 0) {
3371       if (decode_ts > 0) {
3372         timestamp = decode_ts;
3373       } else if (stream->pending_seek != NULL) {
3374         /* if we don't have a timestamp from a tfdt box, we'll use the one
3375          * from the mfra seek table */
3376         GST_INFO_OBJECT (stream->pad, "pending seek ts = %" GST_TIME_FORMAT,
3377             GST_TIME_ARGS (stream->pending_seek->ts));
3378
3379         /* FIXME: this is not fully correct, the timestamp refers to the random
3380          * access sample refered to in the tfra entry, which may not necessarily
3381          * be the first sample in the tfrag/trun (but hopefully/usually is) */
3382         timestamp = GSTTIME_TO_QTSTREAMTIME (stream, stream->pending_seek->ts);
3383       } else {
3384         timestamp = 0;
3385       }
3386
3387       gst_ts = QTSTREAMTIME_TO_GSTTIME (stream, timestamp);
3388       GST_INFO_OBJECT (stream->pad, "first sample ts %" GST_TIME_FORMAT,
3389           GST_TIME_ARGS (gst_ts));
3390     } else {
3391       /* subsequent fragments extend stream */
3392       timestamp =
3393           stream->samples[stream->n_samples - 1].timestamp +
3394           stream->samples[stream->n_samples - 1].duration;
3395
3396       /* If this is a GST_FORMAT_BYTES stream and there's a significant
3397        * difference (1 sec.) between decode_ts and timestamp, prefer the
3398        * former */
3399       if (has_tfdt && !qtdemux->upstream_format_is_time
3400           && ABSDIFF (decode_ts, timestamp) >
3401           MAX (stream->duration_last_moof / 2,
3402               GSTTIME_TO_QTSTREAMTIME (stream, GST_SECOND))) {
3403         GST_INFO_OBJECT (qtdemux,
3404             "decode_ts (%" GST_TIME_FORMAT ") and timestamp (%" GST_TIME_FORMAT
3405             ") are significantly different (more than %" GST_TIME_FORMAT
3406             "), using decode_ts",
3407             GST_TIME_ARGS (QTSTREAMTIME_TO_GSTTIME (stream, decode_ts)),
3408             GST_TIME_ARGS (QTSTREAMTIME_TO_GSTTIME (stream, timestamp)),
3409             GST_TIME_ARGS (QTSTREAMTIME_TO_GSTTIME (stream,
3410                     MAX (stream->duration_last_moof / 2,
3411                         GSTTIME_TO_QTSTREAMTIME (stream, GST_SECOND)))));
3412         timestamp = decode_ts;
3413       }
3414
3415       gst_ts = QTSTREAMTIME_TO_GSTTIME (stream, timestamp);
3416       GST_INFO_OBJECT (qtdemux, "first sample ts %" GST_TIME_FORMAT
3417           " (extends previous samples)", GST_TIME_ARGS (gst_ts));
3418     }
3419   }
3420
3421   initial_offset = *running_offset;
3422
3423   sample = stream->samples + stream->n_samples;
3424   for (i = 0; i < samples_count; i++) {
3425     guint32 dur, size, sflags, ct;
3426
3427     /* first read sample data */
3428     if (flags & TR_SAMPLE_DURATION) {
3429       dur = QT_UINT32 (data + dur_offset);
3430     } else {
3431       dur = d_sample_duration;
3432     }
3433     if (flags & TR_SAMPLE_SIZE) {
3434       size = QT_UINT32 (data + size_offset);
3435     } else {
3436       size = d_sample_size;
3437     }
3438     if (flags & TR_FIRST_SAMPLE_FLAGS) {
3439       if (i == 0) {
3440         sflags = first_flags;
3441       } else {
3442         sflags = d_sample_flags;
3443       }
3444     } else if (flags & TR_SAMPLE_FLAGS) {
3445       sflags = QT_UINT32 (data + flags_offset);
3446     } else {
3447       sflags = d_sample_flags;
3448     }
3449     if (flags & TR_COMPOSITION_TIME_OFFSETS) {
3450       ct = QT_UINT32 (data + ct_offset);
3451     } else {
3452       ct = 0;
3453     }
3454     data += entry_size;
3455
3456     /* fill the sample information */
3457     sample->offset = *running_offset;
3458     sample->pts_offset = ct;
3459     sample->size = size;
3460     sample->timestamp = timestamp;
3461     sample->duration = dur;
3462     /* sample-is-difference-sample */
3463     /* ismv seems to use 0x40 for keyframe, 0xc0 for non-keyframe,
3464      * now idea how it relates to bitfield other than massive LE/BE confusion */
3465     sample->keyframe = ismv ? ((sflags & 0xff) == 0x40) : !(sflags & 0x10000);
3466     *running_offset += size;
3467     timestamp += dur;
3468     stream->duration_moof += dur;
3469     sample++;
3470   }
3471
3472   /* Update total duration if needed */
3473   check_update_duration (qtdemux, QTSTREAMTIME_TO_GSTTIME (stream, timestamp));
3474
3475   /* Pre-emptively figure out size of mdat based on trun information.
3476    * If the [mdat] atom is effectivelly read, it will be replaced by the actual
3477    * size, else we will still be able to use this when dealing with gap'ed
3478    * input */
3479   qtdemux->mdatleft = *running_offset - initial_offset;
3480   qtdemux->mdatoffset = initial_offset;
3481   qtdemux->mdatsize = qtdemux->mdatleft;
3482
3483   stream->n_samples += samples_count;
3484   stream->n_samples_moof += samples_count;
3485
3486   if (stream->pending_seek != NULL)
3487     stream->pending_seek = NULL;
3488
3489   return TRUE;
3490
3491 fail:
3492   {
3493     GST_WARNING_OBJECT (qtdemux, "failed to parse trun");
3494     return FALSE;
3495   }
3496 out_of_memory:
3497   {
3498     GST_WARNING_OBJECT (qtdemux, "failed to allocate %d samples",
3499         stream->n_samples);
3500     return FALSE;
3501   }
3502 index_too_big:
3503   {
3504     GST_WARNING_OBJECT (qtdemux, "not allocating index of %d samples, would "
3505         "be larger than %uMB (broken file?)", stream->n_samples,
3506         QTDEMUX_MAX_SAMPLE_INDEX_SIZE >> 20);
3507     return FALSE;
3508   }
3509 }
3510
3511 /* find stream with @id */
3512 static inline QtDemuxStream *
3513 qtdemux_find_stream (GstQTDemux * qtdemux, guint32 id)
3514 {
3515   QtDemuxStream *stream;
3516   GList *iter;
3517
3518   /* check */
3519   if (G_UNLIKELY (!id)) {
3520     GST_DEBUG_OBJECT (qtdemux, "invalid track id 0");
3521     return NULL;
3522   }
3523
3524   for (iter = qtdemux->active_streams; iter; iter = g_list_next (iter)) {
3525     stream = QTDEMUX_STREAM (iter->data);
3526     if (stream->track_id == id)
3527       return stream;
3528   }
3529   if (qtdemux->mss_mode) {
3530     /* mss should have only 1 stream anyway */
3531     return QTDEMUX_FIRST_STREAM (qtdemux);
3532   }
3533
3534   return NULL;
3535 }
3536
3537 static gboolean
3538 qtdemux_parse_mfhd (GstQTDemux * qtdemux, GstByteReader * mfhd,
3539     guint32 * fragment_number)
3540 {
3541   if (!gst_byte_reader_skip (mfhd, 4))
3542     goto fail;
3543   if (!gst_byte_reader_get_uint32_be (mfhd, fragment_number))
3544     goto fail;
3545   return TRUE;
3546 fail:
3547   {
3548     GST_WARNING_OBJECT (qtdemux, "Failed to parse mfhd atom");
3549     return FALSE;
3550   }
3551 }
3552
3553 static gboolean
3554 qtdemux_parse_tfhd (GstQTDemux * qtdemux, GstByteReader * tfhd,
3555     QtDemuxStream ** stream, guint32 * default_sample_duration,
3556     guint32 * default_sample_size, guint32 * default_sample_flags,
3557     gint64 * base_offset)
3558 {
3559   guint32 flags = 0;
3560   guint32 track_id = 0;
3561
3562   if (!gst_byte_reader_skip (tfhd, 1) ||
3563       !gst_byte_reader_get_uint24_be (tfhd, &flags))
3564     goto invalid_track;
3565
3566   if (!gst_byte_reader_get_uint32_be (tfhd, &track_id))
3567     goto invalid_track;
3568
3569   *stream = qtdemux_find_stream (qtdemux, track_id);
3570   if (G_UNLIKELY (!*stream))
3571     goto unknown_stream;
3572
3573   if (flags & TF_DEFAULT_BASE_IS_MOOF)
3574     *base_offset = qtdemux->moof_offset;
3575
3576   if (flags & TF_BASE_DATA_OFFSET)
3577     if (!gst_byte_reader_get_uint64_be (tfhd, (guint64 *) base_offset))
3578       goto invalid_track;
3579
3580   /* obtain stream defaults */
3581   qtdemux_parse_trex (qtdemux, *stream,
3582       default_sample_duration, default_sample_size, default_sample_flags);
3583
3584   (*stream)->stsd_sample_description_id =
3585       (*stream)->def_sample_description_index - 1;
3586
3587   if (flags & TF_SAMPLE_DESCRIPTION_INDEX) {
3588     guint32 sample_description_index;
3589     if (!gst_byte_reader_get_uint32_be (tfhd, &sample_description_index))
3590       goto invalid_track;
3591     (*stream)->stsd_sample_description_id = sample_description_index - 1;
3592   }
3593
3594   if (qtdemux->mss_mode) {
3595     /* mss has no stsd entry */
3596     (*stream)->stsd_sample_description_id = 0;
3597   }
3598
3599   if (flags & TF_DEFAULT_SAMPLE_DURATION)
3600     if (!gst_byte_reader_get_uint32_be (tfhd, default_sample_duration))
3601       goto invalid_track;
3602
3603   if (flags & TF_DEFAULT_SAMPLE_SIZE)
3604     if (!gst_byte_reader_get_uint32_be (tfhd, default_sample_size))
3605       goto invalid_track;
3606
3607   if (flags & TF_DEFAULT_SAMPLE_FLAGS)
3608     if (!gst_byte_reader_get_uint32_be (tfhd, default_sample_flags))
3609       goto invalid_track;
3610
3611   return TRUE;
3612
3613 invalid_track:
3614   {
3615     GST_WARNING_OBJECT (qtdemux, "invalid track fragment header");
3616     return FALSE;
3617   }
3618 unknown_stream:
3619   {
3620     GST_DEBUG_OBJECT (qtdemux, "unknown stream in tfhd");
3621     return TRUE;
3622   }
3623 }
3624
3625 static gboolean
3626 qtdemux_parse_tfdt (GstQTDemux * qtdemux, GstByteReader * br,
3627     guint64 * decode_time)
3628 {
3629   guint32 version = 0;
3630
3631   if (!gst_byte_reader_get_uint32_be (br, &version))
3632     return FALSE;
3633
3634   version >>= 24;
3635   if (version == 1) {
3636     if (!gst_byte_reader_get_uint64_be (br, decode_time))
3637       goto failed;
3638   } else {
3639     guint32 dec_time = 0;
3640     if (!gst_byte_reader_get_uint32_be (br, &dec_time))
3641       goto failed;
3642     *decode_time = dec_time;
3643   }
3644
3645   GST_INFO_OBJECT (qtdemux, "Track fragment decode time: %" G_GUINT64_FORMAT,
3646       *decode_time);
3647
3648   return TRUE;
3649
3650 failed:
3651   {
3652     GST_DEBUG_OBJECT (qtdemux, "parsing tfdt failed");
3653     return FALSE;
3654   }
3655 }
3656
3657 /* Returns a pointer to a GstStructure containing the properties of
3658  * the stream sample identified by @sample_index. The caller must unref
3659  * the returned object after use. Returns NULL if unsuccessful. */
3660 static GstStructure *
3661 qtdemux_get_cenc_sample_properties (GstQTDemux * qtdemux,
3662     QtDemuxStream * stream, guint sample_index)
3663 {
3664   QtDemuxCencSampleSetInfo *info = NULL;
3665
3666   g_return_val_if_fail (stream != NULL, NULL);
3667   g_return_val_if_fail (stream->protected, NULL);
3668   g_return_val_if_fail (stream->protection_scheme_info != NULL, NULL);
3669
3670   info = (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
3671
3672   /* Currently, cenc properties for groups of samples are not supported, so
3673    * simply return a copy of the default sample properties */
3674   return gst_structure_copy (info->default_properties);
3675 }
3676
3677 /* Parses the sizes of sample auxiliary information contained within a stream,
3678  * as given in a saiz box. Returns array of sample_count guint8 size values,
3679  * or NULL on failure */
3680 static guint8 *
3681 qtdemux_parse_saiz (GstQTDemux * qtdemux, QtDemuxStream * stream,
3682     GstByteReader * br, guint32 * sample_count)
3683 {
3684   guint32 flags = 0;
3685   guint8 *info_sizes;
3686   guint8 default_info_size;
3687
3688   g_return_val_if_fail (qtdemux != NULL, NULL);
3689   g_return_val_if_fail (stream != NULL, NULL);
3690   g_return_val_if_fail (br != NULL, NULL);
3691   g_return_val_if_fail (sample_count != NULL, NULL);
3692
3693   if (!gst_byte_reader_get_uint32_be (br, &flags))
3694     return NULL;
3695
3696   if (flags & 0x1) {
3697     /* aux_info_type and aux_info_type_parameter are ignored */
3698     if (!gst_byte_reader_skip (br, 8))
3699       return NULL;
3700   }
3701
3702   if (!gst_byte_reader_get_uint8 (br, &default_info_size))
3703     return NULL;
3704   GST_DEBUG_OBJECT (qtdemux, "default_info_size: %u", default_info_size);
3705
3706   if (!gst_byte_reader_get_uint32_be (br, sample_count))
3707     return NULL;
3708   GST_DEBUG_OBJECT (qtdemux, "sample_count: %u", *sample_count);
3709
3710
3711   if (default_info_size == 0) {
3712     if (!gst_byte_reader_dup_data (br, *sample_count, &info_sizes)) {
3713       return NULL;
3714     }
3715   } else {
3716     info_sizes = g_new (guint8, *sample_count);
3717     memset (info_sizes, default_info_size, *sample_count);
3718   }
3719
3720   return info_sizes;
3721 }
3722
3723 /* Parses the offset of sample auxiliary information contained within a stream,
3724  * as given in a saio box. Returns TRUE if successful; FALSE otherwise. */
3725 static gboolean
3726 qtdemux_parse_saio (GstQTDemux * qtdemux, QtDemuxStream * stream,
3727     GstByteReader * br, guint32 * info_type, guint32 * info_type_parameter,
3728     guint64 * offset)
3729 {
3730   guint8 version = 0;
3731   guint32 flags = 0;
3732   guint32 aux_info_type = 0;
3733   guint32 aux_info_type_parameter = 0;
3734   guint32 entry_count;
3735   guint32 off_32;
3736   guint64 off_64;
3737   const guint8 *aux_info_type_data = NULL;
3738
3739   g_return_val_if_fail (qtdemux != NULL, FALSE);
3740   g_return_val_if_fail (stream != NULL, FALSE);
3741   g_return_val_if_fail (br != NULL, FALSE);
3742   g_return_val_if_fail (offset != NULL, FALSE);
3743
3744   if (!gst_byte_reader_get_uint8 (br, &version))
3745     return FALSE;
3746
3747   if (!gst_byte_reader_get_uint24_be (br, &flags))
3748     return FALSE;
3749
3750   if (flags & 0x1) {
3751
3752     if (!gst_byte_reader_get_data (br, 4, &aux_info_type_data))
3753       return FALSE;
3754     aux_info_type = QT_FOURCC (aux_info_type_data);
3755
3756     if (!gst_byte_reader_get_uint32_be (br, &aux_info_type_parameter))
3757       return FALSE;
3758   } else if (stream->protected) {
3759     aux_info_type = stream->protection_scheme_type;
3760   } else {
3761     aux_info_type = CUR_STREAM (stream)->fourcc;
3762   }
3763
3764   if (info_type)
3765     *info_type = aux_info_type;
3766   if (info_type_parameter)
3767     *info_type_parameter = aux_info_type_parameter;
3768
3769   GST_DEBUG_OBJECT (qtdemux, "aux_info_type: '%" GST_FOURCC_FORMAT "', "
3770       "aux_info_type_parameter:  %#06x",
3771       GST_FOURCC_ARGS (aux_info_type), aux_info_type_parameter);
3772
3773   if (!gst_byte_reader_get_uint32_be (br, &entry_count))
3774     return FALSE;
3775
3776   if (entry_count != 1) {
3777     GST_ERROR_OBJECT (qtdemux, "multiple offsets are not supported");
3778     return FALSE;
3779   }
3780
3781   if (version == 0) {
3782     if (!gst_byte_reader_get_uint32_be (br, &off_32))
3783       return FALSE;
3784     *offset = (guint64) off_32;
3785   } else {
3786     if (!gst_byte_reader_get_uint64_be (br, &off_64))
3787       return FALSE;
3788     *offset = off_64;
3789   }
3790
3791   GST_DEBUG_OBJECT (qtdemux, "offset: %" G_GUINT64_FORMAT, *offset);
3792   return TRUE;
3793 }
3794
3795 static void
3796 qtdemux_gst_structure_free (GstStructure * gststructure)
3797 {
3798   if (gststructure) {
3799     gst_structure_free (gststructure);
3800   }
3801 }
3802
3803 /* Parses auxiliary information relating to samples protected using Common
3804  * Encryption (cenc); the format of this information is defined in
3805  * ISO/IEC 23001-7. Returns TRUE if successful; FALSE otherwise. */
3806 static gboolean
3807 qtdemux_parse_cenc_aux_info (GstQTDemux * qtdemux, QtDemuxStream * stream,
3808     GstByteReader * br, guint8 * info_sizes, guint32 sample_count)
3809 {
3810   QtDemuxCencSampleSetInfo *ss_info = NULL;
3811   guint8 size;
3812   gint i;
3813   GPtrArray *old_crypto_info = NULL;
3814   guint old_entries = 0;
3815
3816   g_return_val_if_fail (qtdemux != NULL, FALSE);
3817   g_return_val_if_fail (stream != NULL, FALSE);
3818   g_return_val_if_fail (br != NULL, FALSE);
3819   g_return_val_if_fail (stream->protected, FALSE);
3820   g_return_val_if_fail (stream->protection_scheme_info != NULL, FALSE);
3821
3822   ss_info = (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
3823
3824   if (ss_info->crypto_info) {
3825     old_crypto_info = ss_info->crypto_info;
3826     /* Count number of non-null entries remaining at the tail end */
3827     for (i = old_crypto_info->len - 1; i >= 0; i--) {
3828       if (g_ptr_array_index (old_crypto_info, i) == NULL)
3829         break;
3830       old_entries++;
3831     }
3832   }
3833
3834   ss_info->crypto_info =
3835       g_ptr_array_new_full (sample_count + old_entries,
3836       (GDestroyNotify) qtdemux_gst_structure_free);
3837
3838   /* We preserve old entries because we parse the next moof in advance
3839    * of consuming all samples from the previous moof, and otherwise
3840    * we'd discard the corresponding crypto info for the samples
3841    * from the previous fragment. */
3842   if (old_entries) {
3843     GST_DEBUG_OBJECT (qtdemux, "Preserving %d old crypto info entries",
3844         old_entries);
3845     for (i = old_crypto_info->len - old_entries; i < old_crypto_info->len; i++) {
3846       g_ptr_array_add (ss_info->crypto_info, g_ptr_array_index (old_crypto_info,
3847               i));
3848       g_ptr_array_index (old_crypto_info, i) = NULL;
3849     }
3850   }
3851
3852   if (old_crypto_info) {
3853     /* Everything now belongs to the new array */
3854     g_ptr_array_free (old_crypto_info, TRUE);
3855   }
3856
3857   for (i = 0; i < sample_count; ++i) {
3858     GstStructure *properties;
3859     guint16 n_subsamples = 0;
3860     guint8 *data;
3861     guint iv_size;
3862     GstBuffer *buf;
3863
3864     properties = qtdemux_get_cenc_sample_properties (qtdemux, stream, i);
3865     if (properties == NULL) {
3866       GST_ERROR_OBJECT (qtdemux, "failed to get properties for sample %u", i);
3867       return FALSE;
3868     }
3869     if (!gst_structure_get_uint (properties, "iv_size", &iv_size)) {
3870       GST_ERROR_OBJECT (qtdemux, "failed to get iv_size for sample %u", i);
3871       gst_structure_free (properties);
3872       return FALSE;
3873     }
3874     if (!gst_byte_reader_dup_data (br, iv_size, &data)) {
3875       GST_ERROR_OBJECT (qtdemux, "failed to get IV for sample %u", i);
3876       gst_structure_free (properties);
3877       return FALSE;
3878     }
3879     buf = gst_buffer_new_wrapped (data, iv_size);
3880     gst_structure_set (properties, "iv", GST_TYPE_BUFFER, buf, NULL);
3881     gst_buffer_unref (buf);
3882     size = info_sizes[i];
3883     if (size > iv_size) {
3884       if (!gst_byte_reader_get_uint16_be (br, &n_subsamples)
3885           || !(n_subsamples > 0)) {
3886         gst_structure_free (properties);
3887         GST_ERROR_OBJECT (qtdemux,
3888             "failed to get subsample count for sample %u", i);
3889         return FALSE;
3890       }
3891       GST_LOG_OBJECT (qtdemux, "subsample count: %u", n_subsamples);
3892       if (!gst_byte_reader_dup_data (br, n_subsamples * 6, &data)) {
3893         GST_ERROR_OBJECT (qtdemux, "failed to get subsample data for sample %u",
3894             i);
3895         gst_structure_free (properties);
3896         return FALSE;
3897       }
3898       buf = gst_buffer_new_wrapped (data, n_subsamples * 6);
3899       if (!buf) {
3900         gst_structure_free (properties);
3901         return FALSE;
3902       }
3903       gst_structure_set (properties,
3904           "subsample_count", G_TYPE_UINT, n_subsamples,
3905           "subsamples", GST_TYPE_BUFFER, buf, NULL);
3906       gst_buffer_unref (buf);
3907     } else {
3908       gst_structure_set (properties, "subsample_count", G_TYPE_UINT, 0, NULL);
3909     }
3910     g_ptr_array_add (ss_info->crypto_info, properties);
3911   }
3912   return TRUE;
3913 }
3914
3915 /* Converts a UUID in raw byte form to a string representation, as defined in
3916  * RFC 4122. The caller takes ownership of the returned string and is
3917  * responsible for freeing it after use. */
3918 static gchar *
3919 qtdemux_uuid_bytes_to_string (gconstpointer uuid_bytes)
3920 {
3921   const guint8 *uuid = (const guint8 *) uuid_bytes;
3922
3923   return g_strdup_printf ("%02x%02x%02x%02x-%02x%02x-%02x%02x-"
3924       "%02x%02x-%02x%02x%02x%02x%02x%02x",
3925       uuid[0], uuid[1], uuid[2], uuid[3],
3926       uuid[4], uuid[5], uuid[6], uuid[7],
3927       uuid[8], uuid[9], uuid[10], uuid[11],
3928       uuid[12], uuid[13], uuid[14], uuid[15]);
3929 }
3930
3931 /* Parses a Protection System Specific Header box (pssh), as defined in the
3932  * Common Encryption (cenc) standard (ISO/IEC 23001-7), which contains
3933  * information needed by a specific content protection system in order to
3934  * decrypt cenc-protected tracks. Returns TRUE if successful; FALSE
3935  * otherwise. */
3936 static gboolean
3937 qtdemux_parse_pssh (GstQTDemux * qtdemux, GNode * node)
3938 {
3939   gchar *sysid_string;
3940   guint32 pssh_size = QT_UINT32 (node->data);
3941   GstBuffer *pssh = NULL;
3942   GstEvent *event = NULL;
3943   guint32 parent_box_type;
3944   GList *iter;
3945
3946   if (G_UNLIKELY (pssh_size < 32U)) {
3947     GST_ERROR_OBJECT (qtdemux, "invalid box size");
3948     return FALSE;
3949   }
3950
3951   sysid_string =
3952       qtdemux_uuid_bytes_to_string ((const guint8 *) node->data + 12);
3953
3954   gst_qtdemux_append_protection_system_id (qtdemux, sysid_string);
3955
3956   pssh = gst_buffer_new_wrapped (g_memdup (node->data, pssh_size), pssh_size);
3957   GST_LOG_OBJECT (qtdemux, "cenc pssh size: %" G_GSIZE_FORMAT,
3958       gst_buffer_get_size (pssh));
3959
3960   parent_box_type = QT_FOURCC ((const guint8 *) node->parent->data + 4);
3961
3962   /* Push an event containing the pssh box onto the queues of all streams. */
3963   event = gst_event_new_protection (sysid_string, pssh,
3964       (parent_box_type == FOURCC_moov) ? "isobmff/moov" : "isobmff/moof");
3965   for (iter = qtdemux->active_streams; iter; iter = g_list_next (iter)) {
3966     QtDemuxStream *stream = QTDEMUX_STREAM (iter->data);
3967     GST_TRACE_OBJECT (qtdemux,
3968         "adding protection event for stream %s and system %s",
3969         stream->stream_id, sysid_string);
3970     g_queue_push_tail (&stream->protection_scheme_event_queue,
3971         gst_event_ref (event));
3972   }
3973   g_free (sysid_string);
3974   gst_event_unref (event);
3975   gst_buffer_unref (pssh);
3976   return TRUE;
3977 }
3978
3979 static gboolean
3980 qtdemux_parse_moof (GstQTDemux * qtdemux, const guint8 * buffer, guint length,
3981     guint64 moof_offset, QtDemuxStream * stream)
3982 {
3983   GNode *moof_node, *traf_node, *tfhd_node, *trun_node, *tfdt_node, *mfhd_node;
3984   GNode *uuid_node;
3985   GstByteReader mfhd_data, trun_data, tfhd_data, tfdt_data;
3986   GNode *saiz_node, *saio_node, *pssh_node;
3987   GstByteReader saiz_data, saio_data;
3988   guint32 ds_size = 0, ds_duration = 0, ds_flags = 0;
3989   gint64 base_offset, running_offset;
3990   guint32 frag_num;
3991
3992   /* NOTE @stream ignored */
3993
3994   moof_node = g_node_new ((guint8 *) buffer);
3995   qtdemux_parse_node (qtdemux, moof_node, buffer, length);
3996   qtdemux_node_dump (qtdemux, moof_node);
3997
3998   /* Get fragment number from mfhd and check it's valid */
3999   mfhd_node =
4000       qtdemux_tree_get_child_by_type_full (moof_node, FOURCC_mfhd, &mfhd_data);
4001   if (mfhd_node == NULL)
4002     goto missing_mfhd;
4003   if (!qtdemux_parse_mfhd (qtdemux, &mfhd_data, &frag_num))
4004     goto fail;
4005   GST_DEBUG_OBJECT (qtdemux, "Fragment #%d", frag_num);
4006
4007   /* unknown base_offset to start with */
4008   base_offset = running_offset = -1;
4009   traf_node = qtdemux_tree_get_child_by_type (moof_node, FOURCC_traf);
4010   while (traf_node) {
4011     guint64 decode_time = 0;
4012
4013     /* Fragment Header node */
4014     tfhd_node =
4015         qtdemux_tree_get_child_by_type_full (traf_node, FOURCC_tfhd,
4016         &tfhd_data);
4017     if (!tfhd_node)
4018       goto missing_tfhd;
4019     if (!qtdemux_parse_tfhd (qtdemux, &tfhd_data, &stream, &ds_duration,
4020             &ds_size, &ds_flags, &base_offset))
4021       goto missing_tfhd;
4022
4023     /* The following code assumes at most a single set of sample auxiliary
4024      * data in the fragment (consisting of a saiz box and a corresponding saio
4025      * box); in theory, however, there could be multiple sets of sample
4026      * auxiliary data in a fragment. */
4027     saiz_node =
4028         qtdemux_tree_get_child_by_type_full (traf_node, FOURCC_saiz,
4029         &saiz_data);
4030     if (saiz_node) {
4031       guint32 info_type = 0;
4032       guint64 offset = 0;
4033       guint32 info_type_parameter = 0;
4034
4035       g_free (qtdemux->cenc_aux_info_sizes);
4036
4037       qtdemux->cenc_aux_info_sizes =
4038           qtdemux_parse_saiz (qtdemux, stream, &saiz_data,
4039           &qtdemux->cenc_aux_sample_count);
4040       if (qtdemux->cenc_aux_info_sizes == NULL) {
4041         GST_ERROR_OBJECT (qtdemux, "failed to parse saiz box");
4042         goto fail;
4043       }
4044       saio_node =
4045           qtdemux_tree_get_child_by_type_full (traf_node, FOURCC_saio,
4046           &saio_data);
4047       if (!saio_node) {
4048         GST_ERROR_OBJECT (qtdemux, "saiz box without a corresponding saio box");
4049         g_free (qtdemux->cenc_aux_info_sizes);
4050         qtdemux->cenc_aux_info_sizes = NULL;
4051         goto fail;
4052       }
4053
4054       if (G_UNLIKELY (!qtdemux_parse_saio (qtdemux, stream, &saio_data,
4055                   &info_type, &info_type_parameter, &offset))) {
4056         GST_ERROR_OBJECT (qtdemux, "failed to parse saio box");
4057         g_free (qtdemux->cenc_aux_info_sizes);
4058         qtdemux->cenc_aux_info_sizes = NULL;
4059         goto fail;
4060       }
4061       if (base_offset > -1 && base_offset > qtdemux->moof_offset)
4062         offset += (guint64) (base_offset - qtdemux->moof_offset);
4063       if (info_type == FOURCC_cenc && info_type_parameter == 0U) {
4064         GstByteReader br;
4065         if (offset > length) {
4066           GST_DEBUG_OBJECT (qtdemux, "cenc auxiliary info stored out of moof");
4067           qtdemux->cenc_aux_info_offset = offset;
4068         } else {
4069           gst_byte_reader_init (&br, buffer + offset, length - offset);
4070           if (!qtdemux_parse_cenc_aux_info (qtdemux, stream, &br,
4071                   qtdemux->cenc_aux_info_sizes,
4072                   qtdemux->cenc_aux_sample_count)) {
4073             GST_ERROR_OBJECT (qtdemux, "failed to parse cenc auxiliary info");
4074             g_free (qtdemux->cenc_aux_info_sizes);
4075             qtdemux->cenc_aux_info_sizes = NULL;
4076             goto fail;
4077           }
4078         }
4079       }
4080     }
4081
4082     tfdt_node =
4083         qtdemux_tree_get_child_by_type_full (traf_node, FOURCC_tfdt,
4084         &tfdt_data);
4085     if (tfdt_node) {
4086       /* We'll use decode_time to interpolate timestamps
4087        * in case the input timestamps are missing */
4088       qtdemux_parse_tfdt (qtdemux, &tfdt_data, &decode_time);
4089
4090       GST_DEBUG_OBJECT (qtdemux, "decode time %" G_GINT64_FORMAT
4091           " (%" GST_TIME_FORMAT ")", decode_time,
4092           GST_TIME_ARGS (stream ? QTSTREAMTIME_TO_GSTTIME (stream,
4093                   decode_time) : GST_CLOCK_TIME_NONE));
4094
4095       /* Discard the fragment buffer timestamp info to avoid using it.
4096        * Rely on tfdt instead as it is more accurate than the timestamp
4097        * that is fetched from a manifest/playlist and is usually
4098        * less accurate. */
4099       qtdemux->fragment_start = -1;
4100     }
4101
4102     if (G_UNLIKELY (!stream)) {
4103       /* we lost track of offset, we'll need to regain it,
4104        * but can delay complaining until later or avoid doing so altogether */
4105       base_offset = -2;
4106       goto next;
4107     }
4108     if (G_UNLIKELY (base_offset < -1))
4109       goto lost_offset;
4110
4111     if (qtdemux->upstream_format_is_time)
4112       gst_qtdemux_stream_flush_samples_data (stream);
4113
4114     /* initialise moof sample data */
4115     stream->n_samples_moof = 0;
4116     stream->duration_last_moof = stream->duration_moof;
4117     stream->duration_moof = 0;
4118
4119     /* Track Run node */
4120     trun_node =
4121         qtdemux_tree_get_child_by_type_full (traf_node, FOURCC_trun,
4122         &trun_data);
4123     while (trun_node) {
4124       qtdemux_parse_trun (qtdemux, &trun_data, stream,
4125           ds_duration, ds_size, ds_flags, moof_offset, length, &base_offset,
4126           &running_offset, decode_time, (tfdt_node != NULL));
4127       /* iterate all siblings */
4128       trun_node = qtdemux_tree_get_sibling_by_type_full (trun_node, FOURCC_trun,
4129           &trun_data);
4130     }
4131
4132     uuid_node = qtdemux_tree_get_child_by_type (traf_node, FOURCC_uuid);
4133     if (uuid_node) {
4134       guint8 *uuid_buffer = (guint8 *) uuid_node->data;
4135       guint32 box_length = QT_UINT32 (uuid_buffer);
4136
4137       qtdemux_parse_uuid (qtdemux, uuid_buffer, box_length);
4138     }
4139
4140     /* if no new base_offset provided for next traf,
4141      * base is end of current traf */
4142     base_offset = running_offset;
4143     running_offset = -1;
4144
4145     if (stream->n_samples_moof && stream->duration_moof)
4146       stream->new_caps = TRUE;
4147
4148   next:
4149     /* iterate all siblings */
4150     traf_node = qtdemux_tree_get_sibling_by_type (traf_node, FOURCC_traf);
4151   }
4152
4153   /* parse any protection system info */
4154   pssh_node = qtdemux_tree_get_child_by_type (moof_node, FOURCC_pssh);
4155   while (pssh_node) {
4156     GST_LOG_OBJECT (qtdemux, "Parsing pssh box.");
4157     qtdemux_parse_pssh (qtdemux, pssh_node);
4158     pssh_node = qtdemux_tree_get_sibling_by_type (pssh_node, FOURCC_pssh);
4159   }
4160
4161   g_node_destroy (moof_node);
4162   return TRUE;
4163
4164 missing_tfhd:
4165   {
4166     GST_DEBUG_OBJECT (qtdemux, "missing tfhd box");
4167     goto fail;
4168   }
4169 missing_mfhd:
4170   {
4171     GST_DEBUG_OBJECT (qtdemux, "Missing mfhd box");
4172     goto fail;
4173   }
4174 lost_offset:
4175   {
4176     GST_DEBUG_OBJECT (qtdemux, "lost offset");
4177     goto fail;
4178   }
4179 fail:
4180   {
4181     g_node_destroy (moof_node);
4182     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
4183         (_("This file is corrupt and cannot be played.")), (NULL));
4184     return FALSE;
4185   }
4186 }
4187
4188 #if 0
4189 /* might be used if some day we actually use mfra & co
4190  * for random access to fragments,
4191  * but that will require quite some modifications and much less relying
4192  * on a sample array */
4193 #endif
4194
4195 static gboolean
4196 qtdemux_parse_tfra (GstQTDemux * qtdemux, GNode * tfra_node)
4197 {
4198   QtDemuxStream *stream;
4199   guint32 ver_flags, track_id, len, num_entries, i;
4200   guint value_size, traf_size, trun_size, sample_size;
4201   guint64 time = 0, moof_offset = 0;
4202 #if 0
4203   GstBuffer *buf = NULL;
4204   GstFlowReturn ret;
4205 #endif
4206   GstByteReader tfra;
4207
4208   gst_byte_reader_init (&tfra, tfra_node->data, QT_UINT32 (tfra_node->data));
4209
4210   if (!gst_byte_reader_skip (&tfra, 8))
4211     return FALSE;
4212
4213   if (!gst_byte_reader_get_uint32_be (&tfra, &ver_flags))
4214     return FALSE;
4215
4216   if (!gst_byte_reader_get_uint32_be (&tfra, &track_id)
4217       || !gst_byte_reader_get_uint32_be (&tfra, &len)
4218       || !gst_byte_reader_get_uint32_be (&tfra, &num_entries))
4219     return FALSE;
4220
4221   GST_DEBUG_OBJECT (qtdemux, "parsing tfra box for track id %u", track_id);
4222
4223   stream = qtdemux_find_stream (qtdemux, track_id);
4224   if (stream == NULL)
4225     goto unknown_trackid;
4226
4227   value_size = ((ver_flags >> 24) == 1) ? sizeof (guint64) : sizeof (guint32);
4228   sample_size = (len & 3) + 1;
4229   trun_size = ((len & 12) >> 2) + 1;
4230   traf_size = ((len & 48) >> 4) + 1;
4231
4232   GST_DEBUG_OBJECT (qtdemux, "%u entries, sizes: value %u, traf %u, trun %u, "
4233       "sample %u", num_entries, value_size, traf_size, trun_size, sample_size);
4234
4235   if (num_entries == 0)
4236     goto no_samples;
4237
4238   if (!qt_atom_parser_has_chunks (&tfra, num_entries,
4239           value_size + value_size + traf_size + trun_size + sample_size))
4240     goto corrupt_file;
4241
4242   g_free (stream->ra_entries);
4243   stream->ra_entries = g_new (QtDemuxRandomAccessEntry, num_entries);
4244   stream->n_ra_entries = num_entries;
4245
4246   for (i = 0; i < num_entries; i++) {
4247     qt_atom_parser_get_offset (&tfra, value_size, &time);
4248     qt_atom_parser_get_offset (&tfra, value_size, &moof_offset);
4249     qt_atom_parser_get_uint_with_size_unchecked (&tfra, traf_size);
4250     qt_atom_parser_get_uint_with_size_unchecked (&tfra, trun_size);
4251     qt_atom_parser_get_uint_with_size_unchecked (&tfra, sample_size);
4252
4253     time = QTSTREAMTIME_TO_GSTTIME (stream, time);
4254
4255     GST_LOG_OBJECT (qtdemux, "fragment time: %" GST_TIME_FORMAT ", "
4256         " moof_offset: %" G_GUINT64_FORMAT, GST_TIME_ARGS (time), moof_offset);
4257
4258     stream->ra_entries[i].ts = time;
4259     stream->ra_entries[i].moof_offset = moof_offset;
4260
4261     /* don't want to go through the entire file and read all moofs at startup */
4262 #if 0
4263     ret = gst_qtdemux_pull_atom (qtdemux, moof_offset, 0, &buf);
4264     if (ret != GST_FLOW_OK)
4265       goto corrupt_file;
4266     qtdemux_parse_moof (qtdemux, GST_BUFFER_DATA (buf), GST_BUFFER_SIZE (buf),
4267         moof_offset, stream);
4268     gst_buffer_unref (buf);
4269 #endif
4270   }
4271
4272   check_update_duration (qtdemux, time);
4273
4274   return TRUE;
4275
4276 /* ERRORS */
4277 unknown_trackid:
4278   {
4279     GST_WARNING_OBJECT (qtdemux, "Couldn't find stream for track %u", track_id);
4280     return FALSE;
4281   }
4282 corrupt_file:
4283   {
4284     GST_WARNING_OBJECT (qtdemux, "broken traf box, ignoring");
4285     return FALSE;
4286   }
4287 no_samples:
4288   {
4289     GST_WARNING_OBJECT (qtdemux, "stream has no samples");
4290     return FALSE;
4291   }
4292 }
4293
4294 static gboolean
4295 qtdemux_pull_mfro_mfra (GstQTDemux * qtdemux)
4296 {
4297   GstMapInfo mfro_map = GST_MAP_INFO_INIT;
4298   GstMapInfo mfra_map = GST_MAP_INFO_INIT;
4299   GstBuffer *mfro = NULL, *mfra = NULL;
4300   GstFlowReturn flow;
4301   gboolean ret = FALSE;
4302   GNode *mfra_node, *tfra_node;
4303   guint64 mfra_offset = 0;
4304   guint32 fourcc, mfra_size;
4305   gint64 len;
4306
4307   /* query upstream size in bytes */
4308   if (!gst_pad_peer_query_duration (qtdemux->sinkpad, GST_FORMAT_BYTES, &len))
4309     goto size_query_failed;
4310
4311   /* mfro box should be at the very end of the file */
4312   flow = gst_qtdemux_pull_atom (qtdemux, len - 16, 16, &mfro);
4313   if (flow != GST_FLOW_OK)
4314     goto exit;
4315
4316   gst_buffer_map (mfro, &mfro_map, GST_MAP_READ);
4317
4318   fourcc = QT_FOURCC (mfro_map.data + 4);
4319   if (fourcc != FOURCC_mfro)
4320     goto exit;
4321
4322   GST_INFO_OBJECT (qtdemux, "Found mfro box");
4323   if (mfro_map.size < 16)
4324     goto invalid_mfro_size;
4325
4326   mfra_size = QT_UINT32 (mfro_map.data + 12);
4327   if (mfra_size >= len)
4328     goto invalid_mfra_size;
4329
4330   mfra_offset = len - mfra_size;
4331
4332   GST_INFO_OBJECT (qtdemux, "mfra offset: %" G_GUINT64_FORMAT ", size %u",
4333       mfra_offset, mfra_size);
4334
4335   /* now get and parse mfra box */
4336   flow = gst_qtdemux_pull_atom (qtdemux, mfra_offset, mfra_size, &mfra);
4337   if (flow != GST_FLOW_OK)
4338     goto broken_file;
4339
4340   gst_buffer_map (mfra, &mfra_map, GST_MAP_READ);
4341
4342   mfra_node = g_node_new ((guint8 *) mfra_map.data);
4343   qtdemux_parse_node (qtdemux, mfra_node, mfra_map.data, mfra_map.size);
4344
4345   tfra_node = qtdemux_tree_get_child_by_type (mfra_node, FOURCC_tfra);
4346
4347   while (tfra_node) {
4348     qtdemux_parse_tfra (qtdemux, tfra_node);
4349     /* iterate all siblings */
4350     tfra_node = qtdemux_tree_get_sibling_by_type (tfra_node, FOURCC_tfra);
4351   }
4352   g_node_destroy (mfra_node);
4353
4354   GST_INFO_OBJECT (qtdemux, "parsed movie fragment random access box (mfra)");
4355   ret = TRUE;
4356
4357 exit:
4358
4359   if (mfro) {
4360     if (mfro_map.memory != NULL)
4361       gst_buffer_unmap (mfro, &mfro_map);
4362     gst_buffer_unref (mfro);
4363   }
4364   if (mfra) {
4365     if (mfra_map.memory != NULL)
4366       gst_buffer_unmap (mfra, &mfra_map);
4367     gst_buffer_unref (mfra);
4368   }
4369   return ret;
4370
4371 /* ERRORS */
4372 size_query_failed:
4373   {
4374     GST_WARNING_OBJECT (qtdemux, "could not query upstream size");
4375     goto exit;
4376   }
4377 invalid_mfro_size:
4378   {
4379     GST_WARNING_OBJECT (qtdemux, "mfro size is too small");
4380     goto exit;
4381   }
4382 invalid_mfra_size:
4383   {
4384     GST_WARNING_OBJECT (qtdemux, "mfra_size in mfro box is invalid");
4385     goto exit;
4386   }
4387 broken_file:
4388   {
4389     GST_WARNING_OBJECT (qtdemux, "bogus mfra offset or size, broken file");
4390     goto exit;
4391   }
4392 }
4393
4394 static guint64
4395 add_offset (guint64 offset, guint64 advance)
4396 {
4397   /* Avoid 64-bit overflow by clamping */
4398   if (offset > G_MAXUINT64 - advance)
4399     return G_MAXUINT64;
4400   return offset + advance;
4401 }
4402
4403 static GstFlowReturn
4404 gst_qtdemux_loop_state_header (GstQTDemux * qtdemux)
4405 {
4406   guint64 length = 0;
4407   guint32 fourcc = 0;
4408   GstBuffer *buf = NULL;
4409   GstFlowReturn ret = GST_FLOW_OK;
4410   guint64 cur_offset = qtdemux->offset;
4411   GstMapInfo map;
4412
4413   ret = gst_pad_pull_range (qtdemux->sinkpad, cur_offset, 16, &buf);
4414   if (G_UNLIKELY (ret != GST_FLOW_OK))
4415     goto beach;
4416   gst_buffer_map (buf, &map, GST_MAP_READ);
4417   if (G_LIKELY (map.size >= 8))
4418     extract_initial_length_and_fourcc (map.data, map.size, &length, &fourcc);
4419   gst_buffer_unmap (buf, &map);
4420   gst_buffer_unref (buf);
4421
4422   /* maybe we already got most we needed, so only consider this eof */
4423   if (G_UNLIKELY (length == 0)) {
4424     GST_ELEMENT_WARNING (qtdemux, STREAM, DEMUX,
4425         (_("Invalid atom size.")),
4426         ("Header atom '%" GST_FOURCC_FORMAT "' has empty length",
4427             GST_FOURCC_ARGS (fourcc)));
4428     ret = GST_FLOW_EOS;
4429     goto beach;
4430   }
4431
4432   switch (fourcc) {
4433     case FOURCC_moof:
4434       /* record for later parsing when needed */
4435       if (!qtdemux->moof_offset) {
4436         qtdemux->moof_offset = qtdemux->offset;
4437       }
4438       if (qtdemux_pull_mfro_mfra (qtdemux)) {
4439         /* FIXME */
4440       } else {
4441         qtdemux->offset += length;      /* skip moof and keep going */
4442       }
4443       if (qtdemux->got_moov) {
4444         GST_INFO_OBJECT (qtdemux, "moof header, got moov, done with headers");
4445         ret = GST_FLOW_EOS;
4446         goto beach;
4447       }
4448       break;
4449     case FOURCC_mdat:
4450     case FOURCC_free:
4451     case FOURCC_skip:
4452     case FOURCC_wide:
4453     case FOURCC_PICT:
4454     case FOURCC_pnot:
4455     {
4456       GST_LOG_OBJECT (qtdemux,
4457           "skipping atom '%" GST_FOURCC_FORMAT "' at %" G_GUINT64_FORMAT,
4458           GST_FOURCC_ARGS (fourcc), cur_offset);
4459       qtdemux->offset = add_offset (qtdemux->offset, length);
4460       break;
4461     }
4462     case FOURCC_moov:
4463     {
4464       GstBuffer *moov = NULL;
4465
4466       if (qtdemux->got_moov) {
4467         GST_DEBUG_OBJECT (qtdemux, "Skipping moov atom as we have one already");
4468         qtdemux->offset = add_offset (qtdemux->offset, length);
4469         goto beach;
4470       }
4471
4472       ret = gst_pad_pull_range (qtdemux->sinkpad, cur_offset, length, &moov);
4473       if (ret != GST_FLOW_OK)
4474         goto beach;
4475       gst_buffer_map (moov, &map, GST_MAP_READ);
4476
4477       if (length != map.size) {
4478         /* Some files have a 'moov' atom at the end of the file which contains
4479          * a terminal 'free' atom where the body of the atom is missing.
4480          * Check for, and permit, this special case.
4481          */
4482         if (map.size >= 8) {
4483           guint8 *final_data = map.data + (map.size - 8);
4484           guint32 final_length = QT_UINT32 (final_data);
4485           guint32 final_fourcc = QT_FOURCC (final_data + 4);
4486
4487           if (final_fourcc == FOURCC_free
4488               && map.size + final_length - 8 == length) {
4489             /* Ok, we've found that special case. Allocate a new buffer with
4490              * that free atom actually present. */
4491             GstBuffer *newmoov = gst_buffer_new_and_alloc (length);
4492             gst_buffer_fill (newmoov, 0, map.data, map.size);
4493             gst_buffer_memset (newmoov, map.size, 0, final_length - 8);
4494             gst_buffer_unmap (moov, &map);
4495             gst_buffer_unref (moov);
4496             moov = newmoov;
4497             gst_buffer_map (moov, &map, GST_MAP_READ);
4498           }
4499         }
4500       }
4501
4502       if (length != map.size) {
4503         GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
4504             (_("This file is incomplete and cannot be played.")),
4505             ("We got less than expected (received %" G_GSIZE_FORMAT
4506                 ", wanted %u, offset %" G_GUINT64_FORMAT ")", map.size,
4507                 (guint) length, cur_offset));
4508         gst_buffer_unmap (moov, &map);
4509         gst_buffer_unref (moov);
4510         ret = GST_FLOW_ERROR;
4511         goto beach;
4512       }
4513       qtdemux->offset += length;
4514
4515       qtdemux_parse_moov (qtdemux, map.data, length);
4516       qtdemux_node_dump (qtdemux, qtdemux->moov_node);
4517
4518       qtdemux_parse_tree (qtdemux);
4519       if (qtdemux->moov_node_compressed) {
4520         g_node_destroy (qtdemux->moov_node_compressed);
4521         g_free (qtdemux->moov_node->data);
4522       }
4523       qtdemux->moov_node_compressed = NULL;
4524       g_node_destroy (qtdemux->moov_node);
4525       qtdemux->moov_node = NULL;
4526       gst_buffer_unmap (moov, &map);
4527       gst_buffer_unref (moov);
4528       qtdemux->got_moov = TRUE;
4529       if (!qtdemux->fragmented && !qtdemux->upstream_format_is_time) {
4530         /* in this case, parsing the edts entries will give us segments
4531            already */
4532         qtdemux->need_segment = FALSE;
4533       }
4534
4535       break;
4536     }
4537     case FOURCC_ftyp:
4538     {
4539       GstBuffer *ftyp = NULL;
4540
4541       /* extract major brand; might come in handy for ISO vs QT issues */
4542       ret = gst_qtdemux_pull_atom (qtdemux, cur_offset, length, &ftyp);
4543       if (ret != GST_FLOW_OK)
4544         goto beach;
4545       qtdemux->offset += length;
4546       gst_buffer_map (ftyp, &map, GST_MAP_READ);
4547       qtdemux_parse_ftyp (qtdemux, map.data, map.size);
4548       gst_buffer_unmap (ftyp, &map);
4549       gst_buffer_unref (ftyp);
4550       break;
4551     }
4552     case FOURCC_uuid:
4553     {
4554       GstBuffer *uuid = NULL;
4555
4556       /* uuid are extension atoms */
4557       ret = gst_qtdemux_pull_atom (qtdemux, cur_offset, length, &uuid);
4558       if (ret != GST_FLOW_OK)
4559         goto beach;
4560       qtdemux->offset += length;
4561       gst_buffer_map (uuid, &map, GST_MAP_READ);
4562       qtdemux_parse_uuid (qtdemux, map.data, map.size);
4563       gst_buffer_unmap (uuid, &map);
4564       gst_buffer_unref (uuid);
4565       break;
4566     }
4567     case FOURCC_sidx:
4568     {
4569       GstBuffer *sidx = NULL;
4570       ret = gst_qtdemux_pull_atom (qtdemux, cur_offset, length, &sidx);
4571       if (ret != GST_FLOW_OK)
4572         goto beach;
4573       qtdemux->offset += length;
4574       gst_buffer_map (sidx, &map, GST_MAP_READ);
4575       qtdemux_parse_sidx (qtdemux, map.data, map.size);
4576       gst_buffer_unmap (sidx, &map);
4577       gst_buffer_unref (sidx);
4578       break;
4579     }
4580     default:
4581     {
4582       GstBuffer *unknown = NULL;
4583
4584       GST_LOG_OBJECT (qtdemux,
4585           "unknown %08x '%" GST_FOURCC_FORMAT "' of size %" G_GUINT64_FORMAT
4586           " at %" G_GUINT64_FORMAT, fourcc, GST_FOURCC_ARGS (fourcc), length,
4587           cur_offset);
4588       ret = gst_qtdemux_pull_atom (qtdemux, cur_offset, length, &unknown);
4589       if (ret != GST_FLOW_OK)
4590         goto beach;
4591       gst_buffer_map (unknown, &map, GST_MAP_READ);
4592       GST_MEMDUMP ("Unknown tag", map.data, map.size);
4593       gst_buffer_unmap (unknown, &map);
4594       gst_buffer_unref (unknown);
4595       qtdemux->offset += length;
4596       break;
4597     }
4598   }
4599
4600 beach:
4601   if (ret == GST_FLOW_EOS && (qtdemux->got_moov || qtdemux->media_caps)) {
4602     /* digested all data, show what we have */
4603     qtdemux_prepare_streams (qtdemux);
4604     QTDEMUX_EXPOSE_LOCK (qtdemux);
4605     ret = qtdemux_expose_streams (qtdemux);
4606     QTDEMUX_EXPOSE_UNLOCK (qtdemux);
4607
4608     qtdemux->state = QTDEMUX_STATE_MOVIE;
4609     GST_DEBUG_OBJECT (qtdemux, "switching state to STATE_MOVIE (%d)",
4610         qtdemux->state);
4611     return ret;
4612   }
4613   return ret;
4614 }
4615
4616 /* Seeks to the previous keyframe of the indexed stream and
4617  * aligns other streams with respect to the keyframe timestamp
4618  * of indexed stream. Only called in case of Reverse Playback
4619  */
4620 static GstFlowReturn
4621 gst_qtdemux_seek_to_previous_keyframe (GstQTDemux * qtdemux)
4622 {
4623   guint32 seg_idx = 0, k_index = 0;
4624   guint32 ref_seg_idx, ref_k_index;
4625   GstClockTime k_pos = 0, last_stop = 0;
4626   QtDemuxSegment *seg = NULL;
4627   QtDemuxStream *ref_str = NULL;
4628   guint64 seg_media_start_mov;  /* segment media start time in mov format */
4629   guint64 target_ts;
4630   GList *iter;
4631
4632   /* Now we choose an arbitrary stream, get the previous keyframe timestamp
4633    * and finally align all the other streams on that timestamp with their
4634    * respective keyframes */
4635   for (iter = qtdemux->active_streams; iter; iter = g_list_next (iter)) {
4636     QtDemuxStream *str = QTDEMUX_STREAM (iter->data);
4637
4638     /* No candidate yet, take the first stream */
4639     if (!ref_str) {
4640       ref_str = str;
4641       continue;
4642     }
4643
4644     /* So that stream has a segment, we prefer video streams */
4645     if (str->subtype == FOURCC_vide) {
4646       ref_str = str;
4647       break;
4648     }
4649   }
4650
4651   if (G_UNLIKELY (!ref_str)) {
4652     GST_DEBUG_OBJECT (qtdemux, "couldn't find any stream");
4653     goto eos;
4654   }
4655
4656   if (G_UNLIKELY (!ref_str->from_sample)) {
4657     GST_DEBUG_OBJECT (qtdemux, "reached the beginning of the file");
4658     goto eos;
4659   }
4660
4661   /* So that stream has been playing from from_sample to to_sample. We will
4662    * get the timestamp of the previous sample and search for a keyframe before
4663    * that. For audio streams we do an arbitrary jump in the past (10 samples) */
4664   if (ref_str->subtype == FOURCC_vide) {
4665     k_index = gst_qtdemux_find_keyframe (qtdemux, ref_str,
4666         ref_str->from_sample - 1, FALSE);
4667   } else {
4668     if (ref_str->from_sample >= 10)
4669       k_index = ref_str->from_sample - 10;
4670     else
4671       k_index = 0;
4672   }
4673
4674   target_ts =
4675       ref_str->samples[k_index].timestamp +
4676       ref_str->samples[k_index].pts_offset;
4677
4678   /* get current segment for that stream */
4679   seg = &ref_str->segments[ref_str->segment_index];
4680   /* Use segment start in original timescale for comparisons */
4681   seg_media_start_mov = seg->trak_media_start;
4682
4683   GST_LOG_OBJECT (qtdemux, "keyframe index %u ts %" G_GUINT64_FORMAT
4684       " seg start %" G_GUINT64_FORMAT " %" GST_TIME_FORMAT "\n",
4685       k_index, target_ts, seg_media_start_mov,
4686       GST_TIME_ARGS (seg->media_start));
4687
4688   /* Crawl back through segments to find the one containing this I frame */
4689   while (target_ts < seg_media_start_mov) {
4690     GST_DEBUG_OBJECT (qtdemux,
4691         "keyframe position (sample %u) is out of segment %u " " target %"
4692         G_GUINT64_FORMAT " seg start %" G_GUINT64_FORMAT, k_index,
4693         ref_str->segment_index, target_ts, seg_media_start_mov);
4694
4695     if (G_UNLIKELY (!ref_str->segment_index)) {
4696       /* Reached first segment, let's consider it's EOS */
4697       goto eos;
4698     }
4699     ref_str->segment_index--;
4700     seg = &ref_str->segments[ref_str->segment_index];
4701     /* Use segment start in original timescale for comparisons */
4702     seg_media_start_mov = seg->trak_media_start;
4703   }
4704   /* Calculate time position of the keyframe and where we should stop */
4705   k_pos =
4706       QTSTREAMTIME_TO_GSTTIME (ref_str,
4707       target_ts - seg->trak_media_start) + seg->time;
4708   last_stop =
4709       QTSTREAMTIME_TO_GSTTIME (ref_str,
4710       ref_str->samples[ref_str->from_sample].timestamp -
4711       seg->trak_media_start) + seg->time;
4712
4713   GST_DEBUG_OBJECT (qtdemux, "preferred stream played from sample %u, "
4714       "now going to sample %u (pts %" GST_TIME_FORMAT ")", ref_str->from_sample,
4715       k_index, GST_TIME_ARGS (k_pos));
4716
4717   /* Set last_stop with the keyframe timestamp we pushed of that stream */
4718   qtdemux->segment.position = last_stop;
4719   GST_DEBUG_OBJECT (qtdemux, "last_stop now is %" GST_TIME_FORMAT,
4720       GST_TIME_ARGS (last_stop));
4721
4722   if (G_UNLIKELY (last_stop < qtdemux->segment.start)) {
4723     GST_DEBUG_OBJECT (qtdemux, "reached the beginning of segment");
4724     goto eos;
4725   }
4726
4727   ref_seg_idx = ref_str->segment_index;
4728   ref_k_index = k_index;
4729
4730   /* Align them all on this */
4731   for (iter = qtdemux->active_streams; iter; iter = g_list_next (iter)) {
4732     guint32 index = 0;
4733     GstClockTime seg_time = 0;
4734     QtDemuxStream *str = QTDEMUX_STREAM (iter->data);
4735
4736     /* aligning reference stream again might lead to backing up to yet another
4737      * keyframe (due to timestamp rounding issues),
4738      * potentially putting more load on downstream; so let's try to avoid */
4739     if (str == ref_str) {
4740       seg_idx = ref_seg_idx;
4741       seg = &str->segments[seg_idx];
4742       k_index = ref_k_index;
4743       GST_DEBUG_OBJECT (qtdemux, "reference track-id %u segment %d, "
4744           "sample at index %d", str->track_id, ref_str->segment_index, k_index);
4745     } else {
4746       seg_idx = gst_qtdemux_find_segment (qtdemux, str, k_pos);
4747       GST_DEBUG_OBJECT (qtdemux,
4748           "track-id %u align segment %d for keyframe pos %" GST_TIME_FORMAT,
4749           str->track_id, seg_idx, GST_TIME_ARGS (k_pos));
4750
4751       /* get segment and time in the segment */
4752       seg = &str->segments[seg_idx];
4753       seg_time = k_pos - seg->time;
4754
4755       /* get the media time in the segment.
4756        * No adjustment for empty "filler" segments */
4757       if (seg->media_start != GST_CLOCK_TIME_NONE)
4758         seg_time += seg->media_start;
4759
4760       /* get the index of the sample with media time */
4761       index = gst_qtdemux_find_index_linear (qtdemux, str, seg_time);
4762       GST_DEBUG_OBJECT (qtdemux,
4763           "track-id %u sample for %" GST_TIME_FORMAT " at %u", str->track_id,
4764           GST_TIME_ARGS (seg_time), index);
4765
4766       /* find previous keyframe */
4767       k_index = gst_qtdemux_find_keyframe (qtdemux, str, index, FALSE);
4768     }
4769
4770     /* Remember until where we want to go */
4771     str->to_sample = str->from_sample - 1;
4772     /* Define our time position */
4773     target_ts =
4774         str->samples[k_index].timestamp + str->samples[k_index].pts_offset;
4775     str->time_position = QTSTREAMTIME_TO_GSTTIME (str, target_ts) + seg->time;
4776     if (seg->media_start != GST_CLOCK_TIME_NONE)
4777       str->time_position -= seg->media_start;
4778
4779     /* Now seek back in time */
4780     gst_qtdemux_move_stream (qtdemux, str, k_index);
4781     GST_DEBUG_OBJECT (qtdemux, "track-id %u keyframe at %u, time position %"
4782         GST_TIME_FORMAT " playing from sample %u to %u", str->track_id, k_index,
4783         GST_TIME_ARGS (str->time_position), str->from_sample, str->to_sample);
4784   }
4785
4786   return GST_FLOW_OK;
4787
4788 eos:
4789   return GST_FLOW_EOS;
4790 }
4791
4792 /*
4793  * Gets the current qt segment start, stop and position for the
4794  * given time offset. This is used in update_segment()
4795  */
4796 static void
4797 gst_qtdemux_stream_segment_get_boundaries (GstQTDemux * qtdemux,
4798     QtDemuxStream * stream, GstClockTime offset,
4799     GstClockTime * _start, GstClockTime * _stop, GstClockTime * _time)
4800 {
4801   GstClockTime seg_time;
4802   GstClockTime start, stop, time;
4803   QtDemuxSegment *segment;
4804
4805   segment = &stream->segments[stream->segment_index];
4806
4807   /* get time in this segment */
4808   seg_time = (offset - segment->time) * segment->rate;
4809
4810   GST_LOG_OBJECT (stream->pad, "seg_time %" GST_TIME_FORMAT,
4811       GST_TIME_ARGS (seg_time));
4812
4813   if (G_UNLIKELY (seg_time > segment->duration)) {
4814     GST_LOG_OBJECT (stream->pad,
4815         "seg_time > segment->duration %" GST_TIME_FORMAT,
4816         GST_TIME_ARGS (segment->duration));
4817     seg_time = segment->duration;
4818   }
4819
4820   /* qtdemux->segment.stop is in outside-time-realm, whereas
4821    * segment->media_stop is in track-time-realm.
4822    *
4823    * In order to compare the two, we need to bring segment.stop
4824    * into the track-time-realm
4825    *
4826    * FIXME - does this comment still hold? Don't see any conversion here */
4827
4828   stop = qtdemux->segment.stop;
4829   if (stop == GST_CLOCK_TIME_NONE)
4830     stop = qtdemux->segment.duration;
4831   if (stop == GST_CLOCK_TIME_NONE)
4832     stop = segment->media_stop;
4833   else
4834     stop =
4835         MIN (segment->media_stop, stop - segment->time + segment->media_start);
4836
4837   if (G_UNLIKELY (QTSEGMENT_IS_EMPTY (segment))) {
4838     start = segment->time + seg_time;
4839     time = offset;
4840     stop = start - seg_time + segment->duration;
4841   } else if (qtdemux->segment.rate >= 0) {
4842     start = MIN (segment->media_start + seg_time, stop);
4843     time = offset;
4844   } else {
4845     if (segment->media_start >= qtdemux->segment.start) {
4846       time = segment->time;
4847     } else {
4848       time = segment->time + (qtdemux->segment.start - segment->media_start);
4849     }
4850
4851     start = MAX (segment->media_start, qtdemux->segment.start);
4852     stop = MIN (segment->media_start + seg_time, stop);
4853   }
4854
4855   *_start = start;
4856   *_stop = stop;
4857   *_time = time;
4858 }
4859
4860 /*
4861  * Updates the qt segment used for the stream and pushes a new segment event
4862  * downstream on this stream's pad.
4863  */
4864 static gboolean
4865 gst_qtdemux_stream_update_segment (GstQTDemux * qtdemux, QtDemuxStream * stream,
4866     gint seg_idx, GstClockTime offset, GstClockTime * _start,
4867     GstClockTime * _stop)
4868 {
4869   QtDemuxSegment *segment;
4870   GstClockTime start = 0, stop = GST_CLOCK_TIME_NONE, time = 0;
4871   gdouble rate;
4872   GstEvent *event;
4873
4874   /* update the current segment */
4875   stream->segment_index = seg_idx;
4876
4877   /* get the segment */
4878   segment = &stream->segments[seg_idx];
4879
4880   if (G_UNLIKELY (offset < segment->time)) {
4881     GST_WARNING_OBJECT (stream->pad, "offset < segment->time %" GST_TIME_FORMAT,
4882         GST_TIME_ARGS (segment->time));
4883     return FALSE;
4884   }
4885
4886   /* segment lies beyond total indicated duration */
4887   if (G_UNLIKELY (qtdemux->segment.duration != GST_CLOCK_TIME_NONE &&
4888           segment->time > qtdemux->segment.duration)) {
4889     GST_WARNING_OBJECT (stream->pad, "file duration %" GST_TIME_FORMAT
4890         " < segment->time %" GST_TIME_FORMAT,
4891         GST_TIME_ARGS (qtdemux->segment.duration),
4892         GST_TIME_ARGS (segment->time));
4893     return FALSE;
4894   }
4895
4896   gst_qtdemux_stream_segment_get_boundaries (qtdemux, stream, offset,
4897       &start, &stop, &time);
4898
4899   GST_DEBUG_OBJECT (stream->pad, "new segment %d from %" GST_TIME_FORMAT
4900       " to %" GST_TIME_FORMAT ", time %" GST_TIME_FORMAT, seg_idx,
4901       GST_TIME_ARGS (start), GST_TIME_ARGS (stop), GST_TIME_ARGS (time));
4902
4903   /* combine global rate with that of the segment */
4904   rate = segment->rate * qtdemux->segment.rate;
4905
4906   /* Copy flags from main segment */
4907   stream->segment.flags = qtdemux->segment.flags;
4908
4909   /* update the segment values used for clipping */
4910   stream->segment.offset = qtdemux->segment.offset;
4911   stream->segment.base = qtdemux->segment.base + stream->accumulated_base;
4912   stream->segment.applied_rate = qtdemux->segment.applied_rate;
4913   stream->segment.rate = rate;
4914   stream->segment.start = start + QTSTREAMTIME_TO_GSTTIME (stream,
4915       stream->cslg_shift);
4916   stream->segment.stop = stop + QTSTREAMTIME_TO_GSTTIME (stream,
4917       stream->cslg_shift);
4918   stream->segment.time = time;
4919   stream->segment.position = stream->segment.start;
4920
4921   GST_DEBUG_OBJECT (stream->pad, "New segment: %" GST_SEGMENT_FORMAT,
4922       &stream->segment);
4923
4924   /* now prepare and send the segment */
4925   if (stream->pad) {
4926     event = gst_event_new_segment (&stream->segment);
4927     if (qtdemux->segment_seqnum != GST_SEQNUM_INVALID) {
4928       gst_event_set_seqnum (event, qtdemux->segment_seqnum);
4929     }
4930     gst_pad_push_event (stream->pad, event);
4931     /* assume we can send more data now */
4932     GST_PAD_LAST_FLOW_RETURN (stream->pad) = GST_FLOW_OK;
4933     /* clear to send tags on this pad now */
4934     gst_qtdemux_push_tags (qtdemux, stream);
4935   }
4936
4937   if (_start)
4938     *_start = start;
4939   if (_stop)
4940     *_stop = stop;
4941
4942   return TRUE;
4943 }
4944
4945 /* activate the given segment number @seg_idx of @stream at time @offset.
4946  * @offset is an absolute global position over all the segments.
4947  *
4948  * This will push out a NEWSEGMENT event with the right values and
4949  * position the stream index to the first decodable sample before
4950  * @offset.
4951  */
4952 static gboolean
4953 gst_qtdemux_activate_segment (GstQTDemux * qtdemux, QtDemuxStream * stream,
4954     guint32 seg_idx, GstClockTime offset)
4955 {
4956   QtDemuxSegment *segment;
4957   guint32 index, kf_index;
4958   GstClockTime start = 0, stop = GST_CLOCK_TIME_NONE;
4959
4960   GST_LOG_OBJECT (stream->pad, "activate segment %d, offset %" GST_TIME_FORMAT,
4961       seg_idx, GST_TIME_ARGS (offset));
4962
4963   if (!gst_qtdemux_stream_update_segment (qtdemux, stream, seg_idx, offset,
4964           &start, &stop))
4965     return FALSE;
4966
4967   segment = &stream->segments[stream->segment_index];
4968
4969   /* in the fragmented case, we pick a fragment that starts before our
4970    * desired position and rely on downstream to wait for a keyframe
4971    * (FIXME: doesn't seem to work so well with ismv and wmv, as no parser; the
4972    * tfra entries tells us which trun/sample the key unit is in, but we don't
4973    * make use of this additional information at the moment) */
4974   if (qtdemux->fragmented && !qtdemux->fragmented_seek_pending) {
4975     stream->to_sample = G_MAXUINT32;
4976     return TRUE;
4977   } else {
4978     /* well, it will be taken care of below */
4979     qtdemux->fragmented_seek_pending = FALSE;
4980     /* FIXME ideally the do_fragmented_seek can be done right here,
4981      * rather than at loop level
4982      * (which might even allow handling edit lists in a fragmented file) */
4983   }
4984
4985   /* We don't need to look for a sample in push-based */
4986   if (!qtdemux->pullbased)
4987     return TRUE;
4988
4989   /* and move to the keyframe before the indicated media time of the
4990    * segment */
4991   if (G_LIKELY (!QTSEGMENT_IS_EMPTY (segment))) {
4992     if (qtdemux->segment.rate >= 0) {
4993       index = gst_qtdemux_find_index_linear (qtdemux, stream, start);
4994       stream->to_sample = G_MAXUINT32;
4995       GST_DEBUG_OBJECT (stream->pad,
4996           "moving data pointer to %" GST_TIME_FORMAT ", index: %u, pts %"
4997           GST_TIME_FORMAT, GST_TIME_ARGS (start), index,
4998           GST_TIME_ARGS (QTSAMPLE_PTS (stream, &stream->samples[index])));
4999     } else {
5000       index = gst_qtdemux_find_index_linear (qtdemux, stream, stop);
5001       stream->to_sample = index;
5002       GST_DEBUG_OBJECT (stream->pad,
5003           "moving data pointer to %" GST_TIME_FORMAT ", index: %u, pts %"
5004           GST_TIME_FORMAT, GST_TIME_ARGS (stop), index,
5005           GST_TIME_ARGS (QTSAMPLE_PTS (stream, &stream->samples[index])));
5006     }
5007   } else {
5008     GST_DEBUG_OBJECT (stream->pad, "No need to look for keyframe, "
5009         "this is an empty segment");
5010     return TRUE;
5011   }
5012
5013   /* gst_qtdemux_parse_sample () called from gst_qtdemux_find_index_linear ()
5014    * encountered an error and printed a message so we return appropriately */
5015   if (index == -1)
5016     return FALSE;
5017
5018   /* we're at the right spot */
5019   if (index == stream->sample_index) {
5020     GST_DEBUG_OBJECT (stream->pad, "we are at the right index");
5021     return TRUE;
5022   }
5023
5024   /* find keyframe of the target index */
5025   kf_index = gst_qtdemux_find_keyframe (qtdemux, stream, index, FALSE);
5026
5027 /* *INDENT-OFF* */
5028 /* indent does stupid stuff with stream->samples[].timestamp */
5029
5030   /* if we move forwards, we don't have to go back to the previous
5031    * keyframe since we already sent that. We can also just jump to
5032    * the keyframe right before the target index if there is one. */
5033   if (index > stream->sample_index) {
5034     /* moving forwards check if we move past a keyframe */
5035     if (kf_index > stream->sample_index) {
5036       GST_DEBUG_OBJECT (stream->pad,
5037            "moving forwards to keyframe at %u (pts %" GST_TIME_FORMAT " dts %"GST_TIME_FORMAT" )", kf_index,
5038            GST_TIME_ARGS (QTSAMPLE_PTS(stream, &stream->samples[kf_index])),
5039            GST_TIME_ARGS (QTSAMPLE_DTS(stream, &stream->samples[kf_index])));
5040       gst_qtdemux_move_stream (qtdemux, stream, kf_index);
5041     } else {
5042       GST_DEBUG_OBJECT (stream->pad,
5043           "moving forwards, keyframe at %u (pts %" GST_TIME_FORMAT " dts %"GST_TIME_FORMAT" ) already sent", kf_index,
5044           GST_TIME_ARGS (QTSAMPLE_PTS (stream, &stream->samples[kf_index])),
5045           GST_TIME_ARGS (QTSAMPLE_DTS (stream, &stream->samples[kf_index])));
5046     }
5047   } else {
5048     GST_DEBUG_OBJECT (stream->pad,
5049         "moving backwards to keyframe at %u (pts %" GST_TIME_FORMAT " dts %"GST_TIME_FORMAT" )", kf_index,
5050         GST_TIME_ARGS (QTSAMPLE_PTS(stream, &stream->samples[kf_index])),
5051         GST_TIME_ARGS (QTSAMPLE_DTS(stream, &stream->samples[kf_index])));
5052     gst_qtdemux_move_stream (qtdemux, stream, kf_index);
5053   }
5054
5055 /* *INDENT-ON* */
5056
5057   return TRUE;
5058 }
5059
5060 /* prepare to get the current sample of @stream, getting essential values.
5061  *
5062  * This function will also prepare and send the segment when needed.
5063  *
5064  * Return FALSE if the stream is EOS.
5065  *
5066  * PULL-BASED
5067  */
5068 static gboolean
5069 gst_qtdemux_prepare_current_sample (GstQTDemux * qtdemux,
5070     QtDemuxStream * stream, gboolean * empty, guint64 * offset, guint * size,
5071     GstClockTime * dts, GstClockTime * pts, GstClockTime * duration,
5072     gboolean * keyframe)
5073 {
5074   QtDemuxSample *sample;
5075   GstClockTime time_position;
5076   guint32 seg_idx;
5077
5078   g_return_val_if_fail (stream != NULL, FALSE);
5079
5080   time_position = stream->time_position;
5081   if (G_UNLIKELY (time_position == GST_CLOCK_TIME_NONE))
5082     goto eos;
5083
5084   seg_idx = stream->segment_index;
5085   if (G_UNLIKELY (seg_idx == -1)) {
5086     /* find segment corresponding to time_position if we are looking
5087      * for a segment. */
5088     seg_idx = gst_qtdemux_find_segment (qtdemux, stream, time_position);
5089   }
5090
5091   /* different segment, activate it, sample_index will be set. */
5092   if (G_UNLIKELY (stream->segment_index != seg_idx))
5093     gst_qtdemux_activate_segment (qtdemux, stream, seg_idx, time_position);
5094
5095   if (G_UNLIKELY (QTSEGMENT_IS_EMPTY (&stream->segments[stream->
5096                   segment_index]))) {
5097     QtDemuxSegment *seg = &stream->segments[stream->segment_index];
5098
5099     GST_LOG_OBJECT (qtdemux, "Empty segment activated,"
5100         " prepare empty sample");
5101
5102     *empty = TRUE;
5103     *pts = *dts = time_position;
5104     *duration = seg->duration - (time_position - seg->time);
5105
5106     return TRUE;
5107   }
5108
5109   *empty = FALSE;
5110
5111   if (stream->sample_index == -1)
5112     stream->sample_index = 0;
5113
5114   GST_LOG_OBJECT (qtdemux, "segment active, index = %u of %u",
5115       stream->sample_index, stream->n_samples);
5116
5117   if (G_UNLIKELY (stream->sample_index >= stream->n_samples)) {
5118     if (!qtdemux->fragmented)
5119       goto eos;
5120
5121     GST_INFO_OBJECT (qtdemux, "out of samples, trying to add more");
5122     do {
5123       GstFlowReturn flow;
5124
5125       GST_OBJECT_LOCK (qtdemux);
5126       flow = qtdemux_add_fragmented_samples (qtdemux);
5127       GST_OBJECT_UNLOCK (qtdemux);
5128
5129       if (flow != GST_FLOW_OK)
5130         goto eos;
5131     }
5132     while (stream->sample_index >= stream->n_samples);
5133   }
5134
5135   if (!qtdemux_parse_samples (qtdemux, stream, stream->sample_index)) {
5136     GST_LOG_OBJECT (qtdemux, "Parsing of index %u failed!",
5137         stream->sample_index);
5138     return FALSE;
5139   }
5140
5141   /* now get the info for the sample we're at */
5142   sample = &stream->samples[stream->sample_index];
5143
5144   *dts = QTSAMPLE_DTS (stream, sample);
5145   *pts = QTSAMPLE_PTS (stream, sample);
5146   *offset = sample->offset;
5147   *size = sample->size;
5148   *duration = QTSAMPLE_DUR_DTS (stream, sample, *dts);
5149   *keyframe = QTSAMPLE_KEYFRAME (stream, sample);
5150
5151   return TRUE;
5152
5153   /* special cases */
5154 eos:
5155   {
5156     stream->time_position = GST_CLOCK_TIME_NONE;
5157     return FALSE;
5158   }
5159 }
5160
5161 /* move to the next sample in @stream.
5162  *
5163  * Moves to the next segment when needed.
5164  */
5165 static void
5166 gst_qtdemux_advance_sample (GstQTDemux * qtdemux, QtDemuxStream * stream)
5167 {
5168   QtDemuxSample *sample;
5169   QtDemuxSegment *segment;
5170
5171   /* get current segment */
5172   segment = &stream->segments[stream->segment_index];
5173
5174   if (G_UNLIKELY (QTSEGMENT_IS_EMPTY (segment))) {
5175     GST_DEBUG_OBJECT (qtdemux, "Empty segment, no samples to advance");
5176     goto next_segment;
5177   }
5178
5179   if (G_UNLIKELY (stream->sample_index >= stream->to_sample)) {
5180     /* Mark the stream as EOS */
5181     GST_DEBUG_OBJECT (qtdemux,
5182         "reached max allowed sample %u, mark EOS", stream->to_sample);
5183     stream->time_position = GST_CLOCK_TIME_NONE;
5184     return;
5185   }
5186
5187   /* move to next sample */
5188   stream->sample_index++;
5189   stream->offset_in_sample = 0;
5190
5191   /* reached the last sample, we need the next segment */
5192   if (G_UNLIKELY (stream->sample_index >= stream->n_samples))
5193     goto next_segment;
5194
5195   if (!qtdemux_parse_samples (qtdemux, stream, stream->sample_index)) {
5196     GST_LOG_OBJECT (qtdemux, "Parsing of index %u failed!",
5197         stream->sample_index);
5198     return;
5199   }
5200
5201   /* get next sample */
5202   sample = &stream->samples[stream->sample_index];
5203
5204   /* see if we are past the segment */
5205   if (G_UNLIKELY (QTSAMPLE_DTS (stream, sample) >= segment->media_stop))
5206     goto next_segment;
5207
5208   if (QTSAMPLE_DTS (stream, sample) >= segment->media_start) {
5209     /* inside the segment, update time_position, looks very familiar to
5210      * GStreamer segments, doesn't it? */
5211     stream->time_position =
5212         QTSAMPLE_DTS (stream, sample) - segment->media_start + segment->time;
5213   } else {
5214     /* not yet in segment, time does not yet increment. This means
5215      * that we are still prerolling keyframes to the decoder so it can
5216      * decode the first sample of the segment. */
5217     stream->time_position = segment->time;
5218   }
5219   return;
5220
5221   /* move to the next segment */
5222 next_segment:
5223   {
5224     GST_DEBUG_OBJECT (qtdemux, "segment %d ended ", stream->segment_index);
5225
5226     if (stream->segment_index == stream->n_segments - 1) {
5227       /* are we at the end of the last segment, we're EOS */
5228       stream->time_position = GST_CLOCK_TIME_NONE;
5229     } else {
5230       /* else we're only at the end of the current segment */
5231       stream->time_position = segment->stop_time;
5232     }
5233     /* make sure we select a new segment */
5234
5235     /* accumulate previous segments */
5236     if (GST_CLOCK_TIME_IS_VALID (stream->segment.stop))
5237       stream->accumulated_base +=
5238           (stream->segment.stop -
5239           stream->segment.start) / ABS (stream->segment.rate);
5240
5241     stream->segment_index = -1;
5242   }
5243 }
5244
5245 static void
5246 gst_qtdemux_sync_streams (GstQTDemux * demux)
5247 {
5248   GList *iter;
5249
5250   if (demux->n_streams <= 1)
5251     return;
5252
5253   for (iter = demux->active_streams; iter; iter = g_list_next (iter)) {
5254     QtDemuxStream *stream;
5255     GstClockTime end_time;
5256
5257     stream = QTDEMUX_STREAM (iter->data);
5258
5259     if (!stream->pad)
5260       continue;
5261
5262     /* TODO advance time on subtitle streams here, if any some day */
5263
5264     /* some clips/trailers may have unbalanced streams at the end,
5265      * so send EOS on shorter stream to prevent stalling others */
5266
5267     /* do not mess with EOS if SEGMENT seeking */
5268     if (demux->segment.flags & GST_SEEK_FLAG_SEGMENT)
5269       continue;
5270
5271     if (demux->pullbased) {
5272       /* loop mode is sample time based */
5273       if (!STREAM_IS_EOS (stream))
5274         continue;
5275     } else {
5276       /* push mode is byte position based */
5277       if (stream->n_samples &&
5278           stream->samples[stream->n_samples - 1].offset >= demux->offset)
5279         continue;
5280     }
5281
5282     if (stream->sent_eos)
5283       continue;
5284
5285     /* only act if some gap */
5286     end_time = stream->segments[stream->n_segments - 1].stop_time;
5287     GST_LOG_OBJECT (demux, "current position: %" GST_TIME_FORMAT
5288         ", stream end: %" GST_TIME_FORMAT,
5289         GST_TIME_ARGS (demux->segment.position), GST_TIME_ARGS (end_time));
5290     if (GST_CLOCK_TIME_IS_VALID (end_time)
5291         && (end_time + 2 * GST_SECOND < demux->segment.position)) {
5292       GstEvent *event;
5293
5294       GST_DEBUG_OBJECT (demux, "sending EOS for stream %s",
5295           GST_PAD_NAME (stream->pad));
5296       stream->sent_eos = TRUE;
5297       event = gst_event_new_eos ();
5298       if (demux->segment_seqnum != GST_SEQNUM_INVALID)
5299         gst_event_set_seqnum (event, demux->segment_seqnum);
5300       gst_pad_push_event (stream->pad, event);
5301     }
5302   }
5303 }
5304
5305 /* EOS and NOT_LINKED need to be combined. This means that we return:
5306  *
5307  *  GST_FLOW_NOT_LINKED: when all pads NOT_LINKED.
5308  *  GST_FLOW_EOS: when all pads EOS or NOT_LINKED.
5309  */
5310 static GstFlowReturn
5311 gst_qtdemux_combine_flows (GstQTDemux * demux, QtDemuxStream * stream,
5312     GstFlowReturn ret)
5313 {
5314   GST_LOG_OBJECT (demux, "flow return: %s", gst_flow_get_name (ret));
5315
5316   if (stream->pad)
5317     ret = gst_flow_combiner_update_pad_flow (demux->flowcombiner, stream->pad,
5318         ret);
5319   else
5320     ret = gst_flow_combiner_update_flow (demux->flowcombiner, ret);
5321
5322   GST_LOG_OBJECT (demux, "combined flow return: %s", gst_flow_get_name (ret));
5323   return ret;
5324 }
5325
5326 /* the input buffer metadata must be writable. Returns NULL when the buffer is
5327  * completely clipped
5328  *
5329  * Should be used only with raw buffers */
5330 static GstBuffer *
5331 gst_qtdemux_clip_buffer (GstQTDemux * qtdemux, QtDemuxStream * stream,
5332     GstBuffer * buf)
5333 {
5334   guint64 start, stop, cstart, cstop, diff;
5335   GstClockTime pts, duration;
5336   gsize size, osize;
5337   gint num_rate, denom_rate;
5338   gint frame_size;
5339   gboolean clip_data;
5340   guint offset;
5341
5342   osize = size = gst_buffer_get_size (buf);
5343   offset = 0;
5344
5345   /* depending on the type, setup the clip parameters */
5346   if (stream->subtype == FOURCC_soun) {
5347     frame_size = CUR_STREAM (stream)->bytes_per_frame;
5348     num_rate = GST_SECOND;
5349     denom_rate = (gint) CUR_STREAM (stream)->rate;
5350     clip_data = TRUE;
5351   } else if (stream->subtype == FOURCC_vide) {
5352     frame_size = size;
5353     num_rate = CUR_STREAM (stream)->fps_n;
5354     denom_rate = CUR_STREAM (stream)->fps_d;
5355     clip_data = FALSE;
5356   } else
5357     goto wrong_type;
5358
5359   if (frame_size <= 0)
5360     goto bad_frame_size;
5361
5362   /* we can only clip if we have a valid pts */
5363   pts = GST_BUFFER_PTS (buf);
5364   if (G_UNLIKELY (!GST_CLOCK_TIME_IS_VALID (pts)))
5365     goto no_pts;
5366
5367   duration = GST_BUFFER_DURATION (buf);
5368
5369   if (G_UNLIKELY (!GST_CLOCK_TIME_IS_VALID (duration))) {
5370     duration =
5371         gst_util_uint64_scale_int (size / frame_size, num_rate, denom_rate);
5372   }
5373
5374   start = pts;
5375   stop = start + duration;
5376
5377   if (G_UNLIKELY (!gst_segment_clip (&stream->segment,
5378               GST_FORMAT_TIME, start, stop, &cstart, &cstop)))
5379     goto clipped;
5380
5381   /* see if some clipping happened */
5382   diff = cstart - start;
5383   if (diff > 0) {
5384     pts += diff;
5385     duration -= diff;
5386
5387     if (clip_data) {
5388       /* bring clipped time to samples and to bytes */
5389       diff = gst_util_uint64_scale_int (diff, denom_rate, num_rate);
5390       diff *= frame_size;
5391
5392       GST_DEBUG_OBJECT (qtdemux,
5393           "clipping start to %" GST_TIME_FORMAT " %"
5394           G_GUINT64_FORMAT " bytes", GST_TIME_ARGS (cstart), diff);
5395
5396       offset = diff;
5397       size -= diff;
5398     }
5399   }
5400   diff = stop - cstop;
5401   if (diff > 0) {
5402     duration -= diff;
5403
5404     if (clip_data) {
5405       /* bring clipped time to samples and then to bytes */
5406       diff = gst_util_uint64_scale_int (diff, denom_rate, num_rate);
5407       diff *= frame_size;
5408       GST_DEBUG_OBJECT (qtdemux,
5409           "clipping stop to %" GST_TIME_FORMAT " %" G_GUINT64_FORMAT
5410           " bytes", GST_TIME_ARGS (cstop), diff);
5411       size -= diff;
5412     }
5413   }
5414
5415   if (offset != 0 || size != osize)
5416     gst_buffer_resize (buf, offset, size);
5417
5418   GST_BUFFER_DTS (buf) = GST_CLOCK_TIME_NONE;
5419   GST_BUFFER_PTS (buf) = pts;
5420   GST_BUFFER_DURATION (buf) = duration;
5421
5422   return buf;
5423
5424   /* dropped buffer */
5425 wrong_type:
5426   {
5427     GST_DEBUG_OBJECT (qtdemux, "unknown stream type");
5428     return buf;
5429   }
5430 bad_frame_size:
5431   {
5432     GST_DEBUG_OBJECT (qtdemux, "bad frame size");
5433     return buf;
5434   }
5435 no_pts:
5436   {
5437     GST_DEBUG_OBJECT (qtdemux, "no pts on buffer");
5438     return buf;
5439   }
5440 clipped:
5441   {
5442     GST_DEBUG_OBJECT (qtdemux, "clipped buffer");
5443     gst_buffer_unref (buf);
5444     return NULL;
5445   }
5446 }
5447
5448 static GstBuffer *
5449 gst_qtdemux_align_buffer (GstQTDemux * demux,
5450     GstBuffer * buffer, gsize alignment)
5451 {
5452   GstMapInfo map;
5453
5454   gst_buffer_map (buffer, &map, GST_MAP_READ);
5455
5456   if (map.size < sizeof (guintptr)) {
5457     gst_buffer_unmap (buffer, &map);
5458     return buffer;
5459   }
5460
5461   if (((guintptr) map.data) & (alignment - 1)) {
5462     GstBuffer *new_buffer;
5463     GstAllocationParams params = { 0, alignment - 1, 0, 0, };
5464
5465     new_buffer = gst_buffer_new_allocate (NULL,
5466         gst_buffer_get_size (buffer), &params);
5467
5468     /* Copy data "by hand", so ensure alignment is kept: */
5469     gst_buffer_fill (new_buffer, 0, map.data, map.size);
5470
5471     gst_buffer_copy_into (new_buffer, buffer, GST_BUFFER_COPY_METADATA, 0, -1);
5472     GST_DEBUG_OBJECT (demux,
5473         "We want output aligned on %" G_GSIZE_FORMAT ", reallocated",
5474         alignment);
5475
5476     gst_buffer_unmap (buffer, &map);
5477     gst_buffer_unref (buffer);
5478
5479     return new_buffer;
5480   }
5481
5482   gst_buffer_unmap (buffer, &map);
5483   return buffer;
5484 }
5485
5486 static guint8 *
5487 convert_to_ccdata (const guint8 * ccpair, guint8 ccpair_size, guint field,
5488     gsize * res)
5489 {
5490   guint8 *storage;
5491   gsize i;
5492
5493   /* We are converting from pairs to triplets */
5494   *res = ccpair_size / 2 * 3;
5495   storage = g_malloc (*res);
5496   for (i = 0; i * 2 < ccpair_size; i += 1) {
5497     if (field == 1)
5498       storage[i * 3] = 0xfc;
5499     else
5500       storage[i * 3] = 0xfd;
5501     storage[i * 3 + 1] = ccpair[i * 2];
5502     storage[i * 3 + 2] = ccpair[i * 2 + 1];
5503   }
5504
5505   return storage;
5506 }
5507
5508 static guint8 *
5509 extract_cc_from_data (QtDemuxStream * stream, const guint8 * data, gsize size,
5510     gsize * cclen)
5511 {
5512   guint8 *res = NULL;
5513   guint32 atom_length, fourcc;
5514   QtDemuxStreamStsdEntry *stsd_entry;
5515
5516   GST_MEMDUMP ("caption atom", data, size);
5517
5518   /* There might be multiple atoms */
5519
5520   *cclen = 0;
5521   if (size < 8)
5522     goto invalid_cdat;
5523   atom_length = QT_UINT32 (data);
5524   fourcc = QT_FOURCC (data + 4);
5525   if (G_UNLIKELY (atom_length > size || atom_length == 8))
5526     goto invalid_cdat;
5527
5528   GST_DEBUG_OBJECT (stream->pad, "here");
5529
5530   /* Check if we have somethig compatible */
5531   stsd_entry = CUR_STREAM (stream);
5532   switch (stsd_entry->fourcc) {
5533     case FOURCC_c608:{
5534       guint8 *cdat = NULL, *cdt2 = NULL;
5535       gsize cdat_size = 0, cdt2_size = 0;
5536       /* Should be cdat or cdt2 */
5537       if (fourcc != FOURCC_cdat && fourcc != FOURCC_cdt2) {
5538         GST_WARNING_OBJECT (stream->pad,
5539             "Unknown data atom (%" GST_FOURCC_FORMAT ") for CEA608",
5540             GST_FOURCC_ARGS (fourcc));
5541         goto invalid_cdat;
5542       }
5543
5544       /* Convert to cc_data triplet */
5545       if (fourcc == FOURCC_cdat)
5546         cdat = convert_to_ccdata (data + 8, atom_length - 8, 1, &cdat_size);
5547       else
5548         cdt2 = convert_to_ccdata (data + 8, atom_length - 8, 2, &cdt2_size);
5549       GST_DEBUG_OBJECT (stream->pad, "size:%" G_GSIZE_FORMAT " atom_length:%u",
5550           size, atom_length);
5551
5552       /* Check for another atom ? */
5553       if (size > atom_length + 8) {
5554         guint32 new_atom_length = QT_UINT32 (data + atom_length);
5555         if (size >= atom_length + new_atom_length) {
5556           fourcc = QT_FOURCC (data + atom_length + 4);
5557           if (fourcc == FOURCC_cdat) {
5558             if (cdat == NULL)
5559               cdat =
5560                   convert_to_ccdata (data + atom_length + 8,
5561                   new_atom_length - 8, 1, &cdat_size);
5562             else
5563               GST_WARNING_OBJECT (stream->pad,
5564                   "Got multiple [cdat] atoms in a c608 sample. This is unsupported for now. Please file a bug");
5565           } else {
5566             if (cdt2 == NULL)
5567               cdt2 =
5568                   convert_to_ccdata (data + atom_length + 8,
5569                   new_atom_length - 8, 2, &cdt2_size);
5570             else
5571               GST_WARNING_OBJECT (stream->pad,
5572                   "Got multiple [cdt2] atoms in a c608 sample. This is unsupported for now. Please file a bug");
5573           }
5574         }
5575       }
5576
5577       *cclen = cdat_size + cdt2_size;
5578       res = g_malloc (*cclen);
5579       if (cdat_size)
5580         memcpy (res, cdat, cdat_size);
5581       if (cdt2_size)
5582         memcpy (res + cdat_size, cdt2, cdt2_size);
5583       g_free (cdat);
5584       g_free (cdt2);
5585     }
5586       break;
5587     case FOURCC_c708:
5588       if (fourcc != FOURCC_ccdp) {
5589         GST_WARNING_OBJECT (stream->pad,
5590             "Unknown data atom (%" GST_FOURCC_FORMAT ") for CEA708",
5591             GST_FOURCC_ARGS (fourcc));
5592         goto invalid_cdat;
5593       }
5594       *cclen = atom_length - 8;
5595       res = g_memdup (data + 8, *cclen);
5596       break;
5597     default:
5598       /* Keep this here in case other closed caption formats are added */
5599       g_assert_not_reached ();
5600       break;
5601   }
5602
5603   GST_MEMDUMP ("Output", res, *cclen);
5604   return res;
5605
5606   /* Errors */
5607 invalid_cdat:
5608   GST_WARNING ("[cdat] atom is too small or invalid");
5609   return NULL;
5610 }
5611
5612 /* the input buffer metadata must be writable,
5613  * but time/duration etc not yet set and need not be preserved */
5614 static GstBuffer *
5615 gst_qtdemux_process_buffer (GstQTDemux * qtdemux, QtDemuxStream * stream,
5616     GstBuffer * buf)
5617 {
5618   GstMapInfo map;
5619   guint nsize = 0;
5620   gchar *str;
5621
5622   /* not many cases for now */
5623   if (G_UNLIKELY (CUR_STREAM (stream)->fourcc == FOURCC_mp4s)) {
5624     /* send a one time dvd clut event */
5625     if (stream->pending_event && stream->pad)
5626       gst_pad_push_event (stream->pad, stream->pending_event);
5627     stream->pending_event = NULL;
5628   }
5629
5630   if (G_UNLIKELY (stream->subtype != FOURCC_text
5631           && stream->subtype != FOURCC_sbtl &&
5632           stream->subtype != FOURCC_subp && stream->subtype != FOURCC_clcp)) {
5633     return buf;
5634   }
5635
5636   gst_buffer_map (buf, &map, GST_MAP_READ);
5637
5638   /* empty buffer is sent to terminate previous subtitle */
5639   if (map.size <= 2) {
5640     gst_buffer_unmap (buf, &map);
5641     gst_buffer_unref (buf);
5642     return NULL;
5643   }
5644   if (stream->subtype == FOURCC_subp) {
5645     /* That's all the processing needed for subpictures */
5646     gst_buffer_unmap (buf, &map);
5647     return buf;
5648   }
5649
5650   if (stream->subtype == FOURCC_clcp) {
5651     guint8 *cc;
5652     gsize cclen = 0;
5653     /* For closed caption, we need to extract the information from the
5654      * [cdat],[cdt2] or [ccdp] atom */
5655     cc = extract_cc_from_data (stream, map.data, map.size, &cclen);
5656     gst_buffer_unmap (buf, &map);
5657     gst_buffer_unref (buf);
5658     if (cc) {
5659       buf = _gst_buffer_new_wrapped (cc, cclen, g_free);
5660     } else {
5661       /* Conversion failed or there's nothing */
5662       buf = NULL;
5663     }
5664     return buf;
5665   }
5666
5667   nsize = GST_READ_UINT16_BE (map.data);
5668   nsize = MIN (nsize, map.size - 2);
5669
5670   GST_LOG_OBJECT (qtdemux, "3GPP timed text subtitle: %d/%" G_GSIZE_FORMAT "",
5671       nsize, map.size);
5672
5673   /* takes care of UTF-8 validation or UTF-16 recognition,
5674    * no other encoding expected */
5675   str = gst_tag_freeform_string_to_utf8 ((gchar *) map.data + 2, nsize, NULL);
5676   gst_buffer_unmap (buf, &map);
5677   if (str) {
5678     gst_buffer_unref (buf);
5679     buf = _gst_buffer_new_wrapped (str, strlen (str), g_free);
5680   } else {
5681     /* this should not really happen unless the subtitle is corrupted */
5682     gst_buffer_unref (buf);
5683     buf = NULL;
5684   }
5685
5686   /* FIXME ? convert optional subsequent style info to markup */
5687
5688   return buf;
5689 }
5690
5691 /* Sets a buffer's attributes properly and pushes it downstream.
5692  * Also checks for additional actions and custom processing that may
5693  * need to be done first.
5694  */
5695 static GstFlowReturn
5696 gst_qtdemux_decorate_and_push_buffer (GstQTDemux * qtdemux,
5697     QtDemuxStream * stream, GstBuffer * buf,
5698     GstClockTime dts, GstClockTime pts, GstClockTime duration,
5699     gboolean keyframe, GstClockTime position, guint64 byte_position)
5700 {
5701   GstFlowReturn ret = GST_FLOW_OK;
5702
5703   /* offset the timestamps according to the edit list */
5704
5705   if (G_UNLIKELY (CUR_STREAM (stream)->fourcc == FOURCC_rtsp)) {
5706     gchar *url;
5707     GstMapInfo map;
5708
5709     gst_buffer_map (buf, &map, GST_MAP_READ);
5710     url = g_strndup ((gchar *) map.data, map.size);
5711     gst_buffer_unmap (buf, &map);
5712     if (url != NULL && strlen (url) != 0) {
5713       /* we have RTSP redirect now */
5714       gst_element_post_message (GST_ELEMENT_CAST (qtdemux),
5715           gst_message_new_element (GST_OBJECT_CAST (qtdemux),
5716               gst_structure_new ("redirect",
5717                   "new-location", G_TYPE_STRING, url, NULL)));
5718       qtdemux->posted_redirect = TRUE;
5719     } else {
5720       GST_WARNING_OBJECT (qtdemux, "Redirect URI of stream is empty, not "
5721           "posting");
5722     }
5723     g_free (url);
5724   }
5725
5726   /* position reporting */
5727   if (qtdemux->segment.rate >= 0) {
5728     qtdemux->segment.position = position;
5729     gst_qtdemux_sync_streams (qtdemux);
5730   }
5731
5732   if (G_UNLIKELY (!stream->pad)) {
5733     GST_DEBUG_OBJECT (qtdemux, "No output pad for stream, ignoring");
5734     gst_buffer_unref (buf);
5735     goto exit;
5736   }
5737
5738   /* send out pending buffers */
5739   while (stream->buffers) {
5740     GstBuffer *buffer = (GstBuffer *) stream->buffers->data;
5741
5742     if (G_UNLIKELY (stream->discont)) {
5743       GST_LOG_OBJECT (qtdemux, "marking discont buffer");
5744       GST_BUFFER_FLAG_SET (buffer, GST_BUFFER_FLAG_DISCONT);
5745       stream->discont = FALSE;
5746     } else {
5747       GST_BUFFER_FLAG_UNSET (buf, GST_BUFFER_FLAG_DISCONT);
5748     }
5749
5750     if (stream->alignment > 1)
5751       buffer = gst_qtdemux_align_buffer (qtdemux, buffer, stream->alignment);
5752     gst_pad_push (stream->pad, buffer);
5753
5754     stream->buffers = g_slist_delete_link (stream->buffers, stream->buffers);
5755   }
5756
5757   /* we're going to modify the metadata */
5758   buf = gst_buffer_make_writable (buf);
5759
5760   if (G_UNLIKELY (stream->need_process))
5761     buf = gst_qtdemux_process_buffer (qtdemux, stream, buf);
5762
5763   if (!buf) {
5764     goto exit;
5765   }
5766
5767   GST_BUFFER_DTS (buf) = dts;
5768   GST_BUFFER_PTS (buf) = pts;
5769   GST_BUFFER_DURATION (buf) = duration;
5770   GST_BUFFER_OFFSET (buf) = -1;
5771   GST_BUFFER_OFFSET_END (buf) = -1;
5772
5773   if (G_UNLIKELY (CUR_STREAM (stream)->rgb8_palette))
5774     gst_buffer_append_memory (buf,
5775         gst_memory_ref (CUR_STREAM (stream)->rgb8_palette));
5776
5777   if (G_UNLIKELY (CUR_STREAM (stream)->padding)) {
5778     gst_buffer_resize (buf, CUR_STREAM (stream)->padding, -1);
5779   }
5780 #if 0
5781   if (G_UNLIKELY (qtdemux->element_index)) {
5782     GstClockTime stream_time;
5783
5784     stream_time =
5785         gst_segment_to_stream_time (&stream->segment, GST_FORMAT_TIME,
5786         timestamp);
5787     if (GST_CLOCK_TIME_IS_VALID (stream_time)) {
5788       GST_LOG_OBJECT (qtdemux,
5789           "adding association %" GST_TIME_FORMAT "-> %"
5790           G_GUINT64_FORMAT, GST_TIME_ARGS (stream_time), byte_position);
5791       gst_index_add_association (qtdemux->element_index,
5792           qtdemux->index_id,
5793           keyframe ? GST_ASSOCIATION_FLAG_KEY_UNIT :
5794           GST_ASSOCIATION_FLAG_DELTA_UNIT, GST_FORMAT_TIME, stream_time,
5795           GST_FORMAT_BYTES, byte_position, NULL);
5796     }
5797   }
5798 #endif
5799
5800   if (stream->need_clip)
5801     buf = gst_qtdemux_clip_buffer (qtdemux, stream, buf);
5802
5803   if (G_UNLIKELY (buf == NULL))
5804     goto exit;
5805
5806   if (G_UNLIKELY (stream->discont)) {
5807     GST_LOG_OBJECT (qtdemux, "marking discont buffer");
5808     GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_DISCONT);
5809     stream->discont = FALSE;
5810   } else {
5811     GST_BUFFER_FLAG_UNSET (buf, GST_BUFFER_FLAG_DISCONT);
5812   }
5813
5814   if (!keyframe) {
5815     GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_DELTA_UNIT);
5816     stream->on_keyframe = FALSE;
5817   } else {
5818     stream->on_keyframe = TRUE;
5819   }
5820
5821
5822   GST_LOG_OBJECT (qtdemux,
5823       "Pushing buffer with dts %" GST_TIME_FORMAT ", pts %" GST_TIME_FORMAT
5824       ", duration %" GST_TIME_FORMAT " on pad %s", GST_TIME_ARGS (dts),
5825       GST_TIME_ARGS (pts), GST_TIME_ARGS (duration),
5826       GST_PAD_NAME (stream->pad));
5827
5828   if (stream->protected && stream->protection_scheme_type == FOURCC_cenc) {
5829     GstStructure *crypto_info;
5830     QtDemuxCencSampleSetInfo *info =
5831         (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
5832     gint index;
5833     GstEvent *event;
5834
5835     while ((event = g_queue_pop_head (&stream->protection_scheme_event_queue))) {
5836       GST_TRACE_OBJECT (stream->pad, "pushing protection event: %"
5837           GST_PTR_FORMAT, event);
5838       gst_pad_push_event (stream->pad, event);
5839     }
5840
5841     if (info->crypto_info == NULL) {
5842       GST_DEBUG_OBJECT (qtdemux,
5843           "cenc metadata hasn't been parsed yet, pushing buffer as if it wasn't encrypted");
5844     } else {
5845       /* The end of the crypto_info array matches our n_samples position,
5846        * so count backward from there */
5847       index = stream->sample_index - stream->n_samples + info->crypto_info->len;
5848       if (G_LIKELY (index >= 0 && index < info->crypto_info->len)) {
5849         /* steal structure from array */
5850         crypto_info = g_ptr_array_index (info->crypto_info, index);
5851         g_ptr_array_index (info->crypto_info, index) = NULL;
5852         GST_LOG_OBJECT (qtdemux, "attaching cenc metadata [%u/%u]", index,
5853             info->crypto_info->len);
5854         if (!crypto_info || !gst_buffer_add_protection_meta (buf, crypto_info))
5855           GST_ERROR_OBJECT (qtdemux,
5856               "failed to attach cenc metadata to buffer");
5857       } else {
5858         GST_INFO_OBJECT (qtdemux, "No crypto info with index %d and sample %d",
5859             index, stream->sample_index);
5860       }
5861     }
5862   }
5863
5864   if (stream->alignment > 1)
5865     buf = gst_qtdemux_align_buffer (qtdemux, buf, stream->alignment);
5866
5867   ret = gst_pad_push (stream->pad, buf);
5868
5869   if (GST_CLOCK_TIME_IS_VALID (pts) && GST_CLOCK_TIME_IS_VALID (duration)) {
5870     /* mark position in stream, we'll need this to know when to send GAP event */
5871     stream->segment.position = pts + duration;
5872   }
5873
5874 exit:
5875   return ret;
5876 }
5877
5878 static const QtDemuxRandomAccessEntry *
5879 gst_qtdemux_stream_seek_fragment (GstQTDemux * qtdemux, QtDemuxStream * stream,
5880     GstClockTime pos, gboolean after)
5881 {
5882   QtDemuxRandomAccessEntry *entries = stream->ra_entries;
5883   guint n_entries = stream->n_ra_entries;
5884   guint i;
5885
5886   /* we assume the table is sorted */
5887   for (i = 0; i < n_entries; ++i) {
5888     if (entries[i].ts > pos)
5889       break;
5890   }
5891
5892   /* FIXME: maybe save first moof_offset somewhere instead, but for now it's
5893    * probably okay to assume that the index lists the very first fragment */
5894   if (i == 0)
5895     return &entries[0];
5896
5897   if (after)
5898     return &entries[i];
5899   else
5900     return &entries[i - 1];
5901 }
5902
5903 static gboolean
5904 gst_qtdemux_do_fragmented_seek (GstQTDemux * qtdemux)
5905 {
5906   const QtDemuxRandomAccessEntry *best_entry = NULL;
5907   GList *iter;
5908
5909   GST_OBJECT_LOCK (qtdemux);
5910
5911   g_assert (qtdemux->n_streams > 0);
5912
5913   /* first see if we can determine where to go to using mfra,
5914    * before we start clearing things */
5915   for (iter = qtdemux->active_streams; iter; iter = g_list_next (iter)) {
5916     const QtDemuxRandomAccessEntry *entry;
5917     QtDemuxStream *stream;
5918     gboolean is_audio_or_video;
5919
5920     stream = QTDEMUX_STREAM (iter->data);
5921
5922     if (stream->ra_entries == NULL)
5923       continue;
5924
5925     if (stream->subtype == FOURCC_vide || stream->subtype == FOURCC_soun)
5926       is_audio_or_video = TRUE;
5927     else
5928       is_audio_or_video = FALSE;
5929
5930     entry =
5931         gst_qtdemux_stream_seek_fragment (qtdemux, stream,
5932         stream->time_position, !is_audio_or_video);
5933
5934     GST_INFO_OBJECT (stream->pad, "%" GST_TIME_FORMAT " at offset "
5935         "%" G_GUINT64_FORMAT, GST_TIME_ARGS (entry->ts), entry->moof_offset);
5936
5937     stream->pending_seek = entry;
5938
5939     /* decide position to jump to just based on audio/video tracks, not subs */
5940     if (!is_audio_or_video)
5941       continue;
5942
5943     if (best_entry == NULL || entry->moof_offset < best_entry->moof_offset)
5944       best_entry = entry;
5945   }
5946
5947   /* no luck, will handle seek otherwise */
5948   if (best_entry == NULL) {
5949     GST_OBJECT_UNLOCK (qtdemux);
5950     return FALSE;
5951   }
5952
5953   /* ok, now we can prepare for processing as of located moof */
5954   for (iter = qtdemux->active_streams; iter; iter = g_list_next (iter)) {
5955     QtDemuxStream *stream;
5956
5957     stream = QTDEMUX_STREAM (iter->data);
5958
5959     g_free (stream->samples);
5960     stream->samples = NULL;
5961     stream->n_samples = 0;
5962     stream->stbl_index = -1;    /* no samples have yet been parsed */
5963     stream->sample_index = -1;
5964
5965     if (stream->protection_scheme_info) {
5966       /* Clear out any old cenc crypto info entries as we'll move to a new moof */
5967       if (stream->protection_scheme_type == FOURCC_cenc) {
5968         QtDemuxCencSampleSetInfo *info =
5969             (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
5970         if (info->crypto_info) {
5971           g_ptr_array_free (info->crypto_info, TRUE);
5972           info->crypto_info = NULL;
5973         }
5974       }
5975     }
5976   }
5977
5978   GST_INFO_OBJECT (qtdemux, "seek to %" GST_TIME_FORMAT ", best fragment "
5979       "moof offset: %" G_GUINT64_FORMAT ", ts %" GST_TIME_FORMAT,
5980       GST_TIME_ARGS (QTDEMUX_FIRST_STREAM (qtdemux)->time_position),
5981       best_entry->moof_offset, GST_TIME_ARGS (best_entry->ts));
5982
5983   qtdemux->moof_offset = best_entry->moof_offset;
5984
5985   qtdemux_add_fragmented_samples (qtdemux);
5986
5987   GST_OBJECT_UNLOCK (qtdemux);
5988   return TRUE;
5989 }
5990
5991 static GstFlowReturn
5992 gst_qtdemux_loop_state_movie (GstQTDemux * qtdemux)
5993 {
5994   GstFlowReturn ret = GST_FLOW_OK;
5995   GstBuffer *buf = NULL;
5996   QtDemuxStream *stream, *target_stream = NULL;
5997   GstClockTime min_time;
5998   guint64 offset = 0;
5999   GstClockTime dts = GST_CLOCK_TIME_NONE;
6000   GstClockTime pts = GST_CLOCK_TIME_NONE;
6001   GstClockTime duration = 0;
6002   gboolean keyframe = FALSE;
6003   guint sample_size = 0;
6004   gboolean empty = 0;
6005   guint size;
6006   GList *iter;
6007
6008   gst_qtdemux_push_pending_newsegment (qtdemux);
6009
6010   if (qtdemux->fragmented_seek_pending) {
6011     GST_INFO_OBJECT (qtdemux, "pending fragmented seek");
6012     if (gst_qtdemux_do_fragmented_seek (qtdemux)) {
6013       GST_INFO_OBJECT (qtdemux, "fragmented seek done!");
6014       qtdemux->fragmented_seek_pending = FALSE;
6015     } else {
6016       GST_INFO_OBJECT (qtdemux, "fragmented seek still pending");
6017     }
6018   }
6019
6020   /* Figure out the next stream sample to output, min_time is expressed in
6021    * global time and runs over the edit list segments. */
6022   min_time = G_MAXUINT64;
6023   for (iter = qtdemux->active_streams; iter; iter = g_list_next (iter)) {
6024     GstClockTime position;
6025
6026     stream = QTDEMUX_STREAM (iter->data);
6027     position = stream->time_position;
6028
6029     /* position of -1 is EOS */
6030     if (position != GST_CLOCK_TIME_NONE && position < min_time) {
6031       min_time = position;
6032       target_stream = stream;
6033     }
6034   }
6035   /* all are EOS */
6036   if (G_UNLIKELY (target_stream == NULL)) {
6037     GST_DEBUG_OBJECT (qtdemux, "all streams are EOS");
6038     goto eos;
6039   }
6040
6041   /* check for segment end */
6042   if (G_UNLIKELY (qtdemux->segment.stop != -1
6043           && ((qtdemux->segment.rate >= 0 && qtdemux->segment.stop <= min_time)
6044               || (qtdemux->segment.rate < 0
6045                   && qtdemux->segment.start > min_time))
6046           && target_stream->on_keyframe)) {
6047     GST_DEBUG_OBJECT (qtdemux, "we reached the end of our segment.");
6048     target_stream->time_position = GST_CLOCK_TIME_NONE;
6049     goto eos_stream;
6050   }
6051
6052   /* gap events for subtitle streams */
6053   for (iter = qtdemux->active_streams; iter; iter = g_list_next (iter)) {
6054     stream = QTDEMUX_STREAM (iter->data);
6055     if (stream->pad && (stream->subtype == FOURCC_subp
6056             || stream->subtype == FOURCC_text
6057             || stream->subtype == FOURCC_sbtl)) {
6058       /* send one second gap events until the stream catches up */
6059       /* gaps can only be sent after segment is activated (segment.stop is no longer -1) */
6060       while (GST_CLOCK_TIME_IS_VALID (stream->segment.stop) &&
6061           GST_CLOCK_TIME_IS_VALID (stream->segment.position) &&
6062           stream->segment.position + GST_SECOND < min_time) {
6063         GstEvent *gap =
6064             gst_event_new_gap (stream->segment.position, GST_SECOND);
6065         gst_pad_push_event (stream->pad, gap);
6066         stream->segment.position += GST_SECOND;
6067       }
6068     }
6069   }
6070
6071   stream = target_stream;
6072   /* fetch info for the current sample of this stream */
6073   if (G_UNLIKELY (!gst_qtdemux_prepare_current_sample (qtdemux, stream, &empty,
6074               &offset, &sample_size, &dts, &pts, &duration, &keyframe)))
6075     goto eos_stream;
6076
6077   gst_qtdemux_stream_check_and_change_stsd_index (qtdemux, stream);
6078   if (stream->new_caps) {
6079     gst_qtdemux_configure_stream (qtdemux, stream);
6080     qtdemux_do_allocation (qtdemux, stream);
6081   }
6082
6083   /* If we're doing a keyframe-only trickmode, only push keyframes on video streams */
6084   if (G_UNLIKELY (qtdemux->
6085           segment.flags & GST_SEGMENT_FLAG_TRICKMODE_KEY_UNITS)) {
6086     if (stream->subtype == FOURCC_vide && !keyframe) {
6087       GST_LOG_OBJECT (qtdemux, "Skipping non-keyframe on track-id %u",
6088           stream->track_id);
6089       goto next;
6090     }
6091   }
6092
6093   GST_DEBUG_OBJECT (qtdemux,
6094       "pushing from track-id %u, empty %d offset %" G_GUINT64_FORMAT
6095       ", size %d, dts=%" GST_TIME_FORMAT ", pts=%" GST_TIME_FORMAT
6096       ", duration %" GST_TIME_FORMAT, stream->track_id, empty, offset,
6097       sample_size, GST_TIME_ARGS (dts), GST_TIME_ARGS (pts),
6098       GST_TIME_ARGS (duration));
6099
6100   if (G_UNLIKELY (empty)) {
6101     /* empty segment, push a gap if there's a second or more
6102      * difference and move to the next one */
6103     if ((pts + duration - stream->segment.position) >= GST_SECOND)
6104       gst_pad_push_event (stream->pad, gst_event_new_gap (pts, duration));
6105     stream->segment.position = pts + duration;
6106     goto next;
6107   }
6108
6109   /* hmm, empty sample, skip and move to next sample */
6110   if (G_UNLIKELY (sample_size <= 0))
6111     goto next;
6112
6113   /* last pushed sample was out of boundary, goto next sample */
6114   if (G_UNLIKELY (GST_PAD_LAST_FLOW_RETURN (stream->pad) == GST_FLOW_EOS))
6115     goto next;
6116
6117   if (stream->max_buffer_size == 0 || sample_size <= stream->max_buffer_size) {
6118     size = sample_size;
6119   } else {
6120     GST_DEBUG_OBJECT (qtdemux,
6121         "size %d larger than stream max_buffer_size %d, trimming",
6122         sample_size, stream->max_buffer_size);
6123     size =
6124         MIN (sample_size - stream->offset_in_sample, stream->max_buffer_size);
6125   }
6126
6127   if (qtdemux->cenc_aux_info_offset > 0) {
6128     GstMapInfo map;
6129     GstByteReader br;
6130     GstBuffer *aux_info = NULL;
6131
6132     /* pull the data stored before the sample */
6133     ret =
6134         gst_qtdemux_pull_atom (qtdemux, qtdemux->offset,
6135         offset + stream->offset_in_sample - qtdemux->offset, &aux_info);
6136     if (G_UNLIKELY (ret != GST_FLOW_OK))
6137       goto beach;
6138     gst_buffer_map (aux_info, &map, GST_MAP_READ);
6139     GST_DEBUG_OBJECT (qtdemux, "parsing cenc auxiliary info");
6140     gst_byte_reader_init (&br, map.data + 8, map.size);
6141     if (!qtdemux_parse_cenc_aux_info (qtdemux, stream, &br,
6142             qtdemux->cenc_aux_info_sizes, qtdemux->cenc_aux_sample_count)) {
6143       GST_ERROR_OBJECT (qtdemux, "failed to parse cenc auxiliary info");
6144       gst_buffer_unmap (aux_info, &map);
6145       gst_buffer_unref (aux_info);
6146       ret = GST_FLOW_ERROR;
6147       goto beach;
6148     }
6149     gst_buffer_unmap (aux_info, &map);
6150     gst_buffer_unref (aux_info);
6151   }
6152
6153   GST_LOG_OBJECT (qtdemux, "reading %d bytes @ %" G_GUINT64_FORMAT, size,
6154       offset);
6155
6156   if (stream->use_allocator) {
6157     /* if we have a per-stream allocator, use it */
6158     buf = gst_buffer_new_allocate (stream->allocator, size, &stream->params);
6159   }
6160
6161   ret = gst_qtdemux_pull_atom (qtdemux, offset + stream->offset_in_sample,
6162       size, &buf);
6163   if (G_UNLIKELY (ret != GST_FLOW_OK))
6164     goto beach;
6165
6166   if (size != sample_size) {
6167     pts += gst_util_uint64_scale_int (GST_SECOND,
6168         stream->offset_in_sample / CUR_STREAM (stream)->bytes_per_frame,
6169         stream->timescale);
6170     dts +=
6171         gst_util_uint64_scale_int (GST_SECOND,
6172         stream->offset_in_sample / CUR_STREAM (stream)->bytes_per_frame,
6173         stream->timescale);
6174     duration =
6175         gst_util_uint64_scale_int (GST_SECOND,
6176         size / CUR_STREAM (stream)->bytes_per_frame, stream->timescale);
6177   }
6178
6179   ret = gst_qtdemux_decorate_and_push_buffer (qtdemux, stream, buf,
6180       dts, pts, duration, keyframe, min_time, offset);
6181
6182   if (size != sample_size) {
6183     QtDemuxSample *sample = &stream->samples[stream->sample_index];
6184     QtDemuxSegment *segment = &stream->segments[stream->segment_index];
6185
6186     GstClockTime time_position = QTSTREAMTIME_TO_GSTTIME (stream,
6187         sample->timestamp +
6188         stream->offset_in_sample / CUR_STREAM (stream)->bytes_per_frame);
6189     if (time_position >= segment->media_start) {
6190       /* inside the segment, update time_position, looks very familiar to
6191        * GStreamer segments, doesn't it? */
6192       stream->time_position = (time_position - segment->media_start) +
6193           segment->time;
6194     } else {
6195       /* not yet in segment, time does not yet increment. This means
6196        * that we are still prerolling keyframes to the decoder so it can
6197        * decode the first sample of the segment. */
6198       stream->time_position = segment->time;
6199     }
6200   }
6201
6202   /* combine flows */
6203   ret = gst_qtdemux_combine_flows (qtdemux, stream, ret);
6204   /* ignore unlinked, we will not push on the pad anymore and we will EOS when
6205    * we have no more data for the pad to push */
6206   if (ret == GST_FLOW_EOS)
6207     ret = GST_FLOW_OK;
6208
6209   stream->offset_in_sample += size;
6210   if (stream->offset_in_sample >= sample_size) {
6211     gst_qtdemux_advance_sample (qtdemux, stream);
6212   }
6213   goto beach;
6214
6215 next:
6216   gst_qtdemux_advance_sample (qtdemux, stream);
6217
6218 beach:
6219   return ret;
6220
6221   /* special cases */
6222 eos:
6223   {
6224     GST_DEBUG_OBJECT (qtdemux, "No samples left for any streams - EOS");
6225     ret = GST_FLOW_EOS;
6226     goto beach;
6227   }
6228 eos_stream:
6229   {
6230     GST_DEBUG_OBJECT (qtdemux, "No samples left for stream");
6231     /* EOS will be raised if all are EOS */
6232     ret = GST_FLOW_OK;
6233     goto beach;
6234   }
6235 }
6236
6237 static void
6238 gst_qtdemux_loop (GstPad * pad)
6239 {
6240   GstQTDemux *qtdemux;
6241   guint64 cur_offset;
6242   GstFlowReturn ret;
6243
6244   qtdemux = GST_QTDEMUX (gst_pad_get_parent (pad));
6245
6246   cur_offset = qtdemux->offset;
6247   GST_LOG_OBJECT (qtdemux, "loop at position %" G_GUINT64_FORMAT ", state %s",
6248       cur_offset, qt_demux_state_string (qtdemux->state));
6249
6250   switch (qtdemux->state) {
6251     case QTDEMUX_STATE_INITIAL:
6252     case QTDEMUX_STATE_HEADER:
6253       ret = gst_qtdemux_loop_state_header (qtdemux);
6254       break;
6255     case QTDEMUX_STATE_MOVIE:
6256       ret = gst_qtdemux_loop_state_movie (qtdemux);
6257       if (qtdemux->segment.rate < 0 && ret == GST_FLOW_EOS) {
6258         ret = gst_qtdemux_seek_to_previous_keyframe (qtdemux);
6259       }
6260       break;
6261     default:
6262       /* ouch */
6263       goto invalid_state;
6264   }
6265
6266   /* if something went wrong, pause */
6267   if (ret != GST_FLOW_OK)
6268     goto pause;
6269
6270 done:
6271   gst_object_unref (qtdemux);
6272   return;
6273
6274   /* ERRORS */
6275 invalid_state:
6276   {
6277     GST_ELEMENT_ERROR (qtdemux, STREAM, FAILED,
6278         (NULL), ("streaming stopped, invalid state"));
6279     gst_pad_pause_task (pad);
6280     gst_qtdemux_push_event (qtdemux, gst_event_new_eos ());
6281     goto done;
6282   }
6283 pause:
6284   {
6285     const gchar *reason = gst_flow_get_name (ret);
6286
6287     GST_LOG_OBJECT (qtdemux, "pausing task, reason %s", reason);
6288
6289     gst_pad_pause_task (pad);
6290
6291     /* fatal errors need special actions */
6292     /* check EOS */
6293     if (ret == GST_FLOW_EOS) {
6294       if (qtdemux->n_streams == 0) {
6295         /* we have no streams, post an error */
6296         gst_qtdemux_post_no_playable_stream_error (qtdemux);
6297       }
6298       if (qtdemux->segment.flags & GST_SEEK_FLAG_SEGMENT) {
6299         gint64 stop;
6300
6301         if ((stop = qtdemux->segment.stop) == -1)
6302           stop = qtdemux->segment.duration;
6303
6304         if (qtdemux->segment.rate >= 0) {
6305           GstMessage *message;
6306           GstEvent *event;
6307
6308           GST_LOG_OBJECT (qtdemux, "Sending segment done, at end of segment");
6309           message = gst_message_new_segment_done (GST_OBJECT_CAST (qtdemux),
6310               GST_FORMAT_TIME, stop);
6311           event = gst_event_new_segment_done (GST_FORMAT_TIME, stop);
6312           if (qtdemux->segment_seqnum != GST_SEQNUM_INVALID) {
6313             gst_message_set_seqnum (message, qtdemux->segment_seqnum);
6314             gst_event_set_seqnum (event, qtdemux->segment_seqnum);
6315           }
6316           gst_element_post_message (GST_ELEMENT_CAST (qtdemux), message);
6317           gst_qtdemux_push_event (qtdemux, event);
6318         } else {
6319           GstMessage *message;
6320           GstEvent *event;
6321
6322           /*  For Reverse Playback */
6323           GST_LOG_OBJECT (qtdemux, "Sending segment done, at start of segment");
6324           message = gst_message_new_segment_done (GST_OBJECT_CAST (qtdemux),
6325               GST_FORMAT_TIME, qtdemux->segment.start);
6326           event = gst_event_new_segment_done (GST_FORMAT_TIME,
6327               qtdemux->segment.start);
6328           if (qtdemux->segment_seqnum != GST_SEQNUM_INVALID) {
6329             gst_message_set_seqnum (message, qtdemux->segment_seqnum);
6330             gst_event_set_seqnum (event, qtdemux->segment_seqnum);
6331           }
6332           gst_element_post_message (GST_ELEMENT_CAST (qtdemux), message);
6333           gst_qtdemux_push_event (qtdemux, event);
6334         }
6335       } else {
6336         GstEvent *event;
6337
6338         GST_LOG_OBJECT (qtdemux, "Sending EOS at end of segment");
6339         event = gst_event_new_eos ();
6340         if (qtdemux->segment_seqnum != GST_SEQNUM_INVALID)
6341           gst_event_set_seqnum (event, qtdemux->segment_seqnum);
6342         gst_qtdemux_push_event (qtdemux, event);
6343       }
6344     } else if (ret == GST_FLOW_NOT_LINKED || ret < GST_FLOW_EOS) {
6345       GST_ELEMENT_FLOW_ERROR (qtdemux, ret);
6346       gst_qtdemux_push_event (qtdemux, gst_event_new_eos ());
6347     }
6348     goto done;
6349   }
6350 }
6351
6352 /*
6353  * has_next_entry
6354  *
6355  * Returns if there are samples to be played.
6356  */
6357 static gboolean
6358 has_next_entry (GstQTDemux * demux)
6359 {
6360   QtDemuxStream *stream;
6361   GList *iter;
6362
6363   GST_DEBUG_OBJECT (demux, "Checking if there are samples not played yet");
6364
6365   for (iter = demux->active_streams; iter; iter = g_list_next (iter)) {
6366     stream = QTDEMUX_STREAM (iter->data);
6367
6368     if (stream->sample_index == -1) {
6369       stream->sample_index = 0;
6370       stream->offset_in_sample = 0;
6371     }
6372
6373     if (stream->sample_index >= stream->n_samples) {
6374       GST_LOG_OBJECT (demux, "track-id %u samples exhausted", stream->track_id);
6375       continue;
6376     }
6377     GST_DEBUG_OBJECT (demux, "Found a sample");
6378     return TRUE;
6379   }
6380
6381   GST_DEBUG_OBJECT (demux, "There wasn't any next sample");
6382   return FALSE;
6383 }
6384
6385 /*
6386  * next_entry_size
6387  *
6388  * Returns the size of the first entry at the current offset.
6389  * If -1, there are none (which means EOS or empty file).
6390  */
6391 static guint64
6392 next_entry_size (GstQTDemux * demux)
6393 {
6394   QtDemuxStream *stream, *target_stream = NULL;
6395   guint64 smalloffs = (guint64) - 1;
6396   QtDemuxSample *sample;
6397   GList *iter;
6398
6399   GST_LOG_OBJECT (demux, "Finding entry at offset %" G_GUINT64_FORMAT,
6400       demux->offset);
6401
6402   for (iter = demux->active_streams; iter; iter = g_list_next (iter)) {
6403     stream = QTDEMUX_STREAM (iter->data);
6404
6405     if (stream->sample_index == -1) {
6406       stream->sample_index = 0;
6407       stream->offset_in_sample = 0;
6408     }
6409
6410     if (stream->sample_index >= stream->n_samples) {
6411       GST_LOG_OBJECT (demux, "track-id %u samples exhausted", stream->track_id);
6412       continue;
6413     }
6414
6415     if (!qtdemux_parse_samples (demux, stream, stream->sample_index)) {
6416       GST_LOG_OBJECT (demux, "Parsing of index %u from stbl atom failed!",
6417           stream->sample_index);
6418       return -1;
6419     }
6420
6421     sample = &stream->samples[stream->sample_index];
6422
6423     GST_LOG_OBJECT (demux,
6424         "Checking track-id %u (sample_index:%d / offset:%" G_GUINT64_FORMAT
6425         " / size:%" G_GUINT32_FORMAT ")", stream->track_id,
6426         stream->sample_index, sample->offset, sample->size);
6427
6428     if (((smalloffs == -1)
6429             || (sample->offset < smalloffs)) && (sample->size)) {
6430       smalloffs = sample->offset;
6431       target_stream = stream;
6432     }
6433   }
6434
6435   if (!target_stream)
6436     return -1;
6437
6438   GST_LOG_OBJECT (demux,
6439       "track-id %u offset %" G_GUINT64_FORMAT " demux->offset :%"
6440       G_GUINT64_FORMAT, target_stream->track_id, smalloffs, demux->offset);
6441
6442   stream = target_stream;
6443   sample = &stream->samples[stream->sample_index];
6444
6445   if (sample->offset >= demux->offset) {
6446     demux->todrop = sample->offset - demux->offset;
6447     return sample->size + demux->todrop;
6448   }
6449
6450   GST_DEBUG_OBJECT (demux,
6451       "There wasn't any entry at offset %" G_GUINT64_FORMAT, demux->offset);
6452   return -1;
6453 }
6454
6455 static void
6456 gst_qtdemux_post_progress (GstQTDemux * demux, gint num, gint denom)
6457 {
6458   gint perc = (gint) ((gdouble) num * 100.0 / (gdouble) denom);
6459
6460   gst_element_post_message (GST_ELEMENT_CAST (demux),
6461       gst_message_new_element (GST_OBJECT_CAST (demux),
6462           gst_structure_new ("progress", "percent", G_TYPE_INT, perc, NULL)));
6463 }
6464
6465 static gboolean
6466 qtdemux_seek_offset (GstQTDemux * demux, guint64 offset)
6467 {
6468   GstEvent *event;
6469   gboolean res = 0;
6470
6471   GST_DEBUG_OBJECT (demux, "Seeking to %" G_GUINT64_FORMAT, offset);
6472
6473   event =
6474       gst_event_new_seek (1.0, GST_FORMAT_BYTES,
6475       GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_ACCURATE, GST_SEEK_TYPE_SET, offset,
6476       GST_SEEK_TYPE_NONE, -1);
6477
6478   /* store seqnum to drop flush events, they don't need to reach downstream */
6479   demux->offset_seek_seqnum = gst_event_get_seqnum (event);
6480   res = gst_pad_push_event (demux->sinkpad, event);
6481   demux->offset_seek_seqnum = GST_SEQNUM_INVALID;
6482
6483   return res;
6484 }
6485
6486 /* check for seekable upstream, above and beyond a mere query */
6487 static void
6488 gst_qtdemux_check_seekability (GstQTDemux * demux)
6489 {
6490   GstQuery *query;
6491   gboolean seekable = FALSE;
6492   gint64 start = -1, stop = -1;
6493
6494   if (demux->upstream_size)
6495     return;
6496
6497   if (demux->upstream_format_is_time)
6498     return;
6499
6500   query = gst_query_new_seeking (GST_FORMAT_BYTES);
6501   if (!gst_pad_peer_query (demux->sinkpad, query)) {
6502     GST_DEBUG_OBJECT (demux, "seeking query failed");
6503     goto done;
6504   }
6505
6506   gst_query_parse_seeking (query, NULL, &seekable, &start, &stop);
6507
6508   /* try harder to query upstream size if we didn't get it the first time */
6509   if (seekable && stop == -1) {
6510     GST_DEBUG_OBJECT (demux, "doing duration query to fix up unset stop");
6511     gst_pad_peer_query_duration (demux->sinkpad, GST_FORMAT_BYTES, &stop);
6512   }
6513
6514   /* if upstream doesn't know the size, it's likely that it's not seekable in
6515    * practice even if it technically may be seekable */
6516   if (seekable && (start != 0 || stop <= start)) {
6517     GST_DEBUG_OBJECT (demux, "seekable but unknown start/stop -> disable");
6518     seekable = FALSE;
6519   }
6520
6521 done:
6522   gst_query_unref (query);
6523
6524   GST_DEBUG_OBJECT (demux, "seekable: %d (%" G_GUINT64_FORMAT " - %"
6525       G_GUINT64_FORMAT ")", seekable, start, stop);
6526   demux->upstream_seekable = seekable;
6527   demux->upstream_size = seekable ? stop : -1;
6528 }
6529
6530 static void
6531 gst_qtdemux_drop_data (GstQTDemux * demux, gint bytes)
6532 {
6533   g_return_if_fail (bytes <= demux->todrop);
6534
6535   GST_LOG_OBJECT (demux, "Dropping %d bytes", bytes);
6536   gst_adapter_flush (demux->adapter, bytes);
6537   demux->neededbytes -= bytes;
6538   demux->offset += bytes;
6539   demux->todrop -= bytes;
6540 }
6541
6542 static void
6543 gst_qtdemux_check_send_pending_segment (GstQTDemux * demux)
6544 {
6545   if (G_UNLIKELY (demux->need_segment)) {
6546     gint i;
6547     GList *iter;
6548
6549     gst_qtdemux_push_pending_newsegment (demux);
6550     /* clear to send tags on all streams */
6551     for (iter = demux->active_streams, i = 0; iter;
6552         iter = g_list_next (iter), i++) {
6553       QtDemuxStream *stream = QTDEMUX_STREAM (iter->data);
6554       gst_qtdemux_push_tags (demux, stream);
6555       if (CUR_STREAM (stream)->sparse) {
6556         GST_INFO_OBJECT (demux, "Sending gap event on stream %d", i);
6557         gst_pad_push_event (stream->pad,
6558             gst_event_new_gap (stream->segment.position, GST_CLOCK_TIME_NONE));
6559       }
6560     }
6561   }
6562 }
6563
6564 /* Used for push mode only. */
6565 static void
6566 gst_qtdemux_send_gap_for_segment (GstQTDemux * demux,
6567     QtDemuxStream * stream, gint segment_index, GstClockTime pos)
6568 {
6569   GstClockTime ts, dur;
6570
6571   ts = pos;
6572   dur =
6573       stream->segments[segment_index].duration - (pos -
6574       stream->segments[segment_index].time);
6575   stream->time_position += dur;
6576
6577   /* Only gaps with a duration of at least one second are propagated.
6578    * Same workaround as in pull mode.
6579    * (See 2e45926a96ec5298c6ef29bf912e5e6a06dc3e0e) */
6580   if (dur >= GST_SECOND) {
6581     GstEvent *gap;
6582     gap = gst_event_new_gap (ts, dur);
6583
6584     GST_DEBUG_OBJECT (stream->pad, "Pushing gap for empty "
6585         "segment: %" GST_PTR_FORMAT, gap);
6586     gst_pad_push_event (stream->pad, gap);
6587   }
6588 }
6589
6590 static GstClockTime
6591 gst_qtdemux_streams_get_first_sample_ts (GstQTDemux * demux)
6592 {
6593   GstClockTime res = GST_CLOCK_TIME_NONE;
6594   GList *iter;
6595
6596   for (iter = demux->active_streams; iter; iter = g_list_next (iter)) {
6597     QtDemuxStream *stream = QTDEMUX_STREAM (iter->data);
6598     if (stream->n_samples) {
6599       res = MIN (QTSAMPLE_PTS (stream, &stream->samples[0]), res);
6600       res = MIN (QTSAMPLE_DTS (stream, &stream->samples[0]), res);
6601     }
6602   }
6603   return res;
6604 }
6605
6606 static GstClockTime
6607 gst_qtdemux_streams_have_samples (GstQTDemux * demux)
6608 {
6609   GList *iter;
6610
6611   for (iter = demux->active_streams; iter; iter = g_list_next (iter)) {
6612     QtDemuxStream *stream = QTDEMUX_STREAM (iter->data);
6613     if (stream->n_samples)
6614       return TRUE;
6615   }
6616   return FALSE;
6617 }
6618
6619 static GstFlowReturn
6620 gst_qtdemux_chain (GstPad * sinkpad, GstObject * parent, GstBuffer * inbuf)
6621 {
6622   GstQTDemux *demux;
6623
6624   demux = GST_QTDEMUX (parent);
6625
6626   GST_DEBUG_OBJECT (demux,
6627       "Received buffer pts:%" GST_TIME_FORMAT " dts:%" GST_TIME_FORMAT
6628       " offset:%" G_GUINT64_FORMAT " size:%" G_GSIZE_FORMAT " demux offset:%"
6629       G_GUINT64_FORMAT, GST_TIME_ARGS (GST_BUFFER_PTS (inbuf)),
6630       GST_TIME_ARGS (GST_BUFFER_DTS (inbuf)), GST_BUFFER_OFFSET (inbuf),
6631       gst_buffer_get_size (inbuf), demux->offset);
6632
6633   if (GST_BUFFER_FLAG_IS_SET (inbuf, GST_BUFFER_FLAG_DISCONT)) {
6634     gboolean is_gap_input = FALSE;
6635     GList *iter;
6636
6637     GST_DEBUG_OBJECT (demux, "Got DISCONT, marking all streams as DISCONT");
6638
6639     for (iter = demux->active_streams; iter; iter = g_list_next (iter)) {
6640       QTDEMUX_STREAM (iter->data)->discont = TRUE;
6641     }
6642
6643     /* Check if we can land back on our feet in the case where upstream is
6644      * handling the seeking/pushing of samples with gaps in between (like
6645      * in the case of trick-mode DASH for example) */
6646     if (demux->upstream_format_is_time
6647         && GST_BUFFER_OFFSET (inbuf) != GST_BUFFER_OFFSET_NONE) {
6648       for (iter = demux->active_streams; iter; iter = g_list_next (iter)) {
6649         guint32 res;
6650         QtDemuxStream *stream = QTDEMUX_STREAM (iter->data);
6651         GST_LOG_OBJECT (demux,
6652             "track-id #%u , checking if offset %" G_GUINT64_FORMAT
6653             " is a sample start", stream->track_id, GST_BUFFER_OFFSET (inbuf));
6654         res =
6655             gst_qtdemux_find_index_for_given_media_offset_linear (demux,
6656             stream, GST_BUFFER_OFFSET (inbuf));
6657         if (res != -1) {
6658           QtDemuxSample *sample = &stream->samples[res];
6659           GST_LOG_OBJECT (demux,
6660               "Checking if sample %d from track-id %u is valid (offset:%"
6661               G_GUINT64_FORMAT " size:%" G_GUINT32_FORMAT ")", res,
6662               stream->track_id, sample->offset, sample->size);
6663           if (sample->offset == GST_BUFFER_OFFSET (inbuf)) {
6664             GST_LOG_OBJECT (demux,
6665                 "new buffer corresponds to a valid sample : %" G_GUINT32_FORMAT,
6666                 res);
6667             is_gap_input = TRUE;
6668             /* We can go back to standard playback mode */
6669             demux->state = QTDEMUX_STATE_MOVIE;
6670             /* Remember which sample this stream is at */
6671             stream->sample_index = res;
6672             /* Finally update all push-based values to the expected values */
6673             demux->neededbytes = stream->samples[res].size;
6674             demux->offset = GST_BUFFER_OFFSET (inbuf);
6675             demux->mdatleft =
6676                 demux->mdatsize - demux->offset + demux->mdatoffset;
6677             demux->todrop = 0;
6678           }
6679         }
6680       }
6681       if (!is_gap_input) {
6682         GST_DEBUG_OBJECT (demux, "Resetting, actual DISCONT");
6683         /* Reset state if it's a real discont */
6684         demux->neededbytes = 16;
6685         demux->state = QTDEMUX_STATE_INITIAL;
6686         demux->offset = GST_BUFFER_OFFSET (inbuf);
6687         gst_adapter_clear (demux->adapter);
6688       }
6689     }
6690     /* Reverse fragmented playback, need to flush all we have before
6691      * consuming a new fragment.
6692      * The samples array have the timestamps calculated by accumulating the
6693      * durations but this won't work for reverse playback of fragments as
6694      * the timestamps of a subsequent fragment should be smaller than the
6695      * previously received one. */
6696     if (!is_gap_input && demux->fragmented && demux->segment.rate < 0) {
6697       gst_qtdemux_process_adapter (demux, TRUE);
6698       g_list_foreach (demux->active_streams,
6699           (GFunc) gst_qtdemux_stream_flush_samples_data, NULL);
6700     }
6701   }
6702
6703   gst_adapter_push (demux->adapter, inbuf);
6704
6705   GST_DEBUG_OBJECT (demux,
6706       "pushing in inbuf %p, neededbytes:%u, available:%" G_GSIZE_FORMAT, inbuf,
6707       demux->neededbytes, gst_adapter_available (demux->adapter));
6708
6709   return gst_qtdemux_process_adapter (demux, FALSE);
6710 }
6711
6712 static GstFlowReturn
6713 gst_qtdemux_process_adapter (GstQTDemux * demux, gboolean force)
6714 {
6715   GstFlowReturn ret = GST_FLOW_OK;
6716
6717   /* we never really mean to buffer that much */
6718   if (demux->neededbytes == -1) {
6719     goto eos;
6720   }
6721
6722   while (((gst_adapter_available (demux->adapter)) >= demux->neededbytes) &&
6723       (ret == GST_FLOW_OK || (ret == GST_FLOW_NOT_LINKED && force))) {
6724
6725 #ifndef GST_DISABLE_GST_DEBUG
6726     {
6727       guint64 discont_offset, distance_from_discont;
6728
6729       discont_offset = gst_adapter_offset_at_discont (demux->adapter);
6730       distance_from_discont =
6731           gst_adapter_distance_from_discont (demux->adapter);
6732
6733       GST_DEBUG_OBJECT (demux,
6734           "state:%s , demux->neededbytes:%d, demux->offset:%" G_GUINT64_FORMAT
6735           " adapter offset :%" G_GUINT64_FORMAT " (+ %" G_GUINT64_FORMAT
6736           " bytes)", qt_demux_state_string (demux->state), demux->neededbytes,
6737           demux->offset, discont_offset, distance_from_discont);
6738     }
6739 #endif
6740
6741     switch (demux->state) {
6742       case QTDEMUX_STATE_INITIAL:{
6743         const guint8 *data;
6744         guint32 fourcc;
6745         guint64 size;
6746
6747         gst_qtdemux_check_seekability (demux);
6748
6749         data = gst_adapter_map (demux->adapter, demux->neededbytes);
6750
6751         /* get fourcc/length, set neededbytes */
6752         extract_initial_length_and_fourcc ((guint8 *) data, demux->neededbytes,
6753             &size, &fourcc);
6754         gst_adapter_unmap (demux->adapter);
6755         data = NULL;
6756         GST_DEBUG_OBJECT (demux, "Peeking found [%" GST_FOURCC_FORMAT "] "
6757             "size: %" G_GUINT64_FORMAT, GST_FOURCC_ARGS (fourcc), size);
6758         if (size == 0) {
6759           GST_ELEMENT_ERROR (demux, STREAM, DEMUX,
6760               (_("This file is invalid and cannot be played.")),
6761               ("initial atom '%" GST_FOURCC_FORMAT "' has empty length",
6762                   GST_FOURCC_ARGS (fourcc)));
6763           ret = GST_FLOW_ERROR;
6764           break;
6765         }
6766         if (fourcc == FOURCC_mdat) {
6767           gint next_entry = next_entry_size (demux);
6768           if (demux->n_streams > 0 && (next_entry != -1 || !demux->fragmented)) {
6769             /* we have the headers, start playback */
6770             demux->state = QTDEMUX_STATE_MOVIE;
6771             demux->neededbytes = next_entry;
6772             demux->mdatleft = size;
6773             demux->mdatsize = demux->mdatleft;
6774           } else {
6775             /* no headers yet, try to get them */
6776             guint bs;
6777             gboolean res;
6778             guint64 old, target;
6779
6780           buffer_data:
6781             old = demux->offset;
6782             target = old + size;
6783
6784             /* try to jump over the atom with a seek */
6785             /* only bother if it seems worth doing so,
6786              * and avoids possible upstream/server problems */
6787             if (demux->upstream_seekable &&
6788                 demux->upstream_size > 4 * (1 << 20)) {
6789               res = qtdemux_seek_offset (demux, target);
6790             } else {
6791               GST_DEBUG_OBJECT (demux, "skipping seek");
6792               res = FALSE;
6793             }
6794
6795             if (res) {
6796               GST_DEBUG_OBJECT (demux, "seek success");
6797               /* remember the offset fo the first mdat so we can seek back to it
6798                * after we have the headers */
6799               if (fourcc == FOURCC_mdat && demux->first_mdat == -1) {
6800                 demux->first_mdat = old;
6801                 GST_DEBUG_OBJECT (demux, "first mdat at %" G_GUINT64_FORMAT,
6802                     demux->first_mdat);
6803               }
6804               /* seek worked, continue reading */
6805               demux->offset = target;
6806               demux->neededbytes = 16;
6807               demux->state = QTDEMUX_STATE_INITIAL;
6808             } else {
6809               /* seek failed, need to buffer */
6810               demux->offset = old;
6811               GST_DEBUG_OBJECT (demux, "seek failed/skipped");
6812               /* there may be multiple mdat (or alike) buffers */
6813               /* sanity check */
6814               if (demux->mdatbuffer)
6815                 bs = gst_buffer_get_size (demux->mdatbuffer);
6816               else
6817                 bs = 0;
6818               if (size + bs > 10 * (1 << 20))
6819                 goto no_moov;
6820               demux->state = QTDEMUX_STATE_BUFFER_MDAT;
6821               demux->neededbytes = size;
6822               if (!demux->mdatbuffer)
6823                 demux->mdatoffset = demux->offset;
6824             }
6825           }
6826         } else if (G_UNLIKELY (size > QTDEMUX_MAX_ATOM_SIZE)) {
6827           GST_ELEMENT_ERROR (demux, STREAM, DEMUX,
6828               (_("This file is invalid and cannot be played.")),
6829               ("atom %" GST_FOURCC_FORMAT " has bogus size %" G_GUINT64_FORMAT,
6830                   GST_FOURCC_ARGS (fourcc), size));
6831           ret = GST_FLOW_ERROR;
6832           break;
6833         } else {
6834           /* this means we already started buffering and still no moov header,
6835            * let's continue buffering everything till we get moov */
6836           if (demux->mdatbuffer && !(fourcc == FOURCC_moov
6837                   || fourcc == FOURCC_moof))
6838             goto buffer_data;
6839           demux->neededbytes = size;
6840           demux->state = QTDEMUX_STATE_HEADER;
6841         }
6842         break;
6843       }
6844       case QTDEMUX_STATE_HEADER:{
6845         const guint8 *data;
6846         guint32 fourcc;
6847
6848         GST_DEBUG_OBJECT (demux, "In header");
6849
6850         data = gst_adapter_map (demux->adapter, demux->neededbytes);
6851
6852         /* parse the header */
6853         extract_initial_length_and_fourcc (data, demux->neededbytes, NULL,
6854             &fourcc);
6855         if (fourcc == FOURCC_moov) {
6856           /* in usual fragmented setup we could try to scan for more
6857            * and end up at the the moov (after mdat) again */
6858           if (demux->got_moov && demux->n_streams > 0 &&
6859               (!demux->fragmented
6860                   || demux->last_moov_offset == demux->offset)) {
6861             GST_DEBUG_OBJECT (demux,
6862                 "Skipping moov atom as we have (this) one already");
6863           } else {
6864             GST_DEBUG_OBJECT (demux, "Parsing [moov]");
6865
6866             if (demux->got_moov && demux->fragmented) {
6867               GST_DEBUG_OBJECT (demux,
6868                   "Got a second moov, clean up data from old one");
6869               if (demux->moov_node_compressed) {
6870                 g_node_destroy (demux->moov_node_compressed);
6871                 if (demux->moov_node)
6872                   g_free (demux->moov_node->data);
6873               }
6874               demux->moov_node_compressed = NULL;
6875               if (demux->moov_node)
6876                 g_node_destroy (demux->moov_node);
6877               demux->moov_node = NULL;
6878             }
6879
6880             demux->last_moov_offset = demux->offset;
6881
6882             /* Update streams with new moov */
6883             demux->old_streams =
6884                 g_list_concat (demux->old_streams, demux->active_streams);
6885             demux->active_streams = NULL;
6886
6887             qtdemux_parse_moov (demux, data, demux->neededbytes);
6888             qtdemux_node_dump (demux, demux->moov_node);
6889             qtdemux_parse_tree (demux);
6890             qtdemux_prepare_streams (demux);
6891             QTDEMUX_EXPOSE_LOCK (demux);
6892             qtdemux_expose_streams (demux);
6893             QTDEMUX_EXPOSE_UNLOCK (demux);
6894
6895             demux->got_moov = TRUE;
6896             demux->need_segment = TRUE;
6897             gst_qtdemux_map_and_push_segments (demux, &demux->segment);
6898
6899             if (demux->moov_node_compressed) {
6900               g_node_destroy (demux->moov_node_compressed);
6901               g_free (demux->moov_node->data);
6902             }
6903             demux->moov_node_compressed = NULL;
6904             g_node_destroy (demux->moov_node);
6905             demux->moov_node = NULL;
6906             GST_DEBUG_OBJECT (demux, "Finished parsing the header");
6907           }
6908         } else if (fourcc == FOURCC_moof) {
6909           if ((demux->got_moov || demux->media_caps) && demux->fragmented) {
6910             guint64 dist = 0;
6911             GstClockTime prev_pts;
6912             guint64 prev_offset;
6913             guint64 adapter_discont_offset, adapter_discont_dist;
6914
6915             GST_DEBUG_OBJECT (demux, "Parsing [moof]");
6916
6917             /*
6918              * The timestamp of the moof buffer is relevant as some scenarios
6919              * won't have the initial timestamp in the atoms. Whenever a new
6920              * buffer has started, we get that buffer's PTS and use it as a base
6921              * timestamp for the trun entries.
6922              *
6923              * To keep track of the current buffer timestamp and starting point
6924              * we use gst_adapter_prev_pts that gives us the PTS and the distance
6925              * from the beggining of the buffer, with the distance and demux->offset
6926              * we know if it is still the same buffer or not.
6927              */
6928             prev_pts = gst_adapter_prev_pts (demux->adapter, &dist);
6929             prev_offset = demux->offset - dist;
6930             if (demux->fragment_start_offset == -1
6931                 || prev_offset > demux->fragment_start_offset) {
6932               demux->fragment_start_offset = prev_offset;
6933               demux->fragment_start = prev_pts;
6934               GST_DEBUG_OBJECT (demux,
6935                   "New fragment start found at: %" G_GUINT64_FORMAT " : %"
6936                   GST_TIME_FORMAT, demux->fragment_start_offset,
6937                   GST_TIME_ARGS (demux->fragment_start));
6938             }
6939
6940             /* We can't use prev_offset() here because this would require
6941              * upstream to set consistent and correct offsets on all buffers
6942              * since the discont. Nothing ever did that in the past and we
6943              * would break backwards compatibility here then.
6944              * Instead take the offset we had at the last discont and count
6945              * the bytes from there. This works with old code as there would
6946              * be no discont between moov and moof, and also works with
6947              * adaptivedemux which correctly sets offset and will set the
6948              * DISCONT flag accordingly when needed.
6949              *
6950              * We also only do this for upstream TIME segments as otherwise
6951              * there are potential backwards compatibility problems with
6952              * seeking in PUSH mode and upstream providing inconsistent
6953              * timestamps. */
6954             adapter_discont_offset =
6955                 gst_adapter_offset_at_discont (demux->adapter);
6956             adapter_discont_dist =
6957                 gst_adapter_distance_from_discont (demux->adapter);
6958
6959             GST_DEBUG_OBJECT (demux,
6960                 "demux offset %" G_GUINT64_FORMAT " adapter offset %"
6961                 G_GUINT64_FORMAT " (+ %" G_GUINT64_FORMAT " bytes)",
6962                 demux->offset, adapter_discont_offset, adapter_discont_dist);
6963
6964             if (demux->upstream_format_is_time) {
6965               demux->moof_offset = adapter_discont_offset;
6966               if (demux->moof_offset != GST_BUFFER_OFFSET_NONE)
6967                 demux->moof_offset += adapter_discont_dist;
6968               if (demux->moof_offset == GST_BUFFER_OFFSET_NONE)
6969                 demux->moof_offset = demux->offset;
6970             } else {
6971               demux->moof_offset = demux->offset;
6972             }
6973
6974             if (!qtdemux_parse_moof (demux, data, demux->neededbytes,
6975                     demux->moof_offset, NULL)) {
6976               gst_adapter_unmap (demux->adapter);
6977               ret = GST_FLOW_ERROR;
6978               goto done;
6979             }
6980
6981             /* in MSS we need to expose the pads after the first moof as we won't get a moov */
6982             if (demux->mss_mode && !demux->exposed) {
6983               QTDEMUX_EXPOSE_LOCK (demux);
6984               qtdemux_expose_streams (demux);
6985               QTDEMUX_EXPOSE_UNLOCK (demux);
6986             }
6987
6988             gst_qtdemux_check_send_pending_segment (demux);
6989           } else {
6990             GST_DEBUG_OBJECT (demux, "Discarding [moof]");
6991           }
6992         } else if (fourcc == FOURCC_ftyp) {
6993           GST_DEBUG_OBJECT (demux, "Parsing [ftyp]");
6994           qtdemux_parse_ftyp (demux, data, demux->neededbytes);
6995         } else if (fourcc == FOURCC_uuid) {
6996           GST_DEBUG_OBJECT (demux, "Parsing [uuid]");
6997           qtdemux_parse_uuid (demux, data, demux->neededbytes);
6998         } else if (fourcc == FOURCC_sidx) {
6999           GST_DEBUG_OBJECT (demux, "Parsing [sidx]");
7000           qtdemux_parse_sidx (demux, data, demux->neededbytes);
7001         } else {
7002           switch (fourcc) {
7003             case FOURCC_styp:
7004               /* [styp] is like a [ftyp], but in fragment header. We ignore it for now
7005                * FALLTHROUGH */
7006             case FOURCC_skip:
7007             case FOURCC_free:
7008               /* [free] and [skip] are padding atoms */
7009               GST_DEBUG_OBJECT (demux,
7010                   "Skipping fourcc while parsing header : %" GST_FOURCC_FORMAT,
7011                   GST_FOURCC_ARGS (fourcc));
7012               break;
7013             default:
7014               GST_WARNING_OBJECT (demux,
7015                   "Unknown fourcc while parsing header : %" GST_FOURCC_FORMAT,
7016                   GST_FOURCC_ARGS (fourcc));
7017               /* Let's jump that one and go back to initial state */
7018               break;
7019           }
7020         }
7021         gst_adapter_unmap (demux->adapter);
7022         data = NULL;
7023
7024         if (demux->mdatbuffer && demux->n_streams) {
7025           gsize remaining_data_size = 0;
7026
7027           /* the mdat was before the header */
7028           GST_DEBUG_OBJECT (demux, "We have n_streams:%d and mdatbuffer:%p",
7029               demux->n_streams, demux->mdatbuffer);
7030           /* restore our adapter/offset view of things with upstream;
7031            * put preceding buffered data ahead of current moov data.
7032            * This should also handle evil mdat, moov, mdat cases and alike */
7033           gst_adapter_flush (demux->adapter, demux->neededbytes);
7034
7035           /* Store any remaining data after the mdat for later usage */
7036           remaining_data_size = gst_adapter_available (demux->adapter);
7037           if (remaining_data_size > 0) {
7038             g_assert (demux->restoredata_buffer == NULL);
7039             demux->restoredata_buffer =
7040                 gst_adapter_take_buffer (demux->adapter, remaining_data_size);
7041             demux->restoredata_offset = demux->offset + demux->neededbytes;
7042             GST_DEBUG_OBJECT (demux,
7043                 "Stored %" G_GSIZE_FORMAT " post mdat bytes at offset %"
7044                 G_GUINT64_FORMAT, remaining_data_size,
7045                 demux->restoredata_offset);
7046           }
7047
7048           gst_adapter_push (demux->adapter, demux->mdatbuffer);
7049           demux->mdatbuffer = NULL;
7050           demux->offset = demux->mdatoffset;
7051           demux->neededbytes = next_entry_size (demux);
7052           demux->state = QTDEMUX_STATE_MOVIE;
7053           demux->mdatleft = gst_adapter_available (demux->adapter);
7054           demux->mdatsize = demux->mdatleft;
7055         } else {
7056           GST_DEBUG_OBJECT (demux, "Carrying on normally");
7057           gst_adapter_flush (demux->adapter, demux->neededbytes);
7058
7059           /* only go back to the mdat if there are samples to play */
7060           if (demux->got_moov && demux->first_mdat != -1
7061               && has_next_entry (demux)) {
7062             gboolean res;
7063
7064             /* we need to seek back */
7065             res = qtdemux_seek_offset (demux, demux->first_mdat);
7066             if (res) {
7067               demux->offset = demux->first_mdat;
7068             } else {
7069               GST_DEBUG_OBJECT (demux, "Seek back failed");
7070             }
7071           } else {
7072             demux->offset += demux->neededbytes;
7073           }
7074           demux->neededbytes = 16;
7075           demux->state = QTDEMUX_STATE_INITIAL;
7076         }
7077
7078         break;
7079       }
7080       case QTDEMUX_STATE_BUFFER_MDAT:{
7081         GstBuffer *buf;
7082         guint8 fourcc[4];
7083
7084         GST_DEBUG_OBJECT (demux, "Got our buffer at offset %" G_GUINT64_FORMAT,
7085             demux->offset);
7086         buf = gst_adapter_take_buffer (demux->adapter, demux->neededbytes);
7087         gst_buffer_extract (buf, 0, fourcc, 4);
7088         GST_DEBUG_OBJECT (demux, "mdatbuffer starts with %" GST_FOURCC_FORMAT,
7089             GST_FOURCC_ARGS (QT_FOURCC (fourcc)));
7090         if (demux->mdatbuffer)
7091           demux->mdatbuffer = gst_buffer_append (demux->mdatbuffer, buf);
7092         else
7093           demux->mdatbuffer = buf;
7094         demux->offset += demux->neededbytes;
7095         demux->neededbytes = 16;
7096         demux->state = QTDEMUX_STATE_INITIAL;
7097         gst_qtdemux_post_progress (demux, 1, 1);
7098
7099         break;
7100       }
7101       case QTDEMUX_STATE_MOVIE:{
7102         QtDemuxStream *stream = NULL;
7103         QtDemuxSample *sample;
7104         GstClockTime dts, pts, duration;
7105         gboolean keyframe;
7106         GList *iter;
7107
7108         GST_DEBUG_OBJECT (demux,
7109             "BEGIN // in MOVIE for offset %" G_GUINT64_FORMAT, demux->offset);
7110
7111         if (demux->fragmented) {
7112           GST_DEBUG_OBJECT (demux, "mdat remaining %" G_GUINT64_FORMAT,
7113               demux->mdatleft);
7114           if (G_LIKELY (demux->todrop < demux->mdatleft)) {
7115             /* if needed data starts within this atom,
7116              * then it should not exceed this atom */
7117             if (G_UNLIKELY (demux->neededbytes > demux->mdatleft)) {
7118               GST_ELEMENT_ERROR (demux, STREAM, DEMUX,
7119                   (_("This file is invalid and cannot be played.")),
7120                   ("sample data crosses atom boundary"));
7121               ret = GST_FLOW_ERROR;
7122               break;
7123             }
7124             demux->mdatleft -= demux->neededbytes;
7125           } else {
7126             GST_DEBUG_OBJECT (demux, "data atom emptied; resuming atom scan");
7127             /* so we are dropping more than left in this atom */
7128             gst_qtdemux_drop_data (demux, demux->mdatleft);
7129             demux->mdatleft = 0;
7130
7131             /* need to resume atom parsing so we do not miss any other pieces */
7132             demux->state = QTDEMUX_STATE_INITIAL;
7133             demux->neededbytes = 16;
7134
7135             /* check if there was any stored post mdat data from previous buffers */
7136             if (demux->restoredata_buffer) {
7137               g_assert (gst_adapter_available (demux->adapter) == 0);
7138
7139               gst_adapter_push (demux->adapter, demux->restoredata_buffer);
7140               demux->restoredata_buffer = NULL;
7141               demux->offset = demux->restoredata_offset;
7142             }
7143
7144             break;
7145           }
7146         }
7147
7148         if (demux->todrop) {
7149           if (demux->cenc_aux_info_offset > 0) {
7150             GstByteReader br;
7151             const guint8 *data;
7152
7153             GST_DEBUG_OBJECT (demux, "parsing cenc auxiliary info");
7154             data = gst_adapter_map (demux->adapter, demux->todrop);
7155             gst_byte_reader_init (&br, data + 8, demux->todrop);
7156             if (!qtdemux_parse_cenc_aux_info (demux,
7157                     QTDEMUX_FIRST_STREAM (demux), &br,
7158                     demux->cenc_aux_info_sizes, demux->cenc_aux_sample_count)) {
7159               GST_ERROR_OBJECT (demux, "failed to parse cenc auxiliary info");
7160               ret = GST_FLOW_ERROR;
7161               gst_adapter_unmap (demux->adapter);
7162               g_free (demux->cenc_aux_info_sizes);
7163               demux->cenc_aux_info_sizes = NULL;
7164               goto done;
7165             }
7166             demux->cenc_aux_info_offset = 0;
7167             g_free (demux->cenc_aux_info_sizes);
7168             demux->cenc_aux_info_sizes = NULL;
7169             gst_adapter_unmap (demux->adapter);
7170           }
7171           gst_qtdemux_drop_data (demux, demux->todrop);
7172         }
7173
7174         /* first buffer? */
7175         /* initial newsegment sent here after having added pads,
7176          * possible others in sink_event */
7177         gst_qtdemux_check_send_pending_segment (demux);
7178
7179         /* Figure out which stream this packet belongs to */
7180         for (iter = demux->active_streams; iter; iter = g_list_next (iter)) {
7181           stream = QTDEMUX_STREAM (iter->data);
7182           if (stream->sample_index >= stream->n_samples) {
7183             /* reset to be checked below G_UNLIKELY (stream == NULL) */
7184             stream = NULL;
7185             continue;
7186           }
7187           GST_LOG_OBJECT (demux,
7188               "Checking track-id %u (sample_index:%d / offset:%"
7189               G_GUINT64_FORMAT " / size:%d)", stream->track_id,
7190               stream->sample_index,
7191               stream->samples[stream->sample_index].offset,
7192               stream->samples[stream->sample_index].size);
7193
7194           if (stream->samples[stream->sample_index].offset == demux->offset)
7195             break;
7196         }
7197
7198         if (G_UNLIKELY (stream == NULL))
7199           goto unknown_stream;
7200
7201         gst_qtdemux_stream_check_and_change_stsd_index (demux, stream);
7202
7203         if (stream->new_caps) {
7204           gst_qtdemux_configure_stream (demux, stream);
7205         }
7206
7207         /* Put data in a buffer, set timestamps, caps, ... */
7208         sample = &stream->samples[stream->sample_index];
7209
7210         if (G_LIKELY (!(STREAM_IS_EOS (stream)))) {
7211           GST_DEBUG_OBJECT (demux, "stream : %" GST_FOURCC_FORMAT,
7212               GST_FOURCC_ARGS (CUR_STREAM (stream)->fourcc));
7213
7214           dts = QTSAMPLE_DTS (stream, sample);
7215           pts = QTSAMPLE_PTS (stream, sample);
7216           duration = QTSAMPLE_DUR_DTS (stream, sample, dts);
7217           keyframe = QTSAMPLE_KEYFRAME (stream, sample);
7218
7219           /* check for segment end */
7220           if (G_UNLIKELY (demux->segment.stop != -1
7221                   && demux->segment.stop <= pts && stream->on_keyframe)) {
7222             GST_DEBUG_OBJECT (demux, "we reached the end of our segment.");
7223             stream->time_position = GST_CLOCK_TIME_NONE;        /* this means EOS */
7224
7225             /* skip this data, stream is EOS */
7226             gst_adapter_flush (demux->adapter, demux->neededbytes);
7227             demux->offset += demux->neededbytes;
7228
7229             /* check if all streams are eos */
7230             ret = GST_FLOW_EOS;
7231             for (iter = demux->active_streams; iter; iter = g_list_next (iter)) {
7232               if (!STREAM_IS_EOS (QTDEMUX_STREAM (iter->data))) {
7233                 ret = GST_FLOW_OK;
7234                 break;
7235               }
7236             }
7237           } else {
7238             GstBuffer *outbuf;
7239
7240             outbuf =
7241                 gst_adapter_take_buffer (demux->adapter, demux->neededbytes);
7242
7243             /* FIXME: should either be an assert or a plain check */
7244             g_return_val_if_fail (outbuf != NULL, GST_FLOW_ERROR);
7245
7246             ret = gst_qtdemux_decorate_and_push_buffer (demux, stream, outbuf,
7247                 dts, pts, duration, keyframe, dts, demux->offset);
7248           }
7249
7250           /* combine flows */
7251           ret = gst_qtdemux_combine_flows (demux, stream, ret);
7252         } else {
7253           /* skip this data, stream is EOS */
7254           gst_adapter_flush (demux->adapter, demux->neededbytes);
7255         }
7256
7257         stream->sample_index++;
7258         stream->offset_in_sample = 0;
7259
7260         /* update current offset and figure out size of next buffer */
7261         GST_LOG_OBJECT (demux, "increasing offset %" G_GUINT64_FORMAT " by %u",
7262             demux->offset, demux->neededbytes);
7263         demux->offset += demux->neededbytes;
7264         GST_LOG_OBJECT (demux, "offset is now %" G_GUINT64_FORMAT,
7265             demux->offset);
7266
7267
7268         if (ret == GST_FLOW_EOS) {
7269           GST_DEBUG_OBJECT (demux, "All streams are EOS, signal upstream");
7270           demux->neededbytes = -1;
7271           goto eos;
7272         }
7273
7274         if ((demux->neededbytes = next_entry_size (demux)) == -1) {
7275           if (demux->fragmented) {
7276             GST_DEBUG_OBJECT (demux, "(temporarily) out of fragmented samples");
7277             /* there may be more to follow, only finish this atom */
7278             demux->todrop = demux->mdatleft;
7279             demux->neededbytes = demux->todrop;
7280             break;
7281           }
7282           goto eos;
7283         }
7284         if (ret != GST_FLOW_OK && ret != GST_FLOW_NOT_LINKED) {
7285           goto non_ok_unlinked_flow;
7286         }
7287         break;
7288       }
7289       default:
7290         goto invalid_state;
7291     }
7292   }
7293
7294   /* when buffering movie data, at least show user something is happening */
7295   if (ret == GST_FLOW_OK && demux->state == QTDEMUX_STATE_BUFFER_MDAT &&
7296       gst_adapter_available (demux->adapter) <= demux->neededbytes) {
7297     gst_qtdemux_post_progress (demux, gst_adapter_available (demux->adapter),
7298         demux->neededbytes);
7299   }
7300 done:
7301
7302   return ret;
7303
7304   /* ERRORS */
7305 non_ok_unlinked_flow:
7306   {
7307     GST_DEBUG_OBJECT (demux, "Stopping, combined return flow %s",
7308         gst_flow_get_name (ret));
7309     return ret;
7310   }
7311 unknown_stream:
7312   {
7313     GST_ELEMENT_ERROR (demux, STREAM, FAILED, (NULL), ("unknown stream found"));
7314     ret = GST_FLOW_ERROR;
7315     goto done;
7316   }
7317 eos:
7318   {
7319     GST_DEBUG_OBJECT (demux, "no next entry, EOS");
7320     ret = GST_FLOW_EOS;
7321     goto done;
7322   }
7323 invalid_state:
7324   {
7325     GST_ELEMENT_ERROR (demux, STREAM, FAILED,
7326         (NULL), ("qtdemuxer invalid state %d", demux->state));
7327     ret = GST_FLOW_ERROR;
7328     goto done;
7329   }
7330 no_moov:
7331   {
7332     GST_ELEMENT_ERROR (demux, STREAM, FAILED,
7333         (NULL), ("no 'moov' atom within the first 10 MB"));
7334     ret = GST_FLOW_ERROR;
7335     goto done;
7336   }
7337 }
7338
7339 static gboolean
7340 qtdemux_sink_activate (GstPad * sinkpad, GstObject * parent)
7341 {
7342   GstQuery *query;
7343   gboolean pull_mode;
7344
7345   query = gst_query_new_scheduling ();
7346
7347   if (!gst_pad_peer_query (sinkpad, query)) {
7348     gst_query_unref (query);
7349     goto activate_push;
7350   }
7351
7352   pull_mode = gst_query_has_scheduling_mode_with_flags (query,
7353       GST_PAD_MODE_PULL, GST_SCHEDULING_FLAG_SEEKABLE);
7354   gst_query_unref (query);
7355
7356   if (!pull_mode)
7357     goto activate_push;
7358
7359   GST_DEBUG_OBJECT (sinkpad, "activating pull");
7360   return gst_pad_activate_mode (sinkpad, GST_PAD_MODE_PULL, TRUE);
7361
7362 activate_push:
7363   {
7364     GST_DEBUG_OBJECT (sinkpad, "activating push");
7365     return gst_pad_activate_mode (sinkpad, GST_PAD_MODE_PUSH, TRUE);
7366   }
7367 }
7368
7369 static gboolean
7370 qtdemux_sink_activate_mode (GstPad * sinkpad, GstObject * parent,
7371     GstPadMode mode, gboolean active)
7372 {
7373   gboolean res;
7374   GstQTDemux *demux = GST_QTDEMUX (parent);
7375
7376   switch (mode) {
7377     case GST_PAD_MODE_PUSH:
7378       demux->pullbased = FALSE;
7379       res = TRUE;
7380       break;
7381     case GST_PAD_MODE_PULL:
7382       if (active) {
7383         demux->pullbased = TRUE;
7384         res = gst_pad_start_task (sinkpad, (GstTaskFunction) gst_qtdemux_loop,
7385             sinkpad, NULL);
7386       } else {
7387         res = gst_pad_stop_task (sinkpad);
7388       }
7389       break;
7390     default:
7391       res = FALSE;
7392       break;
7393   }
7394   return res;
7395 }
7396
7397 #ifdef HAVE_ZLIB
7398 static void *
7399 qtdemux_inflate (void *z_buffer, guint z_length, guint * length)
7400 {
7401   guint8 *buffer;
7402   z_stream z;
7403   int ret;
7404
7405   memset (&z, 0, sizeof (z));
7406   z.zalloc = NULL;
7407   z.zfree = NULL;
7408   z.opaque = NULL;
7409
7410   if ((ret = inflateInit (&z)) != Z_OK) {
7411     GST_ERROR ("inflateInit() returned %d", ret);
7412     return NULL;
7413   }
7414
7415   z.next_in = z_buffer;
7416   z.avail_in = z_length;
7417
7418   buffer = (guint8 *) g_malloc (*length);
7419   z.avail_out = *length;
7420   z.next_out = (Bytef *) buffer;
7421   do {
7422     ret = inflate (&z, Z_NO_FLUSH);
7423     if (ret == Z_STREAM_END) {
7424       break;
7425     } else if (ret != Z_OK) {
7426       GST_WARNING ("inflate() returned %d", ret);
7427       break;
7428     }
7429
7430     *length += 4096;
7431     buffer = (guint8 *) g_realloc (buffer, *length);
7432     z.next_out = (Bytef *) (buffer + z.total_out);
7433     z.avail_out += 4096;
7434   } while (z.avail_in > 0);
7435
7436   if (ret != Z_STREAM_END) {
7437     g_free (buffer);
7438     buffer = NULL;
7439     *length = 0;
7440   } else {
7441     *length = z.total_out;
7442   }
7443
7444   inflateEnd (&z);
7445
7446   return buffer;
7447 }
7448 #endif /* HAVE_ZLIB */
7449
7450 static gboolean
7451 qtdemux_parse_moov (GstQTDemux * qtdemux, const guint8 * buffer, guint length)
7452 {
7453   GNode *cmov;
7454
7455   qtdemux->moov_node = g_node_new ((guint8 *) buffer);
7456
7457   /* counts as header data */
7458   qtdemux->header_size += length;
7459
7460   GST_DEBUG_OBJECT (qtdemux, "parsing 'moov' atom");
7461   qtdemux_parse_node (qtdemux, qtdemux->moov_node, buffer, length);
7462
7463   cmov = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_cmov);
7464   if (cmov) {
7465     guint32 method;
7466     GNode *dcom;
7467     GNode *cmvd;
7468     guint32 dcom_len;
7469
7470     dcom = qtdemux_tree_get_child_by_type (cmov, FOURCC_dcom);
7471     cmvd = qtdemux_tree_get_child_by_type (cmov, FOURCC_cmvd);
7472     if (dcom == NULL || cmvd == NULL)
7473       goto invalid_compression;
7474
7475     dcom_len = QT_UINT32 (dcom->data);
7476     if (dcom_len < 12)
7477       goto invalid_compression;
7478
7479     method = QT_FOURCC ((guint8 *) dcom->data + 8);
7480     switch (method) {
7481 #ifdef HAVE_ZLIB
7482       case FOURCC_zlib:{
7483         guint uncompressed_length;
7484         guint compressed_length;
7485         guint8 *buf;
7486         guint32 cmvd_len;
7487
7488         cmvd_len = QT_UINT32 ((guint8 *) cmvd->data);
7489         if (cmvd_len < 12)
7490           goto invalid_compression;
7491
7492         uncompressed_length = QT_UINT32 ((guint8 *) cmvd->data + 8);
7493         compressed_length = cmvd_len - 12;
7494         GST_LOG ("length = %u", uncompressed_length);
7495
7496         buf =
7497             (guint8 *) qtdemux_inflate ((guint8 *) cmvd->data + 12,
7498             compressed_length, &uncompressed_length);
7499
7500         if (buf) {
7501           qtdemux->moov_node_compressed = qtdemux->moov_node;
7502           qtdemux->moov_node = g_node_new (buf);
7503
7504           qtdemux_parse_node (qtdemux, qtdemux->moov_node, buf,
7505               uncompressed_length);
7506         }
7507         break;
7508       }
7509 #endif /* HAVE_ZLIB */
7510       default:
7511         GST_WARNING_OBJECT (qtdemux, "unknown or unhandled header compression "
7512             "type %" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (method));
7513         break;
7514     }
7515   }
7516   return TRUE;
7517
7518   /* ERRORS */
7519 invalid_compression:
7520   {
7521     GST_ERROR_OBJECT (qtdemux, "invalid compressed header");
7522     return FALSE;
7523   }
7524 }
7525
7526 static gboolean
7527 qtdemux_parse_container (GstQTDemux * qtdemux, GNode * node, const guint8 * buf,
7528     const guint8 * end)
7529 {
7530   while (G_UNLIKELY (buf < end)) {
7531     GNode *child;
7532     guint32 len;
7533
7534     if (G_UNLIKELY (buf + 4 > end)) {
7535       GST_LOG_OBJECT (qtdemux, "buffer overrun");
7536       break;
7537     }
7538     len = QT_UINT32 (buf);
7539     if (G_UNLIKELY (len == 0)) {
7540       GST_LOG_OBJECT (qtdemux, "empty container");
7541       break;
7542     }
7543     if (G_UNLIKELY (len < 8)) {
7544       GST_WARNING_OBJECT (qtdemux, "length too short (%d < 8)", len);
7545       break;
7546     }
7547     if (G_UNLIKELY (len > (end - buf))) {
7548       GST_WARNING_OBJECT (qtdemux, "length too long (%d > %d)", len,
7549           (gint) (end - buf));
7550       break;
7551     }
7552
7553     child = g_node_new ((guint8 *) buf);
7554     g_node_append (node, child);
7555     GST_LOG_OBJECT (qtdemux, "adding new node of len %d", len);
7556     qtdemux_parse_node (qtdemux, child, buf, len);
7557
7558     buf += len;
7559   }
7560   return TRUE;
7561 }
7562
7563 static gboolean
7564 qtdemux_parse_theora_extension (GstQTDemux * qtdemux, QtDemuxStream * stream,
7565     GNode * xdxt)
7566 {
7567   int len = QT_UINT32 (xdxt->data);
7568   guint8 *buf = xdxt->data;
7569   guint8 *end = buf + len;
7570   GstBuffer *buffer;
7571
7572   /* skip size and type */
7573   buf += 8;
7574   end -= 8;
7575
7576   while (buf < end) {
7577     gint size;
7578     guint32 type;
7579
7580     size = QT_UINT32 (buf);
7581     type = QT_FOURCC (buf + 4);
7582
7583     GST_LOG_OBJECT (qtdemux, "%p %p", buf, end);
7584
7585     if (buf + size > end || size <= 0)
7586       break;
7587
7588     buf += 8;
7589     size -= 8;
7590
7591     GST_WARNING_OBJECT (qtdemux, "have cookie %" GST_FOURCC_FORMAT,
7592         GST_FOURCC_ARGS (type));
7593
7594     switch (type) {
7595       case FOURCC_tCtH:
7596         buffer = gst_buffer_new_and_alloc (size);
7597         gst_buffer_fill (buffer, 0, buf, size);
7598         stream->buffers = g_slist_append (stream->buffers, buffer);
7599         GST_LOG_OBJECT (qtdemux, "parsing theora header");
7600         break;
7601       case FOURCC_tCt_:
7602         buffer = gst_buffer_new_and_alloc (size);
7603         gst_buffer_fill (buffer, 0, buf, size);
7604         stream->buffers = g_slist_append (stream->buffers, buffer);
7605         GST_LOG_OBJECT (qtdemux, "parsing theora comment");
7606         break;
7607       case FOURCC_tCtC:
7608         buffer = gst_buffer_new_and_alloc (size);
7609         gst_buffer_fill (buffer, 0, buf, size);
7610         stream->buffers = g_slist_append (stream->buffers, buffer);
7611         GST_LOG_OBJECT (qtdemux, "parsing theora codebook");
7612         break;
7613       default:
7614         GST_WARNING_OBJECT (qtdemux,
7615             "unknown theora cookie %" GST_FOURCC_FORMAT,
7616             GST_FOURCC_ARGS (type));
7617         break;
7618     }
7619     buf += size;
7620   }
7621   return TRUE;
7622 }
7623
7624 static gboolean
7625 qtdemux_parse_node (GstQTDemux * qtdemux, GNode * node, const guint8 * buffer,
7626     guint length)
7627 {
7628   guint32 fourcc = 0;
7629   guint32 node_length = 0;
7630   const QtNodeType *type;
7631   const guint8 *end;
7632
7633   GST_LOG_OBJECT (qtdemux, "qtdemux_parse buffer %p length %u", buffer, length);
7634
7635   if (G_UNLIKELY (length < 8))
7636     goto not_enough_data;
7637
7638   node_length = QT_UINT32 (buffer);
7639   fourcc = QT_FOURCC (buffer + 4);
7640
7641   /* ignore empty nodes */
7642   if (G_UNLIKELY (fourcc == 0 || node_length == 8))
7643     return TRUE;
7644
7645   type = qtdemux_type_get (fourcc);
7646
7647   end = buffer + length;
7648
7649   GST_LOG_OBJECT (qtdemux,
7650       "parsing '%" GST_FOURCC_FORMAT "', length=%u, name '%s'",
7651       GST_FOURCC_ARGS (fourcc), node_length, type->name);
7652
7653   if (node_length > length)
7654     goto broken_atom_size;
7655
7656   if (type->flags & QT_FLAG_CONTAINER) {
7657     qtdemux_parse_container (qtdemux, node, buffer + 8, end);
7658   } else {
7659     switch (fourcc) {
7660       case FOURCC_stsd:
7661       {
7662         if (node_length < 20) {
7663           GST_LOG_OBJECT (qtdemux, "skipping small stsd box");
7664           break;
7665         }
7666         GST_DEBUG_OBJECT (qtdemux,
7667             "parsing stsd (sample table, sample description) atom");
7668         /* Skip over 8 byte atom hdr + 1 byte version, 3 bytes flags, 4 byte num_entries */
7669         qtdemux_parse_container (qtdemux, node, buffer + 16, end);
7670         break;
7671       }
7672       case FOURCC_mp4a:
7673       case FOURCC_alac:
7674       case FOURCC_fLaC:
7675       {
7676         guint32 version;
7677         guint32 offset;
7678         guint min_size;
7679
7680         /* also read alac (or whatever) in stead of mp4a in the following,
7681          * since a similar layout is used in other cases as well */
7682         if (fourcc == FOURCC_mp4a)
7683           min_size = 20;
7684         else if (fourcc == FOURCC_fLaC)
7685           min_size = 86;
7686         else
7687           min_size = 40;
7688
7689         /* There are two things we might encounter here: a true mp4a atom, and
7690            an mp4a entry in an stsd atom. The latter is what we're interested
7691            in, and it looks like an atom, but isn't really one. The true mp4a
7692            atom is short, so we detect it based on length here. */
7693         if (length < min_size) {
7694           GST_LOG_OBJECT (qtdemux, "skipping small %" GST_FOURCC_FORMAT " box",
7695               GST_FOURCC_ARGS (fourcc));
7696           break;
7697         }
7698
7699         /* 'version' here is the sound sample description version. Types 0 and
7700            1 are documented in the QTFF reference, but type 2 is not: it's
7701            described in Apple header files instead (struct SoundDescriptionV2
7702            in Movies.h) */
7703         version = QT_UINT16 (buffer + 16);
7704
7705         GST_DEBUG_OBJECT (qtdemux, "%" GST_FOURCC_FORMAT " version 0x%08x",
7706             GST_FOURCC_ARGS (fourcc), version);
7707
7708         /* parse any esds descriptors */
7709         switch (version) {
7710           case 0:
7711             offset = 0x24;
7712             break;
7713           case 1:
7714             offset = 0x34;
7715             break;
7716           case 2:
7717             offset = 0x48;
7718             break;
7719           default:
7720             GST_WARNING_OBJECT (qtdemux,
7721                 "unhandled %" GST_FOURCC_FORMAT " version 0x%08x",
7722                 GST_FOURCC_ARGS (fourcc), version);
7723             offset = 0;
7724             break;
7725         }
7726         if (offset)
7727           qtdemux_parse_container (qtdemux, node, buffer + offset, end);
7728         break;
7729       }
7730       case FOURCC_mp4v:
7731       case FOURCC_MP4V:
7732       case FOURCC_fmp4:
7733       case FOURCC_FMP4:
7734       case FOURCC_apcs:
7735       case FOURCC_apch:
7736       case FOURCC_apcn:
7737       case FOURCC_apco:
7738       case FOURCC_ap4h:
7739       case FOURCC_xvid:
7740       case FOURCC_XVID:
7741       case FOURCC_H264:
7742       case FOURCC_avc1:
7743       case FOURCC_avc3:
7744       case FOURCC_H265:
7745       case FOURCC_hvc1:
7746       case FOURCC_hev1:
7747       case FOURCC_mjp2:
7748       case FOURCC_encv:
7749       {
7750         guint32 version;
7751         guint32 str_len;
7752
7753         /* codec_data is contained inside these atoms, which all have
7754          * the same format. */
7755         /* video sample description size is 86 bytes without extension.
7756          * node_length have to be bigger than 86 bytes because video sample
7757          * description can include extenstions such as esds, fiel, glbl, etc. */
7758         if (node_length < 86) {
7759           GST_WARNING_OBJECT (qtdemux, "%" GST_FOURCC_FORMAT
7760               " sample description length too short (%u < 86)",
7761               GST_FOURCC_ARGS (fourcc), node_length);
7762           break;
7763         }
7764
7765         GST_DEBUG_OBJECT (qtdemux, "parsing in %" GST_FOURCC_FORMAT,
7766             GST_FOURCC_ARGS (fourcc));
7767
7768         /* version (2 bytes) : this is set to 0, unless a compressor has changed
7769          *              its data format.
7770          * revision level (2 bytes) : must be set to 0. */
7771         version = QT_UINT32 (buffer + 16);
7772         GST_DEBUG_OBJECT (qtdemux, "version %08x", version);
7773
7774         /* compressor name : PASCAL string and informative purposes
7775          * first byte : the number of bytes to be displayed.
7776          *              it has to be less than 32 because it is reserved
7777          *              space of 32 bytes total including itself. */
7778         str_len = QT_UINT8 (buffer + 50);
7779         if (str_len < 32)
7780           GST_DEBUG_OBJECT (qtdemux, "compressorname = %.*s", str_len,
7781               (char *) buffer + 51);
7782         else
7783           GST_WARNING_OBJECT (qtdemux,
7784               "compressorname length too big (%u > 31)", str_len);
7785
7786         GST_MEMDUMP_OBJECT (qtdemux, "video sample description", buffer,
7787             end - buffer);
7788         qtdemux_parse_container (qtdemux, node, buffer + 86, end);
7789         break;
7790       }
7791       case FOURCC_meta:
7792       {
7793         GST_DEBUG_OBJECT (qtdemux, "parsing meta atom");
7794
7795         /* You are reading this correctly. QTFF specifies that the
7796          * metadata atom is a short atom, whereas ISO BMFF specifies
7797          * it's a full atom. But since so many people are doing things
7798          * differently, we actually peek into the atom to see which
7799          * variant it is */
7800         if (length < 16) {
7801           GST_LOG_OBJECT (qtdemux, "skipping small %" GST_FOURCC_FORMAT " box",
7802               GST_FOURCC_ARGS (fourcc));
7803           break;
7804         }
7805         if (QT_FOURCC (buffer + 12) == FOURCC_hdlr) {
7806           /* Variant 1: What QTFF specifies. 'meta' is a short header which
7807            * starts with a 'hdlr' atom */
7808           qtdemux_parse_container (qtdemux, node, buffer + 8, end);
7809         } else if (QT_UINT32 (buffer + 8) == 0x00000000) {
7810           /* Variant 2: What ISO BMFF specifies. 'meta' is a _full_ atom
7811            * with version/flags both set to zero */
7812           qtdemux_parse_container (qtdemux, node, buffer + 12, end);
7813         } else
7814           GST_WARNING_OBJECT (qtdemux, "Unknown 'meta' atom format");
7815         break;
7816       }
7817       case FOURCC_mp4s:
7818       {
7819         GST_MEMDUMP_OBJECT (qtdemux, "mp4s", buffer, end - buffer);
7820         /* Skip 8 byte header, plus 8 byte version + flags + entry_count */
7821         qtdemux_parse_container (qtdemux, node, buffer + 16, end);
7822         break;
7823       }
7824       case FOURCC_XiTh:
7825       {
7826         guint32 version;
7827         guint32 offset;
7828
7829         if (length < 16) {
7830           GST_LOG_OBJECT (qtdemux, "skipping small %" GST_FOURCC_FORMAT " box",
7831               GST_FOURCC_ARGS (fourcc));
7832           break;
7833         }
7834
7835         version = QT_UINT32 (buffer + 12);
7836         GST_DEBUG_OBJECT (qtdemux, "parsing XiTh atom version 0x%08x", version);
7837
7838         switch (version) {
7839           case 0x00000001:
7840             offset = 0x62;
7841             break;
7842           default:
7843             GST_DEBUG_OBJECT (qtdemux, "unknown version 0x%08x", version);
7844             offset = 0;
7845             break;
7846         }
7847         if (offset) {
7848           if (length < offset) {
7849             GST_WARNING_OBJECT (qtdemux,
7850                 "skipping too small %" GST_FOURCC_FORMAT " box",
7851                 GST_FOURCC_ARGS (fourcc));
7852             break;
7853           }
7854           qtdemux_parse_container (qtdemux, node, buffer + offset, end);
7855         }
7856         break;
7857       }
7858       case FOURCC_in24:
7859       {
7860         qtdemux_parse_container (qtdemux, node, buffer + 0x34, end);
7861         break;
7862       }
7863       case FOURCC_uuid:
7864       {
7865         qtdemux_parse_uuid (qtdemux, buffer, end - buffer);
7866         break;
7867       }
7868       case FOURCC_enca:
7869       {
7870         qtdemux_parse_container (qtdemux, node, buffer + 36, end);
7871         break;
7872       }
7873       default:
7874         if (!strcmp (type->name, "unknown"))
7875           GST_MEMDUMP ("Unknown tag", buffer + 4, end - buffer - 4);
7876         break;
7877     }
7878   }
7879   GST_LOG_OBJECT (qtdemux, "parsed '%" GST_FOURCC_FORMAT "'",
7880       GST_FOURCC_ARGS (fourcc));
7881   return TRUE;
7882
7883 /* ERRORS */
7884 not_enough_data:
7885   {
7886     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
7887         (_("This file is corrupt and cannot be played.")),
7888         ("Not enough data for an atom header, got only %u bytes", length));
7889     return FALSE;
7890   }
7891 broken_atom_size:
7892   {
7893     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
7894         (_("This file is corrupt and cannot be played.")),
7895         ("Atom '%" GST_FOURCC_FORMAT "' has size of %u bytes, but we have only "
7896             "%u bytes available.", GST_FOURCC_ARGS (fourcc), node_length,
7897             length));
7898     return FALSE;
7899   }
7900 }
7901
7902 static GNode *
7903 qtdemux_tree_get_child_by_type (GNode * node, guint32 fourcc)
7904 {
7905   GNode *child;
7906   guint8 *buffer;
7907   guint32 child_fourcc;
7908
7909   for (child = g_node_first_child (node); child;
7910       child = g_node_next_sibling (child)) {
7911     buffer = (guint8 *) child->data;
7912
7913     child_fourcc = QT_FOURCC (buffer + 4);
7914
7915     if (G_UNLIKELY (child_fourcc == fourcc)) {
7916       return child;
7917     }
7918   }
7919   return NULL;
7920 }
7921
7922 static GNode *
7923 qtdemux_tree_get_child_by_type_full (GNode * node, guint32 fourcc,
7924     GstByteReader * parser)
7925 {
7926   GNode *child;
7927   guint8 *buffer;
7928   guint32 child_fourcc, child_len;
7929
7930   for (child = g_node_first_child (node); child;
7931       child = g_node_next_sibling (child)) {
7932     buffer = (guint8 *) child->data;
7933
7934     child_len = QT_UINT32 (buffer);
7935     child_fourcc = QT_FOURCC (buffer + 4);
7936
7937     if (G_UNLIKELY (child_fourcc == fourcc)) {
7938       if (G_UNLIKELY (child_len < (4 + 4)))
7939         return NULL;
7940       /* FIXME: must verify if atom length < parent atom length */
7941       gst_byte_reader_init (parser, buffer + (4 + 4), child_len - (4 + 4));
7942       return child;
7943     }
7944   }
7945   return NULL;
7946 }
7947
7948 static GNode *
7949 qtdemux_tree_get_child_by_index (GNode * node, guint index)
7950 {
7951   return g_node_nth_child (node, index);
7952 }
7953
7954 static GNode *
7955 qtdemux_tree_get_sibling_by_type_full (GNode * node, guint32 fourcc,
7956     GstByteReader * parser)
7957 {
7958   GNode *child;
7959   guint8 *buffer;
7960   guint32 child_fourcc, child_len;
7961
7962   for (child = g_node_next_sibling (node); child;
7963       child = g_node_next_sibling (child)) {
7964     buffer = (guint8 *) child->data;
7965
7966     child_fourcc = QT_FOURCC (buffer + 4);
7967
7968     if (child_fourcc == fourcc) {
7969       if (parser) {
7970         child_len = QT_UINT32 (buffer);
7971         if (G_UNLIKELY (child_len < (4 + 4)))
7972           return NULL;
7973         /* FIXME: must verify if atom length < parent atom length */
7974         gst_byte_reader_init (parser, buffer + (4 + 4), child_len - (4 + 4));
7975       }
7976       return child;
7977     }
7978   }
7979   return NULL;
7980 }
7981
7982 static GNode *
7983 qtdemux_tree_get_sibling_by_type (GNode * node, guint32 fourcc)
7984 {
7985   return qtdemux_tree_get_sibling_by_type_full (node, fourcc, NULL);
7986 }
7987
7988 static void
7989 qtdemux_do_allocation (GstQTDemux * qtdemux, QtDemuxStream * stream)
7990 {
7991 /* FIXME: This can only reliably work if demuxers have a
7992  * separate streaming thread per srcpad. This should be
7993  * done in a demuxer base class, which integrates parts
7994  * of multiqueue
7995  *
7996  * https://bugzilla.gnome.org/show_bug.cgi?id=701856
7997  */
7998 #if 0
7999   GstQuery *query;
8000
8001   query = gst_query_new_allocation (stream->caps, FALSE);
8002
8003   if (!gst_pad_peer_query (stream->pad, query)) {
8004     /* not a problem, just debug a little */
8005     GST_DEBUG_OBJECT (qtdemux, "peer ALLOCATION query failed");
8006   }
8007
8008   if (stream->allocator)
8009     gst_object_unref (stream->allocator);
8010
8011   if (gst_query_get_n_allocation_params (query) > 0) {
8012     /* try the allocator */
8013     gst_query_parse_nth_allocation_param (query, 0, &stream->allocator,
8014         &stream->params);
8015     stream->use_allocator = TRUE;
8016   } else {
8017     stream->allocator = NULL;
8018     gst_allocation_params_init (&stream->params);
8019     stream->use_allocator = FALSE;
8020   }
8021   gst_query_unref (query);
8022 #endif
8023 }
8024
8025 static gboolean
8026 pad_query (const GValue * item, GValue * value, gpointer user_data)
8027 {
8028   GstPad *pad = g_value_get_object (item);
8029   GstQuery *query = user_data;
8030   gboolean res;
8031
8032   res = gst_pad_peer_query (pad, query);
8033
8034   if (res) {
8035     g_value_set_boolean (value, TRUE);
8036     return FALSE;
8037   }
8038
8039   GST_INFO_OBJECT (pad, "pad peer query failed");
8040   return TRUE;
8041 }
8042
8043 static gboolean
8044 gst_qtdemux_run_query (GstElement * element, GstQuery * query,
8045     GstPadDirection direction)
8046 {
8047   GstIterator *it;
8048   GstIteratorFoldFunction func = pad_query;
8049   GValue res = { 0, };
8050
8051   g_value_init (&res, G_TYPE_BOOLEAN);
8052   g_value_set_boolean (&res, FALSE);
8053
8054   /* Ask neighbor */
8055   if (direction == GST_PAD_SRC)
8056     it = gst_element_iterate_src_pads (element);
8057   else
8058     it = gst_element_iterate_sink_pads (element);
8059
8060   while (gst_iterator_fold (it, func, &res, query) == GST_ITERATOR_RESYNC)
8061     gst_iterator_resync (it);
8062
8063   gst_iterator_free (it);
8064
8065   return g_value_get_boolean (&res);
8066 }
8067
8068 static void
8069 gst_qtdemux_request_protection_context (GstQTDemux * qtdemux,
8070     QtDemuxStream * stream)
8071 {
8072   GstQuery *query;
8073   GstContext *ctxt;
8074   GstElement *element = GST_ELEMENT (qtdemux);
8075   GstStructure *st;
8076   gchar **filtered_sys_ids;
8077   GValue event_list = G_VALUE_INIT;
8078   GList *walk;
8079
8080   /* 1. Check if we already have the context. */
8081   if (qtdemux->preferred_protection_system_id != NULL) {
8082     GST_LOG_OBJECT (element,
8083         "already have the protection context, no need to request it again");
8084     return;
8085   }
8086
8087   g_ptr_array_add (qtdemux->protection_system_ids, NULL);
8088   filtered_sys_ids = gst_protection_filter_systems_by_available_decryptors (
8089       (const gchar **) qtdemux->protection_system_ids->pdata);
8090
8091   if (!filtered_sys_ids) {
8092     GST_INFO_OBJECT (element,
8093         "No avalaible decryptor, not worth asking the user to choose.");
8094     return;
8095   }
8096
8097   g_ptr_array_remove_index (qtdemux->protection_system_ids,
8098       qtdemux->protection_system_ids->len - 1);
8099   GST_TRACE_OBJECT (qtdemux, "detected %u protection systems, we have "
8100       "decryptors for %u of them, running context request",
8101       qtdemux->protection_system_ids->len, g_strv_length (filtered_sys_ids));
8102
8103   if (stream->protection_scheme_event_queue.length) {
8104     GST_TRACE_OBJECT (qtdemux, "using stream event queue, length %u",
8105         stream->protection_scheme_event_queue.length);
8106     walk = stream->protection_scheme_event_queue.tail;
8107   } else {
8108     GST_TRACE_OBJECT (qtdemux, "using demuxer event queue, length %u",
8109         qtdemux->protection_event_queue.length);
8110     walk = qtdemux->protection_event_queue.tail;
8111   }
8112
8113   g_value_init (&event_list, GST_TYPE_LIST);
8114   for (; walk; walk = g_list_previous (walk)) {
8115     GValue *event_value = g_new0 (GValue, 1);
8116     g_value_init (event_value, GST_TYPE_EVENT);
8117     g_value_set_boxed (event_value, walk->data);
8118     gst_value_list_append_and_take_value (&event_list, event_value);
8119   }
8120
8121   /*  2a) Query downstream with GST_QUERY_CONTEXT for the context and
8122    *      check if downstream already has a context of the specific type
8123    *  2b) Query upstream as above.
8124    */
8125   query = gst_query_new_context ("drm-preferred-decryption-system-id");
8126   st = gst_query_writable_structure (query);
8127   gst_structure_set (st, "track-id", G_TYPE_UINT, stream->track_id,
8128       "stream-encryption-systems", G_TYPE_STRV, filtered_sys_ids, NULL);
8129   gst_structure_set_value (st, "stream-encryption-events", &event_list);
8130   if (gst_qtdemux_run_query (element, query, GST_PAD_SRC)) {
8131     gst_query_parse_context (query, &ctxt);
8132     GST_INFO_OBJECT (element, "found context (%p) in downstream query", ctxt);
8133     gst_element_set_context (element, ctxt);
8134   } else if (gst_qtdemux_run_query (element, query, GST_PAD_SINK)) {
8135     gst_query_parse_context (query, &ctxt);
8136     GST_INFO_OBJECT (element, "found context (%p) in upstream query", ctxt);
8137     gst_element_set_context (element, ctxt);
8138   } else {
8139     /* 3) Post a GST_MESSAGE_NEED_CONTEXT message on the bus with
8140      *    the required context type and afterwards check if a
8141      *    usable context was set now as in 1). The message could
8142      *    be handled by the parent bins of the element and the
8143      *    application.
8144      */
8145     GstMessage *msg;
8146
8147     GST_INFO_OBJECT (element, "posting need context message");
8148     msg = gst_message_new_need_context (GST_OBJECT_CAST (element),
8149         "drm-preferred-decryption-system-id");
8150     st = (GstStructure *) gst_message_get_structure (msg);
8151     gst_structure_set (st, "track-id", G_TYPE_UINT, stream->track_id,
8152         "stream-encryption-systems", G_TYPE_STRV, filtered_sys_ids, NULL);
8153     gst_structure_set_value (st, "stream-encryption-events", &event_list);
8154     gst_element_post_message (element, msg);
8155   }
8156
8157   g_strfreev (filtered_sys_ids);
8158   g_value_unset (&event_list);
8159   gst_query_unref (query);
8160 }
8161
8162 static gboolean
8163 gst_qtdemux_configure_protected_caps (GstQTDemux * qtdemux,
8164     QtDemuxStream * stream)
8165 {
8166   GstStructure *s;
8167   const gchar *selected_system = NULL;
8168
8169   g_return_val_if_fail (qtdemux != NULL, FALSE);
8170   g_return_val_if_fail (stream != NULL, FALSE);
8171   g_return_val_if_fail (gst_caps_get_size (CUR_STREAM (stream)->caps) == 1,
8172       FALSE);
8173
8174   if (stream->protection_scheme_type != FOURCC_cenc) {
8175     GST_ERROR_OBJECT (qtdemux, "unsupported protection scheme");
8176     return FALSE;
8177   }
8178   if (qtdemux->protection_system_ids == NULL) {
8179     GST_ERROR_OBJECT (qtdemux, "stream is protected using cenc, but no "
8180         "cenc protection system information has been found");
8181     return FALSE;
8182   }
8183
8184   gst_qtdemux_request_protection_context (qtdemux, stream);
8185   if (qtdemux->preferred_protection_system_id != NULL) {
8186     const gchar *preferred_system_array[] =
8187         { qtdemux->preferred_protection_system_id, NULL };
8188
8189     selected_system = gst_protection_select_system (preferred_system_array);
8190
8191     if (selected_system) {
8192       GST_TRACE_OBJECT (qtdemux, "selected preferred system %s",
8193           qtdemux->preferred_protection_system_id);
8194     } else {
8195       GST_WARNING_OBJECT (qtdemux, "could not select preferred system %s "
8196           "because there is no available decryptor",
8197           qtdemux->preferred_protection_system_id);
8198     }
8199   }
8200
8201   if (!selected_system) {
8202     g_ptr_array_add (qtdemux->protection_system_ids, NULL);
8203     selected_system = gst_protection_select_system ((const gchar **)
8204         qtdemux->protection_system_ids->pdata);
8205     g_ptr_array_remove_index (qtdemux->protection_system_ids,
8206         qtdemux->protection_system_ids->len - 1);
8207   }
8208
8209   if (!selected_system) {
8210     GST_ERROR_OBJECT (qtdemux, "stream is protected, but no "
8211         "suitable decryptor element has been found");
8212     return FALSE;
8213   }
8214
8215   GST_DEBUG_OBJECT (qtdemux, "selected protection system is %s",
8216       selected_system);
8217
8218   s = gst_caps_get_structure (CUR_STREAM (stream)->caps, 0);
8219   if (!gst_structure_has_name (s, "application/x-cenc")) {
8220     gst_structure_set (s,
8221         "original-media-type", G_TYPE_STRING, gst_structure_get_name (s),
8222         GST_PROTECTION_SYSTEM_ID_CAPS_FIELD, G_TYPE_STRING, selected_system,
8223         NULL);
8224     gst_structure_set_name (s, "application/x-cenc");
8225   }
8226   return TRUE;
8227 }
8228
8229 static gboolean
8230 gst_qtdemux_configure_stream (GstQTDemux * qtdemux, QtDemuxStream * stream)
8231 {
8232   if (stream->subtype == FOURCC_vide) {
8233     /* fps is calculated base on the duration of the average framerate since
8234      * qt does not have a fixed framerate. */
8235     gboolean fps_available = TRUE;
8236     guint32 first_duration = 0;
8237
8238     if (stream->n_samples > 0)
8239       first_duration = stream->samples[0].duration;
8240
8241     if ((stream->n_samples == 1 && first_duration == 0)
8242         || (qtdemux->fragmented && stream->n_samples_moof == 1)) {
8243       /* still frame */
8244       CUR_STREAM (stream)->fps_n = 0;
8245       CUR_STREAM (stream)->fps_d = 1;
8246     } else {
8247       if (stream->duration == 0 || stream->n_samples < 2) {
8248         CUR_STREAM (stream)->fps_n = stream->timescale;
8249         CUR_STREAM (stream)->fps_d = 1;
8250         fps_available = FALSE;
8251       } else {
8252         GstClockTime avg_duration;
8253         guint64 duration;
8254         guint32 n_samples;
8255
8256         /* duration and n_samples can be updated for fragmented format
8257          * so, framerate of fragmented format is calculated using data in a moof */
8258         if (qtdemux->fragmented && stream->n_samples_moof > 0
8259             && stream->duration_moof > 0) {
8260           n_samples = stream->n_samples_moof;
8261           duration = stream->duration_moof;
8262         } else {
8263           n_samples = stream->n_samples;
8264           duration = stream->duration;
8265         }
8266
8267         /* Calculate a framerate, ignoring the first sample which is sometimes truncated */
8268         /* stream->duration is guint64, timescale, n_samples are guint32 */
8269         avg_duration =
8270             gst_util_uint64_scale_round (duration -
8271             first_duration, GST_SECOND,
8272             (guint64) (stream->timescale) * (n_samples - 1));
8273
8274         GST_LOG_OBJECT (qtdemux,
8275             "Calculating avg sample duration based on stream (or moof) duration %"
8276             G_GUINT64_FORMAT
8277             " minus first sample %u, leaving %d samples gives %"
8278             GST_TIME_FORMAT, duration, first_duration,
8279             n_samples - 1, GST_TIME_ARGS (avg_duration));
8280
8281         gst_video_guess_framerate (avg_duration, &CUR_STREAM (stream)->fps_n,
8282             &CUR_STREAM (stream)->fps_d);
8283
8284         GST_DEBUG_OBJECT (qtdemux,
8285             "Calculating framerate, timescale %u gave fps_n %d fps_d %d",
8286             stream->timescale, CUR_STREAM (stream)->fps_n,
8287             CUR_STREAM (stream)->fps_d);
8288       }
8289     }
8290
8291     if (CUR_STREAM (stream)->caps) {
8292       CUR_STREAM (stream)->caps =
8293           gst_caps_make_writable (CUR_STREAM (stream)->caps);
8294
8295       gst_caps_set_simple (CUR_STREAM (stream)->caps,
8296           "width", G_TYPE_INT, CUR_STREAM (stream)->width,
8297           "height", G_TYPE_INT, CUR_STREAM (stream)->height, NULL);
8298
8299       /* set framerate if calculated framerate is reliable */
8300       if (fps_available) {
8301         gst_caps_set_simple (CUR_STREAM (stream)->caps,
8302             "framerate", GST_TYPE_FRACTION, CUR_STREAM (stream)->fps_n,
8303             CUR_STREAM (stream)->fps_d, NULL);
8304       }
8305
8306       /* calculate pixel-aspect-ratio using display width and height */
8307       GST_DEBUG_OBJECT (qtdemux,
8308           "video size %dx%d, target display size %dx%d",
8309           CUR_STREAM (stream)->width, CUR_STREAM (stream)->height,
8310           stream->display_width, stream->display_height);
8311       /* qt file might have pasp atom */
8312       if (CUR_STREAM (stream)->par_w > 0 && CUR_STREAM (stream)->par_h > 0) {
8313         GST_DEBUG_OBJECT (qtdemux, "par %d:%d", CUR_STREAM (stream)->par_w,
8314             CUR_STREAM (stream)->par_h);
8315         gst_caps_set_simple (CUR_STREAM (stream)->caps, "pixel-aspect-ratio",
8316             GST_TYPE_FRACTION, CUR_STREAM (stream)->par_w,
8317             CUR_STREAM (stream)->par_h, NULL);
8318       } else if (stream->display_width > 0 && stream->display_height > 0
8319           && CUR_STREAM (stream)->width > 0
8320           && CUR_STREAM (stream)->height > 0) {
8321         gint n, d;
8322
8323         /* calculate the pixel aspect ratio using the display and pixel w/h */
8324         n = stream->display_width * CUR_STREAM (stream)->height;
8325         d = stream->display_height * CUR_STREAM (stream)->width;
8326         if (n == d)
8327           n = d = 1;
8328         GST_DEBUG_OBJECT (qtdemux, "setting PAR to %d/%d", n, d);
8329         CUR_STREAM (stream)->par_w = n;
8330         CUR_STREAM (stream)->par_h = d;
8331         gst_caps_set_simple (CUR_STREAM (stream)->caps, "pixel-aspect-ratio",
8332             GST_TYPE_FRACTION, CUR_STREAM (stream)->par_w,
8333             CUR_STREAM (stream)->par_h, NULL);
8334       }
8335
8336       if (CUR_STREAM (stream)->interlace_mode > 0) {
8337         if (CUR_STREAM (stream)->interlace_mode == 1) {
8338           gst_caps_set_simple (CUR_STREAM (stream)->caps, "interlace-mode",
8339               G_TYPE_STRING, "progressive", NULL);
8340         } else if (CUR_STREAM (stream)->interlace_mode == 2) {
8341           gst_caps_set_simple (CUR_STREAM (stream)->caps, "interlace-mode",
8342               G_TYPE_STRING, "interleaved", NULL);
8343           if (CUR_STREAM (stream)->field_order == 9) {
8344             gst_caps_set_simple (CUR_STREAM (stream)->caps, "field-order",
8345                 G_TYPE_STRING, "top-field-first", NULL);
8346           } else if (CUR_STREAM (stream)->field_order == 14) {
8347             gst_caps_set_simple (CUR_STREAM (stream)->caps, "field-order",
8348                 G_TYPE_STRING, "bottom-field-first", NULL);
8349           }
8350         }
8351       }
8352
8353       /* Create incomplete colorimetry here if needed */
8354       if (CUR_STREAM (stream)->colorimetry.range ||
8355           CUR_STREAM (stream)->colorimetry.matrix ||
8356           CUR_STREAM (stream)->colorimetry.transfer
8357           || CUR_STREAM (stream)->colorimetry.primaries) {
8358         gchar *colorimetry =
8359             gst_video_colorimetry_to_string (&CUR_STREAM (stream)->colorimetry);
8360         gst_caps_set_simple (CUR_STREAM (stream)->caps, "colorimetry",
8361             G_TYPE_STRING, colorimetry, NULL);
8362         g_free (colorimetry);
8363       }
8364
8365       if (stream->multiview_mode != GST_VIDEO_MULTIVIEW_MODE_NONE) {
8366         guint par_w = 1, par_h = 1;
8367
8368         if (CUR_STREAM (stream)->par_w > 0 && CUR_STREAM (stream)->par_h > 0) {
8369           par_w = CUR_STREAM (stream)->par_w;
8370           par_h = CUR_STREAM (stream)->par_h;
8371         }
8372
8373         if (gst_video_multiview_guess_half_aspect (stream->multiview_mode,
8374                 CUR_STREAM (stream)->width, CUR_STREAM (stream)->height, par_w,
8375                 par_h)) {
8376           stream->multiview_flags |= GST_VIDEO_MULTIVIEW_FLAGS_HALF_ASPECT;
8377         }
8378
8379         gst_caps_set_simple (CUR_STREAM (stream)->caps,
8380             "multiview-mode", G_TYPE_STRING,
8381             gst_video_multiview_mode_to_caps_string (stream->multiview_mode),
8382             "multiview-flags", GST_TYPE_VIDEO_MULTIVIEW_FLAGSET,
8383             stream->multiview_flags, GST_FLAG_SET_MASK_EXACT, NULL);
8384       }
8385     }
8386   }
8387
8388   else if (stream->subtype == FOURCC_soun) {
8389     if (CUR_STREAM (stream)->caps) {
8390       CUR_STREAM (stream)->caps =
8391           gst_caps_make_writable (CUR_STREAM (stream)->caps);
8392       if (CUR_STREAM (stream)->rate > 0)
8393         gst_caps_set_simple (CUR_STREAM (stream)->caps,
8394             "rate", G_TYPE_INT, (int) CUR_STREAM (stream)->rate, NULL);
8395       if (CUR_STREAM (stream)->n_channels > 0)
8396         gst_caps_set_simple (CUR_STREAM (stream)->caps,
8397             "channels", G_TYPE_INT, CUR_STREAM (stream)->n_channels, NULL);
8398       if (CUR_STREAM (stream)->n_channels > 2) {
8399         /* FIXME: Need to parse the 'chan' atom to get channel layouts
8400          * correctly; this is just the minimum we can do - assume
8401          * we don't actually have any channel positions. */
8402         gst_caps_set_simple (CUR_STREAM (stream)->caps,
8403             "channel-mask", GST_TYPE_BITMASK, G_GUINT64_CONSTANT (0), NULL);
8404       }
8405     }
8406   }
8407
8408   if (stream->pad) {
8409     GstCaps *prev_caps = NULL;
8410
8411     GST_PAD_ELEMENT_PRIVATE (stream->pad) = stream;
8412     gst_pad_set_event_function (stream->pad, gst_qtdemux_handle_src_event);
8413     gst_pad_set_query_function (stream->pad, gst_qtdemux_handle_src_query);
8414     gst_pad_set_active (stream->pad, TRUE);
8415
8416     gst_pad_use_fixed_caps (stream->pad);
8417
8418     if (stream->protected) {
8419       if (!gst_qtdemux_configure_protected_caps (qtdemux, stream)) {
8420         GST_ERROR_OBJECT (qtdemux,
8421             "Failed to configure protected stream caps.");
8422         return FALSE;
8423       }
8424     }
8425
8426     GST_DEBUG_OBJECT (qtdemux, "setting caps %" GST_PTR_FORMAT,
8427         CUR_STREAM (stream)->caps);
8428     if (stream->new_stream) {
8429       GstEvent *event;
8430       GstStreamFlags stream_flags = GST_STREAM_FLAG_NONE;
8431
8432       event =
8433           gst_pad_get_sticky_event (qtdemux->sinkpad, GST_EVENT_STREAM_START,
8434           0);
8435       if (event) {
8436         gst_event_parse_stream_flags (event, &stream_flags);
8437         if (gst_event_parse_group_id (event, &qtdemux->group_id))
8438           qtdemux->have_group_id = TRUE;
8439         else
8440           qtdemux->have_group_id = FALSE;
8441         gst_event_unref (event);
8442       } else if (!qtdemux->have_group_id) {
8443         qtdemux->have_group_id = TRUE;
8444         qtdemux->group_id = gst_util_group_id_next ();
8445       }
8446
8447       stream->new_stream = FALSE;
8448       event = gst_event_new_stream_start (stream->stream_id);
8449       if (qtdemux->have_group_id)
8450         gst_event_set_group_id (event, qtdemux->group_id);
8451       if (stream->disabled)
8452         stream_flags |= GST_STREAM_FLAG_UNSELECT;
8453       if (CUR_STREAM (stream)->sparse) {
8454         stream_flags |= GST_STREAM_FLAG_SPARSE;
8455       } else {
8456         stream_flags &= ~GST_STREAM_FLAG_SPARSE;
8457       }
8458       gst_event_set_stream_flags (event, stream_flags);
8459       gst_pad_push_event (stream->pad, event);
8460     }
8461
8462     prev_caps = gst_pad_get_current_caps (stream->pad);
8463
8464     if (CUR_STREAM (stream)->caps) {
8465       if (!prev_caps
8466           || !gst_caps_is_equal_fixed (prev_caps, CUR_STREAM (stream)->caps)) {
8467         GST_DEBUG_OBJECT (qtdemux, "setting caps %" GST_PTR_FORMAT,
8468             CUR_STREAM (stream)->caps);
8469         gst_pad_set_caps (stream->pad, CUR_STREAM (stream)->caps);
8470       } else {
8471         GST_DEBUG_OBJECT (qtdemux, "ignore duplicated caps");
8472       }
8473     } else {
8474       GST_WARNING_OBJECT (qtdemux, "stream without caps");
8475     }
8476
8477     if (prev_caps)
8478       gst_caps_unref (prev_caps);
8479     stream->new_caps = FALSE;
8480   }
8481   return TRUE;
8482 }
8483
8484 static void
8485 gst_qtdemux_stream_check_and_change_stsd_index (GstQTDemux * demux,
8486     QtDemuxStream * stream)
8487 {
8488   if (stream->cur_stsd_entry_index == stream->stsd_sample_description_id)
8489     return;
8490
8491   GST_DEBUG_OBJECT (stream->pad, "Changing stsd index from '%u' to '%u'",
8492       stream->cur_stsd_entry_index, stream->stsd_sample_description_id);
8493   if (G_UNLIKELY (stream->stsd_sample_description_id >=
8494           stream->stsd_entries_length)) {
8495     GST_ELEMENT_ERROR (demux, STREAM, DEMUX,
8496         (_("This file is invalid and cannot be played.")),
8497         ("New sample description id is out of bounds (%d >= %d)",
8498             stream->stsd_sample_description_id, stream->stsd_entries_length));
8499   } else {
8500     stream->cur_stsd_entry_index = stream->stsd_sample_description_id;
8501     stream->new_caps = TRUE;
8502   }
8503 }
8504
8505 static gboolean
8506 gst_qtdemux_add_stream (GstQTDemux * qtdemux,
8507     QtDemuxStream * stream, GstTagList * list)
8508 {
8509   gboolean ret = TRUE;
8510   /* consistent default for push based mode */
8511   gst_segment_init (&stream->segment, GST_FORMAT_TIME);
8512
8513   if (stream->subtype == FOURCC_vide) {
8514     gchar *name = g_strdup_printf ("video_%u", qtdemux->n_video_streams);
8515
8516     stream->pad =
8517         gst_pad_new_from_static_template (&gst_qtdemux_videosrc_template, name);
8518     g_free (name);
8519
8520     if (!gst_qtdemux_configure_stream (qtdemux, stream)) {
8521       gst_object_unref (stream->pad);
8522       stream->pad = NULL;
8523       ret = FALSE;
8524       goto done;
8525     }
8526
8527     qtdemux->n_video_streams++;
8528   } else if (stream->subtype == FOURCC_soun) {
8529     gchar *name = g_strdup_printf ("audio_%u", qtdemux->n_audio_streams);
8530
8531     stream->pad =
8532         gst_pad_new_from_static_template (&gst_qtdemux_audiosrc_template, name);
8533     g_free (name);
8534     if (!gst_qtdemux_configure_stream (qtdemux, stream)) {
8535       gst_object_unref (stream->pad);
8536       stream->pad = NULL;
8537       ret = FALSE;
8538       goto done;
8539     }
8540     qtdemux->n_audio_streams++;
8541   } else if (stream->subtype == FOURCC_strm) {
8542     GST_DEBUG_OBJECT (qtdemux, "stream type, not creating pad");
8543   } else if (stream->subtype == FOURCC_subp || stream->subtype == FOURCC_text
8544       || stream->subtype == FOURCC_sbtl || stream->subtype == FOURCC_subt) {
8545     gchar *name = g_strdup_printf ("subtitle_%u", qtdemux->n_sub_streams);
8546
8547     stream->pad =
8548         gst_pad_new_from_static_template (&gst_qtdemux_subsrc_template, name);
8549     g_free (name);
8550     if (!gst_qtdemux_configure_stream (qtdemux, stream)) {
8551       gst_object_unref (stream->pad);
8552       stream->pad = NULL;
8553       ret = FALSE;
8554       goto done;
8555     }
8556     qtdemux->n_sub_streams++;
8557   } else if (CUR_STREAM (stream)->caps) {
8558     gchar *name = g_strdup_printf ("video_%u", qtdemux->n_video_streams);
8559
8560     stream->pad =
8561         gst_pad_new_from_static_template (&gst_qtdemux_videosrc_template, name);
8562     g_free (name);
8563     if (!gst_qtdemux_configure_stream (qtdemux, stream)) {
8564       gst_object_unref (stream->pad);
8565       stream->pad = NULL;
8566       ret = FALSE;
8567       goto done;
8568     }
8569     qtdemux->n_video_streams++;
8570   } else {
8571     GST_DEBUG_OBJECT (qtdemux, "unknown stream type");
8572     goto done;
8573   }
8574
8575   if (stream->pad) {
8576     GList *l;
8577
8578     GST_DEBUG_OBJECT (qtdemux, "adding pad %s %p to qtdemux %p",
8579         GST_OBJECT_NAME (stream->pad), stream->pad, qtdemux);
8580     gst_element_add_pad (GST_ELEMENT_CAST (qtdemux), stream->pad);
8581     gst_flow_combiner_add_pad (qtdemux->flowcombiner, stream->pad);
8582
8583     if (stream->stream_tags)
8584       gst_tag_list_unref (stream->stream_tags);
8585     stream->stream_tags = list;
8586     list = NULL;
8587     /* global tags go on each pad anyway */
8588     stream->send_global_tags = TRUE;
8589     /* send upstream GST_EVENT_PROTECTION events that were received before
8590        this source pad was created */
8591     for (l = qtdemux->protection_event_queue.head; l != NULL; l = l->next)
8592       gst_pad_push_event (stream->pad, gst_event_ref (l->data));
8593   }
8594 done:
8595   if (list)
8596     gst_tag_list_unref (list);
8597   return ret;
8598 }
8599
8600 /* find next atom with @fourcc starting at @offset */
8601 static GstFlowReturn
8602 qtdemux_find_atom (GstQTDemux * qtdemux, guint64 * offset,
8603     guint64 * length, guint32 fourcc)
8604 {
8605   GstFlowReturn ret;
8606   guint32 lfourcc;
8607   GstBuffer *buf;
8608
8609   GST_LOG_OBJECT (qtdemux, "finding fourcc %" GST_FOURCC_FORMAT " at offset %"
8610       G_GUINT64_FORMAT, GST_FOURCC_ARGS (fourcc), *offset);
8611
8612   while (TRUE) {
8613     GstMapInfo map;
8614
8615     buf = NULL;
8616     ret = gst_pad_pull_range (qtdemux->sinkpad, *offset, 16, &buf);
8617     if (G_UNLIKELY (ret != GST_FLOW_OK))
8618       goto locate_failed;
8619     if (G_UNLIKELY (gst_buffer_get_size (buf) != 16)) {
8620       /* likely EOF */
8621       ret = GST_FLOW_EOS;
8622       gst_buffer_unref (buf);
8623       goto locate_failed;
8624     }
8625     gst_buffer_map (buf, &map, GST_MAP_READ);
8626     extract_initial_length_and_fourcc (map.data, 16, length, &lfourcc);
8627     gst_buffer_unmap (buf, &map);
8628     gst_buffer_unref (buf);
8629
8630     if (G_UNLIKELY (*length == 0)) {
8631       GST_DEBUG_OBJECT (qtdemux, "invalid length 0");
8632       ret = GST_FLOW_ERROR;
8633       goto locate_failed;
8634     }
8635
8636     if (lfourcc == fourcc) {
8637       GST_DEBUG_OBJECT (qtdemux, "found fourcc at offset %" G_GUINT64_FORMAT,
8638           *offset);
8639       break;
8640     } else {
8641       GST_LOG_OBJECT (qtdemux,
8642           "skipping atom '%" GST_FOURCC_FORMAT "' at %" G_GUINT64_FORMAT,
8643           GST_FOURCC_ARGS (fourcc), *offset);
8644       *offset += *length;
8645     }
8646   }
8647
8648   return GST_FLOW_OK;
8649
8650 locate_failed:
8651   {
8652     /* might simply have had last one */
8653     GST_DEBUG_OBJECT (qtdemux, "fourcc not found");
8654     return ret;
8655   }
8656 }
8657
8658 /* should only do something in pull mode */
8659 /* call with OBJECT lock */
8660 static GstFlowReturn
8661 qtdemux_add_fragmented_samples (GstQTDemux * qtdemux)
8662 {
8663   guint64 length, offset;
8664   GstBuffer *buf = NULL;
8665   GstFlowReturn ret = GST_FLOW_OK;
8666   GstFlowReturn res = GST_FLOW_OK;
8667   GstMapInfo map;
8668
8669   offset = qtdemux->moof_offset;
8670   GST_DEBUG_OBJECT (qtdemux, "next moof at offset %" G_GUINT64_FORMAT, offset);
8671
8672   if (!offset) {
8673     GST_DEBUG_OBJECT (qtdemux, "no next moof");
8674     return GST_FLOW_EOS;
8675   }
8676
8677   /* best not do pull etc with lock held */
8678   GST_OBJECT_UNLOCK (qtdemux);
8679
8680   ret = qtdemux_find_atom (qtdemux, &offset, &length, FOURCC_moof);
8681   if (ret != GST_FLOW_OK)
8682     goto flow_failed;
8683
8684   ret = gst_qtdemux_pull_atom (qtdemux, offset, length, &buf);
8685   if (G_UNLIKELY (ret != GST_FLOW_OK))
8686     goto flow_failed;
8687   gst_buffer_map (buf, &map, GST_MAP_READ);
8688   if (!qtdemux_parse_moof (qtdemux, map.data, map.size, offset, NULL)) {
8689     gst_buffer_unmap (buf, &map);
8690     gst_buffer_unref (buf);
8691     buf = NULL;
8692     goto parse_failed;
8693   }
8694
8695   gst_buffer_unmap (buf, &map);
8696   gst_buffer_unref (buf);
8697   buf = NULL;
8698
8699   offset += length;
8700   /* look for next moof */
8701   ret = qtdemux_find_atom (qtdemux, &offset, &length, FOURCC_moof);
8702   if (G_UNLIKELY (ret != GST_FLOW_OK))
8703     goto flow_failed;
8704
8705 exit:
8706   GST_OBJECT_LOCK (qtdemux);
8707
8708   qtdemux->moof_offset = offset;
8709
8710   return res;
8711
8712 parse_failed:
8713   {
8714     GST_DEBUG_OBJECT (qtdemux, "failed to parse moof");
8715     offset = 0;
8716     res = GST_FLOW_ERROR;
8717     goto exit;
8718   }
8719 flow_failed:
8720   {
8721     /* maybe upstream temporarily flushing */
8722     if (ret != GST_FLOW_FLUSHING) {
8723       GST_DEBUG_OBJECT (qtdemux, "no next moof");
8724       offset = 0;
8725     } else {
8726       GST_DEBUG_OBJECT (qtdemux, "upstream WRONG_STATE");
8727       /* resume at current position next time */
8728     }
8729     res = ret;
8730     goto exit;
8731   }
8732 }
8733
8734 /* initialise bytereaders for stbl sub-atoms */
8735 static gboolean
8736 qtdemux_stbl_init (GstQTDemux * qtdemux, QtDemuxStream * stream, GNode * stbl)
8737 {
8738   stream->stbl_index = -1;      /* no samples have yet been parsed */
8739   stream->sample_index = -1;
8740
8741   /* time-to-sample atom */
8742   if (!qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stts, &stream->stts))
8743     goto corrupt_file;
8744
8745   /* copy atom data into a new buffer for later use */
8746   stream->stts.data = g_memdup (stream->stts.data, stream->stts.size);
8747
8748   /* skip version + flags */
8749   if (!gst_byte_reader_skip (&stream->stts, 1 + 3) ||
8750       !gst_byte_reader_get_uint32_be (&stream->stts, &stream->n_sample_times))
8751     goto corrupt_file;
8752   GST_LOG_OBJECT (qtdemux, "%u timestamp blocks", stream->n_sample_times);
8753
8754   /* make sure there's enough data */
8755   if (!qt_atom_parser_has_chunks (&stream->stts, stream->n_sample_times, 8)) {
8756     stream->n_sample_times = gst_byte_reader_get_remaining (&stream->stts) / 8;
8757     GST_LOG_OBJECT (qtdemux, "overriding to %u timestamp blocks",
8758         stream->n_sample_times);
8759     if (!stream->n_sample_times)
8760       goto corrupt_file;
8761   }
8762
8763   /* sync sample atom */
8764   stream->stps_present = FALSE;
8765   if ((stream->stss_present =
8766           ! !qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stss,
8767               &stream->stss) ? TRUE : FALSE) == TRUE) {
8768     /* copy atom data into a new buffer for later use */
8769     stream->stss.data = g_memdup (stream->stss.data, stream->stss.size);
8770
8771     /* skip version + flags */
8772     if (!gst_byte_reader_skip (&stream->stss, 1 + 3) ||
8773         !gst_byte_reader_get_uint32_be (&stream->stss, &stream->n_sample_syncs))
8774       goto corrupt_file;
8775
8776     if (stream->n_sample_syncs) {
8777       /* make sure there's enough data */
8778       if (!qt_atom_parser_has_chunks (&stream->stss, stream->n_sample_syncs, 4))
8779         goto corrupt_file;
8780     }
8781
8782     /* partial sync sample atom */
8783     if ((stream->stps_present =
8784             ! !qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stps,
8785                 &stream->stps) ? TRUE : FALSE) == TRUE) {
8786       /* copy atom data into a new buffer for later use */
8787       stream->stps.data = g_memdup (stream->stps.data, stream->stps.size);
8788
8789       /* skip version + flags */
8790       if (!gst_byte_reader_skip (&stream->stps, 1 + 3) ||
8791           !gst_byte_reader_get_uint32_be (&stream->stps,
8792               &stream->n_sample_partial_syncs))
8793         goto corrupt_file;
8794
8795       /* if there are no entries, the stss table contains the real
8796        * sync samples */
8797       if (stream->n_sample_partial_syncs) {
8798         /* make sure there's enough data */
8799         if (!qt_atom_parser_has_chunks (&stream->stps,
8800                 stream->n_sample_partial_syncs, 4))
8801           goto corrupt_file;
8802       }
8803     }
8804   }
8805
8806   /* sample size */
8807   if (!qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stsz, &stream->stsz))
8808     goto no_samples;
8809
8810   /* copy atom data into a new buffer for later use */
8811   stream->stsz.data = g_memdup (stream->stsz.data, stream->stsz.size);
8812
8813   /* skip version + flags */
8814   if (!gst_byte_reader_skip (&stream->stsz, 1 + 3) ||
8815       !gst_byte_reader_get_uint32_be (&stream->stsz, &stream->sample_size))
8816     goto corrupt_file;
8817
8818   if (!gst_byte_reader_get_uint32_be (&stream->stsz, &stream->n_samples))
8819     goto corrupt_file;
8820
8821   if (!stream->n_samples)
8822     goto no_samples;
8823
8824   /* sample-to-chunk atom */
8825   if (!qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stsc, &stream->stsc))
8826     goto corrupt_file;
8827
8828   /* copy atom data into a new buffer for later use */
8829   stream->stsc.data = g_memdup (stream->stsc.data, stream->stsc.size);
8830
8831   /* skip version + flags */
8832   if (!gst_byte_reader_skip (&stream->stsc, 1 + 3) ||
8833       !gst_byte_reader_get_uint32_be (&stream->stsc,
8834           &stream->n_samples_per_chunk))
8835     goto corrupt_file;
8836
8837   GST_DEBUG_OBJECT (qtdemux, "n_samples_per_chunk %u",
8838       stream->n_samples_per_chunk);
8839
8840   /* make sure there's enough data */
8841   if (!qt_atom_parser_has_chunks (&stream->stsc, stream->n_samples_per_chunk,
8842           12))
8843     goto corrupt_file;
8844
8845
8846   /* chunk offset */
8847   if (qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stco, &stream->stco))
8848     stream->co_size = sizeof (guint32);
8849   else if (qtdemux_tree_get_child_by_type_full (stbl, FOURCC_co64,
8850           &stream->stco))
8851     stream->co_size = sizeof (guint64);
8852   else
8853     goto corrupt_file;
8854
8855   /* copy atom data into a new buffer for later use */
8856   stream->stco.data = g_memdup (stream->stco.data, stream->stco.size);
8857
8858   /* skip version + flags */
8859   if (!gst_byte_reader_skip (&stream->stco, 1 + 3))
8860     goto corrupt_file;
8861
8862   /* chunks_are_samples == TRUE means treat chunks as samples */
8863   stream->chunks_are_samples = stream->sample_size
8864       && !CUR_STREAM (stream)->sampled;
8865   if (stream->chunks_are_samples) {
8866     /* treat chunks as samples */
8867     if (!gst_byte_reader_get_uint32_be (&stream->stco, &stream->n_samples))
8868       goto corrupt_file;
8869   } else {
8870     /* skip number of entries */
8871     if (!gst_byte_reader_skip (&stream->stco, 4))
8872       goto corrupt_file;
8873
8874     /* make sure there are enough data in the stsz atom */
8875     if (!stream->sample_size) {
8876       /* different sizes for each sample */
8877       if (!qt_atom_parser_has_chunks (&stream->stsz, stream->n_samples, 4))
8878         goto corrupt_file;
8879     }
8880   }
8881
8882   GST_DEBUG_OBJECT (qtdemux, "allocating n_samples %u * %u (%.2f MB)",
8883       stream->n_samples, (guint) sizeof (QtDemuxSample),
8884       stream->n_samples * sizeof (QtDemuxSample) / (1024.0 * 1024.0));
8885
8886   if (stream->n_samples >=
8887       QTDEMUX_MAX_SAMPLE_INDEX_SIZE / sizeof (QtDemuxSample)) {
8888     GST_WARNING_OBJECT (qtdemux, "not allocating index of %d samples, would "
8889         "be larger than %uMB (broken file?)", stream->n_samples,
8890         QTDEMUX_MAX_SAMPLE_INDEX_SIZE >> 20);
8891     return FALSE;
8892   }
8893
8894   g_assert (stream->samples == NULL);
8895   stream->samples = g_try_new0 (QtDemuxSample, stream->n_samples);
8896   if (!stream->samples) {
8897     GST_WARNING_OBJECT (qtdemux, "failed to allocate %d samples",
8898         stream->n_samples);
8899     return FALSE;
8900   }
8901
8902   /* composition time-to-sample */
8903   if ((stream->ctts_present =
8904           ! !qtdemux_tree_get_child_by_type_full (stbl, FOURCC_ctts,
8905               &stream->ctts) ? TRUE : FALSE) == TRUE) {
8906     GstByteReader cslg = GST_BYTE_READER_INIT (NULL, 0);
8907
8908     /* copy atom data into a new buffer for later use */
8909     stream->ctts.data = g_memdup (stream->ctts.data, stream->ctts.size);
8910
8911     /* skip version + flags */
8912     if (!gst_byte_reader_skip (&stream->ctts, 1 + 3)
8913         || !gst_byte_reader_get_uint32_be (&stream->ctts,
8914             &stream->n_composition_times))
8915       goto corrupt_file;
8916
8917     /* make sure there's enough data */
8918     if (!qt_atom_parser_has_chunks (&stream->ctts, stream->n_composition_times,
8919             4 + 4))
8920       goto corrupt_file;
8921
8922     /* This is optional, if missing we iterate the ctts */
8923     if (qtdemux_tree_get_child_by_type_full (stbl, FOURCC_cslg, &cslg)) {
8924       if (!gst_byte_reader_skip (&cslg, 1 + 3)
8925           || !gst_byte_reader_get_uint32_be (&cslg, &stream->cslg_shift)) {
8926         g_free ((gpointer) cslg.data);
8927         goto corrupt_file;
8928       }
8929     } else {
8930       gint32 cslg_least = 0;
8931       guint num_entries, pos;
8932       gint i;
8933
8934       pos = gst_byte_reader_get_pos (&stream->ctts);
8935       num_entries = stream->n_composition_times;
8936
8937       stream->cslg_shift = 0;
8938
8939       for (i = 0; i < num_entries; i++) {
8940         gint32 offset;
8941
8942         gst_byte_reader_skip_unchecked (&stream->ctts, 4);
8943         offset = gst_byte_reader_get_int32_be_unchecked (&stream->ctts);
8944
8945         if (offset < cslg_least)
8946           cslg_least = offset;
8947       }
8948
8949       if (cslg_least < 0)
8950         stream->cslg_shift = ABS (cslg_least);
8951       else
8952         stream->cslg_shift = 0;
8953
8954       /* reset the reader so we can generate sample table */
8955       gst_byte_reader_set_pos (&stream->ctts, pos);
8956     }
8957   } else {
8958     /* Ensure the cslg_shift value is consistent so we can use it
8959      * unconditionnally to produce TS and Segment */
8960     stream->cslg_shift = 0;
8961   }
8962
8963   return TRUE;
8964
8965 corrupt_file:
8966   {
8967     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
8968         (_("This file is corrupt and cannot be played.")), (NULL));
8969     return FALSE;
8970   }
8971 no_samples:
8972   {
8973     gst_qtdemux_stbl_free (stream);
8974     if (!qtdemux->fragmented) {
8975       /* not quite good */
8976       GST_WARNING_OBJECT (qtdemux, "stream has no samples");
8977       return FALSE;
8978     } else {
8979       /* may pick up samples elsewhere */
8980       return TRUE;
8981     }
8982   }
8983 }
8984
8985 /* collect samples from the next sample to be parsed up to sample @n for @stream
8986  * by reading the info from @stbl
8987  *
8988  * This code can be executed from both the streaming thread and the seeking
8989  * thread so it takes the object lock to protect itself
8990  */
8991 static gboolean
8992 qtdemux_parse_samples (GstQTDemux * qtdemux, QtDemuxStream * stream, guint32 n)
8993 {
8994   gint i, j, k;
8995   QtDemuxSample *samples, *first, *cur, *last;
8996   guint32 n_samples_per_chunk;
8997   guint32 n_samples;
8998
8999   GST_LOG_OBJECT (qtdemux, "parsing samples for stream fourcc %"
9000       GST_FOURCC_FORMAT ", pad %s",
9001       GST_FOURCC_ARGS (CUR_STREAM (stream)->fourcc),
9002       stream->pad ? GST_PAD_NAME (stream->pad) : "(NULL)");
9003
9004   n_samples = stream->n_samples;
9005
9006   if (n >= n_samples)
9007     goto out_of_samples;
9008
9009   GST_OBJECT_LOCK (qtdemux);
9010   if (n <= stream->stbl_index)
9011     goto already_parsed;
9012
9013   GST_DEBUG_OBJECT (qtdemux, "parsing up to sample %u", n);
9014
9015   if (!stream->stsz.data) {
9016     /* so we already parsed and passed all the moov samples;
9017      * onto fragmented ones */
9018     g_assert (qtdemux->fragmented);
9019     goto done;
9020   }
9021
9022   /* pointer to the sample table */
9023   samples = stream->samples;
9024
9025   /* starts from -1, moves to the next sample index to parse */
9026   stream->stbl_index++;
9027
9028   /* keep track of the first and last sample to fill */
9029   first = &samples[stream->stbl_index];
9030   last = &samples[n];
9031
9032   if (!stream->chunks_are_samples) {
9033     /* set the sample sizes */
9034     if (stream->sample_size == 0) {
9035       /* different sizes for each sample */
9036       for (cur = first; cur <= last; cur++) {
9037         cur->size = gst_byte_reader_get_uint32_be_unchecked (&stream->stsz);
9038         GST_LOG_OBJECT (qtdemux, "sample %d has size %u",
9039             (guint) (cur - samples), cur->size);
9040       }
9041     } else {
9042       /* samples have the same size */
9043       GST_LOG_OBJECT (qtdemux, "all samples have size %u", stream->sample_size);
9044       for (cur = first; cur <= last; cur++)
9045         cur->size = stream->sample_size;
9046     }
9047   }
9048
9049   n_samples_per_chunk = stream->n_samples_per_chunk;
9050   cur = first;
9051
9052   for (i = stream->stsc_index; i < n_samples_per_chunk; i++) {
9053     guint32 last_chunk;
9054
9055     if (stream->stsc_chunk_index >= stream->last_chunk
9056         || stream->stsc_chunk_index < stream->first_chunk) {
9057       stream->first_chunk =
9058           gst_byte_reader_get_uint32_be_unchecked (&stream->stsc);
9059       stream->samples_per_chunk =
9060           gst_byte_reader_get_uint32_be_unchecked (&stream->stsc);
9061       /* starts from 1 */
9062       stream->stsd_sample_description_id =
9063           gst_byte_reader_get_uint32_be_unchecked (&stream->stsc) - 1;
9064
9065       /* chunk numbers are counted from 1 it seems */
9066       if (G_UNLIKELY (stream->first_chunk == 0))
9067         goto corrupt_file;
9068
9069       --stream->first_chunk;
9070
9071       /* the last chunk of each entry is calculated by taking the first chunk
9072        * of the next entry; except if there is no next, where we fake it with
9073        * INT_MAX */
9074       if (G_UNLIKELY (i == (stream->n_samples_per_chunk - 1))) {
9075         stream->last_chunk = G_MAXUINT32;
9076       } else {
9077         stream->last_chunk =
9078             gst_byte_reader_peek_uint32_be_unchecked (&stream->stsc);
9079         if (G_UNLIKELY (stream->last_chunk == 0))
9080           goto corrupt_file;
9081
9082         --stream->last_chunk;
9083       }
9084
9085       GST_LOG_OBJECT (qtdemux,
9086           "entry %d has first_chunk %d, last_chunk %d, samples_per_chunk %d"
9087           "sample desc ID: %d", i, stream->first_chunk, stream->last_chunk,
9088           stream->samples_per_chunk, stream->stsd_sample_description_id);
9089
9090       if (G_UNLIKELY (stream->last_chunk < stream->first_chunk))
9091         goto corrupt_file;
9092
9093       if (stream->last_chunk != G_MAXUINT32) {
9094         if (!qt_atom_parser_peek_sub (&stream->stco,
9095                 stream->first_chunk * stream->co_size,
9096                 (stream->last_chunk - stream->first_chunk) * stream->co_size,
9097                 &stream->co_chunk))
9098           goto corrupt_file;
9099
9100       } else {
9101         stream->co_chunk = stream->stco;
9102         if (!gst_byte_reader_skip (&stream->co_chunk,
9103                 stream->first_chunk * stream->co_size))
9104           goto corrupt_file;
9105       }
9106
9107       stream->stsc_chunk_index = stream->first_chunk;
9108     }
9109
9110     last_chunk = stream->last_chunk;
9111
9112     if (stream->chunks_are_samples) {
9113       cur = &samples[stream->stsc_chunk_index];
9114
9115       for (j = stream->stsc_chunk_index; j < last_chunk; j++) {
9116         if (j > n) {
9117           /* save state */
9118           stream->stsc_chunk_index = j;
9119           goto done;
9120         }
9121
9122         cur->offset =
9123             qt_atom_parser_get_offset_unchecked (&stream->co_chunk,
9124             stream->co_size);
9125
9126         GST_LOG_OBJECT (qtdemux, "Created entry %d with offset "
9127             "%" G_GUINT64_FORMAT, j, cur->offset);
9128
9129         if (CUR_STREAM (stream)->samples_per_frame > 0 &&
9130             CUR_STREAM (stream)->bytes_per_frame > 0) {
9131           cur->size =
9132               (stream->samples_per_chunk * CUR_STREAM (stream)->n_channels) /
9133               CUR_STREAM (stream)->samples_per_frame *
9134               CUR_STREAM (stream)->bytes_per_frame;
9135         } else {
9136           cur->size = stream->samples_per_chunk;
9137         }
9138
9139         GST_DEBUG_OBJECT (qtdemux,
9140             "keyframe sample %d: timestamp %" GST_TIME_FORMAT ", size %u",
9141             j, GST_TIME_ARGS (QTSTREAMTIME_TO_GSTTIME (stream,
9142                     stream->stco_sample_index)), cur->size);
9143
9144         cur->timestamp = stream->stco_sample_index;
9145         cur->duration = stream->samples_per_chunk;
9146         cur->keyframe = TRUE;
9147         cur++;
9148
9149         stream->stco_sample_index += stream->samples_per_chunk;
9150       }
9151       stream->stsc_chunk_index = j;
9152     } else {
9153       for (j = stream->stsc_chunk_index; j < last_chunk; j++) {
9154         guint32 samples_per_chunk;
9155         guint64 chunk_offset;
9156
9157         if (!stream->stsc_sample_index
9158             && !qt_atom_parser_get_offset (&stream->co_chunk, stream->co_size,
9159                 &stream->chunk_offset))
9160           goto corrupt_file;
9161
9162         samples_per_chunk = stream->samples_per_chunk;
9163         chunk_offset = stream->chunk_offset;
9164
9165         for (k = stream->stsc_sample_index; k < samples_per_chunk; k++) {
9166           GST_LOG_OBJECT (qtdemux, "creating entry %d with offset %"
9167               G_GUINT64_FORMAT " and size %d",
9168               (guint) (cur - samples), chunk_offset, cur->size);
9169
9170           cur->offset = chunk_offset;
9171           chunk_offset += cur->size;
9172           cur++;
9173
9174           if (G_UNLIKELY (cur > last)) {
9175             /* save state */
9176             stream->stsc_sample_index = k + 1;
9177             stream->chunk_offset = chunk_offset;
9178             stream->stsc_chunk_index = j;
9179             goto done2;
9180           }
9181         }
9182         stream->stsc_sample_index = 0;
9183       }
9184       stream->stsc_chunk_index = j;
9185     }
9186     stream->stsc_index++;
9187   }
9188
9189   if (stream->chunks_are_samples)
9190     goto ctts;
9191 done2:
9192   {
9193     guint32 n_sample_times;
9194
9195     n_sample_times = stream->n_sample_times;
9196     cur = first;
9197
9198     for (i = stream->stts_index; i < n_sample_times; i++) {
9199       guint32 stts_samples;
9200       gint32 stts_duration;
9201       gint64 stts_time;
9202
9203       if (stream->stts_sample_index >= stream->stts_samples
9204           || !stream->stts_sample_index) {
9205
9206         stream->stts_samples =
9207             gst_byte_reader_get_uint32_be_unchecked (&stream->stts);
9208         stream->stts_duration =
9209             gst_byte_reader_get_uint32_be_unchecked (&stream->stts);
9210
9211         GST_LOG_OBJECT (qtdemux, "block %d, %u timestamps, duration %u",
9212             i, stream->stts_samples, stream->stts_duration);
9213
9214         stream->stts_sample_index = 0;
9215       }
9216
9217       stts_samples = stream->stts_samples;
9218       stts_duration = stream->stts_duration;
9219       stts_time = stream->stts_time;
9220
9221       for (j = stream->stts_sample_index; j < stts_samples; j++) {
9222         GST_DEBUG_OBJECT (qtdemux,
9223             "sample %d: index %d, timestamp %" GST_TIME_FORMAT,
9224             (guint) (cur - samples), j,
9225             GST_TIME_ARGS (QTSTREAMTIME_TO_GSTTIME (stream, stts_time)));
9226
9227         cur->timestamp = stts_time;
9228         cur->duration = stts_duration;
9229
9230         /* avoid 32-bit wrap-around,
9231          * but still mind possible 'negative' duration */
9232         stts_time += (gint64) stts_duration;
9233         cur++;
9234
9235         if (G_UNLIKELY (cur > last)) {
9236           /* save values */
9237           stream->stts_time = stts_time;
9238           stream->stts_sample_index = j + 1;
9239           if (stream->stts_sample_index >= stream->stts_samples)
9240             stream->stts_index++;
9241           goto done3;
9242         }
9243       }
9244       stream->stts_sample_index = 0;
9245       stream->stts_time = stts_time;
9246       stream->stts_index++;
9247     }
9248     /* fill up empty timestamps with the last timestamp, this can happen when
9249      * the last samples do not decode and so we don't have timestamps for them.
9250      * We however look at the last timestamp to estimate the track length so we
9251      * need something in here. */
9252     for (; cur < last; cur++) {
9253       GST_DEBUG_OBJECT (qtdemux,
9254           "fill sample %d: timestamp %" GST_TIME_FORMAT,
9255           (guint) (cur - samples),
9256           GST_TIME_ARGS (QTSTREAMTIME_TO_GSTTIME (stream, stream->stts_time)));
9257       cur->timestamp = stream->stts_time;
9258       cur->duration = -1;
9259     }
9260   }
9261 done3:
9262   {
9263     /* sample sync, can be NULL */
9264     if (stream->stss_present == TRUE) {
9265       guint32 n_sample_syncs;
9266
9267       n_sample_syncs = stream->n_sample_syncs;
9268
9269       if (!n_sample_syncs) {
9270         GST_DEBUG_OBJECT (qtdemux, "all samples are keyframes");
9271         stream->all_keyframe = TRUE;
9272       } else {
9273         for (i = stream->stss_index; i < n_sample_syncs; i++) {
9274           /* note that the first sample is index 1, not 0 */
9275           guint32 index;
9276
9277           index = gst_byte_reader_get_uint32_be_unchecked (&stream->stss);
9278
9279           if (G_LIKELY (index > 0 && index <= n_samples)) {
9280             index -= 1;
9281             samples[index].keyframe = TRUE;
9282             GST_DEBUG_OBJECT (qtdemux, "samples at %u is keyframe", index);
9283             /* and exit if we have enough samples */
9284             if (G_UNLIKELY (index >= n)) {
9285               i++;
9286               break;
9287             }
9288           }
9289         }
9290         /* save state */
9291         stream->stss_index = i;
9292       }
9293
9294       /* stps marks partial sync frames like open GOP I-Frames */
9295       if (stream->stps_present == TRUE) {
9296         guint32 n_sample_partial_syncs;
9297
9298         n_sample_partial_syncs = stream->n_sample_partial_syncs;
9299
9300         /* if there are no entries, the stss table contains the real
9301          * sync samples */
9302         if (n_sample_partial_syncs) {
9303           for (i = stream->stps_index; i < n_sample_partial_syncs; i++) {
9304             /* note that the first sample is index 1, not 0 */
9305             guint32 index;
9306
9307             index = gst_byte_reader_get_uint32_be_unchecked (&stream->stps);
9308
9309             if (G_LIKELY (index > 0 && index <= n_samples)) {
9310               index -= 1;
9311               samples[index].keyframe = TRUE;
9312               GST_DEBUG_OBJECT (qtdemux, "samples at %u is keyframe", index);
9313               /* and exit if we have enough samples */
9314               if (G_UNLIKELY (index >= n)) {
9315                 i++;
9316                 break;
9317               }
9318             }
9319           }
9320           /* save state */
9321           stream->stps_index = i;
9322         }
9323       }
9324     } else {
9325       /* no stss, all samples are keyframes */
9326       stream->all_keyframe = TRUE;
9327       GST_DEBUG_OBJECT (qtdemux, "setting all keyframes");
9328     }
9329   }
9330
9331 ctts:
9332   /* composition time to sample */
9333   if (stream->ctts_present == TRUE) {
9334     guint32 n_composition_times;
9335     guint32 ctts_count;
9336     gint32 ctts_soffset;
9337
9338     /* Fill in the pts_offsets */
9339     cur = first;
9340     n_composition_times = stream->n_composition_times;
9341
9342     for (i = stream->ctts_index; i < n_composition_times; i++) {
9343       if (stream->ctts_sample_index >= stream->ctts_count
9344           || !stream->ctts_sample_index) {
9345         stream->ctts_count =
9346             gst_byte_reader_get_uint32_be_unchecked (&stream->ctts);
9347         stream->ctts_soffset =
9348             gst_byte_reader_get_int32_be_unchecked (&stream->ctts);
9349         stream->ctts_sample_index = 0;
9350       }
9351
9352       ctts_count = stream->ctts_count;
9353       ctts_soffset = stream->ctts_soffset;
9354
9355       for (j = stream->ctts_sample_index; j < ctts_count; j++) {
9356         cur->pts_offset = ctts_soffset;
9357         cur++;
9358
9359         if (G_UNLIKELY (cur > last)) {
9360           /* save state */
9361           stream->ctts_sample_index = j + 1;
9362           goto done;
9363         }
9364       }
9365       stream->ctts_sample_index = 0;
9366       stream->ctts_index++;
9367     }
9368   }
9369 done:
9370   stream->stbl_index = n;
9371   /* if index has been completely parsed, free data that is no-longer needed */
9372   if (n + 1 == stream->n_samples) {
9373     gst_qtdemux_stbl_free (stream);
9374     GST_DEBUG_OBJECT (qtdemux, "parsed all available samples;");
9375     if (qtdemux->pullbased) {
9376       GST_DEBUG_OBJECT (qtdemux, "checking for more samples");
9377       while (n + 1 == stream->n_samples)
9378         if (qtdemux_add_fragmented_samples (qtdemux) != GST_FLOW_OK)
9379           break;
9380     }
9381   }
9382   GST_OBJECT_UNLOCK (qtdemux);
9383
9384   return TRUE;
9385
9386   /* SUCCESS */
9387 already_parsed:
9388   {
9389     GST_LOG_OBJECT (qtdemux,
9390         "Tried to parse up to sample %u but this sample has already been parsed",
9391         n);
9392     /* if fragmented, there may be more */
9393     if (qtdemux->fragmented && n == stream->stbl_index)
9394       goto done;
9395     GST_OBJECT_UNLOCK (qtdemux);
9396     return TRUE;
9397   }
9398   /* ERRORS */
9399 out_of_samples:
9400   {
9401     GST_LOG_OBJECT (qtdemux,
9402         "Tried to parse up to sample %u but there are only %u samples", n + 1,
9403         stream->n_samples);
9404     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
9405         (_("This file is corrupt and cannot be played.")), (NULL));
9406     return FALSE;
9407   }
9408 corrupt_file:
9409   {
9410     GST_OBJECT_UNLOCK (qtdemux);
9411     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
9412         (_("This file is corrupt and cannot be played.")), (NULL));
9413     return FALSE;
9414   }
9415 }
9416
9417 /* collect all segment info for @stream.
9418  */
9419 static gboolean
9420 qtdemux_parse_segments (GstQTDemux * qtdemux, QtDemuxStream * stream,
9421     GNode * trak)
9422 {
9423   GNode *edts;
9424   /* accept edts if they contain gaps at start and there is only
9425    * one media segment */
9426   gboolean allow_pushbased_edts = TRUE;
9427   gint media_segments_count = 0;
9428
9429   /* parse and prepare segment info from the edit list */
9430   GST_DEBUG_OBJECT (qtdemux, "looking for edit list container");
9431   stream->n_segments = 0;
9432   stream->segments = NULL;
9433   if ((edts = qtdemux_tree_get_child_by_type (trak, FOURCC_edts))) {
9434     GNode *elst;
9435     gint n_segments;
9436     gint segment_number, entry_size;
9437     guint64 time;
9438     GstClockTime stime;
9439     const guint8 *buffer;
9440     guint8 version;
9441     guint32 size;
9442
9443     GST_DEBUG_OBJECT (qtdemux, "looking for edit list");
9444     if (!(elst = qtdemux_tree_get_child_by_type (edts, FOURCC_elst)))
9445       goto done;
9446
9447     buffer = elst->data;
9448
9449     size = QT_UINT32 (buffer);
9450     /* version, flags, n_segments */
9451     if (size < 16) {
9452       GST_WARNING_OBJECT (qtdemux, "Invalid edit list");
9453       goto done;
9454     }
9455     version = QT_UINT8 (buffer + 8);
9456     entry_size = (version == 1) ? 20 : 12;
9457
9458     n_segments = QT_UINT32 (buffer + 12);
9459
9460     if (n_segments > 100000 || size < 16 + n_segments * entry_size) {
9461       GST_WARNING_OBJECT (qtdemux, "Invalid edit list");
9462       goto done;
9463     }
9464
9465     /* we might allocate a bit too much, at least allocate 1 segment */
9466     stream->segments = g_new (QtDemuxSegment, MAX (n_segments, 1));
9467
9468     /* segments always start from 0 */
9469     time = 0;
9470     stime = 0;
9471     buffer += 16;
9472     for (segment_number = 0; segment_number < n_segments; segment_number++) {
9473       guint64 duration;
9474       guint64 media_time;
9475       gboolean empty_edit = FALSE;
9476       QtDemuxSegment *segment;
9477       guint32 rate_int;
9478       GstClockTime media_start = GST_CLOCK_TIME_NONE;
9479
9480       if (version == 1) {
9481         media_time = QT_UINT64 (buffer + 8);
9482         duration = QT_UINT64 (buffer);
9483         if (media_time == G_MAXUINT64)
9484           empty_edit = TRUE;
9485       } else {
9486         media_time = QT_UINT32 (buffer + 4);
9487         duration = QT_UINT32 (buffer);
9488         if (media_time == G_MAXUINT32)
9489           empty_edit = TRUE;
9490       }
9491
9492       if (!empty_edit)
9493         media_start = QTSTREAMTIME_TO_GSTTIME (stream, media_time);
9494
9495       segment = &stream->segments[segment_number];
9496
9497       /* time and duration expressed in global timescale */
9498       segment->time = stime;
9499       if (duration != 0 || empty_edit) {
9500         /* edge case: empty edits with duration=zero are treated here.
9501          * (files should not have these anyway). */
9502
9503         /* add non scaled values so we don't cause roundoff errors */
9504         time += duration;
9505         stime = QTTIME_TO_GSTTIME (qtdemux, time);
9506         segment->duration = stime - segment->time;
9507       } else {
9508         /* zero duration does not imply media_start == media_stop
9509          * but, only specify media_start. The edit ends with the track. */
9510         stime = segment->duration = GST_CLOCK_TIME_NONE;
9511         /* Don't allow more edits after this one. */
9512         n_segments = segment_number + 1;
9513       }
9514       segment->stop_time = stime;
9515
9516       segment->trak_media_start = media_time;
9517       /* media_time expressed in stream timescale */
9518       if (!empty_edit) {
9519         segment->media_start = media_start;
9520         segment->media_stop = GST_CLOCK_TIME_IS_VALID (segment->duration)
9521             ? segment->media_start + segment->duration : GST_CLOCK_TIME_NONE;
9522         media_segments_count++;
9523       } else {
9524         segment->media_start = GST_CLOCK_TIME_NONE;
9525         segment->media_stop = GST_CLOCK_TIME_NONE;
9526       }
9527       rate_int = QT_UINT32 (buffer + ((version == 1) ? 16 : 8));
9528
9529       if (rate_int <= 1) {
9530         /* 0 is not allowed, some programs write 1 instead of the floating point
9531          * value */
9532         GST_WARNING_OBJECT (qtdemux, "found suspicious rate %" G_GUINT32_FORMAT,
9533             rate_int);
9534         segment->rate = 1;
9535       } else {
9536         segment->rate = rate_int / 65536.0;
9537       }
9538
9539       GST_DEBUG_OBJECT (qtdemux, "created segment %d time %" GST_TIME_FORMAT
9540           ", duration %" GST_TIME_FORMAT ", media_start %" GST_TIME_FORMAT
9541           " (%" G_GUINT64_FORMAT ") , media_stop %" GST_TIME_FORMAT
9542           " stop_time %" GST_TIME_FORMAT " rate %g, (%d) timescale %u",
9543           segment_number, GST_TIME_ARGS (segment->time),
9544           GST_TIME_ARGS (segment->duration),
9545           GST_TIME_ARGS (segment->media_start), media_time,
9546           GST_TIME_ARGS (segment->media_stop),
9547           GST_TIME_ARGS (segment->stop_time), segment->rate, rate_int,
9548           stream->timescale);
9549       if (segment->stop_time > qtdemux->segment.stop) {
9550         GST_WARNING_OBJECT (qtdemux, "Segment %d "
9551             " extends to %" GST_TIME_FORMAT
9552             " past the end of the file duration %" GST_TIME_FORMAT
9553             " it will be truncated", segment_number,
9554             GST_TIME_ARGS (segment->stop_time),
9555             GST_TIME_ARGS (qtdemux->segment.stop));
9556         qtdemux->segment.stop = segment->stop_time;
9557       }
9558
9559       buffer += entry_size;
9560     }
9561     GST_DEBUG_OBJECT (qtdemux, "found %d segments", n_segments);
9562     stream->n_segments = n_segments;
9563     if (media_segments_count != 1)
9564       allow_pushbased_edts = FALSE;
9565   }
9566 done:
9567
9568   /* push based does not handle segments, so act accordingly here,
9569    * and warn if applicable */
9570   if (!qtdemux->pullbased && !allow_pushbased_edts) {
9571     GST_WARNING_OBJECT (qtdemux, "streaming; discarding edit list segments");
9572     /* remove and use default one below, we stream like it anyway */
9573     g_free (stream->segments);
9574     stream->segments = NULL;
9575     stream->n_segments = 0;
9576   }
9577
9578   /* no segments, create one to play the complete trak */
9579   if (stream->n_segments == 0) {
9580     GstClockTime stream_duration =
9581         QTSTREAMTIME_TO_GSTTIME (stream, stream->duration);
9582
9583     if (stream->segments == NULL)
9584       stream->segments = g_new (QtDemuxSegment, 1);
9585
9586     /* represent unknown our way */
9587     if (stream_duration == 0)
9588       stream_duration = GST_CLOCK_TIME_NONE;
9589
9590     stream->segments[0].time = 0;
9591     stream->segments[0].stop_time = stream_duration;
9592     stream->segments[0].duration = stream_duration;
9593     stream->segments[0].media_start = 0;
9594     stream->segments[0].media_stop = stream_duration;
9595     stream->segments[0].rate = 1.0;
9596     stream->segments[0].trak_media_start = 0;
9597
9598     GST_DEBUG_OBJECT (qtdemux, "created dummy segment %" GST_TIME_FORMAT,
9599         GST_TIME_ARGS (stream_duration));
9600     stream->n_segments = 1;
9601     stream->dummy_segment = TRUE;
9602   }
9603   GST_DEBUG_OBJECT (qtdemux, "using %d segments", stream->n_segments);
9604
9605   return TRUE;
9606 }
9607
9608 /*
9609  * Parses the stsd atom of a svq3 trak looking for
9610  * the SMI and gama atoms.
9611  */
9612 static void
9613 qtdemux_parse_svq3_stsd_data (GstQTDemux * qtdemux,
9614     const guint8 * stsd_entry_data, const guint8 ** gamma, GstBuffer ** seqh)
9615 {
9616   const guint8 *_gamma = NULL;
9617   GstBuffer *_seqh = NULL;
9618   const guint8 *stsd_data = stsd_entry_data;
9619   guint32 length = QT_UINT32 (stsd_data);
9620   guint16 version;
9621
9622   if (length < 32) {
9623     GST_WARNING_OBJECT (qtdemux, "stsd too short");
9624     goto end;
9625   }
9626
9627   stsd_data += 16;
9628   length -= 16;
9629   version = QT_UINT16 (stsd_data);
9630   if (version == 3) {
9631     if (length >= 70) {
9632       length -= 70;
9633       stsd_data += 70;
9634       while (length > 8) {
9635         guint32 fourcc, size;
9636         const guint8 *data;
9637         size = QT_UINT32 (stsd_data);
9638         fourcc = QT_FOURCC (stsd_data + 4);
9639         data = stsd_data + 8;
9640
9641         if (size == 0) {
9642           GST_WARNING_OBJECT (qtdemux, "Atom of size 0 found, aborting "
9643               "svq3 atom parsing");
9644           goto end;
9645         }
9646
9647         switch (fourcc) {
9648           case FOURCC_gama:{
9649             if (size == 12) {
9650               _gamma = data;
9651             } else {
9652               GST_WARNING_OBJECT (qtdemux, "Unexpected size %" G_GUINT32_FORMAT
9653                   " for gama atom, expected 12", size);
9654             }
9655             break;
9656           }
9657           case FOURCC_SMI_:{
9658             if (size > 16 && QT_FOURCC (data) == FOURCC_SEQH) {
9659               guint32 seqh_size;
9660               if (_seqh != NULL) {
9661                 GST_WARNING_OBJECT (qtdemux, "Unexpected second SEQH SMI atom "
9662                     " found, ignoring");
9663               } else {
9664                 seqh_size = QT_UINT32 (data + 4);
9665                 if (seqh_size > 0) {
9666                   _seqh = gst_buffer_new_and_alloc (seqh_size);
9667                   gst_buffer_fill (_seqh, 0, data + 8, seqh_size);
9668                 }
9669               }
9670             }
9671             break;
9672           }
9673           default:{
9674             GST_WARNING_OBJECT (qtdemux, "Unhandled atom %" GST_FOURCC_FORMAT
9675                 " in SVQ3 entry in stsd atom", GST_FOURCC_ARGS (fourcc));
9676           }
9677         }
9678
9679         if (size <= length) {
9680           length -= size;
9681           stsd_data += size;
9682         }
9683       }
9684     } else {
9685       GST_WARNING_OBJECT (qtdemux, "SVQ3 entry too short in stsd atom");
9686     }
9687   } else {
9688     GST_WARNING_OBJECT (qtdemux, "Unexpected version for SVQ3 entry %"
9689         G_GUINT16_FORMAT, version);
9690     goto end;
9691   }
9692
9693 end:
9694   if (gamma) {
9695     *gamma = _gamma;
9696   }
9697   if (seqh) {
9698     *seqh = _seqh;
9699   } else if (_seqh) {
9700     gst_buffer_unref (_seqh);
9701   }
9702 }
9703
9704 static gchar *
9705 qtdemux_get_rtsp_uri_from_hndl (GstQTDemux * qtdemux, GNode * minf)
9706 {
9707   GNode *dinf;
9708   GstByteReader dref;
9709   gchar *uri = NULL;
9710
9711   /*
9712    * Get 'dinf', to get its child 'dref', that might contain a 'hndl'
9713    * atom that might contain a 'data' atom with the rtsp uri.
9714    * This case was reported in bug #597497, some info about
9715    * the hndl atom can be found in TN1195
9716    */
9717   dinf = qtdemux_tree_get_child_by_type (minf, FOURCC_dinf);
9718   GST_DEBUG_OBJECT (qtdemux, "Trying to obtain rtsp URI for stream trak");
9719
9720   if (dinf) {
9721     guint32 dref_num_entries = 0;
9722     if (qtdemux_tree_get_child_by_type_full (dinf, FOURCC_dref, &dref) &&
9723         gst_byte_reader_skip (&dref, 4) &&
9724         gst_byte_reader_get_uint32_be (&dref, &dref_num_entries)) {
9725       gint i;
9726
9727       /* search dref entries for hndl atom */
9728       for (i = 0; i < dref_num_entries; i++) {
9729         guint32 size = 0, type;
9730         guint8 string_len = 0;
9731         if (gst_byte_reader_get_uint32_be (&dref, &size) &&
9732             qt_atom_parser_get_fourcc (&dref, &type)) {
9733           if (type == FOURCC_hndl) {
9734             GST_DEBUG_OBJECT (qtdemux, "Found hndl atom");
9735
9736             /* skip data reference handle bytes and the
9737              * following pascal string and some extra 4
9738              * bytes I have no idea what are */
9739             if (!gst_byte_reader_skip (&dref, 4) ||
9740                 !gst_byte_reader_get_uint8 (&dref, &string_len) ||
9741                 !gst_byte_reader_skip (&dref, string_len + 4)) {
9742               GST_WARNING_OBJECT (qtdemux, "Failed to parse hndl atom");
9743               break;
9744             }
9745
9746             /* iterate over the atoms to find the data atom */
9747             while (gst_byte_reader_get_remaining (&dref) >= 8) {
9748               guint32 atom_size;
9749               guint32 atom_type;
9750
9751               if (gst_byte_reader_get_uint32_be (&dref, &atom_size) &&
9752                   qt_atom_parser_get_fourcc (&dref, &atom_type)) {
9753                 if (atom_type == FOURCC_data) {
9754                   const guint8 *uri_aux = NULL;
9755
9756                   /* found the data atom that might contain the rtsp uri */
9757                   GST_DEBUG_OBJECT (qtdemux, "Found data atom inside "
9758                       "hndl atom, interpreting it as an URI");
9759                   if (gst_byte_reader_peek_data (&dref, atom_size - 8,
9760                           &uri_aux)) {
9761                     if (g_strstr_len ((gchar *) uri_aux, 7, "rtsp://") != NULL)
9762                       uri = g_strndup ((gchar *) uri_aux, atom_size - 8);
9763                     else
9764                       GST_WARNING_OBJECT (qtdemux, "Data atom in hndl atom "
9765                           "didn't contain a rtsp address");
9766                   } else {
9767                     GST_WARNING_OBJECT (qtdemux, "Failed to get the data "
9768                         "atom contents");
9769                   }
9770                   break;
9771                 }
9772                 /* skipping to the next entry */
9773                 if (!gst_byte_reader_skip (&dref, atom_size - 8))
9774                   break;
9775               } else {
9776                 GST_WARNING_OBJECT (qtdemux, "Failed to parse hndl child "
9777                     "atom header");
9778                 break;
9779               }
9780             }
9781             break;
9782           }
9783           /* skip to the next entry */
9784           if (!gst_byte_reader_skip (&dref, size - 8))
9785             break;
9786         } else {
9787           GST_WARNING_OBJECT (qtdemux, "Error parsing dref atom");
9788         }
9789       }
9790       GST_DEBUG_OBJECT (qtdemux, "Finished parsing dref atom");
9791     }
9792   }
9793   return uri;
9794 }
9795
9796 #define AMR_NB_ALL_MODES        0x81ff
9797 #define AMR_WB_ALL_MODES        0x83ff
9798 static guint
9799 qtdemux_parse_amr_bitrate (GstBuffer * buf, gboolean wb)
9800 {
9801   /* The 'damr' atom is of the form:
9802    *
9803    * | vendor | decoder_ver | mode_set | mode_change_period | frames/sample |
9804    *    32 b       8 b          16 b           8 b                 8 b
9805    *
9806    * The highest set bit of the first 7 (AMR-NB) or 8 (AMR-WB) bits of mode_set
9807    * represents the highest mode used in the stream (and thus the maximum
9808    * bitrate), with a couple of special cases as seen below.
9809    */
9810
9811   /* Map of frame type ID -> bitrate */
9812   static const guint nb_bitrates[] = {
9813     4750, 5150, 5900, 6700, 7400, 7950, 10200, 12200
9814   };
9815   static const guint wb_bitrates[] = {
9816     6600, 8850, 12650, 14250, 15850, 18250, 19850, 23050, 23850
9817   };
9818   GstMapInfo map;
9819   gsize max_mode;
9820   guint16 mode_set;
9821
9822   gst_buffer_map (buf, &map, GST_MAP_READ);
9823
9824   if (map.size != 0x11) {
9825     GST_DEBUG ("Atom should have size 0x11, not %" G_GSIZE_FORMAT, map.size);
9826     goto bad_data;
9827   }
9828
9829   if (QT_FOURCC (map.data + 4) != FOURCC_damr) {
9830     GST_DEBUG ("Unknown atom in %" GST_FOURCC_FORMAT,
9831         GST_FOURCC_ARGS (QT_UINT32 (map.data + 4)));
9832     goto bad_data;
9833   }
9834
9835   mode_set = QT_UINT16 (map.data + 13);
9836
9837   if (mode_set == (wb ? AMR_WB_ALL_MODES : AMR_NB_ALL_MODES))
9838     max_mode = 7 + (wb ? 1 : 0);
9839   else
9840     /* AMR-NB modes fo from 0-7, and AMR-WB modes go from 0-8 */
9841     max_mode = g_bit_nth_msf ((gulong) mode_set & (wb ? 0x1ff : 0xff), -1);
9842
9843   if (max_mode == -1) {
9844     GST_DEBUG ("No mode indication was found (mode set) = %x",
9845         (guint) mode_set);
9846     goto bad_data;
9847   }
9848
9849   gst_buffer_unmap (buf, &map);
9850   return wb ? wb_bitrates[max_mode] : nb_bitrates[max_mode];
9851
9852 bad_data:
9853   gst_buffer_unmap (buf, &map);
9854   return 0;
9855 }
9856
9857 static gboolean
9858 qtdemux_parse_transformation_matrix (GstQTDemux * qtdemux,
9859     GstByteReader * reader, guint32 * matrix, const gchar * atom)
9860 {
9861   /*
9862    * 9 values of 32 bits (fixed point 16.16, except 2 5 and 8 that are 2.30)
9863    * [0 1 2]
9864    * [3 4 5]
9865    * [6 7 8]
9866    */
9867
9868   if (gst_byte_reader_get_remaining (reader) < 36)
9869     return FALSE;
9870
9871   matrix[0] = gst_byte_reader_get_uint32_be_unchecked (reader);
9872   matrix[1] = gst_byte_reader_get_uint32_be_unchecked (reader);
9873   matrix[2] = gst_byte_reader_get_uint32_be_unchecked (reader);
9874   matrix[3] = gst_byte_reader_get_uint32_be_unchecked (reader);
9875   matrix[4] = gst_byte_reader_get_uint32_be_unchecked (reader);
9876   matrix[5] = gst_byte_reader_get_uint32_be_unchecked (reader);
9877   matrix[6] = gst_byte_reader_get_uint32_be_unchecked (reader);
9878   matrix[7] = gst_byte_reader_get_uint32_be_unchecked (reader);
9879   matrix[8] = gst_byte_reader_get_uint32_be_unchecked (reader);
9880
9881   GST_DEBUG_OBJECT (qtdemux, "Transformation matrix from atom %s", atom);
9882   GST_DEBUG_OBJECT (qtdemux, "%u.%u %u.%u %u.%u", matrix[0] >> 16,
9883       matrix[0] & 0xFFFF, matrix[1] >> 16, matrix[1] & 0xFF, matrix[2] >> 16,
9884       matrix[2] & 0xFF);
9885   GST_DEBUG_OBJECT (qtdemux, "%u.%u %u.%u %u.%u", matrix[3] >> 16,
9886       matrix[3] & 0xFFFF, matrix[4] >> 16, matrix[4] & 0xFF, matrix[5] >> 16,
9887       matrix[5] & 0xFF);
9888   GST_DEBUG_OBJECT (qtdemux, "%u.%u %u.%u %u.%u", matrix[6] >> 16,
9889       matrix[6] & 0xFFFF, matrix[7] >> 16, matrix[7] & 0xFF, matrix[8] >> 16,
9890       matrix[8] & 0xFF);
9891
9892   return TRUE;
9893 }
9894
9895 static void
9896 qtdemux_inspect_transformation_matrix (GstQTDemux * qtdemux,
9897     QtDemuxStream * stream, guint32 * matrix, GstTagList ** taglist)
9898 {
9899
9900 /* [a b c]
9901  * [d e f]
9902  * [g h i]
9903  *
9904  * This macro will only compare value abdegh, it expects cfi to have already
9905  * been checked
9906  */
9907 #define QTCHECK_MATRIX(m,a,b,d,e) ((m)[0] == (a << 16) && (m)[1] == (b << 16) && \
9908                                    (m)[3] == (d << 16) && (m)[4] == (e << 16))
9909
9910   /* only handle the cases where the last column has standard values */
9911   if (matrix[2] == 0 && matrix[5] == 0 && matrix[8] == 1 << 30) {
9912     const gchar *rotation_tag = NULL;
9913
9914     /* no rotation needed */
9915     if (QTCHECK_MATRIX (matrix, 1, 0, 0, 1)) {
9916       /* NOP */
9917     } else if (QTCHECK_MATRIX (matrix, 0, 1, G_MAXUINT16, 0)) {
9918       rotation_tag = "rotate-90";
9919     } else if (QTCHECK_MATRIX (matrix, G_MAXUINT16, 0, 0, G_MAXUINT16)) {
9920       rotation_tag = "rotate-180";
9921     } else if (QTCHECK_MATRIX (matrix, 0, G_MAXUINT16, 1, 0)) {
9922       rotation_tag = "rotate-270";
9923     } else {
9924       GST_FIXME_OBJECT (qtdemux, "Unhandled transformation matrix values");
9925     }
9926
9927     GST_DEBUG_OBJECT (qtdemux, "Transformation matrix rotation %s",
9928         rotation_tag);
9929     if (rotation_tag != NULL) {
9930       if (*taglist == NULL)
9931         *taglist = gst_tag_list_new_empty ();
9932       gst_tag_list_add (*taglist, GST_TAG_MERGE_REPLACE,
9933           GST_TAG_IMAGE_ORIENTATION, rotation_tag, NULL);
9934     }
9935   } else {
9936     GST_FIXME_OBJECT (qtdemux, "Unhandled transformation matrix values");
9937   }
9938 }
9939
9940 /* Parses the boxes defined in ISO/IEC 14496-12 that enable support for
9941  * protected streams (sinf, frma, schm and schi); if the protection scheme is
9942  * Common Encryption (cenc), the function will also parse the tenc box (defined
9943  * in ISO/IEC 23001-7). @container points to the node that contains these boxes
9944  * (typically an enc[v|a|t|s] sample entry); the function will set
9945  * @original_fmt to the fourcc of the original unencrypted stream format.
9946  * Returns TRUE if successful; FALSE otherwise. */
9947 static gboolean
9948 qtdemux_parse_protection_scheme_info (GstQTDemux * qtdemux,
9949     QtDemuxStream * stream, GNode * container, guint32 * original_fmt)
9950 {
9951   GNode *sinf;
9952   GNode *frma;
9953   GNode *schm;
9954   GNode *schi;
9955
9956   g_return_val_if_fail (qtdemux != NULL, FALSE);
9957   g_return_val_if_fail (stream != NULL, FALSE);
9958   g_return_val_if_fail (container != NULL, FALSE);
9959   g_return_val_if_fail (original_fmt != NULL, FALSE);
9960
9961   sinf = qtdemux_tree_get_child_by_type (container, FOURCC_sinf);
9962   if (G_UNLIKELY (!sinf)) {
9963     if (stream->protection_scheme_type == FOURCC_cenc) {
9964       GST_ERROR_OBJECT (qtdemux, "sinf box does not contain schi box, which is "
9965           "mandatory for Common Encryption");
9966       return FALSE;
9967     }
9968     return TRUE;
9969   }
9970
9971   frma = qtdemux_tree_get_child_by_type (sinf, FOURCC_frma);
9972   if (G_UNLIKELY (!frma)) {
9973     GST_ERROR_OBJECT (qtdemux, "sinf box does not contain mandatory frma box");
9974     return FALSE;
9975   }
9976
9977   *original_fmt = QT_FOURCC ((const guint8 *) frma->data + 8);
9978   GST_DEBUG_OBJECT (qtdemux, "original stream format: '%" GST_FOURCC_FORMAT "'",
9979       GST_FOURCC_ARGS (*original_fmt));
9980
9981   schm = qtdemux_tree_get_child_by_type (sinf, FOURCC_schm);
9982   if (!schm) {
9983     GST_DEBUG_OBJECT (qtdemux, "sinf box does not contain schm box");
9984     return FALSE;
9985   }
9986   stream->protection_scheme_type = QT_FOURCC ((const guint8 *) schm->data + 12);
9987   stream->protection_scheme_version =
9988       QT_UINT32 ((const guint8 *) schm->data + 16);
9989
9990   GST_DEBUG_OBJECT (qtdemux,
9991       "protection_scheme_type: %" GST_FOURCC_FORMAT ", "
9992       "protection_scheme_version: %#010x",
9993       GST_FOURCC_ARGS (stream->protection_scheme_type),
9994       stream->protection_scheme_version);
9995
9996   schi = qtdemux_tree_get_child_by_type (sinf, FOURCC_schi);
9997   if (!schi) {
9998     GST_DEBUG_OBJECT (qtdemux, "sinf box does not contain schi box");
9999     return FALSE;
10000   }
10001   if (stream->protection_scheme_type == FOURCC_cenc) {
10002     QtDemuxCencSampleSetInfo *info;
10003     GNode *tenc;
10004     const guint8 *tenc_data;
10005     guint32 isEncrypted;
10006     guint8 iv_size;
10007     const guint8 *default_kid;
10008     GstBuffer *kid_buf;
10009
10010     if (G_UNLIKELY (!stream->protection_scheme_info))
10011       stream->protection_scheme_info =
10012           g_malloc0 (sizeof (QtDemuxCencSampleSetInfo));
10013
10014     info = (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
10015
10016     tenc = qtdemux_tree_get_child_by_type (schi, FOURCC_tenc);
10017     if (!tenc) {
10018       GST_ERROR_OBJECT (qtdemux, "schi box does not contain tenc box, "
10019           "which is mandatory for Common Encryption");
10020       return FALSE;
10021     }
10022     tenc_data = (const guint8 *) tenc->data + 12;
10023     isEncrypted = QT_UINT24 (tenc_data);
10024     iv_size = QT_UINT8 (tenc_data + 3);
10025     default_kid = (tenc_data + 4);
10026     kid_buf = gst_buffer_new_allocate (NULL, 16, NULL);
10027     gst_buffer_fill (kid_buf, 0, default_kid, 16);
10028     if (info->default_properties)
10029       gst_structure_free (info->default_properties);
10030     info->default_properties =
10031         gst_structure_new ("application/x-cenc",
10032         "iv_size", G_TYPE_UINT, iv_size,
10033         "encrypted", G_TYPE_BOOLEAN, (isEncrypted == 1),
10034         "kid", GST_TYPE_BUFFER, kid_buf, NULL);
10035     GST_DEBUG_OBJECT (qtdemux, "default sample properties: "
10036         "is_encrypted=%u, iv_size=%u", isEncrypted, iv_size);
10037     gst_buffer_unref (kid_buf);
10038   }
10039   return TRUE;
10040 }
10041
10042 static gint
10043 qtdemux_track_id_compare_func (QtDemuxStream * stream1, QtDemuxStream * stream2)
10044 {
10045   return (gint) stream1->track_id - (gint) stream2->track_id;
10046 }
10047
10048 /* parse the traks.
10049  * With each track we associate a new QtDemuxStream that contains all the info
10050  * about the trak.
10051  * traks that do not decode to something (like strm traks) will not have a pad.
10052  */
10053 static gboolean
10054 qtdemux_parse_trak (GstQTDemux * qtdemux, GNode * trak)
10055 {
10056   GstByteReader tkhd;
10057   int offset;
10058   GNode *mdia;
10059   GNode *mdhd;
10060   GNode *hdlr;
10061   GNode *minf;
10062   GNode *stbl;
10063   GNode *stsd;
10064   GNode *mp4a;
10065   GNode *mp4v;
10066   GNode *esds;
10067   GNode *tref;
10068   GNode *udta;
10069   GNode *svmi;
10070
10071   QtDemuxStream *stream = NULL;
10072   const guint8 *stsd_data;
10073   const guint8 *stsd_entry_data;
10074   guint remaining_stsd_len;
10075   guint stsd_entry_count;
10076   guint stsd_index;
10077   guint16 lang_code;            /* quicktime lang code or packed iso code */
10078   guint32 version;
10079   guint32 tkhd_flags = 0;
10080   guint8 tkhd_version = 0;
10081   guint32 w = 0, h = 0;
10082   guint value_size, stsd_len, len;
10083   guint32 track_id;
10084   guint32 dummy;
10085
10086   GST_DEBUG_OBJECT (qtdemux, "parse_trak");
10087
10088   if (!qtdemux_tree_get_child_by_type_full (trak, FOURCC_tkhd, &tkhd)
10089       || !gst_byte_reader_get_uint8 (&tkhd, &tkhd_version)
10090       || !gst_byte_reader_get_uint24_be (&tkhd, &tkhd_flags))
10091     goto corrupt_file;
10092
10093   /* pick between 64 or 32 bits */
10094   value_size = tkhd_version == 1 ? 8 : 4;
10095   if (!gst_byte_reader_skip (&tkhd, value_size * 2) ||
10096       !gst_byte_reader_get_uint32_be (&tkhd, &track_id))
10097     goto corrupt_file;
10098
10099   /* Check if current moov has duplicated track_id */
10100   if (qtdemux_find_stream (qtdemux, track_id))
10101     goto existing_stream;
10102
10103   stream = _create_stream (qtdemux, track_id);
10104   stream->stream_tags = gst_tag_list_make_writable (stream->stream_tags);
10105
10106   /* need defaults for fragments */
10107   qtdemux_parse_trex (qtdemux, stream, &dummy, &dummy, &dummy);
10108
10109   if ((tkhd_flags & 1) == 0)
10110     stream->disabled = TRUE;
10111
10112   GST_LOG_OBJECT (qtdemux, "track[tkhd] version/flags/id: 0x%02x/%06x/%u",
10113       tkhd_version, tkhd_flags, stream->track_id);
10114
10115   if (!(mdia = qtdemux_tree_get_child_by_type (trak, FOURCC_mdia)))
10116     goto corrupt_file;
10117
10118   if (!(mdhd = qtdemux_tree_get_child_by_type (mdia, FOURCC_mdhd))) {
10119     /* be nice for some crooked mjp2 files that use mhdr for mdhd */
10120     if (qtdemux->major_brand != FOURCC_mjp2 ||
10121         !(mdhd = qtdemux_tree_get_child_by_type (mdia, FOURCC_mhdr)))
10122       goto corrupt_file;
10123   }
10124
10125   len = QT_UINT32 ((guint8 *) mdhd->data);
10126   version = QT_UINT32 ((guint8 *) mdhd->data + 8);
10127   GST_LOG_OBJECT (qtdemux, "track version/flags: %08x", version);
10128   if (version == 0x01000000) {
10129     if (len < 38)
10130       goto corrupt_file;
10131     stream->timescale = QT_UINT32 ((guint8 *) mdhd->data + 28);
10132     stream->duration = QT_UINT64 ((guint8 *) mdhd->data + 32);
10133     lang_code = QT_UINT16 ((guint8 *) mdhd->data + 36);
10134   } else {
10135     if (len < 30)
10136       goto corrupt_file;
10137     stream->timescale = QT_UINT32 ((guint8 *) mdhd->data + 20);
10138     stream->duration = QT_UINT32 ((guint8 *) mdhd->data + 24);
10139     lang_code = QT_UINT16 ((guint8 *) mdhd->data + 28);
10140   }
10141
10142   if (lang_code < 0x400) {
10143     qtdemux_lang_map_qt_code_to_iso (stream->lang_id, lang_code);
10144   } else if (lang_code == 0x7fff) {
10145     stream->lang_id[0] = 0;     /* unspecified */
10146   } else {
10147     stream->lang_id[0] = 0x60 + ((lang_code >> 10) & 0x1F);
10148     stream->lang_id[1] = 0x60 + ((lang_code >> 5) & 0x1F);
10149     stream->lang_id[2] = 0x60 + (lang_code & 0x1F);
10150     stream->lang_id[3] = 0;
10151   }
10152
10153   GST_LOG_OBJECT (qtdemux, "track timescale: %" G_GUINT32_FORMAT,
10154       stream->timescale);
10155   GST_LOG_OBJECT (qtdemux, "track duration: %" G_GUINT64_FORMAT,
10156       stream->duration);
10157   GST_LOG_OBJECT (qtdemux, "track language code/id: 0x%04x/%s",
10158       lang_code, stream->lang_id);
10159
10160   if (G_UNLIKELY (stream->timescale == 0 || qtdemux->timescale == 0))
10161     goto corrupt_file;
10162
10163   if ((tref = qtdemux_tree_get_child_by_type (trak, FOURCC_tref))) {
10164     /* chapters track reference */
10165     GNode *chap = qtdemux_tree_get_child_by_type (tref, FOURCC_chap);
10166     if (chap) {
10167       gsize length = GST_READ_UINT32_BE (chap->data);
10168       if (qtdemux->chapters_track_id)
10169         GST_FIXME_OBJECT (qtdemux, "Multiple CHAP tracks");
10170
10171       if (length >= 12) {
10172         qtdemux->chapters_track_id =
10173             GST_READ_UINT32_BE ((gint8 *) chap->data + 8);
10174       }
10175     }
10176   }
10177
10178   /* fragmented files may have bogus duration in moov */
10179   if (!qtdemux->fragmented &&
10180       qtdemux->duration != G_MAXINT64 && stream->duration != G_MAXINT32) {
10181     guint64 tdur1, tdur2;
10182
10183     /* don't overflow */
10184     tdur1 = stream->timescale * (guint64) qtdemux->duration;
10185     tdur2 = qtdemux->timescale * (guint64) stream->duration;
10186
10187     /* HACK:
10188      * some of those trailers, nowadays, have prologue images that are
10189      * themselves video tracks as well. I haven't really found a way to
10190      * identify those yet, except for just looking at their duration. */
10191     if (tdur1 != 0 && (tdur2 * 10 / tdur1) < 2) {
10192       GST_WARNING_OBJECT (qtdemux,
10193           "Track shorter than 20%% (%" G_GUINT64_FORMAT "/%" G_GUINT32_FORMAT
10194           " vs. %" G_GUINT64_FORMAT "/%" G_GUINT32_FORMAT ") of the stream "
10195           "found, assuming preview image or something; skipping track",
10196           stream->duration, stream->timescale, qtdemux->duration,
10197           qtdemux->timescale);
10198       gst_qtdemux_stream_free (stream);
10199       return TRUE;
10200     }
10201   }
10202
10203   if (!(hdlr = qtdemux_tree_get_child_by_type (mdia, FOURCC_hdlr)))
10204     goto corrupt_file;
10205
10206   GST_LOG_OBJECT (qtdemux, "track type: %" GST_FOURCC_FORMAT,
10207       GST_FOURCC_ARGS (QT_FOURCC ((guint8 *) hdlr->data + 12)));
10208
10209   len = QT_UINT32 ((guint8 *) hdlr->data);
10210   if (len >= 20)
10211     stream->subtype = QT_FOURCC ((guint8 *) hdlr->data + 16);
10212   GST_LOG_OBJECT (qtdemux, "track subtype: %" GST_FOURCC_FORMAT,
10213       GST_FOURCC_ARGS (stream->subtype));
10214
10215   if (!(minf = qtdemux_tree_get_child_by_type (mdia, FOURCC_minf)))
10216     goto corrupt_file;
10217
10218   if (!(stbl = qtdemux_tree_get_child_by_type (minf, FOURCC_stbl)))
10219     goto corrupt_file;
10220
10221   /*parse svmi header if existing */
10222   svmi = qtdemux_tree_get_child_by_type (stbl, FOURCC_svmi);
10223   if (svmi) {
10224     len = QT_UINT32 ((guint8 *) svmi->data);
10225     version = QT_UINT32 ((guint8 *) svmi->data + 8);
10226     if (!version) {
10227       GstVideoMultiviewMode mode = GST_VIDEO_MULTIVIEW_MODE_NONE;
10228       GstVideoMultiviewFlags flags = GST_VIDEO_MULTIVIEW_FLAGS_NONE;
10229       guint8 frame_type, frame_layout;
10230
10231       /* MPEG-A stereo video */
10232       if (qtdemux->major_brand == FOURCC_ss02)
10233         flags |= GST_VIDEO_MULTIVIEW_FLAGS_MIXED_MONO;
10234
10235       frame_type = QT_UINT8 ((guint8 *) svmi->data + 12);
10236       frame_layout = QT_UINT8 ((guint8 *) svmi->data + 13) & 0x01;
10237       switch (frame_type) {
10238         case 0:
10239           mode = GST_VIDEO_MULTIVIEW_MODE_SIDE_BY_SIDE;
10240           break;
10241         case 1:
10242           mode = GST_VIDEO_MULTIVIEW_MODE_ROW_INTERLEAVED;
10243           break;
10244         case 2:
10245           mode = GST_VIDEO_MULTIVIEW_MODE_FRAME_BY_FRAME;
10246           break;
10247         case 3:
10248           /* mode 3 is primary/secondary view sequence, ie
10249            * left/right views in separate tracks. See section 7.2
10250            * of ISO/IEC 23000-11:2009 */
10251           GST_FIXME_OBJECT (qtdemux,
10252               "Implement stereo video in separate streams");
10253       }
10254
10255       if ((frame_layout & 0x1) == 0)
10256         flags |= GST_VIDEO_MULTIVIEW_FLAGS_RIGHT_VIEW_FIRST;
10257
10258       GST_LOG_OBJECT (qtdemux,
10259           "StereoVideo: composition type: %u, is_left_first: %u",
10260           frame_type, frame_layout);
10261       stream->multiview_mode = mode;
10262       stream->multiview_flags = flags;
10263     }
10264   }
10265
10266   /* parse rest of tkhd */
10267   if (stream->subtype == FOURCC_vide) {
10268     guint32 matrix[9];
10269
10270     /* version 1 uses some 64-bit ints */
10271     if (!gst_byte_reader_skip (&tkhd, 20 + value_size))
10272       goto corrupt_file;
10273
10274     if (!qtdemux_parse_transformation_matrix (qtdemux, &tkhd, matrix, "tkhd"))
10275       goto corrupt_file;
10276
10277     if (!gst_byte_reader_get_uint32_be (&tkhd, &w)
10278         || !gst_byte_reader_get_uint32_be (&tkhd, &h))
10279       goto corrupt_file;
10280
10281     qtdemux_inspect_transformation_matrix (qtdemux, stream, matrix,
10282         &stream->stream_tags);
10283   }
10284
10285   /* parse stsd */
10286   if (!(stsd = qtdemux_tree_get_child_by_type (stbl, FOURCC_stsd)))
10287     goto corrupt_file;
10288   stsd_data = (const guint8 *) stsd->data;
10289
10290   /* stsd should at least have one entry */
10291   stsd_len = QT_UINT32 (stsd_data);
10292   if (stsd_len < 24) {
10293     /* .. but skip stream with empty stsd produced by some Vivotek cameras */
10294     if (stream->subtype == FOURCC_vivo) {
10295       gst_qtdemux_stream_free (stream);
10296       return TRUE;
10297     } else {
10298       goto corrupt_file;
10299     }
10300   }
10301
10302   stream->stsd_entries_length = stsd_entry_count = QT_UINT32 (stsd_data + 12);
10303   stream->stsd_entries = g_new0 (QtDemuxStreamStsdEntry, stsd_entry_count);
10304   GST_LOG_OBJECT (qtdemux, "stsd len:           %d", stsd_len);
10305   GST_LOG_OBJECT (qtdemux, "stsd entry count:   %u", stsd_entry_count);
10306
10307   stsd_entry_data = stsd_data + 16;
10308   remaining_stsd_len = stsd_len - 16;
10309   for (stsd_index = 0; stsd_index < stsd_entry_count; stsd_index++) {
10310     guint32 fourcc;
10311     gchar *codec = NULL;
10312     QtDemuxStreamStsdEntry *entry = &stream->stsd_entries[stsd_index];
10313
10314     /* and that entry should fit within stsd */
10315     len = QT_UINT32 (stsd_entry_data);
10316     if (len > remaining_stsd_len)
10317       goto corrupt_file;
10318
10319     entry->fourcc = fourcc = QT_FOURCC (stsd_entry_data + 4);
10320     GST_LOG_OBJECT (qtdemux, "stsd type:          %" GST_FOURCC_FORMAT,
10321         GST_FOURCC_ARGS (entry->fourcc));
10322     GST_LOG_OBJECT (qtdemux, "stsd type len:      %d", len);
10323
10324     if ((fourcc == FOURCC_drms) || (fourcc == FOURCC_drmi))
10325       goto error_encrypted;
10326
10327     if (fourcc == FOURCC_encv || fourcc == FOURCC_enca) {
10328       /* FIXME this looks wrong, there might be multiple children
10329        * with the same type */
10330       GNode *enc = qtdemux_tree_get_child_by_type (stsd, fourcc);
10331       stream->protected = TRUE;
10332       if (!qtdemux_parse_protection_scheme_info (qtdemux, stream, enc, &fourcc))
10333         GST_ERROR_OBJECT (qtdemux, "Failed to parse protection scheme info");
10334     }
10335
10336     if (stream->subtype == FOURCC_vide) {
10337       GNode *colr;
10338       GNode *fiel;
10339       GNode *pasp;
10340       gboolean gray;
10341       gint depth, palette_size, palette_count;
10342       guint32 *palette_data = NULL;
10343
10344       entry->sampled = TRUE;
10345
10346       stream->display_width = w >> 16;
10347       stream->display_height = h >> 16;
10348
10349       offset = 16;
10350       if (len < 86)             /* TODO verify */
10351         goto corrupt_file;
10352
10353       entry->width = QT_UINT16 (stsd_entry_data + offset + 16);
10354       entry->height = QT_UINT16 (stsd_entry_data + offset + 18);
10355       entry->fps_n = 0;         /* this is filled in later */
10356       entry->fps_d = 0;         /* this is filled in later */
10357       entry->bits_per_sample = QT_UINT16 (stsd_entry_data + offset + 66);
10358       entry->color_table_id = QT_UINT16 (stsd_entry_data + offset + 68);
10359
10360       /* if color_table_id is 0, ctab atom must follow; however some files
10361        * produced by TMPEGEnc have color_table_id = 0 and no ctab atom, so
10362        * if color table is not present we'll correct the value */
10363       if (entry->color_table_id == 0 &&
10364           (len < 90
10365               || QT_FOURCC (stsd_entry_data + offset + 70) != FOURCC_ctab)) {
10366         entry->color_table_id = -1;
10367       }
10368
10369       GST_LOG_OBJECT (qtdemux, "width %d, height %d, bps %d, color table id %d",
10370           entry->width, entry->height, entry->bits_per_sample,
10371           entry->color_table_id);
10372
10373       depth = entry->bits_per_sample;
10374
10375       /* more than 32 bits means grayscale */
10376       gray = (depth > 32);
10377       /* low 32 bits specify the depth  */
10378       depth &= 0x1F;
10379
10380       /* different number of palette entries is determined by depth. */
10381       palette_count = 0;
10382       if ((depth == 1) || (depth == 2) || (depth == 4) || (depth == 8))
10383         palette_count = (1 << depth);
10384       palette_size = palette_count * 4;
10385
10386       if (entry->color_table_id) {
10387         switch (palette_count) {
10388           case 0:
10389             break;
10390           case 2:
10391             palette_data = g_memdup (ff_qt_default_palette_2, palette_size);
10392             break;
10393           case 4:
10394             palette_data = g_memdup (ff_qt_default_palette_4, palette_size);
10395             break;
10396           case 16:
10397             if (gray)
10398               palette_data =
10399                   g_memdup (ff_qt_grayscale_palette_16, palette_size);
10400             else
10401               palette_data = g_memdup (ff_qt_default_palette_16, palette_size);
10402             break;
10403           case 256:
10404             if (gray)
10405               palette_data =
10406                   g_memdup (ff_qt_grayscale_palette_256, palette_size);
10407             else
10408               palette_data = g_memdup (ff_qt_default_palette_256, palette_size);
10409             break;
10410           default:
10411             GST_ELEMENT_WARNING (qtdemux, STREAM, DEMUX,
10412                 (_("The video in this file might not play correctly.")),
10413                 ("unsupported palette depth %d", depth));
10414             break;
10415         }
10416       } else {
10417         gint i, j, start, end;
10418
10419         if (len < 94)
10420           goto corrupt_file;
10421
10422         /* read table */
10423         start = QT_UINT32 (stsd_entry_data + offset + 70);
10424         palette_count = QT_UINT16 (stsd_entry_data + offset + 74);
10425         end = QT_UINT16 (stsd_entry_data + offset + 76);
10426
10427         GST_LOG_OBJECT (qtdemux, "start %d, end %d, palette_count %d",
10428             start, end, palette_count);
10429
10430         if (end > 255)
10431           end = 255;
10432         if (start > end)
10433           start = end;
10434
10435         if (len < 94 + (end - start) * 8)
10436           goto corrupt_file;
10437
10438         /* palette is always the same size */
10439         palette_data = g_malloc0 (256 * 4);
10440         palette_size = 256 * 4;
10441
10442         for (j = 0, i = start; i <= end; j++, i++) {
10443           guint32 a, r, g, b;
10444
10445           a = QT_UINT16 (stsd_entry_data + offset + 78 + (j * 8));
10446           r = QT_UINT16 (stsd_entry_data + offset + 80 + (j * 8));
10447           g = QT_UINT16 (stsd_entry_data + offset + 82 + (j * 8));
10448           b = QT_UINT16 (stsd_entry_data + offset + 84 + (j * 8));
10449
10450           palette_data[i] = ((a & 0xff00) << 16) | ((r & 0xff00) << 8) |
10451               (g & 0xff00) | (b >> 8);
10452         }
10453       }
10454
10455       if (entry->caps)
10456         gst_caps_unref (entry->caps);
10457
10458       entry->caps =
10459           qtdemux_video_caps (qtdemux, stream, entry, fourcc, stsd_entry_data,
10460           &codec);
10461       if (G_UNLIKELY (!entry->caps)) {
10462         g_free (palette_data);
10463         goto unknown_stream;
10464       }
10465
10466       if (codec) {
10467         gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
10468             GST_TAG_VIDEO_CODEC, codec, NULL);
10469         g_free (codec);
10470         codec = NULL;
10471       }
10472
10473       if (palette_data) {
10474         GstStructure *s;
10475
10476         if (entry->rgb8_palette)
10477           gst_memory_unref (entry->rgb8_palette);
10478         entry->rgb8_palette = gst_memory_new_wrapped (GST_MEMORY_FLAG_READONLY,
10479             palette_data, palette_size, 0, palette_size, palette_data, g_free);
10480
10481         s = gst_caps_get_structure (entry->caps, 0);
10482
10483         /* non-raw video has a palette_data property. raw video has the palette as
10484          * an extra plane that we append to the output buffers before we push
10485          * them*/
10486         if (!gst_structure_has_name (s, "video/x-raw")) {
10487           GstBuffer *palette;
10488
10489           palette = gst_buffer_new ();
10490           gst_buffer_append_memory (palette, entry->rgb8_palette);
10491           entry->rgb8_palette = NULL;
10492
10493           gst_caps_set_simple (entry->caps, "palette_data",
10494               GST_TYPE_BUFFER, palette, NULL);
10495           gst_buffer_unref (palette);
10496         }
10497       } else if (palette_count != 0) {
10498         GST_ELEMENT_WARNING (qtdemux, STREAM, NOT_IMPLEMENTED,
10499             (NULL), ("Unsupported palette depth %d", depth));
10500       }
10501
10502       GST_LOG_OBJECT (qtdemux, "frame count:   %u",
10503           QT_UINT16 (stsd_entry_data + offset + 32));
10504
10505       esds = NULL;
10506       pasp = NULL;
10507       colr = NULL;
10508       fiel = NULL;
10509       /* pick 'the' stsd child */
10510       mp4v = qtdemux_tree_get_child_by_index (stsd, stsd_index);
10511       if (!stream->protected) {
10512         if (QTDEMUX_TREE_NODE_FOURCC (mp4v) != fourcc) {
10513           mp4v = NULL;
10514         }
10515       } else {
10516         if (QTDEMUX_TREE_NODE_FOURCC (mp4v) != FOURCC_encv) {
10517           mp4v = NULL;
10518         }
10519       }
10520
10521       if (mp4v) {
10522         esds = qtdemux_tree_get_child_by_type (mp4v, FOURCC_esds);
10523         pasp = qtdemux_tree_get_child_by_type (mp4v, FOURCC_pasp);
10524         colr = qtdemux_tree_get_child_by_type (mp4v, FOURCC_colr);
10525         fiel = qtdemux_tree_get_child_by_type (mp4v, FOURCC_fiel);
10526       }
10527
10528       if (pasp) {
10529         const guint8 *pasp_data = (const guint8 *) pasp->data;
10530         gint len = QT_UINT32 (pasp_data);
10531
10532         if (len == 16) {
10533           CUR_STREAM (stream)->par_w = QT_UINT32 (pasp_data + 8);
10534           CUR_STREAM (stream)->par_h = QT_UINT32 (pasp_data + 12);
10535         } else {
10536           CUR_STREAM (stream)->par_w = 0;
10537           CUR_STREAM (stream)->par_h = 0;
10538         }
10539       } else {
10540         CUR_STREAM (stream)->par_w = 0;
10541         CUR_STREAM (stream)->par_h = 0;
10542       }
10543
10544       if (fiel) {
10545         const guint8 *fiel_data = (const guint8 *) fiel->data;
10546         gint len = QT_UINT32 (fiel_data);
10547
10548         if (len == 10) {
10549           CUR_STREAM (stream)->interlace_mode = GST_READ_UINT8 (fiel_data + 8);
10550           CUR_STREAM (stream)->field_order = GST_READ_UINT8 (fiel_data + 9);
10551         }
10552       }
10553
10554       if (colr) {
10555         const guint8 *colr_data = (const guint8 *) colr->data;
10556         gint len = QT_UINT32 (colr_data);
10557
10558         if (len == 19 || len == 18) {
10559           guint32 color_type = GST_READ_UINT32_LE (colr_data + 8);
10560
10561           if (color_type == FOURCC_nclx || color_type == FOURCC_nclc) {
10562             guint16 primaries = GST_READ_UINT16_BE (colr_data + 12);
10563             guint16 transfer_function = GST_READ_UINT16_BE (colr_data + 14);
10564             guint16 matrix = GST_READ_UINT16_BE (colr_data + 16);
10565             gboolean full_range = len == 19 ? colr_data[17] >> 7 : FALSE;
10566
10567             switch (primaries) {
10568               case 1:
10569                 CUR_STREAM (stream)->colorimetry.primaries =
10570                     GST_VIDEO_COLOR_PRIMARIES_BT709;
10571                 break;
10572               case 5:
10573                 CUR_STREAM (stream)->colorimetry.primaries =
10574                     GST_VIDEO_COLOR_PRIMARIES_BT470BG;
10575                 break;
10576               case 6:
10577                 CUR_STREAM (stream)->colorimetry.primaries =
10578                     GST_VIDEO_COLOR_PRIMARIES_SMPTE170M;
10579                 break;
10580               case 9:
10581                 CUR_STREAM (stream)->colorimetry.primaries =
10582                     GST_VIDEO_COLOR_PRIMARIES_BT2020;
10583                 break;
10584               default:
10585                 break;
10586             }
10587
10588             switch (transfer_function) {
10589               case 1:
10590                 CUR_STREAM (stream)->colorimetry.transfer =
10591                     GST_VIDEO_TRANSFER_BT709;
10592                 break;
10593               case 7:
10594                 CUR_STREAM (stream)->colorimetry.transfer =
10595                     GST_VIDEO_TRANSFER_SMPTE240M;
10596                 break;
10597               default:
10598                 break;
10599             }
10600
10601             switch (matrix) {
10602               case 1:
10603                 CUR_STREAM (stream)->colorimetry.matrix =
10604                     GST_VIDEO_COLOR_MATRIX_BT709;
10605                 break;
10606               case 6:
10607                 CUR_STREAM (stream)->colorimetry.matrix =
10608                     GST_VIDEO_COLOR_MATRIX_BT601;
10609                 break;
10610               case 7:
10611                 CUR_STREAM (stream)->colorimetry.matrix =
10612                     GST_VIDEO_COLOR_MATRIX_SMPTE240M;
10613                 break;
10614               case 9:
10615                 CUR_STREAM (stream)->colorimetry.matrix =
10616                     GST_VIDEO_COLOR_MATRIX_BT2020;
10617                 break;
10618               default:
10619                 break;
10620             }
10621
10622             CUR_STREAM (stream)->colorimetry.range =
10623                 full_range ? GST_VIDEO_COLOR_RANGE_0_255 :
10624                 GST_VIDEO_COLOR_RANGE_16_235;
10625           } else {
10626             GST_DEBUG_OBJECT (qtdemux, "Unsupported color type");
10627           }
10628         } else {
10629           GST_WARNING_OBJECT (qtdemux, "Invalid colr atom size");
10630         }
10631       }
10632
10633       if (esds) {
10634         gst_qtdemux_handle_esds (qtdemux, stream, entry, esds,
10635             stream->stream_tags);
10636       } else {
10637         switch (fourcc) {
10638           case FOURCC_H264:
10639           case FOURCC_avc1:
10640           case FOURCC_avc3:
10641           {
10642             gint len = QT_UINT32 (stsd_entry_data) - 0x56;
10643             const guint8 *avc_data = stsd_entry_data + 0x56;
10644
10645             /* find avcC */
10646             while (len >= 0x8) {
10647               gint size;
10648
10649               if (QT_UINT32 (avc_data) <= len)
10650                 size = QT_UINT32 (avc_data) - 0x8;
10651               else
10652                 size = len - 0x8;
10653
10654               if (size < 1)
10655                 /* No real data, so break out */
10656                 break;
10657
10658               switch (QT_FOURCC (avc_data + 0x4)) {
10659                 case FOURCC_avcC:
10660                 {
10661                   /* parse, if found */
10662                   GstBuffer *buf;
10663
10664                   GST_DEBUG_OBJECT (qtdemux, "found avcC codec_data in stsd");
10665
10666                   /* First 4 bytes are the length of the atom, the next 4 bytes
10667                    * are the fourcc, the next 1 byte is the version, and the
10668                    * subsequent bytes are profile_tier_level structure like data. */
10669                   gst_codec_utils_h264_caps_set_level_and_profile (entry->caps,
10670                       avc_data + 8 + 1, size - 1);
10671                   buf = gst_buffer_new_and_alloc (size);
10672                   gst_buffer_fill (buf, 0, avc_data + 0x8, size);
10673                   gst_caps_set_simple (entry->caps,
10674                       "codec_data", GST_TYPE_BUFFER, buf, NULL);
10675                   gst_buffer_unref (buf);
10676
10677                   break;
10678                 }
10679                 case FOURCC_strf:
10680                 {
10681                   GstBuffer *buf;
10682
10683                   GST_DEBUG_OBJECT (qtdemux, "found strf codec_data in stsd");
10684
10685                   /* First 4 bytes are the length of the atom, the next 4 bytes
10686                    * are the fourcc, next 40 bytes are BITMAPINFOHEADER,
10687                    * next 1 byte is the version, and the
10688                    * subsequent bytes are sequence parameter set like data. */
10689
10690                   size -= 40;   /* we'll be skipping BITMAPINFOHEADER */
10691                   if (size > 1) {
10692                     gst_codec_utils_h264_caps_set_level_and_profile
10693                         (entry->caps, avc_data + 8 + 40 + 1, size - 1);
10694
10695                     buf = gst_buffer_new_and_alloc (size);
10696                     gst_buffer_fill (buf, 0, avc_data + 8 + 40, size);
10697                     gst_caps_set_simple (entry->caps,
10698                         "codec_data", GST_TYPE_BUFFER, buf, NULL);
10699                     gst_buffer_unref (buf);
10700                   }
10701                   break;
10702                 }
10703                 case FOURCC_btrt:
10704                 {
10705                   guint avg_bitrate, max_bitrate;
10706
10707                   /* bufferSizeDB, maxBitrate and avgBitrate - 4 bytes each */
10708                   if (size < 12)
10709                     break;
10710
10711                   max_bitrate = QT_UINT32 (avc_data + 0xc);
10712                   avg_bitrate = QT_UINT32 (avc_data + 0x10);
10713
10714                   if (!max_bitrate && !avg_bitrate)
10715                     break;
10716
10717                   /* Some muxers seem to swap the average and maximum bitrates
10718                    * (I'm looking at you, YouTube), so we swap for sanity. */
10719                   if (max_bitrate > 0 && max_bitrate < avg_bitrate) {
10720                     guint temp = avg_bitrate;
10721
10722                     avg_bitrate = max_bitrate;
10723                     max_bitrate = temp;
10724                   }
10725
10726                   if (max_bitrate > 0 && max_bitrate < G_MAXUINT32) {
10727                     gst_tag_list_add (stream->stream_tags,
10728                         GST_TAG_MERGE_REPLACE, GST_TAG_MAXIMUM_BITRATE,
10729                         max_bitrate, NULL);
10730                   }
10731                   if (avg_bitrate > 0 && avg_bitrate < G_MAXUINT32) {
10732                     gst_tag_list_add (stream->stream_tags,
10733                         GST_TAG_MERGE_REPLACE, GST_TAG_BITRATE, avg_bitrate,
10734                         NULL);
10735                   }
10736
10737                   break;
10738                 }
10739
10740                 default:
10741                   break;
10742               }
10743
10744               len -= size + 8;
10745               avc_data += size + 8;
10746             }
10747
10748             break;
10749           }
10750           case FOURCC_H265:
10751           case FOURCC_hvc1:
10752           case FOURCC_hev1:
10753           {
10754             gint len = QT_UINT32 (stsd_entry_data) - 0x56;
10755             const guint8 *hevc_data = stsd_entry_data + 0x56;
10756
10757             /* find hevc */
10758             while (len >= 0x8) {
10759               gint size;
10760
10761               if (QT_UINT32 (hevc_data) <= len)
10762                 size = QT_UINT32 (hevc_data) - 0x8;
10763               else
10764                 size = len - 0x8;
10765
10766               if (size < 1)
10767                 /* No real data, so break out */
10768                 break;
10769
10770               switch (QT_FOURCC (hevc_data + 0x4)) {
10771                 case FOURCC_hvcC:
10772                 {
10773                   /* parse, if found */
10774                   GstBuffer *buf;
10775
10776                   GST_DEBUG_OBJECT (qtdemux, "found hvcC codec_data in stsd");
10777
10778                   /* First 4 bytes are the length of the atom, the next 4 bytes
10779                    * are the fourcc, the next 1 byte is the version, and the
10780                    * subsequent bytes are sequence parameter set like data. */
10781                   gst_codec_utils_h265_caps_set_level_tier_and_profile
10782                       (entry->caps, hevc_data + 8 + 1, size - 1);
10783
10784                   buf = gst_buffer_new_and_alloc (size);
10785                   gst_buffer_fill (buf, 0, hevc_data + 0x8, size);
10786                   gst_caps_set_simple (entry->caps,
10787                       "codec_data", GST_TYPE_BUFFER, buf, NULL);
10788                   gst_buffer_unref (buf);
10789                   break;
10790                 }
10791                 default:
10792                   break;
10793               }
10794               len -= size + 8;
10795               hevc_data += size + 8;
10796             }
10797             break;
10798           }
10799           case FOURCC_mp4v:
10800           case FOURCC_MP4V:
10801           case FOURCC_fmp4:
10802           case FOURCC_FMP4:
10803           case FOURCC_xvid:
10804           case FOURCC_XVID:
10805           {
10806             GNode *glbl;
10807
10808             GST_DEBUG_OBJECT (qtdemux, "found %" GST_FOURCC_FORMAT,
10809                 GST_FOURCC_ARGS (fourcc));
10810
10811             /* codec data might be in glbl extension atom */
10812             glbl = mp4v ?
10813                 qtdemux_tree_get_child_by_type (mp4v, FOURCC_glbl) : NULL;
10814             if (glbl) {
10815               guint8 *data;
10816               GstBuffer *buf;
10817               gint len;
10818
10819               GST_DEBUG_OBJECT (qtdemux, "found glbl data in stsd");
10820               data = glbl->data;
10821               len = QT_UINT32 (data);
10822               if (len > 0x8) {
10823                 len -= 0x8;
10824                 buf = gst_buffer_new_and_alloc (len);
10825                 gst_buffer_fill (buf, 0, data + 8, len);
10826                 gst_caps_set_simple (entry->caps,
10827                     "codec_data", GST_TYPE_BUFFER, buf, NULL);
10828                 gst_buffer_unref (buf);
10829               }
10830             }
10831             break;
10832           }
10833           case FOURCC_mjp2:
10834           {
10835             /* see annex I of the jpeg2000 spec */
10836             GNode *jp2h, *ihdr, *colr, *mjp2, *field, *prefix, *cmap, *cdef;
10837             const guint8 *data;
10838             const gchar *colorspace = NULL;
10839             gint ncomp = 0;
10840             guint32 ncomp_map = 0;
10841             gint32 *comp_map = NULL;
10842             guint32 nchan_def = 0;
10843             gint32 *chan_def = NULL;
10844
10845             GST_DEBUG_OBJECT (qtdemux, "found mjp2");
10846             /* some required atoms */
10847             mjp2 = qtdemux_tree_get_child_by_index (stsd, stsd_index);
10848             if (!mjp2)
10849               break;
10850             jp2h = qtdemux_tree_get_child_by_type (mjp2, FOURCC_jp2h);
10851             if (!jp2h)
10852               break;
10853
10854             /* number of components; redundant with info in codestream, but useful
10855                to a muxer */
10856             ihdr = qtdemux_tree_get_child_by_type (jp2h, FOURCC_ihdr);
10857             if (!ihdr || QT_UINT32 (ihdr->data) != 22)
10858               break;
10859             ncomp = QT_UINT16 (((guint8 *) ihdr->data) + 16);
10860
10861             colr = qtdemux_tree_get_child_by_type (jp2h, FOURCC_colr);
10862             if (!colr)
10863               break;
10864             GST_DEBUG_OBJECT (qtdemux, "found colr");
10865             /* extract colour space info */
10866             if (QT_UINT8 ((guint8 *) colr->data + 8) == 1) {
10867               switch (QT_UINT32 ((guint8 *) colr->data + 11)) {
10868                 case 16:
10869                   colorspace = "sRGB";
10870                   break;
10871                 case 17:
10872                   colorspace = "GRAY";
10873                   break;
10874                 case 18:
10875                   colorspace = "sYUV";
10876                   break;
10877                 default:
10878                   colorspace = NULL;
10879                   break;
10880               }
10881             }
10882             if (!colorspace)
10883               /* colr is required, and only values 16, 17, and 18 are specified,
10884                  so error if we have no colorspace */
10885               break;
10886
10887             /* extract component mapping */
10888             cmap = qtdemux_tree_get_child_by_type (jp2h, FOURCC_cmap);
10889             if (cmap) {
10890               guint32 cmap_len = 0;
10891               int i;
10892               cmap_len = QT_UINT32 (cmap->data);
10893               if (cmap_len >= 8) {
10894                 /* normal box, subtract off header */
10895                 cmap_len -= 8;
10896                 /* cmap: { u16 cmp; u8 mtyp; u8 pcol; }* */
10897                 if (cmap_len % 4 == 0) {
10898                   ncomp_map = (cmap_len / 4);
10899                   comp_map = g_new0 (gint32, ncomp_map);
10900                   for (i = 0; i < ncomp_map; i++) {
10901                     guint16 cmp;
10902                     guint8 mtyp, pcol;
10903                     cmp = QT_UINT16 (((guint8 *) cmap->data) + 8 + i * 4);
10904                     mtyp = QT_UINT8 (((guint8 *) cmap->data) + 8 + i * 4 + 2);
10905                     pcol = QT_UINT8 (((guint8 *) cmap->data) + 8 + i * 4 + 3);
10906                     comp_map[i] = (mtyp << 24) | (pcol << 16) | cmp;
10907                   }
10908                 }
10909               }
10910             }
10911             /* extract channel definitions */
10912             cdef = qtdemux_tree_get_child_by_type (jp2h, FOURCC_cdef);
10913             if (cdef) {
10914               guint32 cdef_len = 0;
10915               int i;
10916               cdef_len = QT_UINT32 (cdef->data);
10917               if (cdef_len >= 10) {
10918                 /* normal box, subtract off header and len */
10919                 cdef_len -= 10;
10920                 /* cdef: u16 n; { u16 cn; u16 typ; u16 asoc; }* */
10921                 if (cdef_len % 6 == 0) {
10922                   nchan_def = (cdef_len / 6);
10923                   chan_def = g_new0 (gint32, nchan_def);
10924                   for (i = 0; i < nchan_def; i++)
10925                     chan_def[i] = -1;
10926                   for (i = 0; i < nchan_def; i++) {
10927                     guint16 cn, typ, asoc;
10928                     cn = QT_UINT16 (((guint8 *) cdef->data) + 10 + i * 6);
10929                     typ = QT_UINT16 (((guint8 *) cdef->data) + 10 + i * 6 + 2);
10930                     asoc = QT_UINT16 (((guint8 *) cdef->data) + 10 + i * 6 + 4);
10931                     if (cn < nchan_def) {
10932                       switch (typ) {
10933                         case 0:
10934                           chan_def[cn] = asoc;
10935                           break;
10936                         case 1:
10937                           chan_def[cn] = 0;     /* alpha */
10938                           break;
10939                         default:
10940                           chan_def[cn] = -typ;
10941                       }
10942                     }
10943                   }
10944                 }
10945               }
10946             }
10947
10948             gst_caps_set_simple (entry->caps,
10949                 "num-components", G_TYPE_INT, ncomp, NULL);
10950             gst_caps_set_simple (entry->caps,
10951                 "colorspace", G_TYPE_STRING, colorspace, NULL);
10952
10953             if (comp_map) {
10954               GValue arr = { 0, };
10955               GValue elt = { 0, };
10956               int i;
10957               g_value_init (&arr, GST_TYPE_ARRAY);
10958               g_value_init (&elt, G_TYPE_INT);
10959               for (i = 0; i < ncomp_map; i++) {
10960                 g_value_set_int (&elt, comp_map[i]);
10961                 gst_value_array_append_value (&arr, &elt);
10962               }
10963               gst_structure_set_value (gst_caps_get_structure (entry->caps, 0),
10964                   "component-map", &arr);
10965               g_value_unset (&elt);
10966               g_value_unset (&arr);
10967               g_free (comp_map);
10968             }
10969
10970             if (chan_def) {
10971               GValue arr = { 0, };
10972               GValue elt = { 0, };
10973               int i;
10974               g_value_init (&arr, GST_TYPE_ARRAY);
10975               g_value_init (&elt, G_TYPE_INT);
10976               for (i = 0; i < nchan_def; i++) {
10977                 g_value_set_int (&elt, chan_def[i]);
10978                 gst_value_array_append_value (&arr, &elt);
10979               }
10980               gst_structure_set_value (gst_caps_get_structure (entry->caps, 0),
10981                   "channel-definitions", &arr);
10982               g_value_unset (&elt);
10983               g_value_unset (&arr);
10984               g_free (chan_def);
10985             }
10986
10987             /* some optional atoms */
10988             field = qtdemux_tree_get_child_by_type (mjp2, FOURCC_fiel);
10989             prefix = qtdemux_tree_get_child_by_type (mjp2, FOURCC_jp2x);
10990
10991             /* indicate possible fields in caps */
10992             if (field) {
10993               data = (guint8 *) field->data + 8;
10994               if (*data != 1)
10995                 gst_caps_set_simple (entry->caps, "fields", G_TYPE_INT,
10996                     (gint) * data, NULL);
10997             }
10998             /* add codec_data if provided */
10999             if (prefix) {
11000               GstBuffer *buf;
11001               gint len;
11002
11003               GST_DEBUG_OBJECT (qtdemux, "found prefix data in stsd");
11004               data = prefix->data;
11005               len = QT_UINT32 (data);
11006               if (len > 0x8) {
11007                 len -= 0x8;
11008                 buf = gst_buffer_new_and_alloc (len);
11009                 gst_buffer_fill (buf, 0, data + 8, len);
11010                 gst_caps_set_simple (entry->caps,
11011                     "codec_data", GST_TYPE_BUFFER, buf, NULL);
11012                 gst_buffer_unref (buf);
11013               }
11014             }
11015             break;
11016           }
11017           case FOURCC_SVQ3:
11018           case FOURCC_VP31:
11019           {
11020             GstBuffer *buf;
11021             GstBuffer *seqh = NULL;
11022             const guint8 *gamma_data = NULL;
11023             gint len = QT_UINT32 (stsd_data);   /* FIXME review - why put the whole stsd in codec data? */
11024
11025             qtdemux_parse_svq3_stsd_data (qtdemux, stsd_entry_data, &gamma_data,
11026                 &seqh);
11027             if (gamma_data) {
11028               gst_caps_set_simple (entry->caps, "applied-gamma", G_TYPE_DOUBLE,
11029                   QT_FP32 (gamma_data), NULL);
11030             }
11031             if (seqh) {
11032               /* sorry for the bad name, but we don't know what this is, other
11033                * than its own fourcc */
11034               gst_caps_set_simple (entry->caps, "seqh", GST_TYPE_BUFFER, seqh,
11035                   NULL);
11036               gst_buffer_unref (seqh);
11037             }
11038
11039             GST_DEBUG_OBJECT (qtdemux, "found codec_data in stsd");
11040             buf = gst_buffer_new_and_alloc (len);
11041             gst_buffer_fill (buf, 0, stsd_data, len);
11042             gst_caps_set_simple (entry->caps,
11043                 "codec_data", GST_TYPE_BUFFER, buf, NULL);
11044             gst_buffer_unref (buf);
11045             break;
11046           }
11047           case FOURCC_jpeg:
11048           {
11049             /* https://developer.apple.com/standards/qtff-2001.pdf,
11050              * page 92, "Video Sample Description", under table 3.1 */
11051             GstByteReader br;
11052
11053             const gint compressor_offset =
11054                 16 + 4 + 4 * 3 + 2 * 2 + 2 * 4 + 4 + 2;
11055             const gint min_size = compressor_offset + 32 + 2 + 2;
11056             GNode *jpeg;
11057             guint32 len;
11058             guint16 color_table_id = 0;
11059             gboolean ok;
11060
11061             GST_DEBUG_OBJECT (qtdemux, "found jpeg");
11062
11063             /* recover information on interlaced/progressive */
11064             jpeg = qtdemux_tree_get_child_by_type (stsd, FOURCC_jpeg);
11065             if (!jpeg)
11066               break;
11067
11068             len = QT_UINT32 (jpeg->data);
11069             GST_DEBUG_OBJECT (qtdemux, "Found jpeg: len %u, need %d", len,
11070                 min_size);
11071             if (len >= min_size) {
11072               gst_byte_reader_init (&br, jpeg->data, len);
11073
11074               gst_byte_reader_skip (&br, compressor_offset + 32 + 2);
11075               gst_byte_reader_get_uint16_le (&br, &color_table_id);
11076               if (color_table_id != 0) {
11077                 /* the spec says there can be concatenated chunks in the data, and we want
11078                  * to find one called field. Walk through them. */
11079                 gint offset = min_size;
11080                 while (offset + 8 < len) {
11081                   guint32 size = 0, tag;
11082                   ok = gst_byte_reader_get_uint32_le (&br, &size);
11083                   ok &= gst_byte_reader_get_uint32_le (&br, &tag);
11084                   if (!ok || size < 8) {
11085                     GST_WARNING_OBJECT (qtdemux,
11086                         "Failed to walk optional chunk list");
11087                     break;
11088                   }
11089                   GST_DEBUG_OBJECT (qtdemux,
11090                       "Found optional %4.4s chunk, size %u",
11091                       (const char *) &tag, size);
11092                   if (tag == FOURCC_fiel) {
11093                     guint8 n_fields = 0, ordering = 0;
11094                     gst_byte_reader_get_uint8 (&br, &n_fields);
11095                     gst_byte_reader_get_uint8 (&br, &ordering);
11096                     if (n_fields == 1 || n_fields == 2) {
11097                       GST_DEBUG_OBJECT (qtdemux,
11098                           "Found fiel tag with %u fields, ordering %u",
11099                           n_fields, ordering);
11100                       if (n_fields == 2)
11101                         gst_caps_set_simple (CUR_STREAM (stream)->caps,
11102                             "interlace-mode", G_TYPE_STRING, "interleaved",
11103                             NULL);
11104                     } else {
11105                       GST_WARNING_OBJECT (qtdemux,
11106                           "Found fiel tag with invalid fields (%u)", n_fields);
11107                     }
11108                   }
11109                   offset += size;
11110                 }
11111               } else {
11112                 GST_DEBUG_OBJECT (qtdemux,
11113                     "Color table ID is 0, not trying to get interlacedness");
11114               }
11115             } else {
11116               GST_WARNING_OBJECT (qtdemux,
11117                   "Length of jpeg chunk is too small, not trying to get interlacedness");
11118             }
11119
11120             break;
11121           }
11122           case FOURCC_rle_:
11123           case FOURCC_WRLE:
11124           {
11125             gst_caps_set_simple (entry->caps,
11126                 "depth", G_TYPE_INT, QT_UINT16 (stsd_entry_data + offset + 66),
11127                 NULL);
11128             break;
11129           }
11130           case FOURCC_XiTh:
11131           {
11132             GNode *xith, *xdxt;
11133
11134             GST_DEBUG_OBJECT (qtdemux, "found XiTh");
11135             xith = qtdemux_tree_get_child_by_index (stsd, stsd_index);
11136             if (!xith)
11137               break;
11138
11139             xdxt = qtdemux_tree_get_child_by_type (xith, FOURCC_XdxT);
11140             if (!xdxt)
11141               break;
11142
11143             GST_DEBUG_OBJECT (qtdemux, "found XdxT node");
11144             /* collect the headers and store them in a stream list so that we can
11145              * send them out first */
11146             qtdemux_parse_theora_extension (qtdemux, stream, xdxt);
11147             break;
11148           }
11149           case FOURCC_ovc1:
11150           {
11151             GNode *ovc1;
11152             guint8 *ovc1_data;
11153             guint ovc1_len;
11154             GstBuffer *buf;
11155
11156             GST_DEBUG_OBJECT (qtdemux, "parse ovc1 header");
11157             ovc1 = qtdemux_tree_get_child_by_index (stsd, stsd_index);
11158             if (!ovc1)
11159               break;
11160             ovc1_data = ovc1->data;
11161             ovc1_len = QT_UINT32 (ovc1_data);
11162             if (ovc1_len <= 198) {
11163               GST_WARNING_OBJECT (qtdemux, "Too small ovc1 header, skipping");
11164               break;
11165             }
11166             buf = gst_buffer_new_and_alloc (ovc1_len - 198);
11167             gst_buffer_fill (buf, 0, ovc1_data + 198, ovc1_len - 198);
11168             gst_caps_set_simple (entry->caps,
11169                 "codec_data", GST_TYPE_BUFFER, buf, NULL);
11170             gst_buffer_unref (buf);
11171             break;
11172           }
11173           case FOURCC_vc_1:
11174           {
11175             gint len = QT_UINT32 (stsd_entry_data) - 0x56;
11176             const guint8 *vc1_data = stsd_entry_data + 0x56;
11177
11178             /* find dvc1 */
11179             while (len >= 8) {
11180               gint size;
11181
11182               if (QT_UINT32 (vc1_data) <= len)
11183                 size = QT_UINT32 (vc1_data) - 8;
11184               else
11185                 size = len - 8;
11186
11187               if (size < 1)
11188                 /* No real data, so break out */
11189                 break;
11190
11191               switch (QT_FOURCC (vc1_data + 0x4)) {
11192                 case GST_MAKE_FOURCC ('d', 'v', 'c', '1'):
11193                 {
11194                   GstBuffer *buf;
11195
11196                   GST_DEBUG_OBJECT (qtdemux, "found dvc1 codec_data in stsd");
11197                   buf = gst_buffer_new_and_alloc (size);
11198                   gst_buffer_fill (buf, 0, vc1_data + 8, size);
11199                   gst_caps_set_simple (entry->caps,
11200                       "codec_data", GST_TYPE_BUFFER, buf, NULL);
11201                   gst_buffer_unref (buf);
11202                   break;
11203                 }
11204                 default:
11205                   break;
11206               }
11207               len -= size + 8;
11208               vc1_data += size + 8;
11209             }
11210             break;
11211           }
11212           default:
11213             break;
11214         }
11215       }
11216
11217       GST_INFO_OBJECT (qtdemux,
11218           "type %" GST_FOURCC_FORMAT " caps %" GST_PTR_FORMAT,
11219           GST_FOURCC_ARGS (fourcc), entry->caps);
11220
11221     } else if (stream->subtype == FOURCC_soun) {
11222       GNode *wave;
11223       int version, samplesize;
11224       guint16 compression_id;
11225       gboolean amrwb = FALSE;
11226
11227       offset = 16;
11228       /* sample description entry (16) + sound sample description v0 (20) */
11229       if (len < 36)
11230         goto corrupt_file;
11231
11232       version = QT_UINT32 (stsd_entry_data + offset);
11233       entry->n_channels = QT_UINT16 (stsd_entry_data + offset + 8);
11234       samplesize = QT_UINT16 (stsd_entry_data + offset + 10);
11235       compression_id = QT_UINT16 (stsd_entry_data + offset + 12);
11236       entry->rate = QT_FP32 (stsd_entry_data + offset + 16);
11237
11238       GST_LOG_OBJECT (qtdemux, "version/rev:      %08x", version);
11239       GST_LOG_OBJECT (qtdemux, "vendor:           %08x",
11240           QT_UINT32 (stsd_entry_data + offset + 4));
11241       GST_LOG_OBJECT (qtdemux, "n_channels:       %d", entry->n_channels);
11242       GST_LOG_OBJECT (qtdemux, "sample_size:      %d", samplesize);
11243       GST_LOG_OBJECT (qtdemux, "compression_id:   %d", compression_id);
11244       GST_LOG_OBJECT (qtdemux, "packet size:      %d",
11245           QT_UINT16 (stsd_entry_data + offset + 14));
11246       GST_LOG_OBJECT (qtdemux, "sample rate:      %g", entry->rate);
11247
11248       if (compression_id == 0xfffe)
11249         entry->sampled = TRUE;
11250
11251       /* first assume uncompressed audio */
11252       entry->bytes_per_sample = samplesize / 8;
11253       entry->samples_per_frame = entry->n_channels;
11254       entry->bytes_per_frame = entry->n_channels * entry->bytes_per_sample;
11255       entry->samples_per_packet = entry->samples_per_frame;
11256       entry->bytes_per_packet = entry->bytes_per_sample;
11257
11258       offset = 36;
11259       switch (fourcc) {
11260           /* Yes, these have to be hard-coded */
11261         case FOURCC_MAC6:
11262         {
11263           entry->samples_per_packet = 6;
11264           entry->bytes_per_packet = 1;
11265           entry->bytes_per_frame = 1 * entry->n_channels;
11266           entry->bytes_per_sample = 1;
11267           entry->samples_per_frame = 6 * entry->n_channels;
11268           break;
11269         }
11270         case FOURCC_MAC3:
11271         {
11272           entry->samples_per_packet = 3;
11273           entry->bytes_per_packet = 1;
11274           entry->bytes_per_frame = 1 * entry->n_channels;
11275           entry->bytes_per_sample = 1;
11276           entry->samples_per_frame = 3 * entry->n_channels;
11277           break;
11278         }
11279         case FOURCC_ima4:
11280         {
11281           entry->samples_per_packet = 64;
11282           entry->bytes_per_packet = 34;
11283           entry->bytes_per_frame = 34 * entry->n_channels;
11284           entry->bytes_per_sample = 2;
11285           entry->samples_per_frame = 64 * entry->n_channels;
11286           break;
11287         }
11288         case FOURCC_ulaw:
11289         case FOURCC_alaw:
11290         {
11291           entry->samples_per_packet = 1;
11292           entry->bytes_per_packet = 1;
11293           entry->bytes_per_frame = 1 * entry->n_channels;
11294           entry->bytes_per_sample = 1;
11295           entry->samples_per_frame = 1 * entry->n_channels;
11296           break;
11297         }
11298         case FOURCC_agsm:
11299         {
11300           entry->samples_per_packet = 160;
11301           entry->bytes_per_packet = 33;
11302           entry->bytes_per_frame = 33 * entry->n_channels;
11303           entry->bytes_per_sample = 2;
11304           entry->samples_per_frame = 160 * entry->n_channels;
11305           break;
11306         }
11307         default:
11308           break;
11309       }
11310
11311       if (version == 0x00010000) {
11312         /* sample description entry (16) + sound sample description v1 (20+16) */
11313         if (len < 52)
11314           goto corrupt_file;
11315
11316         switch (fourcc) {
11317           case FOURCC_twos:
11318           case FOURCC_sowt:
11319           case FOURCC_raw_:
11320           case FOURCC_lpcm:
11321             break;
11322           default:
11323           {
11324             /* only parse extra decoding config for non-pcm audio */
11325             entry->samples_per_packet = QT_UINT32 (stsd_entry_data + offset);
11326             entry->bytes_per_packet = QT_UINT32 (stsd_entry_data + offset + 4);
11327             entry->bytes_per_frame = QT_UINT32 (stsd_entry_data + offset + 8);
11328             entry->bytes_per_sample = QT_UINT32 (stsd_entry_data + offset + 12);
11329
11330             GST_LOG_OBJECT (qtdemux, "samples/packet:   %d",
11331                 entry->samples_per_packet);
11332             GST_LOG_OBJECT (qtdemux, "bytes/packet:     %d",
11333                 entry->bytes_per_packet);
11334             GST_LOG_OBJECT (qtdemux, "bytes/frame:      %d",
11335                 entry->bytes_per_frame);
11336             GST_LOG_OBJECT (qtdemux, "bytes/sample:     %d",
11337                 entry->bytes_per_sample);
11338
11339             if (!entry->sampled && entry->bytes_per_packet) {
11340               entry->samples_per_frame = (entry->bytes_per_frame /
11341                   entry->bytes_per_packet) * entry->samples_per_packet;
11342               GST_LOG_OBJECT (qtdemux, "samples/frame:    %d",
11343                   entry->samples_per_frame);
11344             }
11345             break;
11346           }
11347         }
11348       } else if (version == 0x00020000) {
11349         union
11350         {
11351           gdouble fp;
11352           guint64 val;
11353         } qtfp;
11354
11355         /* sample description entry (16) + sound sample description v2 (56) */
11356         if (len < 72)
11357           goto corrupt_file;
11358
11359         qtfp.val = QT_UINT64 (stsd_entry_data + offset + 4);
11360         entry->rate = qtfp.fp;
11361         entry->n_channels = QT_UINT32 (stsd_entry_data + offset + 12);
11362
11363         GST_LOG_OBJECT (qtdemux, "Sound sample description Version 2");
11364         GST_LOG_OBJECT (qtdemux, "sample rate:        %g", entry->rate);
11365         GST_LOG_OBJECT (qtdemux, "n_channels:         %d", entry->n_channels);
11366         GST_LOG_OBJECT (qtdemux, "bits/channel:       %d",
11367             QT_UINT32 (stsd_entry_data + offset + 20));
11368         GST_LOG_OBJECT (qtdemux, "format flags:       %X",
11369             QT_UINT32 (stsd_entry_data + offset + 24));
11370         GST_LOG_OBJECT (qtdemux, "bytes/packet:       %d",
11371             QT_UINT32 (stsd_entry_data + offset + 28));
11372         GST_LOG_OBJECT (qtdemux, "LPCM frames/packet: %d",
11373             QT_UINT32 (stsd_entry_data + offset + 32));
11374       } else if (version != 0x00000) {
11375         GST_WARNING_OBJECT (qtdemux, "unknown audio STSD version %08x",
11376             version);
11377       }
11378
11379       if (entry->caps)
11380         gst_caps_unref (entry->caps);
11381
11382       entry->caps = qtdemux_audio_caps (qtdemux, stream, entry, fourcc,
11383           stsd_entry_data + 32, len - 16, &codec);
11384
11385       switch (fourcc) {
11386         case FOURCC_in24:
11387         {
11388           GNode *enda;
11389           GNode *in24;
11390
11391           in24 = qtdemux_tree_get_child_by_type (stsd, FOURCC_in24);
11392
11393           enda = qtdemux_tree_get_child_by_type (in24, FOURCC_enda);
11394           if (!enda) {
11395             wave = qtdemux_tree_get_child_by_type (in24, FOURCC_wave);
11396             if (wave)
11397               enda = qtdemux_tree_get_child_by_type (wave, FOURCC_enda);
11398           }
11399           if (enda) {
11400             int enda_value = QT_UINT16 ((guint8 *) enda->data + 8);
11401             gst_caps_set_simple (entry->caps,
11402                 "format", G_TYPE_STRING, (enda_value) ? "S24LE" : "S24BE",
11403                 NULL);
11404           }
11405           break;
11406         }
11407         case FOURCC_owma:
11408         {
11409           const guint8 *owma_data;
11410           const gchar *codec_name = NULL;
11411           guint owma_len;
11412           GstBuffer *buf;
11413           gint version = 1;
11414           /* from http://msdn.microsoft.com/en-us/library/dd757720(VS.85).aspx */
11415           /* FIXME this should also be gst_riff_strf_auds,
11416            * but the latter one is actually missing bits-per-sample :( */
11417           typedef struct
11418           {
11419             gint16 wFormatTag;
11420             gint16 nChannels;
11421             gint32 nSamplesPerSec;
11422             gint32 nAvgBytesPerSec;
11423             gint16 nBlockAlign;
11424             gint16 wBitsPerSample;
11425             gint16 cbSize;
11426           } WAVEFORMATEX;
11427           WAVEFORMATEX *wfex;
11428
11429           GST_DEBUG_OBJECT (qtdemux, "parse owma");
11430           owma_data = stsd_entry_data;
11431           owma_len = QT_UINT32 (owma_data);
11432           if (owma_len <= 54) {
11433             GST_WARNING_OBJECT (qtdemux, "Too small owma header, skipping");
11434             break;
11435           }
11436           wfex = (WAVEFORMATEX *) (owma_data + 36);
11437           buf = gst_buffer_new_and_alloc (owma_len - 54);
11438           gst_buffer_fill (buf, 0, owma_data + 54, owma_len - 54);
11439           if (wfex->wFormatTag == 0x0161) {
11440             codec_name = "Windows Media Audio";
11441             version = 2;
11442           } else if (wfex->wFormatTag == 0x0162) {
11443             codec_name = "Windows Media Audio 9 Pro";
11444             version = 3;
11445           } else if (wfex->wFormatTag == 0x0163) {
11446             codec_name = "Windows Media Audio 9 Lossless";
11447             /* is that correct? gstffmpegcodecmap.c is missing it, but
11448              * fluendo codec seems to support it */
11449             version = 4;
11450           }
11451
11452           gst_caps_set_simple (entry->caps,
11453               "codec_data", GST_TYPE_BUFFER, buf,
11454               "wmaversion", G_TYPE_INT, version,
11455               "block_align", G_TYPE_INT,
11456               GST_READ_UINT16_LE (&wfex->nBlockAlign), "bitrate", G_TYPE_INT,
11457               GST_READ_UINT32_LE (&wfex->nAvgBytesPerSec), "width", G_TYPE_INT,
11458               GST_READ_UINT16_LE (&wfex->wBitsPerSample), "depth", G_TYPE_INT,
11459               GST_READ_UINT16_LE (&wfex->wBitsPerSample), NULL);
11460           gst_buffer_unref (buf);
11461
11462           if (codec_name) {
11463             g_free (codec);
11464             codec = g_strdup (codec_name);
11465           }
11466           break;
11467         }
11468         case FOURCC_wma_:
11469         {
11470           gint len = QT_UINT32 (stsd_entry_data) - offset;
11471           const guint8 *wfex_data = stsd_entry_data + offset;
11472           const gchar *codec_name = NULL;
11473           gint version = 1;
11474           /* from http://msdn.microsoft.com/en-us/library/dd757720(VS.85).aspx */
11475           /* FIXME this should also be gst_riff_strf_auds,
11476            * but the latter one is actually missing bits-per-sample :( */
11477           typedef struct
11478           {
11479             gint16 wFormatTag;
11480             gint16 nChannels;
11481             gint32 nSamplesPerSec;
11482             gint32 nAvgBytesPerSec;
11483             gint16 nBlockAlign;
11484             gint16 wBitsPerSample;
11485             gint16 cbSize;
11486           } WAVEFORMATEX;
11487           WAVEFORMATEX wfex;
11488
11489           /* FIXME: unify with similar wavformatex parsing code above */
11490           GST_DEBUG_OBJECT (qtdemux, "parse wma, looking for wfex");
11491
11492           /* find wfex */
11493           while (len >= 8) {
11494             gint size;
11495
11496             if (QT_UINT32 (wfex_data) <= len)
11497               size = QT_UINT32 (wfex_data) - 8;
11498             else
11499               size = len - 8;
11500
11501             if (size < 1)
11502               /* No real data, so break out */
11503               break;
11504
11505             switch (QT_FOURCC (wfex_data + 4)) {
11506               case GST_MAKE_FOURCC ('w', 'f', 'e', 'x'):
11507               {
11508                 GST_DEBUG_OBJECT (qtdemux, "found wfex in stsd");
11509
11510                 if (size < 8 + 18)
11511                   break;
11512
11513                 wfex.wFormatTag = GST_READ_UINT16_LE (wfex_data + 8 + 0);
11514                 wfex.nChannels = GST_READ_UINT16_LE (wfex_data + 8 + 2);
11515                 wfex.nSamplesPerSec = GST_READ_UINT32_LE (wfex_data + 8 + 4);
11516                 wfex.nAvgBytesPerSec = GST_READ_UINT32_LE (wfex_data + 8 + 8);
11517                 wfex.nBlockAlign = GST_READ_UINT16_LE (wfex_data + 8 + 12);
11518                 wfex.wBitsPerSample = GST_READ_UINT16_LE (wfex_data + 8 + 14);
11519                 wfex.cbSize = GST_READ_UINT16_LE (wfex_data + 8 + 16);
11520
11521                 GST_LOG_OBJECT (qtdemux, "Found wfex box in stsd:");
11522                 GST_LOG_OBJECT (qtdemux, "FormatTag = 0x%04x, Channels = %u, "
11523                     "SamplesPerSec = %u, AvgBytesPerSec = %u, BlockAlign = %u, "
11524                     "BitsPerSample = %u, Size = %u", wfex.wFormatTag,
11525                     wfex.nChannels, wfex.nSamplesPerSec, wfex.nAvgBytesPerSec,
11526                     wfex.nBlockAlign, wfex.wBitsPerSample, wfex.cbSize);
11527
11528                 if (wfex.wFormatTag == 0x0161) {
11529                   codec_name = "Windows Media Audio";
11530                   version = 2;
11531                 } else if (wfex.wFormatTag == 0x0162) {
11532                   codec_name = "Windows Media Audio 9 Pro";
11533                   version = 3;
11534                 } else if (wfex.wFormatTag == 0x0163) {
11535                   codec_name = "Windows Media Audio 9 Lossless";
11536                   /* is that correct? gstffmpegcodecmap.c is missing it, but
11537                    * fluendo codec seems to support it */
11538                   version = 4;
11539                 }
11540
11541                 gst_caps_set_simple (entry->caps,
11542                     "wmaversion", G_TYPE_INT, version,
11543                     "block_align", G_TYPE_INT, wfex.nBlockAlign,
11544                     "bitrate", G_TYPE_INT, wfex.nAvgBytesPerSec,
11545                     "width", G_TYPE_INT, wfex.wBitsPerSample,
11546                     "depth", G_TYPE_INT, wfex.wBitsPerSample, NULL);
11547
11548                 if (size > wfex.cbSize) {
11549                   GstBuffer *buf;
11550
11551                   buf = gst_buffer_new_and_alloc (size - wfex.cbSize);
11552                   gst_buffer_fill (buf, 0, wfex_data + 8 + wfex.cbSize,
11553                       size - wfex.cbSize);
11554                   gst_caps_set_simple (entry->caps,
11555                       "codec_data", GST_TYPE_BUFFER, buf, NULL);
11556                   gst_buffer_unref (buf);
11557                 } else {
11558                   GST_WARNING_OBJECT (qtdemux, "no codec data");
11559                 }
11560
11561                 if (codec_name) {
11562                   g_free (codec);
11563                   codec = g_strdup (codec_name);
11564                 }
11565                 break;
11566               }
11567               default:
11568                 break;
11569             }
11570             len -= size + 8;
11571             wfex_data += size + 8;
11572           }
11573           break;
11574         }
11575         case FOURCC_opus:
11576         {
11577           const guint8 *opus_data;
11578           guint8 *channel_mapping = NULL;
11579           guint32 rate;
11580           guint8 channels;
11581           guint8 channel_mapping_family;
11582           guint8 stream_count;
11583           guint8 coupled_count;
11584           guint8 i;
11585
11586           opus_data = stsd_entry_data;
11587
11588           channels = GST_READ_UINT8 (opus_data + 45);
11589           rate = GST_READ_UINT32_LE (opus_data + 48);
11590           channel_mapping_family = GST_READ_UINT8 (opus_data + 54);
11591           stream_count = GST_READ_UINT8 (opus_data + 55);
11592           coupled_count = GST_READ_UINT8 (opus_data + 56);
11593
11594           if (channels > 0) {
11595             channel_mapping = g_malloc (channels * sizeof (guint8));
11596             for (i = 0; i < channels; i++)
11597               channel_mapping[i] = GST_READ_UINT8 (opus_data + i + 57);
11598           }
11599
11600           entry->caps = gst_codec_utils_opus_create_caps (rate, channels,
11601               channel_mapping_family, stream_count, coupled_count,
11602               channel_mapping);
11603           break;
11604         }
11605         default:
11606           break;
11607       }
11608
11609       if (codec) {
11610         GstStructure *s;
11611         gint bitrate = 0;
11612
11613         gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
11614             GST_TAG_AUDIO_CODEC, codec, NULL);
11615         g_free (codec);
11616         codec = NULL;
11617
11618         /* some bitrate info may have ended up in caps */
11619         s = gst_caps_get_structure (entry->caps, 0);
11620         gst_structure_get_int (s, "bitrate", &bitrate);
11621         if (bitrate > 0)
11622           gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
11623               GST_TAG_BITRATE, bitrate, NULL);
11624       }
11625
11626       mp4a = qtdemux_tree_get_child_by_index (stsd, stsd_index);
11627       if (!stream->protected) {
11628       } else {
11629         if (QTDEMUX_TREE_NODE_FOURCC (mp4v) != FOURCC_encv) {
11630           mp4v = NULL;
11631         }
11632       }
11633       if (stream->protected && fourcc == FOURCC_mp4a) {
11634         if (QTDEMUX_TREE_NODE_FOURCC (mp4a) != FOURCC_enca) {
11635           mp4a = NULL;
11636         }
11637       } else {
11638         if (QTDEMUX_TREE_NODE_FOURCC (mp4a) != FOURCC_mp4a) {
11639           mp4a = NULL;
11640         }
11641       }
11642
11643       wave = NULL;
11644       esds = NULL;
11645       if (mp4a) {
11646         wave = qtdemux_tree_get_child_by_type (mp4a, FOURCC_wave);
11647         if (wave)
11648           esds = qtdemux_tree_get_child_by_type (wave, FOURCC_esds);
11649         if (!esds)
11650           esds = qtdemux_tree_get_child_by_type (mp4a, FOURCC_esds);
11651       }
11652
11653
11654       /* If the fourcc's bottom 16 bits gives 'sm', then the top
11655          16 bits is a byte-swapped wave-style codec identifier,
11656          and we can find a WAVE header internally to a 'wave' atom here.
11657          This can more clearly be thought of as 'ms' as the top 16 bits, and a
11658          codec id as the bottom 16 bits - but byte-swapped to store in QT (which
11659          is big-endian).
11660        */
11661       if ((fourcc & 0xffff) == (('s' << 8) | 'm')) {
11662         if (len < offset + 20) {
11663           GST_WARNING_OBJECT (qtdemux, "No wave atom in MS-style audio");
11664         } else {
11665           guint32 datalen = QT_UINT32 (stsd_entry_data + offset + 16);
11666           const guint8 *data = stsd_entry_data + offset + 16;
11667           GNode *wavenode;
11668           GNode *waveheadernode;
11669
11670           wavenode = g_node_new ((guint8 *) data);
11671           if (qtdemux_parse_node (qtdemux, wavenode, data, datalen)) {
11672             const guint8 *waveheader;
11673             guint32 headerlen;
11674
11675             waveheadernode = qtdemux_tree_get_child_by_type (wavenode, fourcc);
11676             if (waveheadernode) {
11677               waveheader = (const guint8 *) waveheadernode->data;
11678               headerlen = QT_UINT32 (waveheader);
11679
11680               if (headerlen > 8) {
11681                 gst_riff_strf_auds *header = NULL;
11682                 GstBuffer *headerbuf;
11683                 GstBuffer *extra;
11684
11685                 waveheader += 8;
11686                 headerlen -= 8;
11687
11688                 headerbuf = gst_buffer_new_and_alloc (headerlen);
11689                 gst_buffer_fill (headerbuf, 0, waveheader, headerlen);
11690
11691                 if (gst_riff_parse_strf_auds (GST_ELEMENT_CAST (qtdemux),
11692                         headerbuf, &header, &extra)) {
11693                   gst_caps_unref (entry->caps);
11694                   /* FIXME: Need to do something with the channel reorder map */
11695                   entry->caps =
11696                       gst_riff_create_audio_caps (header->format, NULL, header,
11697                       extra, NULL, NULL, NULL);
11698
11699                   if (extra)
11700                     gst_buffer_unref (extra);
11701                   g_free (header);
11702                 }
11703               }
11704             } else
11705               GST_DEBUG ("Didn't find waveheadernode for this codec");
11706           }
11707           g_node_destroy (wavenode);
11708         }
11709       } else if (esds) {
11710         gst_qtdemux_handle_esds (qtdemux, stream, entry, esds,
11711             stream->stream_tags);
11712       } else {
11713         switch (fourcc) {
11714 #if 0
11715             /* FIXME: what is in the chunk? */
11716           case FOURCC_QDMC:
11717           {
11718             gint len = QT_UINT32 (stsd_data);
11719
11720             /* seems to be always = 116 = 0x74 */
11721             break;
11722           }
11723 #endif
11724           case FOURCC_QDM2:
11725           {
11726             gint len = QT_UINT32 (stsd_entry_data);
11727
11728             if (len > 0x3C) {
11729               GstBuffer *buf = gst_buffer_new_and_alloc (len - 0x3C);
11730
11731               gst_buffer_fill (buf, 0, stsd_entry_data + 0x3C, len - 0x3C);
11732               gst_caps_set_simple (entry->caps,
11733                   "codec_data", GST_TYPE_BUFFER, buf, NULL);
11734               gst_buffer_unref (buf);
11735             }
11736             gst_caps_set_simple (entry->caps,
11737                 "samplesize", G_TYPE_INT, samplesize, NULL);
11738             break;
11739           }
11740           case FOURCC_alac:
11741           {
11742             GNode *alac, *wave = NULL;
11743
11744             /* apparently, m4a has this atom appended directly in the stsd entry,
11745              * while mov has it in a wave atom */
11746             alac = qtdemux_tree_get_child_by_type (stsd, FOURCC_alac);
11747             if (alac) {
11748               /* alac now refers to stsd entry atom */
11749               wave = qtdemux_tree_get_child_by_type (alac, FOURCC_wave);
11750               if (wave)
11751                 alac = qtdemux_tree_get_child_by_type (wave, FOURCC_alac);
11752               else
11753                 alac = qtdemux_tree_get_child_by_type (alac, FOURCC_alac);
11754             }
11755             if (alac) {
11756               const guint8 *alac_data = alac->data;
11757               gint len = QT_UINT32 (alac->data);
11758               GstBuffer *buf;
11759
11760               if (len < 36) {
11761                 GST_DEBUG_OBJECT (qtdemux,
11762                     "discarding alac atom with unexpected len %d", len);
11763               } else {
11764                 /* codec-data contains alac atom size and prefix,
11765                  * ffmpeg likes it that way, not quite gst-ish though ...*/
11766                 buf = gst_buffer_new_and_alloc (len);
11767                 gst_buffer_fill (buf, 0, alac->data, len);
11768                 gst_caps_set_simple (entry->caps,
11769                     "codec_data", GST_TYPE_BUFFER, buf, NULL);
11770                 gst_buffer_unref (buf);
11771
11772                 entry->bytes_per_frame = QT_UINT32 (alac_data + 12);
11773                 entry->n_channels = QT_UINT8 (alac_data + 21);
11774                 entry->rate = QT_UINT32 (alac_data + 32);
11775               }
11776             }
11777             gst_caps_set_simple (entry->caps,
11778                 "samplesize", G_TYPE_INT, samplesize, NULL);
11779             break;
11780           }
11781           case FOURCC_fLaC:
11782           {
11783             /* The codingname of the sample entry is 'fLaC' */
11784             GNode *flac = qtdemux_tree_get_child_by_type (stsd, FOURCC_fLaC);
11785
11786             if (flac) {
11787               /* The 'dfLa' box is added to the sample entry to convey
11788                  initializing information for the decoder. */
11789               const GNode *dfla =
11790                   qtdemux_tree_get_child_by_type (flac, FOURCC_dfLa);
11791
11792               if (dfla) {
11793                 const guint32 len = QT_UINT32 (dfla->data);
11794
11795                 /* Must contain at least dfLa box header (12),
11796                  * METADATA_BLOCK_HEADER (4), METADATA_BLOCK_STREAMINFO (34) */
11797                 if (len < 50) {
11798                   GST_DEBUG_OBJECT (qtdemux,
11799                       "discarding dfla atom with unexpected len %d", len);
11800                 } else {
11801                   /* skip dfLa header to get the METADATA_BLOCKs */
11802                   const guint8 *metadata_blocks = (guint8 *) dfla->data + 12;
11803                   const guint32 metadata_blocks_len = len - 12;
11804
11805                   gchar *stream_marker = g_strdup ("fLaC");
11806                   GstBuffer *block = gst_buffer_new_wrapped (stream_marker,
11807                       strlen (stream_marker));
11808
11809                   guint32 index = 0;
11810                   guint32 remainder = 0;
11811                   guint32 block_size = 0;
11812                   gboolean is_last = FALSE;
11813
11814                   GValue array = G_VALUE_INIT;
11815                   GValue value = G_VALUE_INIT;
11816
11817                   g_value_init (&array, GST_TYPE_ARRAY);
11818                   g_value_init (&value, GST_TYPE_BUFFER);
11819
11820                   gst_value_set_buffer (&value, block);
11821                   gst_value_array_append_value (&array, &value);
11822                   g_value_reset (&value);
11823
11824                   gst_buffer_unref (block);
11825
11826                   /* check there's at least one METADATA_BLOCK_HEADER's worth
11827                    * of data, and we haven't already finished parsing */
11828                   while (!is_last && ((index + 3) < metadata_blocks_len)) {
11829                     remainder = metadata_blocks_len - index;
11830
11831                     /* add the METADATA_BLOCK_HEADER size to the signalled size */
11832                     block_size = 4 +
11833                         (metadata_blocks[index + 1] << 16) +
11834                         (metadata_blocks[index + 2] << 8) +
11835                         metadata_blocks[index + 3];
11836
11837                     /* be careful not to read off end of box */
11838                     if (block_size > remainder) {
11839                       break;
11840                     }
11841
11842                     is_last = metadata_blocks[index] >> 7;
11843
11844                     block = gst_buffer_new_and_alloc (block_size);
11845
11846                     gst_buffer_fill (block, 0, &metadata_blocks[index],
11847                         block_size);
11848
11849                     gst_value_set_buffer (&value, block);
11850                     gst_value_array_append_value (&array, &value);
11851                     g_value_reset (&value);
11852
11853                     gst_buffer_unref (block);
11854
11855                     index += block_size;
11856                   }
11857
11858                   /* only append the metadata if we successfully read all of it */
11859                   if (is_last) {
11860                     gst_structure_set_value (gst_caps_get_structure (CUR_STREAM
11861                             (stream)->caps, 0), "streamheader", &array);
11862                   } else {
11863                     GST_WARNING_OBJECT (qtdemux,
11864                         "discarding all METADATA_BLOCKs due to invalid "
11865                         "block_size %d at idx %d, rem %d", block_size, index,
11866                         remainder);
11867                   }
11868
11869                   g_value_unset (&value);
11870                   g_value_unset (&array);
11871
11872                   /* The sample rate obtained from the stsd may not be accurate
11873                    * since it cannot represent rates greater than 65535Hz, so
11874                    * override that value with the sample rate from the
11875                    * METADATA_BLOCK_STREAMINFO block */
11876                   CUR_STREAM (stream)->rate =
11877                       (QT_UINT32 (metadata_blocks + 14) >> 12) & 0xFFFFF;
11878                 }
11879               }
11880             }
11881             break;
11882           }
11883           case FOURCC_sawb:
11884             /* Fallthrough! */
11885             amrwb = TRUE;
11886           case FOURCC_samr:
11887           {
11888             gint len = QT_UINT32 (stsd_entry_data);
11889
11890             if (len > 0x24) {
11891               GstBuffer *buf = gst_buffer_new_and_alloc (len - 0x24);
11892               guint bitrate;
11893
11894               gst_buffer_fill (buf, 0, stsd_entry_data + 0x24, len - 0x24);
11895
11896               /* If we have enough data, let's try to get the 'damr' atom. See
11897                * the 3GPP container spec (26.244) for more details. */
11898               if ((len - 0x34) > 8 &&
11899                   (bitrate = qtdemux_parse_amr_bitrate (buf, amrwb))) {
11900                 gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
11901                     GST_TAG_MAXIMUM_BITRATE, bitrate, NULL);
11902               }
11903
11904               gst_caps_set_simple (entry->caps,
11905                   "codec_data", GST_TYPE_BUFFER, buf, NULL);
11906               gst_buffer_unref (buf);
11907             }
11908             break;
11909           }
11910           case FOURCC_mp4a:
11911           {
11912             /* mp4a atom withtout ESDS; Attempt to build codec data from atom */
11913             gint len = QT_UINT32 (stsd_entry_data);
11914
11915             if (len >= 34) {
11916               guint16 sound_version = QT_UINT16 (stsd_entry_data + 16);
11917
11918               if (sound_version == 1) {
11919                 guint16 channels = QT_UINT16 (stsd_entry_data + 24);
11920                 guint32 time_scale = QT_UINT32 (stsd_entry_data + 30);
11921                 guint8 codec_data[2];
11922                 GstBuffer *buf;
11923                 gint profile = 2;       /* FIXME: Can this be determined somehow? There doesn't seem to be anything in mp4a atom that specifis compression */
11924
11925                 gint sample_rate_index =
11926                     gst_codec_utils_aac_get_index_from_sample_rate (time_scale);
11927
11928                 /* build AAC codec data */
11929                 codec_data[0] = profile << 3;
11930                 codec_data[0] |= ((sample_rate_index >> 1) & 0x7);
11931                 codec_data[1] = (sample_rate_index & 0x01) << 7;
11932                 codec_data[1] |= (channels & 0xF) << 3;
11933
11934                 buf = gst_buffer_new_and_alloc (2);
11935                 gst_buffer_fill (buf, 0, codec_data, 2);
11936                 gst_caps_set_simple (entry->caps,
11937                     "codec_data", GST_TYPE_BUFFER, buf, NULL);
11938                 gst_buffer_unref (buf);
11939               }
11940             }
11941             break;
11942           }
11943           case FOURCC_lpcm:
11944             /* Fully handled elsewhere */
11945             break;
11946           default:
11947             GST_INFO_OBJECT (qtdemux,
11948                 "unhandled type %" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (fourcc));
11949             break;
11950         }
11951       }
11952       GST_INFO_OBJECT (qtdemux,
11953           "type %" GST_FOURCC_FORMAT " caps %" GST_PTR_FORMAT,
11954           GST_FOURCC_ARGS (fourcc), entry->caps);
11955
11956     } else if (stream->subtype == FOURCC_strm) {
11957       if (fourcc == FOURCC_rtsp) {
11958         stream->redirect_uri = qtdemux_get_rtsp_uri_from_hndl (qtdemux, minf);
11959       } else {
11960         GST_INFO_OBJECT (qtdemux, "unhandled stream type %" GST_FOURCC_FORMAT,
11961             GST_FOURCC_ARGS (fourcc));
11962         goto unknown_stream;
11963       }
11964       entry->sampled = TRUE;
11965     } else if (stream->subtype == FOURCC_subp || stream->subtype == FOURCC_text
11966         || stream->subtype == FOURCC_sbtl || stream->subtype == FOURCC_subt
11967         || stream->subtype == FOURCC_clcp) {
11968
11969       entry->sampled = TRUE;
11970       entry->sparse = TRUE;
11971
11972       entry->caps =
11973           qtdemux_sub_caps (qtdemux, stream, entry, fourcc, stsd_entry_data,
11974           &codec);
11975       if (codec) {
11976         gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
11977             GST_TAG_SUBTITLE_CODEC, codec, NULL);
11978         g_free (codec);
11979         codec = NULL;
11980       }
11981
11982       /* hunt for sort-of codec data */
11983       switch (fourcc) {
11984         case FOURCC_mp4s:
11985         {
11986           GNode *mp4s = NULL;
11987           GNode *esds = NULL;
11988
11989           /* look for palette in a stsd->mp4s->esds sub-atom */
11990           mp4s = qtdemux_tree_get_child_by_type (stsd, FOURCC_mp4s);
11991           if (mp4s)
11992             esds = qtdemux_tree_get_child_by_type (mp4s, FOURCC_esds);
11993           if (esds == NULL) {
11994             /* Invalid STSD */
11995             GST_LOG_OBJECT (qtdemux, "Skipping invalid stsd: no esds child");
11996             break;
11997           }
11998
11999           gst_qtdemux_handle_esds (qtdemux, stream, entry, esds,
12000               stream->stream_tags);
12001           break;
12002         }
12003         default:
12004           GST_INFO_OBJECT (qtdemux,
12005               "unhandled type %" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (fourcc));
12006           break;
12007       }
12008       GST_INFO_OBJECT (qtdemux,
12009           "type %" GST_FOURCC_FORMAT " caps %" GST_PTR_FORMAT,
12010           GST_FOURCC_ARGS (fourcc), entry->caps);
12011     } else {
12012       /* everything in 1 sample */
12013       entry->sampled = TRUE;
12014
12015       entry->caps =
12016           qtdemux_generic_caps (qtdemux, stream, entry, fourcc, stsd_entry_data,
12017           &codec);
12018
12019       if (entry->caps == NULL)
12020         goto unknown_stream;
12021
12022       if (codec) {
12023         gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
12024             GST_TAG_SUBTITLE_CODEC, codec, NULL);
12025         g_free (codec);
12026         codec = NULL;
12027       }
12028     }
12029
12030     /* promote to sampled format */
12031     if (entry->fourcc == FOURCC_samr) {
12032       /* force mono 8000 Hz for AMR */
12033       entry->sampled = TRUE;
12034       entry->n_channels = 1;
12035       entry->rate = 8000;
12036     } else if (entry->fourcc == FOURCC_sawb) {
12037       /* force mono 16000 Hz for AMR-WB */
12038       entry->sampled = TRUE;
12039       entry->n_channels = 1;
12040       entry->rate = 16000;
12041     } else if (entry->fourcc == FOURCC_mp4a) {
12042       entry->sampled = TRUE;
12043     }
12044
12045
12046     stsd_entry_data += len;
12047     remaining_stsd_len -= len;
12048
12049   }
12050
12051   /* collect sample information */
12052   if (!qtdemux_stbl_init (qtdemux, stream, stbl))
12053     goto samples_failed;
12054
12055   if (qtdemux->fragmented) {
12056     guint64 offset;
12057
12058     /* need all moov samples as basis; probably not many if any at all */
12059     /* prevent moof parsing taking of at this time */
12060     offset = qtdemux->moof_offset;
12061     qtdemux->moof_offset = 0;
12062     if (stream->n_samples &&
12063         !qtdemux_parse_samples (qtdemux, stream, stream->n_samples - 1)) {
12064       qtdemux->moof_offset = offset;
12065       goto samples_failed;
12066     }
12067     qtdemux->moof_offset = 0;
12068     /* movie duration more reliable in this case (e.g. mehd) */
12069     if (qtdemux->segment.duration &&
12070         GST_CLOCK_TIME_IS_VALID (qtdemux->segment.duration))
12071       stream->duration =
12072           GSTTIME_TO_QTSTREAMTIME (stream, qtdemux->segment.duration);
12073   }
12074
12075   /* configure segments */
12076   if (!qtdemux_parse_segments (qtdemux, stream, trak))
12077     goto segments_failed;
12078
12079   /* add some language tag, if useful */
12080   if (stream->lang_id[0] != '\0' && strcmp (stream->lang_id, "unk") &&
12081       strcmp (stream->lang_id, "und")) {
12082     const gchar *lang_code;
12083
12084     /* convert ISO 639-2 code to ISO 639-1 */
12085     lang_code = gst_tag_get_language_code (stream->lang_id);
12086     gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
12087         GST_TAG_LANGUAGE_CODE, (lang_code) ? lang_code : stream->lang_id, NULL);
12088   }
12089
12090   /* Check for UDTA tags */
12091   if ((udta = qtdemux_tree_get_child_by_type (trak, FOURCC_udta))) {
12092     qtdemux_parse_udta (qtdemux, stream->stream_tags, udta);
12093   }
12094
12095   /* Insert and sort new stream in track-id order.
12096    * This will help in comparing old/new streams during stream update check */
12097   qtdemux->active_streams =
12098       g_list_insert_sorted (qtdemux->active_streams, stream,
12099       (GCompareFunc) qtdemux_track_id_compare_func);
12100   qtdemux->n_streams++;
12101   GST_DEBUG_OBJECT (qtdemux, "n_streams is now %d", qtdemux->n_streams);
12102
12103   return TRUE;
12104
12105 /* ERRORS */
12106 corrupt_file:
12107   {
12108     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
12109         (_("This file is corrupt and cannot be played.")), (NULL));
12110     if (stream)
12111       gst_qtdemux_stream_free (stream);
12112     return FALSE;
12113   }
12114 error_encrypted:
12115   {
12116     GST_ELEMENT_ERROR (qtdemux, STREAM, DECRYPT, (NULL), (NULL));
12117     gst_qtdemux_stream_free (stream);
12118     return FALSE;
12119   }
12120 samples_failed:
12121 segments_failed:
12122   {
12123     /* we posted an error already */
12124     /* free stbl sub-atoms */
12125     gst_qtdemux_stbl_free (stream);
12126     gst_qtdemux_stream_free (stream);
12127     return FALSE;
12128   }
12129 existing_stream:
12130   {
12131     GST_INFO_OBJECT (qtdemux, "stream with track id %i already exists",
12132         track_id);
12133     return TRUE;
12134   }
12135 unknown_stream:
12136   {
12137     GST_INFO_OBJECT (qtdemux, "unknown subtype %" GST_FOURCC_FORMAT,
12138         GST_FOURCC_ARGS (stream->subtype));
12139     gst_qtdemux_stream_free (stream);
12140     return TRUE;
12141   }
12142 }
12143
12144 /* If we can estimate the overall bitrate, and don't have information about the
12145  * stream bitrate for exactly one stream, this guesses the stream bitrate as
12146  * the overall bitrate minus the sum of the bitrates of all other streams. This
12147  * should be useful for the common case where we have one audio and one video
12148  * stream and can estimate the bitrate of one, but not the other. */
12149 static void
12150 gst_qtdemux_guess_bitrate (GstQTDemux * qtdemux)
12151 {
12152   QtDemuxStream *stream = NULL;
12153   gint64 size, sys_bitrate, sum_bitrate = 0;
12154   GstClockTime duration;
12155   guint bitrate;
12156   GList *iter;
12157
12158   if (qtdemux->fragmented)
12159     return;
12160
12161   GST_DEBUG_OBJECT (qtdemux, "Looking for streams with unknown bitrate");
12162
12163   if (!gst_pad_peer_query_duration (qtdemux->sinkpad, GST_FORMAT_BYTES, &size)
12164       || size <= 0) {
12165     GST_DEBUG_OBJECT (qtdemux,
12166         "Size in bytes of the stream not known - bailing");
12167     return;
12168   }
12169
12170   /* Subtract the header size */
12171   GST_DEBUG_OBJECT (qtdemux, "Total size %" G_GINT64_FORMAT ", header size %u",
12172       size, qtdemux->header_size);
12173
12174   if (size < qtdemux->header_size)
12175     return;
12176
12177   size = size - qtdemux->header_size;
12178
12179   if (!gst_qtdemux_get_duration (qtdemux, &duration)) {
12180     GST_DEBUG_OBJECT (qtdemux, "Stream duration not known - bailing");
12181     return;
12182   }
12183
12184   for (iter = qtdemux->active_streams; iter; iter = g_list_next (iter)) {
12185     QtDemuxStream *str = QTDEMUX_STREAM (iter->data);
12186     switch (str->subtype) {
12187       case FOURCC_soun:
12188       case FOURCC_vide:
12189         GST_DEBUG_OBJECT (qtdemux, "checking bitrate for %" GST_PTR_FORMAT,
12190             CUR_STREAM (str)->caps);
12191         /* retrieve bitrate, prefer avg then max */
12192         bitrate = 0;
12193         if (str->stream_tags) {
12194           if (gst_tag_list_get_uint (str->stream_tags,
12195                   GST_TAG_MAXIMUM_BITRATE, &bitrate))
12196             GST_DEBUG_OBJECT (qtdemux, "max-bitrate: %u", bitrate);
12197           if (gst_tag_list_get_uint (str->stream_tags,
12198                   GST_TAG_NOMINAL_BITRATE, &bitrate))
12199             GST_DEBUG_OBJECT (qtdemux, "nominal-bitrate: %u", bitrate);
12200           if (gst_tag_list_get_uint (str->stream_tags,
12201                   GST_TAG_BITRATE, &bitrate))
12202             GST_DEBUG_OBJECT (qtdemux, "bitrate: %u", bitrate);
12203         }
12204         if (bitrate)
12205           sum_bitrate += bitrate;
12206         else {
12207           if (stream) {
12208             GST_DEBUG_OBJECT (qtdemux,
12209                 ">1 stream with unknown bitrate - bailing");
12210             return;
12211           } else
12212             stream = str;
12213         }
12214
12215       default:
12216         /* For other subtypes, we assume no significant impact on bitrate */
12217         break;
12218     }
12219   }
12220
12221   if (!stream) {
12222     GST_DEBUG_OBJECT (qtdemux, "All stream bitrates are known");
12223     return;
12224   }
12225
12226   sys_bitrate = gst_util_uint64_scale (size, GST_SECOND * 8, duration);
12227
12228   if (sys_bitrate < sum_bitrate) {
12229     /* This can happen, since sum_bitrate might be derived from maximum
12230      * bitrates and not average bitrates */
12231     GST_DEBUG_OBJECT (qtdemux,
12232         "System bitrate less than sum bitrate - bailing");
12233     return;
12234   }
12235
12236   bitrate = sys_bitrate - sum_bitrate;
12237   GST_DEBUG_OBJECT (qtdemux, "System bitrate = %" G_GINT64_FORMAT
12238       ", Stream bitrate = %u", sys_bitrate, bitrate);
12239
12240   if (!stream->stream_tags)
12241     stream->stream_tags = gst_tag_list_new_empty ();
12242   else
12243     stream->stream_tags = gst_tag_list_make_writable (stream->stream_tags);
12244
12245   gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
12246       GST_TAG_BITRATE, bitrate, NULL);
12247 }
12248
12249 static GstFlowReturn
12250 qtdemux_prepare_streams (GstQTDemux * qtdemux)
12251 {
12252   GstFlowReturn ret = GST_FLOW_OK;
12253   GList *iter, *next;
12254
12255   GST_DEBUG_OBJECT (qtdemux, "prepare streams");
12256
12257   for (iter = qtdemux->active_streams; ret == GST_FLOW_OK && iter; iter = next) {
12258     QtDemuxStream *stream = QTDEMUX_STREAM (iter->data);
12259     guint32 sample_num = 0;
12260
12261     next = iter->next;
12262
12263     GST_DEBUG_OBJECT (qtdemux, "track-id %u, fourcc %" GST_FOURCC_FORMAT,
12264         stream->track_id, GST_FOURCC_ARGS (CUR_STREAM (stream)->fourcc));
12265
12266     if (qtdemux->fragmented) {
12267       /* need all moov samples first */
12268       GST_OBJECT_LOCK (qtdemux);
12269       while (stream->n_samples == 0)
12270         if ((ret = qtdemux_add_fragmented_samples (qtdemux)) != GST_FLOW_OK)
12271           break;
12272       GST_OBJECT_UNLOCK (qtdemux);
12273     } else {
12274       /* discard any stray moof */
12275       qtdemux->moof_offset = 0;
12276     }
12277
12278     /* prepare braking */
12279     if (ret != GST_FLOW_ERROR)
12280       ret = GST_FLOW_OK;
12281
12282     /* in pull mode, we should have parsed some sample info by now;
12283      * and quite some code will not handle no samples.
12284      * in push mode, we'll just have to deal with it */
12285     if (G_UNLIKELY (qtdemux->pullbased && !stream->n_samples)) {
12286       GST_DEBUG_OBJECT (qtdemux, "no samples for stream; discarding");
12287       gst_qtdemux_remove_stream (qtdemux, stream);
12288       continue;
12289     } else if (stream->track_id == qtdemux->chapters_track_id &&
12290         (stream->subtype == FOURCC_text || stream->subtype == FOURCC_sbtl)) {
12291       /* TODO - parse chapters track and expose it as GstToc; For now just ignore it
12292          so that it doesn't look like a subtitle track */
12293       gst_qtdemux_remove_stream (qtdemux, stream);
12294       continue;
12295     }
12296
12297     /* parse the initial sample for use in setting the frame rate cap */
12298     while (sample_num == 0 && sample_num < stream->n_samples) {
12299       if (!qtdemux_parse_samples (qtdemux, stream, sample_num))
12300         break;
12301       ++sample_num;
12302     }
12303   }
12304
12305   return ret;
12306 }
12307
12308 static GList *
12309 _stream_in_list (GList * list, QtDemuxStream * stream)
12310 {
12311   GList *iter;
12312
12313   for (iter = list; iter; iter = g_list_next (iter)) {
12314     QtDemuxStream *tmp = QTDEMUX_STREAM (iter->data);
12315     if (!g_strcmp0 (tmp->stream_id, stream->stream_id))
12316       return iter;
12317   }
12318
12319   return NULL;
12320 }
12321
12322 static gboolean
12323 qtdemux_is_streams_update (GstQTDemux * qtdemux)
12324 {
12325   GList *new, *old;
12326
12327   g_return_val_if_fail (qtdemux->active_streams != NULL, FALSE);
12328
12329   /* streams in list are sorted in track-id order */
12330   for (new = qtdemux->active_streams, old = qtdemux->old_streams; new && old;
12331       new = g_list_next (new), old = g_list_next (old)) {
12332
12333     /* Different stream-id, updated */
12334     if (g_strcmp0 (QTDEMUX_STREAM (new->data)->stream_id,
12335             QTDEMUX_STREAM (old->data)->stream_id))
12336       return TRUE;
12337   }
12338
12339   /* Different length, updated */
12340   if (new != NULL || old != NULL)
12341     return TRUE;
12342
12343   return FALSE;
12344 }
12345
12346 static gboolean
12347 qtdemux_reuse_and_configure_stream (GstQTDemux * qtdemux,
12348     QtDemuxStream * oldstream, QtDemuxStream * newstream)
12349 {
12350   /* Connect old stream's srcpad to new stream */
12351   newstream->pad = oldstream->pad;
12352   oldstream->pad = NULL;
12353
12354   /* unset new_stream to prevent stream-start event */
12355   newstream->new_stream = FALSE;
12356
12357   return gst_qtdemux_configure_stream (qtdemux, newstream);
12358 }
12359
12360 static gboolean
12361 qtdemux_update_streams (GstQTDemux * qtdemux)
12362 {
12363   GList *iter, *next;
12364
12365   /* At below, figure out which stream in active_streams has identical stream-id
12366    * with that of in old_streams. If there is matching stream-id,
12367    * corresponding newstream will not be exposed again,
12368    * but demux will reuse srcpad of matched old stream
12369    *
12370    * active_streams : newly created streams from the latest moov
12371    * old_streams : existing streams (belong to previous moov)
12372    */
12373
12374   /* Count n_streams again */
12375   qtdemux->n_streams = 0;
12376
12377   for (iter = qtdemux->active_streams; iter; iter = next) {
12378     GList *tmp;
12379     QtDemuxStream *stream = QTDEMUX_STREAM (iter->data);
12380
12381     next = iter->next;
12382
12383     GST_DEBUG_OBJECT (qtdemux, "track-id %u, fourcc %" GST_FOURCC_FORMAT,
12384         stream->track_id, GST_FOURCC_ARGS (CUR_STREAM (stream)->fourcc));
12385
12386     qtdemux->n_streams++;
12387
12388     if (qtdemux->streams_aware
12389         && (tmp = _stream_in_list (qtdemux->old_streams, stream)) != NULL
12390         && QTDEMUX_STREAM (tmp->data)->pad) {
12391       QtDemuxStream *oldstream = QTDEMUX_STREAM (tmp->data);
12392
12393       GST_DEBUG_OBJECT (qtdemux, "Reuse track-id %d", oldstream->track_id);
12394
12395       if (!qtdemux_reuse_and_configure_stream (qtdemux, oldstream, stream))
12396         return FALSE;
12397
12398       qtdemux->old_streams = g_list_remove (qtdemux->old_streams, oldstream);
12399       gst_qtdemux_stream_free (oldstream);
12400     } else {
12401       GstTagList *list;
12402
12403       /* now we have all info and can expose */
12404       list = stream->stream_tags;
12405       stream->stream_tags = NULL;
12406       if (!gst_qtdemux_add_stream (qtdemux, stream, list))
12407         return FALSE;
12408     }
12409   }
12410
12411   return TRUE;
12412 }
12413
12414 /* Must be called with expose lock */
12415 static GstFlowReturn
12416 qtdemux_expose_streams (GstQTDemux * qtdemux)
12417 {
12418   GList *iter, *next;
12419
12420   GST_DEBUG_OBJECT (qtdemux, "exposing streams");
12421
12422   if (!qtdemux_is_streams_update (qtdemux)) {
12423     GList *new, *old;
12424
12425     GST_DEBUG_OBJECT (qtdemux, "Reuse all streams");
12426     for (new = qtdemux->active_streams, old = qtdemux->old_streams; new && old;
12427         new = g_list_next (new), old = g_list_next (old)) {
12428       if (!qtdemux_reuse_and_configure_stream (qtdemux,
12429               QTDEMUX_STREAM (old->data), QTDEMUX_STREAM (new->data)))
12430         return GST_FLOW_ERROR;
12431     }
12432
12433     g_list_free_full (qtdemux->old_streams,
12434         (GDestroyNotify) gst_qtdemux_stream_free);
12435     qtdemux->old_streams = NULL;
12436
12437     return GST_FLOW_OK;
12438   }
12439
12440   if (qtdemux->streams_aware) {
12441     if (!qtdemux_update_streams (qtdemux))
12442       return GST_FLOW_ERROR;
12443   } else {
12444     for (iter = qtdemux->active_streams; iter; iter = g_list_next (iter)) {
12445       QtDemuxStream *stream = QTDEMUX_STREAM (iter->data);
12446       GstTagList *list;
12447
12448       /* now we have all info and can expose */
12449       list = stream->stream_tags;
12450       stream->stream_tags = NULL;
12451       if (!gst_qtdemux_add_stream (qtdemux, stream, list))
12452         return GST_FLOW_ERROR;
12453
12454     }
12455   }
12456
12457   gst_qtdemux_guess_bitrate (qtdemux);
12458
12459   gst_element_no_more_pads (GST_ELEMENT_CAST (qtdemux));
12460
12461   /* If we have still old_streams, it's no more used stream */
12462   for (iter = qtdemux->old_streams; iter; iter = next) {
12463     QtDemuxStream *stream = QTDEMUX_STREAM (iter->data);
12464     next = g_list_next (iter);
12465
12466     if (stream->pad) {
12467       GstEvent *event;
12468
12469       event = gst_event_new_eos ();
12470       if (qtdemux->segment_seqnum)
12471         gst_event_set_seqnum (event, qtdemux->segment_seqnum);
12472
12473       gst_pad_push_event (stream->pad, event);
12474     }
12475
12476     qtdemux->old_streams = g_list_remove (qtdemux->old_streams, stream);
12477     gst_qtdemux_stream_free (stream);
12478   }
12479
12480   /* check if we should post a redirect in case there is a single trak
12481    * and it is a redirecting trak */
12482   if (qtdemux->n_streams == 1 &&
12483       QTDEMUX_FIRST_STREAM (qtdemux)->redirect_uri != NULL) {
12484     GstMessage *m;
12485
12486     GST_INFO_OBJECT (qtdemux, "Issuing a redirect due to a single track with "
12487         "an external content");
12488     m = gst_message_new_element (GST_OBJECT_CAST (qtdemux),
12489         gst_structure_new ("redirect",
12490             "new-location", G_TYPE_STRING,
12491             QTDEMUX_FIRST_STREAM (qtdemux)->redirect_uri, NULL));
12492     gst_element_post_message (GST_ELEMENT_CAST (qtdemux), m);
12493     qtdemux->posted_redirect = TRUE;
12494   }
12495
12496   for (iter = qtdemux->active_streams; iter; iter = g_list_next (iter)) {
12497     qtdemux_do_allocation (qtdemux, QTDEMUX_STREAM (iter->data));
12498   }
12499
12500   qtdemux->exposed = TRUE;
12501   return GST_FLOW_OK;
12502 }
12503
12504 /* check if major or compatible brand is 3GP */
12505 static inline gboolean
12506 qtdemux_is_brand_3gp (GstQTDemux * qtdemux, gboolean major)
12507 {
12508   if (major) {
12509     return ((qtdemux->major_brand & GST_MAKE_FOURCC (255, 255, 0, 0)) ==
12510         FOURCC_3g__);
12511   } else if (qtdemux->comp_brands != NULL) {
12512     GstMapInfo map;
12513     guint8 *data;
12514     gsize size;
12515     gboolean res = FALSE;
12516
12517     gst_buffer_map (qtdemux->comp_brands, &map, GST_MAP_READ);
12518     data = map.data;
12519     size = map.size;
12520     while (size >= 4) {
12521       res = res || ((QT_FOURCC (data) & GST_MAKE_FOURCC (255, 255, 0, 0)) ==
12522           FOURCC_3g__);
12523       data += 4;
12524       size -= 4;
12525     }
12526     gst_buffer_unmap (qtdemux->comp_brands, &map);
12527     return res;
12528   } else {
12529     return FALSE;
12530   }
12531 }
12532
12533 /* check if tag is a spec'ed 3GP tag keyword storing a string */
12534 static inline gboolean
12535 qtdemux_is_string_tag_3gp (GstQTDemux * qtdemux, guint32 fourcc)
12536 {
12537   return fourcc == FOURCC_cprt || fourcc == FOURCC_gnre || fourcc == FOURCC_titl
12538       || fourcc == FOURCC_dscp || fourcc == FOURCC_perf || fourcc == FOURCC_auth
12539       || fourcc == FOURCC_albm;
12540 }
12541
12542 static void
12543 qtdemux_tag_add_location (GstQTDemux * qtdemux, GstTagList * taglist,
12544     const char *tag, const char *dummy, GNode * node)
12545 {
12546   const gchar *env_vars[] = { "GST_QT_TAG_ENCODING", "GST_TAG_ENCODING", NULL };
12547   int offset;
12548   char *name;
12549   gchar *data;
12550   gdouble longitude, latitude, altitude;
12551   gint len;
12552
12553   len = QT_UINT32 (node->data);
12554   if (len <= 14)
12555     goto short_read;
12556
12557   data = node->data;
12558   offset = 14;
12559
12560   /* TODO: language code skipped */
12561
12562   name = gst_tag_freeform_string_to_utf8 (data + offset, -1, env_vars);
12563
12564   if (!name) {
12565     /* do not alarm in trivial case, but bail out otherwise */
12566     if (*(data + offset) != 0) {
12567       GST_DEBUG_OBJECT (qtdemux, "failed to convert %s tag to UTF-8, "
12568           "giving up", tag);
12569     }
12570   } else {
12571     gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE,
12572         GST_TAG_GEO_LOCATION_NAME, name, NULL);
12573     offset += strlen (name);
12574     g_free (name);
12575   }
12576
12577   if (len < offset + 2 + 4 + 4 + 4)
12578     goto short_read;
12579
12580   /* +1 +1 = skip null-terminator and location role byte */
12581   offset += 1 + 1;
12582   /* table in spec says unsigned, semantics say negative has meaning ... */
12583   longitude = QT_SFP32 (data + offset);
12584
12585   offset += 4;
12586   latitude = QT_SFP32 (data + offset);
12587
12588   offset += 4;
12589   altitude = QT_SFP32 (data + offset);
12590
12591   /* one invalid means all are invalid */
12592   if (longitude >= -180.0 && longitude <= 180.0 &&
12593       latitude >= -90.0 && latitude <= 90.0) {
12594     gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE,
12595         GST_TAG_GEO_LOCATION_LATITUDE, latitude,
12596         GST_TAG_GEO_LOCATION_LONGITUDE, longitude,
12597         GST_TAG_GEO_LOCATION_ELEVATION, altitude, NULL);
12598   }
12599
12600   /* TODO: no GST_TAG_, so astronomical body and additional notes skipped */
12601
12602   return;
12603
12604   /* ERRORS */
12605 short_read:
12606   {
12607     GST_DEBUG_OBJECT (qtdemux, "short read parsing 3GP location");
12608     return;
12609   }
12610 }
12611
12612
12613 static void
12614 qtdemux_tag_add_year (GstQTDemux * qtdemux, GstTagList * taglist,
12615     const char *tag, const char *dummy, GNode * node)
12616 {
12617   guint16 y;
12618   GDate *date;
12619   gint len;
12620
12621   len = QT_UINT32 (node->data);
12622   if (len < 14)
12623     return;
12624
12625   y = QT_UINT16 ((guint8 *) node->data + 12);
12626   if (y == 0) {
12627     GST_DEBUG_OBJECT (qtdemux, "year: %u is not a valid year", y);
12628     return;
12629   }
12630   GST_DEBUG_OBJECT (qtdemux, "year: %u", y);
12631
12632   date = g_date_new_dmy (1, 1, y);
12633   gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag, date, NULL);
12634   g_date_free (date);
12635 }
12636
12637 static void
12638 qtdemux_tag_add_classification (GstQTDemux * qtdemux, GstTagList * taglist,
12639     const char *tag, const char *dummy, GNode * node)
12640 {
12641   int offset;
12642   char *tag_str = NULL;
12643   guint8 *entity;
12644   guint16 table;
12645   gint len;
12646
12647   len = QT_UINT32 (node->data);
12648   if (len <= 20)
12649     goto short_read;
12650
12651   offset = 12;
12652   entity = (guint8 *) node->data + offset;
12653   if (entity[0] == 0 || entity[1] == 0 || entity[2] == 0 || entity[3] == 0) {
12654     GST_DEBUG_OBJECT (qtdemux,
12655         "classification info: %c%c%c%c invalid classification entity",
12656         entity[0], entity[1], entity[2], entity[3]);
12657     return;
12658   }
12659
12660   offset += 4;
12661   table = QT_UINT16 ((guint8 *) node->data + offset);
12662
12663   /* Language code skipped */
12664
12665   offset += 4;
12666
12667   /* Tag format: "XXXX://Y[YYYY]/classification info string"
12668    * XXXX: classification entity, fixed length 4 chars.
12669    * Y[YYYY]: classification table, max 5 chars.
12670    */
12671   tag_str = g_strdup_printf ("----://%u/%s",
12672       table, (char *) node->data + offset);
12673
12674   /* memcpy To be sure we're preserving byte order */
12675   memcpy (tag_str, entity, 4);
12676   GST_DEBUG_OBJECT (qtdemux, "classification info: %s", tag_str);
12677
12678   gst_tag_list_add (taglist, GST_TAG_MERGE_APPEND, tag, tag_str, NULL);
12679
12680   g_free (tag_str);
12681
12682   return;
12683
12684   /* ERRORS */
12685 short_read:
12686   {
12687     GST_DEBUG_OBJECT (qtdemux, "short read parsing 3GP classification");
12688     return;
12689   }
12690 }
12691
12692 static gboolean
12693 qtdemux_tag_add_str_full (GstQTDemux * qtdemux, GstTagList * taglist,
12694     const char *tag, const char *dummy, GNode * node)
12695 {
12696   const gchar *env_vars[] = { "GST_QT_TAG_ENCODING", "GST_TAG_ENCODING", NULL };
12697   GNode *data;
12698   char *s;
12699   int len;
12700   guint32 type;
12701   int offset;
12702   gboolean ret = TRUE;
12703   const gchar *charset = NULL;
12704
12705   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
12706   if (data) {
12707     len = QT_UINT32 (data->data);
12708     type = QT_UINT32 ((guint8 *) data->data + 8);
12709     if (type == 0x00000001 && len > 16) {
12710       s = gst_tag_freeform_string_to_utf8 ((char *) data->data + 16, len - 16,
12711           env_vars);
12712       if (s) {
12713         GST_DEBUG_OBJECT (qtdemux, "adding tag %s", GST_STR_NULL (s));
12714         gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag, s, NULL);
12715         g_free (s);
12716       } else {
12717         GST_DEBUG_OBJECT (qtdemux, "failed to convert %s tag to UTF-8", tag);
12718       }
12719     }
12720   } else {
12721     len = QT_UINT32 (node->data);
12722     type = QT_UINT32 ((guint8 *) node->data + 4);
12723     if ((type >> 24) == 0xa9 && len > 8 + 4) {
12724       gint str_len;
12725       gint lang_code;
12726
12727       /* Type starts with the (C) symbol, so the next data is a list
12728        * of (string size(16), language code(16), string) */
12729
12730       str_len = QT_UINT16 ((guint8 *) node->data + 8);
12731       lang_code = QT_UINT16 ((guint8 *) node->data + 10);
12732
12733       /* the string + fourcc + size + 2 16bit fields,
12734        * means that there are more tags in this atom */
12735       if (len > str_len + 8 + 4) {
12736         /* TODO how to represent the same tag in different languages? */
12737         GST_WARNING_OBJECT (qtdemux, "Ignoring metadata entry with multiple "
12738             "text alternatives, reading only first one");
12739       }
12740
12741       offset = 12;
12742       len = MIN (len, str_len + 8 + 4); /* remove trailing strings that we don't use */
12743       GST_DEBUG_OBJECT (qtdemux, "found international text tag");
12744
12745       if (lang_code < 0x800) {  /* MAC encoded string */
12746         charset = "mac";
12747       }
12748     } else if (len > 14 && qtdemux_is_string_tag_3gp (qtdemux,
12749             QT_FOURCC ((guint8 *) node->data + 4))) {
12750       guint32 type = QT_UINT32 ((guint8 *) node->data + 8);
12751
12752       /* we go for 3GP style encoding if major brands claims so,
12753        * or if no hope for data be ok UTF-8, and compatible 3GP brand present */
12754       if (qtdemux_is_brand_3gp (qtdemux, TRUE) ||
12755           (qtdemux_is_brand_3gp (qtdemux, FALSE) &&
12756               ((type & 0x00FFFFFF) == 0x0) && (type >> 24 <= 0xF))) {
12757         offset = 14;
12758         /* 16-bit Language code is ignored here as well */
12759         GST_DEBUG_OBJECT (qtdemux, "found 3gpp text tag");
12760       } else {
12761         goto normal;
12762       }
12763     } else {
12764     normal:
12765       offset = 8;
12766       GST_DEBUG_OBJECT (qtdemux, "found normal text tag");
12767       ret = FALSE;              /* may have to fallback */
12768     }
12769     if (charset) {
12770       GError *err = NULL;
12771
12772       s = g_convert ((gchar *) node->data + offset, len - offset, "utf8",
12773           charset, NULL, NULL, &err);
12774       if (err) {
12775         GST_DEBUG_OBJECT (qtdemux, "Failed to convert string from charset %s:"
12776             " %s(%d): %s", charset, g_quark_to_string (err->domain), err->code,
12777             err->message);
12778         g_error_free (err);
12779       }
12780     } else {
12781       s = gst_tag_freeform_string_to_utf8 ((char *) node->data + offset,
12782           len - offset, env_vars);
12783     }
12784     if (s) {
12785       GST_DEBUG_OBJECT (qtdemux, "adding tag %s", GST_STR_NULL (s));
12786       gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag, s, NULL);
12787       g_free (s);
12788       ret = TRUE;
12789     } else {
12790       GST_DEBUG_OBJECT (qtdemux, "failed to convert %s tag to UTF-8", tag);
12791     }
12792   }
12793   return ret;
12794 }
12795
12796 static void
12797 qtdemux_tag_add_str (GstQTDemux * qtdemux, GstTagList * taglist,
12798     const char *tag, const char *dummy, GNode * node)
12799 {
12800   qtdemux_tag_add_str_full (qtdemux, taglist, tag, dummy, node);
12801 }
12802
12803 static void
12804 qtdemux_tag_add_keywords (GstQTDemux * qtdemux, GstTagList * taglist,
12805     const char *tag, const char *dummy, GNode * node)
12806 {
12807   const gchar *env_vars[] = { "GST_QT_TAG_ENCODING", "GST_TAG_ENCODING", NULL };
12808   guint8 *data;
12809   char *s, *t, *k = NULL;
12810   int len;
12811   int offset;
12812   int count;
12813
12814   /* first try normal string tag if major brand not 3GP */
12815   if (!qtdemux_is_brand_3gp (qtdemux, TRUE)) {
12816     if (!qtdemux_tag_add_str_full (qtdemux, taglist, tag, dummy, node)) {
12817       /* hm, that did not work, maybe 3gpp storage in non-3gpp major brand;
12818        * let's try it 3gpp way after minor safety check */
12819       data = node->data;
12820       if (QT_UINT32 (data) < 15 || !qtdemux_is_brand_3gp (qtdemux, FALSE))
12821         return;
12822     } else
12823       return;
12824   }
12825
12826   GST_DEBUG_OBJECT (qtdemux, "found 3gpp keyword tag");
12827
12828   data = node->data;
12829
12830   len = QT_UINT32 (data);
12831   if (len < 15)
12832     goto short_read;
12833
12834   count = QT_UINT8 (data + 14);
12835   offset = 15;
12836   for (; count; count--) {
12837     gint slen;
12838
12839     if (offset + 1 > len)
12840       goto short_read;
12841     slen = QT_UINT8 (data + offset);
12842     offset += 1;
12843     if (offset + slen > len)
12844       goto short_read;
12845     s = gst_tag_freeform_string_to_utf8 ((char *) node->data + offset,
12846         slen, env_vars);
12847     if (s) {
12848       GST_DEBUG_OBJECT (qtdemux, "adding keyword %s", GST_STR_NULL (s));
12849       if (k) {
12850         t = g_strjoin (",", k, s, NULL);
12851         g_free (s);
12852         g_free (k);
12853         k = t;
12854       } else {
12855         k = s;
12856       }
12857     } else {
12858       GST_DEBUG_OBJECT (qtdemux, "failed to convert keyword to UTF-8");
12859     }
12860     offset += slen;
12861   }
12862
12863 done:
12864   if (k) {
12865     GST_DEBUG_OBJECT (qtdemux, "adding tag %s", GST_STR_NULL (k));
12866     gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag, k, NULL);
12867   }
12868   g_free (k);
12869
12870   return;
12871
12872   /* ERRORS */
12873 short_read:
12874   {
12875     GST_DEBUG_OBJECT (qtdemux, "short read parsing 3GP keywords");
12876     goto done;
12877   }
12878 }
12879
12880 static void
12881 qtdemux_tag_add_num (GstQTDemux * qtdemux, GstTagList * taglist,
12882     const char *tag1, const char *tag2, GNode * node)
12883 {
12884   GNode *data;
12885   int len;
12886   int type;
12887   int n1, n2;
12888
12889   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
12890   if (data) {
12891     len = QT_UINT32 (data->data);
12892     type = QT_UINT32 ((guint8 *) data->data + 8);
12893     if (type == 0x00000000 && len >= 22) {
12894       n1 = QT_UINT16 ((guint8 *) data->data + 18);
12895       n2 = QT_UINT16 ((guint8 *) data->data + 20);
12896       if (n1 > 0) {
12897         GST_DEBUG_OBJECT (qtdemux, "adding tag %s=%d", tag1, n1);
12898         gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag1, n1, NULL);
12899       }
12900       if (n2 > 0) {
12901         GST_DEBUG_OBJECT (qtdemux, "adding tag %s=%d", tag2, n2);
12902         gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag2, n2, NULL);
12903       }
12904     }
12905   }
12906 }
12907
12908 static void
12909 qtdemux_tag_add_tmpo (GstQTDemux * qtdemux, GstTagList * taglist,
12910     const char *tag1, const char *dummy, GNode * node)
12911 {
12912   GNode *data;
12913   int len;
12914   int type;
12915   int n1;
12916
12917   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
12918   if (data) {
12919     len = QT_UINT32 (data->data);
12920     type = QT_UINT32 ((guint8 *) data->data + 8);
12921     GST_DEBUG_OBJECT (qtdemux, "have tempo tag, type=%d,len=%d", type, len);
12922     /* some files wrongly have a type 0x0f=15, but it should be 0x15 */
12923     if ((type == 0x00000015 || type == 0x0000000f) && len >= 18) {
12924       n1 = QT_UINT16 ((guint8 *) data->data + 16);
12925       if (n1) {
12926         /* do not add bpm=0 */
12927         GST_DEBUG_OBJECT (qtdemux, "adding tag %d", n1);
12928         gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag1, (gdouble) n1,
12929             NULL);
12930       }
12931     }
12932   }
12933 }
12934
12935 static void
12936 qtdemux_tag_add_uint32 (GstQTDemux * qtdemux, GstTagList * taglist,
12937     const char *tag1, const char *dummy, GNode * node)
12938 {
12939   GNode *data;
12940   int len;
12941   int type;
12942   guint32 num;
12943
12944   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
12945   if (data) {
12946     len = QT_UINT32 (data->data);
12947     type = QT_UINT32 ((guint8 *) data->data + 8);
12948     GST_DEBUG_OBJECT (qtdemux, "have %s tag, type=%d,len=%d", tag1, type, len);
12949     /* some files wrongly have a type 0x0f=15, but it should be 0x15 */
12950     if ((type == 0x00000015 || type == 0x0000000f) && len >= 20) {
12951       num = QT_UINT32 ((guint8 *) data->data + 16);
12952       if (num) {
12953         /* do not add num=0 */
12954         GST_DEBUG_OBJECT (qtdemux, "adding tag %d", num);
12955         gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag1, num, NULL);
12956       }
12957     }
12958   }
12959 }
12960
12961 static void
12962 qtdemux_tag_add_covr (GstQTDemux * qtdemux, GstTagList * taglist,
12963     const char *tag1, const char *dummy, GNode * node)
12964 {
12965   GNode *data;
12966   int len;
12967   int type;
12968   GstSample *sample;
12969
12970   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
12971   if (data) {
12972     len = QT_UINT32 (data->data);
12973     type = QT_UINT32 ((guint8 *) data->data + 8);
12974     GST_DEBUG_OBJECT (qtdemux, "have covr tag, type=%d,len=%d", type, len);
12975     if ((type == 0x0000000d || type == 0x0000000e) && len > 16) {
12976       GstTagImageType image_type;
12977
12978       if (gst_tag_list_get_tag_size (taglist, GST_TAG_IMAGE) == 0)
12979         image_type = GST_TAG_IMAGE_TYPE_FRONT_COVER;
12980       else
12981         image_type = GST_TAG_IMAGE_TYPE_NONE;
12982
12983       if ((sample =
12984               gst_tag_image_data_to_image_sample ((guint8 *) data->data + 16,
12985                   len - 16, image_type))) {
12986         GST_DEBUG_OBJECT (qtdemux, "adding tag size %d", len - 16);
12987         gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag1, sample, NULL);
12988         gst_sample_unref (sample);
12989       }
12990     }
12991   }
12992 }
12993
12994 static void
12995 qtdemux_tag_add_date (GstQTDemux * qtdemux, GstTagList * taglist,
12996     const char *tag, const char *dummy, GNode * node)
12997 {
12998   GNode *data;
12999   GstDateTime *datetime = NULL;
13000   char *s;
13001   int len;
13002   int type;
13003
13004   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
13005   if (data) {
13006     len = QT_UINT32 (data->data);
13007     type = QT_UINT32 ((guint8 *) data->data + 8);
13008     if (type == 0x00000001 && len > 16) {
13009       guint y, m = 1, d = 1;
13010       gint ret;
13011
13012       s = g_strndup ((char *) data->data + 16, len - 16);
13013       GST_DEBUG_OBJECT (qtdemux, "adding date '%s'", s);
13014       datetime = gst_date_time_new_from_iso8601_string (s);
13015       if (datetime != NULL) {
13016         gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, GST_TAG_DATE_TIME,
13017             datetime, NULL);
13018         gst_date_time_unref (datetime);
13019       }
13020
13021       ret = sscanf (s, "%u-%u-%u", &y, &m, &d);
13022       if (ret >= 1 && y > 1500 && y < 3000) {
13023         GDate *date;
13024
13025         date = g_date_new_dmy (d, m, y);
13026         gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag, date, NULL);
13027         g_date_free (date);
13028       } else {
13029         GST_DEBUG_OBJECT (qtdemux, "could not parse date string '%s'", s);
13030       }
13031       g_free (s);
13032     }
13033   }
13034 }
13035
13036 static void
13037 qtdemux_tag_add_gnre (GstQTDemux * qtdemux, GstTagList * taglist,
13038     const char *tag, const char *dummy, GNode * node)
13039 {
13040   GNode *data;
13041
13042   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
13043
13044   /* re-route to normal string tag if major brand says so
13045    * or no data atom and compatible brand suggests so */
13046   if (qtdemux_is_brand_3gp (qtdemux, TRUE) ||
13047       (qtdemux_is_brand_3gp (qtdemux, FALSE) && !data)) {
13048     qtdemux_tag_add_str (qtdemux, taglist, tag, dummy, node);
13049     return;
13050   }
13051
13052   if (data) {
13053     guint len, type, n;
13054
13055     len = QT_UINT32 (data->data);
13056     type = QT_UINT32 ((guint8 *) data->data + 8);
13057     if (type == 0x00000000 && len >= 18) {
13058       n = QT_UINT16 ((guint8 *) data->data + 16);
13059       if (n > 0) {
13060         const gchar *genre;
13061
13062         genre = gst_tag_id3_genre_get (n - 1);
13063         if (genre != NULL) {
13064           GST_DEBUG_OBJECT (qtdemux, "adding %d [%s]", n, genre);
13065           gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag, genre, NULL);
13066         }
13067       }
13068     }
13069   }
13070 }
13071
13072 static void
13073 qtdemux_add_double_tag_from_str (GstQTDemux * demux, GstTagList * taglist,
13074     const gchar * tag, guint8 * data, guint32 datasize)
13075 {
13076   gdouble value;
13077   gchar *datacopy;
13078
13079   /* make a copy to have \0 at the end */
13080   datacopy = g_strndup ((gchar *) data, datasize);
13081
13082   /* convert the str to double */
13083   if (sscanf (datacopy, "%lf", &value) == 1) {
13084     GST_DEBUG_OBJECT (demux, "adding tag: %s [%s]", tag, datacopy);
13085     gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag, value, NULL);
13086   } else {
13087     GST_WARNING_OBJECT (demux, "Failed to parse double from string: %s",
13088         datacopy);
13089   }
13090   g_free (datacopy);
13091 }
13092
13093
13094 static void
13095 qtdemux_tag_add_revdns (GstQTDemux * demux, GstTagList * taglist,
13096     const char *tag, const char *tag_bis, GNode * node)
13097 {
13098   GNode *mean;
13099   GNode *name;
13100   GNode *data;
13101   guint32 meansize;
13102   guint32 namesize;
13103   guint32 datatype;
13104   guint32 datasize;
13105   const gchar *meanstr;
13106   const gchar *namestr;
13107
13108   /* checking the whole ---- atom size for consistency */
13109   if (QT_UINT32 (node->data) <= 4 + 12 + 12 + 16) {
13110     GST_WARNING_OBJECT (demux, "Tag ---- atom is too small, ignoring");
13111     return;
13112   }
13113
13114   mean = qtdemux_tree_get_child_by_type (node, FOURCC_mean);
13115   if (!mean) {
13116     GST_WARNING_OBJECT (demux, "No 'mean' atom found");
13117     return;
13118   }
13119
13120   meansize = QT_UINT32 (mean->data);
13121   if (meansize <= 12) {
13122     GST_WARNING_OBJECT (demux, "Small mean atom, ignoring the whole tag");
13123     return;
13124   }
13125   meanstr = ((gchar *) mean->data) + 12;
13126   meansize -= 12;
13127
13128   name = qtdemux_tree_get_child_by_type (node, FOURCC_name);
13129   if (!name) {
13130     GST_WARNING_OBJECT (demux, "'name' atom not found, ignoring tag");
13131     return;
13132   }
13133
13134   namesize = QT_UINT32 (name->data);
13135   if (namesize <= 12) {
13136     GST_WARNING_OBJECT (demux, "'name' atom is too small, ignoring tag");
13137     return;
13138   }
13139   namestr = ((gchar *) name->data) + 12;
13140   namesize -= 12;
13141
13142   /*
13143    * Data atom is:
13144    * uint32 - size
13145    * uint32 - name
13146    * uint8  - version
13147    * uint24 - data type
13148    * uint32 - all 0
13149    * rest   - the data
13150    */
13151   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
13152   if (!data) {
13153     GST_WARNING_OBJECT (demux, "No data atom in this tag");
13154     return;
13155   }
13156   datasize = QT_UINT32 (data->data);
13157   if (datasize <= 16) {
13158     GST_WARNING_OBJECT (demux, "Data atom too small");
13159     return;
13160   }
13161   datatype = QT_UINT32 (((gchar *) data->data) + 8) & 0xFFFFFF;
13162
13163   if ((strncmp (meanstr, "com.apple.iTunes", meansize) == 0) ||
13164       (strncmp (meanstr, "org.hydrogenaudio.replaygain", meansize) == 0)) {
13165     static const struct
13166     {
13167       const gchar name[28];
13168       const gchar tag[28];
13169     } tags[] = {
13170       {
13171       "replaygain_track_gain", GST_TAG_TRACK_GAIN}, {
13172       "replaygain_track_peak", GST_TAG_TRACK_PEAK}, {
13173       "replaygain_album_gain", GST_TAG_ALBUM_GAIN}, {
13174       "replaygain_album_peak", GST_TAG_ALBUM_PEAK}, {
13175       "MusicBrainz Track Id", GST_TAG_MUSICBRAINZ_TRACKID}, {
13176       "MusicBrainz Artist Id", GST_TAG_MUSICBRAINZ_ARTISTID}, {
13177       "MusicBrainz Album Id", GST_TAG_MUSICBRAINZ_ALBUMID}, {
13178       "MusicBrainz Album Artist Id", GST_TAG_MUSICBRAINZ_ALBUMARTISTID}
13179     };
13180     int i;
13181
13182     for (i = 0; i < G_N_ELEMENTS (tags); ++i) {
13183       if (!g_ascii_strncasecmp (tags[i].name, namestr, namesize)) {
13184         switch (gst_tag_get_type (tags[i].tag)) {
13185           case G_TYPE_DOUBLE:
13186             qtdemux_add_double_tag_from_str (demux, taglist, tags[i].tag,
13187                 ((guint8 *) data->data) + 16, datasize - 16);
13188             break;
13189           case G_TYPE_STRING:
13190             qtdemux_tag_add_str (demux, taglist, tags[i].tag, NULL, node);
13191             break;
13192           default:
13193             /* not reached */
13194             break;
13195         }
13196         break;
13197       }
13198     }
13199     if (i == G_N_ELEMENTS (tags))
13200       goto unknown_tag;
13201   } else {
13202     goto unknown_tag;
13203   }
13204
13205   return;
13206
13207 /* errors */
13208 unknown_tag:
13209 #ifndef GST_DISABLE_GST_DEBUG
13210   {
13211     gchar *namestr_dbg;
13212     gchar *meanstr_dbg;
13213
13214     meanstr_dbg = g_strndup (meanstr, meansize);
13215     namestr_dbg = g_strndup (namestr, namesize);
13216
13217     GST_WARNING_OBJECT (demux, "This tag %s:%s type:%u is not mapped, "
13218         "file a bug at bugzilla.gnome.org", meanstr_dbg, namestr_dbg, datatype);
13219
13220     g_free (namestr_dbg);
13221     g_free (meanstr_dbg);
13222   }
13223 #endif
13224   return;
13225 }
13226
13227 static void
13228 qtdemux_tag_add_id32 (GstQTDemux * demux, GstTagList * taglist, const char *tag,
13229     const char *tag_bis, GNode * node)
13230 {
13231   guint8 *data;
13232   GstBuffer *buf;
13233   guint len;
13234   GstTagList *id32_taglist = NULL;
13235
13236   GST_LOG_OBJECT (demux, "parsing ID32");
13237
13238   data = node->data;
13239   len = GST_READ_UINT32_BE (data);
13240
13241   /* need at least full box and language tag */
13242   if (len < 12 + 2)
13243     return;
13244
13245   buf = gst_buffer_new_allocate (NULL, len - 14, NULL);
13246   gst_buffer_fill (buf, 0, data + 14, len - 14);
13247
13248   id32_taglist = gst_tag_list_from_id3v2_tag (buf);
13249   if (id32_taglist) {
13250     GST_LOG_OBJECT (demux, "parsing ok");
13251     gst_tag_list_insert (taglist, id32_taglist, GST_TAG_MERGE_KEEP);
13252     gst_tag_list_unref (id32_taglist);
13253   } else {
13254     GST_LOG_OBJECT (demux, "parsing failed");
13255   }
13256
13257   gst_buffer_unref (buf);
13258 }
13259
13260 typedef void (*GstQTDemuxAddTagFunc) (GstQTDemux * demux, GstTagList * taglist,
13261     const char *tag, const char *tag_bis, GNode * node);
13262
13263 /* unmapped tags
13264 FOURCC_pcst -> if media is a podcast -> bool
13265 FOURCC_cpil -> if media is part of a compilation -> bool
13266 FOURCC_pgap -> if media is part of a gapless context -> bool
13267 FOURCC_tven -> the tv episode id e.g. S01E23 -> str
13268 */
13269
13270 static const struct
13271 {
13272   guint32 fourcc;
13273   const gchar *gst_tag;
13274   const gchar *gst_tag_bis;
13275   const GstQTDemuxAddTagFunc func;
13276 } add_funcs[] = {
13277   {
13278   FOURCC__nam, GST_TAG_TITLE, NULL, qtdemux_tag_add_str}, {
13279   FOURCC_titl, GST_TAG_TITLE, NULL, qtdemux_tag_add_str}, {
13280   FOURCC__grp, GST_TAG_GROUPING, NULL, qtdemux_tag_add_str}, {
13281   FOURCC__wrt, GST_TAG_COMPOSER, NULL, qtdemux_tag_add_str}, {
13282   FOURCC__ART, GST_TAG_ARTIST, NULL, qtdemux_tag_add_str}, {
13283   FOURCC_aART, GST_TAG_ALBUM_ARTIST, NULL, qtdemux_tag_add_str}, {
13284   FOURCC_perf, GST_TAG_ARTIST, NULL, qtdemux_tag_add_str}, {
13285   FOURCC_auth, GST_TAG_COMPOSER, NULL, qtdemux_tag_add_str}, {
13286   FOURCC__alb, GST_TAG_ALBUM, NULL, qtdemux_tag_add_str}, {
13287   FOURCC_albm, GST_TAG_ALBUM, NULL, qtdemux_tag_add_str}, {
13288   FOURCC_cprt, GST_TAG_COPYRIGHT, NULL, qtdemux_tag_add_str}, {
13289   FOURCC__cpy, GST_TAG_COPYRIGHT, NULL, qtdemux_tag_add_str}, {
13290   FOURCC__cmt, GST_TAG_COMMENT, NULL, qtdemux_tag_add_str}, {
13291   FOURCC__des, GST_TAG_DESCRIPTION, NULL, qtdemux_tag_add_str}, {
13292   FOURCC_desc, GST_TAG_DESCRIPTION, NULL, qtdemux_tag_add_str}, {
13293   FOURCC_dscp, GST_TAG_DESCRIPTION, NULL, qtdemux_tag_add_str}, {
13294   FOURCC__lyr, GST_TAG_LYRICS, NULL, qtdemux_tag_add_str}, {
13295   FOURCC__day, GST_TAG_DATE, NULL, qtdemux_tag_add_date}, {
13296   FOURCC_yrrc, GST_TAG_DATE, NULL, qtdemux_tag_add_year}, {
13297   FOURCC__too, GST_TAG_ENCODER, NULL, qtdemux_tag_add_str}, {
13298   FOURCC__inf, GST_TAG_COMMENT, NULL, qtdemux_tag_add_str}, {
13299   FOURCC_trkn, GST_TAG_TRACK_NUMBER, GST_TAG_TRACK_COUNT, qtdemux_tag_add_num}, {
13300   FOURCC_disk, GST_TAG_ALBUM_VOLUME_NUMBER, GST_TAG_ALBUM_VOLUME_COUNT,
13301         qtdemux_tag_add_num}, {
13302   FOURCC_disc, GST_TAG_ALBUM_VOLUME_NUMBER, GST_TAG_ALBUM_VOLUME_COUNT,
13303         qtdemux_tag_add_num}, {
13304   FOURCC__gen, GST_TAG_GENRE, NULL, qtdemux_tag_add_str}, {
13305   FOURCC_gnre, GST_TAG_GENRE, NULL, qtdemux_tag_add_gnre}, {
13306   FOURCC_tmpo, GST_TAG_BEATS_PER_MINUTE, NULL, qtdemux_tag_add_tmpo}, {
13307   FOURCC_covr, GST_TAG_IMAGE, NULL, qtdemux_tag_add_covr}, {
13308   FOURCC_sonm, GST_TAG_TITLE_SORTNAME, NULL, qtdemux_tag_add_str}, {
13309   FOURCC_soal, GST_TAG_ALBUM_SORTNAME, NULL, qtdemux_tag_add_str}, {
13310   FOURCC_soar, GST_TAG_ARTIST_SORTNAME, NULL, qtdemux_tag_add_str}, {
13311   FOURCC_soaa, GST_TAG_ALBUM_ARTIST_SORTNAME, NULL, qtdemux_tag_add_str}, {
13312   FOURCC_soco, GST_TAG_COMPOSER_SORTNAME, NULL, qtdemux_tag_add_str}, {
13313   FOURCC_sosn, GST_TAG_SHOW_SORTNAME, NULL, qtdemux_tag_add_str}, {
13314   FOURCC_tvsh, GST_TAG_SHOW_NAME, NULL, qtdemux_tag_add_str}, {
13315   FOURCC_tvsn, GST_TAG_SHOW_SEASON_NUMBER, NULL, qtdemux_tag_add_uint32}, {
13316   FOURCC_tves, GST_TAG_SHOW_EPISODE_NUMBER, NULL, qtdemux_tag_add_uint32}, {
13317   FOURCC_kywd, GST_TAG_KEYWORDS, NULL, qtdemux_tag_add_keywords}, {
13318   FOURCC_keyw, GST_TAG_KEYWORDS, NULL, qtdemux_tag_add_str}, {
13319   FOURCC__enc, GST_TAG_ENCODER, NULL, qtdemux_tag_add_str}, {
13320   FOURCC_loci, GST_TAG_GEO_LOCATION_NAME, NULL, qtdemux_tag_add_location}, {
13321   FOURCC_clsf, GST_QT_DEMUX_CLASSIFICATION_TAG, NULL,
13322         qtdemux_tag_add_classification}, {
13323   FOURCC__mak, GST_TAG_DEVICE_MANUFACTURER, NULL, qtdemux_tag_add_str}, {
13324   FOURCC__mod, GST_TAG_DEVICE_MODEL, NULL, qtdemux_tag_add_str}, {
13325   FOURCC__swr, GST_TAG_APPLICATION_NAME, NULL, qtdemux_tag_add_str}, {
13326
13327     /* This is a special case, some tags are stored in this
13328      * 'reverse dns naming', according to:
13329      * http://atomicparsley.sourceforge.net/mpeg-4files.html and
13330      * bug #614471
13331      */
13332   FOURCC_____, "", NULL, qtdemux_tag_add_revdns}, {
13333     /* see http://www.mp4ra.org/specs.html for ID32 in meta box */
13334   FOURCC_ID32, "", NULL, qtdemux_tag_add_id32}
13335 };
13336
13337 struct _GstQtDemuxTagList
13338 {
13339   GstQTDemux *demux;
13340   GstTagList *taglist;
13341 };
13342 typedef struct _GstQtDemuxTagList GstQtDemuxTagList;
13343
13344 static void
13345 qtdemux_tag_add_blob (GNode * node, GstQtDemuxTagList * qtdemuxtaglist)
13346 {
13347   gint len;
13348   guint8 *data;
13349   GstBuffer *buf;
13350   gchar *media_type;
13351   const gchar *style;
13352   GstSample *sample;
13353   GstStructure *s;
13354   guint i;
13355   guint8 ndata[4];
13356   GstQTDemux *demux = qtdemuxtaglist->demux;
13357   GstTagList *taglist = qtdemuxtaglist->taglist;
13358
13359   data = node->data;
13360   len = QT_UINT32 (data);
13361   buf = gst_buffer_new_and_alloc (len);
13362   gst_buffer_fill (buf, 0, data, len);
13363
13364   /* heuristic to determine style of tag */
13365   if (QT_FOURCC (data + 4) == FOURCC_____ ||
13366       (len > 8 + 12 && QT_FOURCC (data + 12) == FOURCC_data))
13367     style = "itunes";
13368   else if (demux->major_brand == FOURCC_qt__)
13369     style = "quicktime";
13370   /* fall back to assuming iso/3gp tag style */
13371   else
13372     style = "iso";
13373
13374   /* santize the name for the caps. */
13375   for (i = 0; i < 4; i++) {
13376     guint8 d = data[4 + i];
13377     if (g_ascii_isalnum (d))
13378       ndata[i] = g_ascii_tolower (d);
13379     else
13380       ndata[i] = '_';
13381   }
13382
13383   media_type = g_strdup_printf ("application/x-gst-qt-%c%c%c%c-tag",
13384       ndata[0], ndata[1], ndata[2], ndata[3]);
13385   GST_DEBUG_OBJECT (demux, "media type %s", media_type);
13386
13387   s = gst_structure_new (media_type, "style", G_TYPE_STRING, style, NULL);
13388   sample = gst_sample_new (buf, NULL, NULL, s);
13389   gst_buffer_unref (buf);
13390   g_free (media_type);
13391
13392   GST_DEBUG_OBJECT (demux, "adding private tag; size %d, info %" GST_PTR_FORMAT,
13393       len, s);
13394
13395   gst_tag_list_add (taglist, GST_TAG_MERGE_APPEND,
13396       GST_QT_DEMUX_PRIVATE_TAG, sample, NULL);
13397
13398   gst_sample_unref (sample);
13399 }
13400
13401 static void
13402 qtdemux_parse_udta (GstQTDemux * qtdemux, GstTagList * taglist, GNode * udta)
13403 {
13404   GNode *meta;
13405   GNode *ilst;
13406   GNode *xmp_;
13407   GNode *node;
13408   gint i;
13409   GstQtDemuxTagList demuxtaglist;
13410
13411   demuxtaglist.demux = qtdemux;
13412   demuxtaglist.taglist = taglist;
13413
13414   meta = qtdemux_tree_get_child_by_type (udta, FOURCC_meta);
13415   if (meta != NULL) {
13416     ilst = qtdemux_tree_get_child_by_type (meta, FOURCC_ilst);
13417     if (ilst == NULL) {
13418       GST_LOG_OBJECT (qtdemux, "no ilst");
13419       return;
13420     }
13421   } else {
13422     ilst = udta;
13423     GST_LOG_OBJECT (qtdemux, "no meta so using udta itself");
13424   }
13425
13426   i = 0;
13427   while (i < G_N_ELEMENTS (add_funcs)) {
13428     node = qtdemux_tree_get_child_by_type (ilst, add_funcs[i].fourcc);
13429     if (node) {
13430       gint len;
13431
13432       len = QT_UINT32 (node->data);
13433       if (len < 12) {
13434         GST_DEBUG_OBJECT (qtdemux, "too small tag atom %" GST_FOURCC_FORMAT,
13435             GST_FOURCC_ARGS (add_funcs[i].fourcc));
13436       } else {
13437         add_funcs[i].func (qtdemux, taglist, add_funcs[i].gst_tag,
13438             add_funcs[i].gst_tag_bis, node);
13439       }
13440       g_node_destroy (node);
13441     } else {
13442       i++;
13443     }
13444   }
13445
13446   /* parsed nodes have been removed, pass along remainder as blob */
13447   g_node_children_foreach (ilst, G_TRAVERSE_ALL,
13448       (GNodeForeachFunc) qtdemux_tag_add_blob, &demuxtaglist);
13449
13450   /* parse up XMP_ node if existing */
13451   xmp_ = qtdemux_tree_get_child_by_type (udta, FOURCC_XMP_);
13452   if (xmp_ != NULL) {
13453     GstBuffer *buf;
13454     GstTagList *xmptaglist;
13455
13456     buf = _gst_buffer_new_wrapped (((guint8 *) xmp_->data) + 8,
13457         QT_UINT32 ((guint8 *) xmp_->data) - 8, NULL);
13458     xmptaglist = gst_tag_list_from_xmp_buffer (buf);
13459     gst_buffer_unref (buf);
13460
13461     qtdemux_handle_xmp_taglist (qtdemux, taglist, xmptaglist);
13462   } else {
13463     GST_DEBUG_OBJECT (qtdemux, "No XMP_ node found");
13464   }
13465 }
13466
13467 typedef struct
13468 {
13469   GstStructure *structure;      /* helper for sort function */
13470   gchar *location;
13471   guint min_req_bitrate;
13472   guint min_req_qt_version;
13473 } GstQtReference;
13474
13475 static gint
13476 qtdemux_redirects_sort_func (gconstpointer a, gconstpointer b)
13477 {
13478   GstQtReference *ref_a = (GstQtReference *) a;
13479   GstQtReference *ref_b = (GstQtReference *) b;
13480
13481   if (ref_b->min_req_qt_version != ref_a->min_req_qt_version)
13482     return ref_b->min_req_qt_version - ref_a->min_req_qt_version;
13483
13484   /* known bitrates go before unknown; higher bitrates go first */
13485   return ref_b->min_req_bitrate - ref_a->min_req_bitrate;
13486 }
13487
13488 /* sort the redirects and post a message for the application.
13489  */
13490 static void
13491 qtdemux_process_redirects (GstQTDemux * qtdemux, GList * references)
13492 {
13493   GstQtReference *best;
13494   GstStructure *s;
13495   GstMessage *msg;
13496   GValue list_val = { 0, };
13497   GList *l;
13498
13499   g_assert (references != NULL);
13500
13501   references = g_list_sort (references, qtdemux_redirects_sort_func);
13502
13503   best = (GstQtReference *) references->data;
13504
13505   g_value_init (&list_val, GST_TYPE_LIST);
13506
13507   for (l = references; l != NULL; l = l->next) {
13508     GstQtReference *ref = (GstQtReference *) l->data;
13509     GValue struct_val = { 0, };
13510
13511     ref->structure = gst_structure_new ("redirect",
13512         "new-location", G_TYPE_STRING, ref->location, NULL);
13513
13514     if (ref->min_req_bitrate > 0) {
13515       gst_structure_set (ref->structure, "minimum-bitrate", G_TYPE_INT,
13516           ref->min_req_bitrate, NULL);
13517     }
13518
13519     g_value_init (&struct_val, GST_TYPE_STRUCTURE);
13520     g_value_set_boxed (&struct_val, ref->structure);
13521     gst_value_list_append_value (&list_val, &struct_val);
13522     g_value_unset (&struct_val);
13523     /* don't free anything here yet, since we need best->structure below */
13524   }
13525
13526   g_assert (best != NULL);
13527   s = gst_structure_copy (best->structure);
13528
13529   if (g_list_length (references) > 1) {
13530     gst_structure_set_value (s, "locations", &list_val);
13531   }
13532
13533   g_value_unset (&list_val);
13534
13535   for (l = references; l != NULL; l = l->next) {
13536     GstQtReference *ref = (GstQtReference *) l->data;
13537
13538     gst_structure_free (ref->structure);
13539     g_free (ref->location);
13540     g_free (ref);
13541   }
13542   g_list_free (references);
13543
13544   GST_INFO_OBJECT (qtdemux, "posting redirect message: %" GST_PTR_FORMAT, s);
13545   msg = gst_message_new_element (GST_OBJECT_CAST (qtdemux), s);
13546   gst_element_post_message (GST_ELEMENT_CAST (qtdemux), msg);
13547   qtdemux->posted_redirect = TRUE;
13548 }
13549
13550 /* look for redirect nodes, collect all redirect information and
13551  * process it.
13552  */
13553 static gboolean
13554 qtdemux_parse_redirects (GstQTDemux * qtdemux)
13555 {
13556   GNode *rmra, *rmda, *rdrf;
13557
13558   rmra = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_rmra);
13559   if (rmra) {
13560     GList *redirects = NULL;
13561
13562     rmda = qtdemux_tree_get_child_by_type (rmra, FOURCC_rmda);
13563     while (rmda) {
13564       GstQtReference ref = { NULL, NULL, 0, 0 };
13565       GNode *rmdr, *rmvc;
13566
13567       if ((rmdr = qtdemux_tree_get_child_by_type (rmda, FOURCC_rmdr))) {
13568         ref.min_req_bitrate = QT_UINT32 ((guint8 *) rmdr->data + 12);
13569         GST_LOG_OBJECT (qtdemux, "data rate atom, required bitrate = %u",
13570             ref.min_req_bitrate);
13571       }
13572
13573       if ((rmvc = qtdemux_tree_get_child_by_type (rmda, FOURCC_rmvc))) {
13574         guint32 package = QT_FOURCC ((guint8 *) rmvc->data + 12);
13575         guint version = QT_UINT32 ((guint8 *) rmvc->data + 16);
13576
13577 #ifndef GST_DISABLE_GST_DEBUG
13578         guint bitmask = QT_UINT32 ((guint8 *) rmvc->data + 20);
13579 #endif
13580         guint check_type = QT_UINT16 ((guint8 *) rmvc->data + 24);
13581
13582         GST_LOG_OBJECT (qtdemux,
13583             "version check atom [%" GST_FOURCC_FORMAT "], version=0x%08x"
13584             ", mask=%08x, check_type=%u", GST_FOURCC_ARGS (package), version,
13585             bitmask, check_type);
13586         if (package == FOURCC_qtim && check_type == 0) {
13587           ref.min_req_qt_version = version;
13588         }
13589       }
13590
13591       rdrf = qtdemux_tree_get_child_by_type (rmda, FOURCC_rdrf);
13592       if (rdrf) {
13593         guint32 ref_type;
13594         guint8 *ref_data;
13595         guint ref_len;
13596
13597         ref_len = QT_UINT32 ((guint8 *) rdrf->data);
13598         if (ref_len > 20) {
13599           ref_type = QT_FOURCC ((guint8 *) rdrf->data + 12);
13600           ref_data = (guint8 *) rdrf->data + 20;
13601           if (ref_type == FOURCC_alis) {
13602             guint record_len, record_version, fn_len;
13603
13604             if (ref_len > 70) {
13605               /* MacOSX alias record, google for alias-layout.txt */
13606               record_len = QT_UINT16 (ref_data + 4);
13607               record_version = QT_UINT16 (ref_data + 4 + 2);
13608               fn_len = QT_UINT8 (ref_data + 50);
13609               if (record_len > 50 && record_version == 2 && fn_len > 0) {
13610                 ref.location = g_strndup ((gchar *) ref_data + 51, fn_len);
13611               }
13612             } else {
13613               GST_WARNING_OBJECT (qtdemux, "Invalid rdrf/alis size (%u < 70)",
13614                   ref_len);
13615             }
13616           } else if (ref_type == FOURCC_url_) {
13617             ref.location = g_strndup ((gchar *) ref_data, ref_len - 8);
13618           } else {
13619             GST_DEBUG_OBJECT (qtdemux,
13620                 "unknown rdrf reference type %" GST_FOURCC_FORMAT,
13621                 GST_FOURCC_ARGS (ref_type));
13622           }
13623           if (ref.location != NULL) {
13624             GST_INFO_OBJECT (qtdemux, "New location: %s", ref.location);
13625             redirects =
13626                 g_list_prepend (redirects, g_memdup (&ref, sizeof (ref)));
13627           } else {
13628             GST_WARNING_OBJECT (qtdemux,
13629                 "Failed to extract redirect location from rdrf atom");
13630           }
13631         } else {
13632           GST_WARNING_OBJECT (qtdemux, "Invalid rdrf size (%u < 20)", ref_len);
13633         }
13634       }
13635
13636       /* look for others */
13637       rmda = qtdemux_tree_get_sibling_by_type (rmda, FOURCC_rmda);
13638     }
13639
13640     if (redirects != NULL) {
13641       qtdemux_process_redirects (qtdemux, redirects);
13642     }
13643   }
13644   return TRUE;
13645 }
13646
13647 static GstTagList *
13648 qtdemux_add_container_format (GstQTDemux * qtdemux, GstTagList * tags)
13649 {
13650   const gchar *fmt;
13651
13652   if (tags == NULL) {
13653     tags = gst_tag_list_new_empty ();
13654     gst_tag_list_set_scope (tags, GST_TAG_SCOPE_GLOBAL);
13655   }
13656
13657   if (qtdemux->major_brand == FOURCC_mjp2)
13658     fmt = "Motion JPEG 2000";
13659   else if ((qtdemux->major_brand & 0xffff) == FOURCC_3g__)
13660     fmt = "3GP";
13661   else if (qtdemux->major_brand == FOURCC_qt__)
13662     fmt = "Quicktime";
13663   else if (qtdemux->fragmented)
13664     fmt = "ISO fMP4";
13665   else
13666     fmt = "ISO MP4/M4A";
13667
13668   GST_LOG_OBJECT (qtdemux, "mapped %" GST_FOURCC_FORMAT " to '%s'",
13669       GST_FOURCC_ARGS (qtdemux->major_brand), fmt);
13670
13671   gst_tag_list_add (tags, GST_TAG_MERGE_REPLACE, GST_TAG_CONTAINER_FORMAT,
13672       fmt, NULL);
13673
13674   return tags;
13675 }
13676
13677 /* we have read the complete moov node now.
13678  * This function parses all of the relevant info, creates the traks and
13679  * prepares all data structures for playback
13680  */
13681 static gboolean
13682 qtdemux_parse_tree (GstQTDemux * qtdemux)
13683 {
13684   GNode *mvhd;
13685   GNode *trak;
13686   GNode *udta;
13687   GNode *mvex;
13688   GstClockTime duration;
13689   GNode *pssh;
13690   guint64 creation_time;
13691   GstDateTime *datetime = NULL;
13692   gint version;
13693
13694   /* make sure we have a usable taglist */
13695   qtdemux->tag_list = gst_tag_list_make_writable (qtdemux->tag_list);
13696
13697   mvhd = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_mvhd);
13698   if (mvhd == NULL) {
13699     GST_LOG_OBJECT (qtdemux, "No mvhd node found, looking for redirects.");
13700     return qtdemux_parse_redirects (qtdemux);
13701   }
13702
13703   version = QT_UINT8 ((guint8 *) mvhd->data + 8);
13704   if (version == 1) {
13705     creation_time = QT_UINT64 ((guint8 *) mvhd->data + 12);
13706     qtdemux->timescale = QT_UINT32 ((guint8 *) mvhd->data + 28);
13707     qtdemux->duration = QT_UINT64 ((guint8 *) mvhd->data + 32);
13708   } else if (version == 0) {
13709     creation_time = QT_UINT32 ((guint8 *) mvhd->data + 12);
13710     qtdemux->timescale = QT_UINT32 ((guint8 *) mvhd->data + 20);
13711     qtdemux->duration = QT_UINT32 ((guint8 *) mvhd->data + 24);
13712   } else {
13713     GST_WARNING_OBJECT (qtdemux, "Unhandled mvhd version %d", version);
13714     return FALSE;
13715   }
13716
13717   /* Moving qt creation time (secs since 1904) to unix time */
13718   if (creation_time != 0) {
13719     /* Try to use epoch first as it should be faster and more commonly found */
13720     if (creation_time >= QTDEMUX_SECONDS_FROM_1904_TO_1970) {
13721       GTimeVal now;
13722
13723       creation_time -= QTDEMUX_SECONDS_FROM_1904_TO_1970;
13724       /* some data cleansing sanity */
13725       g_get_current_time (&now);
13726       if (now.tv_sec + 24 * 3600 < creation_time) {
13727         GST_DEBUG_OBJECT (qtdemux, "discarding bogus future creation time");
13728       } else {
13729         datetime = gst_date_time_new_from_unix_epoch_utc (creation_time);
13730       }
13731     } else {
13732       GDateTime *base_dt = g_date_time_new_utc (1904, 1, 1, 0, 0, 0);
13733       GDateTime *dt, *dt_local;
13734
13735       dt = g_date_time_add_seconds (base_dt, creation_time);
13736       dt_local = g_date_time_to_local (dt);
13737       datetime = gst_date_time_new_from_g_date_time (dt_local);
13738
13739       g_date_time_unref (base_dt);
13740       g_date_time_unref (dt);
13741     }
13742   }
13743   if (datetime) {
13744     /* Use KEEP as explicit tags should have a higher priority than mvhd tag */
13745     gst_tag_list_add (qtdemux->tag_list, GST_TAG_MERGE_KEEP, GST_TAG_DATE_TIME,
13746         datetime, NULL);
13747     gst_date_time_unref (datetime);
13748   }
13749
13750   GST_INFO_OBJECT (qtdemux, "timescale: %u", qtdemux->timescale);
13751   GST_INFO_OBJECT (qtdemux, "duration: %" G_GUINT64_FORMAT, qtdemux->duration);
13752
13753   /* check for fragmented file and get some (default) data */
13754   mvex = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_mvex);
13755   if (mvex) {
13756     GNode *mehd;
13757     GstByteReader mehd_data;
13758
13759     /* let track parsing or anyone know weird stuff might happen ... */
13760     qtdemux->fragmented = TRUE;
13761
13762     /* compensate for total duration */
13763     mehd = qtdemux_tree_get_child_by_type_full (mvex, FOURCC_mehd, &mehd_data);
13764     if (mehd)
13765       qtdemux_parse_mehd (qtdemux, &mehd_data);
13766   }
13767
13768   /* set duration in the segment info */
13769   gst_qtdemux_get_duration (qtdemux, &duration);
13770   if (duration) {
13771     qtdemux->segment.duration = duration;
13772     /* also do not exceed duration; stop is set that way post seek anyway,
13773      * and segment activation falls back to duration,
13774      * whereas loop only checks stop, so let's align this here as well */
13775     qtdemux->segment.stop = duration;
13776   }
13777
13778   /* parse all traks */
13779   trak = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_trak);
13780   while (trak) {
13781     qtdemux_parse_trak (qtdemux, trak);
13782     /* iterate all siblings */
13783     trak = qtdemux_tree_get_sibling_by_type (trak, FOURCC_trak);
13784   }
13785
13786   qtdemux->tag_list = gst_tag_list_make_writable (qtdemux->tag_list);
13787
13788   /* find tags */
13789   udta = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_udta);
13790   if (udta) {
13791     qtdemux_parse_udta (qtdemux, qtdemux->tag_list, udta);
13792   } else {
13793     GST_LOG_OBJECT (qtdemux, "No udta node found.");
13794   }
13795
13796   /* maybe also some tags in meta box */
13797   udta = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_meta);
13798   if (udta) {
13799     GST_DEBUG_OBJECT (qtdemux, "Parsing meta box for tags.");
13800     qtdemux_parse_udta (qtdemux, qtdemux->tag_list, udta);
13801   } else {
13802     GST_LOG_OBJECT (qtdemux, "No meta node found.");
13803   }
13804
13805   /* parse any protection system info */
13806   pssh = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_pssh);
13807   while (pssh) {
13808     GST_LOG_OBJECT (qtdemux, "Parsing pssh box.");
13809     qtdemux_parse_pssh (qtdemux, pssh);
13810     pssh = qtdemux_tree_get_sibling_by_type (pssh, FOURCC_pssh);
13811   }
13812
13813   qtdemux->tag_list = qtdemux_add_container_format (qtdemux, qtdemux->tag_list);
13814
13815   return TRUE;
13816 }
13817
13818 /* taken from ffmpeg */
13819 static int
13820 read_descr_size (guint8 * ptr, guint8 * end, guint8 ** end_out)
13821 {
13822   int count = 4;
13823   int len = 0;
13824
13825   while (count--) {
13826     int c;
13827
13828     if (ptr >= end)
13829       return -1;
13830
13831     c = *ptr++;
13832     len = (len << 7) | (c & 0x7f);
13833     if (!(c & 0x80))
13834       break;
13835   }
13836   *end_out = ptr;
13837   return len;
13838 }
13839
13840 static GList *
13841 parse_xiph_stream_headers (GstQTDemux * qtdemux, gpointer codec_data,
13842     gsize codec_data_size)
13843 {
13844   GList *list = NULL;
13845   guint8 *p = codec_data;
13846   gint i, offset, num_packets;
13847   guint *length, last;
13848
13849   GST_MEMDUMP_OBJECT (qtdemux, "xiph codec data", codec_data, codec_data_size);
13850
13851   if (codec_data == NULL || codec_data_size == 0)
13852     goto error;
13853
13854   /* start of the stream and vorbis audio or theora video, need to
13855    * send the codec_priv data as first three packets */
13856   num_packets = p[0] + 1;
13857   GST_DEBUG_OBJECT (qtdemux,
13858       "%u stream headers, total length=%" G_GSIZE_FORMAT " bytes",
13859       (guint) num_packets, codec_data_size);
13860
13861   /* Let's put some limits, Don't think there even is a xiph codec
13862    * with more than 3-4 headers */
13863   if (G_UNLIKELY (num_packets > 16)) {
13864     GST_WARNING_OBJECT (qtdemux,
13865         "Unlikely number of xiph headers, most likely not valid");
13866     goto error;
13867   }
13868
13869   length = g_alloca (num_packets * sizeof (guint));
13870   last = 0;
13871   offset = 1;
13872
13873   /* first packets, read length values */
13874   for (i = 0; i < num_packets - 1; i++) {
13875     length[i] = 0;
13876     while (offset < codec_data_size) {
13877       length[i] += p[offset];
13878       if (p[offset++] != 0xff)
13879         break;
13880     }
13881     last += length[i];
13882   }
13883   if (offset + last > codec_data_size)
13884     goto error;
13885
13886   /* last packet is the remaining size */
13887   length[i] = codec_data_size - offset - last;
13888
13889   for (i = 0; i < num_packets; i++) {
13890     GstBuffer *hdr;
13891
13892     GST_DEBUG_OBJECT (qtdemux, "buffer %d: %u bytes", i, (guint) length[i]);
13893
13894     if (offset + length[i] > codec_data_size)
13895       goto error;
13896
13897     hdr = gst_buffer_new_wrapped (g_memdup (p + offset, length[i]), length[i]);
13898     list = g_list_append (list, hdr);
13899
13900     offset += length[i];
13901   }
13902
13903   return list;
13904
13905   /* ERRORS */
13906 error:
13907   {
13908     if (list != NULL)
13909       g_list_free_full (list, (GDestroyNotify) gst_buffer_unref);
13910     return NULL;
13911   }
13912
13913 }
13914
13915 /* this can change the codec originally present in @list */
13916 static void
13917 gst_qtdemux_handle_esds (GstQTDemux * qtdemux, QtDemuxStream * stream,
13918     QtDemuxStreamStsdEntry * entry, GNode * esds, GstTagList * list)
13919 {
13920   int len = QT_UINT32 (esds->data);
13921   guint8 *ptr = esds->data;
13922   guint8 *end = ptr + len;
13923   int tag;
13924   guint8 *data_ptr = NULL;
13925   int data_len = 0;
13926   guint8 object_type_id = 0;
13927   guint8 stream_type = 0;
13928   const char *codec_name = NULL;
13929   GstCaps *caps = NULL;
13930
13931   GST_MEMDUMP_OBJECT (qtdemux, "esds", ptr, len);
13932   ptr += 8;
13933   GST_DEBUG_OBJECT (qtdemux, "version/flags = %08x", QT_UINT32 (ptr));
13934   ptr += 4;
13935   while (ptr + 1 < end) {
13936     tag = QT_UINT8 (ptr);
13937     GST_DEBUG_OBJECT (qtdemux, "tag = %02x", tag);
13938     ptr++;
13939     len = read_descr_size (ptr, end, &ptr);
13940     GST_DEBUG_OBJECT (qtdemux, "len = %d", len);
13941
13942     /* Check the stated amount of data is available for reading */
13943     if (len < 0 || ptr + len > end)
13944       break;
13945
13946     switch (tag) {
13947       case ES_DESCRIPTOR_TAG:
13948         GST_DEBUG_OBJECT (qtdemux, "ID 0x%04x", QT_UINT16 (ptr));
13949         GST_DEBUG_OBJECT (qtdemux, "priority 0x%04x", QT_UINT8 (ptr + 2));
13950         ptr += 3;
13951         break;
13952       case DECODER_CONFIG_DESC_TAG:{
13953         guint max_bitrate, avg_bitrate;
13954
13955         object_type_id = QT_UINT8 (ptr);
13956         stream_type = QT_UINT8 (ptr + 1) >> 2;
13957         max_bitrate = QT_UINT32 (ptr + 5);
13958         avg_bitrate = QT_UINT32 (ptr + 9);
13959         GST_DEBUG_OBJECT (qtdemux, "object_type_id %02x", object_type_id);
13960         GST_DEBUG_OBJECT (qtdemux, "stream_type %02x", stream_type);
13961         GST_DEBUG_OBJECT (qtdemux, "buffer_size_db %02x", QT_UINT24 (ptr + 2));
13962         GST_DEBUG_OBJECT (qtdemux, "max bitrate %u", max_bitrate);
13963         GST_DEBUG_OBJECT (qtdemux, "avg bitrate %u", avg_bitrate);
13964         if (max_bitrate > 0 && max_bitrate < G_MAXUINT32) {
13965           gst_tag_list_add (list, GST_TAG_MERGE_REPLACE,
13966               GST_TAG_MAXIMUM_BITRATE, max_bitrate, NULL);
13967         }
13968         if (avg_bitrate > 0 && avg_bitrate < G_MAXUINT32) {
13969           gst_tag_list_add (list, GST_TAG_MERGE_REPLACE, GST_TAG_BITRATE,
13970               avg_bitrate, NULL);
13971         }
13972         ptr += 13;
13973         break;
13974       }
13975       case DECODER_SPECIFIC_INFO_TAG:
13976         GST_MEMDUMP_OBJECT (qtdemux, "data", ptr, len);
13977         if (object_type_id == 0xe0 && len == 0x40) {
13978           guint8 *data;
13979           GstStructure *s;
13980           guint32 clut[16];
13981           gint i;
13982
13983           GST_DEBUG_OBJECT (qtdemux,
13984               "Have VOBSUB palette. Creating palette event");
13985           /* move to decConfigDescr data and read palette */
13986           data = ptr;
13987           for (i = 0; i < 16; i++) {
13988             clut[i] = QT_UINT32 (data);
13989             data += 4;
13990           }
13991
13992           s = gst_structure_new ("application/x-gst-dvd", "event",
13993               G_TYPE_STRING, "dvd-spu-clut-change",
13994               "clut00", G_TYPE_INT, clut[0], "clut01", G_TYPE_INT, clut[1],
13995               "clut02", G_TYPE_INT, clut[2], "clut03", G_TYPE_INT, clut[3],
13996               "clut04", G_TYPE_INT, clut[4], "clut05", G_TYPE_INT, clut[5],
13997               "clut06", G_TYPE_INT, clut[6], "clut07", G_TYPE_INT, clut[7],
13998               "clut08", G_TYPE_INT, clut[8], "clut09", G_TYPE_INT, clut[9],
13999               "clut10", G_TYPE_INT, clut[10], "clut11", G_TYPE_INT, clut[11],
14000               "clut12", G_TYPE_INT, clut[12], "clut13", G_TYPE_INT, clut[13],
14001               "clut14", G_TYPE_INT, clut[14], "clut15", G_TYPE_INT, clut[15],
14002               NULL);
14003
14004           /* store event and trigger custom processing */
14005           stream->pending_event =
14006               gst_event_new_custom (GST_EVENT_CUSTOM_DOWNSTREAM, s);
14007         } else {
14008           /* Generic codec_data handler puts it on the caps */
14009           data_ptr = ptr;
14010           data_len = len;
14011         }
14012
14013         ptr += len;
14014         break;
14015       case SL_CONFIG_DESC_TAG:
14016         GST_DEBUG_OBJECT (qtdemux, "data %02x", QT_UINT8 (ptr));
14017         ptr += 1;
14018         break;
14019       default:
14020         GST_DEBUG_OBJECT (qtdemux, "Unknown/unhandled descriptor tag %02x",
14021             tag);
14022         GST_MEMDUMP_OBJECT (qtdemux, "descriptor data", ptr, len);
14023         ptr += len;
14024         break;
14025     }
14026   }
14027
14028   /* object_type_id in the esds atom in mp4a and mp4v tells us which codec is
14029    * in use, and should also be used to override some other parameters for some
14030    * codecs. */
14031   switch (object_type_id) {
14032     case 0x20:                 /* MPEG-4 */
14033       /* 4 bytes for the visual_object_sequence_start_code and 1 byte for the
14034        * profile_and_level_indication */
14035       if (data_ptr != NULL && data_len >= 5 &&
14036           GST_READ_UINT32_BE (data_ptr) == 0x000001b0) {
14037         gst_codec_utils_mpeg4video_caps_set_level_and_profile (entry->caps,
14038             data_ptr + 4, data_len - 4);
14039       }
14040       break;                    /* Nothing special needed here */
14041     case 0x21:                 /* H.264 */
14042       codec_name = "H.264 / AVC";
14043       caps = gst_caps_new_simple ("video/x-h264",
14044           "stream-format", G_TYPE_STRING, "avc",
14045           "alignment", G_TYPE_STRING, "au", NULL);
14046       break;
14047     case 0x40:                 /* AAC (any) */
14048     case 0x66:                 /* AAC Main */
14049     case 0x67:                 /* AAC LC */
14050     case 0x68:                 /* AAC SSR */
14051       /* Override channels and rate based on the codec_data, as it's often
14052        * wrong. */
14053       /* Only do so for basic setup without HE-AAC extension */
14054       if (data_ptr && data_len == 2) {
14055         guint channels, rate;
14056
14057         channels = gst_codec_utils_aac_get_channels (data_ptr, data_len);
14058         if (channels > 0)
14059           entry->n_channels = channels;
14060
14061         rate = gst_codec_utils_aac_get_sample_rate (data_ptr, data_len);
14062         if (rate > 0)
14063           entry->rate = rate;
14064       }
14065
14066       /* Set level and profile if possible */
14067       if (data_ptr != NULL && data_len >= 2) {
14068         gst_codec_utils_aac_caps_set_level_and_profile (entry->caps,
14069             data_ptr, data_len);
14070       } else {
14071         const gchar *profile_str = NULL;
14072         GstBuffer *buffer;
14073         GstMapInfo map;
14074         guint8 *codec_data;
14075         gint rate_idx, profile;
14076
14077         /* No codec_data, let's invent something.
14078          * FIXME: This is wrong for SBR! */
14079
14080         GST_WARNING_OBJECT (qtdemux, "No codec_data for AAC available");
14081
14082         buffer = gst_buffer_new_and_alloc (2);
14083         gst_buffer_map (buffer, &map, GST_MAP_WRITE);
14084         codec_data = map.data;
14085
14086         rate_idx =
14087             gst_codec_utils_aac_get_index_from_sample_rate (CUR_STREAM
14088             (stream)->rate);
14089
14090         switch (object_type_id) {
14091           case 0x66:
14092             profile_str = "main";
14093             profile = 0;
14094             break;
14095           case 0x67:
14096             profile_str = "lc";
14097             profile = 1;
14098             break;
14099           case 0x68:
14100             profile_str = "ssr";
14101             profile = 2;
14102             break;
14103           default:
14104             profile = 3;
14105             break;
14106         }
14107
14108         codec_data[0] = ((profile + 1) << 3) | ((rate_idx & 0xE) >> 1);
14109         codec_data[1] =
14110             ((rate_idx & 0x1) << 7) | (CUR_STREAM (stream)->n_channels << 3);
14111
14112         gst_buffer_unmap (buffer, &map);
14113         gst_caps_set_simple (CUR_STREAM (stream)->caps, "codec_data",
14114             GST_TYPE_BUFFER, buffer, NULL);
14115         gst_buffer_unref (buffer);
14116
14117         if (profile_str) {
14118           gst_caps_set_simple (CUR_STREAM (stream)->caps, "profile",
14119               G_TYPE_STRING, profile_str, NULL);
14120         }
14121       }
14122       break;
14123     case 0x60:                 /* MPEG-2, various profiles */
14124     case 0x61:
14125     case 0x62:
14126     case 0x63:
14127     case 0x64:
14128     case 0x65:
14129       codec_name = "MPEG-2 video";
14130       caps = gst_caps_new_simple ("video/mpeg",
14131           "mpegversion", G_TYPE_INT, 2,
14132           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
14133       break;
14134     case 0x69:                 /* MPEG-2 BC audio */
14135     case 0x6B:                 /* MPEG-1 audio */
14136       caps = gst_caps_new_simple ("audio/mpeg",
14137           "mpegversion", G_TYPE_INT, 1, NULL);
14138       codec_name = "MPEG-1 audio";
14139       break;
14140     case 0x6A:                 /* MPEG-1 */
14141       codec_name = "MPEG-1 video";
14142       caps = gst_caps_new_simple ("video/mpeg",
14143           "mpegversion", G_TYPE_INT, 1,
14144           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
14145       break;
14146     case 0x6C:                 /* MJPEG */
14147       caps =
14148           gst_caps_new_simple ("image/jpeg", "parsed", G_TYPE_BOOLEAN, TRUE,
14149           NULL);
14150       codec_name = "Motion-JPEG";
14151       break;
14152     case 0x6D:                 /* PNG */
14153       caps =
14154           gst_caps_new_simple ("image/png", "parsed", G_TYPE_BOOLEAN, TRUE,
14155           NULL);
14156       codec_name = "PNG still images";
14157       break;
14158     case 0x6E:                 /* JPEG2000 */
14159       codec_name = "JPEG-2000";
14160       caps = gst_caps_new_simple ("image/x-j2c", "fields", G_TYPE_INT, 1, NULL);
14161       break;
14162     case 0xA4:                 /* Dirac */
14163       codec_name = "Dirac";
14164       caps = gst_caps_new_empty_simple ("video/x-dirac");
14165       break;
14166     case 0xA5:                 /* AC3 */
14167       codec_name = "AC-3 audio";
14168       caps = gst_caps_new_simple ("audio/x-ac3",
14169           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
14170       break;
14171     case 0xA9:                 /* AC3 */
14172       codec_name = "DTS audio";
14173       caps = gst_caps_new_simple ("audio/x-dts",
14174           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
14175       break;
14176     case 0xDD:
14177       if (stream_type == 0x05 && data_ptr) {
14178         GList *headers =
14179             parse_xiph_stream_headers (qtdemux, data_ptr, data_len);
14180         if (headers) {
14181           GList *tmp;
14182           GValue arr_val = G_VALUE_INIT;
14183           GValue buf_val = G_VALUE_INIT;
14184           GstStructure *s;
14185
14186           /* Let's assume it's vorbis if it's an audio stream of type 0xdd and we have codec data that extracts properly */
14187           codec_name = "Vorbis";
14188           caps = gst_caps_new_empty_simple ("audio/x-vorbis");
14189           g_value_init (&arr_val, GST_TYPE_ARRAY);
14190           g_value_init (&buf_val, GST_TYPE_BUFFER);
14191           for (tmp = headers; tmp; tmp = tmp->next) {
14192             g_value_set_boxed (&buf_val, (GstBuffer *) tmp->data);
14193             gst_value_array_append_value (&arr_val, &buf_val);
14194           }
14195           s = gst_caps_get_structure (caps, 0);
14196           gst_structure_take_value (s, "streamheader", &arr_val);
14197           g_value_unset (&buf_val);
14198           g_list_free (headers);
14199
14200           data_ptr = NULL;
14201           data_len = 0;
14202         }
14203       }
14204       break;
14205     case 0xE1:                 /* QCELP */
14206       /* QCELP, the codec_data is a riff tag (little endian) with
14207        * 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). */
14208       caps = gst_caps_new_empty_simple ("audio/qcelp");
14209       codec_name = "QCELP";
14210       break;
14211     default:
14212       break;
14213   }
14214
14215   /* If we have a replacement caps, then change our caps for this stream */
14216   if (caps) {
14217     gst_caps_unref (entry->caps);
14218     entry->caps = caps;
14219   }
14220
14221   if (codec_name && list)
14222     gst_tag_list_add (list, GST_TAG_MERGE_REPLACE,
14223         GST_TAG_AUDIO_CODEC, codec_name, NULL);
14224
14225   /* Add the codec_data attribute to caps, if we have it */
14226   if (data_ptr) {
14227     GstBuffer *buffer;
14228
14229     buffer = gst_buffer_new_and_alloc (data_len);
14230     gst_buffer_fill (buffer, 0, data_ptr, data_len);
14231
14232     GST_DEBUG_OBJECT (qtdemux, "setting codec_data from esds");
14233     GST_MEMDUMP_OBJECT (qtdemux, "codec_data from esds", data_ptr, data_len);
14234
14235     gst_caps_set_simple (entry->caps, "codec_data", GST_TYPE_BUFFER,
14236         buffer, NULL);
14237     gst_buffer_unref (buffer);
14238   }
14239
14240 }
14241
14242 static inline GstCaps *
14243 _get_unknown_codec_name (const gchar * type, guint32 fourcc)
14244 {
14245   GstCaps *caps;
14246   guint i;
14247   char *s, fourstr[5];
14248
14249   g_snprintf (fourstr, 5, "%" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (fourcc));
14250   for (i = 0; i < 4; i++) {
14251     if (!g_ascii_isalnum (fourstr[i]))
14252       fourstr[i] = '_';
14253   }
14254   s = g_strdup_printf ("%s/x-gst-fourcc-%s", type, g_strstrip (fourstr));
14255   caps = gst_caps_new_empty_simple (s);
14256   g_free (s);
14257   return caps;
14258 }
14259
14260 #define _codec(name) \
14261   do { \
14262     if (codec_name) { \
14263       *codec_name = g_strdup (name); \
14264     } \
14265   } while (0)
14266
14267 static GstCaps *
14268 qtdemux_video_caps (GstQTDemux * qtdemux, QtDemuxStream * stream,
14269     QtDemuxStreamStsdEntry * entry, guint32 fourcc,
14270     const guint8 * stsd_entry_data, gchar ** codec_name)
14271 {
14272   GstCaps *caps = NULL;
14273   GstVideoFormat format = GST_VIDEO_FORMAT_UNKNOWN;
14274
14275   switch (fourcc) {
14276     case FOURCC_png:
14277       _codec ("PNG still images");
14278       caps = gst_caps_new_empty_simple ("image/png");
14279       break;
14280     case FOURCC_jpeg:
14281       _codec ("JPEG still images");
14282       caps =
14283           gst_caps_new_simple ("image/jpeg", "parsed", G_TYPE_BOOLEAN, TRUE,
14284           NULL);
14285       break;
14286     case GST_MAKE_FOURCC ('m', 'j', 'p', 'a'):
14287     case GST_MAKE_FOURCC ('A', 'V', 'D', 'J'):
14288     case GST_MAKE_FOURCC ('M', 'J', 'P', 'G'):
14289     case GST_MAKE_FOURCC ('d', 'm', 'b', '1'):
14290       _codec ("Motion-JPEG");
14291       caps =
14292           gst_caps_new_simple ("image/jpeg", "parsed", G_TYPE_BOOLEAN, TRUE,
14293           NULL);
14294       break;
14295     case GST_MAKE_FOURCC ('m', 'j', 'p', 'b'):
14296       _codec ("Motion-JPEG format B");
14297       caps = gst_caps_new_empty_simple ("video/x-mjpeg-b");
14298       break;
14299     case FOURCC_mjp2:
14300       _codec ("JPEG-2000");
14301       /* override to what it should be according to spec, avoid palette_data */
14302       entry->bits_per_sample = 24;
14303       caps = gst_caps_new_simple ("image/x-j2c", "fields", G_TYPE_INT, 1, NULL);
14304       break;
14305     case FOURCC_SVQ3:
14306       _codec ("Sorensen video v.3");
14307       caps = gst_caps_new_simple ("video/x-svq",
14308           "svqversion", G_TYPE_INT, 3, NULL);
14309       break;
14310     case GST_MAKE_FOURCC ('s', 'v', 'q', 'i'):
14311     case GST_MAKE_FOURCC ('S', 'V', 'Q', '1'):
14312       _codec ("Sorensen video v.1");
14313       caps = gst_caps_new_simple ("video/x-svq",
14314           "svqversion", G_TYPE_INT, 1, NULL);
14315       break;
14316     case GST_MAKE_FOURCC ('W', 'R', 'A', 'W'):
14317       caps = gst_caps_new_empty_simple ("video/x-raw");
14318       gst_caps_set_simple (caps, "format", G_TYPE_STRING, "RGB8P", NULL);
14319       _codec ("Windows Raw RGB");
14320       stream->alignment = 32;
14321       break;
14322     case FOURCC_raw_:
14323     {
14324       guint16 bps;
14325
14326       bps = QT_UINT16 (stsd_entry_data + 82);
14327       switch (bps) {
14328         case 15:
14329           format = GST_VIDEO_FORMAT_RGB15;
14330           break;
14331         case 16:
14332           format = GST_VIDEO_FORMAT_RGB16;
14333           break;
14334         case 24:
14335           format = GST_VIDEO_FORMAT_RGB;
14336           break;
14337         case 32:
14338           format = GST_VIDEO_FORMAT_ARGB;
14339           break;
14340         default:
14341           /* unknown */
14342           break;
14343       }
14344       break;
14345     }
14346     case GST_MAKE_FOURCC ('y', 'v', '1', '2'):
14347       format = GST_VIDEO_FORMAT_I420;
14348       break;
14349     case GST_MAKE_FOURCC ('y', 'u', 'v', '2'):
14350     case GST_MAKE_FOURCC ('Y', 'u', 'v', '2'):
14351       format = GST_VIDEO_FORMAT_I420;
14352       break;
14353     case FOURCC_2vuy:
14354     case GST_MAKE_FOURCC ('2', 'V', 'u', 'y'):
14355       format = GST_VIDEO_FORMAT_UYVY;
14356       break;
14357     case GST_MAKE_FOURCC ('v', '3', '0', '8'):
14358       format = GST_VIDEO_FORMAT_v308;
14359       break;
14360     case GST_MAKE_FOURCC ('v', '2', '1', '6'):
14361       format = GST_VIDEO_FORMAT_v216;
14362       break;
14363     case FOURCC_v210:
14364       format = GST_VIDEO_FORMAT_v210;
14365       break;
14366     case GST_MAKE_FOURCC ('r', '2', '1', '0'):
14367       format = GST_VIDEO_FORMAT_r210;
14368       break;
14369       /* Packed YUV 4:4:4 10 bit in 32 bits, complex
14370          case GST_MAKE_FOURCC ('v', '4', '1', '0'):
14371          format = GST_VIDEO_FORMAT_v410;
14372          break;
14373        */
14374       /* Packed YUV 4:4:4:4 8 bit in 32 bits
14375        * but different order than AYUV
14376        case GST_MAKE_FOURCC ('v', '4', '0', '8'):
14377        format = GST_VIDEO_FORMAT_v408;
14378        break;
14379        */
14380     case GST_MAKE_FOURCC ('m', 'p', 'e', 'g'):
14381     case GST_MAKE_FOURCC ('m', 'p', 'g', '1'):
14382       _codec ("MPEG-1 video");
14383       caps = gst_caps_new_simple ("video/mpeg", "mpegversion", G_TYPE_INT, 1,
14384           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
14385       break;
14386     case GST_MAKE_FOURCC ('h', 'd', 'v', '1'): /* HDV 720p30 */
14387     case GST_MAKE_FOURCC ('h', 'd', 'v', '2'): /* HDV 1080i60 */
14388     case GST_MAKE_FOURCC ('h', 'd', 'v', '3'): /* HDV 1080i50 */
14389     case GST_MAKE_FOURCC ('h', 'd', 'v', '4'): /* HDV 720p24 */
14390     case GST_MAKE_FOURCC ('h', 'd', 'v', '5'): /* HDV 720p25 */
14391     case GST_MAKE_FOURCC ('h', 'd', 'v', '6'): /* HDV 1080p24 */
14392     case GST_MAKE_FOURCC ('h', 'd', 'v', '7'): /* HDV 1080p25 */
14393     case GST_MAKE_FOURCC ('h', 'd', 'v', '8'): /* HDV 1080p30 */
14394     case GST_MAKE_FOURCC ('h', 'd', 'v', '9'): /* HDV 720p60 */
14395     case GST_MAKE_FOURCC ('h', 'd', 'v', 'a'): /* HDV 720p50 */
14396     case GST_MAKE_FOURCC ('m', 'x', '5', 'n'): /* MPEG2 IMX NTSC 525/60 50mb/s produced by FCP */
14397     case GST_MAKE_FOURCC ('m', 'x', '5', 'p'): /* MPEG2 IMX PAL 625/60 50mb/s produced by FCP */
14398     case GST_MAKE_FOURCC ('m', 'x', '4', 'n'): /* MPEG2 IMX NTSC 525/60 40mb/s produced by FCP */
14399     case GST_MAKE_FOURCC ('m', 'x', '4', 'p'): /* MPEG2 IMX PAL 625/60 40mb/s produced by FCP */
14400     case GST_MAKE_FOURCC ('m', 'x', '3', 'n'): /* MPEG2 IMX NTSC 525/60 30mb/s produced by FCP */
14401     case GST_MAKE_FOURCC ('m', 'x', '3', 'p'): /* MPEG2 IMX PAL 625/50 30mb/s produced by FCP */
14402     case GST_MAKE_FOURCC ('x', 'd', 'v', '1'): /* XDCAM HD 720p30 35Mb/s */
14403     case GST_MAKE_FOURCC ('x', 'd', 'v', '2'): /* XDCAM HD 1080i60 35Mb/s */
14404     case GST_MAKE_FOURCC ('x', 'd', 'v', '3'): /* XDCAM HD 1080i50 35Mb/s */
14405     case GST_MAKE_FOURCC ('x', 'd', 'v', '4'): /* XDCAM HD 720p24 35Mb/s */
14406     case GST_MAKE_FOURCC ('x', 'd', 'v', '5'): /* XDCAM HD 720p25 35Mb/s */
14407     case GST_MAKE_FOURCC ('x', 'd', 'v', '6'): /* XDCAM HD 1080p24 35Mb/s */
14408     case GST_MAKE_FOURCC ('x', 'd', 'v', '7'): /* XDCAM HD 1080p25 35Mb/s */
14409     case GST_MAKE_FOURCC ('x', 'd', 'v', '8'): /* XDCAM HD 1080p30 35Mb/s */
14410     case GST_MAKE_FOURCC ('x', 'd', 'v', '9'): /* XDCAM HD 720p60 35Mb/s */
14411     case GST_MAKE_FOURCC ('x', 'd', 'v', 'a'): /* XDCAM HD 720p50 35Mb/s */
14412     case GST_MAKE_FOURCC ('x', 'd', 'v', 'b'): /* XDCAM EX 1080i60 50Mb/s CBR */
14413     case GST_MAKE_FOURCC ('x', 'd', 'v', 'c'): /* XDCAM EX 1080i50 50Mb/s CBR */
14414     case GST_MAKE_FOURCC ('x', 'd', 'v', 'd'): /* XDCAM HD 1080p24 50Mb/s CBR */
14415     case GST_MAKE_FOURCC ('x', 'd', 'v', 'e'): /* XDCAM HD 1080p25 50Mb/s CBR */
14416     case GST_MAKE_FOURCC ('x', 'd', 'v', 'f'): /* XDCAM HD 1080p30 50Mb/s CBR */
14417     case GST_MAKE_FOURCC ('x', 'd', '5', '1'): /* XDCAM HD422 720p30 50Mb/s CBR */
14418     case GST_MAKE_FOURCC ('x', 'd', '5', '4'): /* XDCAM HD422 720p24 50Mb/s CBR */
14419     case GST_MAKE_FOURCC ('x', 'd', '5', '5'): /* XDCAM HD422 720p25 50Mb/s CBR */
14420     case GST_MAKE_FOURCC ('x', 'd', '5', '9'): /* XDCAM HD422 720p60 50Mb/s CBR */
14421     case GST_MAKE_FOURCC ('x', 'd', '5', 'a'): /* XDCAM HD422 720p50 50Mb/s CBR */
14422     case GST_MAKE_FOURCC ('x', 'd', '5', 'b'): /* XDCAM HD422 1080i50 50Mb/s CBR */
14423     case GST_MAKE_FOURCC ('x', 'd', '5', 'c'): /* XDCAM HD422 1080i50 50Mb/s CBR */
14424     case GST_MAKE_FOURCC ('x', 'd', '5', 'd'): /* XDCAM HD422 1080p24 50Mb/s CBR */
14425     case GST_MAKE_FOURCC ('x', 'd', '5', 'e'): /* XDCAM HD422 1080p25 50Mb/s CBR */
14426     case GST_MAKE_FOURCC ('x', 'd', '5', 'f'): /* XDCAM HD422 1080p30 50Mb/s CBR */
14427     case GST_MAKE_FOURCC ('x', 'd', 'h', 'd'): /* XDCAM HD 540p */
14428     case GST_MAKE_FOURCC ('x', 'd', 'h', '2'): /* XDCAM HD422 540p */
14429     case GST_MAKE_FOURCC ('A', 'V', 'm', 'p'): /* AVID IMX PAL */
14430     case GST_MAKE_FOURCC ('m', 'p', 'g', '2'): /* AVID IMX PAL */
14431     case GST_MAKE_FOURCC ('m', 'p', '2', 'v'): /* AVID IMX PAL */
14432     case GST_MAKE_FOURCC ('m', '2', 'v', '1'):
14433       _codec ("MPEG-2 video");
14434       caps = gst_caps_new_simple ("video/mpeg", "mpegversion", G_TYPE_INT, 2,
14435           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
14436       break;
14437     case GST_MAKE_FOURCC ('g', 'i', 'f', ' '):
14438       _codec ("GIF still images");
14439       caps = gst_caps_new_empty_simple ("image/gif");
14440       break;
14441     case FOURCC_h263:
14442     case GST_MAKE_FOURCC ('H', '2', '6', '3'):
14443     case FOURCC_s263:
14444     case GST_MAKE_FOURCC ('U', '2', '6', '3'):
14445       _codec ("H.263");
14446       /* ffmpeg uses the height/width props, don't know why */
14447       caps = gst_caps_new_simple ("video/x-h263",
14448           "variant", G_TYPE_STRING, "itu", NULL);
14449       break;
14450     case FOURCC_mp4v:
14451     case FOURCC_MP4V:
14452       _codec ("MPEG-4 video");
14453       caps = gst_caps_new_simple ("video/mpeg", "mpegversion", G_TYPE_INT, 4,
14454           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
14455       break;
14456     case GST_MAKE_FOURCC ('3', 'i', 'v', 'd'):
14457     case GST_MAKE_FOURCC ('3', 'I', 'V', 'D'):
14458       _codec ("Microsoft MPEG-4 4.3");  /* FIXME? */
14459       caps = gst_caps_new_simple ("video/x-msmpeg",
14460           "msmpegversion", G_TYPE_INT, 43, NULL);
14461       break;
14462     case GST_MAKE_FOURCC ('D', 'I', 'V', '3'):
14463       _codec ("DivX 3");
14464       caps = gst_caps_new_simple ("video/x-divx",
14465           "divxversion", G_TYPE_INT, 3, NULL);
14466       break;
14467     case GST_MAKE_FOURCC ('D', 'I', 'V', 'X'):
14468     case GST_MAKE_FOURCC ('d', 'i', 'v', 'x'):
14469       _codec ("DivX 4");
14470       caps = gst_caps_new_simple ("video/x-divx",
14471           "divxversion", G_TYPE_INT, 4, NULL);
14472       break;
14473     case GST_MAKE_FOURCC ('D', 'X', '5', '0'):
14474       _codec ("DivX 5");
14475       caps = gst_caps_new_simple ("video/x-divx",
14476           "divxversion", G_TYPE_INT, 5, NULL);
14477       break;
14478
14479     case GST_MAKE_FOURCC ('F', 'F', 'V', '1'):
14480       _codec ("FFV1");
14481       caps = gst_caps_new_simple ("video/x-ffv",
14482           "ffvversion", G_TYPE_INT, 1, NULL);
14483       break;
14484
14485     case GST_MAKE_FOURCC ('3', 'I', 'V', '1'):
14486     case GST_MAKE_FOURCC ('3', 'I', 'V', '2'):
14487     case FOURCC_XVID:
14488     case FOURCC_xvid:
14489     case FOURCC_FMP4:
14490     case FOURCC_fmp4:
14491     case GST_MAKE_FOURCC ('U', 'M', 'P', '4'):
14492       caps = gst_caps_new_simple ("video/mpeg", "mpegversion", G_TYPE_INT, 4,
14493           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
14494       _codec ("MPEG-4");
14495       break;
14496
14497     case GST_MAKE_FOURCC ('c', 'v', 'i', 'd'):
14498       _codec ("Cinepak");
14499       caps = gst_caps_new_empty_simple ("video/x-cinepak");
14500       break;
14501     case GST_MAKE_FOURCC ('q', 'd', 'r', 'w'):
14502       _codec ("Apple QuickDraw");
14503       caps = gst_caps_new_empty_simple ("video/x-qdrw");
14504       break;
14505     case GST_MAKE_FOURCC ('r', 'p', 'z', 'a'):
14506       _codec ("Apple video");
14507       caps = gst_caps_new_empty_simple ("video/x-apple-video");
14508       break;
14509     case FOURCC_H264:
14510     case FOURCC_avc1:
14511       _codec ("H.264 / AVC");
14512       caps = gst_caps_new_simple ("video/x-h264",
14513           "stream-format", G_TYPE_STRING, "avc",
14514           "alignment", G_TYPE_STRING, "au", NULL);
14515       break;
14516     case FOURCC_avc3:
14517       _codec ("H.264 / AVC");
14518       caps = gst_caps_new_simple ("video/x-h264",
14519           "stream-format", G_TYPE_STRING, "avc3",
14520           "alignment", G_TYPE_STRING, "au", NULL);
14521       break;
14522     case FOURCC_H265:
14523     case FOURCC_hvc1:
14524       _codec ("H.265 / HEVC");
14525       caps = gst_caps_new_simple ("video/x-h265",
14526           "stream-format", G_TYPE_STRING, "hvc1",
14527           "alignment", G_TYPE_STRING, "au", NULL);
14528       break;
14529     case FOURCC_hev1:
14530       _codec ("H.265 / HEVC");
14531       caps = gst_caps_new_simple ("video/x-h265",
14532           "stream-format", G_TYPE_STRING, "hev1",
14533           "alignment", G_TYPE_STRING, "au", NULL);
14534       break;
14535     case FOURCC_rle_:
14536       _codec ("Run-length encoding");
14537       caps = gst_caps_new_simple ("video/x-rle",
14538           "layout", G_TYPE_STRING, "quicktime", NULL);
14539       break;
14540     case FOURCC_WRLE:
14541       _codec ("Run-length encoding");
14542       caps = gst_caps_new_simple ("video/x-rle",
14543           "layout", G_TYPE_STRING, "microsoft", NULL);
14544       break;
14545     case GST_MAKE_FOURCC ('I', 'V', '3', '2'):
14546     case GST_MAKE_FOURCC ('i', 'v', '3', '2'):
14547       _codec ("Indeo Video 3");
14548       caps = gst_caps_new_simple ("video/x-indeo",
14549           "indeoversion", G_TYPE_INT, 3, NULL);
14550       break;
14551     case GST_MAKE_FOURCC ('I', 'V', '4', '1'):
14552     case GST_MAKE_FOURCC ('i', 'v', '4', '1'):
14553       _codec ("Intel Video 4");
14554       caps = gst_caps_new_simple ("video/x-indeo",
14555           "indeoversion", G_TYPE_INT, 4, NULL);
14556       break;
14557     case FOURCC_dvcp:
14558     case FOURCC_dvc_:
14559     case GST_MAKE_FOURCC ('d', 'v', 's', 'd'):
14560     case GST_MAKE_FOURCC ('D', 'V', 'S', 'D'):
14561     case GST_MAKE_FOURCC ('d', 'v', 'c', 's'):
14562     case GST_MAKE_FOURCC ('D', 'V', 'C', 'S'):
14563     case GST_MAKE_FOURCC ('d', 'v', '2', '5'):
14564     case GST_MAKE_FOURCC ('d', 'v', 'p', 'p'):
14565       _codec ("DV Video");
14566       caps = gst_caps_new_simple ("video/x-dv", "dvversion", G_TYPE_INT, 25,
14567           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
14568       break;
14569     case FOURCC_dv5n:          /* DVCPRO50 NTSC */
14570     case FOURCC_dv5p:          /* DVCPRO50 PAL */
14571       _codec ("DVCPro50 Video");
14572       caps = gst_caps_new_simple ("video/x-dv", "dvversion", G_TYPE_INT, 50,
14573           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
14574       break;
14575     case GST_MAKE_FOURCC ('d', 'v', 'h', '5'): /* DVCPRO HD 50i produced by FCP */
14576     case GST_MAKE_FOURCC ('d', 'v', 'h', '6'): /* DVCPRO HD 60i produced by FCP */
14577       _codec ("DVCProHD Video");
14578       caps = gst_caps_new_simple ("video/x-dv", "dvversion", G_TYPE_INT, 100,
14579           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
14580       break;
14581     case GST_MAKE_FOURCC ('s', 'm', 'c', ' '):
14582       _codec ("Apple Graphics (SMC)");
14583       caps = gst_caps_new_empty_simple ("video/x-smc");
14584       break;
14585     case GST_MAKE_FOURCC ('V', 'P', '3', '1'):
14586       _codec ("VP3");
14587       caps = gst_caps_new_empty_simple ("video/x-vp3");
14588       break;
14589     case GST_MAKE_FOURCC ('V', 'P', '6', 'F'):
14590       _codec ("VP6 Flash");
14591       caps = gst_caps_new_empty_simple ("video/x-vp6-flash");
14592       break;
14593     case FOURCC_XiTh:
14594       _codec ("Theora");
14595       caps = gst_caps_new_empty_simple ("video/x-theora");
14596       /* theora uses one byte of padding in the data stream because it does not
14597        * allow 0 sized packets while theora does */
14598       entry->padding = 1;
14599       break;
14600     case FOURCC_drac:
14601       _codec ("Dirac");
14602       caps = gst_caps_new_empty_simple ("video/x-dirac");
14603       break;
14604     case GST_MAKE_FOURCC ('t', 'i', 'f', 'f'):
14605       _codec ("TIFF still images");
14606       caps = gst_caps_new_empty_simple ("image/tiff");
14607       break;
14608     case GST_MAKE_FOURCC ('i', 'c', 'o', 'd'):
14609       _codec ("Apple Intermediate Codec");
14610       caps = gst_caps_from_string ("video/x-apple-intermediate-codec");
14611       break;
14612     case GST_MAKE_FOURCC ('A', 'V', 'd', 'n'):
14613       _codec ("AVID DNxHD");
14614       caps = gst_caps_from_string ("video/x-dnxhd");
14615       break;
14616     case FOURCC_VP80:
14617     case FOURCC_vp08:
14618       _codec ("On2 VP8");
14619       caps = gst_caps_from_string ("video/x-vp8");
14620       break;
14621     case FOURCC_vp09:
14622       _codec ("Google VP9");
14623       caps = gst_caps_from_string ("video/x-vp9");
14624       break;
14625     case FOURCC_apcs:
14626       _codec ("Apple ProRes LT");
14627       caps =
14628           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING, "lt",
14629           NULL);
14630       break;
14631     case FOURCC_apch:
14632       _codec ("Apple ProRes HQ");
14633       caps =
14634           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING, "hq",
14635           NULL);
14636       break;
14637     case FOURCC_apcn:
14638       _codec ("Apple ProRes");
14639       caps =
14640           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING,
14641           "standard", NULL);
14642       break;
14643     case FOURCC_apco:
14644       _codec ("Apple ProRes Proxy");
14645       caps =
14646           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING,
14647           "proxy", NULL);
14648       break;
14649     case FOURCC_ap4h:
14650       _codec ("Apple ProRes 4444");
14651       caps =
14652           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING,
14653           "4444", NULL);
14654       break;
14655     case FOURCC_ap4x:
14656       _codec ("Apple ProRes 4444 XQ");
14657       caps =
14658           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING,
14659           "4444xq", NULL);
14660       break;
14661     case FOURCC_cfhd:
14662       _codec ("GoPro CineForm");
14663       caps = gst_caps_from_string ("video/x-cineform");
14664       break;
14665     case FOURCC_vc_1:
14666     case FOURCC_ovc1:
14667       _codec ("VC-1");
14668       caps = gst_caps_new_simple ("video/x-wmv",
14669           "wmvversion", G_TYPE_INT, 3, "format", G_TYPE_STRING, "WVC1", NULL);
14670       break;
14671     case GST_MAKE_FOURCC ('k', 'p', 'c', 'd'):
14672     default:
14673     {
14674       caps = _get_unknown_codec_name ("video", fourcc);
14675       break;
14676     }
14677   }
14678
14679   if (format != GST_VIDEO_FORMAT_UNKNOWN) {
14680     GstVideoInfo info;
14681
14682     gst_video_info_init (&info);
14683     gst_video_info_set_format (&info, format, entry->width, entry->height);
14684
14685     caps = gst_video_info_to_caps (&info);
14686     *codec_name = gst_pb_utils_get_codec_description (caps);
14687
14688     /* enable clipping for raw video streams */
14689     stream->need_clip = TRUE;
14690     stream->alignment = 32;
14691   }
14692
14693   return caps;
14694 }
14695
14696 static guint
14697 round_up_pow2 (guint n)
14698 {
14699   n = n - 1;
14700   n = n | (n >> 1);
14701   n = n | (n >> 2);
14702   n = n | (n >> 4);
14703   n = n | (n >> 8);
14704   n = n | (n >> 16);
14705   return n + 1;
14706 }
14707
14708 static GstCaps *
14709 qtdemux_audio_caps (GstQTDemux * qtdemux, QtDemuxStream * stream,
14710     QtDemuxStreamStsdEntry * entry, guint32 fourcc, const guint8 * data,
14711     int len, gchar ** codec_name)
14712 {
14713   GstCaps *caps;
14714   const GstStructure *s;
14715   const gchar *name;
14716   gint endian = 0;
14717   GstAudioFormat format = 0;
14718   gint depth;
14719
14720   GST_DEBUG_OBJECT (qtdemux, "resolve fourcc 0x%08x", GUINT32_TO_BE (fourcc));
14721
14722   depth = entry->bytes_per_packet * 8;
14723
14724   switch (fourcc) {
14725     case GST_MAKE_FOURCC ('N', 'O', 'N', 'E'):
14726     case FOURCC_raw_:
14727       /* 8-bit audio is unsigned */
14728       if (depth == 8)
14729         format = GST_AUDIO_FORMAT_U8;
14730       /* otherwise it's signed and big-endian just like 'twos' */
14731     case FOURCC_twos:
14732       endian = G_BIG_ENDIAN;
14733       /* fall-through */
14734     case FOURCC_sowt:
14735     {
14736       gchar *str;
14737
14738       if (!endian)
14739         endian = G_LITTLE_ENDIAN;
14740
14741       if (!format)
14742         format = gst_audio_format_build_integer (TRUE, endian, depth, depth);
14743
14744       str = g_strdup_printf ("Raw %d-bit PCM audio", depth);
14745       _codec (str);
14746       g_free (str);
14747
14748       caps = gst_caps_new_simple ("audio/x-raw",
14749           "format", G_TYPE_STRING, gst_audio_format_to_string (format),
14750           "layout", G_TYPE_STRING, "interleaved", NULL);
14751       stream->alignment = GST_ROUND_UP_8 (depth);
14752       stream->alignment = round_up_pow2 (stream->alignment);
14753       break;
14754     }
14755     case GST_MAKE_FOURCC ('f', 'l', '6', '4'):
14756       _codec ("Raw 64-bit floating-point audio");
14757       caps = gst_caps_new_simple ("audio/x-raw",
14758           "format", G_TYPE_STRING, "F64BE",
14759           "layout", G_TYPE_STRING, "interleaved", NULL);
14760       stream->alignment = 8;
14761       break;
14762     case GST_MAKE_FOURCC ('f', 'l', '3', '2'):
14763       _codec ("Raw 32-bit floating-point audio");
14764       caps = gst_caps_new_simple ("audio/x-raw",
14765           "format", G_TYPE_STRING, "F32BE",
14766           "layout", G_TYPE_STRING, "interleaved", NULL);
14767       stream->alignment = 4;
14768       break;
14769     case FOURCC_in24:
14770       _codec ("Raw 24-bit PCM audio");
14771       /* we assume BIG ENDIAN, an enda box will tell us to change this to little
14772        * endian later */
14773       caps = gst_caps_new_simple ("audio/x-raw",
14774           "format", G_TYPE_STRING, "S24BE",
14775           "layout", G_TYPE_STRING, "interleaved", NULL);
14776       stream->alignment = 4;
14777       break;
14778     case GST_MAKE_FOURCC ('i', 'n', '3', '2'):
14779       _codec ("Raw 32-bit PCM audio");
14780       caps = gst_caps_new_simple ("audio/x-raw",
14781           "format", G_TYPE_STRING, "S32BE",
14782           "layout", G_TYPE_STRING, "interleaved", NULL);
14783       stream->alignment = 4;
14784       break;
14785     case GST_MAKE_FOURCC ('s', '1', '6', 'l'):
14786       _codec ("Raw 16-bit PCM audio");
14787       caps = gst_caps_new_simple ("audio/x-raw",
14788           "format", G_TYPE_STRING, "S16LE",
14789           "layout", G_TYPE_STRING, "interleaved", NULL);
14790       stream->alignment = 2;
14791       break;
14792     case FOURCC_ulaw:
14793       _codec ("Mu-law audio");
14794       caps = gst_caps_new_empty_simple ("audio/x-mulaw");
14795       break;
14796     case FOURCC_alaw:
14797       _codec ("A-law audio");
14798       caps = gst_caps_new_empty_simple ("audio/x-alaw");
14799       break;
14800     case 0x0200736d:
14801     case 0x6d730002:
14802       _codec ("Microsoft ADPCM");
14803       /* Microsoft ADPCM-ACM code 2 */
14804       caps = gst_caps_new_simple ("audio/x-adpcm",
14805           "layout", G_TYPE_STRING, "microsoft", NULL);
14806       break;
14807     case 0x1100736d:
14808     case 0x6d730011:
14809       _codec ("DVI/IMA ADPCM");
14810       caps = gst_caps_new_simple ("audio/x-adpcm",
14811           "layout", G_TYPE_STRING, "dvi", NULL);
14812       break;
14813     case 0x1700736d:
14814     case 0x6d730017:
14815       _codec ("DVI/Intel IMA ADPCM");
14816       /* FIXME DVI/Intel IMA ADPCM/ACM code 17 */
14817       caps = gst_caps_new_simple ("audio/x-adpcm",
14818           "layout", G_TYPE_STRING, "quicktime", NULL);
14819       break;
14820     case 0x5500736d:
14821     case 0x6d730055:
14822       /* MPEG layer 3, CBR only (pre QT4.1) */
14823     case FOURCC__mp3:
14824       _codec ("MPEG-1 layer 3");
14825       /* MPEG layer 3, CBR & VBR (QT4.1 and later) */
14826       caps = gst_caps_new_simple ("audio/mpeg", "layer", G_TYPE_INT, 3,
14827           "mpegversion", G_TYPE_INT, 1, NULL);
14828       break;
14829     case GST_MAKE_FOURCC ('.', 'm', 'p', '2'):
14830       _codec ("MPEG-1 layer 2");
14831       /* MPEG layer 2 */
14832       caps = gst_caps_new_simple ("audio/mpeg", "layer", G_TYPE_INT, 2,
14833           "mpegversion", G_TYPE_INT, 1, NULL);
14834       break;
14835     case 0x20736d:
14836     case GST_MAKE_FOURCC ('e', 'c', '-', '3'):
14837       _codec ("EAC-3 audio");
14838       caps = gst_caps_new_simple ("audio/x-eac3",
14839           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
14840       entry->sampled = TRUE;
14841       break;
14842     case GST_MAKE_FOURCC ('s', 'a', 'c', '3'): // Nero Recode
14843     case FOURCC_ac_3:
14844       _codec ("AC-3 audio");
14845       caps = gst_caps_new_simple ("audio/x-ac3",
14846           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
14847       entry->sampled = TRUE;
14848       break;
14849     case GST_MAKE_FOURCC ('d', 't', 's', 'c'):
14850     case GST_MAKE_FOURCC ('D', 'T', 'S', ' '):
14851       _codec ("DTS audio");
14852       caps = gst_caps_new_simple ("audio/x-dts",
14853           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
14854       entry->sampled = TRUE;
14855       break;
14856     case GST_MAKE_FOURCC ('d', 't', 's', 'h'): // DTS-HD
14857     case GST_MAKE_FOURCC ('d', 't', 's', 'l'): // DTS-HD Lossless
14858       _codec ("DTS-HD audio");
14859       caps = gst_caps_new_simple ("audio/x-dts",
14860           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
14861       entry->sampled = TRUE;
14862       break;
14863     case FOURCC_MAC3:
14864       _codec ("MACE-3");
14865       caps = gst_caps_new_simple ("audio/x-mace",
14866           "maceversion", G_TYPE_INT, 3, NULL);
14867       break;
14868     case FOURCC_MAC6:
14869       _codec ("MACE-6");
14870       caps = gst_caps_new_simple ("audio/x-mace",
14871           "maceversion", G_TYPE_INT, 6, NULL);
14872       break;
14873     case GST_MAKE_FOURCC ('O', 'g', 'g', 'V'):
14874       /* ogg/vorbis */
14875       caps = gst_caps_new_empty_simple ("application/ogg");
14876       break;
14877     case GST_MAKE_FOURCC ('d', 'v', 'c', 'a'):
14878       _codec ("DV audio");
14879       caps = gst_caps_new_empty_simple ("audio/x-dv");
14880       break;
14881     case FOURCC_mp4a:
14882       _codec ("MPEG-4 AAC audio");
14883       caps = gst_caps_new_simple ("audio/mpeg",
14884           "mpegversion", G_TYPE_INT, 4, "framed", G_TYPE_BOOLEAN, TRUE,
14885           "stream-format", G_TYPE_STRING, "raw", NULL);
14886       break;
14887     case GST_MAKE_FOURCC ('Q', 'D', 'M', 'C'):
14888       _codec ("QDesign Music");
14889       caps = gst_caps_new_empty_simple ("audio/x-qdm");
14890       break;
14891     case FOURCC_QDM2:
14892       _codec ("QDesign Music v.2");
14893       /* FIXME: QDesign music version 2 (no constant) */
14894       if (FALSE && data) {
14895         caps = gst_caps_new_simple ("audio/x-qdm2",
14896             "framesize", G_TYPE_INT, QT_UINT32 (data + 52),
14897             "bitrate", G_TYPE_INT, QT_UINT32 (data + 40),
14898             "blocksize", G_TYPE_INT, QT_UINT32 (data + 44), NULL);
14899       } else {
14900         caps = gst_caps_new_empty_simple ("audio/x-qdm2");
14901       }
14902       break;
14903     case FOURCC_agsm:
14904       _codec ("GSM audio");
14905       caps = gst_caps_new_empty_simple ("audio/x-gsm");
14906       break;
14907     case FOURCC_samr:
14908       _codec ("AMR audio");
14909       caps = gst_caps_new_empty_simple ("audio/AMR");
14910       break;
14911     case FOURCC_sawb:
14912       _codec ("AMR-WB audio");
14913       caps = gst_caps_new_empty_simple ("audio/AMR-WB");
14914       break;
14915     case FOURCC_ima4:
14916       _codec ("Quicktime IMA ADPCM");
14917       caps = gst_caps_new_simple ("audio/x-adpcm",
14918           "layout", G_TYPE_STRING, "quicktime", NULL);
14919       break;
14920     case FOURCC_alac:
14921       _codec ("Apple lossless audio");
14922       caps = gst_caps_new_empty_simple ("audio/x-alac");
14923       break;
14924     case FOURCC_fLaC:
14925       _codec ("Free Lossless Audio Codec");
14926       caps = gst_caps_new_simple ("audio/x-flac",
14927           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
14928       break;
14929     case GST_MAKE_FOURCC ('Q', 'c', 'l', 'p'):
14930       _codec ("QualComm PureVoice");
14931       caps = gst_caps_from_string ("audio/qcelp");
14932       break;
14933     case FOURCC_wma_:
14934     case FOURCC_owma:
14935       _codec ("WMA");
14936       caps = gst_caps_new_empty_simple ("audio/x-wma");
14937       break;
14938     case FOURCC_opus:
14939       _codec ("Opus");
14940       caps = gst_caps_new_empty_simple ("audio/x-opus");
14941       break;
14942     case FOURCC_lpcm:
14943     {
14944       guint32 flags = 0;
14945       guint32 depth = 0;
14946       guint32 width = 0;
14947       GstAudioFormat format;
14948       enum
14949       {
14950         FLAG_IS_FLOAT = 0x1,
14951         FLAG_IS_BIG_ENDIAN = 0x2,
14952         FLAG_IS_SIGNED = 0x4,
14953         FLAG_IS_PACKED = 0x8,
14954         FLAG_IS_ALIGNED_HIGH = 0x10,
14955         FLAG_IS_NON_INTERLEAVED = 0x20
14956       };
14957       _codec ("Raw LPCM audio");
14958
14959       if (data && len >= 36) {
14960         depth = QT_UINT32 (data + 24);
14961         flags = QT_UINT32 (data + 28);
14962         width = QT_UINT32 (data + 32) * 8 / entry->n_channels;
14963       }
14964       if ((flags & FLAG_IS_FLOAT) == 0) {
14965         if (depth == 0)
14966           depth = 16;
14967         if (width == 0)
14968           width = 16;
14969         if ((flags & FLAG_IS_ALIGNED_HIGH))
14970           depth = width;
14971
14972         format = gst_audio_format_build_integer ((flags & FLAG_IS_SIGNED) ?
14973             TRUE : FALSE, (flags & FLAG_IS_BIG_ENDIAN) ?
14974             G_BIG_ENDIAN : G_LITTLE_ENDIAN, width, depth);
14975         caps = gst_caps_new_simple ("audio/x-raw",
14976             "format", G_TYPE_STRING,
14977             format !=
14978             GST_AUDIO_FORMAT_UNKNOWN ? gst_audio_format_to_string (format) :
14979             "UNKNOWN", "layout", G_TYPE_STRING,
14980             (flags & FLAG_IS_NON_INTERLEAVED) ? "non-interleaved" :
14981             "interleaved", NULL);
14982         stream->alignment = GST_ROUND_UP_8 (depth);
14983         stream->alignment = round_up_pow2 (stream->alignment);
14984       } else {
14985         if (width == 0)
14986           width = 32;
14987         if (width == 64) {
14988           if (flags & FLAG_IS_BIG_ENDIAN)
14989             format = GST_AUDIO_FORMAT_F64BE;
14990           else
14991             format = GST_AUDIO_FORMAT_F64LE;
14992         } else {
14993           if (flags & FLAG_IS_BIG_ENDIAN)
14994             format = GST_AUDIO_FORMAT_F32BE;
14995           else
14996             format = GST_AUDIO_FORMAT_F32LE;
14997         }
14998         caps = gst_caps_new_simple ("audio/x-raw",
14999             "format", G_TYPE_STRING, gst_audio_format_to_string (format),
15000             "layout", G_TYPE_STRING, (flags & FLAG_IS_NON_INTERLEAVED) ?
15001             "non-interleaved" : "interleaved", NULL);
15002         stream->alignment = width / 8;
15003       }
15004       break;
15005     }
15006     case GST_MAKE_FOURCC ('q', 't', 'v', 'r'):
15007       /* ? */
15008     default:
15009     {
15010       caps = _get_unknown_codec_name ("audio", fourcc);
15011       break;
15012     }
15013   }
15014
15015   if (caps) {
15016     GstCaps *templ_caps =
15017         gst_static_pad_template_get_caps (&gst_qtdemux_audiosrc_template);
15018     GstCaps *intersection = gst_caps_intersect (caps, templ_caps);
15019     gst_caps_unref (caps);
15020     gst_caps_unref (templ_caps);
15021     caps = intersection;
15022   }
15023
15024   /* enable clipping for raw audio streams */
15025   s = gst_caps_get_structure (caps, 0);
15026   name = gst_structure_get_name (s);
15027   if (g_str_has_prefix (name, "audio/x-raw")) {
15028     stream->need_clip = TRUE;
15029     stream->max_buffer_size = 4096 * entry->bytes_per_frame;
15030     GST_DEBUG ("setting max buffer size to %d", stream->max_buffer_size);
15031   }
15032   return caps;
15033 }
15034
15035 static GstCaps *
15036 qtdemux_sub_caps (GstQTDemux * qtdemux, QtDemuxStream * stream,
15037     QtDemuxStreamStsdEntry * entry, guint32 fourcc,
15038     const guint8 * stsd_entry_data, gchar ** codec_name)
15039 {
15040   GstCaps *caps;
15041
15042   GST_DEBUG_OBJECT (qtdemux, "resolve fourcc 0x%08x", GUINT32_TO_BE (fourcc));
15043
15044   switch (fourcc) {
15045     case FOURCC_mp4s:
15046       _codec ("DVD subtitle");
15047       caps = gst_caps_new_empty_simple ("subpicture/x-dvd");
15048       stream->need_process = TRUE;
15049       break;
15050     case FOURCC_text:
15051       _codec ("Quicktime timed text");
15052       goto text;
15053     case FOURCC_tx3g:
15054       _codec ("3GPP timed text");
15055     text:
15056       caps = gst_caps_new_simple ("text/x-raw", "format", G_TYPE_STRING,
15057           "utf8", NULL);
15058       /* actual text piece needs to be extracted */
15059       stream->need_process = TRUE;
15060       break;
15061     case FOURCC_stpp:
15062       _codec ("XML subtitles");
15063       caps = gst_caps_new_empty_simple ("application/ttml+xml");
15064       break;
15065     case FOURCC_c608:
15066       _codec ("CEA 608 Closed Caption");
15067       caps =
15068           gst_caps_new_simple ("closedcaption/x-cea-608", "format",
15069           G_TYPE_STRING, "cc_data", NULL);
15070       stream->need_process = TRUE;
15071       break;
15072     case FOURCC_c708:
15073       _codec ("CEA 708 Closed Caption");
15074       caps =
15075           gst_caps_new_simple ("closedcaption/x-cea-708", "format",
15076           G_TYPE_STRING, "cdp", NULL);
15077       stream->need_process = TRUE;
15078       break;
15079
15080     default:
15081     {
15082       caps = _get_unknown_codec_name ("text", fourcc);
15083       break;
15084     }
15085   }
15086   return caps;
15087 }
15088
15089 static GstCaps *
15090 qtdemux_generic_caps (GstQTDemux * qtdemux, QtDemuxStream * stream,
15091     QtDemuxStreamStsdEntry * entry, guint32 fourcc,
15092     const guint8 * stsd_entry_data, gchar ** codec_name)
15093 {
15094   GstCaps *caps;
15095
15096   switch (fourcc) {
15097     case FOURCC_m1v:
15098       _codec ("MPEG 1 video");
15099       caps = gst_caps_new_simple ("video/mpeg", "mpegversion", G_TYPE_INT, 1,
15100           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
15101       break;
15102     default:
15103       caps = NULL;
15104       break;
15105   }
15106   return caps;
15107 }
15108
15109 static void
15110 gst_qtdemux_append_protection_system_id (GstQTDemux * qtdemux,
15111     const gchar * system_id)
15112 {
15113   gint i;
15114
15115   if (!qtdemux->protection_system_ids)
15116     qtdemux->protection_system_ids =
15117         g_ptr_array_new_with_free_func ((GDestroyNotify) g_free);
15118   /* Check whether we already have an entry for this system ID. */
15119   for (i = 0; i < qtdemux->protection_system_ids->len; ++i) {
15120     const gchar *id = g_ptr_array_index (qtdemux->protection_system_ids, i);
15121     if (g_ascii_strcasecmp (system_id, id) == 0) {
15122       return;
15123     }
15124   }
15125   GST_DEBUG_OBJECT (qtdemux, "Adding cenc protection system ID %s", system_id);
15126   g_ptr_array_add (qtdemux->protection_system_ids, g_ascii_strdown (system_id,
15127           -1));
15128 }