cf15fad46df0fd65fb444d4710de4a666ad780bf
[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_STREAM(s) ((QtDemuxStream *)(s))
101 #define QTDEMUX_N_STREAMS(demux) ((demux)->active_streams->len)
102 #define QTDEMUX_NTH_STREAM(demux,idx) \
103    QTDEMUX_STREAM(g_ptr_array_index((demux)->active_streams,idx))
104 #define QTDEMUX_NTH_OLD_STREAM(demux,idx) \
105    QTDEMUX_STREAM(g_ptr_array_index((demux)->old_streams,idx))
106
107 GST_DEBUG_CATEGORY (qtdemux_debug);
108 #define GST_CAT_DEFAULT qtdemux_debug
109
110 typedef struct _QtDemuxSegment QtDemuxSegment;
111 typedef struct _QtDemuxSample QtDemuxSample;
112
113 typedef struct _QtDemuxCencSampleSetInfo QtDemuxCencSampleSetInfo;
114
115 struct _QtDemuxSample
116 {
117   guint32 size;
118   gint32 pts_offset;            /* Add this value to timestamp to get the pts */
119   guint64 offset;
120   guint64 timestamp;            /* DTS In mov time */
121   guint32 duration;             /* In mov time */
122   gboolean keyframe;            /* TRUE when this packet is a keyframe */
123 };
124
125 /* Macros for converting to/from timescale */
126 #define QTSTREAMTIME_TO_GSTTIME(stream, value) (gst_util_uint64_scale((value), GST_SECOND, (stream)->timescale))
127 #define GSTTIME_TO_QTSTREAMTIME(stream, value) (gst_util_uint64_scale((value), (stream)->timescale, GST_SECOND))
128
129 #define QTTIME_TO_GSTTIME(qtdemux, value) (gst_util_uint64_scale((value), GST_SECOND, (qtdemux)->timescale))
130 #define GSTTIME_TO_QTTIME(qtdemux, value) (gst_util_uint64_scale((value), (qtdemux)->timescale, GST_SECOND))
131
132 /* timestamp is the DTS */
133 #define QTSAMPLE_DTS(stream,sample) (QTSTREAMTIME_TO_GSTTIME((stream), (sample)->timestamp))
134 /* timestamp + offset + cslg_shift is the outgoing PTS */
135 #define QTSAMPLE_PTS(stream,sample) (QTSTREAMTIME_TO_GSTTIME((stream), (sample)->timestamp + (stream)->cslg_shift + (sample)->pts_offset))
136 /* timestamp + offset is the PTS used for internal seek calcuations */
137 #define QTSAMPLE_PTS_NO_CSLG(stream,sample) (QTSTREAMTIME_TO_GSTTIME((stream), (sample)->timestamp + (sample)->pts_offset))
138 /* timestamp + duration - dts is the duration */
139 #define QTSAMPLE_DUR_DTS(stream, sample, dts) (QTSTREAMTIME_TO_GSTTIME ((stream), (sample)->timestamp + (sample)->duration) - (dts))
140
141 #define QTSAMPLE_KEYFRAME(stream,sample) ((stream)->all_keyframe || (sample)->keyframe)
142
143 #define QTDEMUX_EXPOSE_GET_LOCK(demux) (&((demux)->expose_lock))
144 #define QTDEMUX_EXPOSE_LOCK(demux) G_STMT_START { \
145     GST_TRACE("Locking from thread %p", g_thread_self()); \
146     g_mutex_lock (QTDEMUX_EXPOSE_GET_LOCK (demux)); \
147     GST_TRACE("Locked from thread %p", g_thread_self()); \
148  } G_STMT_END
149
150 #define QTDEMUX_EXPOSE_UNLOCK(demux) G_STMT_START { \
151     GST_TRACE("Unlocking from thread %p", g_thread_self()); \
152     g_mutex_unlock (QTDEMUX_EXPOSE_GET_LOCK (demux)); \
153  } G_STMT_END
154
155 /*
156  * Quicktime has tracks and segments. A track is a continuous piece of
157  * multimedia content. The track is not always played from start to finish but
158  * instead, pieces of the track are 'cut out' and played in sequence. This is
159  * what the segments do.
160  *
161  * Inside the track we have keyframes (K) and delta frames. The track has its
162  * own timing, which starts from 0 and extends to end. The position in the track
163  * is called the media_time.
164  *
165  * The segments now describe the pieces that should be played from this track
166  * and are basically tuples of media_time/duration/rate entries. We can have
167  * multiple segments and they are all played after one another. An example:
168  *
169  * segment 1: media_time: 1 second, duration: 1 second, rate 1
170  * segment 2: media_time: 3 second, duration: 2 second, rate 2
171  *
172  * To correctly play back this track, one must play: 1 second of media starting
173  * from media_time 1 followed by 2 seconds of media starting from media_time 3
174  * at a rate of 2.
175  *
176  * Each of the segments will be played at a specific time, the first segment at
177  * time 0, the second one after the duration of the first one, etc.. Note that
178  * the time in resulting playback is not identical to the media_time of the
179  * track anymore.
180  *
181  * Visually, assuming the track has 4 second of media_time:
182  *
183  *                (a)                   (b)          (c)              (d)
184  *         .-----------------------------------------------------------.
185  * track:  | K.....K.........K........K.......K.......K...........K... |
186  *         '-----------------------------------------------------------'
187  *         0              1              2              3              4
188  *           .------------^              ^   .----------^              ^
189  *          /              .-------------'  /       .------------------'
190  *         /              /          .-----'       /
191  *         .--------------.         .--------------.
192  *         | segment 1    |         | segment 2    |
193  *         '--------------'         '--------------'
194  *
195  * The challenge here is to cut out the right pieces of the track for each of
196  * the playback segments. This fortunately can easily be done with the SEGMENT
197  * events of GStreamer.
198  *
199  * For playback of segment 1, we need to provide the decoder with the keyframe
200  * (a), in the above figure, but we must instruct it only to output the decoded
201  * data between second 1 and 2. We do this with a SEGMENT event for 1 to 2, time
202  * position set to the time of the segment: 0.
203  *
204  * We then proceed to push data from keyframe (a) to frame (b). The decoder
205  * decodes but clips all before media_time 1.
206  *
207  * After finishing a segment, we push out a new SEGMENT event with the clipping
208  * boundaries of the new data.
209  *
210  * This is a good usecase for the GStreamer accumulated SEGMENT events.
211  */
212
213 struct _QtDemuxSegment
214 {
215   /* global time and duration, all gst time */
216   GstClockTime time;
217   GstClockTime stop_time;
218   GstClockTime duration;
219   /* media time of trak, all gst time */
220   GstClockTime media_start;
221   GstClockTime media_stop;
222   gdouble rate;
223   /* Media start time in trak timescale units */
224   guint32 trak_media_start;
225 };
226
227 #define QTSEGMENT_IS_EMPTY(s) ((s)->media_start == GST_CLOCK_TIME_NONE)
228
229 /* Used with fragmented MP4 files (mfra atom) */
230 typedef struct
231 {
232   GstClockTime ts;
233   guint64 moof_offset;
234 } QtDemuxRandomAccessEntry;
235
236 typedef struct _QtDemuxStreamStsdEntry
237 {
238   GstCaps *caps;
239   guint32 fourcc;
240   gboolean sparse;
241
242   /* video info */
243   gint width;
244   gint height;
245   gint par_w;
246   gint par_h;
247   /* Numerator/denominator framerate */
248   gint fps_n;
249   gint fps_d;
250   GstVideoColorimetry colorimetry;
251   guint16 bits_per_sample;
252   guint16 color_table_id;
253   GstMemory *rgb8_palette;
254   guint interlace_mode;
255   guint field_order;
256
257   /* audio info */
258   gdouble rate;
259   gint n_channels;
260   guint samples_per_packet;
261   guint samples_per_frame;
262   guint bytes_per_packet;
263   guint bytes_per_sample;
264   guint bytes_per_frame;
265   guint compression;
266
267   /* if we use chunks or samples */
268   gboolean sampled;
269   guint padding;
270
271 } QtDemuxStreamStsdEntry;
272
273 #define CUR_STREAM(s) (&((s)->stsd_entries[(s)->cur_stsd_entry_index]))
274
275 struct _QtDemuxStream
276 {
277   GstPad *pad;
278
279   GstQTDemux *demux;
280   gchar *stream_id;
281
282   QtDemuxStreamStsdEntry *stsd_entries;
283   guint stsd_entries_length;
284   guint cur_stsd_entry_index;
285
286   /* stream type */
287   guint32 subtype;
288
289   gboolean new_caps;            /* If TRUE, caps need to be generated (by
290                                  * calling _configure_stream()) This happens
291                                  * for MSS and fragmented streams */
292
293   gboolean new_stream;          /* signals that a stream_start is required */
294   gboolean on_keyframe;         /* if this stream last pushed buffer was a
295                                  * keyframe. This is important to identify
296                                  * where to stop pushing buffers after a
297                                  * segment stop time */
298
299   /* if the stream has a redirect URI in its headers, we store it here */
300   gchar *redirect_uri;
301
302   /* track id */
303   guint track_id;
304
305   /* duration/scale */
306   guint64 duration;             /* in timescale units */
307   guint32 timescale;
308
309   /* language */
310   gchar lang_id[4];             /* ISO 639-2T language code */
311
312   /* our samples */
313   guint32 n_samples;
314   QtDemuxSample *samples;
315   gboolean all_keyframe;        /* TRUE when all samples are keyframes (no stss) */
316   guint32 n_samples_moof;       /* sample count in a moof */
317   guint64 duration_moof;        /* duration in timescale of a moof, used for figure out
318                                  * the framerate of fragmented format stream */
319   guint64 duration_last_moof;
320
321   guint32 offset_in_sample;     /* Offset in the current sample, used for
322                                  * streams which have got exceedingly big
323                                  * sample size (such as 24s of raw audio).
324                                  * Only used when max_buffer_size is non-NULL */
325   guint32 max_buffer_size;      /* Maximum allowed size for output buffers.
326                                  * Currently only set for raw audio streams*/
327
328   /* video info */
329   /* aspect ratio */
330   gint display_width;
331   gint display_height;
332
333   /* allocation */
334   gboolean use_allocator;
335   GstAllocator *allocator;
336   GstAllocationParams params;
337
338   gsize alignment;
339
340   /* when a discontinuity is pending */
341   gboolean discont;
342
343   /* list of buffers to push first */
344   GSList *buffers;
345
346   /* if we need to clip this buffer. This is only needed for uncompressed
347    * data */
348   gboolean need_clip;
349
350   /* buffer needs some custom processing, e.g. subtitles */
351   gboolean need_process;
352   /* buffer needs potentially be split, e.g. CEA608 subtitles */
353   gboolean need_split;
354
355   /* current position */
356   guint32 segment_index;
357   guint32 sample_index;
358   GstClockTime time_position;   /* in gst time */
359   guint64 accumulated_base;
360
361   /* the Gst segment we are processing out, used for clipping */
362   GstSegment segment;
363
364   /* quicktime segments */
365   guint32 n_segments;
366   QtDemuxSegment *segments;
367   gboolean dummy_segment;
368   guint32 from_sample;
369   guint32 to_sample;
370
371   gboolean sent_eos;
372   GstTagList *stream_tags;
373   gboolean send_global_tags;
374
375   GstEvent *pending_event;
376
377   GstByteReader stco;
378   GstByteReader stsz;
379   GstByteReader stsc;
380   GstByteReader stts;
381   GstByteReader stss;
382   GstByteReader stps;
383   GstByteReader ctts;
384
385   gboolean chunks_are_samples;  /* TRUE means treat chunks as samples */
386   gint64 stbl_index;
387   /* stco */
388   guint co_size;
389   GstByteReader co_chunk;
390   guint32 first_chunk;
391   guint32 current_chunk;
392   guint32 last_chunk;
393   guint32 samples_per_chunk;
394   guint32 stsd_sample_description_id;
395   guint32 stco_sample_index;
396   /* stsz */
397   guint32 sample_size;          /* 0 means variable sizes are stored in stsz */
398   /* stsc */
399   guint32 stsc_index;
400   guint32 n_samples_per_chunk;
401   guint32 stsc_chunk_index;
402   guint32 stsc_sample_index;
403   guint64 chunk_offset;
404   /* stts */
405   guint32 stts_index;
406   guint32 stts_samples;
407   guint32 n_sample_times;
408   guint32 stts_sample_index;
409   guint64 stts_time;
410   guint32 stts_duration;
411   /* stss */
412   gboolean stss_present;
413   guint32 n_sample_syncs;
414   guint32 stss_index;
415   /* stps */
416   gboolean stps_present;
417   guint32 n_sample_partial_syncs;
418   guint32 stps_index;
419   QtDemuxRandomAccessEntry *ra_entries;
420   guint n_ra_entries;
421
422   const QtDemuxRandomAccessEntry *pending_seek;
423
424   /* ctts */
425   gboolean ctts_present;
426   guint32 n_composition_times;
427   guint32 ctts_index;
428   guint32 ctts_sample_index;
429   guint32 ctts_count;
430   gint32 ctts_soffset;
431
432   /* cslg */
433   guint32 cslg_shift;
434
435   /* fragmented */
436   gboolean parsed_trex;
437   guint32 def_sample_description_index; /* index is 1-based */
438   guint32 def_sample_duration;
439   guint32 def_sample_size;
440   guint32 def_sample_flags;
441
442   gboolean disabled;
443
444   /* stereoscopic video streams */
445   GstVideoMultiviewMode multiview_mode;
446   GstVideoMultiviewFlags multiview_flags;
447
448   /* protected streams */
449   gboolean protected;
450   guint32 protection_scheme_type;
451   guint32 protection_scheme_version;
452   gpointer protection_scheme_info;      /* specific to the protection scheme */
453   GQueue protection_scheme_event_queue;
454
455   gint ref_count;               /* atomic */
456 };
457
458 /* Contains properties and cryptographic info for a set of samples from a
459  * track protected using Common Encryption (cenc) */
460 struct _QtDemuxCencSampleSetInfo
461 {
462   GstStructure *default_properties;
463
464   /* @crypto_info holds one GstStructure per sample */
465   GPtrArray *crypto_info;
466 };
467
468 static const gchar *
469 qt_demux_state_string (enum QtDemuxState state)
470 {
471   switch (state) {
472     case QTDEMUX_STATE_INITIAL:
473       return "<INITIAL>";
474     case QTDEMUX_STATE_HEADER:
475       return "<HEADER>";
476     case QTDEMUX_STATE_MOVIE:
477       return "<MOVIE>";
478     case QTDEMUX_STATE_BUFFER_MDAT:
479       return "<BUFFER_MDAT>";
480     default:
481       return "<UNKNOWN>";
482   }
483 }
484
485 static GNode *qtdemux_tree_get_child_by_type (GNode * node, guint32 fourcc);
486 static GNode *qtdemux_tree_get_child_by_type_full (GNode * node,
487     guint32 fourcc, GstByteReader * parser);
488 static GNode *qtdemux_tree_get_sibling_by_type (GNode * node, guint32 fourcc);
489 static GNode *qtdemux_tree_get_sibling_by_type_full (GNode * node,
490     guint32 fourcc, GstByteReader * parser);
491
492 static GstFlowReturn qtdemux_add_fragmented_samples (GstQTDemux * qtdemux);
493
494 static void gst_qtdemux_check_send_pending_segment (GstQTDemux * demux);
495
496 static GstStaticPadTemplate gst_qtdemux_sink_template =
497     GST_STATIC_PAD_TEMPLATE ("sink",
498     GST_PAD_SINK,
499     GST_PAD_ALWAYS,
500     GST_STATIC_CAPS ("video/quicktime; video/mj2; audio/x-m4a; "
501         "application/x-3gp")
502     );
503
504 static GstStaticPadTemplate gst_qtdemux_videosrc_template =
505 GST_STATIC_PAD_TEMPLATE ("video_%u",
506     GST_PAD_SRC,
507     GST_PAD_SOMETIMES,
508     GST_STATIC_CAPS_ANY);
509
510 static GstStaticPadTemplate gst_qtdemux_audiosrc_template =
511 GST_STATIC_PAD_TEMPLATE ("audio_%u",
512     GST_PAD_SRC,
513     GST_PAD_SOMETIMES,
514     GST_STATIC_CAPS_ANY);
515
516 static GstStaticPadTemplate gst_qtdemux_subsrc_template =
517 GST_STATIC_PAD_TEMPLATE ("subtitle_%u",
518     GST_PAD_SRC,
519     GST_PAD_SOMETIMES,
520     GST_STATIC_CAPS_ANY);
521
522 #define gst_qtdemux_parent_class parent_class
523 G_DEFINE_TYPE (GstQTDemux, gst_qtdemux, GST_TYPE_ELEMENT);
524
525 static void gst_qtdemux_dispose (GObject * object);
526
527 static guint32
528 gst_qtdemux_find_index_linear (GstQTDemux * qtdemux, QtDemuxStream * str,
529     GstClockTime media_time);
530 static guint32
531 gst_qtdemux_find_index_for_given_media_offset_linear (GstQTDemux * qtdemux,
532     QtDemuxStream * str, gint64 media_offset);
533
534 #if 0
535 static void gst_qtdemux_set_index (GstElement * element, GstIndex * index);
536 static GstIndex *gst_qtdemux_get_index (GstElement * element);
537 #endif
538 static GstStateChangeReturn gst_qtdemux_change_state (GstElement * element,
539     GstStateChange transition);
540 static void gst_qtdemux_set_context (GstElement * element,
541     GstContext * context);
542 static gboolean qtdemux_sink_activate (GstPad * sinkpad, GstObject * parent);
543 static gboolean qtdemux_sink_activate_mode (GstPad * sinkpad,
544     GstObject * parent, GstPadMode mode, gboolean active);
545
546 static void gst_qtdemux_loop (GstPad * pad);
547 static GstFlowReturn gst_qtdemux_chain (GstPad * sinkpad, GstObject * parent,
548     GstBuffer * inbuf);
549 static gboolean gst_qtdemux_handle_sink_event (GstPad * pad, GstObject * parent,
550     GstEvent * event);
551 static gboolean gst_qtdemux_handle_sink_query (GstPad * pad, GstObject * parent,
552     GstQuery * query);
553 static gboolean gst_qtdemux_setcaps (GstQTDemux * qtdemux, GstCaps * caps);
554 static gboolean gst_qtdemux_configure_stream (GstQTDemux * qtdemux,
555     QtDemuxStream * stream);
556 static void gst_qtdemux_stream_check_and_change_stsd_index (GstQTDemux * demux,
557     QtDemuxStream * stream);
558 static GstFlowReturn gst_qtdemux_process_adapter (GstQTDemux * demux,
559     gboolean force);
560
561 static void gst_qtdemux_check_seekability (GstQTDemux * demux);
562
563 static gboolean qtdemux_parse_moov (GstQTDemux * qtdemux,
564     const guint8 * buffer, guint length);
565 static gboolean qtdemux_parse_node (GstQTDemux * qtdemux, GNode * node,
566     const guint8 * buffer, guint length);
567 static gboolean qtdemux_parse_tree (GstQTDemux * qtdemux);
568 static void qtdemux_parse_udta (GstQTDemux * qtdemux, GstTagList * taglist,
569     GNode * udta);
570
571 static void gst_qtdemux_handle_esds (GstQTDemux * qtdemux,
572     QtDemuxStream * stream, QtDemuxStreamStsdEntry * entry, GNode * esds,
573     GstTagList * list);
574 static GstCaps *qtdemux_video_caps (GstQTDemux * qtdemux,
575     QtDemuxStream * stream, QtDemuxStreamStsdEntry * entry, guint32 fourcc,
576     const guint8 * stsd_entry_data, gchar ** codec_name);
577 static GstCaps *qtdemux_audio_caps (GstQTDemux * qtdemux,
578     QtDemuxStream * stream, QtDemuxStreamStsdEntry * entry, guint32 fourcc,
579     const guint8 * data, int len, gchar ** codec_name);
580 static GstCaps *qtdemux_sub_caps (GstQTDemux * qtdemux, QtDemuxStream * stream,
581     QtDemuxStreamStsdEntry * entry, guint32 fourcc, const guint8 * data,
582     gchar ** codec_name);
583 static GstCaps *qtdemux_generic_caps (GstQTDemux * qtdemux,
584     QtDemuxStream * stream, QtDemuxStreamStsdEntry * entry, guint32 fourcc,
585     const guint8 * stsd_entry_data, gchar ** codec_name);
586
587 static gboolean qtdemux_parse_samples (GstQTDemux * qtdemux,
588     QtDemuxStream * stream, guint32 n);
589 static GstFlowReturn qtdemux_expose_streams (GstQTDemux * qtdemux);
590 static QtDemuxStream *gst_qtdemux_stream_ref (QtDemuxStream * stream);
591 static void gst_qtdemux_stream_unref (QtDemuxStream * stream);
592 static void gst_qtdemux_stream_clear (QtDemuxStream * stream);
593 static GstFlowReturn qtdemux_prepare_streams (GstQTDemux * qtdemux);
594 static void qtdemux_do_allocation (QtDemuxStream * stream,
595     GstQTDemux * qtdemux);
596 static gboolean gst_qtdemux_activate_segment (GstQTDemux * qtdemux,
597     QtDemuxStream * stream, guint32 seg_idx, GstClockTime offset);
598 static gboolean gst_qtdemux_stream_update_segment (GstQTDemux * qtdemux,
599     QtDemuxStream * stream, gint seg_idx, GstClockTime offset,
600     GstClockTime * _start, GstClockTime * _stop);
601 static void gst_qtdemux_send_gap_for_segment (GstQTDemux * demux,
602     QtDemuxStream * stream, gint segment_index, GstClockTime pos);
603
604 static gboolean qtdemux_pull_mfro_mfra (GstQTDemux * qtdemux);
605 static void check_update_duration (GstQTDemux * qtdemux, GstClockTime duration);
606
607 static gchar *qtdemux_uuid_bytes_to_string (gconstpointer uuid_bytes);
608
609 static GstStructure *qtdemux_get_cenc_sample_properties (GstQTDemux * qtdemux,
610     QtDemuxStream * stream, guint sample_index);
611 static void gst_qtdemux_append_protection_system_id (GstQTDemux * qtdemux,
612     const gchar * id);
613 static void qtdemux_gst_structure_free (GstStructure * gststructure);
614 static void gst_qtdemux_reset (GstQTDemux * qtdemux, gboolean hard);
615
616 static void
617 gst_qtdemux_class_init (GstQTDemuxClass * klass)
618 {
619   GObjectClass *gobject_class;
620   GstElementClass *gstelement_class;
621
622   gobject_class = (GObjectClass *) klass;
623   gstelement_class = (GstElementClass *) klass;
624
625   parent_class = g_type_class_peek_parent (klass);
626
627   gobject_class->dispose = gst_qtdemux_dispose;
628
629   gstelement_class->change_state = GST_DEBUG_FUNCPTR (gst_qtdemux_change_state);
630 #if 0
631   gstelement_class->set_index = GST_DEBUG_FUNCPTR (gst_qtdemux_set_index);
632   gstelement_class->get_index = GST_DEBUG_FUNCPTR (gst_qtdemux_get_index);
633 #endif
634   gstelement_class->set_context = GST_DEBUG_FUNCPTR (gst_qtdemux_set_context);
635
636   gst_tag_register_musicbrainz_tags ();
637
638   gst_element_class_add_static_pad_template (gstelement_class,
639       &gst_qtdemux_sink_template);
640   gst_element_class_add_static_pad_template (gstelement_class,
641       &gst_qtdemux_videosrc_template);
642   gst_element_class_add_static_pad_template (gstelement_class,
643       &gst_qtdemux_audiosrc_template);
644   gst_element_class_add_static_pad_template (gstelement_class,
645       &gst_qtdemux_subsrc_template);
646   gst_element_class_set_static_metadata (gstelement_class, "QuickTime demuxer",
647       "Codec/Demuxer",
648       "Demultiplex a QuickTime file into audio and video streams",
649       "David Schleef <ds@schleef.org>, Wim Taymans <wim@fluendo.com>");
650
651   GST_DEBUG_CATEGORY_INIT (qtdemux_debug, "qtdemux", 0, "qtdemux plugin");
652   gst_riff_init ();
653 }
654
655 static void
656 gst_qtdemux_init (GstQTDemux * qtdemux)
657 {
658   qtdemux->sinkpad =
659       gst_pad_new_from_static_template (&gst_qtdemux_sink_template, "sink");
660   gst_pad_set_activate_function (qtdemux->sinkpad, qtdemux_sink_activate);
661   gst_pad_set_activatemode_function (qtdemux->sinkpad,
662       qtdemux_sink_activate_mode);
663   gst_pad_set_chain_function (qtdemux->sinkpad, gst_qtdemux_chain);
664   gst_pad_set_event_function (qtdemux->sinkpad, gst_qtdemux_handle_sink_event);
665   gst_pad_set_query_function (qtdemux->sinkpad, gst_qtdemux_handle_sink_query);
666   gst_element_add_pad (GST_ELEMENT_CAST (qtdemux), qtdemux->sinkpad);
667
668   qtdemux->adapter = gst_adapter_new ();
669   g_queue_init (&qtdemux->protection_event_queue);
670   qtdemux->flowcombiner = gst_flow_combiner_new ();
671   g_mutex_init (&qtdemux->expose_lock);
672
673   qtdemux->active_streams = g_ptr_array_new_with_free_func
674       ((GDestroyNotify) gst_qtdemux_stream_unref);
675   qtdemux->old_streams = g_ptr_array_new_with_free_func
676       ((GDestroyNotify) gst_qtdemux_stream_unref);
677
678   GST_OBJECT_FLAG_SET (qtdemux, GST_ELEMENT_FLAG_INDEXABLE);
679
680   gst_qtdemux_reset (qtdemux, TRUE);
681 }
682
683 static void
684 gst_qtdemux_dispose (GObject * object)
685 {
686   GstQTDemux *qtdemux = GST_QTDEMUX (object);
687
688   if (qtdemux->adapter) {
689     g_object_unref (G_OBJECT (qtdemux->adapter));
690     qtdemux->adapter = NULL;
691   }
692   gst_tag_list_unref (qtdemux->tag_list);
693   gst_flow_combiner_free (qtdemux->flowcombiner);
694   g_queue_foreach (&qtdemux->protection_event_queue, (GFunc) gst_event_unref,
695       NULL);
696   g_queue_clear (&qtdemux->protection_event_queue);
697
698   g_free (qtdemux->cenc_aux_info_sizes);
699   qtdemux->cenc_aux_info_sizes = NULL;
700   g_mutex_clear (&qtdemux->expose_lock);
701
702   g_ptr_array_free (qtdemux->active_streams, TRUE);
703   g_ptr_array_free (qtdemux->old_streams, TRUE);
704
705   G_OBJECT_CLASS (parent_class)->dispose (object);
706 }
707
708 static void
709 gst_qtdemux_post_no_playable_stream_error (GstQTDemux * qtdemux)
710 {
711   if (qtdemux->posted_redirect) {
712     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
713         (_("This file contains no playable streams.")),
714         ("no known streams found, a redirect message has been posted"));
715   } else {
716     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
717         (_("This file contains no playable streams.")),
718         ("no known streams found"));
719   }
720 }
721
722 static GstBuffer *
723 _gst_buffer_new_wrapped (gpointer mem, gsize size, GFreeFunc free_func)
724 {
725   return gst_buffer_new_wrapped_full (free_func ? 0 : GST_MEMORY_FLAG_READONLY,
726       mem, size, 0, size, mem, free_func);
727 }
728
729 static GstFlowReturn
730 gst_qtdemux_pull_atom (GstQTDemux * qtdemux, guint64 offset, guint64 size,
731     GstBuffer ** buf)
732 {
733   GstFlowReturn flow;
734   GstMapInfo map;
735   gsize bsize;
736
737   if (G_UNLIKELY (size == 0)) {
738     GstFlowReturn ret;
739     GstBuffer *tmp = NULL;
740
741     ret = gst_qtdemux_pull_atom (qtdemux, offset, sizeof (guint32), &tmp);
742     if (ret != GST_FLOW_OK)
743       return ret;
744
745     gst_buffer_map (tmp, &map, GST_MAP_READ);
746     size = QT_UINT32 (map.data);
747     GST_DEBUG_OBJECT (qtdemux, "size 0x%08" G_GINT64_MODIFIER "x", size);
748
749     gst_buffer_unmap (tmp, &map);
750     gst_buffer_unref (tmp);
751   }
752
753   /* Sanity check: catch bogus sizes (fuzzed/broken files) */
754   if (G_UNLIKELY (size > QTDEMUX_MAX_ATOM_SIZE)) {
755     if (qtdemux->state != QTDEMUX_STATE_MOVIE && qtdemux->got_moov) {
756       /* we're pulling header but already got most interesting bits,
757        * so never mind the rest (e.g. tags) (that much) */
758       GST_WARNING_OBJECT (qtdemux, "atom has bogus size %" G_GUINT64_FORMAT,
759           size);
760       return GST_FLOW_EOS;
761     } else {
762       GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
763           (_("This file is invalid and cannot be played.")),
764           ("atom has bogus size %" G_GUINT64_FORMAT, size));
765       return GST_FLOW_ERROR;
766     }
767   }
768
769   flow = gst_pad_pull_range (qtdemux->sinkpad, offset, size, buf);
770
771   if (G_UNLIKELY (flow != GST_FLOW_OK))
772     return flow;
773
774   bsize = gst_buffer_get_size (*buf);
775   /* Catch short reads - we don't want any partial atoms */
776   if (G_UNLIKELY (bsize < size)) {
777     GST_WARNING_OBJECT (qtdemux,
778         "short read: %" G_GSIZE_FORMAT " < %" G_GUINT64_FORMAT, bsize, size);
779     gst_buffer_unref (*buf);
780     *buf = NULL;
781     return GST_FLOW_EOS;
782   }
783
784   return flow;
785 }
786
787 #if 1
788 static gboolean
789 gst_qtdemux_src_convert (GstQTDemux * qtdemux, GstPad * pad,
790     GstFormat src_format, gint64 src_value, GstFormat dest_format,
791     gint64 * dest_value)
792 {
793   gboolean res = TRUE;
794   QtDemuxStream *stream = gst_pad_get_element_private (pad);
795   gint32 index;
796
797   if (stream->subtype != FOURCC_vide) {
798     res = FALSE;
799     goto done;
800   }
801
802   switch (src_format) {
803     case GST_FORMAT_TIME:
804       switch (dest_format) {
805         case GST_FORMAT_BYTES:{
806           index = gst_qtdemux_find_index_linear (qtdemux, stream, src_value);
807           if (-1 == index) {
808             res = FALSE;
809             goto done;
810           }
811
812           *dest_value = stream->samples[index].offset;
813
814           GST_DEBUG_OBJECT (qtdemux, "Format Conversion Time->Offset :%"
815               GST_TIME_FORMAT "->%" G_GUINT64_FORMAT,
816               GST_TIME_ARGS (src_value), *dest_value);
817           break;
818         }
819         default:
820           res = FALSE;
821           break;
822       }
823       break;
824     case GST_FORMAT_BYTES:
825       switch (dest_format) {
826         case GST_FORMAT_TIME:{
827           index =
828               gst_qtdemux_find_index_for_given_media_offset_linear (qtdemux,
829               stream, src_value);
830
831           if (-1 == index) {
832             res = FALSE;
833             goto done;
834           }
835
836           *dest_value =
837               QTSTREAMTIME_TO_GSTTIME (stream,
838               stream->samples[index].timestamp);
839           GST_DEBUG_OBJECT (qtdemux,
840               "Format Conversion Offset->Time :%" G_GUINT64_FORMAT "->%"
841               GST_TIME_FORMAT, src_value, GST_TIME_ARGS (*dest_value));
842           break;
843         }
844         default:
845           res = FALSE;
846           break;
847       }
848       break;
849     default:
850       res = FALSE;
851       break;
852   }
853
854 done:
855   return res;
856 }
857 #endif
858
859 static gboolean
860 gst_qtdemux_get_duration (GstQTDemux * qtdemux, GstClockTime * duration)
861 {
862   gboolean res = FALSE;
863
864   *duration = GST_CLOCK_TIME_NONE;
865
866   if (qtdemux->duration != 0 &&
867       qtdemux->duration != G_MAXINT64 && qtdemux->timescale != 0) {
868     *duration = QTTIME_TO_GSTTIME (qtdemux, qtdemux->duration);
869     res = TRUE;
870   } else {
871     *duration = GST_CLOCK_TIME_NONE;
872   }
873
874   return res;
875 }
876
877 static gboolean
878 gst_qtdemux_handle_src_query (GstPad * pad, GstObject * parent,
879     GstQuery * query)
880 {
881   gboolean res = FALSE;
882   GstQTDemux *qtdemux = GST_QTDEMUX (parent);
883
884   GST_LOG_OBJECT (pad, "%s query", GST_QUERY_TYPE_NAME (query));
885
886   switch (GST_QUERY_TYPE (query)) {
887     case GST_QUERY_POSITION:{
888       GstFormat fmt;
889
890       gst_query_parse_position (query, &fmt, NULL);
891       if (fmt == GST_FORMAT_TIME
892           && GST_CLOCK_TIME_IS_VALID (qtdemux->segment.position)) {
893         gst_query_set_position (query, GST_FORMAT_TIME,
894             qtdemux->segment.position);
895         res = TRUE;
896       }
897     }
898       break;
899     case GST_QUERY_DURATION:{
900       GstFormat fmt;
901
902       gst_query_parse_duration (query, &fmt, NULL);
903       if (fmt == GST_FORMAT_TIME) {
904         /* First try to query upstream */
905         res = gst_pad_query_default (pad, parent, query);
906         if (!res) {
907           GstClockTime duration;
908           if (gst_qtdemux_get_duration (qtdemux, &duration) && duration > 0) {
909             gst_query_set_duration (query, GST_FORMAT_TIME, duration);
910             res = TRUE;
911           }
912         }
913       }
914       break;
915     }
916     case GST_QUERY_CONVERT:{
917       GstFormat src_fmt, dest_fmt;
918       gint64 src_value, dest_value = 0;
919
920       gst_query_parse_convert (query, &src_fmt, &src_value, &dest_fmt, NULL);
921
922       res = gst_qtdemux_src_convert (qtdemux, pad,
923           src_fmt, src_value, dest_fmt, &dest_value);
924       if (res)
925         gst_query_set_convert (query, src_fmt, src_value, dest_fmt, dest_value);
926
927       break;
928     }
929     case GST_QUERY_FORMATS:
930       gst_query_set_formats (query, 2, GST_FORMAT_TIME, GST_FORMAT_BYTES);
931       res = TRUE;
932       break;
933     case GST_QUERY_SEEKING:{
934       GstFormat fmt;
935       gboolean seekable;
936
937       /* try upstream first */
938       res = gst_pad_query_default (pad, parent, query);
939
940       if (!res) {
941         gst_query_parse_seeking (query, &fmt, NULL, NULL, NULL);
942         if (fmt == GST_FORMAT_TIME) {
943           GstClockTime duration;
944
945           gst_qtdemux_get_duration (qtdemux, &duration);
946           seekable = TRUE;
947           if (!qtdemux->pullbased) {
948             GstQuery *q;
949
950             /* we might be able with help from upstream */
951             seekable = FALSE;
952             q = gst_query_new_seeking (GST_FORMAT_BYTES);
953             if (gst_pad_peer_query (qtdemux->sinkpad, q)) {
954               gst_query_parse_seeking (q, &fmt, &seekable, NULL, NULL);
955               GST_LOG_OBJECT (qtdemux, "upstream BYTE seekable %d", seekable);
956             }
957             gst_query_unref (q);
958           }
959           gst_query_set_seeking (query, GST_FORMAT_TIME, seekable, 0, duration);
960           res = TRUE;
961         }
962       }
963       break;
964     }
965     case GST_QUERY_SEGMENT:
966     {
967       GstFormat format;
968       gint64 start, stop;
969
970       format = qtdemux->segment.format;
971
972       start =
973           gst_segment_to_stream_time (&qtdemux->segment, format,
974           qtdemux->segment.start);
975       if ((stop = qtdemux->segment.stop) == -1)
976         stop = qtdemux->segment.duration;
977       else
978         stop = gst_segment_to_stream_time (&qtdemux->segment, format, stop);
979
980       gst_query_set_segment (query, qtdemux->segment.rate, format, start, stop);
981       res = TRUE;
982       break;
983     }
984     default:
985       res = gst_pad_query_default (pad, parent, query);
986       break;
987   }
988
989   return res;
990 }
991
992 static void
993 gst_qtdemux_push_tags (GstQTDemux * qtdemux, QtDemuxStream * stream)
994 {
995   if (G_LIKELY (stream->pad)) {
996     GST_DEBUG_OBJECT (qtdemux, "Checking pad %s:%s for tags",
997         GST_DEBUG_PAD_NAME (stream->pad));
998
999     if (!gst_tag_list_is_empty (stream->stream_tags)) {
1000       GST_DEBUG_OBJECT (qtdemux, "Sending tags %" GST_PTR_FORMAT,
1001           stream->stream_tags);
1002       gst_pad_push_event (stream->pad,
1003           gst_event_new_tag (gst_tag_list_ref (stream->stream_tags)));
1004     }
1005
1006     if (G_UNLIKELY (stream->send_global_tags)) {
1007       GST_DEBUG_OBJECT (qtdemux, "Sending global tags %" GST_PTR_FORMAT,
1008           qtdemux->tag_list);
1009       gst_pad_push_event (stream->pad,
1010           gst_event_new_tag (gst_tag_list_ref (qtdemux->tag_list)));
1011       stream->send_global_tags = FALSE;
1012     }
1013   }
1014 }
1015
1016 /* push event on all source pads; takes ownership of the event */
1017 static void
1018 gst_qtdemux_push_event (GstQTDemux * qtdemux, GstEvent * event)
1019 {
1020   gboolean has_valid_stream = FALSE;
1021   GstEventType etype = GST_EVENT_TYPE (event);
1022   guint i;
1023
1024   GST_DEBUG_OBJECT (qtdemux, "pushing %s event on all source pads",
1025       GST_EVENT_TYPE_NAME (event));
1026
1027   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
1028     GstPad *pad;
1029     QtDemuxStream *stream = QTDEMUX_NTH_STREAM (qtdemux, i);
1030     GST_DEBUG_OBJECT (qtdemux, "pushing on track-id %u", stream->track_id);
1031
1032     if ((pad = stream->pad)) {
1033       has_valid_stream = TRUE;
1034
1035       if (etype == GST_EVENT_EOS) {
1036         /* let's not send twice */
1037         if (stream->sent_eos)
1038           continue;
1039         stream->sent_eos = TRUE;
1040       }
1041
1042       gst_pad_push_event (pad, gst_event_ref (event));
1043     }
1044   }
1045
1046   gst_event_unref (event);
1047
1048   /* if it is EOS and there are no pads, post an error */
1049   if (!has_valid_stream && etype == GST_EVENT_EOS) {
1050     gst_qtdemux_post_no_playable_stream_error (qtdemux);
1051   }
1052 }
1053
1054 typedef struct
1055 {
1056   guint64 media_time;
1057 } FindData;
1058
1059 static gint
1060 find_func (QtDemuxSample * s1, gint64 * media_time, gpointer user_data)
1061 {
1062   if ((gint64) s1->timestamp > *media_time)
1063     return 1;
1064   if ((gint64) s1->timestamp == *media_time)
1065     return 0;
1066
1067   return -1;
1068 }
1069
1070 /* find the index of the sample that includes the data for @media_time using a
1071  * binary search.  Only to be called in optimized cases of linear search below.
1072  *
1073  * Returns the index of the sample with the corresponding *DTS*.
1074  */
1075 static guint32
1076 gst_qtdemux_find_index (GstQTDemux * qtdemux, QtDemuxStream * str,
1077     guint64 media_time)
1078 {
1079   QtDemuxSample *result;
1080   guint32 index;
1081
1082   /* convert media_time to mov format */
1083   media_time =
1084       gst_util_uint64_scale_ceil (media_time, str->timescale, GST_SECOND);
1085
1086   result = gst_util_array_binary_search (str->samples, str->stbl_index + 1,
1087       sizeof (QtDemuxSample), (GCompareDataFunc) find_func,
1088       GST_SEARCH_MODE_BEFORE, &media_time, NULL);
1089
1090   if (G_LIKELY (result))
1091     index = result - str->samples;
1092   else
1093     index = 0;
1094
1095   return index;
1096 }
1097
1098
1099
1100 /* find the index of the sample that includes the data for @media_offset using a
1101  * linear search
1102  *
1103  * Returns the index of the sample.
1104  */
1105 static guint32
1106 gst_qtdemux_find_index_for_given_media_offset_linear (GstQTDemux * qtdemux,
1107     QtDemuxStream * str, gint64 media_offset)
1108 {
1109   QtDemuxSample *result = str->samples;
1110   guint32 index = 0;
1111
1112   if (result == NULL || str->n_samples == 0)
1113     return -1;
1114
1115   if (media_offset == result->offset)
1116     return index;
1117
1118   result++;
1119   while (index < str->n_samples - 1) {
1120     if (!qtdemux_parse_samples (qtdemux, str, index + 1))
1121       goto parse_failed;
1122
1123     if (media_offset < result->offset)
1124       break;
1125
1126     index++;
1127     result++;
1128   }
1129   return index;
1130
1131   /* ERRORS */
1132 parse_failed:
1133   {
1134     GST_LOG_OBJECT (qtdemux, "Parsing of index %u failed!", index + 1);
1135     return -1;
1136   }
1137 }
1138
1139 /* find the index of the sample that includes the data for @media_time using a
1140  * linear search, and keeping in mind that not all samples may have been parsed
1141  * yet.  If possible, it will delegate to binary search.
1142  *
1143  * Returns the index of the sample.
1144  */
1145 static guint32
1146 gst_qtdemux_find_index_linear (GstQTDemux * qtdemux, QtDemuxStream * str,
1147     GstClockTime media_time)
1148 {
1149   guint32 index = 0;
1150   guint64 mov_time;
1151   QtDemuxSample *sample;
1152
1153   /* convert media_time to mov format */
1154   mov_time =
1155       gst_util_uint64_scale_ceil (media_time, str->timescale, GST_SECOND);
1156
1157   sample = str->samples;
1158   if (mov_time == sample->timestamp + sample->pts_offset)
1159     return index;
1160
1161   /* use faster search if requested time in already parsed range */
1162   sample = str->samples + str->stbl_index;
1163   if (str->stbl_index >= 0 && mov_time <= sample->timestamp) {
1164     index = gst_qtdemux_find_index (qtdemux, str, media_time);
1165     sample = str->samples + index;
1166   } else {
1167     while (index < str->n_samples - 1) {
1168       if (!qtdemux_parse_samples (qtdemux, str, index + 1))
1169         goto parse_failed;
1170
1171       sample = str->samples + index + 1;
1172       if (mov_time < sample->timestamp) {
1173         sample = str->samples + index;
1174         break;
1175       }
1176
1177       index++;
1178     }
1179   }
1180
1181   /* sample->timestamp is now <= media_time, need to find the corresponding
1182    * PTS now by looking backwards */
1183   while (index > 0 && sample->timestamp + sample->pts_offset > mov_time) {
1184     index--;
1185     sample = str->samples + index;
1186   }
1187
1188   return index;
1189
1190   /* ERRORS */
1191 parse_failed:
1192   {
1193     GST_LOG_OBJECT (qtdemux, "Parsing of index %u failed!", index + 1);
1194     return -1;
1195   }
1196 }
1197
1198 /* find the index of the keyframe needed to decode the sample at @index
1199  * of stream @str, or of a subsequent keyframe (depending on @next)
1200  *
1201  * Returns the index of the keyframe.
1202  */
1203 static guint32
1204 gst_qtdemux_find_keyframe (GstQTDemux * qtdemux, QtDemuxStream * str,
1205     guint32 index, gboolean next)
1206 {
1207   guint32 new_index = index;
1208
1209   if (index >= str->n_samples) {
1210     new_index = str->n_samples;
1211     goto beach;
1212   }
1213
1214   /* all keyframes, return index */
1215   if (str->all_keyframe) {
1216     new_index = index;
1217     goto beach;
1218   }
1219
1220   /* else search until we have a keyframe */
1221   while (new_index < str->n_samples) {
1222     if (next && !qtdemux_parse_samples (qtdemux, str, new_index))
1223       goto parse_failed;
1224
1225     if (str->samples[new_index].keyframe)
1226       break;
1227
1228     if (new_index == 0)
1229       break;
1230
1231     if (next)
1232       new_index++;
1233     else
1234       new_index--;
1235   }
1236
1237   if (new_index == str->n_samples) {
1238     GST_DEBUG_OBJECT (qtdemux, "no next keyframe");
1239     new_index = -1;
1240   }
1241
1242 beach:
1243   GST_DEBUG_OBJECT (qtdemux, "searching for keyframe index %s index %u "
1244       "gave %u", next ? "after" : "before", index, new_index);
1245
1246   return new_index;
1247
1248   /* ERRORS */
1249 parse_failed:
1250   {
1251     GST_LOG_OBJECT (qtdemux, "Parsing of index %u failed!", new_index);
1252     return -1;
1253   }
1254 }
1255
1256 /* find the segment for @time_position for @stream
1257  *
1258  * Returns the index of the segment containing @time_position.
1259  * Returns the last segment and sets the @eos variable to TRUE
1260  * if the time is beyond the end. @eos may be NULL
1261  */
1262 static guint32
1263 gst_qtdemux_find_segment (GstQTDemux * qtdemux, QtDemuxStream * stream,
1264     GstClockTime time_position)
1265 {
1266   gint i;
1267   guint32 seg_idx;
1268
1269   GST_LOG_OBJECT (stream->pad, "finding segment for %" GST_TIME_FORMAT,
1270       GST_TIME_ARGS (time_position));
1271
1272   seg_idx = -1;
1273   for (i = 0; i < stream->n_segments; i++) {
1274     QtDemuxSegment *segment = &stream->segments[i];
1275
1276     GST_LOG_OBJECT (stream->pad,
1277         "looking at segment %" GST_TIME_FORMAT "-%" GST_TIME_FORMAT,
1278         GST_TIME_ARGS (segment->time), GST_TIME_ARGS (segment->stop_time));
1279
1280     /* For the last segment we include stop_time in the last segment */
1281     if (i < stream->n_segments - 1) {
1282       if (segment->time <= time_position && time_position < segment->stop_time) {
1283         GST_LOG_OBJECT (stream->pad, "segment %d matches", i);
1284         seg_idx = i;
1285         break;
1286       }
1287     } else {
1288       /* Last segment always matches */
1289       seg_idx = i;
1290       break;
1291     }
1292   }
1293   return seg_idx;
1294 }
1295
1296 /* move the stream @str to the sample position @index.
1297  *
1298  * Updates @str->sample_index and marks discontinuity if needed.
1299  */
1300 static void
1301 gst_qtdemux_move_stream (GstQTDemux * qtdemux, QtDemuxStream * str,
1302     guint32 index)
1303 {
1304   /* no change needed */
1305   if (index == str->sample_index)
1306     return;
1307
1308   GST_DEBUG_OBJECT (qtdemux, "moving to sample %u of %u", index,
1309       str->n_samples);
1310
1311   /* position changed, we have a discont */
1312   str->sample_index = index;
1313   str->offset_in_sample = 0;
1314   /* Each time we move in the stream we store the position where we are
1315    * starting from */
1316   str->from_sample = index;
1317   str->discont = TRUE;
1318 }
1319
1320 static void
1321 gst_qtdemux_adjust_seek (GstQTDemux * qtdemux, gint64 desired_time,
1322     gboolean use_sparse, gboolean next, gint64 * key_time, gint64 * key_offset)
1323 {
1324   guint64 min_offset;
1325   gint64 min_byte_offset = -1;
1326   guint i;
1327
1328   min_offset = desired_time;
1329
1330   /* for each stream, find the index of the sample in the segment
1331    * and move back to the previous keyframe. */
1332   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
1333     QtDemuxStream *str;
1334     guint32 index, kindex;
1335     guint32 seg_idx;
1336     GstClockTime media_start;
1337     GstClockTime media_time;
1338     GstClockTime seg_time;
1339     QtDemuxSegment *seg;
1340     gboolean empty_segment = FALSE;
1341
1342     str = QTDEMUX_NTH_STREAM (qtdemux, i);
1343
1344     if (CUR_STREAM (str)->sparse && !use_sparse)
1345       continue;
1346
1347     seg_idx = gst_qtdemux_find_segment (qtdemux, str, desired_time);
1348     GST_DEBUG_OBJECT (qtdemux, "align segment %d", seg_idx);
1349
1350     /* get segment and time in the segment */
1351     seg = &str->segments[seg_idx];
1352     seg_time = (desired_time - seg->time) * seg->rate;
1353
1354     while (QTSEGMENT_IS_EMPTY (seg)) {
1355       seg_time = 0;
1356       empty_segment = TRUE;
1357       GST_DEBUG_OBJECT (str->pad, "Segment %d is empty, moving to next one",
1358           seg_idx);
1359       seg_idx++;
1360       if (seg_idx == str->n_segments)
1361         break;
1362       seg = &str->segments[seg_idx];
1363     }
1364
1365     if (seg_idx == str->n_segments) {
1366       /* FIXME track shouldn't have the last segment as empty, but if it
1367        * happens we better handle it */
1368       continue;
1369     }
1370
1371     /* get the media time in the segment */
1372     media_start = seg->media_start + seg_time;
1373
1374     /* get the index of the sample with media time */
1375     index = gst_qtdemux_find_index_linear (qtdemux, str, media_start);
1376     GST_DEBUG_OBJECT (qtdemux, "sample for %" GST_TIME_FORMAT " at %u"
1377         " at offset %" G_GUINT64_FORMAT " (empty segment: %d)",
1378         GST_TIME_ARGS (media_start), index, str->samples[index].offset,
1379         empty_segment);
1380
1381     /* shift to next frame if we are looking for next keyframe */
1382     if (next && QTSAMPLE_PTS_NO_CSLG (str, &str->samples[index]) < media_start
1383         && index < str->stbl_index)
1384       index++;
1385
1386     if (!empty_segment) {
1387       /* find previous keyframe */
1388       kindex = gst_qtdemux_find_keyframe (qtdemux, str, index, next);
1389
1390       /* we will settle for one before if none found after */
1391       if (next && kindex == -1)
1392         kindex = gst_qtdemux_find_keyframe (qtdemux, str, index, FALSE);
1393
1394       /* if the keyframe is at a different position, we need to update the
1395        * requested seek time */
1396       if (index != kindex) {
1397         index = kindex;
1398
1399         /* get timestamp of keyframe */
1400         media_time = QTSAMPLE_PTS_NO_CSLG (str, &str->samples[kindex]);
1401         GST_DEBUG_OBJECT (qtdemux,
1402             "keyframe at %u with time %" GST_TIME_FORMAT " at offset %"
1403             G_GUINT64_FORMAT, kindex, GST_TIME_ARGS (media_time),
1404             str->samples[kindex].offset);
1405
1406         /* keyframes in the segment get a chance to change the
1407          * desired_offset. keyframes out of the segment are
1408          * ignored. */
1409         if (media_time >= seg->media_start) {
1410           GstClockTime seg_time;
1411
1412           /* this keyframe is inside the segment, convert back to
1413            * segment time */
1414           seg_time = (media_time - seg->media_start) + seg->time;
1415           if ((!next && (seg_time < min_offset)) ||
1416               (next && (seg_time > min_offset)))
1417             min_offset = seg_time;
1418         }
1419       }
1420     }
1421
1422     if (min_byte_offset < 0 || str->samples[index].offset < min_byte_offset)
1423       min_byte_offset = str->samples[index].offset;
1424   }
1425
1426   if (key_time)
1427     *key_time = min_offset;
1428   if (key_offset)
1429     *key_offset = min_byte_offset;
1430 }
1431
1432 static gboolean
1433 gst_qtdemux_convert_seek (GstPad * pad, GstFormat * format,
1434     GstSeekType cur_type, gint64 * cur, GstSeekType stop_type, gint64 * stop)
1435 {
1436   gboolean res;
1437
1438   g_return_val_if_fail (format != NULL, FALSE);
1439   g_return_val_if_fail (cur != NULL, FALSE);
1440   g_return_val_if_fail (stop != NULL, FALSE);
1441
1442   if (*format == GST_FORMAT_TIME)
1443     return TRUE;
1444
1445   res = TRUE;
1446   if (cur_type != GST_SEEK_TYPE_NONE)
1447     res = gst_pad_query_convert (pad, *format, *cur, GST_FORMAT_TIME, cur);
1448   if (res && stop_type != GST_SEEK_TYPE_NONE)
1449     res = gst_pad_query_convert (pad, *format, *stop, GST_FORMAT_TIME, stop);
1450
1451   if (res)
1452     *format = GST_FORMAT_TIME;
1453
1454   return res;
1455 }
1456
1457 /* perform seek in push based mode:
1458    find BYTE position to move to based on time and delegate to upstream
1459 */
1460 static gboolean
1461 gst_qtdemux_do_push_seek (GstQTDemux * qtdemux, GstPad * pad, GstEvent * event)
1462 {
1463   gdouble rate;
1464   GstFormat format;
1465   GstSeekFlags flags;
1466   GstSeekType cur_type, stop_type;
1467   gint64 cur, stop, key_cur;
1468   gboolean res;
1469   gint64 byte_cur;
1470   gint64 original_stop;
1471   guint32 seqnum;
1472
1473   GST_DEBUG_OBJECT (qtdemux, "doing push-based seek");
1474
1475   gst_event_parse_seek (event, &rate, &format, &flags,
1476       &cur_type, &cur, &stop_type, &stop);
1477   seqnum = gst_event_get_seqnum (event);
1478
1479   /* only forward streaming and seeking is possible */
1480   if (rate <= 0)
1481     goto unsupported_seek;
1482
1483   /* convert to TIME if needed and possible */
1484   if (!gst_qtdemux_convert_seek (pad, &format, cur_type, &cur,
1485           stop_type, &stop))
1486     goto no_format;
1487
1488   /* Upstream seek in bytes will have undefined stop, but qtdemux stores
1489    * the original stop position to use when upstream pushes the new segment
1490    * for this seek */
1491   original_stop = stop;
1492   stop = -1;
1493
1494   /* find reasonable corresponding BYTE position,
1495    * also try to mind about keyframes, since we can not go back a bit for them
1496    * later on */
1497   /* determining @next here based on SNAP_BEFORE/SNAP_AFTER should
1498    * mostly just work, but let's not yet boldly go there  ... */
1499   gst_qtdemux_adjust_seek (qtdemux, cur, FALSE, FALSE, &key_cur, &byte_cur);
1500
1501   if (byte_cur == -1)
1502     goto abort_seek;
1503
1504   GST_DEBUG_OBJECT (qtdemux, "Pushing BYTE seek rate %g, "
1505       "start %" G_GINT64_FORMAT ", stop %" G_GINT64_FORMAT, rate, byte_cur,
1506       stop);
1507
1508   GST_OBJECT_LOCK (qtdemux);
1509   qtdemux->seek_offset = byte_cur;
1510   if (!(flags & GST_SEEK_FLAG_KEY_UNIT)) {
1511     qtdemux->push_seek_start = cur;
1512   } else {
1513     qtdemux->push_seek_start = key_cur;
1514   }
1515
1516   if (stop_type == GST_SEEK_TYPE_NONE) {
1517     qtdemux->push_seek_stop = qtdemux->segment.stop;
1518   } else {
1519     qtdemux->push_seek_stop = original_stop;
1520   }
1521   GST_OBJECT_UNLOCK (qtdemux);
1522
1523   qtdemux->segment_seqnum = seqnum;
1524   /* BYTE seek event */
1525   event = gst_event_new_seek (rate, GST_FORMAT_BYTES, flags, cur_type, byte_cur,
1526       stop_type, stop);
1527   gst_event_set_seqnum (event, seqnum);
1528   res = gst_pad_push_event (qtdemux->sinkpad, event);
1529
1530   return res;
1531
1532   /* ERRORS */
1533 abort_seek:
1534   {
1535     GST_DEBUG_OBJECT (qtdemux, "could not determine byte position to seek to, "
1536         "seek aborted.");
1537     return FALSE;
1538   }
1539 unsupported_seek:
1540   {
1541     GST_DEBUG_OBJECT (qtdemux, "unsupported seek, seek aborted.");
1542     return FALSE;
1543   }
1544 no_format:
1545   {
1546     GST_DEBUG_OBJECT (qtdemux, "unsupported format given, seek aborted.");
1547     return FALSE;
1548   }
1549 }
1550
1551 /* perform the seek.
1552  *
1553  * We set all segment_indexes in the streams to unknown and
1554  * adjust the time_position to the desired position. this is enough
1555  * to trigger a segment switch in the streaming thread to start
1556  * streaming from the desired position.
1557  *
1558  * Keyframe seeking is a little more complicated when dealing with
1559  * segments. Ideally we want to move to the previous keyframe in
1560  * the segment but there might not be a keyframe in the segment. In
1561  * fact, none of the segments could contain a keyframe. We take a
1562  * practical approach: seek to the previous keyframe in the segment,
1563  * if there is none, seek to the beginning of the segment.
1564  *
1565  * Called with STREAM_LOCK
1566  */
1567 static gboolean
1568 gst_qtdemux_perform_seek (GstQTDemux * qtdemux, GstSegment * segment,
1569     guint32 seqnum, GstSeekFlags flags)
1570 {
1571   gint64 desired_offset;
1572   guint i;
1573
1574   desired_offset = segment->position;
1575
1576   GST_DEBUG_OBJECT (qtdemux, "seeking to %" GST_TIME_FORMAT,
1577       GST_TIME_ARGS (desired_offset));
1578
1579   /* may not have enough fragmented info to do this adjustment,
1580    * and we can't scan (and probably should not) at this time with
1581    * possibly flushing upstream */
1582   if ((flags & GST_SEEK_FLAG_KEY_UNIT) && !qtdemux->fragmented) {
1583     gint64 min_offset;
1584     gboolean next, before, after;
1585
1586     before = ! !(flags & GST_SEEK_FLAG_SNAP_BEFORE);
1587     after = ! !(flags & GST_SEEK_FLAG_SNAP_AFTER);
1588     next = after && !before;
1589     if (segment->rate < 0)
1590       next = !next;
1591
1592     gst_qtdemux_adjust_seek (qtdemux, desired_offset, TRUE, next, &min_offset,
1593         NULL);
1594     GST_DEBUG_OBJECT (qtdemux, "keyframe seek, align to %"
1595         GST_TIME_FORMAT, GST_TIME_ARGS (min_offset));
1596     desired_offset = min_offset;
1597   }
1598
1599   /* and set all streams to the final position */
1600   gst_flow_combiner_reset (qtdemux->flowcombiner);
1601   qtdemux->segment_seqnum = seqnum;
1602   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
1603     QtDemuxStream *stream = QTDEMUX_NTH_STREAM (qtdemux, i);
1604
1605     stream->time_position = desired_offset;
1606     stream->accumulated_base = 0;
1607     stream->sample_index = -1;
1608     stream->offset_in_sample = 0;
1609     stream->segment_index = -1;
1610     stream->sent_eos = FALSE;
1611
1612     if (segment->flags & GST_SEEK_FLAG_FLUSH)
1613       gst_segment_init (&stream->segment, GST_FORMAT_TIME);
1614   }
1615   segment->position = desired_offset;
1616   segment->time = desired_offset;
1617   if (segment->rate >= 0) {
1618     segment->start = desired_offset;
1619
1620     /* we stop at the end */
1621     if (segment->stop == -1)
1622       segment->stop = segment->duration;
1623   } else {
1624     segment->stop = desired_offset;
1625   }
1626
1627   if (qtdemux->fragmented)
1628     qtdemux->fragmented_seek_pending = TRUE;
1629
1630   return TRUE;
1631 }
1632
1633 /* do a seek in pull based mode */
1634 static gboolean
1635 gst_qtdemux_do_seek (GstQTDemux * qtdemux, GstPad * pad, GstEvent * event)
1636 {
1637   gdouble rate;
1638   GstFormat format;
1639   GstSeekFlags flags;
1640   GstSeekType cur_type, stop_type;
1641   gint64 cur, stop;
1642   gboolean flush;
1643   gboolean update;
1644   GstSegment seeksegment;
1645   guint32 seqnum = GST_SEQNUM_INVALID;
1646   GstEvent *flush_event;
1647   gboolean ret;
1648
1649   if (event) {
1650     GST_DEBUG_OBJECT (qtdemux, "doing seek with event");
1651
1652     gst_event_parse_seek (event, &rate, &format, &flags,
1653         &cur_type, &cur, &stop_type, &stop);
1654     seqnum = gst_event_get_seqnum (event);
1655
1656     /* we have to have a format as the segment format. Try to convert
1657      * if not. */
1658     if (!gst_qtdemux_convert_seek (pad, &format, cur_type, &cur,
1659             stop_type, &stop))
1660       goto no_format;
1661
1662     GST_DEBUG_OBJECT (qtdemux, "seek format %s", gst_format_get_name (format));
1663   } else {
1664     GST_DEBUG_OBJECT (qtdemux, "doing seek without event");
1665     flags = 0;
1666   }
1667
1668   flush = flags & GST_SEEK_FLAG_FLUSH;
1669
1670   /* stop streaming, either by flushing or by pausing the task */
1671   if (flush) {
1672     flush_event = gst_event_new_flush_start ();
1673     if (seqnum != GST_SEQNUM_INVALID)
1674       gst_event_set_seqnum (flush_event, seqnum);
1675     /* unlock upstream pull_range */
1676     gst_pad_push_event (qtdemux->sinkpad, gst_event_ref (flush_event));
1677     /* make sure out loop function exits */
1678     gst_qtdemux_push_event (qtdemux, flush_event);
1679   } else {
1680     /* non flushing seek, pause the task */
1681     gst_pad_pause_task (qtdemux->sinkpad);
1682   }
1683
1684   /* wait for streaming to finish */
1685   GST_PAD_STREAM_LOCK (qtdemux->sinkpad);
1686
1687   /* copy segment, we need this because we still need the old
1688    * segment when we close the current segment. */
1689   memcpy (&seeksegment, &qtdemux->segment, sizeof (GstSegment));
1690
1691   if (event) {
1692     /* configure the segment with the seek variables */
1693     GST_DEBUG_OBJECT (qtdemux, "configuring seek");
1694     if (!gst_segment_do_seek (&seeksegment, rate, format, flags,
1695             cur_type, cur, stop_type, stop, &update)) {
1696       ret = FALSE;
1697       GST_ERROR_OBJECT (qtdemux, "inconsistent seek values, doing nothing");
1698     } else {
1699       /* now do the seek */
1700       ret = gst_qtdemux_perform_seek (qtdemux, &seeksegment, seqnum, flags);
1701     }
1702   } else {
1703     /* now do the seek */
1704     ret = gst_qtdemux_perform_seek (qtdemux, &seeksegment, seqnum, flags);
1705   }
1706
1707   /* prepare for streaming again */
1708   if (flush) {
1709     flush_event = gst_event_new_flush_stop (TRUE);
1710     if (seqnum != GST_SEQNUM_INVALID)
1711       gst_event_set_seqnum (flush_event, seqnum);
1712
1713     gst_pad_push_event (qtdemux->sinkpad, gst_event_ref (flush_event));
1714     gst_qtdemux_push_event (qtdemux, flush_event);
1715   }
1716
1717   /* commit the new segment */
1718   memcpy (&qtdemux->segment, &seeksegment, sizeof (GstSegment));
1719
1720   if (qtdemux->segment.flags & GST_SEEK_FLAG_SEGMENT) {
1721     GstMessage *msg = gst_message_new_segment_start (GST_OBJECT_CAST (qtdemux),
1722         qtdemux->segment.format, qtdemux->segment.position);
1723     if (seqnum != GST_SEQNUM_INVALID)
1724       gst_message_set_seqnum (msg, seqnum);
1725     gst_element_post_message (GST_ELEMENT_CAST (qtdemux), msg);
1726   }
1727
1728   /* restart streaming, NEWSEGMENT will be sent from the streaming thread. */
1729   gst_pad_start_task (qtdemux->sinkpad, (GstTaskFunction) gst_qtdemux_loop,
1730       qtdemux->sinkpad, NULL);
1731
1732   GST_PAD_STREAM_UNLOCK (qtdemux->sinkpad);
1733
1734   return ret;
1735
1736   /* ERRORS */
1737 no_format:
1738   {
1739     GST_DEBUG_OBJECT (qtdemux, "unsupported format given, seek aborted.");
1740     return FALSE;
1741   }
1742 }
1743
1744 static gboolean
1745 qtdemux_ensure_index (GstQTDemux * qtdemux)
1746 {
1747   guint i;
1748
1749   GST_DEBUG_OBJECT (qtdemux, "collecting all metadata for all streams");
1750
1751   /* Build complete index */
1752   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
1753     QtDemuxStream *stream = QTDEMUX_NTH_STREAM (qtdemux, i);
1754
1755     if (!qtdemux_parse_samples (qtdemux, stream, stream->n_samples - 1)) {
1756       GST_LOG_OBJECT (qtdemux,
1757           "Building complete index of track-id %u for seeking failed!",
1758           stream->track_id);
1759       return FALSE;
1760     }
1761   }
1762
1763   return TRUE;
1764 }
1765
1766 static gboolean
1767 gst_qtdemux_handle_src_event (GstPad * pad, GstObject * parent,
1768     GstEvent * event)
1769 {
1770   gboolean res = TRUE;
1771   GstQTDemux *qtdemux = GST_QTDEMUX (parent);
1772
1773   switch (GST_EVENT_TYPE (event)) {
1774     case GST_EVENT_SEEK:
1775     {
1776 #ifndef GST_DISABLE_GST_DEBUG
1777       GstClockTime ts = gst_util_get_timestamp ();
1778 #endif
1779       guint32 seqnum = gst_event_get_seqnum (event);
1780
1781       qtdemux->received_seek = TRUE;
1782
1783       if (seqnum == qtdemux->segment_seqnum) {
1784         GST_LOG_OBJECT (pad,
1785             "Drop duplicated SEEK event seqnum %" G_GUINT32_FORMAT, seqnum);
1786         gst_event_unref (event);
1787         return TRUE;
1788       }
1789
1790       if (qtdemux->upstream_format_is_time && qtdemux->fragmented) {
1791         /* seek should be handled by upstream, we might need to re-download fragments */
1792         GST_DEBUG_OBJECT (qtdemux,
1793             "let upstream handle seek for fragmented playback");
1794         goto upstream;
1795       }
1796
1797       /* Build complete index for seeking;
1798        * if not a fragmented file at least */
1799       if (!qtdemux->fragmented)
1800         if (!qtdemux_ensure_index (qtdemux))
1801           goto index_failed;
1802 #ifndef GST_DISABLE_GST_DEBUG
1803       ts = gst_util_get_timestamp () - ts;
1804       GST_INFO_OBJECT (qtdemux,
1805           "Time taken to parse index %" GST_TIME_FORMAT, GST_TIME_ARGS (ts));
1806 #endif
1807     }
1808       if (qtdemux->pullbased) {
1809         res = gst_qtdemux_do_seek (qtdemux, pad, event);
1810       } else if (gst_pad_push_event (qtdemux->sinkpad, gst_event_ref (event))) {
1811         GST_DEBUG_OBJECT (qtdemux, "Upstream successfully seeked");
1812         res = TRUE;
1813       } else if (qtdemux->state == QTDEMUX_STATE_MOVIE
1814           && QTDEMUX_N_STREAMS (qtdemux)
1815           && !qtdemux->fragmented) {
1816         res = gst_qtdemux_do_push_seek (qtdemux, pad, event);
1817       } else {
1818         GST_DEBUG_OBJECT (qtdemux,
1819             "ignoring seek in push mode in current state");
1820         res = FALSE;
1821       }
1822       gst_event_unref (event);
1823       break;
1824     default:
1825     upstream:
1826       res = gst_pad_event_default (pad, parent, event);
1827       break;
1828   }
1829
1830 done:
1831   return res;
1832
1833   /* ERRORS */
1834 index_failed:
1835   {
1836     GST_ERROR_OBJECT (qtdemux, "Index failed");
1837     gst_event_unref (event);
1838     res = FALSE;
1839     goto done;
1840   }
1841 }
1842
1843 /* Find, for each track, the first sample in coding order that has a file offset >= @byte_pos.
1844  *
1845  * If @fw is false, the coding order is explored backwards.
1846  *
1847  * If @set is true, each stream will be moved to its matched sample, or EOS if no matching
1848  * sample is found for that track.
1849  *
1850  * The stream and sample index of the sample with the minimum offset in the direction explored
1851  * (see @fw) is returned in the output parameters @_stream and @_index respectively.
1852  *
1853  * @_time is set to the QTSAMPLE_PTS of the matched sample with the minimum QTSAMPLE_PTS in the
1854  * direction explored, which may not always match the QTSAMPLE_PTS of the sample returned in
1855  * @_stream and @_index. */
1856 static void
1857 gst_qtdemux_find_sample (GstQTDemux * qtdemux, gint64 byte_pos, gboolean fw,
1858     gboolean set, QtDemuxStream ** _stream, gint * _index, gint64 * _time)
1859 {
1860   gint i, index;
1861   gint64 time, min_time;
1862   QtDemuxStream *stream;
1863   gint iter;
1864
1865   min_time = -1;
1866   stream = NULL;
1867   index = -1;
1868
1869   for (iter = 0; iter < QTDEMUX_N_STREAMS (qtdemux); iter++) {
1870     QtDemuxStream *str;
1871     gint inc;
1872     gboolean set_sample;
1873
1874     str = QTDEMUX_NTH_STREAM (qtdemux, iter);
1875     set_sample = !set;
1876
1877     if (fw) {
1878       i = 0;
1879       inc = 1;
1880     } else {
1881       i = str->n_samples - 1;
1882       inc = -1;
1883     }
1884
1885     for (; (i >= 0) && (i < str->n_samples); i += inc) {
1886       if (str->samples[i].size == 0)
1887         continue;
1888
1889       if (fw && (str->samples[i].offset < byte_pos))
1890         continue;
1891
1892       if (!fw && (str->samples[i].offset + str->samples[i].size > byte_pos))
1893         continue;
1894
1895       /* move stream to first available sample */
1896       if (set) {
1897         gst_qtdemux_move_stream (qtdemux, str, i);
1898         set_sample = TRUE;
1899       }
1900
1901       /* avoid index from sparse streams since they might be far away */
1902       if (!CUR_STREAM (str)->sparse) {
1903         /* determine min/max time */
1904         time = QTSAMPLE_PTS (str, &str->samples[i]);
1905         if (min_time == -1 || (!fw && time > min_time) ||
1906             (fw && time < min_time)) {
1907           min_time = time;
1908         }
1909
1910         /* determine stream with leading sample, to get its position */
1911         if (!stream ||
1912             (fw && (str->samples[i].offset < stream->samples[index].offset)) ||
1913             (!fw && (str->samples[i].offset > stream->samples[index].offset))) {
1914           stream = str;
1915           index = i;
1916         }
1917       }
1918       break;
1919     }
1920
1921     /* no sample for this stream, mark eos */
1922     if (!set_sample)
1923       gst_qtdemux_move_stream (qtdemux, str, str->n_samples);
1924   }
1925
1926   if (_time)
1927     *_time = min_time;
1928   if (_stream)
1929     *_stream = stream;
1930   if (_index)
1931     *_index = index;
1932 }
1933
1934 /* Copied from mpegtsbase code */
1935 /* FIXME: replace this function when we add new util function for stream-id creation */
1936 static gchar *
1937 _get_upstream_id (GstQTDemux * demux)
1938 {
1939   gchar *upstream_id = gst_pad_get_stream_id (demux->sinkpad);
1940
1941   if (!upstream_id) {
1942     /* Try to create one from the upstream URI, else use a randome number */
1943     GstQuery *query;
1944     gchar *uri = NULL;
1945
1946     /* Try to generate one from the URI query and
1947      * if it fails take a random number instead */
1948     query = gst_query_new_uri ();
1949     if (gst_element_query (GST_ELEMENT_CAST (demux), query)) {
1950       gst_query_parse_uri (query, &uri);
1951     }
1952
1953     if (uri) {
1954       GChecksum *cs;
1955
1956       /* And then generate an SHA256 sum of the URI */
1957       cs = g_checksum_new (G_CHECKSUM_SHA256);
1958       g_checksum_update (cs, (const guchar *) uri, strlen (uri));
1959       g_free (uri);
1960       upstream_id = g_strdup (g_checksum_get_string (cs));
1961       g_checksum_free (cs);
1962     } else {
1963       /* Just get some random number if the URI query fails */
1964       GST_FIXME_OBJECT (demux, "Creating random stream-id, consider "
1965           "implementing a deterministic way of creating a stream-id");
1966       upstream_id =
1967           g_strdup_printf ("%08x%08x%08x%08x", g_random_int (), g_random_int (),
1968           g_random_int (), g_random_int ());
1969     }
1970
1971     gst_query_unref (query);
1972   }
1973   return upstream_id;
1974 }
1975
1976 static QtDemuxStream *
1977 _create_stream (GstQTDemux * demux, guint32 track_id)
1978 {
1979   QtDemuxStream *stream;
1980   gchar *upstream_id;
1981
1982   stream = g_new0 (QtDemuxStream, 1);
1983   stream->demux = demux;
1984   stream->track_id = track_id;
1985   upstream_id = _get_upstream_id (demux);
1986   stream->stream_id = g_strdup_printf ("%s/%03u", upstream_id, track_id);
1987   g_free (upstream_id);
1988   /* new streams always need a discont */
1989   stream->discont = TRUE;
1990   /* we enable clipping for raw audio/video streams */
1991   stream->need_clip = FALSE;
1992   stream->need_process = FALSE;
1993   stream->segment_index = -1;
1994   stream->time_position = 0;
1995   stream->sample_index = -1;
1996   stream->offset_in_sample = 0;
1997   stream->new_stream = TRUE;
1998   stream->multiview_mode = GST_VIDEO_MULTIVIEW_MODE_NONE;
1999   stream->multiview_flags = GST_VIDEO_MULTIVIEW_FLAGS_NONE;
2000   stream->protected = FALSE;
2001   stream->protection_scheme_type = 0;
2002   stream->protection_scheme_version = 0;
2003   stream->protection_scheme_info = NULL;
2004   stream->n_samples_moof = 0;
2005   stream->duration_moof = 0;
2006   stream->duration_last_moof = 0;
2007   stream->alignment = 1;
2008   stream->stream_tags = gst_tag_list_new_empty ();
2009   gst_tag_list_set_scope (stream->stream_tags, GST_TAG_SCOPE_STREAM);
2010   g_queue_init (&stream->protection_scheme_event_queue);
2011   stream->ref_count = 1;
2012   /* consistent default for push based mode */
2013   gst_segment_init (&stream->segment, GST_FORMAT_TIME);
2014   return stream;
2015 }
2016
2017 static gboolean
2018 gst_qtdemux_setcaps (GstQTDemux * demux, GstCaps * caps)
2019 {
2020   GstStructure *structure;
2021   const gchar *variant;
2022   const GstCaps *mediacaps = NULL;
2023
2024   GST_DEBUG_OBJECT (demux, "Sink set caps: %" GST_PTR_FORMAT, caps);
2025
2026   structure = gst_caps_get_structure (caps, 0);
2027   variant = gst_structure_get_string (structure, "variant");
2028
2029   if (variant && strcmp (variant, "mss-fragmented") == 0) {
2030     QtDemuxStream *stream;
2031     const GValue *value;
2032
2033     demux->fragmented = TRUE;
2034     demux->mss_mode = TRUE;
2035
2036     if (QTDEMUX_N_STREAMS (demux) > 1) {
2037       /* can't do this, we can only renegotiate for another mss format */
2038       return FALSE;
2039     }
2040
2041     value = gst_structure_get_value (structure, "media-caps");
2042     /* create stream */
2043     if (value) {
2044       const GValue *timescale_v;
2045
2046       /* TODO update when stream changes during playback */
2047
2048       if (QTDEMUX_N_STREAMS (demux) == 0) {
2049         stream = _create_stream (demux, 1);
2050         g_ptr_array_add (demux->active_streams, stream);
2051         /* mss has no stsd/stsd entry, use id 0 as default */
2052         stream->stsd_entries_length = 1;
2053         stream->stsd_sample_description_id = stream->cur_stsd_entry_index = 0;
2054         stream->stsd_entries = g_new0 (QtDemuxStreamStsdEntry, 1);
2055       } else {
2056         stream = QTDEMUX_NTH_STREAM (demux, 0);
2057       }
2058
2059       timescale_v = gst_structure_get_value (structure, "timescale");
2060       if (timescale_v) {
2061         stream->timescale = g_value_get_uint64 (timescale_v);
2062       } else {
2063         /* default mss timescale */
2064         stream->timescale = 10000000;
2065       }
2066       demux->timescale = stream->timescale;
2067
2068       mediacaps = gst_value_get_caps (value);
2069       if (!CUR_STREAM (stream)->caps
2070           || !gst_caps_is_equal_fixed (mediacaps, CUR_STREAM (stream)->caps)) {
2071         GST_DEBUG_OBJECT (demux, "We have a new caps %" GST_PTR_FORMAT,
2072             mediacaps);
2073         stream->new_caps = TRUE;
2074       }
2075       gst_caps_replace (&CUR_STREAM (stream)->caps, (GstCaps *) mediacaps);
2076       structure = gst_caps_get_structure (mediacaps, 0);
2077       if (g_str_has_prefix (gst_structure_get_name (structure), "video")) {
2078         stream->subtype = FOURCC_vide;
2079
2080         gst_structure_get_int (structure, "width", &CUR_STREAM (stream)->width);
2081         gst_structure_get_int (structure, "height",
2082             &CUR_STREAM (stream)->height);
2083         gst_structure_get_fraction (structure, "framerate",
2084             &CUR_STREAM (stream)->fps_n, &CUR_STREAM (stream)->fps_d);
2085       } else if (g_str_has_prefix (gst_structure_get_name (structure), "audio")) {
2086         gint rate = 0;
2087         stream->subtype = FOURCC_soun;
2088         gst_structure_get_int (structure, "channels",
2089             &CUR_STREAM (stream)->n_channels);
2090         gst_structure_get_int (structure, "rate", &rate);
2091         CUR_STREAM (stream)->rate = rate;
2092       }
2093     }
2094     gst_caps_replace (&demux->media_caps, (GstCaps *) mediacaps);
2095   } else {
2096     demux->mss_mode = FALSE;
2097   }
2098
2099   return TRUE;
2100 }
2101
2102 static void
2103 gst_qtdemux_reset (GstQTDemux * qtdemux, gboolean hard)
2104 {
2105   gint i;
2106
2107   GST_DEBUG_OBJECT (qtdemux, "Resetting demux");
2108   gst_pad_stop_task (qtdemux->sinkpad);
2109
2110   if (hard || qtdemux->upstream_format_is_time) {
2111     qtdemux->state = QTDEMUX_STATE_INITIAL;
2112     qtdemux->neededbytes = 16;
2113     qtdemux->todrop = 0;
2114     qtdemux->pullbased = FALSE;
2115     qtdemux->posted_redirect = FALSE;
2116     qtdemux->first_mdat = -1;
2117     qtdemux->header_size = 0;
2118     qtdemux->mdatoffset = -1;
2119     qtdemux->restoredata_offset = -1;
2120     if (qtdemux->mdatbuffer)
2121       gst_buffer_unref (qtdemux->mdatbuffer);
2122     if (qtdemux->restoredata_buffer)
2123       gst_buffer_unref (qtdemux->restoredata_buffer);
2124     qtdemux->mdatbuffer = NULL;
2125     qtdemux->restoredata_buffer = NULL;
2126     qtdemux->mdatleft = 0;
2127     qtdemux->mdatsize = 0;
2128     if (qtdemux->comp_brands)
2129       gst_buffer_unref (qtdemux->comp_brands);
2130     qtdemux->comp_brands = NULL;
2131     qtdemux->last_moov_offset = -1;
2132     if (qtdemux->moov_node_compressed) {
2133       g_node_destroy (qtdemux->moov_node_compressed);
2134       if (qtdemux->moov_node)
2135         g_free (qtdemux->moov_node->data);
2136     }
2137     qtdemux->moov_node_compressed = NULL;
2138     if (qtdemux->moov_node)
2139       g_node_destroy (qtdemux->moov_node);
2140     qtdemux->moov_node = NULL;
2141     if (qtdemux->tag_list)
2142       gst_mini_object_unref (GST_MINI_OBJECT_CAST (qtdemux->tag_list));
2143     qtdemux->tag_list = gst_tag_list_new_empty ();
2144     gst_tag_list_set_scope (qtdemux->tag_list, GST_TAG_SCOPE_GLOBAL);
2145 #if 0
2146     if (qtdemux->element_index)
2147       gst_object_unref (qtdemux->element_index);
2148     qtdemux->element_index = NULL;
2149 #endif
2150     qtdemux->major_brand = 0;
2151     qtdemux->upstream_format_is_time = FALSE;
2152     qtdemux->upstream_seekable = FALSE;
2153     qtdemux->upstream_size = 0;
2154
2155     qtdemux->fragment_start = -1;
2156     qtdemux->fragment_start_offset = -1;
2157     qtdemux->duration = 0;
2158     qtdemux->moof_offset = 0;
2159     qtdemux->chapters_track_id = 0;
2160     qtdemux->have_group_id = FALSE;
2161     qtdemux->group_id = G_MAXUINT;
2162
2163     g_queue_foreach (&qtdemux->protection_event_queue, (GFunc) gst_event_unref,
2164         NULL);
2165     g_queue_clear (&qtdemux->protection_event_queue);
2166
2167     qtdemux->received_seek = FALSE;
2168     qtdemux->first_moof_already_parsed = FALSE;
2169   }
2170   qtdemux->offset = 0;
2171   gst_adapter_clear (qtdemux->adapter);
2172   gst_segment_init (&qtdemux->segment, GST_FORMAT_TIME);
2173   qtdemux->need_segment = TRUE;
2174
2175   if (hard) {
2176     qtdemux->segment_seqnum = GST_SEQNUM_INVALID;
2177     g_ptr_array_remove_range (qtdemux->active_streams,
2178         0, qtdemux->active_streams->len);
2179     g_ptr_array_remove_range (qtdemux->old_streams,
2180         0, qtdemux->old_streams->len);
2181     qtdemux->n_video_streams = 0;
2182     qtdemux->n_audio_streams = 0;
2183     qtdemux->n_sub_streams = 0;
2184     qtdemux->exposed = FALSE;
2185     qtdemux->fragmented = FALSE;
2186     qtdemux->mss_mode = FALSE;
2187     gst_caps_replace (&qtdemux->media_caps, NULL);
2188     qtdemux->timescale = 0;
2189     qtdemux->got_moov = FALSE;
2190     qtdemux->cenc_aux_info_offset = 0;
2191     qtdemux->cenc_aux_info_sizes = NULL;
2192     qtdemux->cenc_aux_sample_count = 0;
2193     if (qtdemux->protection_system_ids) {
2194       g_ptr_array_free (qtdemux->protection_system_ids, TRUE);
2195       qtdemux->protection_system_ids = NULL;
2196     }
2197     qtdemux->streams_aware = GST_OBJECT_PARENT (qtdemux)
2198         && GST_OBJECT_FLAG_IS_SET (GST_OBJECT_PARENT (qtdemux),
2199         GST_BIN_FLAG_STREAMS_AWARE);
2200
2201     if (qtdemux->preferred_protection_system_id) {
2202       g_free (qtdemux->preferred_protection_system_id);
2203       qtdemux->preferred_protection_system_id = NULL;
2204     }
2205   } else if (qtdemux->mss_mode) {
2206     gst_flow_combiner_reset (qtdemux->flowcombiner);
2207     g_ptr_array_foreach (qtdemux->active_streams,
2208         (GFunc) gst_qtdemux_stream_clear, NULL);
2209   } else {
2210     gst_flow_combiner_reset (qtdemux->flowcombiner);
2211     for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
2212       QtDemuxStream *stream = QTDEMUX_NTH_STREAM (qtdemux, i);
2213       stream->sent_eos = FALSE;
2214       stream->time_position = 0;
2215       stream->accumulated_base = 0;
2216     }
2217   }
2218 }
2219
2220
2221 /* Maps the @segment to the qt edts internal segments and pushes
2222  * the correspnding segment event.
2223  *
2224  * If it ends up being at a empty segment, a gap will be pushed and the next
2225  * edts segment will be activated in sequence.
2226  *
2227  * To be used in push-mode only */
2228 static void
2229 gst_qtdemux_map_and_push_segments (GstQTDemux * qtdemux, GstSegment * segment)
2230 {
2231   gint i, iter;
2232
2233   for (iter = 0; iter < QTDEMUX_N_STREAMS (qtdemux); iter++) {
2234     QtDemuxStream *stream = QTDEMUX_NTH_STREAM (qtdemux, iter);
2235
2236     stream->time_position = segment->start;
2237
2238     /* in push mode we should be guaranteed that we will have empty segments
2239      * at the beginning and then one segment after, other scenarios are not
2240      * supported and are discarded when parsing the edts */
2241     for (i = 0; i < stream->n_segments; i++) {
2242       if (stream->segments[i].stop_time > segment->start) {
2243         /* push the empty segment and move to the next one */
2244         gst_qtdemux_activate_segment (qtdemux, stream, i,
2245             stream->time_position);
2246         if (QTSEGMENT_IS_EMPTY (&stream->segments[i])) {
2247           gst_qtdemux_send_gap_for_segment (qtdemux, stream, i,
2248               stream->time_position);
2249
2250           /* accumulate previous segments */
2251           if (GST_CLOCK_TIME_IS_VALID (stream->segment.stop))
2252             stream->accumulated_base +=
2253                 (stream->segment.stop -
2254                 stream->segment.start) / ABS (stream->segment.rate);
2255           continue;
2256         }
2257
2258         g_assert (i == stream->n_segments - 1);
2259       }
2260     }
2261   }
2262 }
2263
2264 static void
2265 gst_qtdemux_stream_concat (GstQTDemux * qtdemux, GPtrArray * dest,
2266     GPtrArray * src)
2267 {
2268   guint i;
2269   guint len;
2270
2271   len = src->len;
2272
2273   if (len == 0)
2274     return;
2275
2276   for (i = 0; i < len; i++) {
2277     QtDemuxStream *stream = g_ptr_array_index (src, i);
2278
2279 #ifndef GST_DISABLE_GST_DEBUG
2280     GST_DEBUG_OBJECT (qtdemux, "Move stream %p (stream-id %s) to %p",
2281         stream, GST_STR_NULL (stream->stream_id), dest);
2282 #endif
2283     g_ptr_array_add (dest, gst_qtdemux_stream_ref (stream));
2284   }
2285
2286   g_ptr_array_remove_range (src, 0, len);
2287 }
2288
2289 static gboolean
2290 gst_qtdemux_handle_sink_event (GstPad * sinkpad, GstObject * parent,
2291     GstEvent * event)
2292 {
2293   GstQTDemux *demux = GST_QTDEMUX (parent);
2294   gboolean res = TRUE;
2295
2296   GST_LOG_OBJECT (demux, "handling %s event", GST_EVENT_TYPE_NAME (event));
2297
2298   switch (GST_EVENT_TYPE (event)) {
2299     case GST_EVENT_SEGMENT:
2300     {
2301       gint64 offset = 0;
2302       QtDemuxStream *stream;
2303       gint idx;
2304       GstSegment segment;
2305
2306       /* some debug output */
2307       gst_event_copy_segment (event, &segment);
2308       GST_DEBUG_OBJECT (demux, "received newsegment %" GST_SEGMENT_FORMAT,
2309           &segment);
2310
2311       if (segment.format == GST_FORMAT_TIME) {
2312         demux->upstream_format_is_time = TRUE;
2313         demux->segment_seqnum = gst_event_get_seqnum (event);
2314       } else {
2315         GST_DEBUG_OBJECT (demux, "Not storing upstream newsegment, "
2316             "not in time format");
2317
2318         /* chain will send initial newsegment after pads have been added */
2319         if (demux->state != QTDEMUX_STATE_MOVIE || !QTDEMUX_N_STREAMS (demux)) {
2320           GST_DEBUG_OBJECT (demux, "still starting, eating event");
2321           goto exit;
2322         }
2323       }
2324
2325       /* check if this matches a time seek we received previously
2326        * FIXME for backwards compatibility reasons we use the
2327        * seek_offset here to compare. In the future we might want to
2328        * change this to use the seqnum as it uniquely should identify
2329        * the segment that corresponds to the seek. */
2330       GST_DEBUG_OBJECT (demux, "Stored seek offset: %" G_GINT64_FORMAT
2331           ", received segment offset %" G_GINT64_FORMAT,
2332           demux->seek_offset, segment.start);
2333       if (segment.format == GST_FORMAT_BYTES
2334           && demux->seek_offset == segment.start) {
2335         GST_OBJECT_LOCK (demux);
2336         offset = segment.start;
2337
2338         segment.format = GST_FORMAT_TIME;
2339         segment.start = demux->push_seek_start;
2340         segment.stop = demux->push_seek_stop;
2341         GST_DEBUG_OBJECT (demux, "Replaced segment with stored seek "
2342             "segment %" GST_TIME_FORMAT " - %" GST_TIME_FORMAT,
2343             GST_TIME_ARGS (segment.start), GST_TIME_ARGS (segment.stop));
2344         GST_OBJECT_UNLOCK (demux);
2345       }
2346
2347       /* we only expect a BYTE segment, e.g. following a seek */
2348       if (segment.format == GST_FORMAT_BYTES) {
2349         if (GST_CLOCK_TIME_IS_VALID (segment.start)) {
2350           offset = segment.start;
2351
2352           gst_qtdemux_find_sample (demux, segment.start, TRUE, FALSE, NULL,
2353               NULL, (gint64 *) & segment.start);
2354           if ((gint64) segment.start < 0)
2355             segment.start = 0;
2356         }
2357         if (GST_CLOCK_TIME_IS_VALID (segment.stop)) {
2358           gst_qtdemux_find_sample (demux, segment.stop, FALSE, FALSE, NULL,
2359               NULL, (gint64 *) & segment.stop);
2360           /* keyframe seeking should already arrange for start >= stop,
2361            * but make sure in other rare cases */
2362           segment.stop = MAX (segment.stop, segment.start);
2363         }
2364       } else if (segment.format == GST_FORMAT_TIME) {
2365         /* push all data on the adapter before starting this
2366          * new segment */
2367         gst_qtdemux_process_adapter (demux, TRUE);
2368       } else {
2369         GST_DEBUG_OBJECT (demux, "unsupported segment format, ignoring");
2370         goto exit;
2371       }
2372
2373       /* We shouldn't modify upstream driven TIME FORMAT segment */
2374       if (!demux->upstream_format_is_time) {
2375         /* accept upstream's notion of segment and distribute along */
2376         segment.format = GST_FORMAT_TIME;
2377         segment.position = segment.time = segment.start;
2378         segment.duration = demux->segment.duration;
2379         segment.base = gst_segment_to_running_time (&demux->segment,
2380             GST_FORMAT_TIME, demux->segment.position);
2381       }
2382
2383       gst_segment_copy_into (&segment, &demux->segment);
2384       GST_DEBUG_OBJECT (demux, "Pushing newseg %" GST_SEGMENT_FORMAT, &segment);
2385
2386       /* map segment to internal qt segments and push on each stream */
2387       if (QTDEMUX_N_STREAMS (demux)) {
2388         demux->need_segment = TRUE;
2389         gst_qtdemux_check_send_pending_segment (demux);
2390       }
2391
2392       /* clear leftover in current segment, if any */
2393       gst_adapter_clear (demux->adapter);
2394
2395       /* set up streaming thread */
2396       demux->offset = offset;
2397       if (demux->upstream_format_is_time) {
2398         GST_DEBUG_OBJECT (demux, "Upstream is driving in time format, "
2399             "set values to restart reading from a new atom");
2400         demux->neededbytes = 16;
2401         demux->todrop = 0;
2402       } else {
2403         gst_qtdemux_find_sample (demux, offset, TRUE, TRUE, &stream, &idx,
2404             NULL);
2405         if (stream) {
2406           demux->todrop = stream->samples[idx].offset - offset;
2407           demux->neededbytes = demux->todrop + stream->samples[idx].size;
2408         } else {
2409           /* set up for EOS */
2410           demux->neededbytes = -1;
2411           demux->todrop = 0;
2412         }
2413       }
2414     exit:
2415       gst_event_unref (event);
2416       res = TRUE;
2417       goto drop;
2418     }
2419     case GST_EVENT_FLUSH_START:
2420     {
2421       if (gst_event_get_seqnum (event) == demux->offset_seek_seqnum) {
2422         gst_event_unref (event);
2423         goto drop;
2424       }
2425       QTDEMUX_EXPOSE_LOCK (demux);
2426       res = gst_pad_event_default (demux->sinkpad, parent, event);
2427       QTDEMUX_EXPOSE_UNLOCK (demux);
2428       goto drop;
2429     }
2430     case GST_EVENT_FLUSH_STOP:
2431     {
2432       guint64 dur;
2433
2434       dur = demux->segment.duration;
2435       gst_qtdemux_reset (demux, FALSE);
2436       demux->segment.duration = dur;
2437
2438       if (gst_event_get_seqnum (event) == demux->offset_seek_seqnum) {
2439         gst_event_unref (event);
2440         goto drop;
2441       }
2442       break;
2443     }
2444     case GST_EVENT_EOS:
2445       /* If we are in push mode, and get an EOS before we've seen any streams,
2446        * then error out - we have nowhere to send the EOS */
2447       if (!demux->pullbased) {
2448         gint i;
2449         gboolean has_valid_stream = FALSE;
2450         for (i = 0; i < QTDEMUX_N_STREAMS (demux); i++) {
2451           if (QTDEMUX_NTH_STREAM (demux, i)->pad != NULL) {
2452             has_valid_stream = TRUE;
2453             break;
2454           }
2455         }
2456         if (!has_valid_stream)
2457           gst_qtdemux_post_no_playable_stream_error (demux);
2458         else {
2459           GST_DEBUG_OBJECT (demux, "Data still available after EOS: %u",
2460               (guint) gst_adapter_available (demux->adapter));
2461           if (gst_qtdemux_process_adapter (demux, TRUE) != GST_FLOW_OK) {
2462             res = FALSE;
2463           }
2464         }
2465       }
2466       break;
2467     case GST_EVENT_CAPS:{
2468       GstCaps *caps = NULL;
2469
2470       gst_event_parse_caps (event, &caps);
2471       gst_qtdemux_setcaps (demux, caps);
2472       res = TRUE;
2473       gst_event_unref (event);
2474       goto drop;
2475     }
2476     case GST_EVENT_PROTECTION:
2477     {
2478       const gchar *system_id = NULL;
2479
2480       gst_event_parse_protection (event, &system_id, NULL, NULL);
2481       GST_DEBUG_OBJECT (demux, "Received protection event for system ID %s",
2482           system_id);
2483       gst_qtdemux_append_protection_system_id (demux, system_id);
2484       /* save the event for later, for source pads that have not been created */
2485       g_queue_push_tail (&demux->protection_event_queue, gst_event_ref (event));
2486       /* send it to all pads that already exist */
2487       gst_qtdemux_push_event (demux, event);
2488       res = TRUE;
2489       goto drop;
2490     }
2491     case GST_EVENT_STREAM_START:
2492     {
2493       res = TRUE;
2494       gst_event_unref (event);
2495
2496       /* Drain all the buffers */
2497       gst_qtdemux_process_adapter (demux, TRUE);
2498       gst_qtdemux_reset (demux, FALSE);
2499       /* We expect new moov box after new stream-start event */
2500       if (demux->exposed) {
2501         gst_qtdemux_stream_concat (demux,
2502             demux->old_streams, demux->active_streams);
2503       }
2504
2505       goto drop;
2506     }
2507     default:
2508       break;
2509   }
2510
2511   res = gst_pad_event_default (demux->sinkpad, parent, event) & res;
2512
2513 drop:
2514   return res;
2515 }
2516
2517 static gboolean
2518 gst_qtdemux_handle_sink_query (GstPad * pad, GstObject * parent,
2519     GstQuery * query)
2520 {
2521   GstQTDemux *demux = GST_QTDEMUX (parent);
2522   gboolean res = FALSE;
2523
2524   switch (GST_QUERY_TYPE (query)) {
2525     case GST_QUERY_BITRATE:
2526     {
2527       GstClockTime duration;
2528
2529       /* populate demux->upstream_size if not done yet */
2530       gst_qtdemux_check_seekability (demux);
2531
2532       if (demux->upstream_size != -1
2533           && gst_qtdemux_get_duration (demux, &duration)) {
2534         guint bitrate =
2535             gst_util_uint64_scale (8 * demux->upstream_size, GST_SECOND,
2536             duration);
2537
2538         GST_LOG_OBJECT (demux, "bitrate query byte length: %" G_GUINT64_FORMAT
2539             " duration %" GST_TIME_FORMAT " resulting a bitrate of %u",
2540             demux->upstream_size, GST_TIME_ARGS (duration), bitrate);
2541
2542         /* TODO: better results based on ranges/index tables */
2543         gst_query_set_bitrate (query, bitrate);
2544         res = TRUE;
2545       }
2546       break;
2547     }
2548     default:
2549       res = gst_pad_query_default (pad, (GstObject *) demux, query);
2550       break;
2551   }
2552
2553   return res;
2554 }
2555
2556
2557 #if 0
2558 static void
2559 gst_qtdemux_set_index (GstElement * element, GstIndex * index)
2560 {
2561   GstQTDemux *demux = GST_QTDEMUX (element);
2562
2563   GST_OBJECT_LOCK (demux);
2564   if (demux->element_index)
2565     gst_object_unref (demux->element_index);
2566   if (index) {
2567     demux->element_index = gst_object_ref (index);
2568   } else {
2569     demux->element_index = NULL;
2570   }
2571   GST_OBJECT_UNLOCK (demux);
2572   /* object lock might be taken again */
2573   if (index)
2574     gst_index_get_writer_id (index, GST_OBJECT (element), &demux->index_id);
2575   GST_DEBUG_OBJECT (demux, "Set index %" GST_PTR_FORMAT "for writer id %d",
2576       demux->element_index, demux->index_id);
2577 }
2578
2579 static GstIndex *
2580 gst_qtdemux_get_index (GstElement * element)
2581 {
2582   GstIndex *result = NULL;
2583   GstQTDemux *demux = GST_QTDEMUX (element);
2584
2585   GST_OBJECT_LOCK (demux);
2586   if (demux->element_index)
2587     result = gst_object_ref (demux->element_index);
2588   GST_OBJECT_UNLOCK (demux);
2589
2590   GST_DEBUG_OBJECT (demux, "Returning index %" GST_PTR_FORMAT, result);
2591
2592   return result;
2593 }
2594 #endif
2595
2596 static void
2597 gst_qtdemux_stbl_free (QtDemuxStream * stream)
2598 {
2599   g_free ((gpointer) stream->stco.data);
2600   stream->stco.data = NULL;
2601   g_free ((gpointer) stream->stsz.data);
2602   stream->stsz.data = NULL;
2603   g_free ((gpointer) stream->stsc.data);
2604   stream->stsc.data = NULL;
2605   g_free ((gpointer) stream->stts.data);
2606   stream->stts.data = NULL;
2607   g_free ((gpointer) stream->stss.data);
2608   stream->stss.data = NULL;
2609   g_free ((gpointer) stream->stps.data);
2610   stream->stps.data = NULL;
2611   g_free ((gpointer) stream->ctts.data);
2612   stream->ctts.data = NULL;
2613 }
2614
2615 static void
2616 gst_qtdemux_stream_flush_segments_data (QtDemuxStream * stream)
2617 {
2618   g_free (stream->segments);
2619   stream->segments = NULL;
2620   stream->segment_index = -1;
2621   stream->accumulated_base = 0;
2622 }
2623
2624 static void
2625 gst_qtdemux_stream_flush_samples_data (QtDemuxStream * stream)
2626 {
2627   g_free (stream->samples);
2628   stream->samples = NULL;
2629   gst_qtdemux_stbl_free (stream);
2630
2631   /* fragments */
2632   g_free (stream->ra_entries);
2633   stream->ra_entries = NULL;
2634   stream->n_ra_entries = 0;
2635
2636   stream->sample_index = -1;
2637   stream->stbl_index = -1;
2638   stream->n_samples = 0;
2639   stream->time_position = 0;
2640
2641   stream->n_samples_moof = 0;
2642   stream->duration_moof = 0;
2643   stream->duration_last_moof = 0;
2644 }
2645
2646 static void
2647 gst_qtdemux_stream_clear (QtDemuxStream * stream)
2648 {
2649   gint i;
2650   if (stream->allocator)
2651     gst_object_unref (stream->allocator);
2652   while (stream->buffers) {
2653     gst_buffer_unref (GST_BUFFER_CAST (stream->buffers->data));
2654     stream->buffers = g_slist_delete_link (stream->buffers, stream->buffers);
2655   }
2656   for (i = 0; i < stream->stsd_entries_length; i++) {
2657     QtDemuxStreamStsdEntry *entry = &stream->stsd_entries[i];
2658     if (entry->rgb8_palette) {
2659       gst_memory_unref (entry->rgb8_palette);
2660       entry->rgb8_palette = NULL;
2661     }
2662     entry->sparse = FALSE;
2663   }
2664
2665   if (stream->stream_tags)
2666     gst_tag_list_unref (stream->stream_tags);
2667
2668   stream->stream_tags = gst_tag_list_new_empty ();
2669   gst_tag_list_set_scope (stream->stream_tags, GST_TAG_SCOPE_STREAM);
2670   g_free (stream->redirect_uri);
2671   stream->redirect_uri = NULL;
2672   stream->sent_eos = FALSE;
2673   stream->protected = FALSE;
2674   if (stream->protection_scheme_info) {
2675     if (stream->protection_scheme_type == FOURCC_cenc) {
2676       QtDemuxCencSampleSetInfo *info =
2677           (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
2678       if (info->default_properties)
2679         gst_structure_free (info->default_properties);
2680       if (info->crypto_info)
2681         g_ptr_array_free (info->crypto_info, TRUE);
2682     }
2683     g_free (stream->protection_scheme_info);
2684     stream->protection_scheme_info = NULL;
2685   }
2686   stream->protection_scheme_type = 0;
2687   stream->protection_scheme_version = 0;
2688   g_queue_foreach (&stream->protection_scheme_event_queue,
2689       (GFunc) gst_event_unref, NULL);
2690   g_queue_clear (&stream->protection_scheme_event_queue);
2691   gst_qtdemux_stream_flush_segments_data (stream);
2692   gst_qtdemux_stream_flush_samples_data (stream);
2693 }
2694
2695 static void
2696 gst_qtdemux_stream_reset (QtDemuxStream * stream)
2697 {
2698   gint i;
2699   gst_qtdemux_stream_clear (stream);
2700   for (i = 0; i < stream->stsd_entries_length; i++) {
2701     QtDemuxStreamStsdEntry *entry = &stream->stsd_entries[i];
2702     if (entry->caps) {
2703       gst_caps_unref (entry->caps);
2704       entry->caps = NULL;
2705     }
2706   }
2707   g_free (stream->stsd_entries);
2708   stream->stsd_entries = NULL;
2709   stream->stsd_entries_length = 0;
2710 }
2711
2712 static QtDemuxStream *
2713 gst_qtdemux_stream_ref (QtDemuxStream * stream)
2714 {
2715   g_atomic_int_add (&stream->ref_count, 1);
2716
2717   return stream;
2718 }
2719
2720 static void
2721 gst_qtdemux_stream_unref (QtDemuxStream * stream)
2722 {
2723   if (g_atomic_int_dec_and_test (&stream->ref_count)) {
2724     gst_qtdemux_stream_reset (stream);
2725     gst_tag_list_unref (stream->stream_tags);
2726     if (stream->pad) {
2727       GstQTDemux *demux = stream->demux;
2728       gst_element_remove_pad (GST_ELEMENT_CAST (demux), stream->pad);
2729       gst_flow_combiner_remove_pad (demux->flowcombiner, stream->pad);
2730     }
2731     g_free (stream->stream_id);
2732     g_free (stream);
2733   }
2734 }
2735
2736 static GstStateChangeReturn
2737 gst_qtdemux_change_state (GstElement * element, GstStateChange transition)
2738 {
2739   GstQTDemux *qtdemux = GST_QTDEMUX (element);
2740   GstStateChangeReturn result = GST_STATE_CHANGE_FAILURE;
2741
2742   switch (transition) {
2743     case GST_STATE_CHANGE_READY_TO_PAUSED:
2744       gst_qtdemux_reset (qtdemux, TRUE);
2745       break;
2746     default:
2747       break;
2748   }
2749
2750   result = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
2751
2752   switch (transition) {
2753     case GST_STATE_CHANGE_PAUSED_TO_READY:{
2754       gst_qtdemux_reset (qtdemux, TRUE);
2755       break;
2756     }
2757     default:
2758       break;
2759   }
2760
2761   return result;
2762 }
2763
2764 static void
2765 gst_qtdemux_set_context (GstElement * element, GstContext * context)
2766 {
2767   GstQTDemux *qtdemux = GST_QTDEMUX (element);
2768
2769   g_return_if_fail (GST_IS_CONTEXT (context));
2770
2771   if (gst_context_has_context_type (context,
2772           "drm-preferred-decryption-system-id")) {
2773     const GstStructure *s;
2774
2775     s = gst_context_get_structure (context);
2776     g_free (qtdemux->preferred_protection_system_id);
2777     qtdemux->preferred_protection_system_id =
2778         g_strdup (gst_structure_get_string (s, "decryption-system-id"));
2779     GST_DEBUG_OBJECT (element, "set preferred decryption system to %s",
2780         qtdemux->preferred_protection_system_id);
2781   }
2782
2783   GST_ELEMENT_CLASS (parent_class)->set_context (element, context);
2784 }
2785
2786 static void
2787 qtdemux_parse_ftyp (GstQTDemux * qtdemux, const guint8 * buffer, gint length)
2788 {
2789   /* counts as header data */
2790   qtdemux->header_size += length;
2791
2792   /* only consider at least a sufficiently complete ftyp atom */
2793   if (length >= 20) {
2794     GstBuffer *buf;
2795
2796     qtdemux->major_brand = QT_FOURCC (buffer + 8);
2797     GST_DEBUG_OBJECT (qtdemux, "major brand: %" GST_FOURCC_FORMAT,
2798         GST_FOURCC_ARGS (qtdemux->major_brand));
2799     if (qtdemux->comp_brands)
2800       gst_buffer_unref (qtdemux->comp_brands);
2801     buf = qtdemux->comp_brands = gst_buffer_new_and_alloc (length - 16);
2802     gst_buffer_fill (buf, 0, buffer + 16, length - 16);
2803   }
2804 }
2805
2806 static void
2807 qtdemux_handle_xmp_taglist (GstQTDemux * qtdemux, GstTagList * taglist,
2808     GstTagList * xmptaglist)
2809 {
2810   /* Strip out bogus fields */
2811   if (xmptaglist) {
2812     if (gst_tag_list_get_scope (taglist) == GST_TAG_SCOPE_GLOBAL) {
2813       gst_tag_list_remove_tag (xmptaglist, GST_TAG_VIDEO_CODEC);
2814       gst_tag_list_remove_tag (xmptaglist, GST_TAG_AUDIO_CODEC);
2815     } else {
2816       gst_tag_list_remove_tag (xmptaglist, GST_TAG_CONTAINER_FORMAT);
2817     }
2818
2819     GST_DEBUG_OBJECT (qtdemux, "Found XMP tags %" GST_PTR_FORMAT, xmptaglist);
2820
2821     /* prioritize native tags using _KEEP mode */
2822     gst_tag_list_insert (taglist, xmptaglist, GST_TAG_MERGE_KEEP);
2823     gst_tag_list_unref (xmptaglist);
2824   }
2825 }
2826
2827 static void
2828 qtdemux_update_default_sample_encryption_settings (GstQTDemux * qtdemux,
2829     QtDemuxCencSampleSetInfo * info, guint32 is_encrypted, guint8 iv_size,
2830     const guint8 * kid)
2831 {
2832   GstBuffer *kid_buf = gst_buffer_new_allocate (NULL, 16, NULL);
2833   gst_buffer_fill (kid_buf, 0, kid, 16);
2834   if (info->default_properties)
2835     gst_structure_free (info->default_properties);
2836   info->default_properties =
2837       gst_structure_new ("application/x-cenc",
2838       "iv_size", G_TYPE_UINT, iv_size,
2839       "encrypted", G_TYPE_BOOLEAN, (is_encrypted == 1),
2840       "kid", GST_TYPE_BUFFER, kid_buf, NULL);
2841   GST_DEBUG_OBJECT (qtdemux, "default sample properties: "
2842       "is_encrypted=%u, iv_size=%u", is_encrypted, iv_size);
2843   gst_buffer_unref (kid_buf);
2844 }
2845
2846 static gboolean
2847 qtdemux_update_default_piff_encryption_settings (GstQTDemux * qtdemux,
2848     QtDemuxCencSampleSetInfo * info, GstByteReader * br)
2849 {
2850   guint32 algorithm_id = 0;
2851   const guint8 *kid;
2852   gboolean is_encrypted = TRUE;
2853   guint8 iv_size = 8;
2854
2855   if (!gst_byte_reader_get_uint24_le (br, &algorithm_id)) {
2856     GST_ERROR_OBJECT (qtdemux, "Error getting box's algorithm ID field");
2857     return FALSE;
2858   }
2859
2860   algorithm_id >>= 8;
2861   if (algorithm_id == 0) {
2862     is_encrypted = FALSE;
2863   } else if (algorithm_id == 1) {
2864     GST_DEBUG_OBJECT (qtdemux, "AES 128-bits CTR encrypted stream");
2865   } else if (algorithm_id == 2) {
2866     GST_DEBUG_OBJECT (qtdemux, "AES 128-bits CBC encrypted stream");
2867   }
2868
2869   if (!gst_byte_reader_get_uint8 (br, &iv_size))
2870     return FALSE;
2871
2872   if (!gst_byte_reader_get_data (br, 16, &kid))
2873     return FALSE;
2874
2875   qtdemux_update_default_sample_encryption_settings (qtdemux, info,
2876       is_encrypted, iv_size, kid);
2877   gst_structure_set (info->default_properties, "piff_algorithm_id",
2878       G_TYPE_UINT, algorithm_id, NULL);
2879   return TRUE;
2880 }
2881
2882
2883 static void
2884 qtdemux_parse_piff (GstQTDemux * qtdemux, const guint8 * buffer, gint length,
2885     guint offset)
2886 {
2887   GstByteReader br;
2888   guint8 version;
2889   guint32 flags = 0;
2890   guint i;
2891   guint iv_size = 8;
2892   QtDemuxStream *stream;
2893   GstStructure *structure;
2894   QtDemuxCencSampleSetInfo *ss_info = NULL;
2895   const gchar *system_id;
2896   gboolean uses_sub_sample_encryption = FALSE;
2897   guint32 sample_count;
2898
2899   if (QTDEMUX_N_STREAMS (qtdemux) == 0)
2900     return;
2901
2902   stream = QTDEMUX_NTH_STREAM (qtdemux, 0);
2903
2904   structure = gst_caps_get_structure (CUR_STREAM (stream)->caps, 0);
2905   if (!gst_structure_has_name (structure, "application/x-cenc")) {
2906     GST_WARNING_OBJECT (qtdemux,
2907         "Attempting PIFF box parsing on an unencrypted stream.");
2908     return;
2909   }
2910
2911   gst_structure_get (structure, GST_PROTECTION_SYSTEM_ID_CAPS_FIELD,
2912       G_TYPE_STRING, &system_id, NULL);
2913   gst_qtdemux_append_protection_system_id (qtdemux, system_id);
2914
2915   stream->protected = TRUE;
2916   stream->protection_scheme_type = FOURCC_cenc;
2917
2918   if (!stream->protection_scheme_info)
2919     stream->protection_scheme_info = g_new0 (QtDemuxCencSampleSetInfo, 1);
2920
2921   ss_info = (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
2922   if (!ss_info->default_properties) {
2923     ss_info->default_properties =
2924         gst_structure_new ("application/x-cenc",
2925         "iv_size", G_TYPE_UINT, iv_size, "encrypted", G_TYPE_BOOLEAN, TRUE,
2926         NULL);
2927
2928   }
2929
2930   if (ss_info->crypto_info) {
2931     GST_LOG_OBJECT (qtdemux, "unreffing existing crypto_info");
2932     g_ptr_array_free (ss_info->crypto_info, TRUE);
2933     ss_info->crypto_info = NULL;
2934   }
2935
2936   /* skip UUID */
2937   gst_byte_reader_init (&br, buffer + offset + 16, length - offset - 16);
2938
2939   if (!gst_byte_reader_get_uint8 (&br, &version)) {
2940     GST_ERROR_OBJECT (qtdemux, "Error getting box's version field");
2941     return;
2942   }
2943
2944   if (!gst_byte_reader_get_uint24_be (&br, &flags)) {
2945     GST_ERROR_OBJECT (qtdemux, "Error getting box's flags field");
2946     return;
2947   }
2948
2949   if ((flags & 0x000001)) {
2950     if (!qtdemux_update_default_piff_encryption_settings (qtdemux, ss_info,
2951             &br))
2952       return;
2953   } else if ((flags & 0x000002)) {
2954     uses_sub_sample_encryption = TRUE;
2955   }
2956
2957   if (!gst_structure_get_uint (ss_info->default_properties, "iv_size",
2958           &iv_size)) {
2959     GST_ERROR_OBJECT (qtdemux, "Error getting encryption IV size field");
2960     return;
2961   }
2962
2963   if (!gst_byte_reader_get_uint32_be (&br, &sample_count)) {
2964     GST_ERROR_OBJECT (qtdemux, "Error getting box's sample count field");
2965     return;
2966   }
2967
2968   ss_info->crypto_info =
2969       g_ptr_array_new_full (sample_count,
2970       (GDestroyNotify) qtdemux_gst_structure_free);
2971
2972   for (i = 0; i < sample_count; ++i) {
2973     GstStructure *properties;
2974     guint8 *data;
2975     GstBuffer *buf;
2976
2977     properties = qtdemux_get_cenc_sample_properties (qtdemux, stream, i);
2978     if (properties == NULL) {
2979       GST_ERROR_OBJECT (qtdemux, "failed to get properties for sample %u", i);
2980       qtdemux->cenc_aux_sample_count = i;
2981       return;
2982     }
2983
2984     if (!gst_byte_reader_dup_data (&br, iv_size, &data)) {
2985       GST_ERROR_OBJECT (qtdemux, "IV data not present for sample %u", i);
2986       gst_structure_free (properties);
2987       qtdemux->cenc_aux_sample_count = i;
2988       return;
2989     }
2990     buf = gst_buffer_new_wrapped (data, iv_size);
2991     gst_structure_set (properties, "iv", GST_TYPE_BUFFER, buf, NULL);
2992     gst_buffer_unref (buf);
2993
2994     if (uses_sub_sample_encryption) {
2995       guint16 n_subsamples;
2996       const GValue *kid_buf_value;
2997
2998       if (!gst_byte_reader_get_uint16_be (&br, &n_subsamples)
2999           || n_subsamples == 0) {
3000         GST_ERROR_OBJECT (qtdemux,
3001             "failed to get subsample count for sample %u", i);
3002         gst_structure_free (properties);
3003         qtdemux->cenc_aux_sample_count = i;
3004         return;
3005       }
3006       GST_LOG_OBJECT (qtdemux, "subsample count: %u", n_subsamples);
3007       if (!gst_byte_reader_dup_data (&br, n_subsamples * 6, &data)) {
3008         GST_ERROR_OBJECT (qtdemux, "failed to get subsample data for sample %u",
3009             i);
3010         gst_structure_free (properties);
3011         qtdemux->cenc_aux_sample_count = i;
3012         return;
3013       }
3014       buf = gst_buffer_new_wrapped (data, n_subsamples * 6);
3015
3016       kid_buf_value =
3017           gst_structure_get_value (ss_info->default_properties, "kid");
3018
3019       gst_structure_set (properties,
3020           "subsample_count", G_TYPE_UINT, n_subsamples,
3021           "subsamples", GST_TYPE_BUFFER, buf, NULL);
3022       gst_structure_set_value (properties, "kid", kid_buf_value);
3023       gst_buffer_unref (buf);
3024     } else {
3025       gst_structure_set (properties, "subsample_count", G_TYPE_UINT, 0, NULL);
3026     }
3027
3028     g_ptr_array_add (ss_info->crypto_info, properties);
3029   }
3030
3031   qtdemux->cenc_aux_sample_count = sample_count;
3032 }
3033
3034 static void
3035 qtdemux_parse_uuid (GstQTDemux * qtdemux, const guint8 * buffer, gint length)
3036 {
3037   static const guint8 xmp_uuid[] = { 0xBE, 0x7A, 0xCF, 0xCB,
3038     0x97, 0xA9, 0x42, 0xE8,
3039     0x9C, 0x71, 0x99, 0x94,
3040     0x91, 0xE3, 0xAF, 0xAC
3041   };
3042   static const guint8 playready_uuid[] = {
3043     0xd0, 0x8a, 0x4f, 0x18, 0x10, 0xf3, 0x4a, 0x82,
3044     0xb6, 0xc8, 0x32, 0xd8, 0xab, 0xa1, 0x83, 0xd3
3045   };
3046
3047   static const guint8 piff_sample_encryption_uuid[] = {
3048     0xa2, 0x39, 0x4f, 0x52, 0x5a, 0x9b, 0x4f, 0x14,
3049     0xa2, 0x44, 0x6c, 0x42, 0x7c, 0x64, 0x8d, 0xf4
3050   };
3051
3052   guint offset;
3053
3054   /* counts as header data */
3055   qtdemux->header_size += length;
3056
3057   offset = (QT_UINT32 (buffer) == 0) ? 16 : 8;
3058
3059   if (length <= offset + 16) {
3060     GST_DEBUG_OBJECT (qtdemux, "uuid atom is too short, skipping");
3061     return;
3062   }
3063
3064   if (memcmp (buffer + offset, xmp_uuid, 16) == 0) {
3065     GstBuffer *buf;
3066     GstTagList *taglist;
3067
3068     buf = _gst_buffer_new_wrapped ((guint8 *) buffer + offset + 16,
3069         length - offset - 16, NULL);
3070     taglist = gst_tag_list_from_xmp_buffer (buf);
3071     gst_buffer_unref (buf);
3072
3073     /* make sure we have a usable taglist */
3074     qtdemux->tag_list = gst_tag_list_make_writable (qtdemux->tag_list);
3075
3076     qtdemux_handle_xmp_taglist (qtdemux, qtdemux->tag_list, taglist);
3077
3078   } else if (memcmp (buffer + offset, playready_uuid, 16) == 0) {
3079     int len;
3080     const gunichar2 *s_utf16;
3081     char *contents;
3082
3083     len = GST_READ_UINT16_LE (buffer + offset + 0x30);
3084     s_utf16 = (const gunichar2 *) (buffer + offset + 0x32);
3085     contents = g_utf16_to_utf8 (s_utf16, len / 2, NULL, NULL, NULL);
3086     GST_ERROR_OBJECT (qtdemux, "contents: %s", contents);
3087
3088     g_free (contents);
3089
3090     GST_ELEMENT_ERROR (qtdemux, STREAM, DECRYPT,
3091         (_("Cannot play stream because it is encrypted with PlayReady DRM.")),
3092         (NULL));
3093   } else if (memcmp (buffer + offset, piff_sample_encryption_uuid, 16) == 0) {
3094     qtdemux_parse_piff (qtdemux, buffer, length, offset);
3095   } else {
3096     GST_DEBUG_OBJECT (qtdemux, "Ignoring unknown uuid: %08x-%08x-%08x-%08x",
3097         GST_READ_UINT32_LE (buffer + offset),
3098         GST_READ_UINT32_LE (buffer + offset + 4),
3099         GST_READ_UINT32_LE (buffer + offset + 8),
3100         GST_READ_UINT32_LE (buffer + offset + 12));
3101   }
3102 }
3103
3104 static void
3105 qtdemux_parse_sidx (GstQTDemux * qtdemux, const guint8 * buffer, gint length)
3106 {
3107   GstSidxParser sidx_parser;
3108   GstIsoffParserResult res;
3109   guint consumed;
3110
3111   gst_isoff_qt_sidx_parser_init (&sidx_parser);
3112
3113   res =
3114       gst_isoff_qt_sidx_parser_add_data (&sidx_parser, buffer, length,
3115       &consumed);
3116   GST_DEBUG_OBJECT (qtdemux, "sidx parse result: %d", res);
3117   if (res == GST_ISOFF_QT_PARSER_DONE) {
3118     check_update_duration (qtdemux, sidx_parser.cumulative_pts);
3119   }
3120   gst_isoff_qt_sidx_parser_clear (&sidx_parser);
3121 }
3122
3123 /* caller verifies at least 8 bytes in buf */
3124 static void
3125 extract_initial_length_and_fourcc (const guint8 * data, guint size,
3126     guint64 * plength, guint32 * pfourcc)
3127 {
3128   guint64 length;
3129   guint32 fourcc;
3130
3131   length = QT_UINT32 (data);
3132   GST_DEBUG ("length 0x%08" G_GINT64_MODIFIER "x", length);
3133   fourcc = QT_FOURCC (data + 4);
3134   GST_DEBUG ("atom type %" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (fourcc));
3135
3136   if (length == 0) {
3137     length = G_MAXUINT64;
3138   } else if (length == 1 && size >= 16) {
3139     /* this means we have an extended size, which is the 64 bit value of
3140      * the next 8 bytes */
3141     length = QT_UINT64 (data + 8);
3142     GST_DEBUG ("length 0x%08" G_GINT64_MODIFIER "x", length);
3143   }
3144
3145   if (plength)
3146     *plength = length;
3147   if (pfourcc)
3148     *pfourcc = fourcc;
3149 }
3150
3151 static gboolean
3152 qtdemux_parse_mehd (GstQTDemux * qtdemux, GstByteReader * br)
3153 {
3154   guint32 version = 0;
3155   GstClockTime duration = 0;
3156
3157   if (!gst_byte_reader_get_uint32_be (br, &version))
3158     goto failed;
3159
3160   version >>= 24;
3161   if (version == 1) {
3162     if (!gst_byte_reader_get_uint64_be (br, &duration))
3163       goto failed;
3164   } else {
3165     guint32 dur = 0;
3166
3167     if (!gst_byte_reader_get_uint32_be (br, &dur))
3168       goto failed;
3169     duration = dur;
3170   }
3171
3172   GST_INFO_OBJECT (qtdemux, "mehd duration: %" G_GUINT64_FORMAT, duration);
3173   qtdemux->duration = duration;
3174
3175   return TRUE;
3176
3177 failed:
3178   {
3179     GST_DEBUG_OBJECT (qtdemux, "parsing mehd failed");
3180     return FALSE;
3181   }
3182 }
3183
3184 static gboolean
3185 qtdemux_parse_trex (GstQTDemux * qtdemux, QtDemuxStream * stream,
3186     guint32 * ds_duration, guint32 * ds_size, guint32 * ds_flags)
3187 {
3188   if (!stream->parsed_trex && qtdemux->moov_node) {
3189     GNode *mvex, *trex;
3190     GstByteReader trex_data;
3191
3192     mvex = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_mvex);
3193     if (mvex) {
3194       trex = qtdemux_tree_get_child_by_type_full (mvex, FOURCC_trex,
3195           &trex_data);
3196       while (trex) {
3197         guint32 id = 0, sdi = 0, dur = 0, size = 0, flags = 0;
3198
3199         /* skip version/flags */
3200         if (!gst_byte_reader_skip (&trex_data, 4))
3201           goto next;
3202         if (!gst_byte_reader_get_uint32_be (&trex_data, &id))
3203           goto next;
3204         if (id != stream->track_id)
3205           goto next;
3206         if (!gst_byte_reader_get_uint32_be (&trex_data, &sdi))
3207           goto next;
3208         if (!gst_byte_reader_get_uint32_be (&trex_data, &dur))
3209           goto next;
3210         if (!gst_byte_reader_get_uint32_be (&trex_data, &size))
3211           goto next;
3212         if (!gst_byte_reader_get_uint32_be (&trex_data, &flags))
3213           goto next;
3214
3215         GST_DEBUG_OBJECT (qtdemux, "fragment defaults for stream %d; "
3216             "duration %d,  size %d, flags 0x%x", stream->track_id,
3217             dur, size, flags);
3218
3219         stream->parsed_trex = TRUE;
3220         stream->def_sample_description_index = sdi;
3221         stream->def_sample_duration = dur;
3222         stream->def_sample_size = size;
3223         stream->def_sample_flags = flags;
3224
3225       next:
3226         /* iterate all siblings */
3227         trex = qtdemux_tree_get_sibling_by_type_full (trex, FOURCC_trex,
3228             &trex_data);
3229       }
3230     }
3231   }
3232
3233   *ds_duration = stream->def_sample_duration;
3234   *ds_size = stream->def_sample_size;
3235   *ds_flags = stream->def_sample_flags;
3236
3237   /* even then, above values are better than random ... */
3238   if (G_UNLIKELY (!stream->parsed_trex)) {
3239     GST_WARNING_OBJECT (qtdemux,
3240         "failed to find fragment defaults for stream %d", stream->track_id);
3241     return FALSE;
3242   }
3243
3244   return TRUE;
3245 }
3246
3247 /* This method should be called whenever a more accurate duration might
3248  * have been found. It will update all relevant variables if/where needed
3249  */
3250 static void
3251 check_update_duration (GstQTDemux * qtdemux, GstClockTime duration)
3252 {
3253   guint i;
3254   guint64 movdur;
3255   GstClockTime prevdur;
3256
3257   movdur = GSTTIME_TO_QTTIME (qtdemux, duration);
3258
3259   if (movdur > qtdemux->duration) {
3260     prevdur = QTTIME_TO_GSTTIME (qtdemux, qtdemux->duration);
3261     GST_DEBUG_OBJECT (qtdemux,
3262         "Updating total duration to %" GST_TIME_FORMAT " was %" GST_TIME_FORMAT,
3263         GST_TIME_ARGS (duration), GST_TIME_ARGS (prevdur));
3264     qtdemux->duration = movdur;
3265     GST_DEBUG_OBJECT (qtdemux,
3266         "qtdemux->segment.duration: %" GST_TIME_FORMAT " .stop: %"
3267         GST_TIME_FORMAT, GST_TIME_ARGS (qtdemux->segment.duration),
3268         GST_TIME_ARGS (qtdemux->segment.stop));
3269     if (qtdemux->segment.duration == prevdur) {
3270       /* If the current segment has duration/stop identical to previous duration
3271        * update them also (because they were set at that point in time with
3272        * the wrong duration */
3273       /* We convert the value *from* the timescale version to avoid rounding errors */
3274       GstClockTime fixeddur = QTTIME_TO_GSTTIME (qtdemux, movdur);
3275       GST_DEBUG_OBJECT (qtdemux, "Updated segment.duration and segment.stop");
3276       qtdemux->segment.duration = fixeddur;
3277       qtdemux->segment.stop = fixeddur;
3278     }
3279   }
3280
3281   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
3282     QtDemuxStream *stream = QTDEMUX_NTH_STREAM (qtdemux, i);
3283
3284     movdur = GSTTIME_TO_QTSTREAMTIME (stream, duration);
3285     if (movdur > stream->duration) {
3286       GST_DEBUG_OBJECT (qtdemux,
3287           "Updating stream #%d duration to %" GST_TIME_FORMAT, i,
3288           GST_TIME_ARGS (duration));
3289       stream->duration = movdur;
3290       /* internal duration tracking state has been updated above, so */
3291       /* preserve an open-ended dummy segment rather than repeatedly updating
3292        * it and spamming downstream accordingly with segment events */
3293       if (stream->dummy_segment &&
3294           GST_CLOCK_TIME_IS_VALID (stream->segments[0].duration)) {
3295         /* Update all dummy values to new duration */
3296         stream->segments[0].stop_time = duration;
3297         stream->segments[0].duration = duration;
3298         stream->segments[0].media_stop = duration;
3299
3300         /* let downstream know we possibly have a new stop time */
3301         if (stream->segment_index != -1) {
3302           GstClockTime pos;
3303
3304           if (qtdemux->segment.rate >= 0) {
3305             pos = stream->segment.start;
3306           } else {
3307             pos = stream->segment.stop;
3308           }
3309
3310           gst_qtdemux_stream_update_segment (qtdemux, stream,
3311               stream->segment_index, pos, NULL, NULL);
3312         }
3313       }
3314     }
3315   }
3316 }
3317
3318 static gboolean
3319 qtdemux_parse_trun (GstQTDemux * qtdemux, GstByteReader * trun,
3320     QtDemuxStream * stream, guint32 d_sample_duration, guint32 d_sample_size,
3321     guint32 d_sample_flags, gint64 moof_offset, gint64 moof_length,
3322     gint64 * base_offset, gint64 * running_offset, gint64 decode_ts,
3323     gboolean has_tfdt)
3324 {
3325   GstClockTime gst_ts = GST_CLOCK_TIME_NONE;
3326   guint64 timestamp;
3327   gint32 data_offset = 0;
3328   guint32 flags = 0, first_flags = 0, samples_count = 0;
3329   gint i;
3330   guint8 *data;
3331   guint entry_size, dur_offset, size_offset, flags_offset = 0, ct_offset = 0;
3332   QtDemuxSample *sample;
3333   gboolean ismv = FALSE;
3334   gint64 initial_offset;
3335
3336   GST_LOG_OBJECT (qtdemux, "parsing trun track-id %d; "
3337       "default dur %d, size %d, flags 0x%x, base offset %" G_GINT64_FORMAT ", "
3338       "decode ts %" G_GINT64_FORMAT, stream->track_id, d_sample_duration,
3339       d_sample_size, d_sample_flags, *base_offset, decode_ts);
3340
3341   if (stream->pending_seek && moof_offset < stream->pending_seek->moof_offset) {
3342     GST_INFO_OBJECT (stream->pad, "skipping trun before seek target fragment");
3343     return TRUE;
3344   }
3345
3346   /* presence of stss or not can't really tell us much,
3347    * and flags and so on tend to be marginally reliable in these files */
3348   if (stream->subtype == FOURCC_soun) {
3349     GST_DEBUG_OBJECT (qtdemux,
3350         "sound track in fragmented file; marking all keyframes");
3351     stream->all_keyframe = TRUE;
3352   }
3353
3354   if (!gst_byte_reader_skip (trun, 1) ||
3355       !gst_byte_reader_get_uint24_be (trun, &flags))
3356     goto fail;
3357
3358   if (!gst_byte_reader_get_uint32_be (trun, &samples_count))
3359     goto fail;
3360
3361   if (flags & TR_DATA_OFFSET) {
3362     /* note this is really signed */
3363     if (!gst_byte_reader_get_int32_be (trun, &data_offset))
3364       goto fail;
3365     GST_LOG_OBJECT (qtdemux, "trun data offset %d", data_offset);
3366     /* default base offset = first byte of moof */
3367     if (*base_offset == -1) {
3368       GST_LOG_OBJECT (qtdemux, "base_offset at moof");
3369       *base_offset = moof_offset;
3370     }
3371     *running_offset = *base_offset + data_offset;
3372   } else {
3373     /* if no offset at all, that would mean data starts at moof start,
3374      * which is a bit wrong and is ismv crappy way, so compensate
3375      * assuming data is in mdat following moof */
3376     if (*base_offset == -1) {
3377       *base_offset = moof_offset + moof_length + 8;
3378       GST_LOG_OBJECT (qtdemux, "base_offset assumed in mdat after moof");
3379       ismv = TRUE;
3380     }
3381     if (*running_offset == -1)
3382       *running_offset = *base_offset;
3383   }
3384
3385   GST_LOG_OBJECT (qtdemux, "running offset now %" G_GINT64_FORMAT,
3386       *running_offset);
3387   GST_LOG_OBJECT (qtdemux, "trun offset %d, flags 0x%x, entries %d",
3388       data_offset, flags, samples_count);
3389
3390   if (flags & TR_FIRST_SAMPLE_FLAGS) {
3391     if (G_UNLIKELY (flags & TR_SAMPLE_FLAGS)) {
3392       GST_DEBUG_OBJECT (qtdemux,
3393           "invalid flags; SAMPLE and FIRST_SAMPLE present, discarding latter");
3394       flags ^= TR_FIRST_SAMPLE_FLAGS;
3395     } else {
3396       if (!gst_byte_reader_get_uint32_be (trun, &first_flags))
3397         goto fail;
3398       GST_LOG_OBJECT (qtdemux, "first flags: 0x%x", first_flags);
3399     }
3400   }
3401
3402   /* FIXME ? spec says other bits should also be checked to determine
3403    * entry size (and prefix size for that matter) */
3404   entry_size = 0;
3405   dur_offset = size_offset = 0;
3406   if (flags & TR_SAMPLE_DURATION) {
3407     GST_LOG_OBJECT (qtdemux, "entry duration present");
3408     dur_offset = entry_size;
3409     entry_size += 4;
3410   }
3411   if (flags & TR_SAMPLE_SIZE) {
3412     GST_LOG_OBJECT (qtdemux, "entry size present");
3413     size_offset = entry_size;
3414     entry_size += 4;
3415   }
3416   if (flags & TR_SAMPLE_FLAGS) {
3417     GST_LOG_OBJECT (qtdemux, "entry flags present");
3418     flags_offset = entry_size;
3419     entry_size += 4;
3420   }
3421   if (flags & TR_COMPOSITION_TIME_OFFSETS) {
3422     GST_LOG_OBJECT (qtdemux, "entry ct offset present");
3423     ct_offset = entry_size;
3424     entry_size += 4;
3425   }
3426
3427   if (!qt_atom_parser_has_chunks (trun, samples_count, entry_size))
3428     goto fail;
3429   data = (guint8 *) gst_byte_reader_peek_data_unchecked (trun);
3430
3431   if (stream->n_samples + samples_count >=
3432       QTDEMUX_MAX_SAMPLE_INDEX_SIZE / sizeof (QtDemuxSample))
3433     goto index_too_big;
3434
3435   GST_DEBUG_OBJECT (qtdemux, "allocating n_samples %u * %u (%.2f MB)",
3436       stream->n_samples + samples_count, (guint) sizeof (QtDemuxSample),
3437       (stream->n_samples + samples_count) *
3438       sizeof (QtDemuxSample) / (1024.0 * 1024.0));
3439
3440   /* create a new array of samples if it's the first sample parsed */
3441   if (stream->n_samples == 0) {
3442     g_assert (stream->samples == NULL);
3443     stream->samples = g_try_new0 (QtDemuxSample, samples_count);
3444     /* or try to reallocate it with space enough to insert the new samples */
3445   } else
3446     stream->samples = g_try_renew (QtDemuxSample, stream->samples,
3447         stream->n_samples + samples_count);
3448   if (stream->samples == NULL)
3449     goto out_of_memory;
3450
3451   if (qtdemux->fragment_start != -1) {
3452     timestamp = GSTTIME_TO_QTSTREAMTIME (stream, qtdemux->fragment_start);
3453     qtdemux->fragment_start = -1;
3454   } else {
3455     if (stream->n_samples == 0) {
3456       if (decode_ts > 0) {
3457         timestamp = decode_ts;
3458       } else if (stream->pending_seek != NULL) {
3459         /* if we don't have a timestamp from a tfdt box, we'll use the one
3460          * from the mfra seek table */
3461         GST_INFO_OBJECT (stream->pad, "pending seek ts = %" GST_TIME_FORMAT,
3462             GST_TIME_ARGS (stream->pending_seek->ts));
3463
3464         /* FIXME: this is not fully correct, the timestamp refers to the random
3465          * access sample refered to in the tfra entry, which may not necessarily
3466          * be the first sample in the tfrag/trun (but hopefully/usually is) */
3467         timestamp = GSTTIME_TO_QTSTREAMTIME (stream, stream->pending_seek->ts);
3468       } else {
3469         timestamp = 0;
3470       }
3471
3472       gst_ts = QTSTREAMTIME_TO_GSTTIME (stream, timestamp);
3473       GST_INFO_OBJECT (stream->pad, "first sample ts %" GST_TIME_FORMAT,
3474           GST_TIME_ARGS (gst_ts));
3475     } else {
3476       /* subsequent fragments extend stream */
3477       timestamp =
3478           stream->samples[stream->n_samples - 1].timestamp +
3479           stream->samples[stream->n_samples - 1].duration;
3480
3481       /* If this is a GST_FORMAT_BYTES stream and there's a significant
3482        * difference (1 sec.) between decode_ts and timestamp, prefer the
3483        * former */
3484       if (has_tfdt && !qtdemux->upstream_format_is_time
3485           && ABSDIFF (decode_ts, timestamp) >
3486           MAX (stream->duration_last_moof / 2,
3487               GSTTIME_TO_QTSTREAMTIME (stream, GST_SECOND))) {
3488         GST_INFO_OBJECT (qtdemux,
3489             "decode_ts (%" GST_TIME_FORMAT ") and timestamp (%" GST_TIME_FORMAT
3490             ") are significantly different (more than %" GST_TIME_FORMAT
3491             "), using decode_ts",
3492             GST_TIME_ARGS (QTSTREAMTIME_TO_GSTTIME (stream, decode_ts)),
3493             GST_TIME_ARGS (QTSTREAMTIME_TO_GSTTIME (stream, timestamp)),
3494             GST_TIME_ARGS (QTSTREAMTIME_TO_GSTTIME (stream,
3495                     MAX (stream->duration_last_moof / 2,
3496                         GSTTIME_TO_QTSTREAMTIME (stream, GST_SECOND)))));
3497         timestamp = decode_ts;
3498       }
3499
3500       gst_ts = QTSTREAMTIME_TO_GSTTIME (stream, timestamp);
3501       GST_INFO_OBJECT (qtdemux, "first sample ts %" GST_TIME_FORMAT
3502           " (extends previous samples)", GST_TIME_ARGS (gst_ts));
3503     }
3504   }
3505
3506   initial_offset = *running_offset;
3507
3508   sample = stream->samples + stream->n_samples;
3509   for (i = 0; i < samples_count; i++) {
3510     guint32 dur, size, sflags, ct;
3511
3512     /* first read sample data */
3513     if (flags & TR_SAMPLE_DURATION) {
3514       dur = QT_UINT32 (data + dur_offset);
3515     } else {
3516       dur = d_sample_duration;
3517     }
3518     if (flags & TR_SAMPLE_SIZE) {
3519       size = QT_UINT32 (data + size_offset);
3520     } else {
3521       size = d_sample_size;
3522     }
3523     if (flags & TR_FIRST_SAMPLE_FLAGS) {
3524       if (i == 0) {
3525         sflags = first_flags;
3526       } else {
3527         sflags = d_sample_flags;
3528       }
3529     } else if (flags & TR_SAMPLE_FLAGS) {
3530       sflags = QT_UINT32 (data + flags_offset);
3531     } else {
3532       sflags = d_sample_flags;
3533     }
3534     if (flags & TR_COMPOSITION_TIME_OFFSETS) {
3535       ct = QT_UINT32 (data + ct_offset);
3536     } else {
3537       ct = 0;
3538     }
3539     data += entry_size;
3540
3541     /* fill the sample information */
3542     sample->offset = *running_offset;
3543     sample->pts_offset = ct;
3544     sample->size = size;
3545     sample->timestamp = timestamp;
3546     sample->duration = dur;
3547     /* sample-is-difference-sample */
3548     /* ismv seems to use 0x40 for keyframe, 0xc0 for non-keyframe,
3549      * now idea how it relates to bitfield other than massive LE/BE confusion */
3550     sample->keyframe = ismv ? ((sflags & 0xff) == 0x40) : !(sflags & 0x10000);
3551     *running_offset += size;
3552     timestamp += dur;
3553     stream->duration_moof += dur;
3554     sample++;
3555   }
3556
3557   /* Update total duration if needed */
3558   check_update_duration (qtdemux, QTSTREAMTIME_TO_GSTTIME (stream, timestamp));
3559
3560   /* Pre-emptively figure out size of mdat based on trun information.
3561    * If the [mdat] atom is effectivelly read, it will be replaced by the actual
3562    * size, else we will still be able to use this when dealing with gap'ed
3563    * input */
3564   qtdemux->mdatleft = *running_offset - initial_offset;
3565   qtdemux->mdatoffset = initial_offset;
3566   qtdemux->mdatsize = qtdemux->mdatleft;
3567
3568   stream->n_samples += samples_count;
3569   stream->n_samples_moof += samples_count;
3570
3571   if (stream->pending_seek != NULL)
3572     stream->pending_seek = NULL;
3573
3574   return TRUE;
3575
3576 fail:
3577   {
3578     GST_WARNING_OBJECT (qtdemux, "failed to parse trun");
3579     return FALSE;
3580   }
3581 out_of_memory:
3582   {
3583     GST_WARNING_OBJECT (qtdemux, "failed to allocate %d samples",
3584         stream->n_samples);
3585     return FALSE;
3586   }
3587 index_too_big:
3588   {
3589     GST_WARNING_OBJECT (qtdemux, "not allocating index of %d samples, would "
3590         "be larger than %uMB (broken file?)", stream->n_samples,
3591         QTDEMUX_MAX_SAMPLE_INDEX_SIZE >> 20);
3592     return FALSE;
3593   }
3594 }
3595
3596 /* find stream with @id */
3597 static inline QtDemuxStream *
3598 qtdemux_find_stream (GstQTDemux * qtdemux, guint32 id)
3599 {
3600   QtDemuxStream *stream;
3601   gint i;
3602
3603   /* check */
3604   if (G_UNLIKELY (!id)) {
3605     GST_DEBUG_OBJECT (qtdemux, "invalid track id 0");
3606     return NULL;
3607   }
3608
3609   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
3610     stream = QTDEMUX_NTH_STREAM (qtdemux, i);
3611     if (stream->track_id == id)
3612       return stream;
3613   }
3614   if (qtdemux->mss_mode) {
3615     /* mss should have only 1 stream anyway */
3616     return QTDEMUX_NTH_STREAM (qtdemux, 0);
3617   }
3618
3619   return NULL;
3620 }
3621
3622 static gboolean
3623 qtdemux_parse_mfhd (GstQTDemux * qtdemux, GstByteReader * mfhd,
3624     guint32 * fragment_number)
3625 {
3626   if (!gst_byte_reader_skip (mfhd, 4))
3627     goto fail;
3628   if (!gst_byte_reader_get_uint32_be (mfhd, fragment_number))
3629     goto fail;
3630   return TRUE;
3631 fail:
3632   {
3633     GST_WARNING_OBJECT (qtdemux, "Failed to parse mfhd atom");
3634     return FALSE;
3635   }
3636 }
3637
3638 static gboolean
3639 qtdemux_parse_tfhd (GstQTDemux * qtdemux, GstByteReader * tfhd,
3640     QtDemuxStream ** stream, guint32 * default_sample_duration,
3641     guint32 * default_sample_size, guint32 * default_sample_flags,
3642     gint64 * base_offset)
3643 {
3644   guint32 flags = 0;
3645   guint32 track_id = 0;
3646
3647   if (!gst_byte_reader_skip (tfhd, 1) ||
3648       !gst_byte_reader_get_uint24_be (tfhd, &flags))
3649     goto invalid_track;
3650
3651   if (!gst_byte_reader_get_uint32_be (tfhd, &track_id))
3652     goto invalid_track;
3653
3654   *stream = qtdemux_find_stream (qtdemux, track_id);
3655   if (G_UNLIKELY (!*stream))
3656     goto unknown_stream;
3657
3658   if (flags & TF_DEFAULT_BASE_IS_MOOF)
3659     *base_offset = qtdemux->moof_offset;
3660
3661   if (flags & TF_BASE_DATA_OFFSET)
3662     if (!gst_byte_reader_get_uint64_be (tfhd, (guint64 *) base_offset))
3663       goto invalid_track;
3664
3665   /* obtain stream defaults */
3666   qtdemux_parse_trex (qtdemux, *stream,
3667       default_sample_duration, default_sample_size, default_sample_flags);
3668
3669   (*stream)->stsd_sample_description_id =
3670       (*stream)->def_sample_description_index - 1;
3671
3672   if (flags & TF_SAMPLE_DESCRIPTION_INDEX) {
3673     guint32 sample_description_index;
3674     if (!gst_byte_reader_get_uint32_be (tfhd, &sample_description_index))
3675       goto invalid_track;
3676     (*stream)->stsd_sample_description_id = sample_description_index - 1;
3677   }
3678
3679   if (qtdemux->mss_mode) {
3680     /* mss has no stsd entry */
3681     (*stream)->stsd_sample_description_id = 0;
3682   }
3683
3684   if (flags & TF_DEFAULT_SAMPLE_DURATION)
3685     if (!gst_byte_reader_get_uint32_be (tfhd, default_sample_duration))
3686       goto invalid_track;
3687
3688   if (flags & TF_DEFAULT_SAMPLE_SIZE)
3689     if (!gst_byte_reader_get_uint32_be (tfhd, default_sample_size))
3690       goto invalid_track;
3691
3692   if (flags & TF_DEFAULT_SAMPLE_FLAGS)
3693     if (!gst_byte_reader_get_uint32_be (tfhd, default_sample_flags))
3694       goto invalid_track;
3695
3696   return TRUE;
3697
3698 invalid_track:
3699   {
3700     GST_WARNING_OBJECT (qtdemux, "invalid track fragment header");
3701     return FALSE;
3702   }
3703 unknown_stream:
3704   {
3705     GST_DEBUG_OBJECT (qtdemux, "unknown stream in tfhd");
3706     return TRUE;
3707   }
3708 }
3709
3710 static gboolean
3711 qtdemux_parse_tfdt (GstQTDemux * qtdemux, GstByteReader * br,
3712     guint64 * decode_time)
3713 {
3714   guint32 version = 0;
3715
3716   if (!gst_byte_reader_get_uint32_be (br, &version))
3717     return FALSE;
3718
3719   version >>= 24;
3720   if (version == 1) {
3721     if (!gst_byte_reader_get_uint64_be (br, decode_time))
3722       goto failed;
3723   } else {
3724     guint32 dec_time = 0;
3725     if (!gst_byte_reader_get_uint32_be (br, &dec_time))
3726       goto failed;
3727     *decode_time = dec_time;
3728   }
3729
3730   GST_INFO_OBJECT (qtdemux, "Track fragment decode time: %" G_GUINT64_FORMAT,
3731       *decode_time);
3732
3733   return TRUE;
3734
3735 failed:
3736   {
3737     GST_DEBUG_OBJECT (qtdemux, "parsing tfdt failed");
3738     return FALSE;
3739   }
3740 }
3741
3742 /* Returns a pointer to a GstStructure containing the properties of
3743  * the stream sample identified by @sample_index. The caller must unref
3744  * the returned object after use. Returns NULL if unsuccessful. */
3745 static GstStructure *
3746 qtdemux_get_cenc_sample_properties (GstQTDemux * qtdemux,
3747     QtDemuxStream * stream, guint sample_index)
3748 {
3749   QtDemuxCencSampleSetInfo *info = NULL;
3750
3751   g_return_val_if_fail (stream != NULL, NULL);
3752   g_return_val_if_fail (stream->protected, NULL);
3753   g_return_val_if_fail (stream->protection_scheme_info != NULL, NULL);
3754
3755   info = (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
3756
3757   /* Currently, cenc properties for groups of samples are not supported, so
3758    * simply return a copy of the default sample properties */
3759   return gst_structure_copy (info->default_properties);
3760 }
3761
3762 /* Parses the sizes of sample auxiliary information contained within a stream,
3763  * as given in a saiz box. Returns array of sample_count guint8 size values,
3764  * or NULL on failure */
3765 static guint8 *
3766 qtdemux_parse_saiz (GstQTDemux * qtdemux, QtDemuxStream * stream,
3767     GstByteReader * br, guint32 * sample_count)
3768 {
3769   guint32 flags = 0;
3770   guint8 *info_sizes;
3771   guint8 default_info_size;
3772
3773   g_return_val_if_fail (qtdemux != NULL, NULL);
3774   g_return_val_if_fail (stream != NULL, NULL);
3775   g_return_val_if_fail (br != NULL, NULL);
3776   g_return_val_if_fail (sample_count != NULL, NULL);
3777
3778   if (!gst_byte_reader_get_uint32_be (br, &flags))
3779     return NULL;
3780
3781   if (flags & 0x1) {
3782     /* aux_info_type and aux_info_type_parameter are ignored */
3783     if (!gst_byte_reader_skip (br, 8))
3784       return NULL;
3785   }
3786
3787   if (!gst_byte_reader_get_uint8 (br, &default_info_size))
3788     return NULL;
3789   GST_DEBUG_OBJECT (qtdemux, "default_info_size: %u", default_info_size);
3790
3791   if (!gst_byte_reader_get_uint32_be (br, sample_count))
3792     return NULL;
3793   GST_DEBUG_OBJECT (qtdemux, "sample_count: %u", *sample_count);
3794
3795
3796   if (default_info_size == 0) {
3797     if (!gst_byte_reader_dup_data (br, *sample_count, &info_sizes)) {
3798       return NULL;
3799     }
3800   } else {
3801     info_sizes = g_new (guint8, *sample_count);
3802     memset (info_sizes, default_info_size, *sample_count);
3803   }
3804
3805   return info_sizes;
3806 }
3807
3808 /* Parses the offset of sample auxiliary information contained within a stream,
3809  * as given in a saio box. Returns TRUE if successful; FALSE otherwise. */
3810 static gboolean
3811 qtdemux_parse_saio (GstQTDemux * qtdemux, QtDemuxStream * stream,
3812     GstByteReader * br, guint32 * info_type, guint32 * info_type_parameter,
3813     guint64 * offset)
3814 {
3815   guint8 version = 0;
3816   guint32 flags = 0;
3817   guint32 aux_info_type = 0;
3818   guint32 aux_info_type_parameter = 0;
3819   guint32 entry_count;
3820   guint32 off_32;
3821   guint64 off_64;
3822   const guint8 *aux_info_type_data = NULL;
3823
3824   g_return_val_if_fail (qtdemux != NULL, FALSE);
3825   g_return_val_if_fail (stream != NULL, FALSE);
3826   g_return_val_if_fail (br != NULL, FALSE);
3827   g_return_val_if_fail (offset != NULL, FALSE);
3828
3829   if (!gst_byte_reader_get_uint8 (br, &version))
3830     return FALSE;
3831
3832   if (!gst_byte_reader_get_uint24_be (br, &flags))
3833     return FALSE;
3834
3835   if (flags & 0x1) {
3836
3837     if (!gst_byte_reader_get_data (br, 4, &aux_info_type_data))
3838       return FALSE;
3839     aux_info_type = QT_FOURCC (aux_info_type_data);
3840
3841     if (!gst_byte_reader_get_uint32_be (br, &aux_info_type_parameter))
3842       return FALSE;
3843   } else if (stream->protected) {
3844     aux_info_type = stream->protection_scheme_type;
3845   } else {
3846     aux_info_type = CUR_STREAM (stream)->fourcc;
3847   }
3848
3849   if (info_type)
3850     *info_type = aux_info_type;
3851   if (info_type_parameter)
3852     *info_type_parameter = aux_info_type_parameter;
3853
3854   GST_DEBUG_OBJECT (qtdemux, "aux_info_type: '%" GST_FOURCC_FORMAT "', "
3855       "aux_info_type_parameter:  %#06x",
3856       GST_FOURCC_ARGS (aux_info_type), aux_info_type_parameter);
3857
3858   if (!gst_byte_reader_get_uint32_be (br, &entry_count))
3859     return FALSE;
3860
3861   if (entry_count != 1) {
3862     GST_ERROR_OBJECT (qtdemux, "multiple offsets are not supported");
3863     return FALSE;
3864   }
3865
3866   if (version == 0) {
3867     if (!gst_byte_reader_get_uint32_be (br, &off_32))
3868       return FALSE;
3869     *offset = (guint64) off_32;
3870   } else {
3871     if (!gst_byte_reader_get_uint64_be (br, &off_64))
3872       return FALSE;
3873     *offset = off_64;
3874   }
3875
3876   GST_DEBUG_OBJECT (qtdemux, "offset: %" G_GUINT64_FORMAT, *offset);
3877   return TRUE;
3878 }
3879
3880 static void
3881 qtdemux_gst_structure_free (GstStructure * gststructure)
3882 {
3883   if (gststructure) {
3884     gst_structure_free (gststructure);
3885   }
3886 }
3887
3888 /* Parses auxiliary information relating to samples protected using Common
3889  * Encryption (cenc); the format of this information is defined in
3890  * ISO/IEC 23001-7. Returns TRUE if successful; FALSE otherwise. */
3891 static gboolean
3892 qtdemux_parse_cenc_aux_info (GstQTDemux * qtdemux, QtDemuxStream * stream,
3893     GstByteReader * br, guint8 * info_sizes, guint32 sample_count)
3894 {
3895   QtDemuxCencSampleSetInfo *ss_info = NULL;
3896   guint8 size;
3897   gint i;
3898   GPtrArray *old_crypto_info = NULL;
3899   guint old_entries = 0;
3900
3901   g_return_val_if_fail (qtdemux != NULL, FALSE);
3902   g_return_val_if_fail (stream != NULL, FALSE);
3903   g_return_val_if_fail (br != NULL, FALSE);
3904   g_return_val_if_fail (stream->protected, FALSE);
3905   g_return_val_if_fail (stream->protection_scheme_info != NULL, FALSE);
3906
3907   ss_info = (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
3908
3909   if (ss_info->crypto_info) {
3910     old_crypto_info = ss_info->crypto_info;
3911     /* Count number of non-null entries remaining at the tail end */
3912     for (i = old_crypto_info->len - 1; i >= 0; i--) {
3913       if (g_ptr_array_index (old_crypto_info, i) == NULL)
3914         break;
3915       old_entries++;
3916     }
3917   }
3918
3919   ss_info->crypto_info =
3920       g_ptr_array_new_full (sample_count + old_entries,
3921       (GDestroyNotify) qtdemux_gst_structure_free);
3922
3923   /* We preserve old entries because we parse the next moof in advance
3924    * of consuming all samples from the previous moof, and otherwise
3925    * we'd discard the corresponding crypto info for the samples
3926    * from the previous fragment. */
3927   if (old_entries) {
3928     GST_DEBUG_OBJECT (qtdemux, "Preserving %d old crypto info entries",
3929         old_entries);
3930     for (i = old_crypto_info->len - old_entries; i < old_crypto_info->len; i++) {
3931       g_ptr_array_add (ss_info->crypto_info, g_ptr_array_index (old_crypto_info,
3932               i));
3933       g_ptr_array_index (old_crypto_info, i) = NULL;
3934     }
3935   }
3936
3937   if (old_crypto_info) {
3938     /* Everything now belongs to the new array */
3939     g_ptr_array_free (old_crypto_info, TRUE);
3940   }
3941
3942   for (i = 0; i < sample_count; ++i) {
3943     GstStructure *properties;
3944     guint16 n_subsamples = 0;
3945     guint8 *data;
3946     guint iv_size;
3947     GstBuffer *buf;
3948
3949     properties = qtdemux_get_cenc_sample_properties (qtdemux, stream, i);
3950     if (properties == NULL) {
3951       GST_ERROR_OBJECT (qtdemux, "failed to get properties for sample %u", i);
3952       return FALSE;
3953     }
3954     if (!gst_structure_get_uint (properties, "iv_size", &iv_size)) {
3955       GST_ERROR_OBJECT (qtdemux, "failed to get iv_size for sample %u", i);
3956       gst_structure_free (properties);
3957       return FALSE;
3958     }
3959     if (!gst_byte_reader_dup_data (br, iv_size, &data)) {
3960       GST_ERROR_OBJECT (qtdemux, "failed to get IV for sample %u", i);
3961       gst_structure_free (properties);
3962       return FALSE;
3963     }
3964     buf = gst_buffer_new_wrapped (data, iv_size);
3965     gst_structure_set (properties, "iv", GST_TYPE_BUFFER, buf, NULL);
3966     gst_buffer_unref (buf);
3967     size = info_sizes[i];
3968     if (size > iv_size) {
3969       if (!gst_byte_reader_get_uint16_be (br, &n_subsamples)
3970           || !(n_subsamples > 0)) {
3971         gst_structure_free (properties);
3972         GST_ERROR_OBJECT (qtdemux,
3973             "failed to get subsample count for sample %u", i);
3974         return FALSE;
3975       }
3976       GST_LOG_OBJECT (qtdemux, "subsample count: %u", n_subsamples);
3977       if (!gst_byte_reader_dup_data (br, n_subsamples * 6, &data)) {
3978         GST_ERROR_OBJECT (qtdemux, "failed to get subsample data for sample %u",
3979             i);
3980         gst_structure_free (properties);
3981         return FALSE;
3982       }
3983       buf = gst_buffer_new_wrapped (data, n_subsamples * 6);
3984       if (!buf) {
3985         gst_structure_free (properties);
3986         return FALSE;
3987       }
3988       gst_structure_set (properties,
3989           "subsample_count", G_TYPE_UINT, n_subsamples,
3990           "subsamples", GST_TYPE_BUFFER, buf, NULL);
3991       gst_buffer_unref (buf);
3992     } else {
3993       gst_structure_set (properties, "subsample_count", G_TYPE_UINT, 0, NULL);
3994     }
3995     g_ptr_array_add (ss_info->crypto_info, properties);
3996   }
3997   return TRUE;
3998 }
3999
4000 /* Converts a UUID in raw byte form to a string representation, as defined in
4001  * RFC 4122. The caller takes ownership of the returned string and is
4002  * responsible for freeing it after use. */
4003 static gchar *
4004 qtdemux_uuid_bytes_to_string (gconstpointer uuid_bytes)
4005 {
4006   const guint8 *uuid = (const guint8 *) uuid_bytes;
4007
4008   return g_strdup_printf ("%02x%02x%02x%02x-%02x%02x-%02x%02x-"
4009       "%02x%02x-%02x%02x%02x%02x%02x%02x",
4010       uuid[0], uuid[1], uuid[2], uuid[3],
4011       uuid[4], uuid[5], uuid[6], uuid[7],
4012       uuid[8], uuid[9], uuid[10], uuid[11],
4013       uuid[12], uuid[13], uuid[14], uuid[15]);
4014 }
4015
4016 /* Parses a Protection System Specific Header box (pssh), as defined in the
4017  * Common Encryption (cenc) standard (ISO/IEC 23001-7), which contains
4018  * information needed by a specific content protection system in order to
4019  * decrypt cenc-protected tracks. Returns TRUE if successful; FALSE
4020  * otherwise. */
4021 static gboolean
4022 qtdemux_parse_pssh (GstQTDemux * qtdemux, GNode * node)
4023 {
4024   gchar *sysid_string;
4025   guint32 pssh_size = QT_UINT32 (node->data);
4026   GstBuffer *pssh = NULL;
4027   GstEvent *event = NULL;
4028   guint32 parent_box_type;
4029   gint i;
4030
4031   if (G_UNLIKELY (pssh_size < 32U)) {
4032     GST_ERROR_OBJECT (qtdemux, "invalid box size");
4033     return FALSE;
4034   }
4035
4036   sysid_string =
4037       qtdemux_uuid_bytes_to_string ((const guint8 *) node->data + 12);
4038
4039   gst_qtdemux_append_protection_system_id (qtdemux, sysid_string);
4040
4041   pssh = gst_buffer_new_wrapped (g_memdup (node->data, pssh_size), pssh_size);
4042   GST_LOG_OBJECT (qtdemux, "cenc pssh size: %" G_GSIZE_FORMAT,
4043       gst_buffer_get_size (pssh));
4044
4045   parent_box_type = QT_FOURCC ((const guint8 *) node->parent->data + 4);
4046
4047   /* Push an event containing the pssh box onto the queues of all streams. */
4048   event = gst_event_new_protection (sysid_string, pssh,
4049       (parent_box_type == FOURCC_moov) ? "isobmff/moov" : "isobmff/moof");
4050   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
4051     QtDemuxStream *stream = QTDEMUX_NTH_STREAM (qtdemux, i);
4052     GST_TRACE_OBJECT (qtdemux,
4053         "adding protection event for stream %s and system %s",
4054         stream->stream_id, sysid_string);
4055     g_queue_push_tail (&stream->protection_scheme_event_queue,
4056         gst_event_ref (event));
4057   }
4058   g_free (sysid_string);
4059   gst_event_unref (event);
4060   gst_buffer_unref (pssh);
4061   return TRUE;
4062 }
4063
4064 static gboolean
4065 qtdemux_parse_moof (GstQTDemux * qtdemux, const guint8 * buffer, guint length,
4066     guint64 moof_offset, QtDemuxStream * stream)
4067 {
4068   GNode *moof_node, *traf_node, *tfhd_node, *trun_node, *tfdt_node, *mfhd_node;
4069   GNode *uuid_node;
4070   GstByteReader mfhd_data, trun_data, tfhd_data, tfdt_data;
4071   GNode *saiz_node, *saio_node, *pssh_node;
4072   GstByteReader saiz_data, saio_data;
4073   guint32 ds_size = 0, ds_duration = 0, ds_flags = 0;
4074   gint64 base_offset, running_offset;
4075   guint32 frag_num;
4076   GstClockTime min_dts = GST_CLOCK_TIME_NONE;
4077
4078   /* NOTE @stream ignored */
4079
4080   moof_node = g_node_new ((guint8 *) buffer);
4081   qtdemux_parse_node (qtdemux, moof_node, buffer, length);
4082   qtdemux_node_dump (qtdemux, moof_node);
4083
4084   /* Get fragment number from mfhd and check it's valid */
4085   mfhd_node =
4086       qtdemux_tree_get_child_by_type_full (moof_node, FOURCC_mfhd, &mfhd_data);
4087   if (mfhd_node == NULL)
4088     goto missing_mfhd;
4089   if (!qtdemux_parse_mfhd (qtdemux, &mfhd_data, &frag_num))
4090     goto fail;
4091   GST_DEBUG_OBJECT (qtdemux, "Fragment #%d", frag_num);
4092
4093   /* unknown base_offset to start with */
4094   base_offset = running_offset = -1;
4095   traf_node = qtdemux_tree_get_child_by_type (moof_node, FOURCC_traf);
4096   while (traf_node) {
4097     guint64 decode_time = 0;
4098
4099     /* Fragment Header node */
4100     tfhd_node =
4101         qtdemux_tree_get_child_by_type_full (traf_node, FOURCC_tfhd,
4102         &tfhd_data);
4103     if (!tfhd_node)
4104       goto missing_tfhd;
4105     if (!qtdemux_parse_tfhd (qtdemux, &tfhd_data, &stream, &ds_duration,
4106             &ds_size, &ds_flags, &base_offset))
4107       goto missing_tfhd;
4108
4109     /* The following code assumes at most a single set of sample auxiliary
4110      * data in the fragment (consisting of a saiz box and a corresponding saio
4111      * box); in theory, however, there could be multiple sets of sample
4112      * auxiliary data in a fragment. */
4113     saiz_node =
4114         qtdemux_tree_get_child_by_type_full (traf_node, FOURCC_saiz,
4115         &saiz_data);
4116     if (saiz_node) {
4117       guint32 info_type = 0;
4118       guint64 offset = 0;
4119       guint32 info_type_parameter = 0;
4120
4121       g_free (qtdemux->cenc_aux_info_sizes);
4122
4123       qtdemux->cenc_aux_info_sizes =
4124           qtdemux_parse_saiz (qtdemux, stream, &saiz_data,
4125           &qtdemux->cenc_aux_sample_count);
4126       if (qtdemux->cenc_aux_info_sizes == NULL) {
4127         GST_ERROR_OBJECT (qtdemux, "failed to parse saiz box");
4128         goto fail;
4129       }
4130       saio_node =
4131           qtdemux_tree_get_child_by_type_full (traf_node, FOURCC_saio,
4132           &saio_data);
4133       if (!saio_node) {
4134         GST_ERROR_OBJECT (qtdemux, "saiz box without a corresponding saio box");
4135         g_free (qtdemux->cenc_aux_info_sizes);
4136         qtdemux->cenc_aux_info_sizes = NULL;
4137         goto fail;
4138       }
4139
4140       if (G_UNLIKELY (!qtdemux_parse_saio (qtdemux, stream, &saio_data,
4141                   &info_type, &info_type_parameter, &offset))) {
4142         GST_ERROR_OBJECT (qtdemux, "failed to parse saio box");
4143         g_free (qtdemux->cenc_aux_info_sizes);
4144         qtdemux->cenc_aux_info_sizes = NULL;
4145         goto fail;
4146       }
4147       if (base_offset > -1 && base_offset > qtdemux->moof_offset)
4148         offset += (guint64) (base_offset - qtdemux->moof_offset);
4149       if (info_type == FOURCC_cenc && info_type_parameter == 0U) {
4150         GstByteReader br;
4151         if (offset > length) {
4152           GST_DEBUG_OBJECT (qtdemux, "cenc auxiliary info stored out of moof");
4153           qtdemux->cenc_aux_info_offset = offset;
4154         } else {
4155           gst_byte_reader_init (&br, buffer + offset, length - offset);
4156           if (!qtdemux_parse_cenc_aux_info (qtdemux, stream, &br,
4157                   qtdemux->cenc_aux_info_sizes,
4158                   qtdemux->cenc_aux_sample_count)) {
4159             GST_ERROR_OBJECT (qtdemux, "failed to parse cenc auxiliary info");
4160             g_free (qtdemux->cenc_aux_info_sizes);
4161             qtdemux->cenc_aux_info_sizes = NULL;
4162             goto fail;
4163           }
4164         }
4165       }
4166     }
4167
4168     tfdt_node =
4169         qtdemux_tree_get_child_by_type_full (traf_node, FOURCC_tfdt,
4170         &tfdt_data);
4171     if (tfdt_node) {
4172       /* We'll use decode_time to interpolate timestamps
4173        * in case the input timestamps are missing */
4174       qtdemux_parse_tfdt (qtdemux, &tfdt_data, &decode_time);
4175
4176       GST_DEBUG_OBJECT (qtdemux, "decode time %" G_GINT64_FORMAT
4177           " (%" GST_TIME_FORMAT ")", decode_time,
4178           GST_TIME_ARGS (stream ? QTSTREAMTIME_TO_GSTTIME (stream,
4179                   decode_time) : GST_CLOCK_TIME_NONE));
4180
4181       /* Discard the fragment buffer timestamp info to avoid using it.
4182        * Rely on tfdt instead as it is more accurate than the timestamp
4183        * that is fetched from a manifest/playlist and is usually
4184        * less accurate. */
4185       qtdemux->fragment_start = -1;
4186     }
4187
4188     if (G_UNLIKELY (!stream)) {
4189       /* we lost track of offset, we'll need to regain it,
4190        * but can delay complaining until later or avoid doing so altogether */
4191       base_offset = -2;
4192       goto next;
4193     }
4194     if (G_UNLIKELY (base_offset < -1))
4195       goto lost_offset;
4196
4197     min_dts = MIN (min_dts, QTSTREAMTIME_TO_GSTTIME (stream, decode_time));
4198
4199     if (!qtdemux->pullbased) {
4200       /* Sample tables can grow enough to be problematic if the system memory
4201        * is very low (e.g. embedded devices) and the videos very long
4202        * (~8 MiB/hour for 25-30 fps video + typical AAC audio frames).
4203        * Fortunately, we can easily discard them for each new fragment when
4204        * we know qtdemux will not receive seeks outside of the current fragment.
4205        * adaptivedemux honors this assumption.
4206        * This optimization is also useful for applications that use qtdemux as
4207        * a push-based simple demuxer, like Media Source Extensions. */
4208       gst_qtdemux_stream_flush_samples_data (stream);
4209     }
4210
4211     /* initialise moof sample data */
4212     stream->n_samples_moof = 0;
4213     stream->duration_last_moof = stream->duration_moof;
4214     stream->duration_moof = 0;
4215
4216     /* Track Run node */
4217     trun_node =
4218         qtdemux_tree_get_child_by_type_full (traf_node, FOURCC_trun,
4219         &trun_data);
4220     while (trun_node) {
4221       qtdemux_parse_trun (qtdemux, &trun_data, stream,
4222           ds_duration, ds_size, ds_flags, moof_offset, length, &base_offset,
4223           &running_offset, decode_time, (tfdt_node != NULL));
4224       /* iterate all siblings */
4225       trun_node = qtdemux_tree_get_sibling_by_type_full (trun_node, FOURCC_trun,
4226           &trun_data);
4227     }
4228
4229     uuid_node = qtdemux_tree_get_child_by_type (traf_node, FOURCC_uuid);
4230     if (uuid_node) {
4231       guint8 *uuid_buffer = (guint8 *) uuid_node->data;
4232       guint32 box_length = QT_UINT32 (uuid_buffer);
4233
4234       qtdemux_parse_uuid (qtdemux, uuid_buffer, box_length);
4235     }
4236
4237     /* if no new base_offset provided for next traf,
4238      * base is end of current traf */
4239     base_offset = running_offset;
4240     running_offset = -1;
4241
4242     if (stream->n_samples_moof && stream->duration_moof)
4243       stream->new_caps = TRUE;
4244
4245   next:
4246     /* iterate all siblings */
4247     traf_node = qtdemux_tree_get_sibling_by_type (traf_node, FOURCC_traf);
4248   }
4249
4250   /* parse any protection system info */
4251   pssh_node = qtdemux_tree_get_child_by_type (moof_node, FOURCC_pssh);
4252   while (pssh_node) {
4253     GST_LOG_OBJECT (qtdemux, "Parsing pssh box.");
4254     qtdemux_parse_pssh (qtdemux, pssh_node);
4255     pssh_node = qtdemux_tree_get_sibling_by_type (pssh_node, FOURCC_pssh);
4256   }
4257
4258   if (!qtdemux->upstream_format_is_time && !qtdemux->first_moof_already_parsed
4259       && !qtdemux->received_seek && GST_CLOCK_TIME_IS_VALID (min_dts)
4260       && min_dts != 0) {
4261     /* Unless the user has explictly requested another seek, perform an
4262      * internal seek to the time specified in the tfdt.
4263      *
4264      * This way if the user opens a file where the first tfdt is 1 hour
4265      * into the presentation, they will not have to wait 1 hour for run
4266      * time to catch up and actual playback to start. */
4267     gint i;
4268
4269     GST_DEBUG_OBJECT (qtdemux, "First fragment has a non-zero tfdt, "
4270         "performing an internal seek to %" GST_TIME_FORMAT,
4271         GST_TIME_ARGS (min_dts));
4272
4273     qtdemux->segment.start = min_dts;
4274     qtdemux->segment.time = qtdemux->segment.position = min_dts;
4275
4276     for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
4277       QtDemuxStream *stream = QTDEMUX_NTH_STREAM (qtdemux, i);
4278       stream->time_position = min_dts;
4279     }
4280
4281     /* Before this code was run a segment was already sent when the moov was
4282      * parsed... which is OK -- some apps (mostly tests) expect a segment to
4283      * be emitted after a moov, and we can emit a second segment anyway for
4284      * special cases like this. */
4285     qtdemux->need_segment = TRUE;
4286   }
4287
4288   qtdemux->first_moof_already_parsed = TRUE;
4289
4290   g_node_destroy (moof_node);
4291   return TRUE;
4292
4293 missing_tfhd:
4294   {
4295     GST_DEBUG_OBJECT (qtdemux, "missing tfhd box");
4296     goto fail;
4297   }
4298 missing_mfhd:
4299   {
4300     GST_DEBUG_OBJECT (qtdemux, "Missing mfhd box");
4301     goto fail;
4302   }
4303 lost_offset:
4304   {
4305     GST_DEBUG_OBJECT (qtdemux, "lost offset");
4306     goto fail;
4307   }
4308 fail:
4309   {
4310     g_node_destroy (moof_node);
4311     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
4312         (_("This file is corrupt and cannot be played.")), (NULL));
4313     return FALSE;
4314   }
4315 }
4316
4317 #if 0
4318 /* might be used if some day we actually use mfra & co
4319  * for random access to fragments,
4320  * but that will require quite some modifications and much less relying
4321  * on a sample array */
4322 #endif
4323
4324 static gboolean
4325 qtdemux_parse_tfra (GstQTDemux * qtdemux, GNode * tfra_node)
4326 {
4327   QtDemuxStream *stream;
4328   guint32 ver_flags, track_id, len, num_entries, i;
4329   guint value_size, traf_size, trun_size, sample_size;
4330   guint64 time = 0, moof_offset = 0;
4331 #if 0
4332   GstBuffer *buf = NULL;
4333   GstFlowReturn ret;
4334 #endif
4335   GstByteReader tfra;
4336
4337   gst_byte_reader_init (&tfra, tfra_node->data, QT_UINT32 (tfra_node->data));
4338
4339   if (!gst_byte_reader_skip (&tfra, 8))
4340     return FALSE;
4341
4342   if (!gst_byte_reader_get_uint32_be (&tfra, &ver_flags))
4343     return FALSE;
4344
4345   if (!gst_byte_reader_get_uint32_be (&tfra, &track_id)
4346       || !gst_byte_reader_get_uint32_be (&tfra, &len)
4347       || !gst_byte_reader_get_uint32_be (&tfra, &num_entries))
4348     return FALSE;
4349
4350   GST_DEBUG_OBJECT (qtdemux, "parsing tfra box for track id %u", track_id);
4351
4352   stream = qtdemux_find_stream (qtdemux, track_id);
4353   if (stream == NULL)
4354     goto unknown_trackid;
4355
4356   value_size = ((ver_flags >> 24) == 1) ? sizeof (guint64) : sizeof (guint32);
4357   sample_size = (len & 3) + 1;
4358   trun_size = ((len & 12) >> 2) + 1;
4359   traf_size = ((len & 48) >> 4) + 1;
4360
4361   GST_DEBUG_OBJECT (qtdemux, "%u entries, sizes: value %u, traf %u, trun %u, "
4362       "sample %u", num_entries, value_size, traf_size, trun_size, sample_size);
4363
4364   if (num_entries == 0)
4365     goto no_samples;
4366
4367   if (!qt_atom_parser_has_chunks (&tfra, num_entries,
4368           value_size + value_size + traf_size + trun_size + sample_size))
4369     goto corrupt_file;
4370
4371   g_free (stream->ra_entries);
4372   stream->ra_entries = g_new (QtDemuxRandomAccessEntry, num_entries);
4373   stream->n_ra_entries = num_entries;
4374
4375   for (i = 0; i < num_entries; i++) {
4376     qt_atom_parser_get_offset (&tfra, value_size, &time);
4377     qt_atom_parser_get_offset (&tfra, value_size, &moof_offset);
4378     qt_atom_parser_get_uint_with_size_unchecked (&tfra, traf_size);
4379     qt_atom_parser_get_uint_with_size_unchecked (&tfra, trun_size);
4380     qt_atom_parser_get_uint_with_size_unchecked (&tfra, sample_size);
4381
4382     time = QTSTREAMTIME_TO_GSTTIME (stream, time);
4383
4384     GST_LOG_OBJECT (qtdemux, "fragment time: %" GST_TIME_FORMAT ", "
4385         " moof_offset: %" G_GUINT64_FORMAT, GST_TIME_ARGS (time), moof_offset);
4386
4387     stream->ra_entries[i].ts = time;
4388     stream->ra_entries[i].moof_offset = moof_offset;
4389
4390     /* don't want to go through the entire file and read all moofs at startup */
4391 #if 0
4392     ret = gst_qtdemux_pull_atom (qtdemux, moof_offset, 0, &buf);
4393     if (ret != GST_FLOW_OK)
4394       goto corrupt_file;
4395     qtdemux_parse_moof (qtdemux, GST_BUFFER_DATA (buf), GST_BUFFER_SIZE (buf),
4396         moof_offset, stream);
4397     gst_buffer_unref (buf);
4398 #endif
4399   }
4400
4401   check_update_duration (qtdemux, time);
4402
4403   return TRUE;
4404
4405 /* ERRORS */
4406 unknown_trackid:
4407   {
4408     GST_WARNING_OBJECT (qtdemux, "Couldn't find stream for track %u", track_id);
4409     return FALSE;
4410   }
4411 corrupt_file:
4412   {
4413     GST_WARNING_OBJECT (qtdemux, "broken traf box, ignoring");
4414     return FALSE;
4415   }
4416 no_samples:
4417   {
4418     GST_WARNING_OBJECT (qtdemux, "stream has no samples");
4419     return FALSE;
4420   }
4421 }
4422
4423 static gboolean
4424 qtdemux_pull_mfro_mfra (GstQTDemux * qtdemux)
4425 {
4426   GstMapInfo mfro_map = GST_MAP_INFO_INIT;
4427   GstMapInfo mfra_map = GST_MAP_INFO_INIT;
4428   GstBuffer *mfro = NULL, *mfra = NULL;
4429   GstFlowReturn flow;
4430   gboolean ret = FALSE;
4431   GNode *mfra_node, *tfra_node;
4432   guint64 mfra_offset = 0;
4433   guint32 fourcc, mfra_size;
4434   gint64 len;
4435
4436   /* query upstream size in bytes */
4437   if (!gst_pad_peer_query_duration (qtdemux->sinkpad, GST_FORMAT_BYTES, &len))
4438     goto size_query_failed;
4439
4440   /* mfro box should be at the very end of the file */
4441   flow = gst_qtdemux_pull_atom (qtdemux, len - 16, 16, &mfro);
4442   if (flow != GST_FLOW_OK)
4443     goto exit;
4444
4445   gst_buffer_map (mfro, &mfro_map, GST_MAP_READ);
4446
4447   fourcc = QT_FOURCC (mfro_map.data + 4);
4448   if (fourcc != FOURCC_mfro)
4449     goto exit;
4450
4451   GST_INFO_OBJECT (qtdemux, "Found mfro box");
4452   if (mfro_map.size < 16)
4453     goto invalid_mfro_size;
4454
4455   mfra_size = QT_UINT32 (mfro_map.data + 12);
4456   if (mfra_size >= len)
4457     goto invalid_mfra_size;
4458
4459   mfra_offset = len - mfra_size;
4460
4461   GST_INFO_OBJECT (qtdemux, "mfra offset: %" G_GUINT64_FORMAT ", size %u",
4462       mfra_offset, mfra_size);
4463
4464   /* now get and parse mfra box */
4465   flow = gst_qtdemux_pull_atom (qtdemux, mfra_offset, mfra_size, &mfra);
4466   if (flow != GST_FLOW_OK)
4467     goto broken_file;
4468
4469   gst_buffer_map (mfra, &mfra_map, GST_MAP_READ);
4470
4471   mfra_node = g_node_new ((guint8 *) mfra_map.data);
4472   qtdemux_parse_node (qtdemux, mfra_node, mfra_map.data, mfra_map.size);
4473
4474   tfra_node = qtdemux_tree_get_child_by_type (mfra_node, FOURCC_tfra);
4475
4476   while (tfra_node) {
4477     qtdemux_parse_tfra (qtdemux, tfra_node);
4478     /* iterate all siblings */
4479     tfra_node = qtdemux_tree_get_sibling_by_type (tfra_node, FOURCC_tfra);
4480   }
4481   g_node_destroy (mfra_node);
4482
4483   GST_INFO_OBJECT (qtdemux, "parsed movie fragment random access box (mfra)");
4484   ret = TRUE;
4485
4486 exit:
4487
4488   if (mfro) {
4489     if (mfro_map.memory != NULL)
4490       gst_buffer_unmap (mfro, &mfro_map);
4491     gst_buffer_unref (mfro);
4492   }
4493   if (mfra) {
4494     if (mfra_map.memory != NULL)
4495       gst_buffer_unmap (mfra, &mfra_map);
4496     gst_buffer_unref (mfra);
4497   }
4498   return ret;
4499
4500 /* ERRORS */
4501 size_query_failed:
4502   {
4503     GST_WARNING_OBJECT (qtdemux, "could not query upstream size");
4504     goto exit;
4505   }
4506 invalid_mfro_size:
4507   {
4508     GST_WARNING_OBJECT (qtdemux, "mfro size is too small");
4509     goto exit;
4510   }
4511 invalid_mfra_size:
4512   {
4513     GST_WARNING_OBJECT (qtdemux, "mfra_size in mfro box is invalid");
4514     goto exit;
4515   }
4516 broken_file:
4517   {
4518     GST_WARNING_OBJECT (qtdemux, "bogus mfra offset or size, broken file");
4519     goto exit;
4520   }
4521 }
4522
4523 static guint64
4524 add_offset (guint64 offset, guint64 advance)
4525 {
4526   /* Avoid 64-bit overflow by clamping */
4527   if (offset > G_MAXUINT64 - advance)
4528     return G_MAXUINT64;
4529   return offset + advance;
4530 }
4531
4532 static GstFlowReturn
4533 gst_qtdemux_loop_state_header (GstQTDemux * qtdemux)
4534 {
4535   guint64 length = 0;
4536   guint32 fourcc = 0;
4537   GstBuffer *buf = NULL;
4538   GstFlowReturn ret = GST_FLOW_OK;
4539   guint64 cur_offset = qtdemux->offset;
4540   GstMapInfo map;
4541
4542   ret = gst_pad_pull_range (qtdemux->sinkpad, cur_offset, 16, &buf);
4543   if (G_UNLIKELY (ret != GST_FLOW_OK))
4544     goto beach;
4545   gst_buffer_map (buf, &map, GST_MAP_READ);
4546   if (G_LIKELY (map.size >= 8))
4547     extract_initial_length_and_fourcc (map.data, map.size, &length, &fourcc);
4548   gst_buffer_unmap (buf, &map);
4549   gst_buffer_unref (buf);
4550
4551   /* maybe we already got most we needed, so only consider this eof */
4552   if (G_UNLIKELY (length == 0)) {
4553     GST_ELEMENT_WARNING (qtdemux, STREAM, DEMUX,
4554         (_("Invalid atom size.")),
4555         ("Header atom '%" GST_FOURCC_FORMAT "' has empty length",
4556             GST_FOURCC_ARGS (fourcc)));
4557     ret = GST_FLOW_EOS;
4558     goto beach;
4559   }
4560
4561   switch (fourcc) {
4562     case FOURCC_moof:
4563       /* record for later parsing when needed */
4564       if (!qtdemux->moof_offset) {
4565         qtdemux->moof_offset = qtdemux->offset;
4566       }
4567       if (qtdemux_pull_mfro_mfra (qtdemux)) {
4568         /* FIXME */
4569       } else {
4570         qtdemux->offset += length;      /* skip moof and keep going */
4571       }
4572       if (qtdemux->got_moov) {
4573         GST_INFO_OBJECT (qtdemux, "moof header, got moov, done with headers");
4574         ret = GST_FLOW_EOS;
4575         goto beach;
4576       }
4577       break;
4578     case FOURCC_mdat:
4579     case FOURCC_free:
4580     case FOURCC_skip:
4581     case FOURCC_wide:
4582     case FOURCC_PICT:
4583     case FOURCC_pnot:
4584     {
4585       GST_LOG_OBJECT (qtdemux,
4586           "skipping atom '%" GST_FOURCC_FORMAT "' at %" G_GUINT64_FORMAT,
4587           GST_FOURCC_ARGS (fourcc), cur_offset);
4588       qtdemux->offset = add_offset (qtdemux->offset, length);
4589       break;
4590     }
4591     case FOURCC_moov:
4592     {
4593       GstBuffer *moov = NULL;
4594
4595       if (qtdemux->got_moov) {
4596         GST_DEBUG_OBJECT (qtdemux, "Skipping moov atom as we have one already");
4597         qtdemux->offset = add_offset (qtdemux->offset, length);
4598         goto beach;
4599       }
4600
4601       ret = gst_pad_pull_range (qtdemux->sinkpad, cur_offset, length, &moov);
4602       if (ret != GST_FLOW_OK)
4603         goto beach;
4604       gst_buffer_map (moov, &map, GST_MAP_READ);
4605
4606       if (length != map.size) {
4607         /* Some files have a 'moov' atom at the end of the file which contains
4608          * a terminal 'free' atom where the body of the atom is missing.
4609          * Check for, and permit, this special case.
4610          */
4611         if (map.size >= 8) {
4612           guint8 *final_data = map.data + (map.size - 8);
4613           guint32 final_length = QT_UINT32 (final_data);
4614           guint32 final_fourcc = QT_FOURCC (final_data + 4);
4615
4616           if (final_fourcc == FOURCC_free
4617               && map.size + final_length - 8 == length) {
4618             /* Ok, we've found that special case. Allocate a new buffer with
4619              * that free atom actually present. */
4620             GstBuffer *newmoov = gst_buffer_new_and_alloc (length);
4621             gst_buffer_fill (newmoov, 0, map.data, map.size);
4622             gst_buffer_memset (newmoov, map.size, 0, final_length - 8);
4623             gst_buffer_unmap (moov, &map);
4624             gst_buffer_unref (moov);
4625             moov = newmoov;
4626             gst_buffer_map (moov, &map, GST_MAP_READ);
4627           }
4628         }
4629       }
4630
4631       if (length != map.size) {
4632         GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
4633             (_("This file is incomplete and cannot be played.")),
4634             ("We got less than expected (received %" G_GSIZE_FORMAT
4635                 ", wanted %u, offset %" G_GUINT64_FORMAT ")", map.size,
4636                 (guint) length, cur_offset));
4637         gst_buffer_unmap (moov, &map);
4638         gst_buffer_unref (moov);
4639         ret = GST_FLOW_ERROR;
4640         goto beach;
4641       }
4642       qtdemux->offset += length;
4643
4644       qtdemux_parse_moov (qtdemux, map.data, length);
4645       qtdemux_node_dump (qtdemux, qtdemux->moov_node);
4646
4647       qtdemux_parse_tree (qtdemux);
4648       if (qtdemux->moov_node_compressed) {
4649         g_node_destroy (qtdemux->moov_node_compressed);
4650         g_free (qtdemux->moov_node->data);
4651       }
4652       qtdemux->moov_node_compressed = NULL;
4653       g_node_destroy (qtdemux->moov_node);
4654       qtdemux->moov_node = NULL;
4655       gst_buffer_unmap (moov, &map);
4656       gst_buffer_unref (moov);
4657       qtdemux->got_moov = TRUE;
4658
4659       break;
4660     }
4661     case FOURCC_ftyp:
4662     {
4663       GstBuffer *ftyp = NULL;
4664
4665       /* extract major brand; might come in handy for ISO vs QT issues */
4666       ret = gst_qtdemux_pull_atom (qtdemux, cur_offset, length, &ftyp);
4667       if (ret != GST_FLOW_OK)
4668         goto beach;
4669       qtdemux->offset += length;
4670       gst_buffer_map (ftyp, &map, GST_MAP_READ);
4671       qtdemux_parse_ftyp (qtdemux, map.data, map.size);
4672       gst_buffer_unmap (ftyp, &map);
4673       gst_buffer_unref (ftyp);
4674       break;
4675     }
4676     case FOURCC_uuid:
4677     {
4678       GstBuffer *uuid = NULL;
4679
4680       /* uuid are extension atoms */
4681       ret = gst_qtdemux_pull_atom (qtdemux, cur_offset, length, &uuid);
4682       if (ret != GST_FLOW_OK)
4683         goto beach;
4684       qtdemux->offset += length;
4685       gst_buffer_map (uuid, &map, GST_MAP_READ);
4686       qtdemux_parse_uuid (qtdemux, map.data, map.size);
4687       gst_buffer_unmap (uuid, &map);
4688       gst_buffer_unref (uuid);
4689       break;
4690     }
4691     case FOURCC_sidx:
4692     {
4693       GstBuffer *sidx = NULL;
4694       ret = gst_qtdemux_pull_atom (qtdemux, cur_offset, length, &sidx);
4695       if (ret != GST_FLOW_OK)
4696         goto beach;
4697       qtdemux->offset += length;
4698       gst_buffer_map (sidx, &map, GST_MAP_READ);
4699       qtdemux_parse_sidx (qtdemux, map.data, map.size);
4700       gst_buffer_unmap (sidx, &map);
4701       gst_buffer_unref (sidx);
4702       break;
4703     }
4704     default:
4705     {
4706       GstBuffer *unknown = NULL;
4707
4708       GST_LOG_OBJECT (qtdemux,
4709           "unknown %08x '%" GST_FOURCC_FORMAT "' of size %" G_GUINT64_FORMAT
4710           " at %" G_GUINT64_FORMAT, fourcc, GST_FOURCC_ARGS (fourcc), length,
4711           cur_offset);
4712       ret = gst_qtdemux_pull_atom (qtdemux, cur_offset, length, &unknown);
4713       if (ret != GST_FLOW_OK)
4714         goto beach;
4715       gst_buffer_map (unknown, &map, GST_MAP_READ);
4716       GST_MEMDUMP ("Unknown tag", map.data, map.size);
4717       gst_buffer_unmap (unknown, &map);
4718       gst_buffer_unref (unknown);
4719       qtdemux->offset += length;
4720       break;
4721     }
4722   }
4723
4724 beach:
4725   if (ret == GST_FLOW_EOS && (qtdemux->got_moov || qtdemux->media_caps)) {
4726     /* digested all data, show what we have */
4727     qtdemux_prepare_streams (qtdemux);
4728     QTDEMUX_EXPOSE_LOCK (qtdemux);
4729     ret = qtdemux_expose_streams (qtdemux);
4730     QTDEMUX_EXPOSE_UNLOCK (qtdemux);
4731
4732     qtdemux->state = QTDEMUX_STATE_MOVIE;
4733     GST_DEBUG_OBJECT (qtdemux, "switching state to STATE_MOVIE (%d)",
4734         qtdemux->state);
4735     return ret;
4736   }
4737   return ret;
4738 }
4739
4740 /* Seeks to the previous keyframe of the indexed stream and
4741  * aligns other streams with respect to the keyframe timestamp
4742  * of indexed stream. Only called in case of Reverse Playback
4743  */
4744 static GstFlowReturn
4745 gst_qtdemux_seek_to_previous_keyframe (GstQTDemux * qtdemux)
4746 {
4747   guint32 seg_idx = 0, k_index = 0;
4748   guint32 ref_seg_idx, ref_k_index;
4749   GstClockTime k_pos = 0, last_stop = 0;
4750   QtDemuxSegment *seg = NULL;
4751   QtDemuxStream *ref_str = NULL;
4752   guint64 seg_media_start_mov;  /* segment media start time in mov format */
4753   guint64 target_ts;
4754   gint i;
4755
4756   /* Now we choose an arbitrary stream, get the previous keyframe timestamp
4757    * and finally align all the other streams on that timestamp with their
4758    * respective keyframes */
4759   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
4760     QtDemuxStream *str = QTDEMUX_NTH_STREAM (qtdemux, i);
4761
4762     /* No candidate yet, take the first stream */
4763     if (!ref_str) {
4764       ref_str = str;
4765       continue;
4766     }
4767
4768     /* So that stream has a segment, we prefer video streams */
4769     if (str->subtype == FOURCC_vide) {
4770       ref_str = str;
4771       break;
4772     }
4773   }
4774
4775   if (G_UNLIKELY (!ref_str)) {
4776     GST_DEBUG_OBJECT (qtdemux, "couldn't find any stream");
4777     goto eos;
4778   }
4779
4780   if (G_UNLIKELY (!ref_str->from_sample)) {
4781     GST_DEBUG_OBJECT (qtdemux, "reached the beginning of the file");
4782     goto eos;
4783   }
4784
4785   /* So that stream has been playing from from_sample to to_sample. We will
4786    * get the timestamp of the previous sample and search for a keyframe before
4787    * that. For audio streams we do an arbitrary jump in the past (10 samples) */
4788   if (ref_str->subtype == FOURCC_vide) {
4789     k_index = gst_qtdemux_find_keyframe (qtdemux, ref_str,
4790         ref_str->from_sample - 1, FALSE);
4791   } else {
4792     if (ref_str->from_sample >= 10)
4793       k_index = ref_str->from_sample - 10;
4794     else
4795       k_index = 0;
4796   }
4797
4798   target_ts =
4799       ref_str->samples[k_index].timestamp +
4800       ref_str->samples[k_index].pts_offset;
4801
4802   /* get current segment for that stream */
4803   seg = &ref_str->segments[ref_str->segment_index];
4804   /* Use segment start in original timescale for comparisons */
4805   seg_media_start_mov = seg->trak_media_start;
4806
4807   GST_LOG_OBJECT (qtdemux, "keyframe index %u ts %" G_GUINT64_FORMAT
4808       " seg start %" G_GUINT64_FORMAT " %" GST_TIME_FORMAT,
4809       k_index, target_ts, seg_media_start_mov,
4810       GST_TIME_ARGS (seg->media_start));
4811
4812   /* Crawl back through segments to find the one containing this I frame */
4813   while (target_ts < seg_media_start_mov) {
4814     GST_DEBUG_OBJECT (qtdemux,
4815         "keyframe position (sample %u) is out of segment %u " " target %"
4816         G_GUINT64_FORMAT " seg start %" G_GUINT64_FORMAT, k_index,
4817         ref_str->segment_index, target_ts, seg_media_start_mov);
4818
4819     if (G_UNLIKELY (!ref_str->segment_index)) {
4820       /* Reached first segment, let's consider it's EOS */
4821       goto eos;
4822     }
4823     ref_str->segment_index--;
4824     seg = &ref_str->segments[ref_str->segment_index];
4825     /* Use segment start in original timescale for comparisons */
4826     seg_media_start_mov = seg->trak_media_start;
4827   }
4828   /* Calculate time position of the keyframe and where we should stop */
4829   k_pos =
4830       QTSTREAMTIME_TO_GSTTIME (ref_str,
4831       target_ts - seg->trak_media_start) + seg->time;
4832   last_stop =
4833       QTSTREAMTIME_TO_GSTTIME (ref_str,
4834       ref_str->samples[ref_str->from_sample].timestamp -
4835       seg->trak_media_start) + seg->time;
4836
4837   GST_DEBUG_OBJECT (qtdemux, "preferred stream played from sample %u, "
4838       "now going to sample %u (pts %" GST_TIME_FORMAT ")", ref_str->from_sample,
4839       k_index, GST_TIME_ARGS (k_pos));
4840
4841   /* Set last_stop with the keyframe timestamp we pushed of that stream */
4842   qtdemux->segment.position = last_stop;
4843   GST_DEBUG_OBJECT (qtdemux, "last_stop now is %" GST_TIME_FORMAT,
4844       GST_TIME_ARGS (last_stop));
4845
4846   if (G_UNLIKELY (last_stop < qtdemux->segment.start)) {
4847     GST_DEBUG_OBJECT (qtdemux, "reached the beginning of segment");
4848     goto eos;
4849   }
4850
4851   ref_seg_idx = ref_str->segment_index;
4852   ref_k_index = k_index;
4853
4854   /* Align them all on this */
4855   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
4856     guint32 index = 0;
4857     GstClockTime seg_time = 0;
4858     QtDemuxStream *str = QTDEMUX_NTH_STREAM (qtdemux, i);
4859
4860     /* aligning reference stream again might lead to backing up to yet another
4861      * keyframe (due to timestamp rounding issues),
4862      * potentially putting more load on downstream; so let's try to avoid */
4863     if (str == ref_str) {
4864       seg_idx = ref_seg_idx;
4865       seg = &str->segments[seg_idx];
4866       k_index = ref_k_index;
4867       GST_DEBUG_OBJECT (qtdemux, "reference track-id %u segment %d, "
4868           "sample at index %d", str->track_id, ref_str->segment_index, k_index);
4869     } else {
4870       seg_idx = gst_qtdemux_find_segment (qtdemux, str, k_pos);
4871       GST_DEBUG_OBJECT (qtdemux,
4872           "track-id %u align segment %d for keyframe pos %" GST_TIME_FORMAT,
4873           str->track_id, seg_idx, GST_TIME_ARGS (k_pos));
4874
4875       /* get segment and time in the segment */
4876       seg = &str->segments[seg_idx];
4877       seg_time = k_pos - seg->time;
4878
4879       /* get the media time in the segment.
4880        * No adjustment for empty "filler" segments */
4881       if (seg->media_start != GST_CLOCK_TIME_NONE)
4882         seg_time += seg->media_start;
4883
4884       /* get the index of the sample with media time */
4885       index = gst_qtdemux_find_index_linear (qtdemux, str, seg_time);
4886       GST_DEBUG_OBJECT (qtdemux,
4887           "track-id %u sample for %" GST_TIME_FORMAT " at %u", str->track_id,
4888           GST_TIME_ARGS (seg_time), index);
4889
4890       /* find previous keyframe */
4891       k_index = gst_qtdemux_find_keyframe (qtdemux, str, index, FALSE);
4892     }
4893
4894     /* Remember until where we want to go */
4895     str->to_sample = str->from_sample - 1;
4896     /* Define our time position */
4897     target_ts =
4898         str->samples[k_index].timestamp + str->samples[k_index].pts_offset;
4899     str->time_position = QTSTREAMTIME_TO_GSTTIME (str, target_ts) + seg->time;
4900     if (seg->media_start != GST_CLOCK_TIME_NONE)
4901       str->time_position -= seg->media_start;
4902
4903     /* Now seek back in time */
4904     gst_qtdemux_move_stream (qtdemux, str, k_index);
4905     GST_DEBUG_OBJECT (qtdemux, "track-id %u keyframe at %u, time position %"
4906         GST_TIME_FORMAT " playing from sample %u to %u", str->track_id, k_index,
4907         GST_TIME_ARGS (str->time_position), str->from_sample, str->to_sample);
4908   }
4909
4910   return GST_FLOW_OK;
4911
4912 eos:
4913   return GST_FLOW_EOS;
4914 }
4915
4916 /*
4917  * Gets the current qt segment start, stop and position for the
4918  * given time offset. This is used in update_segment()
4919  */
4920 static void
4921 gst_qtdemux_stream_segment_get_boundaries (GstQTDemux * qtdemux,
4922     QtDemuxStream * stream, GstClockTime offset,
4923     GstClockTime * _start, GstClockTime * _stop, GstClockTime * _time)
4924 {
4925   GstClockTime seg_time;
4926   GstClockTime start, stop, time;
4927   QtDemuxSegment *segment;
4928
4929   segment = &stream->segments[stream->segment_index];
4930
4931   /* get time in this segment */
4932   seg_time = (offset - segment->time) * segment->rate;
4933
4934   GST_LOG_OBJECT (stream->pad, "seg_time %" GST_TIME_FORMAT,
4935       GST_TIME_ARGS (seg_time));
4936
4937   if (G_UNLIKELY (seg_time > segment->duration)) {
4938     GST_LOG_OBJECT (stream->pad,
4939         "seg_time > segment->duration %" GST_TIME_FORMAT,
4940         GST_TIME_ARGS (segment->duration));
4941     seg_time = segment->duration;
4942   }
4943
4944   /* qtdemux->segment.stop is in outside-time-realm, whereas
4945    * segment->media_stop is in track-time-realm.
4946    *
4947    * In order to compare the two, we need to bring segment.stop
4948    * into the track-time-realm
4949    *
4950    * FIXME - does this comment still hold? Don't see any conversion here */
4951
4952   stop = qtdemux->segment.stop;
4953   if (stop == GST_CLOCK_TIME_NONE)
4954     stop = qtdemux->segment.duration;
4955   if (stop == GST_CLOCK_TIME_NONE)
4956     stop = segment->media_stop;
4957   else
4958     stop =
4959         MIN (segment->media_stop, stop - segment->time + segment->media_start);
4960
4961   if (G_UNLIKELY (QTSEGMENT_IS_EMPTY (segment))) {
4962     start = segment->time + seg_time;
4963     time = offset;
4964     stop = start - seg_time + segment->duration;
4965   } else if (qtdemux->segment.rate >= 0) {
4966     start = MIN (segment->media_start + seg_time, stop);
4967     time = offset;
4968   } else {
4969     if (segment->media_start >= qtdemux->segment.start) {
4970       time = segment->time;
4971     } else {
4972       time = segment->time + (qtdemux->segment.start - segment->media_start);
4973     }
4974
4975     start = MAX (segment->media_start, qtdemux->segment.start);
4976     stop = MIN (segment->media_start + seg_time, stop);
4977   }
4978
4979   *_start = start;
4980   *_stop = stop;
4981   *_time = time;
4982 }
4983
4984 /*
4985  * Updates the qt segment used for the stream and pushes a new segment event
4986  * downstream on this stream's pad.
4987  */
4988 static gboolean
4989 gst_qtdemux_stream_update_segment (GstQTDemux * qtdemux, QtDemuxStream * stream,
4990     gint seg_idx, GstClockTime offset, GstClockTime * _start,
4991     GstClockTime * _stop)
4992 {
4993   QtDemuxSegment *segment;
4994   GstClockTime start = 0, stop = GST_CLOCK_TIME_NONE, time = 0;
4995   gdouble rate;
4996   GstEvent *event;
4997
4998   /* update the current segment */
4999   stream->segment_index = seg_idx;
5000
5001   /* get the segment */
5002   segment = &stream->segments[seg_idx];
5003
5004   if (G_UNLIKELY (offset < segment->time)) {
5005     GST_WARNING_OBJECT (stream->pad, "offset < segment->time %" GST_TIME_FORMAT,
5006         GST_TIME_ARGS (segment->time));
5007     return FALSE;
5008   }
5009
5010   /* segment lies beyond total indicated duration */
5011   if (G_UNLIKELY (qtdemux->segment.duration != GST_CLOCK_TIME_NONE &&
5012           segment->time > qtdemux->segment.duration)) {
5013     GST_WARNING_OBJECT (stream->pad, "file duration %" GST_TIME_FORMAT
5014         " < segment->time %" GST_TIME_FORMAT,
5015         GST_TIME_ARGS (qtdemux->segment.duration),
5016         GST_TIME_ARGS (segment->time));
5017     return FALSE;
5018   }
5019
5020   gst_qtdemux_stream_segment_get_boundaries (qtdemux, stream, offset,
5021       &start, &stop, &time);
5022
5023   GST_DEBUG_OBJECT (stream->pad, "new segment %d from %" GST_TIME_FORMAT
5024       " to %" GST_TIME_FORMAT ", time %" GST_TIME_FORMAT, seg_idx,
5025       GST_TIME_ARGS (start), GST_TIME_ARGS (stop), GST_TIME_ARGS (time));
5026
5027   /* combine global rate with that of the segment */
5028   rate = segment->rate * qtdemux->segment.rate;
5029
5030   /* Copy flags from main segment */
5031   stream->segment.flags = qtdemux->segment.flags;
5032
5033   /* update the segment values used for clipping */
5034   stream->segment.offset = qtdemux->segment.offset;
5035   stream->segment.base = qtdemux->segment.base + stream->accumulated_base;
5036   stream->segment.applied_rate = qtdemux->segment.applied_rate;
5037   stream->segment.rate = rate;
5038   stream->segment.start = start + QTSTREAMTIME_TO_GSTTIME (stream,
5039       stream->cslg_shift);
5040   stream->segment.stop = stop + QTSTREAMTIME_TO_GSTTIME (stream,
5041       stream->cslg_shift);
5042   stream->segment.time = time;
5043   stream->segment.position = stream->segment.start;
5044
5045   GST_DEBUG_OBJECT (stream->pad, "New segment: %" GST_SEGMENT_FORMAT,
5046       &stream->segment);
5047
5048   /* now prepare and send the segment */
5049   if (stream->pad) {
5050     event = gst_event_new_segment (&stream->segment);
5051     if (qtdemux->segment_seqnum != GST_SEQNUM_INVALID) {
5052       gst_event_set_seqnum (event, qtdemux->segment_seqnum);
5053     }
5054     gst_pad_push_event (stream->pad, event);
5055     /* assume we can send more data now */
5056     GST_PAD_LAST_FLOW_RETURN (stream->pad) = GST_FLOW_OK;
5057     /* clear to send tags on this pad now */
5058     gst_qtdemux_push_tags (qtdemux, stream);
5059   }
5060
5061   if (_start)
5062     *_start = start;
5063   if (_stop)
5064     *_stop = stop;
5065
5066   return TRUE;
5067 }
5068
5069 /* activate the given segment number @seg_idx of @stream at time @offset.
5070  * @offset is an absolute global position over all the segments.
5071  *
5072  * This will push out a NEWSEGMENT event with the right values and
5073  * position the stream index to the first decodable sample before
5074  * @offset.
5075  */
5076 static gboolean
5077 gst_qtdemux_activate_segment (GstQTDemux * qtdemux, QtDemuxStream * stream,
5078     guint32 seg_idx, GstClockTime offset)
5079 {
5080   QtDemuxSegment *segment;
5081   guint32 index, kf_index;
5082   GstClockTime start = 0, stop = GST_CLOCK_TIME_NONE;
5083
5084   GST_LOG_OBJECT (stream->pad, "activate segment %d, offset %" GST_TIME_FORMAT,
5085       seg_idx, GST_TIME_ARGS (offset));
5086
5087   if (!gst_qtdemux_stream_update_segment (qtdemux, stream, seg_idx, offset,
5088           &start, &stop))
5089     return FALSE;
5090
5091   segment = &stream->segments[stream->segment_index];
5092
5093   /* in the fragmented case, we pick a fragment that starts before our
5094    * desired position and rely on downstream to wait for a keyframe
5095    * (FIXME: doesn't seem to work so well with ismv and wmv, as no parser; the
5096    * tfra entries tells us which trun/sample the key unit is in, but we don't
5097    * make use of this additional information at the moment) */
5098   if (qtdemux->fragmented && !qtdemux->fragmented_seek_pending) {
5099     stream->to_sample = G_MAXUINT32;
5100     return TRUE;
5101   } else {
5102     /* well, it will be taken care of below */
5103     qtdemux->fragmented_seek_pending = FALSE;
5104     /* FIXME ideally the do_fragmented_seek can be done right here,
5105      * rather than at loop level
5106      * (which might even allow handling edit lists in a fragmented file) */
5107   }
5108
5109   /* We don't need to look for a sample in push-based */
5110   if (!qtdemux->pullbased)
5111     return TRUE;
5112
5113   /* and move to the keyframe before the indicated media time of the
5114    * segment */
5115   if (G_LIKELY (!QTSEGMENT_IS_EMPTY (segment))) {
5116     if (qtdemux->segment.rate >= 0) {
5117       index = gst_qtdemux_find_index_linear (qtdemux, stream, start);
5118       stream->to_sample = G_MAXUINT32;
5119       GST_DEBUG_OBJECT (stream->pad,
5120           "moving data pointer to %" GST_TIME_FORMAT ", index: %u, pts %"
5121           GST_TIME_FORMAT, GST_TIME_ARGS (start), index,
5122           GST_TIME_ARGS (QTSAMPLE_PTS (stream, &stream->samples[index])));
5123     } else {
5124       index = gst_qtdemux_find_index_linear (qtdemux, stream, stop);
5125       stream->to_sample = index;
5126       GST_DEBUG_OBJECT (stream->pad,
5127           "moving data pointer to %" GST_TIME_FORMAT ", index: %u, pts %"
5128           GST_TIME_FORMAT, GST_TIME_ARGS (stop), index,
5129           GST_TIME_ARGS (QTSAMPLE_PTS (stream, &stream->samples[index])));
5130     }
5131   } else {
5132     GST_DEBUG_OBJECT (stream->pad, "No need to look for keyframe, "
5133         "this is an empty segment");
5134     return TRUE;
5135   }
5136
5137   /* gst_qtdemux_parse_sample () called from gst_qtdemux_find_index_linear ()
5138    * encountered an error and printed a message so we return appropriately */
5139   if (index == -1)
5140     return FALSE;
5141
5142   /* we're at the right spot */
5143   if (index == stream->sample_index) {
5144     GST_DEBUG_OBJECT (stream->pad, "we are at the right index");
5145     return TRUE;
5146   }
5147
5148   /* find keyframe of the target index */
5149   kf_index = gst_qtdemux_find_keyframe (qtdemux, stream, index, FALSE);
5150
5151 /* *INDENT-OFF* */
5152 /* indent does stupid stuff with stream->samples[].timestamp */
5153
5154   /* if we move forwards, we don't have to go back to the previous
5155    * keyframe since we already sent that. We can also just jump to
5156    * the keyframe right before the target index if there is one. */
5157   if (index > stream->sample_index) {
5158     /* moving forwards check if we move past a keyframe */
5159     if (kf_index > stream->sample_index) {
5160       GST_DEBUG_OBJECT (stream->pad,
5161            "moving forwards to keyframe at %u (pts %" GST_TIME_FORMAT " dts %"GST_TIME_FORMAT" )", kf_index,
5162            GST_TIME_ARGS (QTSAMPLE_PTS(stream, &stream->samples[kf_index])),
5163            GST_TIME_ARGS (QTSAMPLE_DTS(stream, &stream->samples[kf_index])));
5164       gst_qtdemux_move_stream (qtdemux, stream, kf_index);
5165     } else {
5166       GST_DEBUG_OBJECT (stream->pad,
5167           "moving forwards, keyframe at %u (pts %" GST_TIME_FORMAT " dts %"GST_TIME_FORMAT" ) already sent", kf_index,
5168           GST_TIME_ARGS (QTSAMPLE_PTS (stream, &stream->samples[kf_index])),
5169           GST_TIME_ARGS (QTSAMPLE_DTS (stream, &stream->samples[kf_index])));
5170     }
5171   } else {
5172     GST_DEBUG_OBJECT (stream->pad,
5173         "moving backwards to keyframe at %u (pts %" GST_TIME_FORMAT " dts %"GST_TIME_FORMAT" )", kf_index,
5174         GST_TIME_ARGS (QTSAMPLE_PTS(stream, &stream->samples[kf_index])),
5175         GST_TIME_ARGS (QTSAMPLE_DTS(stream, &stream->samples[kf_index])));
5176     gst_qtdemux_move_stream (qtdemux, stream, kf_index);
5177   }
5178
5179 /* *INDENT-ON* */
5180
5181   return TRUE;
5182 }
5183
5184 /* prepare to get the current sample of @stream, getting essential values.
5185  *
5186  * This function will also prepare and send the segment when needed.
5187  *
5188  * Return FALSE if the stream is EOS.
5189  *
5190  * PULL-BASED
5191  */
5192 static gboolean
5193 gst_qtdemux_prepare_current_sample (GstQTDemux * qtdemux,
5194     QtDemuxStream * stream, gboolean * empty, guint64 * offset, guint * size,
5195     GstClockTime * dts, GstClockTime * pts, GstClockTime * duration,
5196     gboolean * keyframe)
5197 {
5198   QtDemuxSample *sample;
5199   GstClockTime time_position;
5200   guint32 seg_idx;
5201
5202   g_return_val_if_fail (stream != NULL, FALSE);
5203
5204   time_position = stream->time_position;
5205   if (G_UNLIKELY (time_position == GST_CLOCK_TIME_NONE))
5206     goto eos;
5207
5208   seg_idx = stream->segment_index;
5209   if (G_UNLIKELY (seg_idx == -1)) {
5210     /* find segment corresponding to time_position if we are looking
5211      * for a segment. */
5212     seg_idx = gst_qtdemux_find_segment (qtdemux, stream, time_position);
5213   }
5214
5215   /* different segment, activate it, sample_index will be set. */
5216   if (G_UNLIKELY (stream->segment_index != seg_idx))
5217     gst_qtdemux_activate_segment (qtdemux, stream, seg_idx, time_position);
5218
5219   if (G_UNLIKELY (QTSEGMENT_IS_EMPTY (&stream->
5220               segments[stream->segment_index]))) {
5221     QtDemuxSegment *seg = &stream->segments[stream->segment_index];
5222
5223     GST_LOG_OBJECT (qtdemux, "Empty segment activated,"
5224         " prepare empty sample");
5225
5226     *empty = TRUE;
5227     *pts = *dts = time_position;
5228     *duration = seg->duration - (time_position - seg->time);
5229
5230     return TRUE;
5231   }
5232
5233   *empty = FALSE;
5234
5235   if (stream->sample_index == -1)
5236     stream->sample_index = 0;
5237
5238   GST_LOG_OBJECT (qtdemux, "segment active, index = %u of %u",
5239       stream->sample_index, stream->n_samples);
5240
5241   if (G_UNLIKELY (stream->sample_index >= stream->n_samples)) {
5242     if (!qtdemux->fragmented)
5243       goto eos;
5244
5245     GST_INFO_OBJECT (qtdemux, "out of samples, trying to add more");
5246     do {
5247       GstFlowReturn flow;
5248
5249       GST_OBJECT_LOCK (qtdemux);
5250       flow = qtdemux_add_fragmented_samples (qtdemux);
5251       GST_OBJECT_UNLOCK (qtdemux);
5252
5253       if (flow != GST_FLOW_OK)
5254         goto eos;
5255     }
5256     while (stream->sample_index >= stream->n_samples);
5257   }
5258
5259   if (!qtdemux_parse_samples (qtdemux, stream, stream->sample_index)) {
5260     GST_LOG_OBJECT (qtdemux, "Parsing of index %u failed!",
5261         stream->sample_index);
5262     return FALSE;
5263   }
5264
5265   /* now get the info for the sample we're at */
5266   sample = &stream->samples[stream->sample_index];
5267
5268   *dts = QTSAMPLE_DTS (stream, sample);
5269   *pts = QTSAMPLE_PTS (stream, sample);
5270   *offset = sample->offset;
5271   *size = sample->size;
5272   *duration = QTSAMPLE_DUR_DTS (stream, sample, *dts);
5273   *keyframe = QTSAMPLE_KEYFRAME (stream, sample);
5274
5275   return TRUE;
5276
5277   /* special cases */
5278 eos:
5279   {
5280     stream->time_position = GST_CLOCK_TIME_NONE;
5281     return FALSE;
5282   }
5283 }
5284
5285 /* move to the next sample in @stream.
5286  *
5287  * Moves to the next segment when needed.
5288  */
5289 static void
5290 gst_qtdemux_advance_sample (GstQTDemux * qtdemux, QtDemuxStream * stream)
5291 {
5292   QtDemuxSample *sample;
5293   QtDemuxSegment *segment;
5294
5295   /* get current segment */
5296   segment = &stream->segments[stream->segment_index];
5297
5298   if (G_UNLIKELY (QTSEGMENT_IS_EMPTY (segment))) {
5299     GST_DEBUG_OBJECT (qtdemux, "Empty segment, no samples to advance");
5300     goto next_segment;
5301   }
5302
5303   if (G_UNLIKELY (stream->sample_index >= stream->to_sample)) {
5304     /* Mark the stream as EOS */
5305     GST_DEBUG_OBJECT (qtdemux,
5306         "reached max allowed sample %u, mark EOS", stream->to_sample);
5307     stream->time_position = GST_CLOCK_TIME_NONE;
5308     return;
5309   }
5310
5311   /* move to next sample */
5312   stream->sample_index++;
5313   stream->offset_in_sample = 0;
5314
5315   /* reached the last sample, we need the next segment */
5316   if (G_UNLIKELY (stream->sample_index >= stream->n_samples))
5317     goto next_segment;
5318
5319   if (!qtdemux_parse_samples (qtdemux, stream, stream->sample_index)) {
5320     GST_LOG_OBJECT (qtdemux, "Parsing of index %u failed!",
5321         stream->sample_index);
5322     return;
5323   }
5324
5325   /* get next sample */
5326   sample = &stream->samples[stream->sample_index];
5327
5328   /* see if we are past the segment */
5329   if (G_UNLIKELY (QTSAMPLE_DTS (stream, sample) >= segment->media_stop))
5330     goto next_segment;
5331
5332   if (QTSAMPLE_DTS (stream, sample) >= segment->media_start) {
5333     /* inside the segment, update time_position, looks very familiar to
5334      * GStreamer segments, doesn't it? */
5335     stream->time_position =
5336         QTSAMPLE_DTS (stream, sample) - segment->media_start + segment->time;
5337   } else {
5338     /* not yet in segment, time does not yet increment. This means
5339      * that we are still prerolling keyframes to the decoder so it can
5340      * decode the first sample of the segment. */
5341     stream->time_position = segment->time;
5342   }
5343   return;
5344
5345   /* move to the next segment */
5346 next_segment:
5347   {
5348     GST_DEBUG_OBJECT (qtdemux, "segment %d ended ", stream->segment_index);
5349
5350     if (stream->segment_index == stream->n_segments - 1) {
5351       /* are we at the end of the last segment, we're EOS */
5352       stream->time_position = GST_CLOCK_TIME_NONE;
5353     } else {
5354       /* else we're only at the end of the current segment */
5355       stream->time_position = segment->stop_time;
5356     }
5357     /* make sure we select a new segment */
5358
5359     /* accumulate previous segments */
5360     if (GST_CLOCK_TIME_IS_VALID (stream->segment.stop))
5361       stream->accumulated_base +=
5362           (stream->segment.stop -
5363           stream->segment.start) / ABS (stream->segment.rate);
5364
5365     stream->segment_index = -1;
5366   }
5367 }
5368
5369 static void
5370 gst_qtdemux_sync_streams (GstQTDemux * demux)
5371 {
5372   gint i;
5373
5374   if (QTDEMUX_N_STREAMS (demux) <= 1)
5375     return;
5376
5377   for (i = 0; i < QTDEMUX_N_STREAMS (demux); i++) {
5378     QtDemuxStream *stream;
5379     GstClockTime end_time;
5380
5381     stream = QTDEMUX_NTH_STREAM (demux, i);
5382
5383     if (!stream->pad)
5384       continue;
5385
5386     /* TODO advance time on subtitle streams here, if any some day */
5387
5388     /* some clips/trailers may have unbalanced streams at the end,
5389      * so send EOS on shorter stream to prevent stalling others */
5390
5391     /* do not mess with EOS if SEGMENT seeking */
5392     if (demux->segment.flags & GST_SEEK_FLAG_SEGMENT)
5393       continue;
5394
5395     if (demux->pullbased) {
5396       /* loop mode is sample time based */
5397       if (!STREAM_IS_EOS (stream))
5398         continue;
5399     } else {
5400       /* push mode is byte position based */
5401       if (stream->n_samples &&
5402           stream->samples[stream->n_samples - 1].offset >= demux->offset)
5403         continue;
5404     }
5405
5406     if (stream->sent_eos)
5407       continue;
5408
5409     /* only act if some gap */
5410     end_time = stream->segments[stream->n_segments - 1].stop_time;
5411     GST_LOG_OBJECT (demux, "current position: %" GST_TIME_FORMAT
5412         ", stream end: %" GST_TIME_FORMAT,
5413         GST_TIME_ARGS (demux->segment.position), GST_TIME_ARGS (end_time));
5414     if (GST_CLOCK_TIME_IS_VALID (end_time)
5415         && (end_time + 2 * GST_SECOND < demux->segment.position)) {
5416       GstEvent *event;
5417
5418       GST_DEBUG_OBJECT (demux, "sending EOS for stream %s",
5419           GST_PAD_NAME (stream->pad));
5420       stream->sent_eos = TRUE;
5421       event = gst_event_new_eos ();
5422       if (demux->segment_seqnum != GST_SEQNUM_INVALID)
5423         gst_event_set_seqnum (event, demux->segment_seqnum);
5424       gst_pad_push_event (stream->pad, event);
5425     }
5426   }
5427 }
5428
5429 /* EOS and NOT_LINKED need to be combined. This means that we return:
5430  *
5431  *  GST_FLOW_NOT_LINKED: when all pads NOT_LINKED.
5432  *  GST_FLOW_EOS: when all pads EOS or NOT_LINKED.
5433  */
5434 static GstFlowReturn
5435 gst_qtdemux_combine_flows (GstQTDemux * demux, QtDemuxStream * stream,
5436     GstFlowReturn ret)
5437 {
5438   GST_LOG_OBJECT (demux, "flow return: %s", gst_flow_get_name (ret));
5439
5440   if (stream->pad)
5441     ret = gst_flow_combiner_update_pad_flow (demux->flowcombiner, stream->pad,
5442         ret);
5443   else
5444     ret = gst_flow_combiner_update_flow (demux->flowcombiner, ret);
5445
5446   GST_LOG_OBJECT (demux, "combined flow return: %s", gst_flow_get_name (ret));
5447   return ret;
5448 }
5449
5450 /* the input buffer metadata must be writable. Returns NULL when the buffer is
5451  * completely clipped
5452  *
5453  * Should be used only with raw buffers */
5454 static GstBuffer *
5455 gst_qtdemux_clip_buffer (GstQTDemux * qtdemux, QtDemuxStream * stream,
5456     GstBuffer * buf)
5457 {
5458   guint64 start, stop, cstart, cstop, diff;
5459   GstClockTime pts, duration;
5460   gsize size, osize;
5461   gint num_rate, denom_rate;
5462   gint frame_size;
5463   gboolean clip_data;
5464   guint offset;
5465
5466   osize = size = gst_buffer_get_size (buf);
5467   offset = 0;
5468
5469   /* depending on the type, setup the clip parameters */
5470   if (stream->subtype == FOURCC_soun) {
5471     frame_size = CUR_STREAM (stream)->bytes_per_frame;
5472     num_rate = GST_SECOND;
5473     denom_rate = (gint) CUR_STREAM (stream)->rate;
5474     clip_data = TRUE;
5475   } else if (stream->subtype == FOURCC_vide) {
5476     frame_size = size;
5477     num_rate = CUR_STREAM (stream)->fps_n;
5478     denom_rate = CUR_STREAM (stream)->fps_d;
5479     clip_data = FALSE;
5480   } else
5481     goto wrong_type;
5482
5483   if (frame_size <= 0)
5484     goto bad_frame_size;
5485
5486   /* we can only clip if we have a valid pts */
5487   pts = GST_BUFFER_PTS (buf);
5488   if (G_UNLIKELY (!GST_CLOCK_TIME_IS_VALID (pts)))
5489     goto no_pts;
5490
5491   duration = GST_BUFFER_DURATION (buf);
5492
5493   if (G_UNLIKELY (!GST_CLOCK_TIME_IS_VALID (duration))) {
5494     duration =
5495         gst_util_uint64_scale_int (size / frame_size, num_rate, denom_rate);
5496   }
5497
5498   start = pts;
5499   stop = start + duration;
5500
5501   if (G_UNLIKELY (!gst_segment_clip (&stream->segment,
5502               GST_FORMAT_TIME, start, stop, &cstart, &cstop)))
5503     goto clipped;
5504
5505   /* see if some clipping happened */
5506   diff = cstart - start;
5507   if (diff > 0) {
5508     pts += diff;
5509     duration -= diff;
5510
5511     if (clip_data) {
5512       /* bring clipped time to samples and to bytes */
5513       diff = gst_util_uint64_scale_int (diff, denom_rate, num_rate);
5514       diff *= frame_size;
5515
5516       GST_DEBUG_OBJECT (qtdemux,
5517           "clipping start to %" GST_TIME_FORMAT " %"
5518           G_GUINT64_FORMAT " bytes", GST_TIME_ARGS (cstart), diff);
5519
5520       offset = diff;
5521       size -= diff;
5522     }
5523   }
5524   diff = stop - cstop;
5525   if (diff > 0) {
5526     duration -= diff;
5527
5528     if (clip_data) {
5529       /* bring clipped time to samples and then to bytes */
5530       diff = gst_util_uint64_scale_int (diff, denom_rate, num_rate);
5531       diff *= frame_size;
5532       GST_DEBUG_OBJECT (qtdemux,
5533           "clipping stop to %" GST_TIME_FORMAT " %" G_GUINT64_FORMAT
5534           " bytes", GST_TIME_ARGS (cstop), diff);
5535       size -= diff;
5536     }
5537   }
5538
5539   if (offset != 0 || size != osize)
5540     gst_buffer_resize (buf, offset, size);
5541
5542   GST_BUFFER_DTS (buf) = GST_CLOCK_TIME_NONE;
5543   GST_BUFFER_PTS (buf) = pts;
5544   GST_BUFFER_DURATION (buf) = duration;
5545
5546   return buf;
5547
5548   /* dropped buffer */
5549 wrong_type:
5550   {
5551     GST_DEBUG_OBJECT (qtdemux, "unknown stream type");
5552     return buf;
5553   }
5554 bad_frame_size:
5555   {
5556     GST_DEBUG_OBJECT (qtdemux, "bad frame size");
5557     return buf;
5558   }
5559 no_pts:
5560   {
5561     GST_DEBUG_OBJECT (qtdemux, "no pts on buffer");
5562     return buf;
5563   }
5564 clipped:
5565   {
5566     GST_DEBUG_OBJECT (qtdemux, "clipped buffer");
5567     gst_buffer_unref (buf);
5568     return NULL;
5569   }
5570 }
5571
5572 static GstBuffer *
5573 gst_qtdemux_align_buffer (GstQTDemux * demux,
5574     GstBuffer * buffer, gsize alignment)
5575 {
5576   GstMapInfo map;
5577
5578   gst_buffer_map (buffer, &map, GST_MAP_READ);
5579
5580   if (map.size < sizeof (guintptr)) {
5581     gst_buffer_unmap (buffer, &map);
5582     return buffer;
5583   }
5584
5585   if (((guintptr) map.data) & (alignment - 1)) {
5586     GstBuffer *new_buffer;
5587     GstAllocationParams params = { 0, alignment - 1, 0, 0, };
5588
5589     new_buffer = gst_buffer_new_allocate (NULL,
5590         gst_buffer_get_size (buffer), &params);
5591
5592     /* Copy data "by hand", so ensure alignment is kept: */
5593     gst_buffer_fill (new_buffer, 0, map.data, map.size);
5594
5595     gst_buffer_copy_into (new_buffer, buffer, GST_BUFFER_COPY_METADATA, 0, -1);
5596     GST_DEBUG_OBJECT (demux,
5597         "We want output aligned on %" G_GSIZE_FORMAT ", reallocated",
5598         alignment);
5599
5600     gst_buffer_unmap (buffer, &map);
5601     gst_buffer_unref (buffer);
5602
5603     return new_buffer;
5604   }
5605
5606   gst_buffer_unmap (buffer, &map);
5607   return buffer;
5608 }
5609
5610 static guint8 *
5611 convert_to_s334_1a (const guint8 * ccpair, guint8 ccpair_size, guint field,
5612     gsize * res)
5613 {
5614   guint8 *storage;
5615   gsize i;
5616
5617   /* We are converting from pairs to triplets */
5618   *res = ccpair_size / 2 * 3;
5619   storage = g_malloc (*res);
5620   for (i = 0; i * 2 < ccpair_size; i += 1) {
5621     /* FIXME: Use line offset 0 as we simply can't know here */
5622     if (field == 1)
5623       storage[i * 3] = 0x80 | 0x00;
5624     else
5625       storage[i * 3] = 0x00 | 0x00;
5626     storage[i * 3 + 1] = ccpair[i * 2];
5627     storage[i * 3 + 2] = ccpair[i * 2 + 1];
5628   }
5629
5630   return storage;
5631 }
5632
5633 static guint8 *
5634 extract_cc_from_data (QtDemuxStream * stream, const guint8 * data, gsize size,
5635     gsize * cclen)
5636 {
5637   guint8 *res = NULL;
5638   guint32 atom_length, fourcc;
5639   QtDemuxStreamStsdEntry *stsd_entry;
5640
5641   GST_MEMDUMP ("caption atom", data, size);
5642
5643   /* There might be multiple atoms */
5644
5645   *cclen = 0;
5646   if (size < 8)
5647     goto invalid_cdat;
5648   atom_length = QT_UINT32 (data);
5649   fourcc = QT_FOURCC (data + 4);
5650   if (G_UNLIKELY (atom_length > size || atom_length == 8))
5651     goto invalid_cdat;
5652
5653   GST_DEBUG_OBJECT (stream->pad, "here");
5654
5655   /* Check if we have somethig compatible */
5656   stsd_entry = CUR_STREAM (stream);
5657   switch (stsd_entry->fourcc) {
5658     case FOURCC_c608:{
5659       guint8 *cdat = NULL, *cdt2 = NULL;
5660       gsize cdat_size = 0, cdt2_size = 0;
5661       /* Should be cdat or cdt2 */
5662       if (fourcc != FOURCC_cdat && fourcc != FOURCC_cdt2) {
5663         GST_WARNING_OBJECT (stream->pad,
5664             "Unknown data atom (%" GST_FOURCC_FORMAT ") for CEA608",
5665             GST_FOURCC_ARGS (fourcc));
5666         goto invalid_cdat;
5667       }
5668
5669       /* Convert to S334-1 Annex A byte triplet */
5670       if (fourcc == FOURCC_cdat)
5671         cdat = convert_to_s334_1a (data + 8, atom_length - 8, 1, &cdat_size);
5672       else
5673         cdt2 = convert_to_s334_1a (data + 8, atom_length - 8, 2, &cdt2_size);
5674       GST_DEBUG_OBJECT (stream->pad, "size:%" G_GSIZE_FORMAT " atom_length:%u",
5675           size, atom_length);
5676
5677       /* Check for another atom ? */
5678       if (size > atom_length + 8) {
5679         guint32 new_atom_length = QT_UINT32 (data + atom_length);
5680         if (size >= atom_length + new_atom_length) {
5681           fourcc = QT_FOURCC (data + atom_length + 4);
5682           if (fourcc == FOURCC_cdat) {
5683             if (cdat == NULL)
5684               cdat =
5685                   convert_to_s334_1a (data + atom_length + 8,
5686                   new_atom_length - 8, 1, &cdat_size);
5687             else
5688               GST_WARNING_OBJECT (stream->pad,
5689                   "Got multiple [cdat] atoms in a c608 sample. This is unsupported for now. Please file a bug");
5690           } else {
5691             if (cdt2 == NULL)
5692               cdt2 =
5693                   convert_to_s334_1a (data + atom_length + 8,
5694                   new_atom_length - 8, 2, &cdt2_size);
5695             else
5696               GST_WARNING_OBJECT (stream->pad,
5697                   "Got multiple [cdt2] atoms in a c608 sample. This is unsupported for now. Please file a bug");
5698           }
5699         }
5700       }
5701
5702       *cclen = cdat_size + cdt2_size;
5703       res = g_malloc (*cclen);
5704       if (cdat_size)
5705         memcpy (res, cdat, cdat_size);
5706       if (cdt2_size)
5707         memcpy (res + cdat_size, cdt2, cdt2_size);
5708       g_free (cdat);
5709       g_free (cdt2);
5710     }
5711       break;
5712     case FOURCC_c708:
5713       if (fourcc != FOURCC_ccdp) {
5714         GST_WARNING_OBJECT (stream->pad,
5715             "Unknown data atom (%" GST_FOURCC_FORMAT ") for CEA708",
5716             GST_FOURCC_ARGS (fourcc));
5717         goto invalid_cdat;
5718       }
5719       *cclen = atom_length - 8;
5720       res = g_memdup (data + 8, *cclen);
5721       break;
5722     default:
5723       /* Keep this here in case other closed caption formats are added */
5724       g_assert_not_reached ();
5725       break;
5726   }
5727
5728   GST_MEMDUMP ("Output", res, *cclen);
5729   return res;
5730
5731   /* Errors */
5732 invalid_cdat:
5733   GST_WARNING ("[cdat] atom is too small or invalid");
5734   return NULL;
5735 }
5736
5737 /* the input buffer metadata must be writable,
5738  * but time/duration etc not yet set and need not be preserved */
5739 static GstBuffer *
5740 gst_qtdemux_process_buffer (GstQTDemux * qtdemux, QtDemuxStream * stream,
5741     GstBuffer * buf)
5742 {
5743   GstMapInfo map;
5744   guint nsize = 0;
5745   gchar *str;
5746
5747   /* not many cases for now */
5748   if (G_UNLIKELY (CUR_STREAM (stream)->fourcc == FOURCC_mp4s)) {
5749     /* send a one time dvd clut event */
5750     if (stream->pending_event && stream->pad)
5751       gst_pad_push_event (stream->pad, stream->pending_event);
5752     stream->pending_event = NULL;
5753   }
5754
5755   if (G_UNLIKELY (stream->subtype != FOURCC_text
5756           && stream->subtype != FOURCC_sbtl &&
5757           stream->subtype != FOURCC_subp && stream->subtype != FOURCC_clcp)) {
5758     return buf;
5759   }
5760
5761   gst_buffer_map (buf, &map, GST_MAP_READ);
5762
5763   /* empty buffer is sent to terminate previous subtitle */
5764   if (map.size <= 2) {
5765     gst_buffer_unmap (buf, &map);
5766     gst_buffer_unref (buf);
5767     return NULL;
5768   }
5769   if (stream->subtype == FOURCC_subp) {
5770     /* That's all the processing needed for subpictures */
5771     gst_buffer_unmap (buf, &map);
5772     return buf;
5773   }
5774
5775   if (stream->subtype == FOURCC_clcp) {
5776     guint8 *cc;
5777     gsize cclen = 0;
5778     /* For closed caption, we need to extract the information from the
5779      * [cdat],[cdt2] or [ccdp] atom */
5780     cc = extract_cc_from_data (stream, map.data, map.size, &cclen);
5781     gst_buffer_unmap (buf, &map);
5782     gst_buffer_unref (buf);
5783     if (cc) {
5784       buf = _gst_buffer_new_wrapped (cc, cclen, g_free);
5785     } else {
5786       /* Conversion failed or there's nothing */
5787       buf = NULL;
5788     }
5789     return buf;
5790   }
5791
5792   nsize = GST_READ_UINT16_BE (map.data);
5793   nsize = MIN (nsize, map.size - 2);
5794
5795   GST_LOG_OBJECT (qtdemux, "3GPP timed text subtitle: %d/%" G_GSIZE_FORMAT "",
5796       nsize, map.size);
5797
5798   /* takes care of UTF-8 validation or UTF-16 recognition,
5799    * no other encoding expected */
5800   str = gst_tag_freeform_string_to_utf8 ((gchar *) map.data + 2, nsize, NULL);
5801   gst_buffer_unmap (buf, &map);
5802   if (str) {
5803     gst_buffer_unref (buf);
5804     buf = _gst_buffer_new_wrapped (str, strlen (str), g_free);
5805   } else {
5806     /* this should not really happen unless the subtitle is corrupted */
5807     gst_buffer_unref (buf);
5808     buf = NULL;
5809   }
5810
5811   /* FIXME ? convert optional subsequent style info to markup */
5812
5813   return buf;
5814 }
5815
5816 static GstFlowReturn
5817 gst_qtdemux_push_buffer (GstQTDemux * qtdemux, QtDemuxStream * stream,
5818     GstBuffer * buf)
5819 {
5820   GstFlowReturn ret = GST_FLOW_OK;
5821   GstClockTime pts, duration;
5822
5823   if (stream->need_clip)
5824     buf = gst_qtdemux_clip_buffer (qtdemux, stream, buf);
5825
5826   if (G_UNLIKELY (buf == NULL))
5827     goto exit;
5828
5829   if (G_UNLIKELY (stream->discont)) {
5830     GST_LOG_OBJECT (qtdemux, "marking discont buffer");
5831     GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_DISCONT);
5832     stream->discont = FALSE;
5833   } else {
5834     GST_BUFFER_FLAG_UNSET (buf, GST_BUFFER_FLAG_DISCONT);
5835   }
5836
5837   GST_LOG_OBJECT (qtdemux,
5838       "Pushing buffer with dts %" GST_TIME_FORMAT ", pts %" GST_TIME_FORMAT
5839       ", duration %" GST_TIME_FORMAT " on pad %s",
5840       GST_TIME_ARGS (GST_BUFFER_DTS (buf)),
5841       GST_TIME_ARGS (GST_BUFFER_PTS (buf)),
5842       GST_TIME_ARGS (GST_BUFFER_DURATION (buf)), GST_PAD_NAME (stream->pad));
5843
5844   if (stream->protected && stream->protection_scheme_type == FOURCC_cenc) {
5845     GstStructure *crypto_info;
5846     QtDemuxCencSampleSetInfo *info =
5847         (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
5848     gint index;
5849     GstEvent *event;
5850
5851     while ((event = g_queue_pop_head (&stream->protection_scheme_event_queue))) {
5852       GST_TRACE_OBJECT (stream->pad, "pushing protection event: %"
5853           GST_PTR_FORMAT, event);
5854       gst_pad_push_event (stream->pad, event);
5855     }
5856
5857     if (info->crypto_info == NULL) {
5858       GST_DEBUG_OBJECT (qtdemux,
5859           "cenc metadata hasn't been parsed yet, pushing buffer as if it wasn't encrypted");
5860     } else {
5861       /* The end of the crypto_info array matches our n_samples position,
5862        * so count backward from there */
5863       index = stream->sample_index - stream->n_samples + info->crypto_info->len;
5864       if (G_LIKELY (index >= 0 && index < info->crypto_info->len)) {
5865         /* steal structure from array */
5866         crypto_info = g_ptr_array_index (info->crypto_info, index);
5867         g_ptr_array_index (info->crypto_info, index) = NULL;
5868         GST_LOG_OBJECT (qtdemux, "attaching cenc metadata [%u/%u]", index,
5869             info->crypto_info->len);
5870         if (!crypto_info || !gst_buffer_add_protection_meta (buf, crypto_info))
5871           GST_ERROR_OBJECT (qtdemux,
5872               "failed to attach cenc metadata to buffer");
5873       } else {
5874         GST_INFO_OBJECT (qtdemux, "No crypto info with index %d and sample %d",
5875             index, stream->sample_index);
5876       }
5877     }
5878   }
5879
5880   if (stream->alignment > 1)
5881     buf = gst_qtdemux_align_buffer (qtdemux, buf, stream->alignment);
5882
5883   pts = GST_BUFFER_PTS (buf);
5884   duration = GST_BUFFER_DURATION (buf);
5885
5886   ret = gst_pad_push (stream->pad, buf);
5887
5888   if (GST_CLOCK_TIME_IS_VALID (pts) && GST_CLOCK_TIME_IS_VALID (duration)) {
5889     /* mark position in stream, we'll need this to know when to send GAP event */
5890     stream->segment.position = pts + duration;
5891   }
5892
5893 exit:
5894
5895   return ret;
5896 }
5897
5898 static GstFlowReturn
5899 gst_qtdemux_split_and_push_buffer (GstQTDemux * qtdemux, QtDemuxStream * stream,
5900     GstBuffer * buf)
5901 {
5902   GstFlowReturn ret = GST_FLOW_OK;
5903
5904   if (stream->subtype == FOURCC_clcp
5905       && CUR_STREAM (stream)->fourcc == FOURCC_c608 && stream->need_split) {
5906     GstMapInfo map;
5907     guint n_output_buffers, n_field1 = 0, n_field2 = 0;
5908     guint n_triplets, i;
5909     guint field1_off = 0, field2_off = 0;
5910
5911     /* We have to split CEA608 buffers so that each outgoing buffer contains
5912      * one byte pair per field according to the framerate of the video track.
5913      *
5914      * If there is only a single byte pair per field we don't have to do
5915      * anything
5916      */
5917
5918     gst_buffer_map (buf, &map, GST_MAP_READ);
5919
5920     n_triplets = map.size / 3;
5921     for (i = 0; i < n_triplets; i++) {
5922       if (map.data[3 * i] & 0x80)
5923         n_field1++;
5924       else
5925         n_field2++;
5926     }
5927
5928     g_assert (n_field1 || n_field2);
5929
5930     /* If there's more than 1 frame we have to split, otherwise we can just
5931      * pass through */
5932     if (n_field1 > 1 || n_field2 > 1) {
5933       n_output_buffers =
5934           gst_util_uint64_scale (GST_BUFFER_DURATION (buf),
5935           CUR_STREAM (stream)->fps_n, GST_SECOND * CUR_STREAM (stream)->fps_d);
5936
5937       for (i = 0; i < n_output_buffers; i++) {
5938         GstBuffer *outbuf =
5939             gst_buffer_new_and_alloc ((n_field1 ? 3 : 0) + (n_field2 ? 3 : 0));
5940         GstMapInfo outmap;
5941         guint8 *outptr;
5942
5943         gst_buffer_map (outbuf, &outmap, GST_MAP_WRITE);
5944         outptr = outmap.data;
5945
5946         if (n_field1) {
5947           gboolean found = FALSE;
5948
5949           while (map.data + field1_off < map.data + map.size) {
5950             if (map.data[field1_off] & 0x80) {
5951               memcpy (outptr, &map.data[field1_off], 3);
5952               field1_off += 3;
5953               found = TRUE;
5954               break;
5955             }
5956             field1_off += 3;
5957           }
5958
5959           if (!found) {
5960             const guint8 empty[] = { 0x80, 0x80, 0x80 };
5961
5962             memcpy (outptr, empty, 3);
5963           }
5964
5965           outptr += 3;
5966         }
5967
5968         if (n_field2) {
5969           gboolean found = FALSE;
5970
5971           while (map.data + field2_off < map.data + map.size) {
5972             if ((map.data[field2_off] & 0x80) == 0) {
5973               memcpy (outptr, &map.data[field2_off], 3);
5974               field2_off += 3;
5975               found = TRUE;
5976               break;
5977             }
5978             field2_off += 3;
5979           }
5980
5981           if (!found) {
5982             const guint8 empty[] = { 0x00, 0x80, 0x80 };
5983
5984             memcpy (outptr, empty, 3);
5985           }
5986
5987           outptr += 3;
5988         }
5989
5990         gst_buffer_unmap (outbuf, &outmap);
5991
5992         GST_BUFFER_PTS (outbuf) =
5993             GST_BUFFER_PTS (buf) + gst_util_uint64_scale (i,
5994             GST_SECOND * CUR_STREAM (stream)->fps_d,
5995             CUR_STREAM (stream)->fps_n);
5996         GST_BUFFER_DURATION (outbuf) =
5997             gst_util_uint64_scale (GST_SECOND, CUR_STREAM (stream)->fps_d,
5998             CUR_STREAM (stream)->fps_n);
5999         GST_BUFFER_OFFSET (outbuf) = -1;
6000         GST_BUFFER_OFFSET_END (outbuf) = -1;
6001
6002         ret = gst_qtdemux_push_buffer (qtdemux, stream, outbuf);
6003
6004         if (ret != GST_FLOW_OK && ret != GST_FLOW_NOT_LINKED)
6005           break;
6006       }
6007       gst_buffer_unmap (buf, &map);
6008       gst_buffer_unref (buf);
6009     } else {
6010       gst_buffer_unmap (buf, &map);
6011       ret = gst_qtdemux_push_buffer (qtdemux, stream, buf);
6012     }
6013   } else {
6014     ret = gst_qtdemux_push_buffer (qtdemux, stream, buf);
6015   }
6016
6017   return ret;
6018 }
6019
6020 /* Sets a buffer's attributes properly and pushes it downstream.
6021  * Also checks for additional actions and custom processing that may
6022  * need to be done first.
6023  */
6024 static GstFlowReturn
6025 gst_qtdemux_decorate_and_push_buffer (GstQTDemux * qtdemux,
6026     QtDemuxStream * stream, GstBuffer * buf,
6027     GstClockTime dts, GstClockTime pts, GstClockTime duration,
6028     gboolean keyframe, GstClockTime position, guint64 byte_position)
6029 {
6030   GstFlowReturn ret = GST_FLOW_OK;
6031
6032   /* offset the timestamps according to the edit list */
6033
6034   if (G_UNLIKELY (CUR_STREAM (stream)->fourcc == FOURCC_rtsp)) {
6035     gchar *url;
6036     GstMapInfo map;
6037
6038     gst_buffer_map (buf, &map, GST_MAP_READ);
6039     url = g_strndup ((gchar *) map.data, map.size);
6040     gst_buffer_unmap (buf, &map);
6041     if (url != NULL && strlen (url) != 0) {
6042       /* we have RTSP redirect now */
6043       gst_element_post_message (GST_ELEMENT_CAST (qtdemux),
6044           gst_message_new_element (GST_OBJECT_CAST (qtdemux),
6045               gst_structure_new ("redirect",
6046                   "new-location", G_TYPE_STRING, url, NULL)));
6047       qtdemux->posted_redirect = TRUE;
6048     } else {
6049       GST_WARNING_OBJECT (qtdemux, "Redirect URI of stream is empty, not "
6050           "posting");
6051     }
6052     g_free (url);
6053   }
6054
6055   /* position reporting */
6056   if (qtdemux->segment.rate >= 0) {
6057     qtdemux->segment.position = position;
6058     gst_qtdemux_sync_streams (qtdemux);
6059   }
6060
6061   if (G_UNLIKELY (!stream->pad)) {
6062     GST_DEBUG_OBJECT (qtdemux, "No output pad for stream, ignoring");
6063     gst_buffer_unref (buf);
6064     goto exit;
6065   }
6066
6067   /* send out pending buffers */
6068   while (stream->buffers) {
6069     GstBuffer *buffer = (GstBuffer *) stream->buffers->data;
6070
6071     if (G_UNLIKELY (stream->discont)) {
6072       GST_LOG_OBJECT (qtdemux, "marking discont buffer");
6073       GST_BUFFER_FLAG_SET (buffer, GST_BUFFER_FLAG_DISCONT);
6074       stream->discont = FALSE;
6075     } else {
6076       GST_BUFFER_FLAG_UNSET (buf, GST_BUFFER_FLAG_DISCONT);
6077     }
6078
6079     if (stream->alignment > 1)
6080       buffer = gst_qtdemux_align_buffer (qtdemux, buffer, stream->alignment);
6081     gst_pad_push (stream->pad, buffer);
6082
6083     stream->buffers = g_slist_delete_link (stream->buffers, stream->buffers);
6084   }
6085
6086   /* we're going to modify the metadata */
6087   buf = gst_buffer_make_writable (buf);
6088
6089   if (G_UNLIKELY (stream->need_process))
6090     buf = gst_qtdemux_process_buffer (qtdemux, stream, buf);
6091
6092   if (!buf) {
6093     goto exit;
6094   }
6095
6096   GST_BUFFER_DTS (buf) = dts;
6097   GST_BUFFER_PTS (buf) = pts;
6098   GST_BUFFER_DURATION (buf) = duration;
6099   GST_BUFFER_OFFSET (buf) = -1;
6100   GST_BUFFER_OFFSET_END (buf) = -1;
6101
6102   if (!keyframe) {
6103     GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_DELTA_UNIT);
6104     stream->on_keyframe = FALSE;
6105   } else {
6106     stream->on_keyframe = TRUE;
6107   }
6108
6109   if (G_UNLIKELY (CUR_STREAM (stream)->rgb8_palette))
6110     gst_buffer_append_memory (buf,
6111         gst_memory_ref (CUR_STREAM (stream)->rgb8_palette));
6112
6113   if (G_UNLIKELY (CUR_STREAM (stream)->padding)) {
6114     gst_buffer_resize (buf, CUR_STREAM (stream)->padding, -1);
6115   }
6116 #if 0
6117   if (G_UNLIKELY (qtdemux->element_index)) {
6118     GstClockTime stream_time;
6119
6120     stream_time =
6121         gst_segment_to_stream_time (&stream->segment, GST_FORMAT_TIME,
6122         timestamp);
6123     if (GST_CLOCK_TIME_IS_VALID (stream_time)) {
6124       GST_LOG_OBJECT (qtdemux,
6125           "adding association %" GST_TIME_FORMAT "-> %"
6126           G_GUINT64_FORMAT, GST_TIME_ARGS (stream_time), byte_position);
6127       gst_index_add_association (qtdemux->element_index,
6128           qtdemux->index_id,
6129           keyframe ? GST_ASSOCIATION_FLAG_KEY_UNIT :
6130           GST_ASSOCIATION_FLAG_DELTA_UNIT, GST_FORMAT_TIME, stream_time,
6131           GST_FORMAT_BYTES, byte_position, NULL);
6132     }
6133   }
6134 #endif
6135
6136   ret = gst_qtdemux_split_and_push_buffer (qtdemux, stream, buf);
6137
6138 exit:
6139   return ret;
6140 }
6141
6142 static const QtDemuxRandomAccessEntry *
6143 gst_qtdemux_stream_seek_fragment (GstQTDemux * qtdemux, QtDemuxStream * stream,
6144     GstClockTime pos, gboolean after)
6145 {
6146   QtDemuxRandomAccessEntry *entries = stream->ra_entries;
6147   guint n_entries = stream->n_ra_entries;
6148   guint i;
6149
6150   /* we assume the table is sorted */
6151   for (i = 0; i < n_entries; ++i) {
6152     if (entries[i].ts > pos)
6153       break;
6154   }
6155
6156   /* FIXME: maybe save first moof_offset somewhere instead, but for now it's
6157    * probably okay to assume that the index lists the very first fragment */
6158   if (i == 0)
6159     return &entries[0];
6160
6161   if (after)
6162     return &entries[i];
6163   else
6164     return &entries[i - 1];
6165 }
6166
6167 static gboolean
6168 gst_qtdemux_do_fragmented_seek (GstQTDemux * qtdemux)
6169 {
6170   const QtDemuxRandomAccessEntry *best_entry = NULL;
6171   gint i;
6172
6173   GST_OBJECT_LOCK (qtdemux);
6174
6175   g_assert (QTDEMUX_N_STREAMS (qtdemux) > 0);
6176
6177   /* first see if we can determine where to go to using mfra,
6178    * before we start clearing things */
6179   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
6180     const QtDemuxRandomAccessEntry *entry;
6181     QtDemuxStream *stream;
6182     gboolean is_audio_or_video;
6183
6184     stream = QTDEMUX_NTH_STREAM (qtdemux, i);
6185
6186     if (stream->ra_entries == NULL)
6187       continue;
6188
6189     if (stream->subtype == FOURCC_vide || stream->subtype == FOURCC_soun)
6190       is_audio_or_video = TRUE;
6191     else
6192       is_audio_or_video = FALSE;
6193
6194     entry =
6195         gst_qtdemux_stream_seek_fragment (qtdemux, stream,
6196         stream->time_position, !is_audio_or_video);
6197
6198     GST_INFO_OBJECT (stream->pad, "%" GST_TIME_FORMAT " at offset "
6199         "%" G_GUINT64_FORMAT, GST_TIME_ARGS (entry->ts), entry->moof_offset);
6200
6201     stream->pending_seek = entry;
6202
6203     /* decide position to jump to just based on audio/video tracks, not subs */
6204     if (!is_audio_or_video)
6205       continue;
6206
6207     if (best_entry == NULL || entry->moof_offset < best_entry->moof_offset)
6208       best_entry = entry;
6209   }
6210
6211   /* no luck, will handle seek otherwise */
6212   if (best_entry == NULL) {
6213     GST_OBJECT_UNLOCK (qtdemux);
6214     return FALSE;
6215   }
6216
6217   /* ok, now we can prepare for processing as of located moof */
6218   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
6219     QtDemuxStream *stream;
6220
6221     stream = QTDEMUX_NTH_STREAM (qtdemux, i);
6222
6223     g_free (stream->samples);
6224     stream->samples = NULL;
6225     stream->n_samples = 0;
6226     stream->stbl_index = -1;    /* no samples have yet been parsed */
6227     stream->sample_index = -1;
6228
6229     if (stream->protection_scheme_info) {
6230       /* Clear out any old cenc crypto info entries as we'll move to a new moof */
6231       if (stream->protection_scheme_type == FOURCC_cenc) {
6232         QtDemuxCencSampleSetInfo *info =
6233             (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
6234         if (info->crypto_info) {
6235           g_ptr_array_free (info->crypto_info, TRUE);
6236           info->crypto_info = NULL;
6237         }
6238       }
6239     }
6240   }
6241
6242   GST_INFO_OBJECT (qtdemux, "seek to %" GST_TIME_FORMAT ", best fragment "
6243       "moof offset: %" G_GUINT64_FORMAT ", ts %" GST_TIME_FORMAT,
6244       GST_TIME_ARGS (QTDEMUX_NTH_STREAM (qtdemux, 0)->time_position),
6245       best_entry->moof_offset, GST_TIME_ARGS (best_entry->ts));
6246
6247   qtdemux->moof_offset = best_entry->moof_offset;
6248
6249   qtdemux_add_fragmented_samples (qtdemux);
6250
6251   GST_OBJECT_UNLOCK (qtdemux);
6252   return TRUE;
6253 }
6254
6255 static GstFlowReturn
6256 gst_qtdemux_loop_state_movie (GstQTDemux * qtdemux)
6257 {
6258   GstFlowReturn ret = GST_FLOW_OK;
6259   GstBuffer *buf = NULL;
6260   QtDemuxStream *stream, *target_stream = NULL;
6261   GstClockTime min_time;
6262   guint64 offset = 0;
6263   GstClockTime dts = GST_CLOCK_TIME_NONE;
6264   GstClockTime pts = GST_CLOCK_TIME_NONE;
6265   GstClockTime duration = 0;
6266   gboolean keyframe = FALSE;
6267   guint sample_size = 0;
6268   gboolean empty = 0;
6269   guint size;
6270   gint i;
6271
6272   if (qtdemux->fragmented_seek_pending) {
6273     GST_INFO_OBJECT (qtdemux, "pending fragmented seek");
6274     if (gst_qtdemux_do_fragmented_seek (qtdemux)) {
6275       GST_INFO_OBJECT (qtdemux, "fragmented seek done!");
6276       qtdemux->fragmented_seek_pending = FALSE;
6277     } else {
6278       GST_INFO_OBJECT (qtdemux, "fragmented seek still pending");
6279     }
6280   }
6281
6282   /* Figure out the next stream sample to output, min_time is expressed in
6283    * global time and runs over the edit list segments. */
6284   min_time = G_MAXUINT64;
6285   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
6286     GstClockTime position;
6287
6288     stream = QTDEMUX_NTH_STREAM (qtdemux, i);
6289     position = stream->time_position;
6290
6291     /* position of -1 is EOS */
6292     if (position != GST_CLOCK_TIME_NONE && position < min_time) {
6293       min_time = position;
6294       target_stream = stream;
6295     }
6296   }
6297   /* all are EOS */
6298   if (G_UNLIKELY (target_stream == NULL)) {
6299     GST_DEBUG_OBJECT (qtdemux, "all streams are EOS");
6300     goto eos;
6301   }
6302
6303   /* check for segment end */
6304   if (G_UNLIKELY (qtdemux->segment.stop != -1
6305           && ((qtdemux->segment.rate >= 0 && qtdemux->segment.stop <= min_time)
6306               || (qtdemux->segment.rate < 0
6307                   && qtdemux->segment.start > min_time))
6308           && target_stream->on_keyframe)) {
6309     GST_DEBUG_OBJECT (qtdemux, "we reached the end of our segment.");
6310     target_stream->time_position = GST_CLOCK_TIME_NONE;
6311     goto eos_stream;
6312   }
6313
6314   /* gap events for subtitle streams */
6315   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
6316     stream = QTDEMUX_NTH_STREAM (qtdemux, i);
6317     if (stream->pad && (stream->subtype == FOURCC_subp
6318             || stream->subtype == FOURCC_text
6319             || stream->subtype == FOURCC_sbtl)) {
6320       /* send one second gap events until the stream catches up */
6321       /* gaps can only be sent after segment is activated (segment.stop is no longer -1) */
6322       while (GST_CLOCK_TIME_IS_VALID (stream->segment.stop) &&
6323           GST_CLOCK_TIME_IS_VALID (stream->segment.position) &&
6324           stream->segment.position + GST_SECOND < min_time) {
6325         GstEvent *gap =
6326             gst_event_new_gap (stream->segment.position, GST_SECOND);
6327         gst_pad_push_event (stream->pad, gap);
6328         stream->segment.position += GST_SECOND;
6329       }
6330     }
6331   }
6332
6333   stream = target_stream;
6334   /* fetch info for the current sample of this stream */
6335   if (G_UNLIKELY (!gst_qtdemux_prepare_current_sample (qtdemux, stream, &empty,
6336               &offset, &sample_size, &dts, &pts, &duration, &keyframe)))
6337     goto eos_stream;
6338
6339   gst_qtdemux_stream_check_and_change_stsd_index (qtdemux, stream);
6340   if (stream->new_caps) {
6341     gst_qtdemux_configure_stream (qtdemux, stream);
6342     qtdemux_do_allocation (stream, qtdemux);
6343   }
6344
6345   /* If we're doing a keyframe-only trickmode, only push keyframes on video streams */
6346   if (G_UNLIKELY (qtdemux->segment.
6347           flags & GST_SEGMENT_FLAG_TRICKMODE_KEY_UNITS)) {
6348     if (stream->subtype == FOURCC_vide && !keyframe) {
6349       GST_LOG_OBJECT (qtdemux, "Skipping non-keyframe on track-id %u",
6350           stream->track_id);
6351       goto next;
6352     }
6353   }
6354
6355   GST_DEBUG_OBJECT (qtdemux,
6356       "pushing from track-id %u, empty %d offset %" G_GUINT64_FORMAT
6357       ", size %d, dts=%" GST_TIME_FORMAT ", pts=%" GST_TIME_FORMAT
6358       ", duration %" GST_TIME_FORMAT, stream->track_id, empty, offset,
6359       sample_size, GST_TIME_ARGS (dts), GST_TIME_ARGS (pts),
6360       GST_TIME_ARGS (duration));
6361
6362   if (G_UNLIKELY (empty)) {
6363     /* empty segment, push a gap if there's a second or more
6364      * difference and move to the next one */
6365     if ((pts + duration - stream->segment.position) >= GST_SECOND)
6366       gst_pad_push_event (stream->pad, gst_event_new_gap (pts, duration));
6367     stream->segment.position = pts + duration;
6368     goto next;
6369   }
6370
6371   /* hmm, empty sample, skip and move to next sample */
6372   if (G_UNLIKELY (sample_size <= 0))
6373     goto next;
6374
6375   /* last pushed sample was out of boundary, goto next sample */
6376   if (G_UNLIKELY (GST_PAD_LAST_FLOW_RETURN (stream->pad) == GST_FLOW_EOS))
6377     goto next;
6378
6379   if (stream->max_buffer_size == 0 || sample_size <= stream->max_buffer_size) {
6380     size = sample_size;
6381   } else {
6382     GST_DEBUG_OBJECT (qtdemux,
6383         "size %d larger than stream max_buffer_size %d, trimming",
6384         sample_size, stream->max_buffer_size);
6385     size =
6386         MIN (sample_size - stream->offset_in_sample, stream->max_buffer_size);
6387   }
6388
6389   if (qtdemux->cenc_aux_info_offset > 0) {
6390     GstMapInfo map;
6391     GstByteReader br;
6392     GstBuffer *aux_info = NULL;
6393
6394     /* pull the data stored before the sample */
6395     ret =
6396         gst_qtdemux_pull_atom (qtdemux, qtdemux->offset,
6397         offset + stream->offset_in_sample - qtdemux->offset, &aux_info);
6398     if (G_UNLIKELY (ret != GST_FLOW_OK))
6399       goto beach;
6400     gst_buffer_map (aux_info, &map, GST_MAP_READ);
6401     GST_DEBUG_OBJECT (qtdemux, "parsing cenc auxiliary info");
6402     gst_byte_reader_init (&br, map.data + 8, map.size);
6403     if (!qtdemux_parse_cenc_aux_info (qtdemux, stream, &br,
6404             qtdemux->cenc_aux_info_sizes, qtdemux->cenc_aux_sample_count)) {
6405       GST_ERROR_OBJECT (qtdemux, "failed to parse cenc auxiliary info");
6406       gst_buffer_unmap (aux_info, &map);
6407       gst_buffer_unref (aux_info);
6408       ret = GST_FLOW_ERROR;
6409       goto beach;
6410     }
6411     gst_buffer_unmap (aux_info, &map);
6412     gst_buffer_unref (aux_info);
6413   }
6414
6415   GST_LOG_OBJECT (qtdemux, "reading %d bytes @ %" G_GUINT64_FORMAT, size,
6416       offset);
6417
6418   if (stream->use_allocator) {
6419     /* if we have a per-stream allocator, use it */
6420     buf = gst_buffer_new_allocate (stream->allocator, size, &stream->params);
6421   }
6422
6423   ret = gst_qtdemux_pull_atom (qtdemux, offset + stream->offset_in_sample,
6424       size, &buf);
6425   if (G_UNLIKELY (ret != GST_FLOW_OK))
6426     goto beach;
6427
6428   if (size != sample_size) {
6429     pts += gst_util_uint64_scale_int (GST_SECOND,
6430         stream->offset_in_sample / CUR_STREAM (stream)->bytes_per_frame,
6431         stream->timescale);
6432     dts +=
6433         gst_util_uint64_scale_int (GST_SECOND,
6434         stream->offset_in_sample / CUR_STREAM (stream)->bytes_per_frame,
6435         stream->timescale);
6436     duration =
6437         gst_util_uint64_scale_int (GST_SECOND,
6438         size / CUR_STREAM (stream)->bytes_per_frame, stream->timescale);
6439   }
6440
6441   ret = gst_qtdemux_decorate_and_push_buffer (qtdemux, stream, buf,
6442       dts, pts, duration, keyframe, min_time, offset);
6443
6444   if (size != sample_size) {
6445     QtDemuxSample *sample = &stream->samples[stream->sample_index];
6446     QtDemuxSegment *segment = &stream->segments[stream->segment_index];
6447
6448     GstClockTime time_position = QTSTREAMTIME_TO_GSTTIME (stream,
6449         sample->timestamp +
6450         stream->offset_in_sample / CUR_STREAM (stream)->bytes_per_frame);
6451     if (time_position >= segment->media_start) {
6452       /* inside the segment, update time_position, looks very familiar to
6453        * GStreamer segments, doesn't it? */
6454       stream->time_position = (time_position - segment->media_start) +
6455           segment->time;
6456     } else {
6457       /* not yet in segment, time does not yet increment. This means
6458        * that we are still prerolling keyframes to the decoder so it can
6459        * decode the first sample of the segment. */
6460       stream->time_position = segment->time;
6461     }
6462   }
6463
6464   /* combine flows */
6465   ret = gst_qtdemux_combine_flows (qtdemux, stream, ret);
6466   /* ignore unlinked, we will not push on the pad anymore and we will EOS when
6467    * we have no more data for the pad to push */
6468   if (ret == GST_FLOW_EOS)
6469     ret = GST_FLOW_OK;
6470
6471   stream->offset_in_sample += size;
6472   if (stream->offset_in_sample >= sample_size) {
6473     gst_qtdemux_advance_sample (qtdemux, stream);
6474   }
6475   goto beach;
6476
6477 next:
6478   gst_qtdemux_advance_sample (qtdemux, stream);
6479
6480 beach:
6481   return ret;
6482
6483   /* special cases */
6484 eos:
6485   {
6486     GST_DEBUG_OBJECT (qtdemux, "No samples left for any streams - EOS");
6487     ret = GST_FLOW_EOS;
6488     goto beach;
6489   }
6490 eos_stream:
6491   {
6492     GST_DEBUG_OBJECT (qtdemux, "No samples left for stream");
6493     /* EOS will be raised if all are EOS */
6494     ret = GST_FLOW_OK;
6495     goto beach;
6496   }
6497 }
6498
6499 static void
6500 gst_qtdemux_loop (GstPad * pad)
6501 {
6502   GstQTDemux *qtdemux;
6503   guint64 cur_offset;
6504   GstFlowReturn ret;
6505
6506   qtdemux = GST_QTDEMUX (gst_pad_get_parent (pad));
6507
6508   cur_offset = qtdemux->offset;
6509   GST_LOG_OBJECT (qtdemux, "loop at position %" G_GUINT64_FORMAT ", state %s",
6510       cur_offset, qt_demux_state_string (qtdemux->state));
6511
6512   switch (qtdemux->state) {
6513     case QTDEMUX_STATE_INITIAL:
6514     case QTDEMUX_STATE_HEADER:
6515       ret = gst_qtdemux_loop_state_header (qtdemux);
6516       break;
6517     case QTDEMUX_STATE_MOVIE:
6518       ret = gst_qtdemux_loop_state_movie (qtdemux);
6519       if (qtdemux->segment.rate < 0 && ret == GST_FLOW_EOS) {
6520         ret = gst_qtdemux_seek_to_previous_keyframe (qtdemux);
6521       }
6522       break;
6523     default:
6524       /* ouch */
6525       goto invalid_state;
6526   }
6527
6528   /* if something went wrong, pause */
6529   if (ret != GST_FLOW_OK)
6530     goto pause;
6531
6532 done:
6533   gst_object_unref (qtdemux);
6534   return;
6535
6536   /* ERRORS */
6537 invalid_state:
6538   {
6539     GST_ELEMENT_ERROR (qtdemux, STREAM, FAILED,
6540         (NULL), ("streaming stopped, invalid state"));
6541     gst_pad_pause_task (pad);
6542     gst_qtdemux_push_event (qtdemux, gst_event_new_eos ());
6543     goto done;
6544   }
6545 pause:
6546   {
6547     const gchar *reason = gst_flow_get_name (ret);
6548
6549     GST_LOG_OBJECT (qtdemux, "pausing task, reason %s", reason);
6550
6551     gst_pad_pause_task (pad);
6552
6553     /* fatal errors need special actions */
6554     /* check EOS */
6555     if (ret == GST_FLOW_EOS) {
6556       if (QTDEMUX_N_STREAMS (qtdemux) == 0) {
6557         /* we have no streams, post an error */
6558         gst_qtdemux_post_no_playable_stream_error (qtdemux);
6559       }
6560       if (qtdemux->segment.flags & GST_SEEK_FLAG_SEGMENT) {
6561         gint64 stop;
6562
6563         if ((stop = qtdemux->segment.stop) == -1)
6564           stop = qtdemux->segment.duration;
6565
6566         if (qtdemux->segment.rate >= 0) {
6567           GstMessage *message;
6568           GstEvent *event;
6569
6570           GST_LOG_OBJECT (qtdemux, "Sending segment done, at end of segment");
6571           message = gst_message_new_segment_done (GST_OBJECT_CAST (qtdemux),
6572               GST_FORMAT_TIME, stop);
6573           event = gst_event_new_segment_done (GST_FORMAT_TIME, stop);
6574           if (qtdemux->segment_seqnum != GST_SEQNUM_INVALID) {
6575             gst_message_set_seqnum (message, qtdemux->segment_seqnum);
6576             gst_event_set_seqnum (event, qtdemux->segment_seqnum);
6577           }
6578           gst_element_post_message (GST_ELEMENT_CAST (qtdemux), message);
6579           gst_qtdemux_push_event (qtdemux, event);
6580         } else {
6581           GstMessage *message;
6582           GstEvent *event;
6583
6584           /*  For Reverse Playback */
6585           GST_LOG_OBJECT (qtdemux, "Sending segment done, at start of segment");
6586           message = gst_message_new_segment_done (GST_OBJECT_CAST (qtdemux),
6587               GST_FORMAT_TIME, qtdemux->segment.start);
6588           event = gst_event_new_segment_done (GST_FORMAT_TIME,
6589               qtdemux->segment.start);
6590           if (qtdemux->segment_seqnum != GST_SEQNUM_INVALID) {
6591             gst_message_set_seqnum (message, qtdemux->segment_seqnum);
6592             gst_event_set_seqnum (event, qtdemux->segment_seqnum);
6593           }
6594           gst_element_post_message (GST_ELEMENT_CAST (qtdemux), message);
6595           gst_qtdemux_push_event (qtdemux, event);
6596         }
6597       } else {
6598         GstEvent *event;
6599
6600         GST_LOG_OBJECT (qtdemux, "Sending EOS at end of segment");
6601         event = gst_event_new_eos ();
6602         if (qtdemux->segment_seqnum != GST_SEQNUM_INVALID)
6603           gst_event_set_seqnum (event, qtdemux->segment_seqnum);
6604         gst_qtdemux_push_event (qtdemux, event);
6605       }
6606     } else if (ret == GST_FLOW_NOT_LINKED || ret < GST_FLOW_EOS) {
6607       GST_ELEMENT_FLOW_ERROR (qtdemux, ret);
6608       gst_qtdemux_push_event (qtdemux, gst_event_new_eos ());
6609     }
6610     goto done;
6611   }
6612 }
6613
6614 /*
6615  * has_next_entry
6616  *
6617  * Returns if there are samples to be played.
6618  */
6619 static gboolean
6620 has_next_entry (GstQTDemux * demux)
6621 {
6622   QtDemuxStream *stream;
6623   gint i;
6624
6625   GST_DEBUG_OBJECT (demux, "Checking if there are samples not played yet");
6626
6627   for (i = 0; i < QTDEMUX_N_STREAMS (demux); i++) {
6628     stream = QTDEMUX_NTH_STREAM (demux, i);
6629
6630     if (stream->sample_index == -1) {
6631       stream->sample_index = 0;
6632       stream->offset_in_sample = 0;
6633     }
6634
6635     if (stream->sample_index >= stream->n_samples) {
6636       GST_LOG_OBJECT (demux, "track-id %u samples exhausted", stream->track_id);
6637       continue;
6638     }
6639     GST_DEBUG_OBJECT (demux, "Found a sample");
6640     return TRUE;
6641   }
6642
6643   GST_DEBUG_OBJECT (demux, "There wasn't any next sample");
6644   return FALSE;
6645 }
6646
6647 /*
6648  * next_entry_size
6649  *
6650  * Returns the size of the first entry at the current offset.
6651  * If -1, there are none (which means EOS or empty file).
6652  */
6653 static guint64
6654 next_entry_size (GstQTDemux * demux)
6655 {
6656   QtDemuxStream *stream, *target_stream = NULL;
6657   guint64 smalloffs = (guint64) - 1;
6658   QtDemuxSample *sample;
6659   gint i;
6660
6661   GST_LOG_OBJECT (demux, "Finding entry at offset %" G_GUINT64_FORMAT,
6662       demux->offset);
6663
6664   for (i = 0; i < QTDEMUX_N_STREAMS (demux); i++) {
6665     stream = QTDEMUX_NTH_STREAM (demux, i);
6666
6667     if (stream->sample_index == -1) {
6668       stream->sample_index = 0;
6669       stream->offset_in_sample = 0;
6670     }
6671
6672     if (stream->sample_index >= stream->n_samples) {
6673       GST_LOG_OBJECT (demux, "track-id %u samples exhausted", stream->track_id);
6674       continue;
6675     }
6676
6677     if (!qtdemux_parse_samples (demux, stream, stream->sample_index)) {
6678       GST_LOG_OBJECT (demux, "Parsing of index %u from stbl atom failed!",
6679           stream->sample_index);
6680       return -1;
6681     }
6682
6683     sample = &stream->samples[stream->sample_index];
6684
6685     GST_LOG_OBJECT (demux,
6686         "Checking track-id %u (sample_index:%d / offset:%" G_GUINT64_FORMAT
6687         " / size:%" G_GUINT32_FORMAT ")", stream->track_id,
6688         stream->sample_index, sample->offset, sample->size);
6689
6690     if (((smalloffs == -1)
6691             || (sample->offset < smalloffs)) && (sample->size)) {
6692       smalloffs = sample->offset;
6693       target_stream = stream;
6694     }
6695   }
6696
6697   if (!target_stream)
6698     return -1;
6699
6700   GST_LOG_OBJECT (demux,
6701       "track-id %u offset %" G_GUINT64_FORMAT " demux->offset :%"
6702       G_GUINT64_FORMAT, target_stream->track_id, smalloffs, demux->offset);
6703
6704   stream = target_stream;
6705   sample = &stream->samples[stream->sample_index];
6706
6707   if (sample->offset >= demux->offset) {
6708     demux->todrop = sample->offset - demux->offset;
6709     return sample->size + demux->todrop;
6710   }
6711
6712   GST_DEBUG_OBJECT (demux,
6713       "There wasn't any entry at offset %" G_GUINT64_FORMAT, demux->offset);
6714   return -1;
6715 }
6716
6717 static void
6718 gst_qtdemux_post_progress (GstQTDemux * demux, gint num, gint denom)
6719 {
6720   gint perc = (gint) ((gdouble) num * 100.0 / (gdouble) denom);
6721
6722   gst_element_post_message (GST_ELEMENT_CAST (demux),
6723       gst_message_new_element (GST_OBJECT_CAST (demux),
6724           gst_structure_new ("progress", "percent", G_TYPE_INT, perc, NULL)));
6725 }
6726
6727 static gboolean
6728 qtdemux_seek_offset (GstQTDemux * demux, guint64 offset)
6729 {
6730   GstEvent *event;
6731   gboolean res = 0;
6732
6733   GST_DEBUG_OBJECT (demux, "Seeking to %" G_GUINT64_FORMAT, offset);
6734
6735   event =
6736       gst_event_new_seek (1.0, GST_FORMAT_BYTES,
6737       GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_ACCURATE, GST_SEEK_TYPE_SET, offset,
6738       GST_SEEK_TYPE_NONE, -1);
6739
6740   /* store seqnum to drop flush events, they don't need to reach downstream */
6741   demux->offset_seek_seqnum = gst_event_get_seqnum (event);
6742   res = gst_pad_push_event (demux->sinkpad, event);
6743   demux->offset_seek_seqnum = GST_SEQNUM_INVALID;
6744
6745   return res;
6746 }
6747
6748 /* check for seekable upstream, above and beyond a mere query */
6749 static void
6750 gst_qtdemux_check_seekability (GstQTDemux * demux)
6751 {
6752   GstQuery *query;
6753   gboolean seekable = FALSE;
6754   gint64 start = -1, stop = -1;
6755
6756   if (demux->upstream_size)
6757     return;
6758
6759   if (demux->upstream_format_is_time)
6760     return;
6761
6762   query = gst_query_new_seeking (GST_FORMAT_BYTES);
6763   if (!gst_pad_peer_query (demux->sinkpad, query)) {
6764     GST_DEBUG_OBJECT (demux, "seeking query failed");
6765     goto done;
6766   }
6767
6768   gst_query_parse_seeking (query, NULL, &seekable, &start, &stop);
6769
6770   /* try harder to query upstream size if we didn't get it the first time */
6771   if (seekable && stop == -1) {
6772     GST_DEBUG_OBJECT (demux, "doing duration query to fix up unset stop");
6773     gst_pad_peer_query_duration (demux->sinkpad, GST_FORMAT_BYTES, &stop);
6774   }
6775
6776   /* if upstream doesn't know the size, it's likely that it's not seekable in
6777    * practice even if it technically may be seekable */
6778   if (seekable && (start != 0 || stop <= start)) {
6779     GST_DEBUG_OBJECT (demux, "seekable but unknown start/stop -> disable");
6780     seekable = FALSE;
6781   }
6782
6783 done:
6784   gst_query_unref (query);
6785
6786   GST_DEBUG_OBJECT (demux, "seekable: %d (%" G_GUINT64_FORMAT " - %"
6787       G_GUINT64_FORMAT ")", seekable, start, stop);
6788   demux->upstream_seekable = seekable;
6789   demux->upstream_size = seekable ? stop : -1;
6790 }
6791
6792 static void
6793 gst_qtdemux_drop_data (GstQTDemux * demux, gint bytes)
6794 {
6795   g_return_if_fail (bytes <= demux->todrop);
6796
6797   GST_LOG_OBJECT (demux, "Dropping %d bytes", bytes);
6798   gst_adapter_flush (demux->adapter, bytes);
6799   demux->neededbytes -= bytes;
6800   demux->offset += bytes;
6801   demux->todrop -= bytes;
6802 }
6803
6804 /* PUSH-MODE only: Send a segment, if not done already. */
6805 static void
6806 gst_qtdemux_check_send_pending_segment (GstQTDemux * demux)
6807 {
6808   if (G_UNLIKELY (demux->need_segment)) {
6809     gint i;
6810
6811     if (!demux->upstream_format_is_time) {
6812       gst_qtdemux_map_and_push_segments (demux, &demux->segment);
6813     } else {
6814       GstEvent *segment_event;
6815       segment_event = gst_event_new_segment (&demux->segment);
6816       if (demux->segment_seqnum != GST_SEQNUM_INVALID)
6817         gst_event_set_seqnum (segment_event, demux->segment_seqnum);
6818       gst_qtdemux_push_event (demux, segment_event);
6819     }
6820
6821     demux->need_segment = FALSE;
6822
6823     /* clear to send tags on all streams */
6824     for (i = 0; i < QTDEMUX_N_STREAMS (demux); i++) {
6825       QtDemuxStream *stream = QTDEMUX_NTH_STREAM (demux, i);
6826       gst_qtdemux_push_tags (demux, stream);
6827       if (CUR_STREAM (stream)->sparse) {
6828         GST_INFO_OBJECT (demux, "Sending gap event on stream %d", i);
6829         gst_pad_push_event (stream->pad,
6830             gst_event_new_gap (stream->segment.position, GST_CLOCK_TIME_NONE));
6831       }
6832     }
6833   }
6834 }
6835
6836 /* Used for push mode only. */
6837 static void
6838 gst_qtdemux_send_gap_for_segment (GstQTDemux * demux,
6839     QtDemuxStream * stream, gint segment_index, GstClockTime pos)
6840 {
6841   GstClockTime ts, dur;
6842
6843   ts = pos;
6844   dur =
6845       stream->segments[segment_index].duration - (pos -
6846       stream->segments[segment_index].time);
6847   stream->time_position += dur;
6848
6849   /* Only gaps with a duration of at least one second are propagated.
6850    * Same workaround as in pull mode.
6851    * (See 2e45926a96ec5298c6ef29bf912e5e6a06dc3e0e) */
6852   if (dur >= GST_SECOND) {
6853     GstEvent *gap;
6854     gap = gst_event_new_gap (ts, dur);
6855
6856     GST_DEBUG_OBJECT (stream->pad, "Pushing gap for empty "
6857         "segment: %" GST_PTR_FORMAT, gap);
6858     gst_pad_push_event (stream->pad, gap);
6859   }
6860 }
6861
6862 static GstFlowReturn
6863 gst_qtdemux_chain (GstPad * sinkpad, GstObject * parent, GstBuffer * inbuf)
6864 {
6865   GstQTDemux *demux;
6866
6867   demux = GST_QTDEMUX (parent);
6868
6869   GST_DEBUG_OBJECT (demux,
6870       "Received buffer pts:%" GST_TIME_FORMAT " dts:%" GST_TIME_FORMAT
6871       " offset:%" G_GUINT64_FORMAT " size:%" G_GSIZE_FORMAT " demux offset:%"
6872       G_GUINT64_FORMAT, GST_TIME_ARGS (GST_BUFFER_PTS (inbuf)),
6873       GST_TIME_ARGS (GST_BUFFER_DTS (inbuf)), GST_BUFFER_OFFSET (inbuf),
6874       gst_buffer_get_size (inbuf), demux->offset);
6875
6876   if (GST_BUFFER_FLAG_IS_SET (inbuf, GST_BUFFER_FLAG_DISCONT)) {
6877     gboolean is_gap_input = FALSE;
6878     gint i;
6879
6880     GST_DEBUG_OBJECT (demux, "Got DISCONT, marking all streams as DISCONT");
6881
6882     for (i = 0; i < QTDEMUX_N_STREAMS (demux); i++) {
6883       QTDEMUX_NTH_STREAM (demux, i)->discont = TRUE;
6884     }
6885
6886     /* Check if we can land back on our feet in the case where upstream is
6887      * handling the seeking/pushing of samples with gaps in between (like
6888      * in the case of trick-mode DASH for example) */
6889     if (demux->upstream_format_is_time
6890         && GST_BUFFER_OFFSET (inbuf) != GST_BUFFER_OFFSET_NONE) {
6891       for (i = 0; i < QTDEMUX_N_STREAMS (demux); i++) {
6892         guint32 res;
6893         QtDemuxStream *stream = QTDEMUX_NTH_STREAM (demux, i);
6894         GST_LOG_OBJECT (demux,
6895             "track-id #%u , checking if offset %" G_GUINT64_FORMAT
6896             " is a sample start", stream->track_id, GST_BUFFER_OFFSET (inbuf));
6897         res =
6898             gst_qtdemux_find_index_for_given_media_offset_linear (demux,
6899             stream, GST_BUFFER_OFFSET (inbuf));
6900         if (res != -1) {
6901           QtDemuxSample *sample = &stream->samples[res];
6902           GST_LOG_OBJECT (demux,
6903               "Checking if sample %d from track-id %u is valid (offset:%"
6904               G_GUINT64_FORMAT " size:%" G_GUINT32_FORMAT ")", res,
6905               stream->track_id, sample->offset, sample->size);
6906           if (sample->offset == GST_BUFFER_OFFSET (inbuf)) {
6907             GST_LOG_OBJECT (demux,
6908                 "new buffer corresponds to a valid sample : %" G_GUINT32_FORMAT,
6909                 res);
6910             is_gap_input = TRUE;
6911             /* We can go back to standard playback mode */
6912             demux->state = QTDEMUX_STATE_MOVIE;
6913             /* Remember which sample this stream is at */
6914             stream->sample_index = res;
6915             /* Finally update all push-based values to the expected values */
6916             demux->neededbytes = stream->samples[res].size;
6917             demux->offset = GST_BUFFER_OFFSET (inbuf);
6918             demux->mdatleft =
6919                 demux->mdatsize - demux->offset + demux->mdatoffset;
6920             demux->todrop = 0;
6921           }
6922         }
6923       }
6924       if (!is_gap_input) {
6925         GST_DEBUG_OBJECT (demux, "Resetting, actual DISCONT");
6926         /* Reset state if it's a real discont */
6927         demux->neededbytes = 16;
6928         demux->state = QTDEMUX_STATE_INITIAL;
6929         demux->offset = GST_BUFFER_OFFSET (inbuf);
6930         gst_adapter_clear (demux->adapter);
6931       }
6932     }
6933     /* Reverse fragmented playback, need to flush all we have before
6934      * consuming a new fragment.
6935      * The samples array have the timestamps calculated by accumulating the
6936      * durations but this won't work for reverse playback of fragments as
6937      * the timestamps of a subsequent fragment should be smaller than the
6938      * previously received one. */
6939     if (!is_gap_input && demux->fragmented && demux->segment.rate < 0) {
6940       gst_qtdemux_process_adapter (demux, TRUE);
6941       g_ptr_array_foreach (demux->active_streams,
6942           (GFunc) gst_qtdemux_stream_flush_samples_data, NULL);
6943     }
6944   }
6945
6946   gst_adapter_push (demux->adapter, inbuf);
6947
6948   GST_DEBUG_OBJECT (demux,
6949       "pushing in inbuf %p, neededbytes:%u, available:%" G_GSIZE_FORMAT, inbuf,
6950       demux->neededbytes, gst_adapter_available (demux->adapter));
6951
6952   return gst_qtdemux_process_adapter (demux, FALSE);
6953 }
6954
6955 static GstFlowReturn
6956 gst_qtdemux_process_adapter (GstQTDemux * demux, gboolean force)
6957 {
6958   GstFlowReturn ret = GST_FLOW_OK;
6959
6960   /* we never really mean to buffer that much */
6961   if (demux->neededbytes == -1) {
6962     goto eos;
6963   }
6964
6965   while (((gst_adapter_available (demux->adapter)) >= demux->neededbytes) &&
6966       (ret == GST_FLOW_OK || (ret == GST_FLOW_NOT_LINKED && force))) {
6967
6968 #ifndef GST_DISABLE_GST_DEBUG
6969     {
6970       guint64 discont_offset, distance_from_discont;
6971
6972       discont_offset = gst_adapter_offset_at_discont (demux->adapter);
6973       distance_from_discont =
6974           gst_adapter_distance_from_discont (demux->adapter);
6975
6976       GST_DEBUG_OBJECT (demux,
6977           "state:%s , demux->neededbytes:%d, demux->offset:%" G_GUINT64_FORMAT
6978           " adapter offset :%" G_GUINT64_FORMAT " (+ %" G_GUINT64_FORMAT
6979           " bytes)", qt_demux_state_string (demux->state), demux->neededbytes,
6980           demux->offset, discont_offset, distance_from_discont);
6981     }
6982 #endif
6983
6984     switch (demux->state) {
6985       case QTDEMUX_STATE_INITIAL:{
6986         const guint8 *data;
6987         guint32 fourcc;
6988         guint64 size;
6989
6990         gst_qtdemux_check_seekability (demux);
6991
6992         data = gst_adapter_map (demux->adapter, demux->neededbytes);
6993
6994         /* get fourcc/length, set neededbytes */
6995         extract_initial_length_and_fourcc ((guint8 *) data, demux->neededbytes,
6996             &size, &fourcc);
6997         gst_adapter_unmap (demux->adapter);
6998         data = NULL;
6999         GST_DEBUG_OBJECT (demux, "Peeking found [%" GST_FOURCC_FORMAT "] "
7000             "size: %" G_GUINT64_FORMAT, GST_FOURCC_ARGS (fourcc), size);
7001         if (size == 0) {
7002           GST_ELEMENT_ERROR (demux, STREAM, DEMUX,
7003               (_("This file is invalid and cannot be played.")),
7004               ("initial atom '%" GST_FOURCC_FORMAT "' has empty length",
7005                   GST_FOURCC_ARGS (fourcc)));
7006           ret = GST_FLOW_ERROR;
7007           break;
7008         }
7009         if (fourcc == FOURCC_mdat) {
7010           gint next_entry = next_entry_size (demux);
7011           if (QTDEMUX_N_STREAMS (demux) > 0 && (next_entry != -1
7012                   || !demux->fragmented)) {
7013             /* we have the headers, start playback */
7014             demux->state = QTDEMUX_STATE_MOVIE;
7015             demux->neededbytes = next_entry;
7016             demux->mdatleft = size;
7017             demux->mdatsize = demux->mdatleft;
7018           } else {
7019             /* no headers yet, try to get them */
7020             guint bs;
7021             gboolean res;
7022             guint64 old, target;
7023
7024           buffer_data:
7025             old = demux->offset;
7026             target = old + size;
7027
7028             /* try to jump over the atom with a seek */
7029             /* only bother if it seems worth doing so,
7030              * and avoids possible upstream/server problems */
7031             if (demux->upstream_seekable &&
7032                 demux->upstream_size > 4 * (1 << 20)) {
7033               res = qtdemux_seek_offset (demux, target);
7034             } else {
7035               GST_DEBUG_OBJECT (demux, "skipping seek");
7036               res = FALSE;
7037             }
7038
7039             if (res) {
7040               GST_DEBUG_OBJECT (demux, "seek success");
7041               /* remember the offset fo the first mdat so we can seek back to it
7042                * after we have the headers */
7043               if (fourcc == FOURCC_mdat && demux->first_mdat == -1) {
7044                 demux->first_mdat = old;
7045                 GST_DEBUG_OBJECT (demux, "first mdat at %" G_GUINT64_FORMAT,
7046                     demux->first_mdat);
7047               }
7048               /* seek worked, continue reading */
7049               demux->offset = target;
7050               demux->neededbytes = 16;
7051               demux->state = QTDEMUX_STATE_INITIAL;
7052             } else {
7053               /* seek failed, need to buffer */
7054               demux->offset = old;
7055               GST_DEBUG_OBJECT (demux, "seek failed/skipped");
7056               /* there may be multiple mdat (or alike) buffers */
7057               /* sanity check */
7058               if (demux->mdatbuffer)
7059                 bs = gst_buffer_get_size (demux->mdatbuffer);
7060               else
7061                 bs = 0;
7062               if (size + bs > 10 * (1 << 20))
7063                 goto no_moov;
7064               demux->state = QTDEMUX_STATE_BUFFER_MDAT;
7065               demux->neededbytes = size;
7066               if (!demux->mdatbuffer)
7067                 demux->mdatoffset = demux->offset;
7068             }
7069           }
7070         } else if (G_UNLIKELY (size > QTDEMUX_MAX_ATOM_SIZE)) {
7071           GST_ELEMENT_ERROR (demux, STREAM, DEMUX,
7072               (_("This file is invalid and cannot be played.")),
7073               ("atom %" GST_FOURCC_FORMAT " has bogus size %" G_GUINT64_FORMAT,
7074                   GST_FOURCC_ARGS (fourcc), size));
7075           ret = GST_FLOW_ERROR;
7076           break;
7077         } else {
7078           /* this means we already started buffering and still no moov header,
7079            * let's continue buffering everything till we get moov */
7080           if (demux->mdatbuffer && !(fourcc == FOURCC_moov
7081                   || fourcc == FOURCC_moof))
7082             goto buffer_data;
7083           demux->neededbytes = size;
7084           demux->state = QTDEMUX_STATE_HEADER;
7085         }
7086         break;
7087       }
7088       case QTDEMUX_STATE_HEADER:{
7089         const guint8 *data;
7090         guint32 fourcc;
7091
7092         GST_DEBUG_OBJECT (demux, "In header");
7093
7094         data = gst_adapter_map (demux->adapter, demux->neededbytes);
7095
7096         /* parse the header */
7097         extract_initial_length_and_fourcc (data, demux->neededbytes, NULL,
7098             &fourcc);
7099         if (fourcc == FOURCC_moov) {
7100           /* in usual fragmented setup we could try to scan for more
7101            * and end up at the the moov (after mdat) again */
7102           if (demux->got_moov && QTDEMUX_N_STREAMS (demux) > 0 &&
7103               (!demux->fragmented
7104                   || demux->last_moov_offset == demux->offset)) {
7105             GST_DEBUG_OBJECT (demux,
7106                 "Skipping moov atom as we have (this) one already");
7107           } else {
7108             GST_DEBUG_OBJECT (demux, "Parsing [moov]");
7109
7110             if (demux->got_moov && demux->fragmented) {
7111               GST_DEBUG_OBJECT (demux,
7112                   "Got a second moov, clean up data from old one");
7113               if (demux->moov_node_compressed) {
7114                 g_node_destroy (demux->moov_node_compressed);
7115                 if (demux->moov_node)
7116                   g_free (demux->moov_node->data);
7117               }
7118               demux->moov_node_compressed = NULL;
7119               if (demux->moov_node)
7120                 g_node_destroy (demux->moov_node);
7121               demux->moov_node = NULL;
7122             }
7123
7124             demux->last_moov_offset = demux->offset;
7125
7126             /* Update streams with new moov */
7127             gst_qtdemux_stream_concat (demux,
7128                 demux->old_streams, demux->active_streams);
7129
7130             qtdemux_parse_moov (demux, data, demux->neededbytes);
7131             qtdemux_node_dump (demux, demux->moov_node);
7132             qtdemux_parse_tree (demux);
7133             qtdemux_prepare_streams (demux);
7134             QTDEMUX_EXPOSE_LOCK (demux);
7135             qtdemux_expose_streams (demux);
7136             QTDEMUX_EXPOSE_UNLOCK (demux);
7137
7138             demux->got_moov = TRUE;
7139
7140             gst_qtdemux_check_send_pending_segment (demux);
7141
7142             if (demux->moov_node_compressed) {
7143               g_node_destroy (demux->moov_node_compressed);
7144               g_free (demux->moov_node->data);
7145             }
7146             demux->moov_node_compressed = NULL;
7147             g_node_destroy (demux->moov_node);
7148             demux->moov_node = NULL;
7149             GST_DEBUG_OBJECT (demux, "Finished parsing the header");
7150           }
7151         } else if (fourcc == FOURCC_moof) {
7152           if ((demux->got_moov || demux->media_caps) && demux->fragmented) {
7153             guint64 dist = 0;
7154             GstClockTime prev_pts;
7155             guint64 prev_offset;
7156             guint64 adapter_discont_offset, adapter_discont_dist;
7157
7158             GST_DEBUG_OBJECT (demux, "Parsing [moof]");
7159
7160             /*
7161              * The timestamp of the moof buffer is relevant as some scenarios
7162              * won't have the initial timestamp in the atoms. Whenever a new
7163              * buffer has started, we get that buffer's PTS and use it as a base
7164              * timestamp for the trun entries.
7165              *
7166              * To keep track of the current buffer timestamp and starting point
7167              * we use gst_adapter_prev_pts that gives us the PTS and the distance
7168              * from the beggining of the buffer, with the distance and demux->offset
7169              * we know if it is still the same buffer or not.
7170              */
7171             prev_pts = gst_adapter_prev_pts (demux->adapter, &dist);
7172             prev_offset = demux->offset - dist;
7173             if (demux->fragment_start_offset == -1
7174                 || prev_offset > demux->fragment_start_offset) {
7175               demux->fragment_start_offset = prev_offset;
7176               demux->fragment_start = prev_pts;
7177               GST_DEBUG_OBJECT (demux,
7178                   "New fragment start found at: %" G_GUINT64_FORMAT " : %"
7179                   GST_TIME_FORMAT, demux->fragment_start_offset,
7180                   GST_TIME_ARGS (demux->fragment_start));
7181             }
7182
7183             /* We can't use prev_offset() here because this would require
7184              * upstream to set consistent and correct offsets on all buffers
7185              * since the discont. Nothing ever did that in the past and we
7186              * would break backwards compatibility here then.
7187              * Instead take the offset we had at the last discont and count
7188              * the bytes from there. This works with old code as there would
7189              * be no discont between moov and moof, and also works with
7190              * adaptivedemux which correctly sets offset and will set the
7191              * DISCONT flag accordingly when needed.
7192              *
7193              * We also only do this for upstream TIME segments as otherwise
7194              * there are potential backwards compatibility problems with
7195              * seeking in PUSH mode and upstream providing inconsistent
7196              * timestamps. */
7197             adapter_discont_offset =
7198                 gst_adapter_offset_at_discont (demux->adapter);
7199             adapter_discont_dist =
7200                 gst_adapter_distance_from_discont (demux->adapter);
7201
7202             GST_DEBUG_OBJECT (demux,
7203                 "demux offset %" G_GUINT64_FORMAT " adapter offset %"
7204                 G_GUINT64_FORMAT " (+ %" G_GUINT64_FORMAT " bytes)",
7205                 demux->offset, adapter_discont_offset, adapter_discont_dist);
7206
7207             if (demux->upstream_format_is_time) {
7208               demux->moof_offset = adapter_discont_offset;
7209               if (demux->moof_offset != GST_BUFFER_OFFSET_NONE)
7210                 demux->moof_offset += adapter_discont_dist;
7211               if (demux->moof_offset == GST_BUFFER_OFFSET_NONE)
7212                 demux->moof_offset = demux->offset;
7213             } else {
7214               demux->moof_offset = demux->offset;
7215             }
7216
7217             if (!qtdemux_parse_moof (demux, data, demux->neededbytes,
7218                     demux->moof_offset, NULL)) {
7219               gst_adapter_unmap (demux->adapter);
7220               ret = GST_FLOW_ERROR;
7221               goto done;
7222             }
7223
7224             /* in MSS we need to expose the pads after the first moof as we won't get a moov */
7225             if (demux->mss_mode && !demux->exposed) {
7226               QTDEMUX_EXPOSE_LOCK (demux);
7227               qtdemux_expose_streams (demux);
7228               QTDEMUX_EXPOSE_UNLOCK (demux);
7229             }
7230
7231             gst_qtdemux_check_send_pending_segment (demux);
7232           } else {
7233             GST_DEBUG_OBJECT (demux, "Discarding [moof]");
7234           }
7235         } else if (fourcc == FOURCC_ftyp) {
7236           GST_DEBUG_OBJECT (demux, "Parsing [ftyp]");
7237           qtdemux_parse_ftyp (demux, data, demux->neededbytes);
7238         } else if (fourcc == FOURCC_uuid) {
7239           GST_DEBUG_OBJECT (demux, "Parsing [uuid]");
7240           qtdemux_parse_uuid (demux, data, demux->neededbytes);
7241         } else if (fourcc == FOURCC_sidx) {
7242           GST_DEBUG_OBJECT (demux, "Parsing [sidx]");
7243           qtdemux_parse_sidx (demux, data, demux->neededbytes);
7244         } else {
7245           switch (fourcc) {
7246             case FOURCC_styp:
7247               /* [styp] is like a [ftyp], but in fragment header. We ignore it for now
7248                * FALLTHROUGH */
7249             case FOURCC_skip:
7250             case FOURCC_free:
7251               /* [free] and [skip] are padding atoms */
7252               GST_DEBUG_OBJECT (demux,
7253                   "Skipping fourcc while parsing header : %" GST_FOURCC_FORMAT,
7254                   GST_FOURCC_ARGS (fourcc));
7255               break;
7256             default:
7257               GST_WARNING_OBJECT (demux,
7258                   "Unknown fourcc while parsing header : %" GST_FOURCC_FORMAT,
7259                   GST_FOURCC_ARGS (fourcc));
7260               /* Let's jump that one and go back to initial state */
7261               break;
7262           }
7263         }
7264         gst_adapter_unmap (demux->adapter);
7265         data = NULL;
7266
7267         if (demux->mdatbuffer && QTDEMUX_N_STREAMS (demux)) {
7268           gsize remaining_data_size = 0;
7269
7270           /* the mdat was before the header */
7271           GST_DEBUG_OBJECT (demux, "We have n_streams:%d and mdatbuffer:%p",
7272               QTDEMUX_N_STREAMS (demux), demux->mdatbuffer);
7273           /* restore our adapter/offset view of things with upstream;
7274            * put preceding buffered data ahead of current moov data.
7275            * This should also handle evil mdat, moov, mdat cases and alike */
7276           gst_adapter_flush (demux->adapter, demux->neededbytes);
7277
7278           /* Store any remaining data after the mdat for later usage */
7279           remaining_data_size = gst_adapter_available (demux->adapter);
7280           if (remaining_data_size > 0) {
7281             g_assert (demux->restoredata_buffer == NULL);
7282             demux->restoredata_buffer =
7283                 gst_adapter_take_buffer (demux->adapter, remaining_data_size);
7284             demux->restoredata_offset = demux->offset + demux->neededbytes;
7285             GST_DEBUG_OBJECT (demux,
7286                 "Stored %" G_GSIZE_FORMAT " post mdat bytes at offset %"
7287                 G_GUINT64_FORMAT, remaining_data_size,
7288                 demux->restoredata_offset);
7289           }
7290
7291           gst_adapter_push (demux->adapter, demux->mdatbuffer);
7292           demux->mdatbuffer = NULL;
7293           demux->offset = demux->mdatoffset;
7294           demux->neededbytes = next_entry_size (demux);
7295           demux->state = QTDEMUX_STATE_MOVIE;
7296           demux->mdatleft = gst_adapter_available (demux->adapter);
7297           demux->mdatsize = demux->mdatleft;
7298         } else {
7299           GST_DEBUG_OBJECT (demux, "Carrying on normally");
7300           gst_adapter_flush (demux->adapter, demux->neededbytes);
7301
7302           /* only go back to the mdat if there are samples to play */
7303           if (demux->got_moov && demux->first_mdat != -1
7304               && has_next_entry (demux)) {
7305             gboolean res;
7306
7307             /* we need to seek back */
7308             res = qtdemux_seek_offset (demux, demux->first_mdat);
7309             if (res) {
7310               demux->offset = demux->first_mdat;
7311             } else {
7312               GST_DEBUG_OBJECT (demux, "Seek back failed");
7313             }
7314           } else {
7315             demux->offset += demux->neededbytes;
7316           }
7317           demux->neededbytes = 16;
7318           demux->state = QTDEMUX_STATE_INITIAL;
7319         }
7320
7321         break;
7322       }
7323       case QTDEMUX_STATE_BUFFER_MDAT:{
7324         GstBuffer *buf;
7325         guint8 fourcc[4];
7326
7327         GST_DEBUG_OBJECT (demux, "Got our buffer at offset %" G_GUINT64_FORMAT,
7328             demux->offset);
7329         buf = gst_adapter_take_buffer (demux->adapter, demux->neededbytes);
7330         gst_buffer_extract (buf, 0, fourcc, 4);
7331         GST_DEBUG_OBJECT (demux, "mdatbuffer starts with %" GST_FOURCC_FORMAT,
7332             GST_FOURCC_ARGS (QT_FOURCC (fourcc)));
7333         if (demux->mdatbuffer)
7334           demux->mdatbuffer = gst_buffer_append (demux->mdatbuffer, buf);
7335         else
7336           demux->mdatbuffer = buf;
7337         demux->offset += demux->neededbytes;
7338         demux->neededbytes = 16;
7339         demux->state = QTDEMUX_STATE_INITIAL;
7340         gst_qtdemux_post_progress (demux, 1, 1);
7341
7342         break;
7343       }
7344       case QTDEMUX_STATE_MOVIE:{
7345         QtDemuxStream *stream = NULL;
7346         QtDemuxSample *sample;
7347         GstClockTime dts, pts, duration;
7348         gboolean keyframe;
7349         gint i;
7350
7351         GST_DEBUG_OBJECT (demux,
7352             "BEGIN // in MOVIE for offset %" G_GUINT64_FORMAT, demux->offset);
7353
7354         if (demux->fragmented) {
7355           GST_DEBUG_OBJECT (demux, "mdat remaining %" G_GUINT64_FORMAT,
7356               demux->mdatleft);
7357           if (G_LIKELY (demux->todrop < demux->mdatleft)) {
7358             /* if needed data starts within this atom,
7359              * then it should not exceed this atom */
7360             if (G_UNLIKELY (demux->neededbytes > demux->mdatleft)) {
7361               GST_ELEMENT_ERROR (demux, STREAM, DEMUX,
7362                   (_("This file is invalid and cannot be played.")),
7363                   ("sample data crosses atom boundary"));
7364               ret = GST_FLOW_ERROR;
7365               break;
7366             }
7367             demux->mdatleft -= demux->neededbytes;
7368           } else {
7369             GST_DEBUG_OBJECT (demux, "data atom emptied; resuming atom scan");
7370             /* so we are dropping more than left in this atom */
7371             gst_qtdemux_drop_data (demux, demux->mdatleft);
7372             demux->mdatleft = 0;
7373
7374             /* need to resume atom parsing so we do not miss any other pieces */
7375             demux->state = QTDEMUX_STATE_INITIAL;
7376             demux->neededbytes = 16;
7377
7378             /* check if there was any stored post mdat data from previous buffers */
7379             if (demux->restoredata_buffer) {
7380               g_assert (gst_adapter_available (demux->adapter) == 0);
7381
7382               gst_adapter_push (demux->adapter, demux->restoredata_buffer);
7383               demux->restoredata_buffer = NULL;
7384               demux->offset = demux->restoredata_offset;
7385             }
7386
7387             break;
7388           }
7389         }
7390
7391         if (demux->todrop) {
7392           if (demux->cenc_aux_info_offset > 0) {
7393             GstByteReader br;
7394             const guint8 *data;
7395
7396             GST_DEBUG_OBJECT (demux, "parsing cenc auxiliary info");
7397             data = gst_adapter_map (demux->adapter, demux->todrop);
7398             gst_byte_reader_init (&br, data + 8, demux->todrop);
7399             if (!qtdemux_parse_cenc_aux_info (demux,
7400                     QTDEMUX_NTH_STREAM (demux, 0), &br,
7401                     demux->cenc_aux_info_sizes, demux->cenc_aux_sample_count)) {
7402               GST_ERROR_OBJECT (demux, "failed to parse cenc auxiliary info");
7403               ret = GST_FLOW_ERROR;
7404               gst_adapter_unmap (demux->adapter);
7405               g_free (demux->cenc_aux_info_sizes);
7406               demux->cenc_aux_info_sizes = NULL;
7407               goto done;
7408             }
7409             demux->cenc_aux_info_offset = 0;
7410             g_free (demux->cenc_aux_info_sizes);
7411             demux->cenc_aux_info_sizes = NULL;
7412             gst_adapter_unmap (demux->adapter);
7413           }
7414           gst_qtdemux_drop_data (demux, demux->todrop);
7415         }
7416
7417         /* first buffer? */
7418         /* initial newsegment sent here after having added pads,
7419          * possible others in sink_event */
7420         gst_qtdemux_check_send_pending_segment (demux);
7421
7422         /* Figure out which stream this packet belongs to */
7423         for (i = 0; i < QTDEMUX_N_STREAMS (demux); i++) {
7424           stream = QTDEMUX_NTH_STREAM (demux, i);
7425           if (stream->sample_index >= stream->n_samples) {
7426             /* reset to be checked below G_UNLIKELY (stream == NULL) */
7427             stream = NULL;
7428             continue;
7429           }
7430           GST_LOG_OBJECT (demux,
7431               "Checking track-id %u (sample_index:%d / offset:%"
7432               G_GUINT64_FORMAT " / size:%d)", stream->track_id,
7433               stream->sample_index,
7434               stream->samples[stream->sample_index].offset,
7435               stream->samples[stream->sample_index].size);
7436
7437           if (stream->samples[stream->sample_index].offset == demux->offset)
7438             break;
7439         }
7440
7441         if (G_UNLIKELY (stream == NULL))
7442           goto unknown_stream;
7443
7444         gst_qtdemux_stream_check_and_change_stsd_index (demux, stream);
7445
7446         if (stream->new_caps) {
7447           gst_qtdemux_configure_stream (demux, stream);
7448         }
7449
7450         /* Put data in a buffer, set timestamps, caps, ... */
7451         sample = &stream->samples[stream->sample_index];
7452
7453         if (G_LIKELY (!(STREAM_IS_EOS (stream)))) {
7454           GST_DEBUG_OBJECT (demux, "stream : %" GST_FOURCC_FORMAT,
7455               GST_FOURCC_ARGS (CUR_STREAM (stream)->fourcc));
7456
7457           dts = QTSAMPLE_DTS (stream, sample);
7458           pts = QTSAMPLE_PTS (stream, sample);
7459           duration = QTSAMPLE_DUR_DTS (stream, sample, dts);
7460           keyframe = QTSAMPLE_KEYFRAME (stream, sample);
7461
7462           /* check for segment end */
7463           if (G_UNLIKELY (demux->segment.stop != -1
7464                   && demux->segment.stop <= pts && stream->on_keyframe)
7465               && !(demux->upstream_format_is_time && demux->segment.rate < 0)) {
7466             GST_DEBUG_OBJECT (demux, "we reached the end of our segment.");
7467             stream->time_position = GST_CLOCK_TIME_NONE;        /* this means EOS */
7468
7469             /* skip this data, stream is EOS */
7470             gst_adapter_flush (demux->adapter, demux->neededbytes);
7471             demux->offset += demux->neededbytes;
7472
7473             /* check if all streams are eos */
7474             ret = GST_FLOW_EOS;
7475             for (i = 0; i < QTDEMUX_N_STREAMS (demux); i++) {
7476               if (!STREAM_IS_EOS (QTDEMUX_NTH_STREAM (demux, i))) {
7477                 ret = GST_FLOW_OK;
7478                 break;
7479               }
7480             }
7481           } else {
7482             GstBuffer *outbuf;
7483
7484             outbuf =
7485                 gst_adapter_take_buffer (demux->adapter, demux->neededbytes);
7486
7487             /* FIXME: should either be an assert or a plain check */
7488             g_return_val_if_fail (outbuf != NULL, GST_FLOW_ERROR);
7489
7490             ret = gst_qtdemux_decorate_and_push_buffer (demux, stream, outbuf,
7491                 dts, pts, duration, keyframe, dts, demux->offset);
7492           }
7493
7494           /* combine flows */
7495           ret = gst_qtdemux_combine_flows (demux, stream, ret);
7496         } else {
7497           /* skip this data, stream is EOS */
7498           gst_adapter_flush (demux->adapter, demux->neededbytes);
7499         }
7500
7501         stream->sample_index++;
7502         stream->offset_in_sample = 0;
7503
7504         /* update current offset and figure out size of next buffer */
7505         GST_LOG_OBJECT (demux, "increasing offset %" G_GUINT64_FORMAT " by %u",
7506             demux->offset, demux->neededbytes);
7507         demux->offset += demux->neededbytes;
7508         GST_LOG_OBJECT (demux, "offset is now %" G_GUINT64_FORMAT,
7509             demux->offset);
7510
7511
7512         if (ret == GST_FLOW_EOS) {
7513           GST_DEBUG_OBJECT (demux, "All streams are EOS, signal upstream");
7514           demux->neededbytes = -1;
7515           goto eos;
7516         }
7517
7518         if ((demux->neededbytes = next_entry_size (demux)) == -1) {
7519           if (demux->fragmented) {
7520             GST_DEBUG_OBJECT (demux, "(temporarily) out of fragmented samples");
7521             /* there may be more to follow, only finish this atom */
7522             demux->todrop = demux->mdatleft;
7523             demux->neededbytes = demux->todrop;
7524             break;
7525           }
7526           goto eos;
7527         }
7528         if (ret != GST_FLOW_OK && ret != GST_FLOW_NOT_LINKED) {
7529           goto non_ok_unlinked_flow;
7530         }
7531         break;
7532       }
7533       default:
7534         goto invalid_state;
7535     }
7536   }
7537
7538   /* when buffering movie data, at least show user something is happening */
7539   if (ret == GST_FLOW_OK && demux->state == QTDEMUX_STATE_BUFFER_MDAT &&
7540       gst_adapter_available (demux->adapter) <= demux->neededbytes) {
7541     gst_qtdemux_post_progress (demux, gst_adapter_available (demux->adapter),
7542         demux->neededbytes);
7543   }
7544 done:
7545
7546   return ret;
7547
7548   /* ERRORS */
7549 non_ok_unlinked_flow:
7550   {
7551     GST_DEBUG_OBJECT (demux, "Stopping, combined return flow %s",
7552         gst_flow_get_name (ret));
7553     return ret;
7554   }
7555 unknown_stream:
7556   {
7557     GST_ELEMENT_ERROR (demux, STREAM, FAILED, (NULL), ("unknown stream found"));
7558     ret = GST_FLOW_ERROR;
7559     goto done;
7560   }
7561 eos:
7562   {
7563     GST_DEBUG_OBJECT (demux, "no next entry, EOS");
7564     ret = GST_FLOW_EOS;
7565     goto done;
7566   }
7567 invalid_state:
7568   {
7569     GST_ELEMENT_ERROR (demux, STREAM, FAILED,
7570         (NULL), ("qtdemuxer invalid state %d", demux->state));
7571     ret = GST_FLOW_ERROR;
7572     goto done;
7573   }
7574 no_moov:
7575   {
7576     GST_ELEMENT_ERROR (demux, STREAM, FAILED,
7577         (NULL), ("no 'moov' atom within the first 10 MB"));
7578     ret = GST_FLOW_ERROR;
7579     goto done;
7580   }
7581 }
7582
7583 static gboolean
7584 qtdemux_sink_activate (GstPad * sinkpad, GstObject * parent)
7585 {
7586   GstQuery *query;
7587   gboolean pull_mode;
7588
7589   query = gst_query_new_scheduling ();
7590
7591   if (!gst_pad_peer_query (sinkpad, query)) {
7592     gst_query_unref (query);
7593     goto activate_push;
7594   }
7595
7596   pull_mode = gst_query_has_scheduling_mode_with_flags (query,
7597       GST_PAD_MODE_PULL, GST_SCHEDULING_FLAG_SEEKABLE);
7598   gst_query_unref (query);
7599
7600   if (!pull_mode)
7601     goto activate_push;
7602
7603   GST_DEBUG_OBJECT (sinkpad, "activating pull");
7604   return gst_pad_activate_mode (sinkpad, GST_PAD_MODE_PULL, TRUE);
7605
7606 activate_push:
7607   {
7608     GST_DEBUG_OBJECT (sinkpad, "activating push");
7609     return gst_pad_activate_mode (sinkpad, GST_PAD_MODE_PUSH, TRUE);
7610   }
7611 }
7612
7613 static gboolean
7614 qtdemux_sink_activate_mode (GstPad * sinkpad, GstObject * parent,
7615     GstPadMode mode, gboolean active)
7616 {
7617   gboolean res;
7618   GstQTDemux *demux = GST_QTDEMUX (parent);
7619
7620   switch (mode) {
7621     case GST_PAD_MODE_PUSH:
7622       demux->pullbased = FALSE;
7623       res = TRUE;
7624       break;
7625     case GST_PAD_MODE_PULL:
7626       if (active) {
7627         demux->pullbased = TRUE;
7628         res = gst_pad_start_task (sinkpad, (GstTaskFunction) gst_qtdemux_loop,
7629             sinkpad, NULL);
7630       } else {
7631         res = gst_pad_stop_task (sinkpad);
7632       }
7633       break;
7634     default:
7635       res = FALSE;
7636       break;
7637   }
7638   return res;
7639 }
7640
7641 #ifdef HAVE_ZLIB
7642 static void *
7643 qtdemux_inflate (void *z_buffer, guint z_length, guint * length)
7644 {
7645   guint8 *buffer;
7646   z_stream z;
7647   int ret;
7648
7649   memset (&z, 0, sizeof (z));
7650   z.zalloc = NULL;
7651   z.zfree = NULL;
7652   z.opaque = NULL;
7653
7654   if ((ret = inflateInit (&z)) != Z_OK) {
7655     GST_ERROR ("inflateInit() returned %d", ret);
7656     return NULL;
7657   }
7658
7659   z.next_in = z_buffer;
7660   z.avail_in = z_length;
7661
7662   buffer = (guint8 *) g_malloc (*length);
7663   z.avail_out = *length;
7664   z.next_out = (Bytef *) buffer;
7665   do {
7666     ret = inflate (&z, Z_NO_FLUSH);
7667     if (ret == Z_STREAM_END) {
7668       break;
7669     } else if (ret != Z_OK) {
7670       GST_WARNING ("inflate() returned %d", ret);
7671       break;
7672     }
7673
7674     *length += 4096;
7675     buffer = (guint8 *) g_realloc (buffer, *length);
7676     z.next_out = (Bytef *) (buffer + z.total_out);
7677     z.avail_out += 4096;
7678   } while (z.avail_in > 0);
7679
7680   if (ret != Z_STREAM_END) {
7681     g_free (buffer);
7682     buffer = NULL;
7683     *length = 0;
7684   } else {
7685     *length = z.total_out;
7686   }
7687
7688   inflateEnd (&z);
7689
7690   return buffer;
7691 }
7692 #endif /* HAVE_ZLIB */
7693
7694 static gboolean
7695 qtdemux_parse_moov (GstQTDemux * qtdemux, const guint8 * buffer, guint length)
7696 {
7697   GNode *cmov;
7698
7699   qtdemux->moov_node = g_node_new ((guint8 *) buffer);
7700
7701   /* counts as header data */
7702   qtdemux->header_size += length;
7703
7704   GST_DEBUG_OBJECT (qtdemux, "parsing 'moov' atom");
7705   qtdemux_parse_node (qtdemux, qtdemux->moov_node, buffer, length);
7706
7707   cmov = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_cmov);
7708   if (cmov) {
7709     guint32 method;
7710     GNode *dcom;
7711     GNode *cmvd;
7712     guint32 dcom_len;
7713
7714     dcom = qtdemux_tree_get_child_by_type (cmov, FOURCC_dcom);
7715     cmvd = qtdemux_tree_get_child_by_type (cmov, FOURCC_cmvd);
7716     if (dcom == NULL || cmvd == NULL)
7717       goto invalid_compression;
7718
7719     dcom_len = QT_UINT32 (dcom->data);
7720     if (dcom_len < 12)
7721       goto invalid_compression;
7722
7723     method = QT_FOURCC ((guint8 *) dcom->data + 8);
7724     switch (method) {
7725 #ifdef HAVE_ZLIB
7726       case FOURCC_zlib:{
7727         guint uncompressed_length;
7728         guint compressed_length;
7729         guint8 *buf;
7730         guint32 cmvd_len;
7731
7732         cmvd_len = QT_UINT32 ((guint8 *) cmvd->data);
7733         if (cmvd_len < 12)
7734           goto invalid_compression;
7735
7736         uncompressed_length = QT_UINT32 ((guint8 *) cmvd->data + 8);
7737         compressed_length = cmvd_len - 12;
7738         GST_LOG ("length = %u", uncompressed_length);
7739
7740         buf =
7741             (guint8 *) qtdemux_inflate ((guint8 *) cmvd->data + 12,
7742             compressed_length, &uncompressed_length);
7743
7744         if (buf) {
7745           qtdemux->moov_node_compressed = qtdemux->moov_node;
7746           qtdemux->moov_node = g_node_new (buf);
7747
7748           qtdemux_parse_node (qtdemux, qtdemux->moov_node, buf,
7749               uncompressed_length);
7750         }
7751         break;
7752       }
7753 #endif /* HAVE_ZLIB */
7754       default:
7755         GST_WARNING_OBJECT (qtdemux, "unknown or unhandled header compression "
7756             "type %" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (method));
7757         break;
7758     }
7759   }
7760   return TRUE;
7761
7762   /* ERRORS */
7763 invalid_compression:
7764   {
7765     GST_ERROR_OBJECT (qtdemux, "invalid compressed header");
7766     return FALSE;
7767   }
7768 }
7769
7770 static gboolean
7771 qtdemux_parse_container (GstQTDemux * qtdemux, GNode * node, const guint8 * buf,
7772     const guint8 * end)
7773 {
7774   while (G_UNLIKELY (buf < end)) {
7775     GNode *child;
7776     guint32 len;
7777
7778     if (G_UNLIKELY (buf + 4 > end)) {
7779       GST_LOG_OBJECT (qtdemux, "buffer overrun");
7780       break;
7781     }
7782     len = QT_UINT32 (buf);
7783     if (G_UNLIKELY (len == 0)) {
7784       GST_LOG_OBJECT (qtdemux, "empty container");
7785       break;
7786     }
7787     if (G_UNLIKELY (len < 8)) {
7788       GST_WARNING_OBJECT (qtdemux, "length too short (%d < 8)", len);
7789       break;
7790     }
7791     if (G_UNLIKELY (len > (end - buf))) {
7792       GST_WARNING_OBJECT (qtdemux, "length too long (%d > %d)", len,
7793           (gint) (end - buf));
7794       break;
7795     }
7796
7797     child = g_node_new ((guint8 *) buf);
7798     g_node_append (node, child);
7799     GST_LOG_OBJECT (qtdemux, "adding new node of len %d", len);
7800     qtdemux_parse_node (qtdemux, child, buf, len);
7801
7802     buf += len;
7803   }
7804   return TRUE;
7805 }
7806
7807 static gboolean
7808 qtdemux_parse_theora_extension (GstQTDemux * qtdemux, QtDemuxStream * stream,
7809     GNode * xdxt)
7810 {
7811   int len = QT_UINT32 (xdxt->data);
7812   guint8 *buf = xdxt->data;
7813   guint8 *end = buf + len;
7814   GstBuffer *buffer;
7815
7816   /* skip size and type */
7817   buf += 8;
7818   end -= 8;
7819
7820   while (buf < end) {
7821     gint size;
7822     guint32 type;
7823
7824     size = QT_UINT32 (buf);
7825     type = QT_FOURCC (buf + 4);
7826
7827     GST_LOG_OBJECT (qtdemux, "%p %p", buf, end);
7828
7829     if (buf + size > end || size <= 0)
7830       break;
7831
7832     buf += 8;
7833     size -= 8;
7834
7835     GST_WARNING_OBJECT (qtdemux, "have cookie %" GST_FOURCC_FORMAT,
7836         GST_FOURCC_ARGS (type));
7837
7838     switch (type) {
7839       case FOURCC_tCtH:
7840         buffer = gst_buffer_new_and_alloc (size);
7841         gst_buffer_fill (buffer, 0, buf, size);
7842         stream->buffers = g_slist_append (stream->buffers, buffer);
7843         GST_LOG_OBJECT (qtdemux, "parsing theora header");
7844         break;
7845       case FOURCC_tCt_:
7846         buffer = gst_buffer_new_and_alloc (size);
7847         gst_buffer_fill (buffer, 0, buf, size);
7848         stream->buffers = g_slist_append (stream->buffers, buffer);
7849         GST_LOG_OBJECT (qtdemux, "parsing theora comment");
7850         break;
7851       case FOURCC_tCtC:
7852         buffer = gst_buffer_new_and_alloc (size);
7853         gst_buffer_fill (buffer, 0, buf, size);
7854         stream->buffers = g_slist_append (stream->buffers, buffer);
7855         GST_LOG_OBJECT (qtdemux, "parsing theora codebook");
7856         break;
7857       default:
7858         GST_WARNING_OBJECT (qtdemux,
7859             "unknown theora cookie %" GST_FOURCC_FORMAT,
7860             GST_FOURCC_ARGS (type));
7861         break;
7862     }
7863     buf += size;
7864   }
7865   return TRUE;
7866 }
7867
7868 static gboolean
7869 qtdemux_parse_node (GstQTDemux * qtdemux, GNode * node, const guint8 * buffer,
7870     guint length)
7871 {
7872   guint32 fourcc = 0;
7873   guint32 node_length = 0;
7874   const QtNodeType *type;
7875   const guint8 *end;
7876
7877   GST_LOG_OBJECT (qtdemux, "qtdemux_parse buffer %p length %u", buffer, length);
7878
7879   if (G_UNLIKELY (length < 8))
7880     goto not_enough_data;
7881
7882   node_length = QT_UINT32 (buffer);
7883   fourcc = QT_FOURCC (buffer + 4);
7884
7885   /* ignore empty nodes */
7886   if (G_UNLIKELY (fourcc == 0 || node_length == 8))
7887     return TRUE;
7888
7889   type = qtdemux_type_get (fourcc);
7890
7891   end = buffer + length;
7892
7893   GST_LOG_OBJECT (qtdemux,
7894       "parsing '%" GST_FOURCC_FORMAT "', length=%u, name '%s'",
7895       GST_FOURCC_ARGS (fourcc), node_length, type->name);
7896
7897   if (node_length > length)
7898     goto broken_atom_size;
7899
7900   if (type->flags & QT_FLAG_CONTAINER) {
7901     qtdemux_parse_container (qtdemux, node, buffer + 8, end);
7902   } else {
7903     switch (fourcc) {
7904       case FOURCC_stsd:
7905       {
7906         if (node_length < 20) {
7907           GST_LOG_OBJECT (qtdemux, "skipping small stsd box");
7908           break;
7909         }
7910         GST_DEBUG_OBJECT (qtdemux,
7911             "parsing stsd (sample table, sample description) atom");
7912         /* Skip over 8 byte atom hdr + 1 byte version, 3 bytes flags, 4 byte num_entries */
7913         qtdemux_parse_container (qtdemux, node, buffer + 16, end);
7914         break;
7915       }
7916       case FOURCC_mp4a:
7917       case FOURCC_alac:
7918       case FOURCC_fLaC:
7919       {
7920         guint32 version;
7921         guint32 offset;
7922         guint min_size;
7923
7924         /* also read alac (or whatever) in stead of mp4a in the following,
7925          * since a similar layout is used in other cases as well */
7926         if (fourcc == FOURCC_mp4a)
7927           min_size = 20;
7928         else if (fourcc == FOURCC_fLaC)
7929           min_size = 86;
7930         else
7931           min_size = 40;
7932
7933         /* There are two things we might encounter here: a true mp4a atom, and
7934            an mp4a entry in an stsd atom. The latter is what we're interested
7935            in, and it looks like an atom, but isn't really one. The true mp4a
7936            atom is short, so we detect it based on length here. */
7937         if (length < min_size) {
7938           GST_LOG_OBJECT (qtdemux, "skipping small %" GST_FOURCC_FORMAT " box",
7939               GST_FOURCC_ARGS (fourcc));
7940           break;
7941         }
7942
7943         /* 'version' here is the sound sample description version. Types 0 and
7944            1 are documented in the QTFF reference, but type 2 is not: it's
7945            described in Apple header files instead (struct SoundDescriptionV2
7946            in Movies.h) */
7947         version = QT_UINT16 (buffer + 16);
7948
7949         GST_DEBUG_OBJECT (qtdemux, "%" GST_FOURCC_FORMAT " version 0x%08x",
7950             GST_FOURCC_ARGS (fourcc), version);
7951
7952         /* parse any esds descriptors */
7953         switch (version) {
7954           case 0:
7955             offset = 0x24;
7956             break;
7957           case 1:
7958             offset = 0x34;
7959             break;
7960           case 2:
7961             offset = 0x48;
7962             break;
7963           default:
7964             GST_WARNING_OBJECT (qtdemux,
7965                 "unhandled %" GST_FOURCC_FORMAT " version 0x%08x",
7966                 GST_FOURCC_ARGS (fourcc), version);
7967             offset = 0;
7968             break;
7969         }
7970         if (offset)
7971           qtdemux_parse_container (qtdemux, node, buffer + offset, end);
7972         break;
7973       }
7974       case FOURCC_mp4v:
7975       case FOURCC_MP4V:
7976       case FOURCC_fmp4:
7977       case FOURCC_FMP4:
7978       case FOURCC_apcs:
7979       case FOURCC_apch:
7980       case FOURCC_apcn:
7981       case FOURCC_apco:
7982       case FOURCC_ap4h:
7983       case FOURCC_xvid:
7984       case FOURCC_XVID:
7985       case FOURCC_H264:
7986       case FOURCC_avc1:
7987       case FOURCC_avc3:
7988       case FOURCC_H265:
7989       case FOURCC_hvc1:
7990       case FOURCC_hev1:
7991       case FOURCC_mjp2:
7992       case FOURCC_encv:
7993       {
7994         guint32 version;
7995         guint32 str_len;
7996
7997         /* codec_data is contained inside these atoms, which all have
7998          * the same format. */
7999         /* video sample description size is 86 bytes without extension.
8000          * node_length have to be bigger than 86 bytes because video sample
8001          * description can include extenstions such as esds, fiel, glbl, etc. */
8002         if (node_length < 86) {
8003           GST_WARNING_OBJECT (qtdemux, "%" GST_FOURCC_FORMAT
8004               " sample description length too short (%u < 86)",
8005               GST_FOURCC_ARGS (fourcc), node_length);
8006           break;
8007         }
8008
8009         GST_DEBUG_OBJECT (qtdemux, "parsing in %" GST_FOURCC_FORMAT,
8010             GST_FOURCC_ARGS (fourcc));
8011
8012         /* version (2 bytes) : this is set to 0, unless a compressor has changed
8013          *              its data format.
8014          * revision level (2 bytes) : must be set to 0. */
8015         version = QT_UINT32 (buffer + 16);
8016         GST_DEBUG_OBJECT (qtdemux, "version %08x", version);
8017
8018         /* compressor name : PASCAL string and informative purposes
8019          * first byte : the number of bytes to be displayed.
8020          *              it has to be less than 32 because it is reserved
8021          *              space of 32 bytes total including itself. */
8022         str_len = QT_UINT8 (buffer + 50);
8023         if (str_len < 32)
8024           GST_DEBUG_OBJECT (qtdemux, "compressorname = %.*s", str_len,
8025               (char *) buffer + 51);
8026         else
8027           GST_WARNING_OBJECT (qtdemux,
8028               "compressorname length too big (%u > 31)", str_len);
8029
8030         GST_MEMDUMP_OBJECT (qtdemux, "video sample description", buffer,
8031             end - buffer);
8032         qtdemux_parse_container (qtdemux, node, buffer + 86, end);
8033         break;
8034       }
8035       case FOURCC_meta:
8036       {
8037         GST_DEBUG_OBJECT (qtdemux, "parsing meta atom");
8038
8039         /* You are reading this correctly. QTFF specifies that the
8040          * metadata atom is a short atom, whereas ISO BMFF specifies
8041          * it's a full atom. But since so many people are doing things
8042          * differently, we actually peek into the atom to see which
8043          * variant it is */
8044         if (length < 16) {
8045           GST_LOG_OBJECT (qtdemux, "skipping small %" GST_FOURCC_FORMAT " box",
8046               GST_FOURCC_ARGS (fourcc));
8047           break;
8048         }
8049         if (QT_FOURCC (buffer + 12) == FOURCC_hdlr) {
8050           /* Variant 1: What QTFF specifies. 'meta' is a short header which
8051            * starts with a 'hdlr' atom */
8052           qtdemux_parse_container (qtdemux, node, buffer + 8, end);
8053         } else if (QT_UINT32 (buffer + 8) == 0x00000000) {
8054           /* Variant 2: What ISO BMFF specifies. 'meta' is a _full_ atom
8055            * with version/flags both set to zero */
8056           qtdemux_parse_container (qtdemux, node, buffer + 12, end);
8057         } else
8058           GST_WARNING_OBJECT (qtdemux, "Unknown 'meta' atom format");
8059         break;
8060       }
8061       case FOURCC_mp4s:
8062       {
8063         GST_MEMDUMP_OBJECT (qtdemux, "mp4s", buffer, end - buffer);
8064         /* Skip 8 byte header, plus 8 byte version + flags + entry_count */
8065         qtdemux_parse_container (qtdemux, node, buffer + 16, end);
8066         break;
8067       }
8068       case FOURCC_XiTh:
8069       {
8070         guint32 version;
8071         guint32 offset;
8072
8073         if (length < 16) {
8074           GST_LOG_OBJECT (qtdemux, "skipping small %" GST_FOURCC_FORMAT " box",
8075               GST_FOURCC_ARGS (fourcc));
8076           break;
8077         }
8078
8079         version = QT_UINT32 (buffer + 12);
8080         GST_DEBUG_OBJECT (qtdemux, "parsing XiTh atom version 0x%08x", version);
8081
8082         switch (version) {
8083           case 0x00000001:
8084             offset = 0x62;
8085             break;
8086           default:
8087             GST_DEBUG_OBJECT (qtdemux, "unknown version 0x%08x", version);
8088             offset = 0;
8089             break;
8090         }
8091         if (offset) {
8092           if (length < offset) {
8093             GST_WARNING_OBJECT (qtdemux,
8094                 "skipping too small %" GST_FOURCC_FORMAT " box",
8095                 GST_FOURCC_ARGS (fourcc));
8096             break;
8097           }
8098           qtdemux_parse_container (qtdemux, node, buffer + offset, end);
8099         }
8100         break;
8101       }
8102       case FOURCC_in24:
8103       {
8104         qtdemux_parse_container (qtdemux, node, buffer + 0x34, end);
8105         break;
8106       }
8107       case FOURCC_uuid:
8108       {
8109         qtdemux_parse_uuid (qtdemux, buffer, end - buffer);
8110         break;
8111       }
8112       case FOURCC_enca:
8113       {
8114         qtdemux_parse_container (qtdemux, node, buffer + 36, end);
8115         break;
8116       }
8117       default:
8118         if (!strcmp (type->name, "unknown"))
8119           GST_MEMDUMP ("Unknown tag", buffer + 4, end - buffer - 4);
8120         break;
8121     }
8122   }
8123   GST_LOG_OBJECT (qtdemux, "parsed '%" GST_FOURCC_FORMAT "'",
8124       GST_FOURCC_ARGS (fourcc));
8125   return TRUE;
8126
8127 /* ERRORS */
8128 not_enough_data:
8129   {
8130     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
8131         (_("This file is corrupt and cannot be played.")),
8132         ("Not enough data for an atom header, got only %u bytes", length));
8133     return FALSE;
8134   }
8135 broken_atom_size:
8136   {
8137     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
8138         (_("This file is corrupt and cannot be played.")),
8139         ("Atom '%" GST_FOURCC_FORMAT "' has size of %u bytes, but we have only "
8140             "%u bytes available.", GST_FOURCC_ARGS (fourcc), node_length,
8141             length));
8142     return FALSE;
8143   }
8144 }
8145
8146 static GNode *
8147 qtdemux_tree_get_child_by_type (GNode * node, guint32 fourcc)
8148 {
8149   GNode *child;
8150   guint8 *buffer;
8151   guint32 child_fourcc;
8152
8153   for (child = g_node_first_child (node); child;
8154       child = g_node_next_sibling (child)) {
8155     buffer = (guint8 *) child->data;
8156
8157     child_fourcc = QT_FOURCC (buffer + 4);
8158
8159     if (G_UNLIKELY (child_fourcc == fourcc)) {
8160       return child;
8161     }
8162   }
8163   return NULL;
8164 }
8165
8166 static GNode *
8167 qtdemux_tree_get_child_by_type_full (GNode * node, guint32 fourcc,
8168     GstByteReader * parser)
8169 {
8170   GNode *child;
8171   guint8 *buffer;
8172   guint32 child_fourcc, child_len;
8173
8174   for (child = g_node_first_child (node); child;
8175       child = g_node_next_sibling (child)) {
8176     buffer = (guint8 *) child->data;
8177
8178     child_len = QT_UINT32 (buffer);
8179     child_fourcc = QT_FOURCC (buffer + 4);
8180
8181     if (G_UNLIKELY (child_fourcc == fourcc)) {
8182       if (G_UNLIKELY (child_len < (4 + 4)))
8183         return NULL;
8184       /* FIXME: must verify if atom length < parent atom length */
8185       gst_byte_reader_init (parser, buffer + (4 + 4), child_len - (4 + 4));
8186       return child;
8187     }
8188   }
8189   return NULL;
8190 }
8191
8192 static GNode *
8193 qtdemux_tree_get_child_by_index (GNode * node, guint index)
8194 {
8195   return g_node_nth_child (node, index);
8196 }
8197
8198 static GNode *
8199 qtdemux_tree_get_sibling_by_type_full (GNode * node, guint32 fourcc,
8200     GstByteReader * parser)
8201 {
8202   GNode *child;
8203   guint8 *buffer;
8204   guint32 child_fourcc, child_len;
8205
8206   for (child = g_node_next_sibling (node); child;
8207       child = g_node_next_sibling (child)) {
8208     buffer = (guint8 *) child->data;
8209
8210     child_fourcc = QT_FOURCC (buffer + 4);
8211
8212     if (child_fourcc == fourcc) {
8213       if (parser) {
8214         child_len = QT_UINT32 (buffer);
8215         if (G_UNLIKELY (child_len < (4 + 4)))
8216           return NULL;
8217         /* FIXME: must verify if atom length < parent atom length */
8218         gst_byte_reader_init (parser, buffer + (4 + 4), child_len - (4 + 4));
8219       }
8220       return child;
8221     }
8222   }
8223   return NULL;
8224 }
8225
8226 static GNode *
8227 qtdemux_tree_get_sibling_by_type (GNode * node, guint32 fourcc)
8228 {
8229   return qtdemux_tree_get_sibling_by_type_full (node, fourcc, NULL);
8230 }
8231
8232 static void
8233 qtdemux_do_allocation (QtDemuxStream * stream, GstQTDemux * qtdemux)
8234 {
8235 /* FIXME: This can only reliably work if demuxers have a
8236  * separate streaming thread per srcpad. This should be
8237  * done in a demuxer base class, which integrates parts
8238  * of multiqueue
8239  *
8240  * https://bugzilla.gnome.org/show_bug.cgi?id=701856
8241  */
8242 #if 0
8243   GstQuery *query;
8244
8245   query = gst_query_new_allocation (stream->caps, FALSE);
8246
8247   if (!gst_pad_peer_query (stream->pad, query)) {
8248     /* not a problem, just debug a little */
8249     GST_DEBUG_OBJECT (qtdemux, "peer ALLOCATION query failed");
8250   }
8251
8252   if (stream->allocator)
8253     gst_object_unref (stream->allocator);
8254
8255   if (gst_query_get_n_allocation_params (query) > 0) {
8256     /* try the allocator */
8257     gst_query_parse_nth_allocation_param (query, 0, &stream->allocator,
8258         &stream->params);
8259     stream->use_allocator = TRUE;
8260   } else {
8261     stream->allocator = NULL;
8262     gst_allocation_params_init (&stream->params);
8263     stream->use_allocator = FALSE;
8264   }
8265   gst_query_unref (query);
8266 #endif
8267 }
8268
8269 static gboolean
8270 pad_query (const GValue * item, GValue * value, gpointer user_data)
8271 {
8272   GstPad *pad = g_value_get_object (item);
8273   GstQuery *query = user_data;
8274   gboolean res;
8275
8276   res = gst_pad_peer_query (pad, query);
8277
8278   if (res) {
8279     g_value_set_boolean (value, TRUE);
8280     return FALSE;
8281   }
8282
8283   GST_INFO_OBJECT (pad, "pad peer query failed");
8284   return TRUE;
8285 }
8286
8287 static gboolean
8288 gst_qtdemux_run_query (GstElement * element, GstQuery * query,
8289     GstPadDirection direction)
8290 {
8291   GstIterator *it;
8292   GstIteratorFoldFunction func = pad_query;
8293   GValue res = { 0, };
8294
8295   g_value_init (&res, G_TYPE_BOOLEAN);
8296   g_value_set_boolean (&res, FALSE);
8297
8298   /* Ask neighbor */
8299   if (direction == GST_PAD_SRC)
8300     it = gst_element_iterate_src_pads (element);
8301   else
8302     it = gst_element_iterate_sink_pads (element);
8303
8304   while (gst_iterator_fold (it, func, &res, query) == GST_ITERATOR_RESYNC)
8305     gst_iterator_resync (it);
8306
8307   gst_iterator_free (it);
8308
8309   return g_value_get_boolean (&res);
8310 }
8311
8312 static void
8313 gst_qtdemux_request_protection_context (GstQTDemux * qtdemux,
8314     QtDemuxStream * stream)
8315 {
8316   GstQuery *query;
8317   GstContext *ctxt;
8318   GstElement *element = GST_ELEMENT (qtdemux);
8319   GstStructure *st;
8320   gchar **filtered_sys_ids;
8321   GValue event_list = G_VALUE_INIT;
8322   GList *walk;
8323
8324   /* 1. Check if we already have the context. */
8325   if (qtdemux->preferred_protection_system_id != NULL) {
8326     GST_LOG_OBJECT (element,
8327         "already have the protection context, no need to request it again");
8328     return;
8329   }
8330
8331   g_ptr_array_add (qtdemux->protection_system_ids, NULL);
8332   filtered_sys_ids = gst_protection_filter_systems_by_available_decryptors (
8333       (const gchar **) qtdemux->protection_system_ids->pdata);
8334
8335   g_ptr_array_remove_index (qtdemux->protection_system_ids,
8336       qtdemux->protection_system_ids->len - 1);
8337   GST_TRACE_OBJECT (qtdemux, "detected %u protection systems, we have "
8338       "decryptors for %u of them, running context request",
8339       qtdemux->protection_system_ids->len,
8340       filtered_sys_ids ? g_strv_length (filtered_sys_ids) : 0);
8341
8342
8343   if (stream->protection_scheme_event_queue.length) {
8344     GST_TRACE_OBJECT (qtdemux, "using stream event queue, length %u",
8345         stream->protection_scheme_event_queue.length);
8346     walk = stream->protection_scheme_event_queue.tail;
8347   } else {
8348     GST_TRACE_OBJECT (qtdemux, "using demuxer event queue, length %u",
8349         qtdemux->protection_event_queue.length);
8350     walk = qtdemux->protection_event_queue.tail;
8351   }
8352
8353   g_value_init (&event_list, GST_TYPE_LIST);
8354   for (; walk; walk = g_list_previous (walk)) {
8355     GValue *event_value = g_new0 (GValue, 1);
8356     g_value_init (event_value, GST_TYPE_EVENT);
8357     g_value_set_boxed (event_value, walk->data);
8358     gst_value_list_append_and_take_value (&event_list, event_value);
8359   }
8360
8361   /*  2a) Query downstream with GST_QUERY_CONTEXT for the context and
8362    *      check if downstream already has a context of the specific type
8363    *  2b) Query upstream as above.
8364    */
8365   query = gst_query_new_context ("drm-preferred-decryption-system-id");
8366   st = gst_query_writable_structure (query);
8367   gst_structure_set (st, "track-id", G_TYPE_UINT, stream->track_id,
8368       "available-stream-encryption-systems", G_TYPE_STRV, filtered_sys_ids,
8369       NULL);
8370   gst_structure_set_value (st, "stream-encryption-events", &event_list);
8371   if (gst_qtdemux_run_query (element, query, GST_PAD_SRC)) {
8372     gst_query_parse_context (query, &ctxt);
8373     GST_INFO_OBJECT (element, "found context (%p) in downstream query", ctxt);
8374     gst_element_set_context (element, ctxt);
8375   } else if (gst_qtdemux_run_query (element, query, GST_PAD_SINK)) {
8376     gst_query_parse_context (query, &ctxt);
8377     GST_INFO_OBJECT (element, "found context (%p) in upstream query", ctxt);
8378     gst_element_set_context (element, ctxt);
8379   } else {
8380     /* 3) Post a GST_MESSAGE_NEED_CONTEXT message on the bus with
8381      *    the required context type and afterwards check if a
8382      *    usable context was set now as in 1). The message could
8383      *    be handled by the parent bins of the element and the
8384      *    application.
8385      */
8386     GstMessage *msg;
8387
8388     GST_INFO_OBJECT (element, "posting need context message");
8389     msg = gst_message_new_need_context (GST_OBJECT_CAST (element),
8390         "drm-preferred-decryption-system-id");
8391     st = (GstStructure *) gst_message_get_structure (msg);
8392     gst_structure_set (st, "track-id", G_TYPE_UINT, stream->track_id,
8393         "available-stream-encryption-systems", G_TYPE_STRV, filtered_sys_ids,
8394         NULL);
8395
8396     gst_structure_set_value (st, "stream-encryption-events", &event_list);
8397     gst_element_post_message (element, msg);
8398   }
8399
8400   g_strfreev (filtered_sys_ids);
8401   g_value_unset (&event_list);
8402   gst_query_unref (query);
8403 }
8404
8405 static gboolean
8406 gst_qtdemux_configure_protected_caps (GstQTDemux * qtdemux,
8407     QtDemuxStream * stream)
8408 {
8409   GstStructure *s;
8410   const gchar *selected_system = NULL;
8411
8412   g_return_val_if_fail (qtdemux != NULL, FALSE);
8413   g_return_val_if_fail (stream != NULL, FALSE);
8414   g_return_val_if_fail (gst_caps_get_size (CUR_STREAM (stream)->caps) == 1,
8415       FALSE);
8416
8417   if (stream->protection_scheme_type != FOURCC_cenc) {
8418     GST_ERROR_OBJECT (qtdemux,
8419         "unsupported protection scheme: %" GST_FOURCC_FORMAT,
8420         GST_FOURCC_ARGS (stream->protection_scheme_type));
8421     return FALSE;
8422   }
8423   if (qtdemux->protection_system_ids == NULL) {
8424     GST_ERROR_OBJECT (qtdemux, "stream is protected using cenc, but no "
8425         "cenc protection system information has been found");
8426     return FALSE;
8427   }
8428
8429   gst_qtdemux_request_protection_context (qtdemux, stream);
8430   if (qtdemux->preferred_protection_system_id != NULL) {
8431     const gchar *preferred_system_array[] =
8432         { qtdemux->preferred_protection_system_id, NULL };
8433
8434     selected_system = gst_protection_select_system (preferred_system_array);
8435
8436     if (selected_system) {
8437       GST_TRACE_OBJECT (qtdemux, "selected preferred system %s",
8438           qtdemux->preferred_protection_system_id);
8439     } else {
8440       GST_WARNING_OBJECT (qtdemux, "could not select preferred system %s "
8441           "because there is no available decryptor",
8442           qtdemux->preferred_protection_system_id);
8443     }
8444   }
8445
8446   if (!selected_system) {
8447     g_ptr_array_add (qtdemux->protection_system_ids, NULL);
8448     selected_system = gst_protection_select_system ((const gchar **)
8449         qtdemux->protection_system_ids->pdata);
8450     g_ptr_array_remove_index (qtdemux->protection_system_ids,
8451         qtdemux->protection_system_ids->len - 1);
8452   }
8453
8454   if (!selected_system) {
8455     GST_ERROR_OBJECT (qtdemux, "stream is protected, but no "
8456         "suitable decryptor element has been found");
8457     return FALSE;
8458   }
8459
8460   GST_DEBUG_OBJECT (qtdemux, "selected protection system is %s",
8461       selected_system);
8462
8463   s = gst_caps_get_structure (CUR_STREAM (stream)->caps, 0);
8464   if (!gst_structure_has_name (s, "application/x-cenc")) {
8465     gst_structure_set (s,
8466         "original-media-type", G_TYPE_STRING, gst_structure_get_name (s),
8467         GST_PROTECTION_SYSTEM_ID_CAPS_FIELD, G_TYPE_STRING, selected_system,
8468         NULL);
8469     gst_structure_set_name (s, "application/x-cenc");
8470   }
8471   return TRUE;
8472 }
8473
8474 static gboolean
8475 gst_qtdemux_guess_framerate (GstQTDemux * qtdemux, QtDemuxStream * stream)
8476 {
8477   /* fps is calculated base on the duration of the average framerate since
8478    * qt does not have a fixed framerate. */
8479   gboolean fps_available = TRUE;
8480   guint32 first_duration = 0;
8481
8482   if (stream->n_samples > 0)
8483     first_duration = stream->samples[0].duration;
8484
8485   if ((stream->n_samples == 1 && first_duration == 0)
8486       || (qtdemux->fragmented && stream->n_samples_moof == 1)) {
8487     /* still frame */
8488     CUR_STREAM (stream)->fps_n = 0;
8489     CUR_STREAM (stream)->fps_d = 1;
8490   } else {
8491     if (stream->duration == 0 || stream->n_samples < 2) {
8492       CUR_STREAM (stream)->fps_n = stream->timescale;
8493       CUR_STREAM (stream)->fps_d = 1;
8494       fps_available = FALSE;
8495     } else {
8496       GstClockTime avg_duration;
8497       guint64 duration;
8498       guint32 n_samples;
8499
8500       /* duration and n_samples can be updated for fragmented format
8501        * so, framerate of fragmented format is calculated using data in a moof */
8502       if (qtdemux->fragmented && stream->n_samples_moof > 0
8503           && stream->duration_moof > 0) {
8504         n_samples = stream->n_samples_moof;
8505         duration = stream->duration_moof;
8506       } else {
8507         n_samples = stream->n_samples;
8508         duration = stream->duration;
8509       }
8510
8511       /* Calculate a framerate, ignoring the first sample which is sometimes truncated */
8512       /* stream->duration is guint64, timescale, n_samples are guint32 */
8513       avg_duration =
8514           gst_util_uint64_scale_round (duration -
8515           first_duration, GST_SECOND,
8516           (guint64) (stream->timescale) * (n_samples - 1));
8517
8518       GST_LOG_OBJECT (qtdemux,
8519           "Calculating avg sample duration based on stream (or moof) duration %"
8520           G_GUINT64_FORMAT
8521           " minus first sample %u, leaving %d samples gives %"
8522           GST_TIME_FORMAT, duration, first_duration,
8523           n_samples - 1, GST_TIME_ARGS (avg_duration));
8524
8525       fps_available =
8526           gst_video_guess_framerate (avg_duration,
8527           &CUR_STREAM (stream)->fps_n, &CUR_STREAM (stream)->fps_d);
8528
8529       GST_DEBUG_OBJECT (qtdemux,
8530           "Calculating framerate, timescale %u gave fps_n %d fps_d %d",
8531           stream->timescale, CUR_STREAM (stream)->fps_n,
8532           CUR_STREAM (stream)->fps_d);
8533     }
8534   }
8535
8536   return fps_available;
8537 }
8538
8539 static gboolean
8540 gst_qtdemux_configure_stream (GstQTDemux * qtdemux, QtDemuxStream * stream)
8541 {
8542   if (stream->subtype == FOURCC_vide) {
8543     gboolean fps_available = gst_qtdemux_guess_framerate (qtdemux, stream);
8544
8545     if (CUR_STREAM (stream)->caps) {
8546       CUR_STREAM (stream)->caps =
8547           gst_caps_make_writable (CUR_STREAM (stream)->caps);
8548
8549       if (CUR_STREAM (stream)->width && CUR_STREAM (stream)->height)
8550         gst_caps_set_simple (CUR_STREAM (stream)->caps,
8551             "width", G_TYPE_INT, CUR_STREAM (stream)->width,
8552             "height", G_TYPE_INT, CUR_STREAM (stream)->height, NULL);
8553
8554       /* set framerate if calculated framerate is reliable */
8555       if (fps_available) {
8556         gst_caps_set_simple (CUR_STREAM (stream)->caps,
8557             "framerate", GST_TYPE_FRACTION, CUR_STREAM (stream)->fps_n,
8558             CUR_STREAM (stream)->fps_d, NULL);
8559       }
8560
8561       /* calculate pixel-aspect-ratio using display width and height */
8562       GST_DEBUG_OBJECT (qtdemux,
8563           "video size %dx%d, target display size %dx%d",
8564           CUR_STREAM (stream)->width, CUR_STREAM (stream)->height,
8565           stream->display_width, stream->display_height);
8566       /* qt file might have pasp atom */
8567       if (CUR_STREAM (stream)->par_w > 0 && CUR_STREAM (stream)->par_h > 0) {
8568         GST_DEBUG_OBJECT (qtdemux, "par %d:%d", CUR_STREAM (stream)->par_w,
8569             CUR_STREAM (stream)->par_h);
8570         gst_caps_set_simple (CUR_STREAM (stream)->caps, "pixel-aspect-ratio",
8571             GST_TYPE_FRACTION, CUR_STREAM (stream)->par_w,
8572             CUR_STREAM (stream)->par_h, NULL);
8573       } else if (stream->display_width > 0 && stream->display_height > 0
8574           && CUR_STREAM (stream)->width > 0
8575           && CUR_STREAM (stream)->height > 0) {
8576         gint n, d;
8577
8578         /* calculate the pixel aspect ratio using the display and pixel w/h */
8579         n = stream->display_width * CUR_STREAM (stream)->height;
8580         d = stream->display_height * CUR_STREAM (stream)->width;
8581         if (n == d)
8582           n = d = 1;
8583         GST_DEBUG_OBJECT (qtdemux, "setting PAR to %d/%d", n, d);
8584         CUR_STREAM (stream)->par_w = n;
8585         CUR_STREAM (stream)->par_h = d;
8586         gst_caps_set_simple (CUR_STREAM (stream)->caps, "pixel-aspect-ratio",
8587             GST_TYPE_FRACTION, CUR_STREAM (stream)->par_w,
8588             CUR_STREAM (stream)->par_h, NULL);
8589       }
8590
8591       if (CUR_STREAM (stream)->interlace_mode > 0) {
8592         if (CUR_STREAM (stream)->interlace_mode == 1) {
8593           gst_caps_set_simple (CUR_STREAM (stream)->caps, "interlace-mode",
8594               G_TYPE_STRING, "progressive", NULL);
8595         } else if (CUR_STREAM (stream)->interlace_mode == 2) {
8596           gst_caps_set_simple (CUR_STREAM (stream)->caps, "interlace-mode",
8597               G_TYPE_STRING, "interleaved", NULL);
8598           if (CUR_STREAM (stream)->field_order == 9) {
8599             gst_caps_set_simple (CUR_STREAM (stream)->caps, "field-order",
8600                 G_TYPE_STRING, "top-field-first", NULL);
8601           } else if (CUR_STREAM (stream)->field_order == 14) {
8602             gst_caps_set_simple (CUR_STREAM (stream)->caps, "field-order",
8603                 G_TYPE_STRING, "bottom-field-first", NULL);
8604           }
8605         }
8606       }
8607
8608       /* Create incomplete colorimetry here if needed */
8609       if (CUR_STREAM (stream)->colorimetry.range ||
8610           CUR_STREAM (stream)->colorimetry.matrix ||
8611           CUR_STREAM (stream)->colorimetry.transfer
8612           || CUR_STREAM (stream)->colorimetry.primaries) {
8613         gchar *colorimetry =
8614             gst_video_colorimetry_to_string (&CUR_STREAM (stream)->colorimetry);
8615         gst_caps_set_simple (CUR_STREAM (stream)->caps, "colorimetry",
8616             G_TYPE_STRING, colorimetry, NULL);
8617         g_free (colorimetry);
8618       }
8619
8620       if (stream->multiview_mode != GST_VIDEO_MULTIVIEW_MODE_NONE) {
8621         guint par_w = 1, par_h = 1;
8622
8623         if (CUR_STREAM (stream)->par_w > 0 && CUR_STREAM (stream)->par_h > 0) {
8624           par_w = CUR_STREAM (stream)->par_w;
8625           par_h = CUR_STREAM (stream)->par_h;
8626         }
8627
8628         if (gst_video_multiview_guess_half_aspect (stream->multiview_mode,
8629                 CUR_STREAM (stream)->width, CUR_STREAM (stream)->height, par_w,
8630                 par_h)) {
8631           stream->multiview_flags |= GST_VIDEO_MULTIVIEW_FLAGS_HALF_ASPECT;
8632         }
8633
8634         gst_caps_set_simple (CUR_STREAM (stream)->caps,
8635             "multiview-mode", G_TYPE_STRING,
8636             gst_video_multiview_mode_to_caps_string (stream->multiview_mode),
8637             "multiview-flags", GST_TYPE_VIDEO_MULTIVIEW_FLAGSET,
8638             stream->multiview_flags, GST_FLAG_SET_MASK_EXACT, NULL);
8639       }
8640     }
8641   }
8642
8643   else if (stream->subtype == FOURCC_soun) {
8644     if (CUR_STREAM (stream)->caps) {
8645       CUR_STREAM (stream)->caps =
8646           gst_caps_make_writable (CUR_STREAM (stream)->caps);
8647       if (CUR_STREAM (stream)->rate > 0)
8648         gst_caps_set_simple (CUR_STREAM (stream)->caps,
8649             "rate", G_TYPE_INT, (int) CUR_STREAM (stream)->rate, NULL);
8650       if (CUR_STREAM (stream)->n_channels > 0)
8651         gst_caps_set_simple (CUR_STREAM (stream)->caps,
8652             "channels", G_TYPE_INT, CUR_STREAM (stream)->n_channels, NULL);
8653       if (CUR_STREAM (stream)->n_channels > 2) {
8654         /* FIXME: Need to parse the 'chan' atom to get channel layouts
8655          * correctly; this is just the minimum we can do - assume
8656          * we don't actually have any channel positions. */
8657         gst_caps_set_simple (CUR_STREAM (stream)->caps,
8658             "channel-mask", GST_TYPE_BITMASK, G_GUINT64_CONSTANT (0), NULL);
8659       }
8660     }
8661   }
8662
8663   else if (stream->subtype == FOURCC_clcp && CUR_STREAM (stream)->caps) {
8664     const GstStructure *s;
8665     QtDemuxStream *fps_stream = NULL;
8666     gboolean fps_available = FALSE;
8667
8668     /* CEA608 closed caption tracks are a bit special in that each sample
8669      * can contain CCs for multiple frames, and CCs can be omitted and have to
8670      * be inferred from the duration of the sample then.
8671      *
8672      * As such we take the framerate from the (first) video track here for
8673      * CEA608 as there must be one CC byte pair for every video frame
8674      * according to the spec.
8675      *
8676      * For CEA708 all is fine and there is one sample per frame.
8677      */
8678
8679     s = gst_caps_get_structure (CUR_STREAM (stream)->caps, 0);
8680     if (gst_structure_has_name (s, "closedcaption/x-cea-608")) {
8681       gint i;
8682
8683       for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
8684         QtDemuxStream *tmp = QTDEMUX_NTH_STREAM (qtdemux, i);
8685
8686         if (tmp->subtype == FOURCC_vide) {
8687           fps_stream = tmp;
8688           break;
8689         }
8690       }
8691
8692       if (fps_stream) {
8693         fps_available = gst_qtdemux_guess_framerate (qtdemux, fps_stream);
8694         CUR_STREAM (stream)->fps_n = CUR_STREAM (fps_stream)->fps_n;
8695         CUR_STREAM (stream)->fps_d = CUR_STREAM (fps_stream)->fps_d;
8696       }
8697     } else {
8698       fps_available = gst_qtdemux_guess_framerate (qtdemux, stream);
8699       fps_stream = stream;
8700     }
8701
8702     CUR_STREAM (stream)->caps =
8703         gst_caps_make_writable (CUR_STREAM (stream)->caps);
8704
8705     /* set framerate if calculated framerate is reliable */
8706     if (fps_available) {
8707       gst_caps_set_simple (CUR_STREAM (stream)->caps,
8708           "framerate", GST_TYPE_FRACTION, CUR_STREAM (stream)->fps_n,
8709           CUR_STREAM (stream)->fps_d, NULL);
8710     }
8711   }
8712
8713   if (stream->pad) {
8714     GstCaps *prev_caps = NULL;
8715
8716     GST_PAD_ELEMENT_PRIVATE (stream->pad) = stream;
8717     gst_pad_set_event_function (stream->pad, gst_qtdemux_handle_src_event);
8718     gst_pad_set_query_function (stream->pad, gst_qtdemux_handle_src_query);
8719     gst_pad_set_active (stream->pad, TRUE);
8720
8721     gst_pad_use_fixed_caps (stream->pad);
8722
8723     if (stream->protected) {
8724       if (!gst_qtdemux_configure_protected_caps (qtdemux, stream)) {
8725         GST_ERROR_OBJECT (qtdemux,
8726             "Failed to configure protected stream caps.");
8727         return FALSE;
8728       }
8729     }
8730
8731     GST_DEBUG_OBJECT (qtdemux, "setting caps %" GST_PTR_FORMAT,
8732         CUR_STREAM (stream)->caps);
8733     if (stream->new_stream) {
8734       GstEvent *event;
8735       GstStreamFlags stream_flags = GST_STREAM_FLAG_NONE;
8736
8737       event =
8738           gst_pad_get_sticky_event (qtdemux->sinkpad, GST_EVENT_STREAM_START,
8739           0);
8740       if (event) {
8741         gst_event_parse_stream_flags (event, &stream_flags);
8742         if (gst_event_parse_group_id (event, &qtdemux->group_id))
8743           qtdemux->have_group_id = TRUE;
8744         else
8745           qtdemux->have_group_id = FALSE;
8746         gst_event_unref (event);
8747       } else if (!qtdemux->have_group_id) {
8748         qtdemux->have_group_id = TRUE;
8749         qtdemux->group_id = gst_util_group_id_next ();
8750       }
8751
8752       stream->new_stream = FALSE;
8753       event = gst_event_new_stream_start (stream->stream_id);
8754       if (qtdemux->have_group_id)
8755         gst_event_set_group_id (event, qtdemux->group_id);
8756       if (stream->disabled)
8757         stream_flags |= GST_STREAM_FLAG_UNSELECT;
8758       if (CUR_STREAM (stream)->sparse) {
8759         stream_flags |= GST_STREAM_FLAG_SPARSE;
8760       } else {
8761         stream_flags &= ~GST_STREAM_FLAG_SPARSE;
8762       }
8763       gst_event_set_stream_flags (event, stream_flags);
8764       gst_pad_push_event (stream->pad, event);
8765     }
8766
8767     prev_caps = gst_pad_get_current_caps (stream->pad);
8768
8769     if (CUR_STREAM (stream)->caps) {
8770       if (!prev_caps
8771           || !gst_caps_is_equal_fixed (prev_caps, CUR_STREAM (stream)->caps)) {
8772         GST_DEBUG_OBJECT (qtdemux, "setting caps %" GST_PTR_FORMAT,
8773             CUR_STREAM (stream)->caps);
8774         gst_pad_set_caps (stream->pad, CUR_STREAM (stream)->caps);
8775       } else {
8776         GST_DEBUG_OBJECT (qtdemux, "ignore duplicated caps");
8777       }
8778     } else {
8779       GST_WARNING_OBJECT (qtdemux, "stream without caps");
8780     }
8781
8782     if (prev_caps)
8783       gst_caps_unref (prev_caps);
8784     stream->new_caps = FALSE;
8785   }
8786   return TRUE;
8787 }
8788
8789 static void
8790 gst_qtdemux_stream_check_and_change_stsd_index (GstQTDemux * demux,
8791     QtDemuxStream * stream)
8792 {
8793   if (stream->cur_stsd_entry_index == stream->stsd_sample_description_id)
8794     return;
8795
8796   GST_DEBUG_OBJECT (stream->pad, "Changing stsd index from '%u' to '%u'",
8797       stream->cur_stsd_entry_index, stream->stsd_sample_description_id);
8798   if (G_UNLIKELY (stream->stsd_sample_description_id >=
8799           stream->stsd_entries_length)) {
8800     GST_ELEMENT_ERROR (demux, STREAM, DEMUX,
8801         (_("This file is invalid and cannot be played.")),
8802         ("New sample description id is out of bounds (%d >= %d)",
8803             stream->stsd_sample_description_id, stream->stsd_entries_length));
8804   } else {
8805     stream->cur_stsd_entry_index = stream->stsd_sample_description_id;
8806     stream->new_caps = TRUE;
8807   }
8808 }
8809
8810 static gboolean
8811 gst_qtdemux_add_stream (GstQTDemux * qtdemux,
8812     QtDemuxStream * stream, GstTagList * list)
8813 {
8814   gboolean ret = TRUE;
8815
8816   if (stream->subtype == FOURCC_vide) {
8817     gchar *name = g_strdup_printf ("video_%u", qtdemux->n_video_streams);
8818
8819     stream->pad =
8820         gst_pad_new_from_static_template (&gst_qtdemux_videosrc_template, name);
8821     g_free (name);
8822
8823     if (!gst_qtdemux_configure_stream (qtdemux, stream)) {
8824       gst_object_unref (stream->pad);
8825       stream->pad = NULL;
8826       ret = FALSE;
8827       goto done;
8828     }
8829
8830     qtdemux->n_video_streams++;
8831   } else if (stream->subtype == FOURCC_soun) {
8832     gchar *name = g_strdup_printf ("audio_%u", qtdemux->n_audio_streams);
8833
8834     stream->pad =
8835         gst_pad_new_from_static_template (&gst_qtdemux_audiosrc_template, name);
8836     g_free (name);
8837     if (!gst_qtdemux_configure_stream (qtdemux, stream)) {
8838       gst_object_unref (stream->pad);
8839       stream->pad = NULL;
8840       ret = FALSE;
8841       goto done;
8842     }
8843     qtdemux->n_audio_streams++;
8844   } else if (stream->subtype == FOURCC_strm) {
8845     GST_DEBUG_OBJECT (qtdemux, "stream type, not creating pad");
8846   } else if (stream->subtype == FOURCC_subp || stream->subtype == FOURCC_text
8847       || stream->subtype == FOURCC_sbtl || stream->subtype == FOURCC_subt
8848       || stream->subtype == FOURCC_clcp) {
8849     gchar *name = g_strdup_printf ("subtitle_%u", qtdemux->n_sub_streams);
8850
8851     stream->pad =
8852         gst_pad_new_from_static_template (&gst_qtdemux_subsrc_template, name);
8853     g_free (name);
8854     if (!gst_qtdemux_configure_stream (qtdemux, stream)) {
8855       gst_object_unref (stream->pad);
8856       stream->pad = NULL;
8857       ret = FALSE;
8858       goto done;
8859     }
8860     qtdemux->n_sub_streams++;
8861   } else if (CUR_STREAM (stream)->caps) {
8862     gchar *name = g_strdup_printf ("video_%u", qtdemux->n_video_streams);
8863
8864     stream->pad =
8865         gst_pad_new_from_static_template (&gst_qtdemux_videosrc_template, name);
8866     g_free (name);
8867     if (!gst_qtdemux_configure_stream (qtdemux, stream)) {
8868       gst_object_unref (stream->pad);
8869       stream->pad = NULL;
8870       ret = FALSE;
8871       goto done;
8872     }
8873     qtdemux->n_video_streams++;
8874   } else {
8875     GST_DEBUG_OBJECT (qtdemux, "unknown stream type");
8876     goto done;
8877   }
8878
8879   if (stream->pad) {
8880     GList *l;
8881
8882     GST_DEBUG_OBJECT (qtdemux, "adding pad %s %p to qtdemux %p",
8883         GST_OBJECT_NAME (stream->pad), stream->pad, qtdemux);
8884     gst_element_add_pad (GST_ELEMENT_CAST (qtdemux), stream->pad);
8885     gst_flow_combiner_add_pad (qtdemux->flowcombiner, stream->pad);
8886
8887     if (stream->stream_tags)
8888       gst_tag_list_unref (stream->stream_tags);
8889     stream->stream_tags = list;
8890     list = NULL;
8891     /* global tags go on each pad anyway */
8892     stream->send_global_tags = TRUE;
8893     /* send upstream GST_EVENT_PROTECTION events that were received before
8894        this source pad was created */
8895     for (l = qtdemux->protection_event_queue.head; l != NULL; l = l->next)
8896       gst_pad_push_event (stream->pad, gst_event_ref (l->data));
8897   }
8898 done:
8899   if (list)
8900     gst_tag_list_unref (list);
8901   return ret;
8902 }
8903
8904 /* find next atom with @fourcc starting at @offset */
8905 static GstFlowReturn
8906 qtdemux_find_atom (GstQTDemux * qtdemux, guint64 * offset,
8907     guint64 * length, guint32 fourcc)
8908 {
8909   GstFlowReturn ret;
8910   guint32 lfourcc;
8911   GstBuffer *buf;
8912
8913   GST_LOG_OBJECT (qtdemux, "finding fourcc %" GST_FOURCC_FORMAT " at offset %"
8914       G_GUINT64_FORMAT, GST_FOURCC_ARGS (fourcc), *offset);
8915
8916   while (TRUE) {
8917     GstMapInfo map;
8918
8919     buf = NULL;
8920     ret = gst_pad_pull_range (qtdemux->sinkpad, *offset, 16, &buf);
8921     if (G_UNLIKELY (ret != GST_FLOW_OK))
8922       goto locate_failed;
8923     if (G_UNLIKELY (gst_buffer_get_size (buf) != 16)) {
8924       /* likely EOF */
8925       ret = GST_FLOW_EOS;
8926       gst_buffer_unref (buf);
8927       goto locate_failed;
8928     }
8929     gst_buffer_map (buf, &map, GST_MAP_READ);
8930     extract_initial_length_and_fourcc (map.data, 16, length, &lfourcc);
8931     gst_buffer_unmap (buf, &map);
8932     gst_buffer_unref (buf);
8933
8934     if (G_UNLIKELY (*length == 0)) {
8935       GST_DEBUG_OBJECT (qtdemux, "invalid length 0");
8936       ret = GST_FLOW_ERROR;
8937       goto locate_failed;
8938     }
8939
8940     if (lfourcc == fourcc) {
8941       GST_DEBUG_OBJECT (qtdemux, "found fourcc at offset %" G_GUINT64_FORMAT,
8942           *offset);
8943       break;
8944     } else {
8945       GST_LOG_OBJECT (qtdemux,
8946           "skipping atom '%" GST_FOURCC_FORMAT "' at %" G_GUINT64_FORMAT,
8947           GST_FOURCC_ARGS (fourcc), *offset);
8948       *offset += *length;
8949     }
8950   }
8951
8952   return GST_FLOW_OK;
8953
8954 locate_failed:
8955   {
8956     /* might simply have had last one */
8957     GST_DEBUG_OBJECT (qtdemux, "fourcc not found");
8958     return ret;
8959   }
8960 }
8961
8962 /* should only do something in pull mode */
8963 /* call with OBJECT lock */
8964 static GstFlowReturn
8965 qtdemux_add_fragmented_samples (GstQTDemux * qtdemux)
8966 {
8967   guint64 length, offset;
8968   GstBuffer *buf = NULL;
8969   GstFlowReturn ret = GST_FLOW_OK;
8970   GstFlowReturn res = GST_FLOW_OK;
8971   GstMapInfo map;
8972
8973   offset = qtdemux->moof_offset;
8974   GST_DEBUG_OBJECT (qtdemux, "next moof at offset %" G_GUINT64_FORMAT, offset);
8975
8976   if (!offset) {
8977     GST_DEBUG_OBJECT (qtdemux, "no next moof");
8978     return GST_FLOW_EOS;
8979   }
8980
8981   /* best not do pull etc with lock held */
8982   GST_OBJECT_UNLOCK (qtdemux);
8983
8984   ret = qtdemux_find_atom (qtdemux, &offset, &length, FOURCC_moof);
8985   if (ret != GST_FLOW_OK)
8986     goto flow_failed;
8987
8988   ret = gst_qtdemux_pull_atom (qtdemux, offset, length, &buf);
8989   if (G_UNLIKELY (ret != GST_FLOW_OK))
8990     goto flow_failed;
8991   gst_buffer_map (buf, &map, GST_MAP_READ);
8992   if (!qtdemux_parse_moof (qtdemux, map.data, map.size, offset, NULL)) {
8993     gst_buffer_unmap (buf, &map);
8994     gst_buffer_unref (buf);
8995     buf = NULL;
8996     goto parse_failed;
8997   }
8998
8999   gst_buffer_unmap (buf, &map);
9000   gst_buffer_unref (buf);
9001   buf = NULL;
9002
9003   offset += length;
9004   /* look for next moof */
9005   ret = qtdemux_find_atom (qtdemux, &offset, &length, FOURCC_moof);
9006   if (G_UNLIKELY (ret != GST_FLOW_OK))
9007     goto flow_failed;
9008
9009 exit:
9010   GST_OBJECT_LOCK (qtdemux);
9011
9012   qtdemux->moof_offset = offset;
9013
9014   return res;
9015
9016 parse_failed:
9017   {
9018     GST_DEBUG_OBJECT (qtdemux, "failed to parse moof");
9019     offset = 0;
9020     res = GST_FLOW_ERROR;
9021     goto exit;
9022   }
9023 flow_failed:
9024   {
9025     /* maybe upstream temporarily flushing */
9026     if (ret != GST_FLOW_FLUSHING) {
9027       GST_DEBUG_OBJECT (qtdemux, "no next moof");
9028       offset = 0;
9029     } else {
9030       GST_DEBUG_OBJECT (qtdemux, "upstream WRONG_STATE");
9031       /* resume at current position next time */
9032     }
9033     res = ret;
9034     goto exit;
9035   }
9036 }
9037
9038 /* initialise bytereaders for stbl sub-atoms */
9039 static gboolean
9040 qtdemux_stbl_init (GstQTDemux * qtdemux, QtDemuxStream * stream, GNode * stbl)
9041 {
9042   stream->stbl_index = -1;      /* no samples have yet been parsed */
9043   stream->sample_index = -1;
9044
9045   /* time-to-sample atom */
9046   if (!qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stts, &stream->stts))
9047     goto corrupt_file;
9048
9049   /* copy atom data into a new buffer for later use */
9050   stream->stts.data = g_memdup (stream->stts.data, stream->stts.size);
9051
9052   /* skip version + flags */
9053   if (!gst_byte_reader_skip (&stream->stts, 1 + 3) ||
9054       !gst_byte_reader_get_uint32_be (&stream->stts, &stream->n_sample_times))
9055     goto corrupt_file;
9056   GST_LOG_OBJECT (qtdemux, "%u timestamp blocks", stream->n_sample_times);
9057
9058   /* make sure there's enough data */
9059   if (!qt_atom_parser_has_chunks (&stream->stts, stream->n_sample_times, 8)) {
9060     stream->n_sample_times = gst_byte_reader_get_remaining (&stream->stts) / 8;
9061     GST_LOG_OBJECT (qtdemux, "overriding to %u timestamp blocks",
9062         stream->n_sample_times);
9063     if (!stream->n_sample_times)
9064       goto corrupt_file;
9065   }
9066
9067   /* sync sample atom */
9068   stream->stps_present = FALSE;
9069   if ((stream->stss_present =
9070           ! !qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stss,
9071               &stream->stss) ? TRUE : FALSE) == TRUE) {
9072     /* copy atom data into a new buffer for later use */
9073     stream->stss.data = g_memdup (stream->stss.data, stream->stss.size);
9074
9075     /* skip version + flags */
9076     if (!gst_byte_reader_skip (&stream->stss, 1 + 3) ||
9077         !gst_byte_reader_get_uint32_be (&stream->stss, &stream->n_sample_syncs))
9078       goto corrupt_file;
9079
9080     if (stream->n_sample_syncs) {
9081       /* make sure there's enough data */
9082       if (!qt_atom_parser_has_chunks (&stream->stss, stream->n_sample_syncs, 4))
9083         goto corrupt_file;
9084     }
9085
9086     /* partial sync sample atom */
9087     if ((stream->stps_present =
9088             ! !qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stps,
9089                 &stream->stps) ? TRUE : FALSE) == TRUE) {
9090       /* copy atom data into a new buffer for later use */
9091       stream->stps.data = g_memdup (stream->stps.data, stream->stps.size);
9092
9093       /* skip version + flags */
9094       if (!gst_byte_reader_skip (&stream->stps, 1 + 3) ||
9095           !gst_byte_reader_get_uint32_be (&stream->stps,
9096               &stream->n_sample_partial_syncs))
9097         goto corrupt_file;
9098
9099       /* if there are no entries, the stss table contains the real
9100        * sync samples */
9101       if (stream->n_sample_partial_syncs) {
9102         /* make sure there's enough data */
9103         if (!qt_atom_parser_has_chunks (&stream->stps,
9104                 stream->n_sample_partial_syncs, 4))
9105           goto corrupt_file;
9106       }
9107     }
9108   }
9109
9110   /* sample size */
9111   if (!qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stsz, &stream->stsz))
9112     goto no_samples;
9113
9114   /* copy atom data into a new buffer for later use */
9115   stream->stsz.data = g_memdup (stream->stsz.data, stream->stsz.size);
9116
9117   /* skip version + flags */
9118   if (!gst_byte_reader_skip (&stream->stsz, 1 + 3) ||
9119       !gst_byte_reader_get_uint32_be (&stream->stsz, &stream->sample_size))
9120     goto corrupt_file;
9121
9122   if (!gst_byte_reader_get_uint32_be (&stream->stsz, &stream->n_samples))
9123     goto corrupt_file;
9124
9125   if (!stream->n_samples)
9126     goto no_samples;
9127
9128   /* sample-to-chunk atom */
9129   if (!qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stsc, &stream->stsc))
9130     goto corrupt_file;
9131
9132   /* copy atom data into a new buffer for later use */
9133   stream->stsc.data = g_memdup (stream->stsc.data, stream->stsc.size);
9134
9135   /* skip version + flags */
9136   if (!gst_byte_reader_skip (&stream->stsc, 1 + 3) ||
9137       !gst_byte_reader_get_uint32_be (&stream->stsc,
9138           &stream->n_samples_per_chunk))
9139     goto corrupt_file;
9140
9141   GST_DEBUG_OBJECT (qtdemux, "n_samples_per_chunk %u",
9142       stream->n_samples_per_chunk);
9143
9144   /* make sure there's enough data */
9145   if (!qt_atom_parser_has_chunks (&stream->stsc, stream->n_samples_per_chunk,
9146           12))
9147     goto corrupt_file;
9148
9149
9150   /* chunk offset */
9151   if (qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stco, &stream->stco))
9152     stream->co_size = sizeof (guint32);
9153   else if (qtdemux_tree_get_child_by_type_full (stbl, FOURCC_co64,
9154           &stream->stco))
9155     stream->co_size = sizeof (guint64);
9156   else
9157     goto corrupt_file;
9158
9159   /* copy atom data into a new buffer for later use */
9160   stream->stco.data = g_memdup (stream->stco.data, stream->stco.size);
9161
9162   /* skip version + flags */
9163   if (!gst_byte_reader_skip (&stream->stco, 1 + 3))
9164     goto corrupt_file;
9165
9166   /* chunks_are_samples == TRUE means treat chunks as samples */
9167   stream->chunks_are_samples = stream->sample_size
9168       && !CUR_STREAM (stream)->sampled;
9169   if (stream->chunks_are_samples) {
9170     /* treat chunks as samples */
9171     if (!gst_byte_reader_get_uint32_be (&stream->stco, &stream->n_samples))
9172       goto corrupt_file;
9173   } else {
9174     /* skip number of entries */
9175     if (!gst_byte_reader_skip (&stream->stco, 4))
9176       goto corrupt_file;
9177
9178     /* make sure there are enough data in the stsz atom */
9179     if (!stream->sample_size) {
9180       /* different sizes for each sample */
9181       if (!qt_atom_parser_has_chunks (&stream->stsz, stream->n_samples, 4))
9182         goto corrupt_file;
9183     }
9184   }
9185
9186   GST_DEBUG_OBJECT (qtdemux, "allocating n_samples %u * %u (%.2f MB)",
9187       stream->n_samples, (guint) sizeof (QtDemuxSample),
9188       stream->n_samples * sizeof (QtDemuxSample) / (1024.0 * 1024.0));
9189
9190   if (stream->n_samples >=
9191       QTDEMUX_MAX_SAMPLE_INDEX_SIZE / sizeof (QtDemuxSample)) {
9192     GST_WARNING_OBJECT (qtdemux, "not allocating index of %d samples, would "
9193         "be larger than %uMB (broken file?)", stream->n_samples,
9194         QTDEMUX_MAX_SAMPLE_INDEX_SIZE >> 20);
9195     return FALSE;
9196   }
9197
9198   g_assert (stream->samples == NULL);
9199   stream->samples = g_try_new0 (QtDemuxSample, stream->n_samples);
9200   if (!stream->samples) {
9201     GST_WARNING_OBJECT (qtdemux, "failed to allocate %d samples",
9202         stream->n_samples);
9203     return FALSE;
9204   }
9205
9206   /* composition time-to-sample */
9207   if ((stream->ctts_present =
9208           ! !qtdemux_tree_get_child_by_type_full (stbl, FOURCC_ctts,
9209               &stream->ctts) ? TRUE : FALSE) == TRUE) {
9210     GstByteReader cslg = GST_BYTE_READER_INIT (NULL, 0);
9211
9212     /* copy atom data into a new buffer for later use */
9213     stream->ctts.data = g_memdup (stream->ctts.data, stream->ctts.size);
9214
9215     /* skip version + flags */
9216     if (!gst_byte_reader_skip (&stream->ctts, 1 + 3)
9217         || !gst_byte_reader_get_uint32_be (&stream->ctts,
9218             &stream->n_composition_times))
9219       goto corrupt_file;
9220
9221     /* make sure there's enough data */
9222     if (!qt_atom_parser_has_chunks (&stream->ctts, stream->n_composition_times,
9223             4 + 4))
9224       goto corrupt_file;
9225
9226     /* This is optional, if missing we iterate the ctts */
9227     if (qtdemux_tree_get_child_by_type_full (stbl, FOURCC_cslg, &cslg)) {
9228       if (!gst_byte_reader_skip (&cslg, 1 + 3)
9229           || !gst_byte_reader_get_uint32_be (&cslg, &stream->cslg_shift)) {
9230         g_free ((gpointer) cslg.data);
9231         goto corrupt_file;
9232       }
9233     } else {
9234       gint32 cslg_least = 0;
9235       guint num_entries, pos;
9236       gint i;
9237
9238       pos = gst_byte_reader_get_pos (&stream->ctts);
9239       num_entries = stream->n_composition_times;
9240
9241       stream->cslg_shift = 0;
9242
9243       for (i = 0; i < num_entries; i++) {
9244         gint32 offset;
9245
9246         gst_byte_reader_skip_unchecked (&stream->ctts, 4);
9247         offset = gst_byte_reader_get_int32_be_unchecked (&stream->ctts);
9248         /* HACK: if sample_offset is larger than 2 * duration, ignore the box.
9249          * slightly inaccurate PTS could be more usable than corrupted one */
9250         if (G_UNLIKELY ((ABS (offset) / 2) > stream->duration)) {
9251           GST_WARNING_OBJECT (qtdemux,
9252               "Ignore corrupted ctts, sample_offset %" G_GINT32_FORMAT
9253               " larger than duration %" G_GUINT64_FORMAT,
9254               offset, stream->duration);
9255
9256           stream->cslg_shift = 0;
9257           stream->ctts_present = FALSE;
9258           return TRUE;
9259         }
9260
9261         if (offset < cslg_least)
9262           cslg_least = offset;
9263       }
9264
9265       if (cslg_least < 0)
9266         stream->cslg_shift = ABS (cslg_least);
9267       else
9268         stream->cslg_shift = 0;
9269
9270       /* reset the reader so we can generate sample table */
9271       gst_byte_reader_set_pos (&stream->ctts, pos);
9272     }
9273   } else {
9274     /* Ensure the cslg_shift value is consistent so we can use it
9275      * unconditionnally to produce TS and Segment */
9276     stream->cslg_shift = 0;
9277   }
9278
9279   return TRUE;
9280
9281 corrupt_file:
9282   {
9283     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
9284         (_("This file is corrupt and cannot be played.")), (NULL));
9285     return FALSE;
9286   }
9287 no_samples:
9288   {
9289     gst_qtdemux_stbl_free (stream);
9290     if (!qtdemux->fragmented) {
9291       /* not quite good */
9292       GST_WARNING_OBJECT (qtdemux, "stream has no samples");
9293       return FALSE;
9294     } else {
9295       /* may pick up samples elsewhere */
9296       return TRUE;
9297     }
9298   }
9299 }
9300
9301 /* collect samples from the next sample to be parsed up to sample @n for @stream
9302  * by reading the info from @stbl
9303  *
9304  * This code can be executed from both the streaming thread and the seeking
9305  * thread so it takes the object lock to protect itself
9306  */
9307 static gboolean
9308 qtdemux_parse_samples (GstQTDemux * qtdemux, QtDemuxStream * stream, guint32 n)
9309 {
9310   gint i, j, k;
9311   QtDemuxSample *samples, *first, *cur, *last;
9312   guint32 n_samples_per_chunk;
9313   guint32 n_samples;
9314
9315   GST_LOG_OBJECT (qtdemux, "parsing samples for stream fourcc %"
9316       GST_FOURCC_FORMAT ", pad %s",
9317       GST_FOURCC_ARGS (CUR_STREAM (stream)->fourcc),
9318       stream->pad ? GST_PAD_NAME (stream->pad) : "(NULL)");
9319
9320   n_samples = stream->n_samples;
9321
9322   if (n >= n_samples)
9323     goto out_of_samples;
9324
9325   GST_OBJECT_LOCK (qtdemux);
9326   if (n <= stream->stbl_index)
9327     goto already_parsed;
9328
9329   GST_DEBUG_OBJECT (qtdemux, "parsing up to sample %u", n);
9330
9331   if (!stream->stsz.data) {
9332     /* so we already parsed and passed all the moov samples;
9333      * onto fragmented ones */
9334     g_assert (qtdemux->fragmented);
9335     goto done;
9336   }
9337
9338   /* pointer to the sample table */
9339   samples = stream->samples;
9340
9341   /* starts from -1, moves to the next sample index to parse */
9342   stream->stbl_index++;
9343
9344   /* keep track of the first and last sample to fill */
9345   first = &samples[stream->stbl_index];
9346   last = &samples[n];
9347
9348   if (!stream->chunks_are_samples) {
9349     /* set the sample sizes */
9350     if (stream->sample_size == 0) {
9351       /* different sizes for each sample */
9352       for (cur = first; cur <= last; cur++) {
9353         cur->size = gst_byte_reader_get_uint32_be_unchecked (&stream->stsz);
9354         GST_LOG_OBJECT (qtdemux, "sample %d has size %u",
9355             (guint) (cur - samples), cur->size);
9356       }
9357     } else {
9358       /* samples have the same size */
9359       GST_LOG_OBJECT (qtdemux, "all samples have size %u", stream->sample_size);
9360       for (cur = first; cur <= last; cur++)
9361         cur->size = stream->sample_size;
9362     }
9363   }
9364
9365   n_samples_per_chunk = stream->n_samples_per_chunk;
9366   cur = first;
9367
9368   for (i = stream->stsc_index; i < n_samples_per_chunk; i++) {
9369     guint32 last_chunk;
9370
9371     if (stream->stsc_chunk_index >= stream->last_chunk
9372         || stream->stsc_chunk_index < stream->first_chunk) {
9373       stream->first_chunk =
9374           gst_byte_reader_get_uint32_be_unchecked (&stream->stsc);
9375       stream->samples_per_chunk =
9376           gst_byte_reader_get_uint32_be_unchecked (&stream->stsc);
9377       /* starts from 1 */
9378       stream->stsd_sample_description_id =
9379           gst_byte_reader_get_uint32_be_unchecked (&stream->stsc) - 1;
9380
9381       /* chunk numbers are counted from 1 it seems */
9382       if (G_UNLIKELY (stream->first_chunk == 0))
9383         goto corrupt_file;
9384
9385       --stream->first_chunk;
9386
9387       /* the last chunk of each entry is calculated by taking the first chunk
9388        * of the next entry; except if there is no next, where we fake it with
9389        * INT_MAX */
9390       if (G_UNLIKELY (i == (stream->n_samples_per_chunk - 1))) {
9391         stream->last_chunk = G_MAXUINT32;
9392       } else {
9393         stream->last_chunk =
9394             gst_byte_reader_peek_uint32_be_unchecked (&stream->stsc);
9395         if (G_UNLIKELY (stream->last_chunk == 0))
9396           goto corrupt_file;
9397
9398         --stream->last_chunk;
9399       }
9400
9401       GST_LOG_OBJECT (qtdemux,
9402           "entry %d has first_chunk %d, last_chunk %d, samples_per_chunk %d"
9403           "sample desc ID: %d", i, stream->first_chunk, stream->last_chunk,
9404           stream->samples_per_chunk, stream->stsd_sample_description_id);
9405
9406       if (G_UNLIKELY (stream->last_chunk < stream->first_chunk))
9407         goto corrupt_file;
9408
9409       if (stream->last_chunk != G_MAXUINT32) {
9410         if (!qt_atom_parser_peek_sub (&stream->stco,
9411                 stream->first_chunk * stream->co_size,
9412                 (stream->last_chunk - stream->first_chunk) * stream->co_size,
9413                 &stream->co_chunk))
9414           goto corrupt_file;
9415
9416       } else {
9417         stream->co_chunk = stream->stco;
9418         if (!gst_byte_reader_skip (&stream->co_chunk,
9419                 stream->first_chunk * stream->co_size))
9420           goto corrupt_file;
9421       }
9422
9423       stream->stsc_chunk_index = stream->first_chunk;
9424     }
9425
9426     last_chunk = stream->last_chunk;
9427
9428     if (stream->chunks_are_samples) {
9429       cur = &samples[stream->stsc_chunk_index];
9430
9431       for (j = stream->stsc_chunk_index; j < last_chunk; j++) {
9432         if (j > n) {
9433           /* save state */
9434           stream->stsc_chunk_index = j;
9435           goto done;
9436         }
9437
9438         cur->offset =
9439             qt_atom_parser_get_offset_unchecked (&stream->co_chunk,
9440             stream->co_size);
9441
9442         GST_LOG_OBJECT (qtdemux, "Created entry %d with offset "
9443             "%" G_GUINT64_FORMAT, j, cur->offset);
9444
9445         if (CUR_STREAM (stream)->samples_per_frame > 0 &&
9446             CUR_STREAM (stream)->bytes_per_frame > 0) {
9447           cur->size =
9448               (stream->samples_per_chunk * CUR_STREAM (stream)->n_channels) /
9449               CUR_STREAM (stream)->samples_per_frame *
9450               CUR_STREAM (stream)->bytes_per_frame;
9451         } else {
9452           cur->size = stream->samples_per_chunk;
9453         }
9454
9455         GST_DEBUG_OBJECT (qtdemux,
9456             "keyframe sample %d: timestamp %" GST_TIME_FORMAT ", size %u",
9457             j, GST_TIME_ARGS (QTSTREAMTIME_TO_GSTTIME (stream,
9458                     stream->stco_sample_index)), cur->size);
9459
9460         cur->timestamp = stream->stco_sample_index;
9461         cur->duration = stream->samples_per_chunk;
9462         cur->keyframe = TRUE;
9463         cur++;
9464
9465         stream->stco_sample_index += stream->samples_per_chunk;
9466       }
9467       stream->stsc_chunk_index = j;
9468     } else {
9469       for (j = stream->stsc_chunk_index; j < last_chunk; j++) {
9470         guint32 samples_per_chunk;
9471         guint64 chunk_offset;
9472
9473         if (!stream->stsc_sample_index
9474             && !qt_atom_parser_get_offset (&stream->co_chunk, stream->co_size,
9475                 &stream->chunk_offset))
9476           goto corrupt_file;
9477
9478         samples_per_chunk = stream->samples_per_chunk;
9479         chunk_offset = stream->chunk_offset;
9480
9481         for (k = stream->stsc_sample_index; k < samples_per_chunk; k++) {
9482           GST_LOG_OBJECT (qtdemux, "creating entry %d with offset %"
9483               G_GUINT64_FORMAT " and size %d",
9484               (guint) (cur - samples), chunk_offset, cur->size);
9485
9486           cur->offset = chunk_offset;
9487           chunk_offset += cur->size;
9488           cur++;
9489
9490           if (G_UNLIKELY (cur > last)) {
9491             /* save state */
9492             stream->stsc_sample_index = k + 1;
9493             stream->chunk_offset = chunk_offset;
9494             stream->stsc_chunk_index = j;
9495             goto done2;
9496           }
9497         }
9498         stream->stsc_sample_index = 0;
9499       }
9500       stream->stsc_chunk_index = j;
9501     }
9502     stream->stsc_index++;
9503   }
9504
9505   if (stream->chunks_are_samples)
9506     goto ctts;
9507 done2:
9508   {
9509     guint32 n_sample_times;
9510
9511     n_sample_times = stream->n_sample_times;
9512     cur = first;
9513
9514     for (i = stream->stts_index; i < n_sample_times; i++) {
9515       guint32 stts_samples;
9516       gint32 stts_duration;
9517       gint64 stts_time;
9518
9519       if (stream->stts_sample_index >= stream->stts_samples
9520           || !stream->stts_sample_index) {
9521
9522         stream->stts_samples =
9523             gst_byte_reader_get_uint32_be_unchecked (&stream->stts);
9524         stream->stts_duration =
9525             gst_byte_reader_get_uint32_be_unchecked (&stream->stts);
9526
9527         GST_LOG_OBJECT (qtdemux, "block %d, %u timestamps, duration %u",
9528             i, stream->stts_samples, stream->stts_duration);
9529
9530         stream->stts_sample_index = 0;
9531       }
9532
9533       stts_samples = stream->stts_samples;
9534       stts_duration = stream->stts_duration;
9535       stts_time = stream->stts_time;
9536
9537       for (j = stream->stts_sample_index; j < stts_samples; j++) {
9538         GST_DEBUG_OBJECT (qtdemux,
9539             "sample %d: index %d, timestamp %" GST_TIME_FORMAT,
9540             (guint) (cur - samples), j,
9541             GST_TIME_ARGS (QTSTREAMTIME_TO_GSTTIME (stream, stts_time)));
9542
9543         cur->timestamp = stts_time;
9544         cur->duration = stts_duration;
9545
9546         /* avoid 32-bit wrap-around,
9547          * but still mind possible 'negative' duration */
9548         stts_time += (gint64) stts_duration;
9549         cur++;
9550
9551         if (G_UNLIKELY (cur > last)) {
9552           /* save values */
9553           stream->stts_time = stts_time;
9554           stream->stts_sample_index = j + 1;
9555           if (stream->stts_sample_index >= stream->stts_samples)
9556             stream->stts_index++;
9557           goto done3;
9558         }
9559       }
9560       stream->stts_sample_index = 0;
9561       stream->stts_time = stts_time;
9562       stream->stts_index++;
9563     }
9564     /* fill up empty timestamps with the last timestamp, this can happen when
9565      * the last samples do not decode and so we don't have timestamps for them.
9566      * We however look at the last timestamp to estimate the track length so we
9567      * need something in here. */
9568     for (; cur < last; cur++) {
9569       GST_DEBUG_OBJECT (qtdemux,
9570           "fill sample %d: timestamp %" GST_TIME_FORMAT,
9571           (guint) (cur - samples),
9572           GST_TIME_ARGS (QTSTREAMTIME_TO_GSTTIME (stream, stream->stts_time)));
9573       cur->timestamp = stream->stts_time;
9574       cur->duration = -1;
9575     }
9576   }
9577 done3:
9578   {
9579     /* sample sync, can be NULL */
9580     if (stream->stss_present == TRUE) {
9581       guint32 n_sample_syncs;
9582
9583       n_sample_syncs = stream->n_sample_syncs;
9584
9585       if (!n_sample_syncs) {
9586         GST_DEBUG_OBJECT (qtdemux, "all samples are keyframes");
9587         stream->all_keyframe = TRUE;
9588       } else {
9589         for (i = stream->stss_index; i < n_sample_syncs; i++) {
9590           /* note that the first sample is index 1, not 0 */
9591           guint32 index;
9592
9593           index = gst_byte_reader_get_uint32_be_unchecked (&stream->stss);
9594
9595           if (G_LIKELY (index > 0 && index <= n_samples)) {
9596             index -= 1;
9597             samples[index].keyframe = TRUE;
9598             GST_DEBUG_OBJECT (qtdemux, "samples at %u is keyframe", index);
9599             /* and exit if we have enough samples */
9600             if (G_UNLIKELY (index >= n)) {
9601               i++;
9602               break;
9603             }
9604           }
9605         }
9606         /* save state */
9607         stream->stss_index = i;
9608       }
9609
9610       /* stps marks partial sync frames like open GOP I-Frames */
9611       if (stream->stps_present == TRUE) {
9612         guint32 n_sample_partial_syncs;
9613
9614         n_sample_partial_syncs = stream->n_sample_partial_syncs;
9615
9616         /* if there are no entries, the stss table contains the real
9617          * sync samples */
9618         if (n_sample_partial_syncs) {
9619           for (i = stream->stps_index; i < n_sample_partial_syncs; i++) {
9620             /* note that the first sample is index 1, not 0 */
9621             guint32 index;
9622
9623             index = gst_byte_reader_get_uint32_be_unchecked (&stream->stps);
9624
9625             if (G_LIKELY (index > 0 && index <= n_samples)) {
9626               index -= 1;
9627               samples[index].keyframe = TRUE;
9628               GST_DEBUG_OBJECT (qtdemux, "samples at %u is keyframe", index);
9629               /* and exit if we have enough samples */
9630               if (G_UNLIKELY (index >= n)) {
9631                 i++;
9632                 break;
9633               }
9634             }
9635           }
9636           /* save state */
9637           stream->stps_index = i;
9638         }
9639       }
9640     } else {
9641       /* no stss, all samples are keyframes */
9642       stream->all_keyframe = TRUE;
9643       GST_DEBUG_OBJECT (qtdemux, "setting all keyframes");
9644     }
9645   }
9646
9647 ctts:
9648   /* composition time to sample */
9649   if (stream->ctts_present == TRUE) {
9650     guint32 n_composition_times;
9651     guint32 ctts_count;
9652     gint32 ctts_soffset;
9653
9654     /* Fill in the pts_offsets */
9655     cur = first;
9656     n_composition_times = stream->n_composition_times;
9657
9658     for (i = stream->ctts_index; i < n_composition_times; i++) {
9659       if (stream->ctts_sample_index >= stream->ctts_count
9660           || !stream->ctts_sample_index) {
9661         stream->ctts_count =
9662             gst_byte_reader_get_uint32_be_unchecked (&stream->ctts);
9663         stream->ctts_soffset =
9664             gst_byte_reader_get_int32_be_unchecked (&stream->ctts);
9665         stream->ctts_sample_index = 0;
9666       }
9667
9668       ctts_count = stream->ctts_count;
9669       ctts_soffset = stream->ctts_soffset;
9670
9671       for (j = stream->ctts_sample_index; j < ctts_count; j++) {
9672         cur->pts_offset = ctts_soffset;
9673         cur++;
9674
9675         if (G_UNLIKELY (cur > last)) {
9676           /* save state */
9677           stream->ctts_sample_index = j + 1;
9678           goto done;
9679         }
9680       }
9681       stream->ctts_sample_index = 0;
9682       stream->ctts_index++;
9683     }
9684   }
9685 done:
9686   stream->stbl_index = n;
9687   /* if index has been completely parsed, free data that is no-longer needed */
9688   if (n + 1 == stream->n_samples) {
9689     gst_qtdemux_stbl_free (stream);
9690     GST_DEBUG_OBJECT (qtdemux, "parsed all available samples;");
9691     if (qtdemux->pullbased) {
9692       GST_DEBUG_OBJECT (qtdemux, "checking for more samples");
9693       while (n + 1 == stream->n_samples)
9694         if (qtdemux_add_fragmented_samples (qtdemux) != GST_FLOW_OK)
9695           break;
9696     }
9697   }
9698   GST_OBJECT_UNLOCK (qtdemux);
9699
9700   return TRUE;
9701
9702   /* SUCCESS */
9703 already_parsed:
9704   {
9705     GST_LOG_OBJECT (qtdemux,
9706         "Tried to parse up to sample %u but this sample has already been parsed",
9707         n);
9708     /* if fragmented, there may be more */
9709     if (qtdemux->fragmented && n == stream->stbl_index)
9710       goto done;
9711     GST_OBJECT_UNLOCK (qtdemux);
9712     return TRUE;
9713   }
9714   /* ERRORS */
9715 out_of_samples:
9716   {
9717     GST_LOG_OBJECT (qtdemux,
9718         "Tried to parse up to sample %u but there are only %u samples", n + 1,
9719         stream->n_samples);
9720     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
9721         (_("This file is corrupt and cannot be played.")), (NULL));
9722     return FALSE;
9723   }
9724 corrupt_file:
9725   {
9726     GST_OBJECT_UNLOCK (qtdemux);
9727     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
9728         (_("This file is corrupt and cannot be played.")), (NULL));
9729     return FALSE;
9730   }
9731 }
9732
9733 /* collect all segment info for @stream.
9734  */
9735 static gboolean
9736 qtdemux_parse_segments (GstQTDemux * qtdemux, QtDemuxStream * stream,
9737     GNode * trak)
9738 {
9739   GNode *edts;
9740   /* accept edts if they contain gaps at start and there is only
9741    * one media segment */
9742   gboolean allow_pushbased_edts = TRUE;
9743   gint media_segments_count = 0;
9744
9745   /* parse and prepare segment info from the edit list */
9746   GST_DEBUG_OBJECT (qtdemux, "looking for edit list container");
9747   stream->n_segments = 0;
9748   stream->segments = NULL;
9749   if ((edts = qtdemux_tree_get_child_by_type (trak, FOURCC_edts))) {
9750     GNode *elst;
9751     gint n_segments;
9752     gint segment_number, entry_size;
9753     guint64 time;
9754     GstClockTime stime;
9755     const guint8 *buffer;
9756     guint8 version;
9757     guint32 size;
9758
9759     GST_DEBUG_OBJECT (qtdemux, "looking for edit list");
9760     if (!(elst = qtdemux_tree_get_child_by_type (edts, FOURCC_elst)))
9761       goto done;
9762
9763     buffer = elst->data;
9764
9765     size = QT_UINT32 (buffer);
9766     /* version, flags, n_segments */
9767     if (size < 16) {
9768       GST_WARNING_OBJECT (qtdemux, "Invalid edit list");
9769       goto done;
9770     }
9771     version = QT_UINT8 (buffer + 8);
9772     entry_size = (version == 1) ? 20 : 12;
9773
9774     n_segments = QT_UINT32 (buffer + 12);
9775
9776     if (n_segments > 100000 || size < 16 + n_segments * entry_size) {
9777       GST_WARNING_OBJECT (qtdemux, "Invalid edit list");
9778       goto done;
9779     }
9780
9781     /* we might allocate a bit too much, at least allocate 1 segment */
9782     stream->segments = g_new (QtDemuxSegment, MAX (n_segments, 1));
9783
9784     /* segments always start from 0 */
9785     time = 0;
9786     stime = 0;
9787     buffer += 16;
9788     for (segment_number = 0; segment_number < n_segments; segment_number++) {
9789       guint64 duration;
9790       guint64 media_time;
9791       gboolean empty_edit = FALSE;
9792       QtDemuxSegment *segment;
9793       guint32 rate_int;
9794       GstClockTime media_start = GST_CLOCK_TIME_NONE;
9795
9796       if (version == 1) {
9797         media_time = QT_UINT64 (buffer + 8);
9798         duration = QT_UINT64 (buffer);
9799         if (media_time == G_MAXUINT64)
9800           empty_edit = TRUE;
9801       } else {
9802         media_time = QT_UINT32 (buffer + 4);
9803         duration = QT_UINT32 (buffer);
9804         if (media_time == G_MAXUINT32)
9805           empty_edit = TRUE;
9806       }
9807
9808       if (!empty_edit)
9809         media_start = QTSTREAMTIME_TO_GSTTIME (stream, media_time);
9810
9811       segment = &stream->segments[segment_number];
9812
9813       /* time and duration expressed in global timescale */
9814       segment->time = stime;
9815       if (duration != 0 || empty_edit) {
9816         /* edge case: empty edits with duration=zero are treated here.
9817          * (files should not have these anyway). */
9818
9819         /* add non scaled values so we don't cause roundoff errors */
9820         time += duration;
9821         stime = QTTIME_TO_GSTTIME (qtdemux, time);
9822         segment->duration = stime - segment->time;
9823       } else {
9824         /* zero duration does not imply media_start == media_stop
9825          * but, only specify media_start. The edit ends with the track. */
9826         stime = segment->duration = GST_CLOCK_TIME_NONE;
9827         /* Don't allow more edits after this one. */
9828         n_segments = segment_number + 1;
9829       }
9830       segment->stop_time = stime;
9831
9832       segment->trak_media_start = media_time;
9833       /* media_time expressed in stream timescale */
9834       if (!empty_edit) {
9835         segment->media_start = media_start;
9836         segment->media_stop = GST_CLOCK_TIME_IS_VALID (segment->duration)
9837             ? segment->media_start + segment->duration : GST_CLOCK_TIME_NONE;
9838         media_segments_count++;
9839       } else {
9840         segment->media_start = GST_CLOCK_TIME_NONE;
9841         segment->media_stop = GST_CLOCK_TIME_NONE;
9842       }
9843       rate_int = QT_UINT32 (buffer + ((version == 1) ? 16 : 8));
9844
9845       if (rate_int <= 1) {
9846         /* 0 is not allowed, some programs write 1 instead of the floating point
9847          * value */
9848         GST_WARNING_OBJECT (qtdemux, "found suspicious rate %" G_GUINT32_FORMAT,
9849             rate_int);
9850         segment->rate = 1;
9851       } else {
9852         segment->rate = rate_int / 65536.0;
9853       }
9854
9855       GST_DEBUG_OBJECT (qtdemux, "created segment %d time %" GST_TIME_FORMAT
9856           ", duration %" GST_TIME_FORMAT ", media_start %" GST_TIME_FORMAT
9857           " (%" G_GUINT64_FORMAT ") , media_stop %" GST_TIME_FORMAT
9858           " stop_time %" GST_TIME_FORMAT " rate %g, (%d) timescale %u",
9859           segment_number, GST_TIME_ARGS (segment->time),
9860           GST_TIME_ARGS (segment->duration),
9861           GST_TIME_ARGS (segment->media_start), media_time,
9862           GST_TIME_ARGS (segment->media_stop),
9863           GST_TIME_ARGS (segment->stop_time), segment->rate, rate_int,
9864           stream->timescale);
9865       if (segment->stop_time > qtdemux->segment.stop &&
9866           !qtdemux->upstream_format_is_time) {
9867         GST_WARNING_OBJECT (qtdemux, "Segment %d "
9868             " extends to %" GST_TIME_FORMAT
9869             " past the end of the declared movie duration %" GST_TIME_FORMAT
9870             " movie segment will be extended", segment_number,
9871             GST_TIME_ARGS (segment->stop_time),
9872             GST_TIME_ARGS (qtdemux->segment.stop));
9873         qtdemux->segment.stop = qtdemux->segment.duration = segment->stop_time;
9874       }
9875
9876       buffer += entry_size;
9877     }
9878     GST_DEBUG_OBJECT (qtdemux, "found %d segments", n_segments);
9879     stream->n_segments = n_segments;
9880     if (media_segments_count != 1)
9881       allow_pushbased_edts = FALSE;
9882   }
9883 done:
9884
9885   /* push based does not handle segments, so act accordingly here,
9886    * and warn if applicable */
9887   if (!qtdemux->pullbased && !allow_pushbased_edts) {
9888     GST_WARNING_OBJECT (qtdemux, "streaming; discarding edit list segments");
9889     /* remove and use default one below, we stream like it anyway */
9890     g_free (stream->segments);
9891     stream->segments = NULL;
9892     stream->n_segments = 0;
9893   }
9894
9895   /* no segments, create one to play the complete trak */
9896   if (stream->n_segments == 0) {
9897     GstClockTime stream_duration =
9898         QTSTREAMTIME_TO_GSTTIME (stream, stream->duration);
9899
9900     if (stream->segments == NULL)
9901       stream->segments = g_new (QtDemuxSegment, 1);
9902
9903     /* represent unknown our way */
9904     if (stream_duration == 0)
9905       stream_duration = GST_CLOCK_TIME_NONE;
9906
9907     stream->segments[0].time = 0;
9908     stream->segments[0].stop_time = stream_duration;
9909     stream->segments[0].duration = stream_duration;
9910     stream->segments[0].media_start = 0;
9911     stream->segments[0].media_stop = stream_duration;
9912     stream->segments[0].rate = 1.0;
9913     stream->segments[0].trak_media_start = 0;
9914
9915     GST_DEBUG_OBJECT (qtdemux, "created dummy segment %" GST_TIME_FORMAT,
9916         GST_TIME_ARGS (stream_duration));
9917     stream->n_segments = 1;
9918     stream->dummy_segment = TRUE;
9919   }
9920   GST_DEBUG_OBJECT (qtdemux, "using %d segments", stream->n_segments);
9921
9922   return TRUE;
9923 }
9924
9925 /*
9926  * Parses the stsd atom of a svq3 trak looking for
9927  * the SMI and gama atoms.
9928  */
9929 static void
9930 qtdemux_parse_svq3_stsd_data (GstQTDemux * qtdemux,
9931     const guint8 * stsd_entry_data, const guint8 ** gamma, GstBuffer ** seqh)
9932 {
9933   const guint8 *_gamma = NULL;
9934   GstBuffer *_seqh = NULL;
9935   const guint8 *stsd_data = stsd_entry_data;
9936   guint32 length = QT_UINT32 (stsd_data);
9937   guint16 version;
9938
9939   if (length < 32) {
9940     GST_WARNING_OBJECT (qtdemux, "stsd too short");
9941     goto end;
9942   }
9943
9944   stsd_data += 16;
9945   length -= 16;
9946   version = QT_UINT16 (stsd_data);
9947   if (version == 3) {
9948     if (length >= 70) {
9949       length -= 70;
9950       stsd_data += 70;
9951       while (length > 8) {
9952         guint32 fourcc, size;
9953         const guint8 *data;
9954         size = QT_UINT32 (stsd_data);
9955         fourcc = QT_FOURCC (stsd_data + 4);
9956         data = stsd_data + 8;
9957
9958         if (size == 0) {
9959           GST_WARNING_OBJECT (qtdemux, "Atom of size 0 found, aborting "
9960               "svq3 atom parsing");
9961           goto end;
9962         }
9963
9964         switch (fourcc) {
9965           case FOURCC_gama:{
9966             if (size == 12) {
9967               _gamma = data;
9968             } else {
9969               GST_WARNING_OBJECT (qtdemux, "Unexpected size %" G_GUINT32_FORMAT
9970                   " for gama atom, expected 12", size);
9971             }
9972             break;
9973           }
9974           case FOURCC_SMI_:{
9975             if (size > 16 && QT_FOURCC (data) == FOURCC_SEQH) {
9976               guint32 seqh_size;
9977               if (_seqh != NULL) {
9978                 GST_WARNING_OBJECT (qtdemux, "Unexpected second SEQH SMI atom "
9979                     " found, ignoring");
9980               } else {
9981                 seqh_size = QT_UINT32 (data + 4);
9982                 if (seqh_size > 0) {
9983                   _seqh = gst_buffer_new_and_alloc (seqh_size);
9984                   gst_buffer_fill (_seqh, 0, data + 8, seqh_size);
9985                 }
9986               }
9987             }
9988             break;
9989           }
9990           default:{
9991             GST_WARNING_OBJECT (qtdemux, "Unhandled atom %" GST_FOURCC_FORMAT
9992                 " in SVQ3 entry in stsd atom", GST_FOURCC_ARGS (fourcc));
9993           }
9994         }
9995
9996         if (size <= length) {
9997           length -= size;
9998           stsd_data += size;
9999         }
10000       }
10001     } else {
10002       GST_WARNING_OBJECT (qtdemux, "SVQ3 entry too short in stsd atom");
10003     }
10004   } else {
10005     GST_WARNING_OBJECT (qtdemux, "Unexpected version for SVQ3 entry %"
10006         G_GUINT16_FORMAT, version);
10007     goto end;
10008   }
10009
10010 end:
10011   if (gamma) {
10012     *gamma = _gamma;
10013   }
10014   if (seqh) {
10015     *seqh = _seqh;
10016   } else if (_seqh) {
10017     gst_buffer_unref (_seqh);
10018   }
10019 }
10020
10021 static gchar *
10022 qtdemux_get_rtsp_uri_from_hndl (GstQTDemux * qtdemux, GNode * minf)
10023 {
10024   GNode *dinf;
10025   GstByteReader dref;
10026   gchar *uri = NULL;
10027
10028   /*
10029    * Get 'dinf', to get its child 'dref', that might contain a 'hndl'
10030    * atom that might contain a 'data' atom with the rtsp uri.
10031    * This case was reported in bug #597497, some info about
10032    * the hndl atom can be found in TN1195
10033    */
10034   dinf = qtdemux_tree_get_child_by_type (minf, FOURCC_dinf);
10035   GST_DEBUG_OBJECT (qtdemux, "Trying to obtain rtsp URI for stream trak");
10036
10037   if (dinf) {
10038     guint32 dref_num_entries = 0;
10039     if (qtdemux_tree_get_child_by_type_full (dinf, FOURCC_dref, &dref) &&
10040         gst_byte_reader_skip (&dref, 4) &&
10041         gst_byte_reader_get_uint32_be (&dref, &dref_num_entries)) {
10042       gint i;
10043
10044       /* search dref entries for hndl atom */
10045       for (i = 0; i < dref_num_entries; i++) {
10046         guint32 size = 0, type;
10047         guint8 string_len = 0;
10048         if (gst_byte_reader_get_uint32_be (&dref, &size) &&
10049             qt_atom_parser_get_fourcc (&dref, &type)) {
10050           if (type == FOURCC_hndl) {
10051             GST_DEBUG_OBJECT (qtdemux, "Found hndl atom");
10052
10053             /* skip data reference handle bytes and the
10054              * following pascal string and some extra 4
10055              * bytes I have no idea what are */
10056             if (!gst_byte_reader_skip (&dref, 4) ||
10057                 !gst_byte_reader_get_uint8 (&dref, &string_len) ||
10058                 !gst_byte_reader_skip (&dref, string_len + 4)) {
10059               GST_WARNING_OBJECT (qtdemux, "Failed to parse hndl atom");
10060               break;
10061             }
10062
10063             /* iterate over the atoms to find the data atom */
10064             while (gst_byte_reader_get_remaining (&dref) >= 8) {
10065               guint32 atom_size;
10066               guint32 atom_type;
10067
10068               if (gst_byte_reader_get_uint32_be (&dref, &atom_size) &&
10069                   qt_atom_parser_get_fourcc (&dref, &atom_type)) {
10070                 if (atom_type == FOURCC_data) {
10071                   const guint8 *uri_aux = NULL;
10072
10073                   /* found the data atom that might contain the rtsp uri */
10074                   GST_DEBUG_OBJECT (qtdemux, "Found data atom inside "
10075                       "hndl atom, interpreting it as an URI");
10076                   if (gst_byte_reader_peek_data (&dref, atom_size - 8,
10077                           &uri_aux)) {
10078                     if (g_strstr_len ((gchar *) uri_aux, 7, "rtsp://") != NULL)
10079                       uri = g_strndup ((gchar *) uri_aux, atom_size - 8);
10080                     else
10081                       GST_WARNING_OBJECT (qtdemux, "Data atom in hndl atom "
10082                           "didn't contain a rtsp address");
10083                   } else {
10084                     GST_WARNING_OBJECT (qtdemux, "Failed to get the data "
10085                         "atom contents");
10086                   }
10087                   break;
10088                 }
10089                 /* skipping to the next entry */
10090                 if (!gst_byte_reader_skip (&dref, atom_size - 8))
10091                   break;
10092               } else {
10093                 GST_WARNING_OBJECT (qtdemux, "Failed to parse hndl child "
10094                     "atom header");
10095                 break;
10096               }
10097             }
10098             break;
10099           }
10100           /* skip to the next entry */
10101           if (!gst_byte_reader_skip (&dref, size - 8))
10102             break;
10103         } else {
10104           GST_WARNING_OBJECT (qtdemux, "Error parsing dref atom");
10105         }
10106       }
10107       GST_DEBUG_OBJECT (qtdemux, "Finished parsing dref atom");
10108     }
10109   }
10110   return uri;
10111 }
10112
10113 #define AMR_NB_ALL_MODES        0x81ff
10114 #define AMR_WB_ALL_MODES        0x83ff
10115 static guint
10116 qtdemux_parse_amr_bitrate (GstBuffer * buf, gboolean wb)
10117 {
10118   /* The 'damr' atom is of the form:
10119    *
10120    * | vendor | decoder_ver | mode_set | mode_change_period | frames/sample |
10121    *    32 b       8 b          16 b           8 b                 8 b
10122    *
10123    * The highest set bit of the first 7 (AMR-NB) or 8 (AMR-WB) bits of mode_set
10124    * represents the highest mode used in the stream (and thus the maximum
10125    * bitrate), with a couple of special cases as seen below.
10126    */
10127
10128   /* Map of frame type ID -> bitrate */
10129   static const guint nb_bitrates[] = {
10130     4750, 5150, 5900, 6700, 7400, 7950, 10200, 12200
10131   };
10132   static const guint wb_bitrates[] = {
10133     6600, 8850, 12650, 14250, 15850, 18250, 19850, 23050, 23850
10134   };
10135   GstMapInfo map;
10136   gsize max_mode;
10137   guint16 mode_set;
10138
10139   gst_buffer_map (buf, &map, GST_MAP_READ);
10140
10141   if (map.size != 0x11) {
10142     GST_DEBUG ("Atom should have size 0x11, not %" G_GSIZE_FORMAT, map.size);
10143     goto bad_data;
10144   }
10145
10146   if (QT_FOURCC (map.data + 4) != FOURCC_damr) {
10147     GST_DEBUG ("Unknown atom in %" GST_FOURCC_FORMAT,
10148         GST_FOURCC_ARGS (QT_UINT32 (map.data + 4)));
10149     goto bad_data;
10150   }
10151
10152   mode_set = QT_UINT16 (map.data + 13);
10153
10154   if (mode_set == (wb ? AMR_WB_ALL_MODES : AMR_NB_ALL_MODES))
10155     max_mode = 7 + (wb ? 1 : 0);
10156   else
10157     /* AMR-NB modes fo from 0-7, and AMR-WB modes go from 0-8 */
10158     max_mode = g_bit_nth_msf ((gulong) mode_set & (wb ? 0x1ff : 0xff), -1);
10159
10160   if (max_mode == -1) {
10161     GST_DEBUG ("No mode indication was found (mode set) = %x",
10162         (guint) mode_set);
10163     goto bad_data;
10164   }
10165
10166   gst_buffer_unmap (buf, &map);
10167   return wb ? wb_bitrates[max_mode] : nb_bitrates[max_mode];
10168
10169 bad_data:
10170   gst_buffer_unmap (buf, &map);
10171   return 0;
10172 }
10173
10174 static gboolean
10175 qtdemux_parse_transformation_matrix (GstQTDemux * qtdemux,
10176     GstByteReader * reader, guint32 * matrix, const gchar * atom)
10177 {
10178   /*
10179    * 9 values of 32 bits (fixed point 16.16, except 2 5 and 8 that are 2.30)
10180    * [0 1 2]
10181    * [3 4 5]
10182    * [6 7 8]
10183    */
10184
10185   if (gst_byte_reader_get_remaining (reader) < 36)
10186     return FALSE;
10187
10188   matrix[0] = gst_byte_reader_get_uint32_be_unchecked (reader);
10189   matrix[1] = gst_byte_reader_get_uint32_be_unchecked (reader);
10190   matrix[2] = gst_byte_reader_get_uint32_be_unchecked (reader);
10191   matrix[3] = gst_byte_reader_get_uint32_be_unchecked (reader);
10192   matrix[4] = gst_byte_reader_get_uint32_be_unchecked (reader);
10193   matrix[5] = gst_byte_reader_get_uint32_be_unchecked (reader);
10194   matrix[6] = gst_byte_reader_get_uint32_be_unchecked (reader);
10195   matrix[7] = gst_byte_reader_get_uint32_be_unchecked (reader);
10196   matrix[8] = gst_byte_reader_get_uint32_be_unchecked (reader);
10197
10198   GST_DEBUG_OBJECT (qtdemux, "Transformation matrix from atom %s", atom);
10199   GST_DEBUG_OBJECT (qtdemux, "%u.%u %u.%u %u.%u", matrix[0] >> 16,
10200       matrix[0] & 0xFFFF, matrix[1] >> 16, matrix[1] & 0xFF, matrix[2] >> 16,
10201       matrix[2] & 0xFF);
10202   GST_DEBUG_OBJECT (qtdemux, "%u.%u %u.%u %u.%u", matrix[3] >> 16,
10203       matrix[3] & 0xFFFF, matrix[4] >> 16, matrix[4] & 0xFF, matrix[5] >> 16,
10204       matrix[5] & 0xFF);
10205   GST_DEBUG_OBJECT (qtdemux, "%u.%u %u.%u %u.%u", matrix[6] >> 16,
10206       matrix[6] & 0xFFFF, matrix[7] >> 16, matrix[7] & 0xFF, matrix[8] >> 16,
10207       matrix[8] & 0xFF);
10208
10209   return TRUE;
10210 }
10211
10212 static void
10213 qtdemux_inspect_transformation_matrix (GstQTDemux * qtdemux,
10214     QtDemuxStream * stream, guint32 * matrix, GstTagList ** taglist)
10215 {
10216
10217 /* [a b c]
10218  * [d e f]
10219  * [g h i]
10220  *
10221  * This macro will only compare value abdegh, it expects cfi to have already
10222  * been checked
10223  */
10224 #define QTCHECK_MATRIX(m,a,b,d,e) ((m)[0] == (a << 16) && (m)[1] == (b << 16) && \
10225                                    (m)[3] == (d << 16) && (m)[4] == (e << 16))
10226
10227   /* only handle the cases where the last column has standard values */
10228   if (matrix[2] == 0 && matrix[5] == 0 && matrix[8] == 1 << 30) {
10229     const gchar *rotation_tag = NULL;
10230
10231     /* no rotation needed */
10232     if (QTCHECK_MATRIX (matrix, 1, 0, 0, 1)) {
10233       /* NOP */
10234     } else if (QTCHECK_MATRIX (matrix, 0, 1, G_MAXUINT16, 0)) {
10235       rotation_tag = "rotate-90";
10236     } else if (QTCHECK_MATRIX (matrix, G_MAXUINT16, 0, 0, G_MAXUINT16)) {
10237       rotation_tag = "rotate-180";
10238     } else if (QTCHECK_MATRIX (matrix, 0, G_MAXUINT16, 1, 0)) {
10239       rotation_tag = "rotate-270";
10240     } else {
10241       GST_FIXME_OBJECT (qtdemux, "Unhandled transformation matrix values");
10242     }
10243
10244     GST_DEBUG_OBJECT (qtdemux, "Transformation matrix rotation %s",
10245         rotation_tag);
10246     if (rotation_tag != NULL) {
10247       if (*taglist == NULL)
10248         *taglist = gst_tag_list_new_empty ();
10249       gst_tag_list_add (*taglist, GST_TAG_MERGE_REPLACE,
10250           GST_TAG_IMAGE_ORIENTATION, rotation_tag, NULL);
10251     }
10252   } else {
10253     GST_FIXME_OBJECT (qtdemux, "Unhandled transformation matrix values");
10254   }
10255 }
10256
10257 /* Parses the boxes defined in ISO/IEC 14496-12 that enable support for
10258  * protected streams (sinf, frma, schm and schi); if the protection scheme is
10259  * Common Encryption (cenc), the function will also parse the tenc box (defined
10260  * in ISO/IEC 23001-7). @container points to the node that contains these boxes
10261  * (typically an enc[v|a|t|s] sample entry); the function will set
10262  * @original_fmt to the fourcc of the original unencrypted stream format.
10263  * Returns TRUE if successful; FALSE otherwise. */
10264 static gboolean
10265 qtdemux_parse_protection_scheme_info (GstQTDemux * qtdemux,
10266     QtDemuxStream * stream, GNode * container, guint32 * original_fmt)
10267 {
10268   GNode *sinf;
10269   GNode *frma;
10270   GNode *schm;
10271   GNode *schi;
10272   QtDemuxCencSampleSetInfo *info;
10273   GNode *tenc;
10274   const guint8 *tenc_data;
10275
10276   g_return_val_if_fail (qtdemux != NULL, FALSE);
10277   g_return_val_if_fail (stream != NULL, FALSE);
10278   g_return_val_if_fail (container != NULL, FALSE);
10279   g_return_val_if_fail (original_fmt != NULL, FALSE);
10280
10281   sinf = qtdemux_tree_get_child_by_type (container, FOURCC_sinf);
10282   if (G_UNLIKELY (!sinf)) {
10283     if (stream->protection_scheme_type == FOURCC_cenc) {
10284       GST_ERROR_OBJECT (qtdemux, "sinf box does not contain schi box, which is "
10285           "mandatory for Common Encryption");
10286       return FALSE;
10287     }
10288     return TRUE;
10289   }
10290
10291   frma = qtdemux_tree_get_child_by_type (sinf, FOURCC_frma);
10292   if (G_UNLIKELY (!frma)) {
10293     GST_ERROR_OBJECT (qtdemux, "sinf box does not contain mandatory frma box");
10294     return FALSE;
10295   }
10296
10297   *original_fmt = QT_FOURCC ((const guint8 *) frma->data + 8);
10298   GST_DEBUG_OBJECT (qtdemux, "original stream format: '%" GST_FOURCC_FORMAT "'",
10299       GST_FOURCC_ARGS (*original_fmt));
10300
10301   schm = qtdemux_tree_get_child_by_type (sinf, FOURCC_schm);
10302   if (!schm) {
10303     GST_DEBUG_OBJECT (qtdemux, "sinf box does not contain schm box");
10304     return FALSE;
10305   }
10306   stream->protection_scheme_type = QT_FOURCC ((const guint8 *) schm->data + 12);
10307   stream->protection_scheme_version =
10308       QT_UINT32 ((const guint8 *) schm->data + 16);
10309
10310   GST_DEBUG_OBJECT (qtdemux,
10311       "protection_scheme_type: %" GST_FOURCC_FORMAT ", "
10312       "protection_scheme_version: %#010x",
10313       GST_FOURCC_ARGS (stream->protection_scheme_type),
10314       stream->protection_scheme_version);
10315
10316   schi = qtdemux_tree_get_child_by_type (sinf, FOURCC_schi);
10317   if (!schi) {
10318     GST_DEBUG_OBJECT (qtdemux, "sinf box does not contain schi box");
10319     return FALSE;
10320   }
10321   if (stream->protection_scheme_type != FOURCC_cenc &&
10322       stream->protection_scheme_type != FOURCC_piff) {
10323     GST_ERROR_OBJECT (qtdemux,
10324         "Invalid protection_scheme_type: %" GST_FOURCC_FORMAT,
10325         GST_FOURCC_ARGS (stream->protection_scheme_type));
10326     return FALSE;
10327   }
10328
10329   if (G_UNLIKELY (!stream->protection_scheme_info))
10330     stream->protection_scheme_info =
10331         g_malloc0 (sizeof (QtDemuxCencSampleSetInfo));
10332
10333   info = (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
10334
10335   if (stream->protection_scheme_type == FOURCC_cenc) {
10336     guint32 is_encrypted;
10337     guint8 iv_size;
10338     const guint8 *default_kid;
10339
10340     tenc = qtdemux_tree_get_child_by_type (schi, FOURCC_tenc);
10341     if (!tenc) {
10342       GST_ERROR_OBJECT (qtdemux, "schi box does not contain tenc box, "
10343           "which is mandatory for Common Encryption");
10344       return FALSE;
10345     }
10346     tenc_data = (const guint8 *) tenc->data + 12;
10347     is_encrypted = QT_UINT24 (tenc_data);
10348     iv_size = QT_UINT8 (tenc_data + 3);
10349     default_kid = (tenc_data + 4);
10350     qtdemux_update_default_sample_encryption_settings (qtdemux, info,
10351         is_encrypted, iv_size, default_kid);
10352   } else if (stream->protection_scheme_type == FOURCC_piff) {
10353     GstByteReader br;
10354     static const guint8 piff_track_encryption_uuid[] = {
10355       0x89, 0x74, 0xdb, 0xce, 0x7b, 0xe7, 0x4c, 0x51,
10356       0x84, 0xf9, 0x71, 0x48, 0xf9, 0x88, 0x25, 0x54
10357     };
10358
10359     tenc = qtdemux_tree_get_child_by_type (schi, FOURCC_uuid);
10360     if (!tenc) {
10361       GST_ERROR_OBJECT (qtdemux, "schi box does not contain tenc box, "
10362           "which is mandatory for Common Encryption");
10363       return FALSE;
10364     }
10365
10366     tenc_data = (const guint8 *) tenc->data + 8;
10367     if (memcmp (tenc_data, piff_track_encryption_uuid, 16) != 0) {
10368       gchar *box_uuid = qtdemux_uuid_bytes_to_string (tenc_data);
10369       GST_ERROR_OBJECT (qtdemux,
10370           "Unsupported track encryption box with uuid: %s", box_uuid);
10371       g_free (box_uuid);
10372       return FALSE;
10373     }
10374     tenc_data = (const guint8 *) tenc->data + 16 + 12;
10375     gst_byte_reader_init (&br, tenc_data, 20);
10376     if (!qtdemux_update_default_piff_encryption_settings (qtdemux, info, &br)) {
10377       GST_ERROR_OBJECT (qtdemux, "PIFF track box parsing error");
10378       return FALSE;
10379     }
10380     stream->protection_scheme_type = FOURCC_cenc;
10381   }
10382
10383   return TRUE;
10384 }
10385
10386 static gint
10387 qtdemux_track_id_compare_func (QtDemuxStream ** stream1,
10388     QtDemuxStream ** stream2)
10389 {
10390   return (gint) (*stream1)->track_id - (gint) (*stream2)->track_id;
10391 }
10392
10393 /* parse the traks.
10394  * With each track we associate a new QtDemuxStream that contains all the info
10395  * about the trak.
10396  * traks that do not decode to something (like strm traks) will not have a pad.
10397  */
10398 static gboolean
10399 qtdemux_parse_trak (GstQTDemux * qtdemux, GNode * trak)
10400 {
10401   GstByteReader tkhd;
10402   int offset;
10403   GNode *mdia;
10404   GNode *mdhd;
10405   GNode *hdlr;
10406   GNode *minf;
10407   GNode *stbl;
10408   GNode *stsd;
10409   GNode *mp4a;
10410   GNode *mp4v;
10411   GNode *esds;
10412   GNode *tref;
10413   GNode *udta;
10414   GNode *svmi;
10415
10416   QtDemuxStream *stream = NULL;
10417   const guint8 *stsd_data;
10418   const guint8 *stsd_entry_data;
10419   guint remaining_stsd_len;
10420   guint stsd_entry_count;
10421   guint stsd_index;
10422   guint16 lang_code;            /* quicktime lang code or packed iso code */
10423   guint32 version;
10424   guint32 tkhd_flags = 0;
10425   guint8 tkhd_version = 0;
10426   guint32 w = 0, h = 0;
10427   guint value_size, stsd_len, len;
10428   guint32 track_id;
10429   guint32 dummy;
10430
10431   GST_DEBUG_OBJECT (qtdemux, "parse_trak");
10432
10433   if (!qtdemux_tree_get_child_by_type_full (trak, FOURCC_tkhd, &tkhd)
10434       || !gst_byte_reader_get_uint8 (&tkhd, &tkhd_version)
10435       || !gst_byte_reader_get_uint24_be (&tkhd, &tkhd_flags))
10436     goto corrupt_file;
10437
10438   /* pick between 64 or 32 bits */
10439   value_size = tkhd_version == 1 ? 8 : 4;
10440   if (!gst_byte_reader_skip (&tkhd, value_size * 2) ||
10441       !gst_byte_reader_get_uint32_be (&tkhd, &track_id))
10442     goto corrupt_file;
10443
10444   /* Check if current moov has duplicated track_id */
10445   if (qtdemux_find_stream (qtdemux, track_id))
10446     goto existing_stream;
10447
10448   stream = _create_stream (qtdemux, track_id);
10449   stream->stream_tags = gst_tag_list_make_writable (stream->stream_tags);
10450
10451   /* need defaults for fragments */
10452   qtdemux_parse_trex (qtdemux, stream, &dummy, &dummy, &dummy);
10453
10454   if ((tkhd_flags & 1) == 0)
10455     stream->disabled = TRUE;
10456
10457   GST_LOG_OBJECT (qtdemux, "track[tkhd] version/flags/id: 0x%02x/%06x/%u",
10458       tkhd_version, tkhd_flags, stream->track_id);
10459
10460   if (!(mdia = qtdemux_tree_get_child_by_type (trak, FOURCC_mdia)))
10461     goto corrupt_file;
10462
10463   if (!(mdhd = qtdemux_tree_get_child_by_type (mdia, FOURCC_mdhd))) {
10464     /* be nice for some crooked mjp2 files that use mhdr for mdhd */
10465     if (qtdemux->major_brand != FOURCC_mjp2 ||
10466         !(mdhd = qtdemux_tree_get_child_by_type (mdia, FOURCC_mhdr)))
10467       goto corrupt_file;
10468   }
10469
10470   len = QT_UINT32 ((guint8 *) mdhd->data);
10471   version = QT_UINT32 ((guint8 *) mdhd->data + 8);
10472   GST_LOG_OBJECT (qtdemux, "track version/flags: %08x", version);
10473   if (version == 0x01000000) {
10474     if (len < 42)
10475       goto corrupt_file;
10476     stream->timescale = QT_UINT32 ((guint8 *) mdhd->data + 28);
10477     stream->duration = QT_UINT64 ((guint8 *) mdhd->data + 32);
10478     lang_code = QT_UINT16 ((guint8 *) mdhd->data + 40);
10479   } else {
10480     if (len < 30)
10481       goto corrupt_file;
10482     stream->timescale = QT_UINT32 ((guint8 *) mdhd->data + 20);
10483     stream->duration = QT_UINT32 ((guint8 *) mdhd->data + 24);
10484     lang_code = QT_UINT16 ((guint8 *) mdhd->data + 28);
10485   }
10486
10487   if (lang_code < 0x400) {
10488     qtdemux_lang_map_qt_code_to_iso (stream->lang_id, lang_code);
10489   } else if (lang_code == 0x7fff) {
10490     stream->lang_id[0] = 0;     /* unspecified */
10491   } else {
10492     stream->lang_id[0] = 0x60 + ((lang_code >> 10) & 0x1F);
10493     stream->lang_id[1] = 0x60 + ((lang_code >> 5) & 0x1F);
10494     stream->lang_id[2] = 0x60 + (lang_code & 0x1F);
10495     stream->lang_id[3] = 0;
10496   }
10497
10498   GST_LOG_OBJECT (qtdemux, "track timescale: %" G_GUINT32_FORMAT,
10499       stream->timescale);
10500   GST_LOG_OBJECT (qtdemux, "track duration: %" G_GUINT64_FORMAT,
10501       stream->duration);
10502   GST_LOG_OBJECT (qtdemux, "track language code/id: 0x%04x/%s",
10503       lang_code, stream->lang_id);
10504
10505   if (G_UNLIKELY (stream->timescale == 0 || qtdemux->timescale == 0))
10506     goto corrupt_file;
10507
10508   if ((tref = qtdemux_tree_get_child_by_type (trak, FOURCC_tref))) {
10509     /* chapters track reference */
10510     GNode *chap = qtdemux_tree_get_child_by_type (tref, FOURCC_chap);
10511     if (chap) {
10512       gsize length = GST_READ_UINT32_BE (chap->data);
10513       if (qtdemux->chapters_track_id)
10514         GST_FIXME_OBJECT (qtdemux, "Multiple CHAP tracks");
10515
10516       if (length >= 12) {
10517         qtdemux->chapters_track_id =
10518             GST_READ_UINT32_BE ((gint8 *) chap->data + 8);
10519       }
10520     }
10521   }
10522
10523   /* fragmented files may have bogus duration in moov */
10524   if (!qtdemux->fragmented &&
10525       qtdemux->duration != G_MAXINT64 && stream->duration != G_MAXINT32) {
10526     guint64 tdur1, tdur2;
10527
10528     /* don't overflow */
10529     tdur1 = stream->timescale * (guint64) qtdemux->duration;
10530     tdur2 = qtdemux->timescale * (guint64) stream->duration;
10531
10532     /* HACK:
10533      * some of those trailers, nowadays, have prologue images that are
10534      * themselves video tracks as well. I haven't really found a way to
10535      * identify those yet, except for just looking at their duration. */
10536     if (tdur1 != 0 && (tdur2 * 10 / tdur1) < 2) {
10537       GST_WARNING_OBJECT (qtdemux,
10538           "Track shorter than 20%% (%" G_GUINT64_FORMAT "/%" G_GUINT32_FORMAT
10539           " vs. %" G_GUINT64_FORMAT "/%" G_GUINT32_FORMAT ") of the stream "
10540           "found, assuming preview image or something; skipping track",
10541           stream->duration, stream->timescale, qtdemux->duration,
10542           qtdemux->timescale);
10543       gst_qtdemux_stream_unref (stream);
10544       return TRUE;
10545     }
10546   }
10547
10548   if (!(hdlr = qtdemux_tree_get_child_by_type (mdia, FOURCC_hdlr)))
10549     goto corrupt_file;
10550
10551   GST_LOG_OBJECT (qtdemux, "track type: %" GST_FOURCC_FORMAT,
10552       GST_FOURCC_ARGS (QT_FOURCC ((guint8 *) hdlr->data + 12)));
10553
10554   len = QT_UINT32 ((guint8 *) hdlr->data);
10555   if (len >= 20)
10556     stream->subtype = QT_FOURCC ((guint8 *) hdlr->data + 16);
10557   GST_LOG_OBJECT (qtdemux, "track subtype: %" GST_FOURCC_FORMAT,
10558       GST_FOURCC_ARGS (stream->subtype));
10559
10560   if (!(minf = qtdemux_tree_get_child_by_type (mdia, FOURCC_minf)))
10561     goto corrupt_file;
10562
10563   if (!(stbl = qtdemux_tree_get_child_by_type (minf, FOURCC_stbl)))
10564     goto corrupt_file;
10565
10566   /*parse svmi header if existing */
10567   svmi = qtdemux_tree_get_child_by_type (stbl, FOURCC_svmi);
10568   if (svmi) {
10569     len = QT_UINT32 ((guint8 *) svmi->data);
10570     version = QT_UINT32 ((guint8 *) svmi->data + 8);
10571     if (!version) {
10572       GstVideoMultiviewMode mode = GST_VIDEO_MULTIVIEW_MODE_NONE;
10573       GstVideoMultiviewFlags flags = GST_VIDEO_MULTIVIEW_FLAGS_NONE;
10574       guint8 frame_type, frame_layout;
10575
10576       /* MPEG-A stereo video */
10577       if (qtdemux->major_brand == FOURCC_ss02)
10578         flags |= GST_VIDEO_MULTIVIEW_FLAGS_MIXED_MONO;
10579
10580       frame_type = QT_UINT8 ((guint8 *) svmi->data + 12);
10581       frame_layout = QT_UINT8 ((guint8 *) svmi->data + 13) & 0x01;
10582       switch (frame_type) {
10583         case 0:
10584           mode = GST_VIDEO_MULTIVIEW_MODE_SIDE_BY_SIDE;
10585           break;
10586         case 1:
10587           mode = GST_VIDEO_MULTIVIEW_MODE_ROW_INTERLEAVED;
10588           break;
10589         case 2:
10590           mode = GST_VIDEO_MULTIVIEW_MODE_FRAME_BY_FRAME;
10591           break;
10592         case 3:
10593           /* mode 3 is primary/secondary view sequence, ie
10594            * left/right views in separate tracks. See section 7.2
10595            * of ISO/IEC 23000-11:2009 */
10596           GST_FIXME_OBJECT (qtdemux,
10597               "Implement stereo video in separate streams");
10598       }
10599
10600       if ((frame_layout & 0x1) == 0)
10601         flags |= GST_VIDEO_MULTIVIEW_FLAGS_RIGHT_VIEW_FIRST;
10602
10603       GST_LOG_OBJECT (qtdemux,
10604           "StereoVideo: composition type: %u, is_left_first: %u",
10605           frame_type, frame_layout);
10606       stream->multiview_mode = mode;
10607       stream->multiview_flags = flags;
10608     }
10609   }
10610
10611   /* parse rest of tkhd */
10612   if (stream->subtype == FOURCC_vide) {
10613     guint32 matrix[9];
10614
10615     /* version 1 uses some 64-bit ints */
10616     if (!gst_byte_reader_skip (&tkhd, 20 + value_size))
10617       goto corrupt_file;
10618
10619     if (!qtdemux_parse_transformation_matrix (qtdemux, &tkhd, matrix, "tkhd"))
10620       goto corrupt_file;
10621
10622     if (!gst_byte_reader_get_uint32_be (&tkhd, &w)
10623         || !gst_byte_reader_get_uint32_be (&tkhd, &h))
10624       goto corrupt_file;
10625
10626     qtdemux_inspect_transformation_matrix (qtdemux, stream, matrix,
10627         &stream->stream_tags);
10628   }
10629
10630   /* parse stsd */
10631   if (!(stsd = qtdemux_tree_get_child_by_type (stbl, FOURCC_stsd)))
10632     goto corrupt_file;
10633   stsd_data = (const guint8 *) stsd->data;
10634
10635   /* stsd should at least have one entry */
10636   stsd_len = QT_UINT32 (stsd_data);
10637   if (stsd_len < 24) {
10638     /* .. but skip stream with empty stsd produced by some Vivotek cameras */
10639     if (stream->subtype == FOURCC_vivo) {
10640       gst_qtdemux_stream_unref (stream);
10641       return TRUE;
10642     } else {
10643       goto corrupt_file;
10644     }
10645   }
10646
10647   stream->stsd_entries_length = stsd_entry_count = QT_UINT32 (stsd_data + 12);
10648   stream->stsd_entries = g_new0 (QtDemuxStreamStsdEntry, stsd_entry_count);
10649   GST_LOG_OBJECT (qtdemux, "stsd len:           %d", stsd_len);
10650   GST_LOG_OBJECT (qtdemux, "stsd entry count:   %u", stsd_entry_count);
10651
10652   stsd_entry_data = stsd_data + 16;
10653   remaining_stsd_len = stsd_len - 16;
10654   for (stsd_index = 0; stsd_index < stsd_entry_count; stsd_index++) {
10655     guint32 fourcc;
10656     gchar *codec = NULL;
10657     QtDemuxStreamStsdEntry *entry = &stream->stsd_entries[stsd_index];
10658
10659     /* and that entry should fit within stsd */
10660     len = QT_UINT32 (stsd_entry_data);
10661     if (len > remaining_stsd_len)
10662       goto corrupt_file;
10663
10664     entry->fourcc = fourcc = QT_FOURCC (stsd_entry_data + 4);
10665     GST_LOG_OBJECT (qtdemux, "stsd type:          %" GST_FOURCC_FORMAT,
10666         GST_FOURCC_ARGS (entry->fourcc));
10667     GST_LOG_OBJECT (qtdemux, "stsd type len:      %d", len);
10668
10669     if ((fourcc == FOURCC_drms) || (fourcc == FOURCC_drmi))
10670       goto error_encrypted;
10671
10672     if (fourcc == FOURCC_encv || fourcc == FOURCC_enca) {
10673       /* FIXME this looks wrong, there might be multiple children
10674        * with the same type */
10675       GNode *enc = qtdemux_tree_get_child_by_type (stsd, fourcc);
10676       stream->protected = TRUE;
10677       if (!qtdemux_parse_protection_scheme_info (qtdemux, stream, enc, &fourcc))
10678         GST_ERROR_OBJECT (qtdemux, "Failed to parse protection scheme info");
10679     }
10680
10681     if (stream->subtype == FOURCC_vide) {
10682       GNode *colr;
10683       GNode *fiel;
10684       GNode *pasp;
10685       gboolean gray;
10686       gint depth, palette_size, palette_count;
10687       guint32 *palette_data = NULL;
10688
10689       entry->sampled = TRUE;
10690
10691       stream->display_width = w >> 16;
10692       stream->display_height = h >> 16;
10693
10694       offset = 16;
10695       if (len < 86)             /* TODO verify */
10696         goto corrupt_file;
10697
10698       entry->width = QT_UINT16 (stsd_entry_data + offset + 16);
10699       entry->height = QT_UINT16 (stsd_entry_data + offset + 18);
10700       entry->fps_n = 0;         /* this is filled in later */
10701       entry->fps_d = 0;         /* this is filled in later */
10702       entry->bits_per_sample = QT_UINT16 (stsd_entry_data + offset + 66);
10703       entry->color_table_id = QT_UINT16 (stsd_entry_data + offset + 68);
10704
10705       /* if color_table_id is 0, ctab atom must follow; however some files
10706        * produced by TMPEGEnc have color_table_id = 0 and no ctab atom, so
10707        * if color table is not present we'll correct the value */
10708       if (entry->color_table_id == 0 &&
10709           (len < 90
10710               || QT_FOURCC (stsd_entry_data + offset + 70) != FOURCC_ctab)) {
10711         entry->color_table_id = -1;
10712       }
10713
10714       GST_LOG_OBJECT (qtdemux, "width %d, height %d, bps %d, color table id %d",
10715           entry->width, entry->height, entry->bits_per_sample,
10716           entry->color_table_id);
10717
10718       depth = entry->bits_per_sample;
10719
10720       /* more than 32 bits means grayscale */
10721       gray = (depth > 32);
10722       /* low 32 bits specify the depth  */
10723       depth &= 0x1F;
10724
10725       /* different number of palette entries is determined by depth. */
10726       palette_count = 0;
10727       if ((depth == 1) || (depth == 2) || (depth == 4) || (depth == 8))
10728         palette_count = (1 << depth);
10729       palette_size = palette_count * 4;
10730
10731       if (entry->color_table_id) {
10732         switch (palette_count) {
10733           case 0:
10734             break;
10735           case 2:
10736             palette_data = g_memdup (ff_qt_default_palette_2, palette_size);
10737             break;
10738           case 4:
10739             palette_data = g_memdup (ff_qt_default_palette_4, palette_size);
10740             break;
10741           case 16:
10742             if (gray)
10743               palette_data =
10744                   g_memdup (ff_qt_grayscale_palette_16, palette_size);
10745             else
10746               palette_data = g_memdup (ff_qt_default_palette_16, palette_size);
10747             break;
10748           case 256:
10749             if (gray)
10750               palette_data =
10751                   g_memdup (ff_qt_grayscale_palette_256, palette_size);
10752             else
10753               palette_data = g_memdup (ff_qt_default_palette_256, palette_size);
10754             break;
10755           default:
10756             GST_ELEMENT_WARNING (qtdemux, STREAM, DEMUX,
10757                 (_("The video in this file might not play correctly.")),
10758                 ("unsupported palette depth %d", depth));
10759             break;
10760         }
10761       } else {
10762         gint i, j, start, end;
10763
10764         if (len < 94)
10765           goto corrupt_file;
10766
10767         /* read table */
10768         start = QT_UINT32 (stsd_entry_data + offset + 70);
10769         palette_count = QT_UINT16 (stsd_entry_data + offset + 74);
10770         end = QT_UINT16 (stsd_entry_data + offset + 76);
10771
10772         GST_LOG_OBJECT (qtdemux, "start %d, end %d, palette_count %d",
10773             start, end, palette_count);
10774
10775         if (end > 255)
10776           end = 255;
10777         if (start > end)
10778           start = end;
10779
10780         if (len < 94 + (end - start) * 8)
10781           goto corrupt_file;
10782
10783         /* palette is always the same size */
10784         palette_data = g_malloc0 (256 * 4);
10785         palette_size = 256 * 4;
10786
10787         for (j = 0, i = start; i <= end; j++, i++) {
10788           guint32 a, r, g, b;
10789
10790           a = QT_UINT16 (stsd_entry_data + offset + 78 + (j * 8));
10791           r = QT_UINT16 (stsd_entry_data + offset + 80 + (j * 8));
10792           g = QT_UINT16 (stsd_entry_data + offset + 82 + (j * 8));
10793           b = QT_UINT16 (stsd_entry_data + offset + 84 + (j * 8));
10794
10795           palette_data[i] = ((a & 0xff00) << 16) | ((r & 0xff00) << 8) |
10796               (g & 0xff00) | (b >> 8);
10797         }
10798       }
10799
10800       if (entry->caps)
10801         gst_caps_unref (entry->caps);
10802
10803       entry->caps =
10804           qtdemux_video_caps (qtdemux, stream, entry, fourcc, stsd_entry_data,
10805           &codec);
10806       if (G_UNLIKELY (!entry->caps)) {
10807         g_free (palette_data);
10808         goto unknown_stream;
10809       }
10810
10811       if (codec) {
10812         gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
10813             GST_TAG_VIDEO_CODEC, codec, NULL);
10814         g_free (codec);
10815         codec = NULL;
10816       }
10817
10818       if (palette_data) {
10819         GstStructure *s;
10820
10821         if (entry->rgb8_palette)
10822           gst_memory_unref (entry->rgb8_palette);
10823         entry->rgb8_palette = gst_memory_new_wrapped (GST_MEMORY_FLAG_READONLY,
10824             palette_data, palette_size, 0, palette_size, palette_data, g_free);
10825
10826         s = gst_caps_get_structure (entry->caps, 0);
10827
10828         /* non-raw video has a palette_data property. raw video has the palette as
10829          * an extra plane that we append to the output buffers before we push
10830          * them*/
10831         if (!gst_structure_has_name (s, "video/x-raw")) {
10832           GstBuffer *palette;
10833
10834           palette = gst_buffer_new ();
10835           gst_buffer_append_memory (palette, entry->rgb8_palette);
10836           entry->rgb8_palette = NULL;
10837
10838           gst_caps_set_simple (entry->caps, "palette_data",
10839               GST_TYPE_BUFFER, palette, NULL);
10840           gst_buffer_unref (palette);
10841         }
10842       } else if (palette_count != 0) {
10843         GST_ELEMENT_WARNING (qtdemux, STREAM, NOT_IMPLEMENTED,
10844             (NULL), ("Unsupported palette depth %d", depth));
10845       }
10846
10847       GST_LOG_OBJECT (qtdemux, "frame count:   %u",
10848           QT_UINT16 (stsd_entry_data + offset + 32));
10849
10850       esds = NULL;
10851       pasp = NULL;
10852       colr = NULL;
10853       fiel = NULL;
10854       /* pick 'the' stsd child */
10855       mp4v = qtdemux_tree_get_child_by_index (stsd, stsd_index);
10856       // We should skip parsing the stsd for non-protected streams if
10857       // the entry doesn't match the fourcc, since they don't change
10858       // format. However, for protected streams we can have partial
10859       // encryption, where parts of the stream are encrypted and parts
10860       // not. For both parts of such streams, we should ensure the
10861       // esds overrides are parsed for both from the stsd.
10862       if (QTDEMUX_TREE_NODE_FOURCC (mp4v) != fourcc) {
10863         if (stream->protected && QTDEMUX_TREE_NODE_FOURCC (mp4v) != FOURCC_encv)
10864           mp4v = NULL;
10865         else if (!stream->protected)
10866           mp4v = NULL;
10867       }
10868
10869       if (mp4v) {
10870         esds = qtdemux_tree_get_child_by_type (mp4v, FOURCC_esds);
10871         pasp = qtdemux_tree_get_child_by_type (mp4v, FOURCC_pasp);
10872         colr = qtdemux_tree_get_child_by_type (mp4v, FOURCC_colr);
10873         fiel = qtdemux_tree_get_child_by_type (mp4v, FOURCC_fiel);
10874       }
10875
10876       if (pasp) {
10877         const guint8 *pasp_data = (const guint8 *) pasp->data;
10878         gint len = QT_UINT32 (pasp_data);
10879
10880         if (len == 16) {
10881           CUR_STREAM (stream)->par_w = QT_UINT32 (pasp_data + 8);
10882           CUR_STREAM (stream)->par_h = QT_UINT32 (pasp_data + 12);
10883         } else {
10884           CUR_STREAM (stream)->par_w = 0;
10885           CUR_STREAM (stream)->par_h = 0;
10886         }
10887       } else {
10888         CUR_STREAM (stream)->par_w = 0;
10889         CUR_STREAM (stream)->par_h = 0;
10890       }
10891
10892       if (fiel) {
10893         const guint8 *fiel_data = (const guint8 *) fiel->data;
10894         gint len = QT_UINT32 (fiel_data);
10895
10896         if (len == 10) {
10897           CUR_STREAM (stream)->interlace_mode = GST_READ_UINT8 (fiel_data + 8);
10898           CUR_STREAM (stream)->field_order = GST_READ_UINT8 (fiel_data + 9);
10899         }
10900       }
10901
10902       if (colr) {
10903         const guint8 *colr_data = (const guint8 *) colr->data;
10904         gint len = QT_UINT32 (colr_data);
10905
10906         if (len == 19 || len == 18) {
10907           guint32 color_type = GST_READ_UINT32_LE (colr_data + 8);
10908
10909           if (color_type == FOURCC_nclx || color_type == FOURCC_nclc) {
10910             guint16 primaries = GST_READ_UINT16_BE (colr_data + 12);
10911             guint16 transfer_function = GST_READ_UINT16_BE (colr_data + 14);
10912             guint16 matrix = GST_READ_UINT16_BE (colr_data + 16);
10913             gboolean full_range = len == 19 ? colr_data[17] >> 7 : FALSE;
10914
10915             switch (primaries) {
10916               case 1:
10917                 CUR_STREAM (stream)->colorimetry.primaries =
10918                     GST_VIDEO_COLOR_PRIMARIES_BT709;
10919                 break;
10920               case 5:
10921                 CUR_STREAM (stream)->colorimetry.primaries =
10922                     GST_VIDEO_COLOR_PRIMARIES_BT470BG;
10923                 break;
10924               case 6:
10925                 CUR_STREAM (stream)->colorimetry.primaries =
10926                     GST_VIDEO_COLOR_PRIMARIES_SMPTE170M;
10927                 break;
10928               case 9:
10929                 CUR_STREAM (stream)->colorimetry.primaries =
10930                     GST_VIDEO_COLOR_PRIMARIES_BT2020;
10931                 break;
10932               default:
10933                 break;
10934             }
10935
10936             switch (transfer_function) {
10937               case 1:
10938                 CUR_STREAM (stream)->colorimetry.transfer =
10939                     GST_VIDEO_TRANSFER_BT709;
10940                 break;
10941               case 7:
10942                 CUR_STREAM (stream)->colorimetry.transfer =
10943                     GST_VIDEO_TRANSFER_SMPTE240M;
10944                 break;
10945               default:
10946                 break;
10947             }
10948
10949             switch (matrix) {
10950               case 1:
10951                 CUR_STREAM (stream)->colorimetry.matrix =
10952                     GST_VIDEO_COLOR_MATRIX_BT709;
10953                 break;
10954               case 6:
10955                 CUR_STREAM (stream)->colorimetry.matrix =
10956                     GST_VIDEO_COLOR_MATRIX_BT601;
10957                 break;
10958               case 7:
10959                 CUR_STREAM (stream)->colorimetry.matrix =
10960                     GST_VIDEO_COLOR_MATRIX_SMPTE240M;
10961                 break;
10962               case 9:
10963                 CUR_STREAM (stream)->colorimetry.matrix =
10964                     GST_VIDEO_COLOR_MATRIX_BT2020;
10965                 break;
10966               default:
10967                 break;
10968             }
10969
10970             CUR_STREAM (stream)->colorimetry.range =
10971                 full_range ? GST_VIDEO_COLOR_RANGE_0_255 :
10972                 GST_VIDEO_COLOR_RANGE_16_235;
10973           } else {
10974             GST_DEBUG_OBJECT (qtdemux, "Unsupported color type");
10975           }
10976         } else {
10977           GST_WARNING_OBJECT (qtdemux, "Invalid colr atom size");
10978         }
10979       }
10980
10981       if (esds) {
10982         gst_qtdemux_handle_esds (qtdemux, stream, entry, esds,
10983             stream->stream_tags);
10984       } else {
10985         switch (fourcc) {
10986           case FOURCC_H264:
10987           case FOURCC_avc1:
10988           case FOURCC_avc3:
10989           {
10990             gint len = QT_UINT32 (stsd_entry_data) - 0x56;
10991             const guint8 *avc_data = stsd_entry_data + 0x56;
10992
10993             /* find avcC */
10994             while (len >= 0x8) {
10995               gint size;
10996
10997               if (QT_UINT32 (avc_data) <= len)
10998                 size = QT_UINT32 (avc_data) - 0x8;
10999               else
11000                 size = len - 0x8;
11001
11002               if (size < 1)
11003                 /* No real data, so break out */
11004                 break;
11005
11006               switch (QT_FOURCC (avc_data + 0x4)) {
11007                 case FOURCC_avcC:
11008                 {
11009                   /* parse, if found */
11010                   GstBuffer *buf;
11011
11012                   GST_DEBUG_OBJECT (qtdemux, "found avcC codec_data in stsd");
11013
11014                   /* First 4 bytes are the length of the atom, the next 4 bytes
11015                    * are the fourcc, the next 1 byte is the version, and the
11016                    * subsequent bytes are profile_tier_level structure like data. */
11017                   gst_codec_utils_h264_caps_set_level_and_profile (entry->caps,
11018                       avc_data + 8 + 1, size - 1);
11019                   buf = gst_buffer_new_and_alloc (size);
11020                   gst_buffer_fill (buf, 0, avc_data + 0x8, size);
11021                   gst_caps_set_simple (entry->caps,
11022                       "codec_data", GST_TYPE_BUFFER, buf, NULL);
11023                   gst_buffer_unref (buf);
11024
11025                   break;
11026                 }
11027                 case FOURCC_strf:
11028                 {
11029                   GstBuffer *buf;
11030
11031                   GST_DEBUG_OBJECT (qtdemux, "found strf codec_data in stsd");
11032
11033                   /* First 4 bytes are the length of the atom, the next 4 bytes
11034                    * are the fourcc, next 40 bytes are BITMAPINFOHEADER,
11035                    * next 1 byte is the version, and the
11036                    * subsequent bytes are sequence parameter set like data. */
11037
11038                   size -= 40;   /* we'll be skipping BITMAPINFOHEADER */
11039                   if (size > 1) {
11040                     gst_codec_utils_h264_caps_set_level_and_profile
11041                         (entry->caps, avc_data + 8 + 40 + 1, size - 1);
11042
11043                     buf = gst_buffer_new_and_alloc (size);
11044                     gst_buffer_fill (buf, 0, avc_data + 8 + 40, size);
11045                     gst_caps_set_simple (entry->caps,
11046                         "codec_data", GST_TYPE_BUFFER, buf, NULL);
11047                     gst_buffer_unref (buf);
11048                   }
11049                   break;
11050                 }
11051                 case FOURCC_btrt:
11052                 {
11053                   guint avg_bitrate, max_bitrate;
11054
11055                   /* bufferSizeDB, maxBitrate and avgBitrate - 4 bytes each */
11056                   if (size < 12)
11057                     break;
11058
11059                   max_bitrate = QT_UINT32 (avc_data + 0xc);
11060                   avg_bitrate = QT_UINT32 (avc_data + 0x10);
11061
11062                   if (!max_bitrate && !avg_bitrate)
11063                     break;
11064
11065                   /* Some muxers seem to swap the average and maximum bitrates
11066                    * (I'm looking at you, YouTube), so we swap for sanity. */
11067                   if (max_bitrate > 0 && max_bitrate < avg_bitrate) {
11068                     guint temp = avg_bitrate;
11069
11070                     avg_bitrate = max_bitrate;
11071                     max_bitrate = temp;
11072                   }
11073
11074                   if (max_bitrate > 0 && max_bitrate < G_MAXUINT32) {
11075                     gst_tag_list_add (stream->stream_tags,
11076                         GST_TAG_MERGE_REPLACE, GST_TAG_MAXIMUM_BITRATE,
11077                         max_bitrate, NULL);
11078                   }
11079                   if (avg_bitrate > 0 && avg_bitrate < G_MAXUINT32) {
11080                     gst_tag_list_add (stream->stream_tags,
11081                         GST_TAG_MERGE_REPLACE, GST_TAG_BITRATE, avg_bitrate,
11082                         NULL);
11083                   }
11084
11085                   break;
11086                 }
11087
11088                 default:
11089                   break;
11090               }
11091
11092               len -= size + 8;
11093               avc_data += size + 8;
11094             }
11095
11096             break;
11097           }
11098           case FOURCC_H265:
11099           case FOURCC_hvc1:
11100           case FOURCC_hev1:
11101           {
11102             gint len = QT_UINT32 (stsd_entry_data) - 0x56;
11103             const guint8 *hevc_data = stsd_entry_data + 0x56;
11104
11105             /* find hevc */
11106             while (len >= 0x8) {
11107               gint size;
11108
11109               if (QT_UINT32 (hevc_data) <= len)
11110                 size = QT_UINT32 (hevc_data) - 0x8;
11111               else
11112                 size = len - 0x8;
11113
11114               if (size < 1)
11115                 /* No real data, so break out */
11116                 break;
11117
11118               switch (QT_FOURCC (hevc_data + 0x4)) {
11119                 case FOURCC_hvcC:
11120                 {
11121                   /* parse, if found */
11122                   GstBuffer *buf;
11123
11124                   GST_DEBUG_OBJECT (qtdemux, "found hvcC codec_data in stsd");
11125
11126                   /* First 4 bytes are the length of the atom, the next 4 bytes
11127                    * are the fourcc, the next 1 byte is the version, and the
11128                    * subsequent bytes are sequence parameter set like data. */
11129                   gst_codec_utils_h265_caps_set_level_tier_and_profile
11130                       (entry->caps, hevc_data + 8 + 1, size - 1);
11131
11132                   buf = gst_buffer_new_and_alloc (size);
11133                   gst_buffer_fill (buf, 0, hevc_data + 0x8, size);
11134                   gst_caps_set_simple (entry->caps,
11135                       "codec_data", GST_TYPE_BUFFER, buf, NULL);
11136                   gst_buffer_unref (buf);
11137                   break;
11138                 }
11139                 default:
11140                   break;
11141               }
11142               len -= size + 8;
11143               hevc_data += size + 8;
11144             }
11145             break;
11146           }
11147           case FOURCC_mp4v:
11148           case FOURCC_MP4V:
11149           case FOURCC_fmp4:
11150           case FOURCC_FMP4:
11151           case FOURCC_xvid:
11152           case FOURCC_XVID:
11153           {
11154             GNode *glbl;
11155
11156             GST_DEBUG_OBJECT (qtdemux, "found %" GST_FOURCC_FORMAT,
11157                 GST_FOURCC_ARGS (fourcc));
11158
11159             /* codec data might be in glbl extension atom */
11160             glbl = mp4v ?
11161                 qtdemux_tree_get_child_by_type (mp4v, FOURCC_glbl) : NULL;
11162             if (glbl) {
11163               guint8 *data;
11164               GstBuffer *buf;
11165               gint len;
11166
11167               GST_DEBUG_OBJECT (qtdemux, "found glbl data in stsd");
11168               data = glbl->data;
11169               len = QT_UINT32 (data);
11170               if (len > 0x8) {
11171                 len -= 0x8;
11172                 buf = gst_buffer_new_and_alloc (len);
11173                 gst_buffer_fill (buf, 0, data + 8, len);
11174                 gst_caps_set_simple (entry->caps,
11175                     "codec_data", GST_TYPE_BUFFER, buf, NULL);
11176                 gst_buffer_unref (buf);
11177               }
11178             }
11179             break;
11180           }
11181           case FOURCC_mjp2:
11182           {
11183             /* see annex I of the jpeg2000 spec */
11184             GNode *jp2h, *ihdr, *colr, *mjp2, *field, *prefix, *cmap, *cdef;
11185             const guint8 *data;
11186             const gchar *colorspace = NULL;
11187             gint ncomp = 0;
11188             guint32 ncomp_map = 0;
11189             gint32 *comp_map = NULL;
11190             guint32 nchan_def = 0;
11191             gint32 *chan_def = NULL;
11192
11193             GST_DEBUG_OBJECT (qtdemux, "found mjp2");
11194             /* some required atoms */
11195             mjp2 = qtdemux_tree_get_child_by_index (stsd, stsd_index);
11196             if (!mjp2)
11197               break;
11198             jp2h = qtdemux_tree_get_child_by_type (mjp2, FOURCC_jp2h);
11199             if (!jp2h)
11200               break;
11201
11202             /* number of components; redundant with info in codestream, but useful
11203                to a muxer */
11204             ihdr = qtdemux_tree_get_child_by_type (jp2h, FOURCC_ihdr);
11205             if (!ihdr || QT_UINT32 (ihdr->data) != 22)
11206               break;
11207             ncomp = QT_UINT16 (((guint8 *) ihdr->data) + 16);
11208
11209             colr = qtdemux_tree_get_child_by_type (jp2h, FOURCC_colr);
11210             if (!colr)
11211               break;
11212             GST_DEBUG_OBJECT (qtdemux, "found colr");
11213             /* extract colour space info */
11214             if (QT_UINT8 ((guint8 *) colr->data + 8) == 1) {
11215               switch (QT_UINT32 ((guint8 *) colr->data + 11)) {
11216                 case 16:
11217                   colorspace = "sRGB";
11218                   break;
11219                 case 17:
11220                   colorspace = "GRAY";
11221                   break;
11222                 case 18:
11223                   colorspace = "sYUV";
11224                   break;
11225                 default:
11226                   colorspace = NULL;
11227                   break;
11228               }
11229             }
11230             if (!colorspace)
11231               /* colr is required, and only values 16, 17, and 18 are specified,
11232                  so error if we have no colorspace */
11233               break;
11234
11235             /* extract component mapping */
11236             cmap = qtdemux_tree_get_child_by_type (jp2h, FOURCC_cmap);
11237             if (cmap) {
11238               guint32 cmap_len = 0;
11239               int i;
11240               cmap_len = QT_UINT32 (cmap->data);
11241               if (cmap_len >= 8) {
11242                 /* normal box, subtract off header */
11243                 cmap_len -= 8;
11244                 /* cmap: { u16 cmp; u8 mtyp; u8 pcol; }* */
11245                 if (cmap_len % 4 == 0) {
11246                   ncomp_map = (cmap_len / 4);
11247                   comp_map = g_new0 (gint32, ncomp_map);
11248                   for (i = 0; i < ncomp_map; i++) {
11249                     guint16 cmp;
11250                     guint8 mtyp, pcol;
11251                     cmp = QT_UINT16 (((guint8 *) cmap->data) + 8 + i * 4);
11252                     mtyp = QT_UINT8 (((guint8 *) cmap->data) + 8 + i * 4 + 2);
11253                     pcol = QT_UINT8 (((guint8 *) cmap->data) + 8 + i * 4 + 3);
11254                     comp_map[i] = (mtyp << 24) | (pcol << 16) | cmp;
11255                   }
11256                 }
11257               }
11258             }
11259             /* extract channel definitions */
11260             cdef = qtdemux_tree_get_child_by_type (jp2h, FOURCC_cdef);
11261             if (cdef) {
11262               guint32 cdef_len = 0;
11263               int i;
11264               cdef_len = QT_UINT32 (cdef->data);
11265               if (cdef_len >= 10) {
11266                 /* normal box, subtract off header and len */
11267                 cdef_len -= 10;
11268                 /* cdef: u16 n; { u16 cn; u16 typ; u16 asoc; }* */
11269                 if (cdef_len % 6 == 0) {
11270                   nchan_def = (cdef_len / 6);
11271                   chan_def = g_new0 (gint32, nchan_def);
11272                   for (i = 0; i < nchan_def; i++)
11273                     chan_def[i] = -1;
11274                   for (i = 0; i < nchan_def; i++) {
11275                     guint16 cn, typ, asoc;
11276                     cn = QT_UINT16 (((guint8 *) cdef->data) + 10 + i * 6);
11277                     typ = QT_UINT16 (((guint8 *) cdef->data) + 10 + i * 6 + 2);
11278                     asoc = QT_UINT16 (((guint8 *) cdef->data) + 10 + i * 6 + 4);
11279                     if (cn < nchan_def) {
11280                       switch (typ) {
11281                         case 0:
11282                           chan_def[cn] = asoc;
11283                           break;
11284                         case 1:
11285                           chan_def[cn] = 0;     /* alpha */
11286                           break;
11287                         default:
11288                           chan_def[cn] = -typ;
11289                       }
11290                     }
11291                   }
11292                 }
11293               }
11294             }
11295
11296             gst_caps_set_simple (entry->caps,
11297                 "num-components", G_TYPE_INT, ncomp, NULL);
11298             gst_caps_set_simple (entry->caps,
11299                 "colorspace", G_TYPE_STRING, colorspace, NULL);
11300
11301             if (comp_map) {
11302               GValue arr = { 0, };
11303               GValue elt = { 0, };
11304               int i;
11305               g_value_init (&arr, GST_TYPE_ARRAY);
11306               g_value_init (&elt, G_TYPE_INT);
11307               for (i = 0; i < ncomp_map; i++) {
11308                 g_value_set_int (&elt, comp_map[i]);
11309                 gst_value_array_append_value (&arr, &elt);
11310               }
11311               gst_structure_set_value (gst_caps_get_structure (entry->caps, 0),
11312                   "component-map", &arr);
11313               g_value_unset (&elt);
11314               g_value_unset (&arr);
11315               g_free (comp_map);
11316             }
11317
11318             if (chan_def) {
11319               GValue arr = { 0, };
11320               GValue elt = { 0, };
11321               int i;
11322               g_value_init (&arr, GST_TYPE_ARRAY);
11323               g_value_init (&elt, G_TYPE_INT);
11324               for (i = 0; i < nchan_def; i++) {
11325                 g_value_set_int (&elt, chan_def[i]);
11326                 gst_value_array_append_value (&arr, &elt);
11327               }
11328               gst_structure_set_value (gst_caps_get_structure (entry->caps, 0),
11329                   "channel-definitions", &arr);
11330               g_value_unset (&elt);
11331               g_value_unset (&arr);
11332               g_free (chan_def);
11333             }
11334
11335             /* some optional atoms */
11336             field = qtdemux_tree_get_child_by_type (mjp2, FOURCC_fiel);
11337             prefix = qtdemux_tree_get_child_by_type (mjp2, FOURCC_jp2x);
11338
11339             /* indicate possible fields in caps */
11340             if (field) {
11341               data = (guint8 *) field->data + 8;
11342               if (*data != 1)
11343                 gst_caps_set_simple (entry->caps, "fields", G_TYPE_INT,
11344                     (gint) * data, NULL);
11345             }
11346             /* add codec_data if provided */
11347             if (prefix) {
11348               GstBuffer *buf;
11349               gint len;
11350
11351               GST_DEBUG_OBJECT (qtdemux, "found prefix data in stsd");
11352               data = prefix->data;
11353               len = QT_UINT32 (data);
11354               if (len > 0x8) {
11355                 len -= 0x8;
11356                 buf = gst_buffer_new_and_alloc (len);
11357                 gst_buffer_fill (buf, 0, data + 8, len);
11358                 gst_caps_set_simple (entry->caps,
11359                     "codec_data", GST_TYPE_BUFFER, buf, NULL);
11360                 gst_buffer_unref (buf);
11361               }
11362             }
11363             break;
11364           }
11365           case FOURCC_SVQ3:
11366           case FOURCC_VP31:
11367           {
11368             GstBuffer *buf;
11369             GstBuffer *seqh = NULL;
11370             const guint8 *gamma_data = NULL;
11371             gint len = QT_UINT32 (stsd_data);   /* FIXME review - why put the whole stsd in codec data? */
11372
11373             qtdemux_parse_svq3_stsd_data (qtdemux, stsd_entry_data, &gamma_data,
11374                 &seqh);
11375             if (gamma_data) {
11376               gst_caps_set_simple (entry->caps, "applied-gamma", G_TYPE_DOUBLE,
11377                   QT_FP32 (gamma_data), NULL);
11378             }
11379             if (seqh) {
11380               /* sorry for the bad name, but we don't know what this is, other
11381                * than its own fourcc */
11382               gst_caps_set_simple (entry->caps, "seqh", GST_TYPE_BUFFER, seqh,
11383                   NULL);
11384               gst_buffer_unref (seqh);
11385             }
11386
11387             GST_DEBUG_OBJECT (qtdemux, "found codec_data in stsd");
11388             buf = gst_buffer_new_and_alloc (len);
11389             gst_buffer_fill (buf, 0, stsd_data, len);
11390             gst_caps_set_simple (entry->caps,
11391                 "codec_data", GST_TYPE_BUFFER, buf, NULL);
11392             gst_buffer_unref (buf);
11393             break;
11394           }
11395           case FOURCC_jpeg:
11396           {
11397             /* https://developer.apple.com/standards/qtff-2001.pdf,
11398              * page 92, "Video Sample Description", under table 3.1 */
11399             GstByteReader br;
11400
11401             const gint compressor_offset =
11402                 16 + 4 + 4 * 3 + 2 * 2 + 2 * 4 + 4 + 2;
11403             const gint min_size = compressor_offset + 32 + 2 + 2;
11404             GNode *jpeg;
11405             guint32 len;
11406             guint16 color_table_id = 0;
11407             gboolean ok;
11408
11409             GST_DEBUG_OBJECT (qtdemux, "found jpeg");
11410
11411             /* recover information on interlaced/progressive */
11412             jpeg = qtdemux_tree_get_child_by_type (stsd, FOURCC_jpeg);
11413             if (!jpeg)
11414               break;
11415
11416             len = QT_UINT32 (jpeg->data);
11417             GST_DEBUG_OBJECT (qtdemux, "Found jpeg: len %u, need %d", len,
11418                 min_size);
11419             if (len >= min_size) {
11420               gst_byte_reader_init (&br, jpeg->data, len);
11421
11422               gst_byte_reader_skip (&br, compressor_offset + 32 + 2);
11423               gst_byte_reader_get_uint16_le (&br, &color_table_id);
11424               if (color_table_id != 0) {
11425                 /* the spec says there can be concatenated chunks in the data, and we want
11426                  * to find one called field. Walk through them. */
11427                 gint offset = min_size;
11428                 while (offset + 8 < len) {
11429                   guint32 size = 0, tag;
11430                   ok = gst_byte_reader_get_uint32_le (&br, &size);
11431                   ok &= gst_byte_reader_get_uint32_le (&br, &tag);
11432                   if (!ok || size < 8) {
11433                     GST_WARNING_OBJECT (qtdemux,
11434                         "Failed to walk optional chunk list");
11435                     break;
11436                   }
11437                   GST_DEBUG_OBJECT (qtdemux,
11438                       "Found optional %4.4s chunk, size %u",
11439                       (const char *) &tag, size);
11440                   if (tag == FOURCC_fiel) {
11441                     guint8 n_fields = 0, ordering = 0;
11442                     gst_byte_reader_get_uint8 (&br, &n_fields);
11443                     gst_byte_reader_get_uint8 (&br, &ordering);
11444                     if (n_fields == 1 || n_fields == 2) {
11445                       GST_DEBUG_OBJECT (qtdemux,
11446                           "Found fiel tag with %u fields, ordering %u",
11447                           n_fields, ordering);
11448                       if (n_fields == 2)
11449                         gst_caps_set_simple (CUR_STREAM (stream)->caps,
11450                             "interlace-mode", G_TYPE_STRING, "interleaved",
11451                             NULL);
11452                     } else {
11453                       GST_WARNING_OBJECT (qtdemux,
11454                           "Found fiel tag with invalid fields (%u)", n_fields);
11455                     }
11456                   }
11457                   offset += size;
11458                 }
11459               } else {
11460                 GST_DEBUG_OBJECT (qtdemux,
11461                     "Color table ID is 0, not trying to get interlacedness");
11462               }
11463             } else {
11464               GST_WARNING_OBJECT (qtdemux,
11465                   "Length of jpeg chunk is too small, not trying to get interlacedness");
11466             }
11467
11468             break;
11469           }
11470           case FOURCC_rle_:
11471           case FOURCC_WRLE:
11472           {
11473             gst_caps_set_simple (entry->caps,
11474                 "depth", G_TYPE_INT, QT_UINT16 (stsd_entry_data + offset + 66),
11475                 NULL);
11476             break;
11477           }
11478           case FOURCC_XiTh:
11479           {
11480             GNode *xith, *xdxt;
11481
11482             GST_DEBUG_OBJECT (qtdemux, "found XiTh");
11483             xith = qtdemux_tree_get_child_by_index (stsd, stsd_index);
11484             if (!xith)
11485               break;
11486
11487             xdxt = qtdemux_tree_get_child_by_type (xith, FOURCC_XdxT);
11488             if (!xdxt)
11489               break;
11490
11491             GST_DEBUG_OBJECT (qtdemux, "found XdxT node");
11492             /* collect the headers and store them in a stream list so that we can
11493              * send them out first */
11494             qtdemux_parse_theora_extension (qtdemux, stream, xdxt);
11495             break;
11496           }
11497           case FOURCC_ovc1:
11498           {
11499             GNode *ovc1;
11500             guint8 *ovc1_data;
11501             guint ovc1_len;
11502             GstBuffer *buf;
11503
11504             GST_DEBUG_OBJECT (qtdemux, "parse ovc1 header");
11505             ovc1 = qtdemux_tree_get_child_by_index (stsd, stsd_index);
11506             if (!ovc1)
11507               break;
11508             ovc1_data = ovc1->data;
11509             ovc1_len = QT_UINT32 (ovc1_data);
11510             if (ovc1_len <= 198) {
11511               GST_WARNING_OBJECT (qtdemux, "Too small ovc1 header, skipping");
11512               break;
11513             }
11514             buf = gst_buffer_new_and_alloc (ovc1_len - 198);
11515             gst_buffer_fill (buf, 0, ovc1_data + 198, ovc1_len - 198);
11516             gst_caps_set_simple (entry->caps,
11517                 "codec_data", GST_TYPE_BUFFER, buf, NULL);
11518             gst_buffer_unref (buf);
11519             break;
11520           }
11521           case FOURCC_vc_1:
11522           {
11523             gint len = QT_UINT32 (stsd_entry_data) - 0x56;
11524             const guint8 *vc1_data = stsd_entry_data + 0x56;
11525
11526             /* find dvc1 */
11527             while (len >= 8) {
11528               gint size;
11529
11530               if (QT_UINT32 (vc1_data) <= len)
11531                 size = QT_UINT32 (vc1_data) - 8;
11532               else
11533                 size = len - 8;
11534
11535               if (size < 1)
11536                 /* No real data, so break out */
11537                 break;
11538
11539               switch (QT_FOURCC (vc1_data + 0x4)) {
11540                 case GST_MAKE_FOURCC ('d', 'v', 'c', '1'):
11541                 {
11542                   GstBuffer *buf;
11543
11544                   GST_DEBUG_OBJECT (qtdemux, "found dvc1 codec_data in stsd");
11545                   buf = gst_buffer_new_and_alloc (size);
11546                   gst_buffer_fill (buf, 0, vc1_data + 8, size);
11547                   gst_caps_set_simple (entry->caps,
11548                       "codec_data", GST_TYPE_BUFFER, buf, NULL);
11549                   gst_buffer_unref (buf);
11550                   break;
11551                 }
11552                 default:
11553                   break;
11554               }
11555               len -= size + 8;
11556               vc1_data += size + 8;
11557             }
11558             break;
11559           }
11560           case FOURCC_av01:
11561           {
11562             gint len = QT_UINT32 (stsd_entry_data) - 0x56;
11563             const guint8 *av1_data = stsd_entry_data + 0x56;
11564
11565             /* find av1C */
11566             while (len >= 0x8) {
11567               gint size;
11568
11569               if (QT_UINT32 (av1_data) <= len)
11570                 size = QT_UINT32 (av1_data) - 0x8;
11571               else
11572                 size = len - 0x8;
11573
11574               if (size < 1)
11575                 /* No real data, so break out */
11576                 break;
11577
11578               switch (QT_FOURCC (av1_data + 0x4)) {
11579                 case FOURCC_av1C:
11580                 {
11581                   /* parse, if found */
11582                   GstBuffer *buf;
11583                   guint8 pres_delay_field;
11584
11585                   GST_DEBUG_OBJECT (qtdemux,
11586                       "found av1C codec_data in stsd of size %d", size);
11587
11588                   /* not enough data, just ignore and hope for the best */
11589                   if (size < 5)
11590                     break;
11591
11592                   /* Content is:
11593                    * 4 bytes: atom length
11594                    * 4 bytes: fourcc
11595                    * 1 byte: version
11596                    * 3 bytes: flags
11597                    * 3 bits: reserved
11598                    * 1 bits:  initial_presentation_delay_present
11599                    * 4 bits: initial_presentation_delay (if present else reserved
11600                    * rest: OBUs.
11601                    */
11602
11603                   if (av1_data[9] != 0) {
11604                     GST_WARNING ("Unknown version %d of av1C box", av1_data[9]);
11605                     break;
11606                   }
11607
11608                   /* We skip initial_presentation_delay* for now */
11609                   pres_delay_field = *(av1_data + 12);
11610                   if (pres_delay_field & (1 << 5)) {
11611                     gst_caps_set_simple (entry->caps,
11612                         "presentation-delay", G_TYPE_INT,
11613                         (gint) (pres_delay_field & 0x0F) + 1, NULL);
11614                   }
11615                   if (size > 5) {
11616                     buf = gst_buffer_new_and_alloc (size - 5);
11617                     GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_HEADER);
11618                     gst_buffer_fill (buf, 0, av1_data + 13, size - 5);
11619                     gst_caps_set_simple (entry->caps,
11620                         "codec_data", GST_TYPE_BUFFER, buf, NULL);
11621                     gst_buffer_unref (buf);
11622                   }
11623                   break;
11624                 }
11625                 default:
11626                   break;
11627               }
11628
11629               len -= size + 8;
11630               av1_data += size + 8;
11631             }
11632
11633             break;
11634           }
11635           default:
11636             break;
11637         }
11638       }
11639
11640       GST_INFO_OBJECT (qtdemux,
11641           "type %" GST_FOURCC_FORMAT " caps %" GST_PTR_FORMAT,
11642           GST_FOURCC_ARGS (fourcc), entry->caps);
11643
11644     } else if (stream->subtype == FOURCC_soun) {
11645       GNode *wave;
11646       int version, samplesize;
11647       guint16 compression_id;
11648       gboolean amrwb = FALSE;
11649
11650       offset = 16;
11651       /* sample description entry (16) + sound sample description v0 (20) */
11652       if (len < 36)
11653         goto corrupt_file;
11654
11655       version = QT_UINT32 (stsd_entry_data + offset);
11656       entry->n_channels = QT_UINT16 (stsd_entry_data + offset + 8);
11657       samplesize = QT_UINT16 (stsd_entry_data + offset + 10);
11658       compression_id = QT_UINT16 (stsd_entry_data + offset + 12);
11659       entry->rate = QT_FP32 (stsd_entry_data + offset + 16);
11660
11661       GST_LOG_OBJECT (qtdemux, "version/rev:      %08x", version);
11662       GST_LOG_OBJECT (qtdemux, "vendor:           %08x",
11663           QT_UINT32 (stsd_entry_data + offset + 4));
11664       GST_LOG_OBJECT (qtdemux, "n_channels:       %d", entry->n_channels);
11665       GST_LOG_OBJECT (qtdemux, "sample_size:      %d", samplesize);
11666       GST_LOG_OBJECT (qtdemux, "compression_id:   %d", compression_id);
11667       GST_LOG_OBJECT (qtdemux, "packet size:      %d",
11668           QT_UINT16 (stsd_entry_data + offset + 14));
11669       GST_LOG_OBJECT (qtdemux, "sample rate:      %g", entry->rate);
11670
11671       if (compression_id == 0xfffe)
11672         entry->sampled = TRUE;
11673
11674       /* first assume uncompressed audio */
11675       entry->bytes_per_sample = samplesize / 8;
11676       entry->samples_per_frame = entry->n_channels;
11677       entry->bytes_per_frame = entry->n_channels * entry->bytes_per_sample;
11678       entry->samples_per_packet = entry->samples_per_frame;
11679       entry->bytes_per_packet = entry->bytes_per_sample;
11680
11681       offset = 36;
11682       switch (fourcc) {
11683           /* Yes, these have to be hard-coded */
11684         case FOURCC_MAC6:
11685         {
11686           entry->samples_per_packet = 6;
11687           entry->bytes_per_packet = 1;
11688           entry->bytes_per_frame = 1 * entry->n_channels;
11689           entry->bytes_per_sample = 1;
11690           entry->samples_per_frame = 6 * entry->n_channels;
11691           break;
11692         }
11693         case FOURCC_MAC3:
11694         {
11695           entry->samples_per_packet = 3;
11696           entry->bytes_per_packet = 1;
11697           entry->bytes_per_frame = 1 * entry->n_channels;
11698           entry->bytes_per_sample = 1;
11699           entry->samples_per_frame = 3 * entry->n_channels;
11700           break;
11701         }
11702         case FOURCC_ima4:
11703         {
11704           entry->samples_per_packet = 64;
11705           entry->bytes_per_packet = 34;
11706           entry->bytes_per_frame = 34 * entry->n_channels;
11707           entry->bytes_per_sample = 2;
11708           entry->samples_per_frame = 64 * entry->n_channels;
11709           break;
11710         }
11711         case FOURCC_ulaw:
11712         case FOURCC_alaw:
11713         {
11714           entry->samples_per_packet = 1;
11715           entry->bytes_per_packet = 1;
11716           entry->bytes_per_frame = 1 * entry->n_channels;
11717           entry->bytes_per_sample = 1;
11718           entry->samples_per_frame = 1 * entry->n_channels;
11719           break;
11720         }
11721         case FOURCC_agsm:
11722         {
11723           entry->samples_per_packet = 160;
11724           entry->bytes_per_packet = 33;
11725           entry->bytes_per_frame = 33 * entry->n_channels;
11726           entry->bytes_per_sample = 2;
11727           entry->samples_per_frame = 160 * entry->n_channels;
11728           break;
11729         }
11730         default:
11731           break;
11732       }
11733
11734       if (version == 0x00010000) {
11735         /* sample description entry (16) + sound sample description v1 (20+16) */
11736         if (len < 52)
11737           goto corrupt_file;
11738
11739         switch (fourcc) {
11740           case FOURCC_twos:
11741           case FOURCC_sowt:
11742           case FOURCC_raw_:
11743           case FOURCC_lpcm:
11744             break;
11745           default:
11746           {
11747             /* only parse extra decoding config for non-pcm audio */
11748             entry->samples_per_packet = QT_UINT32 (stsd_entry_data + offset);
11749             entry->bytes_per_packet = QT_UINT32 (stsd_entry_data + offset + 4);
11750             entry->bytes_per_frame = QT_UINT32 (stsd_entry_data + offset + 8);
11751             entry->bytes_per_sample = QT_UINT32 (stsd_entry_data + offset + 12);
11752
11753             GST_LOG_OBJECT (qtdemux, "samples/packet:   %d",
11754                 entry->samples_per_packet);
11755             GST_LOG_OBJECT (qtdemux, "bytes/packet:     %d",
11756                 entry->bytes_per_packet);
11757             GST_LOG_OBJECT (qtdemux, "bytes/frame:      %d",
11758                 entry->bytes_per_frame);
11759             GST_LOG_OBJECT (qtdemux, "bytes/sample:     %d",
11760                 entry->bytes_per_sample);
11761
11762             if (!entry->sampled && entry->bytes_per_packet) {
11763               entry->samples_per_frame = (entry->bytes_per_frame /
11764                   entry->bytes_per_packet) * entry->samples_per_packet;
11765               GST_LOG_OBJECT (qtdemux, "samples/frame:    %d",
11766                   entry->samples_per_frame);
11767             }
11768             break;
11769           }
11770         }
11771       } else if (version == 0x00020000) {
11772         union
11773         {
11774           gdouble fp;
11775           guint64 val;
11776         } qtfp;
11777
11778         /* sample description entry (16) + sound sample description v2 (56) */
11779         if (len < 72)
11780           goto corrupt_file;
11781
11782         qtfp.val = QT_UINT64 (stsd_entry_data + offset + 4);
11783         entry->rate = qtfp.fp;
11784         entry->n_channels = QT_UINT32 (stsd_entry_data + offset + 12);
11785
11786         GST_LOG_OBJECT (qtdemux, "Sound sample description Version 2");
11787         GST_LOG_OBJECT (qtdemux, "sample rate:        %g", entry->rate);
11788         GST_LOG_OBJECT (qtdemux, "n_channels:         %d", entry->n_channels);
11789         GST_LOG_OBJECT (qtdemux, "bits/channel:       %d",
11790             QT_UINT32 (stsd_entry_data + offset + 20));
11791         GST_LOG_OBJECT (qtdemux, "format flags:       %X",
11792             QT_UINT32 (stsd_entry_data + offset + 24));
11793         GST_LOG_OBJECT (qtdemux, "bytes/packet:       %d",
11794             QT_UINT32 (stsd_entry_data + offset + 28));
11795         GST_LOG_OBJECT (qtdemux, "LPCM frames/packet: %d",
11796             QT_UINT32 (stsd_entry_data + offset + 32));
11797       } else if (version != 0x00000) {
11798         GST_WARNING_OBJECT (qtdemux, "unknown audio STSD version %08x",
11799             version);
11800       }
11801
11802       if (entry->caps)
11803         gst_caps_unref (entry->caps);
11804
11805       entry->caps = qtdemux_audio_caps (qtdemux, stream, entry, fourcc,
11806           stsd_entry_data + 32, len - 16, &codec);
11807
11808       switch (fourcc) {
11809         case FOURCC_in24:
11810         {
11811           GNode *enda;
11812           GNode *in24;
11813
11814           in24 = qtdemux_tree_get_child_by_type (stsd, FOURCC_in24);
11815
11816           enda = qtdemux_tree_get_child_by_type (in24, FOURCC_enda);
11817           if (!enda) {
11818             wave = qtdemux_tree_get_child_by_type (in24, FOURCC_wave);
11819             if (wave)
11820               enda = qtdemux_tree_get_child_by_type (wave, FOURCC_enda);
11821           }
11822           if (enda) {
11823             int enda_value = QT_UINT16 ((guint8 *) enda->data + 8);
11824             gst_caps_set_simple (entry->caps,
11825                 "format", G_TYPE_STRING, (enda_value) ? "S24LE" : "S24BE",
11826                 NULL);
11827           }
11828           break;
11829         }
11830         case FOURCC_owma:
11831         {
11832           const guint8 *owma_data;
11833           const gchar *codec_name = NULL;
11834           guint owma_len;
11835           GstBuffer *buf;
11836           gint version = 1;
11837           /* from http://msdn.microsoft.com/en-us/library/dd757720(VS.85).aspx */
11838           /* FIXME this should also be gst_riff_strf_auds,
11839            * but the latter one is actually missing bits-per-sample :( */
11840           typedef struct
11841           {
11842             gint16 wFormatTag;
11843             gint16 nChannels;
11844             gint32 nSamplesPerSec;
11845             gint32 nAvgBytesPerSec;
11846             gint16 nBlockAlign;
11847             gint16 wBitsPerSample;
11848             gint16 cbSize;
11849           } WAVEFORMATEX;
11850           WAVEFORMATEX *wfex;
11851
11852           GST_DEBUG_OBJECT (qtdemux, "parse owma");
11853           owma_data = stsd_entry_data;
11854           owma_len = QT_UINT32 (owma_data);
11855           if (owma_len <= 54) {
11856             GST_WARNING_OBJECT (qtdemux, "Too small owma header, skipping");
11857             break;
11858           }
11859           wfex = (WAVEFORMATEX *) (owma_data + 36);
11860           buf = gst_buffer_new_and_alloc (owma_len - 54);
11861           gst_buffer_fill (buf, 0, owma_data + 54, owma_len - 54);
11862           if (wfex->wFormatTag == 0x0161) {
11863             codec_name = "Windows Media Audio";
11864             version = 2;
11865           } else if (wfex->wFormatTag == 0x0162) {
11866             codec_name = "Windows Media Audio 9 Pro";
11867             version = 3;
11868           } else if (wfex->wFormatTag == 0x0163) {
11869             codec_name = "Windows Media Audio 9 Lossless";
11870             /* is that correct? gstffmpegcodecmap.c is missing it, but
11871              * fluendo codec seems to support it */
11872             version = 4;
11873           }
11874
11875           gst_caps_set_simple (entry->caps,
11876               "codec_data", GST_TYPE_BUFFER, buf,
11877               "wmaversion", G_TYPE_INT, version,
11878               "block_align", G_TYPE_INT,
11879               GST_READ_UINT16_LE (&wfex->nBlockAlign), "bitrate", G_TYPE_INT,
11880               GST_READ_UINT32_LE (&wfex->nAvgBytesPerSec), "width", G_TYPE_INT,
11881               GST_READ_UINT16_LE (&wfex->wBitsPerSample), "depth", G_TYPE_INT,
11882               GST_READ_UINT16_LE (&wfex->wBitsPerSample), NULL);
11883           gst_buffer_unref (buf);
11884
11885           if (codec_name) {
11886             g_free (codec);
11887             codec = g_strdup (codec_name);
11888           }
11889           break;
11890         }
11891         case FOURCC_wma_:
11892         {
11893           gint len = QT_UINT32 (stsd_entry_data) - offset;
11894           const guint8 *wfex_data = stsd_entry_data + offset;
11895           const gchar *codec_name = NULL;
11896           gint version = 1;
11897           /* from http://msdn.microsoft.com/en-us/library/dd757720(VS.85).aspx */
11898           /* FIXME this should also be gst_riff_strf_auds,
11899            * but the latter one is actually missing bits-per-sample :( */
11900           typedef struct
11901           {
11902             gint16 wFormatTag;
11903             gint16 nChannels;
11904             gint32 nSamplesPerSec;
11905             gint32 nAvgBytesPerSec;
11906             gint16 nBlockAlign;
11907             gint16 wBitsPerSample;
11908             gint16 cbSize;
11909           } WAVEFORMATEX;
11910           WAVEFORMATEX wfex;
11911
11912           /* FIXME: unify with similar wavformatex parsing code above */
11913           GST_DEBUG_OBJECT (qtdemux, "parse wma, looking for wfex");
11914
11915           /* find wfex */
11916           while (len >= 8) {
11917             gint size;
11918
11919             if (QT_UINT32 (wfex_data) <= len)
11920               size = QT_UINT32 (wfex_data) - 8;
11921             else
11922               size = len - 8;
11923
11924             if (size < 1)
11925               /* No real data, so break out */
11926               break;
11927
11928             switch (QT_FOURCC (wfex_data + 4)) {
11929               case GST_MAKE_FOURCC ('w', 'f', 'e', 'x'):
11930               {
11931                 GST_DEBUG_OBJECT (qtdemux, "found wfex in stsd");
11932
11933                 if (size < 8 + 18)
11934                   break;
11935
11936                 wfex.wFormatTag = GST_READ_UINT16_LE (wfex_data + 8 + 0);
11937                 wfex.nChannels = GST_READ_UINT16_LE (wfex_data + 8 + 2);
11938                 wfex.nSamplesPerSec = GST_READ_UINT32_LE (wfex_data + 8 + 4);
11939                 wfex.nAvgBytesPerSec = GST_READ_UINT32_LE (wfex_data + 8 + 8);
11940                 wfex.nBlockAlign = GST_READ_UINT16_LE (wfex_data + 8 + 12);
11941                 wfex.wBitsPerSample = GST_READ_UINT16_LE (wfex_data + 8 + 14);
11942                 wfex.cbSize = GST_READ_UINT16_LE (wfex_data + 8 + 16);
11943
11944                 GST_LOG_OBJECT (qtdemux, "Found wfex box in stsd:");
11945                 GST_LOG_OBJECT (qtdemux, "FormatTag = 0x%04x, Channels = %u, "
11946                     "SamplesPerSec = %u, AvgBytesPerSec = %u, BlockAlign = %u, "
11947                     "BitsPerSample = %u, Size = %u", wfex.wFormatTag,
11948                     wfex.nChannels, wfex.nSamplesPerSec, wfex.nAvgBytesPerSec,
11949                     wfex.nBlockAlign, wfex.wBitsPerSample, wfex.cbSize);
11950
11951                 if (wfex.wFormatTag == 0x0161) {
11952                   codec_name = "Windows Media Audio";
11953                   version = 2;
11954                 } else if (wfex.wFormatTag == 0x0162) {
11955                   codec_name = "Windows Media Audio 9 Pro";
11956                   version = 3;
11957                 } else if (wfex.wFormatTag == 0x0163) {
11958                   codec_name = "Windows Media Audio 9 Lossless";
11959                   /* is that correct? gstffmpegcodecmap.c is missing it, but
11960                    * fluendo codec seems to support it */
11961                   version = 4;
11962                 }
11963
11964                 gst_caps_set_simple (entry->caps,
11965                     "wmaversion", G_TYPE_INT, version,
11966                     "block_align", G_TYPE_INT, wfex.nBlockAlign,
11967                     "bitrate", G_TYPE_INT, wfex.nAvgBytesPerSec,
11968                     "width", G_TYPE_INT, wfex.wBitsPerSample,
11969                     "depth", G_TYPE_INT, wfex.wBitsPerSample, NULL);
11970
11971                 if (size > wfex.cbSize) {
11972                   GstBuffer *buf;
11973
11974                   buf = gst_buffer_new_and_alloc (size - wfex.cbSize);
11975                   gst_buffer_fill (buf, 0, wfex_data + 8 + wfex.cbSize,
11976                       size - wfex.cbSize);
11977                   gst_caps_set_simple (entry->caps,
11978                       "codec_data", GST_TYPE_BUFFER, buf, NULL);
11979                   gst_buffer_unref (buf);
11980                 } else {
11981                   GST_WARNING_OBJECT (qtdemux, "no codec data");
11982                 }
11983
11984                 if (codec_name) {
11985                   g_free (codec);
11986                   codec = g_strdup (codec_name);
11987                 }
11988                 break;
11989               }
11990               default:
11991                 break;
11992             }
11993             len -= size + 8;
11994             wfex_data += size + 8;
11995           }
11996           break;
11997         }
11998         case FOURCC_opus:
11999         {
12000           const guint8 *opus_data;
12001           guint8 *channel_mapping = NULL;
12002           guint32 rate;
12003           guint8 channels;
12004           guint8 channel_mapping_family;
12005           guint8 stream_count;
12006           guint8 coupled_count;
12007           guint8 i;
12008
12009           opus_data = stsd_entry_data;
12010
12011           channels = GST_READ_UINT8 (opus_data + 45);
12012           rate = GST_READ_UINT32_LE (opus_data + 48);
12013           channel_mapping_family = GST_READ_UINT8 (opus_data + 54);
12014           stream_count = GST_READ_UINT8 (opus_data + 55);
12015           coupled_count = GST_READ_UINT8 (opus_data + 56);
12016
12017           if (channels > 0) {
12018             channel_mapping = g_malloc (channels * sizeof (guint8));
12019             for (i = 0; i < channels; i++)
12020               channel_mapping[i] = GST_READ_UINT8 (opus_data + i + 57);
12021           }
12022
12023           entry->caps = gst_codec_utils_opus_create_caps (rate, channels,
12024               channel_mapping_family, stream_count, coupled_count,
12025               channel_mapping);
12026           break;
12027         }
12028         default:
12029           break;
12030       }
12031
12032       if (codec) {
12033         GstStructure *s;
12034         gint bitrate = 0;
12035
12036         gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
12037             GST_TAG_AUDIO_CODEC, codec, NULL);
12038         g_free (codec);
12039         codec = NULL;
12040
12041         /* some bitrate info may have ended up in caps */
12042         s = gst_caps_get_structure (entry->caps, 0);
12043         gst_structure_get_int (s, "bitrate", &bitrate);
12044         if (bitrate > 0)
12045           gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
12046               GST_TAG_BITRATE, bitrate, NULL);
12047       }
12048
12049       mp4a = qtdemux_tree_get_child_by_index (stsd, stsd_index);
12050       if (QTDEMUX_TREE_NODE_FOURCC (mp4a) != fourcc) {
12051         if (stream->protected && QTDEMUX_TREE_NODE_FOURCC (mp4a) != FOURCC_enca)
12052           mp4a = NULL;
12053         else if (!stream->protected)
12054           mp4a = NULL;
12055       }
12056
12057       wave = NULL;
12058       esds = NULL;
12059       if (mp4a) {
12060         wave = qtdemux_tree_get_child_by_type (mp4a, FOURCC_wave);
12061         if (wave)
12062           esds = qtdemux_tree_get_child_by_type (wave, FOURCC_esds);
12063         if (!esds)
12064           esds = qtdemux_tree_get_child_by_type (mp4a, FOURCC_esds);
12065       }
12066
12067
12068       /* If the fourcc's bottom 16 bits gives 'sm', then the top
12069          16 bits is a byte-swapped wave-style codec identifier,
12070          and we can find a WAVE header internally to a 'wave' atom here.
12071          This can more clearly be thought of as 'ms' as the top 16 bits, and a
12072          codec id as the bottom 16 bits - but byte-swapped to store in QT (which
12073          is big-endian).
12074        */
12075       if ((fourcc & 0xffff) == (('s' << 8) | 'm')) {
12076         if (len < offset + 20) {
12077           GST_WARNING_OBJECT (qtdemux, "No wave atom in MS-style audio");
12078         } else {
12079           guint32 datalen = QT_UINT32 (stsd_entry_data + offset + 16);
12080           const guint8 *data = stsd_entry_data + offset + 16;
12081           GNode *wavenode;
12082           GNode *waveheadernode;
12083
12084           wavenode = g_node_new ((guint8 *) data);
12085           if (qtdemux_parse_node (qtdemux, wavenode, data, datalen)) {
12086             const guint8 *waveheader;
12087             guint32 headerlen;
12088
12089             waveheadernode = qtdemux_tree_get_child_by_type (wavenode, fourcc);
12090             if (waveheadernode) {
12091               waveheader = (const guint8 *) waveheadernode->data;
12092               headerlen = QT_UINT32 (waveheader);
12093
12094               if (headerlen > 8) {
12095                 gst_riff_strf_auds *header = NULL;
12096                 GstBuffer *headerbuf;
12097                 GstBuffer *extra;
12098
12099                 waveheader += 8;
12100                 headerlen -= 8;
12101
12102                 headerbuf = gst_buffer_new_and_alloc (headerlen);
12103                 gst_buffer_fill (headerbuf, 0, waveheader, headerlen);
12104
12105                 if (gst_riff_parse_strf_auds (GST_ELEMENT_CAST (qtdemux),
12106                         headerbuf, &header, &extra)) {
12107                   gst_caps_unref (entry->caps);
12108                   /* FIXME: Need to do something with the channel reorder map */
12109                   entry->caps =
12110                       gst_riff_create_audio_caps (header->format, NULL, header,
12111                       extra, NULL, NULL, NULL);
12112
12113                   if (extra)
12114                     gst_buffer_unref (extra);
12115                   g_free (header);
12116                 }
12117               }
12118             } else
12119               GST_DEBUG ("Didn't find waveheadernode for this codec");
12120           }
12121           g_node_destroy (wavenode);
12122         }
12123       } else if (esds) {
12124         gst_qtdemux_handle_esds (qtdemux, stream, entry, esds,
12125             stream->stream_tags);
12126       } else {
12127         switch (fourcc) {
12128 #if 0
12129             /* FIXME: what is in the chunk? */
12130           case FOURCC_QDMC:
12131           {
12132             gint len = QT_UINT32 (stsd_data);
12133
12134             /* seems to be always = 116 = 0x74 */
12135             break;
12136           }
12137 #endif
12138           case FOURCC_QDM2:
12139           {
12140             gint len = QT_UINT32 (stsd_entry_data);
12141
12142             if (len > 0x3C) {
12143               GstBuffer *buf = gst_buffer_new_and_alloc (len - 0x3C);
12144
12145               gst_buffer_fill (buf, 0, stsd_entry_data + 0x3C, len - 0x3C);
12146               gst_caps_set_simple (entry->caps,
12147                   "codec_data", GST_TYPE_BUFFER, buf, NULL);
12148               gst_buffer_unref (buf);
12149             }
12150             gst_caps_set_simple (entry->caps,
12151                 "samplesize", G_TYPE_INT, samplesize, NULL);
12152             break;
12153           }
12154           case FOURCC_alac:
12155           {
12156             GNode *alac, *wave = NULL;
12157
12158             /* apparently, m4a has this atom appended directly in the stsd entry,
12159              * while mov has it in a wave atom */
12160             alac = qtdemux_tree_get_child_by_type (stsd, FOURCC_alac);
12161             if (alac) {
12162               /* alac now refers to stsd entry atom */
12163               wave = qtdemux_tree_get_child_by_type (alac, FOURCC_wave);
12164               if (wave)
12165                 alac = qtdemux_tree_get_child_by_type (wave, FOURCC_alac);
12166               else
12167                 alac = qtdemux_tree_get_child_by_type (alac, FOURCC_alac);
12168             }
12169             if (alac) {
12170               const guint8 *alac_data = alac->data;
12171               gint len = QT_UINT32 (alac->data);
12172               GstBuffer *buf;
12173
12174               if (len < 36) {
12175                 GST_DEBUG_OBJECT (qtdemux,
12176                     "discarding alac atom with unexpected len %d", len);
12177               } else {
12178                 /* codec-data contains alac atom size and prefix,
12179                  * ffmpeg likes it that way, not quite gst-ish though ...*/
12180                 buf = gst_buffer_new_and_alloc (len);
12181                 gst_buffer_fill (buf, 0, alac->data, len);
12182                 gst_caps_set_simple (entry->caps,
12183                     "codec_data", GST_TYPE_BUFFER, buf, NULL);
12184                 gst_buffer_unref (buf);
12185
12186                 entry->bytes_per_frame = QT_UINT32 (alac_data + 12);
12187                 entry->n_channels = QT_UINT8 (alac_data + 21);
12188                 entry->rate = QT_UINT32 (alac_data + 32);
12189               }
12190             }
12191             gst_caps_set_simple (entry->caps,
12192                 "samplesize", G_TYPE_INT, samplesize, NULL);
12193             break;
12194           }
12195           case FOURCC_fLaC:
12196           {
12197             /* The codingname of the sample entry is 'fLaC' */
12198             GNode *flac = qtdemux_tree_get_child_by_type (stsd, FOURCC_fLaC);
12199
12200             if (flac) {
12201               /* The 'dfLa' box is added to the sample entry to convey
12202                  initializing information for the decoder. */
12203               const GNode *dfla =
12204                   qtdemux_tree_get_child_by_type (flac, FOURCC_dfLa);
12205
12206               if (dfla) {
12207                 const guint32 len = QT_UINT32 (dfla->data);
12208
12209                 /* Must contain at least dfLa box header (12),
12210                  * METADATA_BLOCK_HEADER (4), METADATA_BLOCK_STREAMINFO (34) */
12211                 if (len < 50) {
12212                   GST_DEBUG_OBJECT (qtdemux,
12213                       "discarding dfla atom with unexpected len %d", len);
12214                 } else {
12215                   /* skip dfLa header to get the METADATA_BLOCKs */
12216                   const guint8 *metadata_blocks = (guint8 *) dfla->data + 12;
12217                   const guint32 metadata_blocks_len = len - 12;
12218
12219                   gchar *stream_marker = g_strdup ("fLaC");
12220                   GstBuffer *block = gst_buffer_new_wrapped (stream_marker,
12221                       strlen (stream_marker));
12222
12223                   guint32 index = 0;
12224                   guint32 remainder = 0;
12225                   guint32 block_size = 0;
12226                   gboolean is_last = FALSE;
12227
12228                   GValue array = G_VALUE_INIT;
12229                   GValue value = G_VALUE_INIT;
12230
12231                   g_value_init (&array, GST_TYPE_ARRAY);
12232                   g_value_init (&value, GST_TYPE_BUFFER);
12233
12234                   gst_value_set_buffer (&value, block);
12235                   gst_value_array_append_value (&array, &value);
12236                   g_value_reset (&value);
12237
12238                   gst_buffer_unref (block);
12239
12240                   /* check there's at least one METADATA_BLOCK_HEADER's worth
12241                    * of data, and we haven't already finished parsing */
12242                   while (!is_last && ((index + 3) < metadata_blocks_len)) {
12243                     remainder = metadata_blocks_len - index;
12244
12245                     /* add the METADATA_BLOCK_HEADER size to the signalled size */
12246                     block_size = 4 +
12247                         (metadata_blocks[index + 1] << 16) +
12248                         (metadata_blocks[index + 2] << 8) +
12249                         metadata_blocks[index + 3];
12250
12251                     /* be careful not to read off end of box */
12252                     if (block_size > remainder) {
12253                       break;
12254                     }
12255
12256                     is_last = metadata_blocks[index] >> 7;
12257
12258                     block = gst_buffer_new_and_alloc (block_size);
12259
12260                     gst_buffer_fill (block, 0, &metadata_blocks[index],
12261                         block_size);
12262
12263                     gst_value_set_buffer (&value, block);
12264                     gst_value_array_append_value (&array, &value);
12265                     g_value_reset (&value);
12266
12267                     gst_buffer_unref (block);
12268
12269                     index += block_size;
12270                   }
12271
12272                   /* only append the metadata if we successfully read all of it */
12273                   if (is_last) {
12274                     gst_structure_set_value (gst_caps_get_structure (CUR_STREAM
12275                             (stream)->caps, 0), "streamheader", &array);
12276                   } else {
12277                     GST_WARNING_OBJECT (qtdemux,
12278                         "discarding all METADATA_BLOCKs due to invalid "
12279                         "block_size %d at idx %d, rem %d", block_size, index,
12280                         remainder);
12281                   }
12282
12283                   g_value_unset (&value);
12284                   g_value_unset (&array);
12285
12286                   /* The sample rate obtained from the stsd may not be accurate
12287                    * since it cannot represent rates greater than 65535Hz, so
12288                    * override that value with the sample rate from the
12289                    * METADATA_BLOCK_STREAMINFO block */
12290                   CUR_STREAM (stream)->rate =
12291                       (QT_UINT32 (metadata_blocks + 14) >> 12) & 0xFFFFF;
12292                 }
12293               }
12294             }
12295             break;
12296           }
12297           case FOURCC_sawb:
12298             /* Fallthrough! */
12299             amrwb = TRUE;
12300           case FOURCC_samr:
12301           {
12302             gint len = QT_UINT32 (stsd_entry_data);
12303
12304             if (len > 0x24) {
12305               GstBuffer *buf = gst_buffer_new_and_alloc (len - 0x24);
12306               guint bitrate;
12307
12308               gst_buffer_fill (buf, 0, stsd_entry_data + 0x24, len - 0x24);
12309
12310               /* If we have enough data, let's try to get the 'damr' atom. See
12311                * the 3GPP container spec (26.244) for more details. */
12312               if ((len - 0x34) > 8 &&
12313                   (bitrate = qtdemux_parse_amr_bitrate (buf, amrwb))) {
12314                 gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
12315                     GST_TAG_MAXIMUM_BITRATE, bitrate, NULL);
12316               }
12317
12318               gst_caps_set_simple (entry->caps,
12319                   "codec_data", GST_TYPE_BUFFER, buf, NULL);
12320               gst_buffer_unref (buf);
12321             }
12322             break;
12323           }
12324           case FOURCC_mp4a:
12325           {
12326             /* mp4a atom withtout ESDS; Attempt to build codec data from atom */
12327             gint len = QT_UINT32 (stsd_entry_data);
12328
12329             if (len >= 34) {
12330               guint16 sound_version = QT_UINT16 (stsd_entry_data + 16);
12331
12332               if (sound_version == 1) {
12333                 guint16 channels = QT_UINT16 (stsd_entry_data + 24);
12334                 guint32 time_scale = QT_UINT32 (stsd_entry_data + 30);
12335                 guint8 codec_data[2];
12336                 GstBuffer *buf;
12337                 gint profile = 2;       /* FIXME: Can this be determined somehow? There doesn't seem to be anything in mp4a atom that specifis compression */
12338
12339                 gint sample_rate_index =
12340                     gst_codec_utils_aac_get_index_from_sample_rate (time_scale);
12341
12342                 /* build AAC codec data */
12343                 codec_data[0] = profile << 3;
12344                 codec_data[0] |= ((sample_rate_index >> 1) & 0x7);
12345                 codec_data[1] = (sample_rate_index & 0x01) << 7;
12346                 codec_data[1] |= (channels & 0xF) << 3;
12347
12348                 buf = gst_buffer_new_and_alloc (2);
12349                 gst_buffer_fill (buf, 0, codec_data, 2);
12350                 gst_caps_set_simple (entry->caps,
12351                     "codec_data", GST_TYPE_BUFFER, buf, NULL);
12352                 gst_buffer_unref (buf);
12353               }
12354             }
12355             break;
12356           }
12357           case FOURCC_lpcm:
12358             /* Fully handled elsewhere */
12359             break;
12360           default:
12361             GST_INFO_OBJECT (qtdemux,
12362                 "unhandled type %" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (fourcc));
12363             break;
12364         }
12365       }
12366       GST_INFO_OBJECT (qtdemux,
12367           "type %" GST_FOURCC_FORMAT " caps %" GST_PTR_FORMAT,
12368           GST_FOURCC_ARGS (fourcc), entry->caps);
12369
12370     } else if (stream->subtype == FOURCC_strm) {
12371       if (fourcc == FOURCC_rtsp) {
12372         stream->redirect_uri = qtdemux_get_rtsp_uri_from_hndl (qtdemux, minf);
12373       } else {
12374         GST_INFO_OBJECT (qtdemux, "unhandled stream type %" GST_FOURCC_FORMAT,
12375             GST_FOURCC_ARGS (fourcc));
12376         goto unknown_stream;
12377       }
12378       entry->sampled = TRUE;
12379     } else if (stream->subtype == FOURCC_subp || stream->subtype == FOURCC_text
12380         || stream->subtype == FOURCC_sbtl || stream->subtype == FOURCC_subt
12381         || stream->subtype == FOURCC_clcp) {
12382
12383       entry->sampled = TRUE;
12384       entry->sparse = TRUE;
12385
12386       entry->caps =
12387           qtdemux_sub_caps (qtdemux, stream, entry, fourcc, stsd_entry_data,
12388           &codec);
12389       if (codec) {
12390         gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
12391             GST_TAG_SUBTITLE_CODEC, codec, NULL);
12392         g_free (codec);
12393         codec = NULL;
12394       }
12395
12396       /* hunt for sort-of codec data */
12397       switch (fourcc) {
12398         case FOURCC_mp4s:
12399         {
12400           GNode *mp4s = NULL;
12401           GNode *esds = NULL;
12402
12403           /* look for palette in a stsd->mp4s->esds sub-atom */
12404           mp4s = qtdemux_tree_get_child_by_type (stsd, FOURCC_mp4s);
12405           if (mp4s)
12406             esds = qtdemux_tree_get_child_by_type (mp4s, FOURCC_esds);
12407           if (esds == NULL) {
12408             /* Invalid STSD */
12409             GST_LOG_OBJECT (qtdemux, "Skipping invalid stsd: no esds child");
12410             break;
12411           }
12412
12413           gst_qtdemux_handle_esds (qtdemux, stream, entry, esds,
12414               stream->stream_tags);
12415           break;
12416         }
12417         default:
12418           GST_INFO_OBJECT (qtdemux,
12419               "unhandled type %" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (fourcc));
12420           break;
12421       }
12422       GST_INFO_OBJECT (qtdemux,
12423           "type %" GST_FOURCC_FORMAT " caps %" GST_PTR_FORMAT,
12424           GST_FOURCC_ARGS (fourcc), entry->caps);
12425     } else {
12426       /* everything in 1 sample */
12427       entry->sampled = TRUE;
12428
12429       entry->caps =
12430           qtdemux_generic_caps (qtdemux, stream, entry, fourcc, stsd_entry_data,
12431           &codec);
12432
12433       if (entry->caps == NULL)
12434         goto unknown_stream;
12435
12436       if (codec) {
12437         gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
12438             GST_TAG_SUBTITLE_CODEC, codec, NULL);
12439         g_free (codec);
12440         codec = NULL;
12441       }
12442     }
12443
12444     /* promote to sampled format */
12445     if (entry->fourcc == FOURCC_samr) {
12446       /* force mono 8000 Hz for AMR */
12447       entry->sampled = TRUE;
12448       entry->n_channels = 1;
12449       entry->rate = 8000;
12450     } else if (entry->fourcc == FOURCC_sawb) {
12451       /* force mono 16000 Hz for AMR-WB */
12452       entry->sampled = TRUE;
12453       entry->n_channels = 1;
12454       entry->rate = 16000;
12455     } else if (entry->fourcc == FOURCC_mp4a) {
12456       entry->sampled = TRUE;
12457     }
12458
12459
12460     stsd_entry_data += len;
12461     remaining_stsd_len -= len;
12462
12463   }
12464
12465   /* collect sample information */
12466   if (!qtdemux_stbl_init (qtdemux, stream, stbl))
12467     goto samples_failed;
12468
12469   if (qtdemux->fragmented) {
12470     guint64 offset;
12471
12472     /* need all moov samples as basis; probably not many if any at all */
12473     /* prevent moof parsing taking of at this time */
12474     offset = qtdemux->moof_offset;
12475     qtdemux->moof_offset = 0;
12476     if (stream->n_samples &&
12477         !qtdemux_parse_samples (qtdemux, stream, stream->n_samples - 1)) {
12478       qtdemux->moof_offset = offset;
12479       goto samples_failed;
12480     }
12481     qtdemux->moof_offset = 0;
12482     /* movie duration more reliable in this case (e.g. mehd) */
12483     if (qtdemux->segment.duration &&
12484         GST_CLOCK_TIME_IS_VALID (qtdemux->segment.duration))
12485       stream->duration =
12486           GSTTIME_TO_QTSTREAMTIME (stream, qtdemux->segment.duration);
12487   }
12488
12489   /* configure segments */
12490   if (!qtdemux_parse_segments (qtdemux, stream, trak))
12491     goto segments_failed;
12492
12493   /* add some language tag, if useful */
12494   if (stream->lang_id[0] != '\0' && strcmp (stream->lang_id, "unk") &&
12495       strcmp (stream->lang_id, "und")) {
12496     const gchar *lang_code;
12497
12498     /* convert ISO 639-2 code to ISO 639-1 */
12499     lang_code = gst_tag_get_language_code (stream->lang_id);
12500     gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
12501         GST_TAG_LANGUAGE_CODE, (lang_code) ? lang_code : stream->lang_id, NULL);
12502   }
12503
12504   /* Check for UDTA tags */
12505   if ((udta = qtdemux_tree_get_child_by_type (trak, FOURCC_udta))) {
12506     qtdemux_parse_udta (qtdemux, stream->stream_tags, udta);
12507   }
12508
12509   /* Insert and sort new stream in track-id order.
12510    * This will help in comparing old/new streams during stream update check */
12511   g_ptr_array_add (qtdemux->active_streams, stream);
12512   g_ptr_array_sort (qtdemux->active_streams,
12513       (GCompareFunc) qtdemux_track_id_compare_func);
12514   GST_DEBUG_OBJECT (qtdemux, "n_streams is now %d",
12515       QTDEMUX_N_STREAMS (qtdemux));
12516
12517   return TRUE;
12518
12519 /* ERRORS */
12520 corrupt_file:
12521   {
12522     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
12523         (_("This file is corrupt and cannot be played.")), (NULL));
12524     if (stream)
12525       gst_qtdemux_stream_unref (stream);
12526     return FALSE;
12527   }
12528 error_encrypted:
12529   {
12530     GST_ELEMENT_ERROR (qtdemux, STREAM, DECRYPT, (NULL), (NULL));
12531     gst_qtdemux_stream_unref (stream);
12532     return FALSE;
12533   }
12534 samples_failed:
12535 segments_failed:
12536   {
12537     /* we posted an error already */
12538     /* free stbl sub-atoms */
12539     gst_qtdemux_stbl_free (stream);
12540     gst_qtdemux_stream_unref (stream);
12541     return FALSE;
12542   }
12543 existing_stream:
12544   {
12545     GST_INFO_OBJECT (qtdemux, "stream with track id %i already exists",
12546         track_id);
12547     return TRUE;
12548   }
12549 unknown_stream:
12550   {
12551     GST_INFO_OBJECT (qtdemux, "unknown subtype %" GST_FOURCC_FORMAT,
12552         GST_FOURCC_ARGS (stream->subtype));
12553     gst_qtdemux_stream_unref (stream);
12554     return TRUE;
12555   }
12556 }
12557
12558 /* If we can estimate the overall bitrate, and don't have information about the
12559  * stream bitrate for exactly one stream, this guesses the stream bitrate as
12560  * the overall bitrate minus the sum of the bitrates of all other streams. This
12561  * should be useful for the common case where we have one audio and one video
12562  * stream and can estimate the bitrate of one, but not the other. */
12563 static void
12564 gst_qtdemux_guess_bitrate (GstQTDemux * qtdemux)
12565 {
12566   QtDemuxStream *stream = NULL;
12567   gint64 size, sys_bitrate, sum_bitrate = 0;
12568   GstClockTime duration;
12569   guint bitrate;
12570   gint i;
12571
12572   if (qtdemux->fragmented)
12573     return;
12574
12575   GST_DEBUG_OBJECT (qtdemux, "Looking for streams with unknown bitrate");
12576
12577   if (!gst_pad_peer_query_duration (qtdemux->sinkpad, GST_FORMAT_BYTES, &size)
12578       || size <= 0) {
12579     GST_DEBUG_OBJECT (qtdemux,
12580         "Size in bytes of the stream not known - bailing");
12581     return;
12582   }
12583
12584   /* Subtract the header size */
12585   GST_DEBUG_OBJECT (qtdemux, "Total size %" G_GINT64_FORMAT ", header size %u",
12586       size, qtdemux->header_size);
12587
12588   if (size < qtdemux->header_size)
12589     return;
12590
12591   size = size - qtdemux->header_size;
12592
12593   if (!gst_qtdemux_get_duration (qtdemux, &duration)) {
12594     GST_DEBUG_OBJECT (qtdemux, "Stream duration not known - bailing");
12595     return;
12596   }
12597
12598   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
12599     QtDemuxStream *str = QTDEMUX_NTH_STREAM (qtdemux, i);
12600     switch (str->subtype) {
12601       case FOURCC_soun:
12602       case FOURCC_vide:
12603         GST_DEBUG_OBJECT (qtdemux, "checking bitrate for %" GST_PTR_FORMAT,
12604             CUR_STREAM (str)->caps);
12605         /* retrieve bitrate, prefer avg then max */
12606         bitrate = 0;
12607         if (str->stream_tags) {
12608           if (gst_tag_list_get_uint (str->stream_tags,
12609                   GST_TAG_MAXIMUM_BITRATE, &bitrate))
12610             GST_DEBUG_OBJECT (qtdemux, "max-bitrate: %u", bitrate);
12611           if (gst_tag_list_get_uint (str->stream_tags,
12612                   GST_TAG_NOMINAL_BITRATE, &bitrate))
12613             GST_DEBUG_OBJECT (qtdemux, "nominal-bitrate: %u", bitrate);
12614           if (gst_tag_list_get_uint (str->stream_tags,
12615                   GST_TAG_BITRATE, &bitrate))
12616             GST_DEBUG_OBJECT (qtdemux, "bitrate: %u", bitrate);
12617         }
12618         if (bitrate)
12619           sum_bitrate += bitrate;
12620         else {
12621           if (stream) {
12622             GST_DEBUG_OBJECT (qtdemux,
12623                 ">1 stream with unknown bitrate - bailing");
12624             return;
12625           } else
12626             stream = str;
12627         }
12628
12629       default:
12630         /* For other subtypes, we assume no significant impact on bitrate */
12631         break;
12632     }
12633   }
12634
12635   if (!stream) {
12636     GST_DEBUG_OBJECT (qtdemux, "All stream bitrates are known");
12637     return;
12638   }
12639
12640   sys_bitrate = gst_util_uint64_scale (size, GST_SECOND * 8, duration);
12641
12642   if (sys_bitrate < sum_bitrate) {
12643     /* This can happen, since sum_bitrate might be derived from maximum
12644      * bitrates and not average bitrates */
12645     GST_DEBUG_OBJECT (qtdemux,
12646         "System bitrate less than sum bitrate - bailing");
12647     return;
12648   }
12649
12650   bitrate = sys_bitrate - sum_bitrate;
12651   GST_DEBUG_OBJECT (qtdemux, "System bitrate = %" G_GINT64_FORMAT
12652       ", Stream bitrate = %u", sys_bitrate, bitrate);
12653
12654   if (!stream->stream_tags)
12655     stream->stream_tags = gst_tag_list_new_empty ();
12656   else
12657     stream->stream_tags = gst_tag_list_make_writable (stream->stream_tags);
12658
12659   gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
12660       GST_TAG_BITRATE, bitrate, NULL);
12661 }
12662
12663 static GstFlowReturn
12664 qtdemux_prepare_streams (GstQTDemux * qtdemux)
12665 {
12666   GstFlowReturn ret = GST_FLOW_OK;
12667   gint i;
12668
12669   GST_DEBUG_OBJECT (qtdemux, "prepare streams");
12670
12671   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
12672     QtDemuxStream *stream = QTDEMUX_NTH_STREAM (qtdemux, i);
12673     guint32 sample_num = 0;
12674
12675     GST_DEBUG_OBJECT (qtdemux, "track-id %u, fourcc %" GST_FOURCC_FORMAT,
12676         stream->track_id, GST_FOURCC_ARGS (CUR_STREAM (stream)->fourcc));
12677
12678     if (qtdemux->fragmented) {
12679       /* need all moov samples first */
12680       GST_OBJECT_LOCK (qtdemux);
12681       while (stream->n_samples == 0)
12682         if ((ret = qtdemux_add_fragmented_samples (qtdemux)) != GST_FLOW_OK)
12683           break;
12684       GST_OBJECT_UNLOCK (qtdemux);
12685     } else {
12686       /* discard any stray moof */
12687       qtdemux->moof_offset = 0;
12688     }
12689
12690     /* prepare braking */
12691     if (ret != GST_FLOW_ERROR)
12692       ret = GST_FLOW_OK;
12693
12694     /* in pull mode, we should have parsed some sample info by now;
12695      * and quite some code will not handle no samples.
12696      * in push mode, we'll just have to deal with it */
12697     if (G_UNLIKELY (qtdemux->pullbased && !stream->n_samples)) {
12698       GST_DEBUG_OBJECT (qtdemux, "no samples for stream; discarding");
12699       g_ptr_array_remove_index (qtdemux->active_streams, i);
12700       i--;
12701       continue;
12702     } else if (stream->track_id == qtdemux->chapters_track_id &&
12703         (stream->subtype == FOURCC_text || stream->subtype == FOURCC_sbtl)) {
12704       /* TODO - parse chapters track and expose it as GstToc; For now just ignore it
12705          so that it doesn't look like a subtitle track */
12706       g_ptr_array_remove_index (qtdemux->active_streams, i);
12707       i--;
12708       continue;
12709     }
12710
12711     /* parse the initial sample for use in setting the frame rate cap */
12712     while (sample_num == 0 && sample_num < stream->n_samples) {
12713       if (!qtdemux_parse_samples (qtdemux, stream, sample_num))
12714         break;
12715       ++sample_num;
12716     }
12717   }
12718
12719   return ret;
12720 }
12721
12722 static gboolean
12723 _stream_equal_func (const QtDemuxStream * stream, const gchar * stream_id)
12724 {
12725   return g_strcmp0 (stream->stream_id, stream_id) == 0;
12726 }
12727
12728 static gboolean
12729 qtdemux_is_streams_update (GstQTDemux * qtdemux)
12730 {
12731   gint i;
12732
12733   /* Different length, updated */
12734   if (QTDEMUX_N_STREAMS (qtdemux) != qtdemux->old_streams->len)
12735     return TRUE;
12736
12737   /* streams in list are sorted in track-id order */
12738   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
12739     /* Different stream-id, updated */
12740     if (g_strcmp0 (QTDEMUX_NTH_STREAM (qtdemux, i)->stream_id,
12741             QTDEMUX_NTH_OLD_STREAM (qtdemux, i)->stream_id))
12742       return TRUE;
12743   }
12744
12745   return FALSE;
12746 }
12747
12748 static gboolean
12749 qtdemux_reuse_and_configure_stream (GstQTDemux * qtdemux,
12750     QtDemuxStream * oldstream, QtDemuxStream * newstream)
12751 {
12752   /* Connect old stream's srcpad to new stream */
12753   newstream->pad = oldstream->pad;
12754   oldstream->pad = NULL;
12755
12756   /* unset new_stream to prevent stream-start event */
12757   newstream->new_stream = FALSE;
12758
12759   return gst_qtdemux_configure_stream (qtdemux, newstream);
12760 }
12761
12762 /* g_ptr_array_find_with_equal_func is available since 2.54,
12763  * replacement until we can depend unconditionally on the real one in GLib */
12764 #if !GLIB_CHECK_VERSION(2,54,0)
12765 #define g_ptr_array_find_with_equal_func qtdemux_ptr_array_find_with_equal_func
12766 static gboolean
12767 qtdemux_ptr_array_find_with_equal_func (GPtrArray * haystack,
12768     gconstpointer needle, GEqualFunc equal_func, guint * index_)
12769 {
12770   guint i;
12771
12772   g_return_val_if_fail (haystack != NULL, FALSE);
12773
12774   if (equal_func == NULL)
12775     equal_func = g_direct_equal;
12776
12777   for (i = 0; i < haystack->len; i++) {
12778     if (equal_func (g_ptr_array_index (haystack, i), needle)) {
12779       if (index_ != NULL)
12780         *index_ = i;
12781       return TRUE;
12782     }
12783   }
12784
12785   return FALSE;
12786 }
12787 #endif
12788
12789 static gboolean
12790 qtdemux_update_streams (GstQTDemux * qtdemux)
12791 {
12792   gint i;
12793   g_assert (qtdemux->streams_aware);
12794
12795   /* At below, figure out which stream in active_streams has identical stream-id
12796    * with that of in old_streams. If there is matching stream-id,
12797    * corresponding newstream will not be exposed again,
12798    * but demux will reuse srcpad of matched old stream
12799    *
12800    * active_streams : newly created streams from the latest moov
12801    * old_streams : existing streams (belong to previous moov)
12802    */
12803
12804   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
12805     QtDemuxStream *stream = QTDEMUX_NTH_STREAM (qtdemux, i);
12806     QtDemuxStream *oldstream = NULL;
12807     guint target;
12808
12809     GST_DEBUG_OBJECT (qtdemux, "track-id %u, fourcc %" GST_FOURCC_FORMAT,
12810         stream->track_id, GST_FOURCC_ARGS (CUR_STREAM (stream)->fourcc));
12811
12812     if (g_ptr_array_find_with_equal_func (qtdemux->old_streams,
12813             stream->stream_id, (GEqualFunc) _stream_equal_func, &target)) {
12814       oldstream = QTDEMUX_NTH_OLD_STREAM (qtdemux, target);
12815
12816       /* null pad stream cannot be reused */
12817       if (oldstream->pad == NULL)
12818         oldstream = NULL;
12819     }
12820
12821     if (oldstream) {
12822       GST_DEBUG_OBJECT (qtdemux, "Reuse track-id %d", oldstream->track_id);
12823
12824       if (!qtdemux_reuse_and_configure_stream (qtdemux, oldstream, stream))
12825         return FALSE;
12826
12827       /* we don't need to preserve order of old streams */
12828       g_ptr_array_remove_fast (qtdemux->old_streams, oldstream);
12829     } else {
12830       GstTagList *list;
12831
12832       /* now we have all info and can expose */
12833       list = stream->stream_tags;
12834       stream->stream_tags = NULL;
12835       if (!gst_qtdemux_add_stream (qtdemux, stream, list))
12836         return FALSE;
12837     }
12838   }
12839
12840   return TRUE;
12841 }
12842
12843 /* Must be called with expose lock */
12844 static GstFlowReturn
12845 qtdemux_expose_streams (GstQTDemux * qtdemux)
12846 {
12847   gint i;
12848
12849   GST_DEBUG_OBJECT (qtdemux, "exposing streams");
12850
12851   if (!qtdemux_is_streams_update (qtdemux)) {
12852     GST_DEBUG_OBJECT (qtdemux, "Reuse all streams");
12853     for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
12854       QtDemuxStream *new_stream = QTDEMUX_NTH_STREAM (qtdemux, i);
12855       QtDemuxStream *old_stream = QTDEMUX_NTH_OLD_STREAM (qtdemux, i);
12856       if (!qtdemux_reuse_and_configure_stream (qtdemux, old_stream, new_stream))
12857         return GST_FLOW_ERROR;
12858     }
12859
12860     g_ptr_array_remove_range (qtdemux->old_streams,
12861         0, qtdemux->old_streams->len);
12862
12863     qtdemux->need_segment = TRUE;
12864
12865     return GST_FLOW_OK;
12866   }
12867
12868   if (qtdemux->streams_aware) {
12869     if (!qtdemux_update_streams (qtdemux))
12870       return GST_FLOW_ERROR;
12871   } else {
12872     for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
12873       QtDemuxStream *stream = QTDEMUX_NTH_STREAM (qtdemux, i);
12874       GstTagList *list;
12875
12876       /* now we have all info and can expose */
12877       list = stream->stream_tags;
12878       stream->stream_tags = NULL;
12879       if (!gst_qtdemux_add_stream (qtdemux, stream, list))
12880         return GST_FLOW_ERROR;
12881
12882     }
12883   }
12884
12885   gst_qtdemux_guess_bitrate (qtdemux);
12886
12887   gst_element_no_more_pads (GST_ELEMENT_CAST (qtdemux));
12888
12889   /* If we have still old_streams, it's no more used stream */
12890   for (i = 0; i < qtdemux->old_streams->len; i++) {
12891     QtDemuxStream *stream = QTDEMUX_NTH_OLD_STREAM (qtdemux, i);
12892
12893     if (stream->pad) {
12894       GstEvent *event;
12895
12896       event = gst_event_new_eos ();
12897       if (qtdemux->segment_seqnum)
12898         gst_event_set_seqnum (event, qtdemux->segment_seqnum);
12899
12900       gst_pad_push_event (stream->pad, event);
12901     }
12902   }
12903
12904   g_ptr_array_remove_range (qtdemux->old_streams, 0, qtdemux->old_streams->len);
12905
12906   /* check if we should post a redirect in case there is a single trak
12907    * and it is a redirecting trak */
12908   if (QTDEMUX_N_STREAMS (qtdemux) == 1 &&
12909       QTDEMUX_NTH_STREAM (qtdemux, 0)->redirect_uri != NULL) {
12910     GstMessage *m;
12911
12912     GST_INFO_OBJECT (qtdemux, "Issuing a redirect due to a single track with "
12913         "an external content");
12914     m = gst_message_new_element (GST_OBJECT_CAST (qtdemux),
12915         gst_structure_new ("redirect",
12916             "new-location", G_TYPE_STRING,
12917             QTDEMUX_NTH_STREAM (qtdemux, 0)->redirect_uri, NULL));
12918     gst_element_post_message (GST_ELEMENT_CAST (qtdemux), m);
12919     qtdemux->posted_redirect = TRUE;
12920   }
12921
12922   g_ptr_array_foreach (qtdemux->active_streams,
12923       (GFunc) qtdemux_do_allocation, qtdemux);
12924
12925   qtdemux->need_segment = TRUE;
12926
12927   qtdemux->exposed = TRUE;
12928   return GST_FLOW_OK;
12929 }
12930
12931 /* check if major or compatible brand is 3GP */
12932 static inline gboolean
12933 qtdemux_is_brand_3gp (GstQTDemux * qtdemux, gboolean major)
12934 {
12935   if (major) {
12936     return ((qtdemux->major_brand & GST_MAKE_FOURCC (255, 255, 0, 0)) ==
12937         FOURCC_3g__);
12938   } else if (qtdemux->comp_brands != NULL) {
12939     GstMapInfo map;
12940     guint8 *data;
12941     gsize size;
12942     gboolean res = FALSE;
12943
12944     gst_buffer_map (qtdemux->comp_brands, &map, GST_MAP_READ);
12945     data = map.data;
12946     size = map.size;
12947     while (size >= 4) {
12948       res = res || ((QT_FOURCC (data) & GST_MAKE_FOURCC (255, 255, 0, 0)) ==
12949           FOURCC_3g__);
12950       data += 4;
12951       size -= 4;
12952     }
12953     gst_buffer_unmap (qtdemux->comp_brands, &map);
12954     return res;
12955   } else {
12956     return FALSE;
12957   }
12958 }
12959
12960 /* check if tag is a spec'ed 3GP tag keyword storing a string */
12961 static inline gboolean
12962 qtdemux_is_string_tag_3gp (GstQTDemux * qtdemux, guint32 fourcc)
12963 {
12964   return fourcc == FOURCC_cprt || fourcc == FOURCC_gnre || fourcc == FOURCC_titl
12965       || fourcc == FOURCC_dscp || fourcc == FOURCC_perf || fourcc == FOURCC_auth
12966       || fourcc == FOURCC_albm;
12967 }
12968
12969 static void
12970 qtdemux_tag_add_location (GstQTDemux * qtdemux, GstTagList * taglist,
12971     const char *tag, const char *dummy, GNode * node)
12972 {
12973   const gchar *env_vars[] = { "GST_QT_TAG_ENCODING", "GST_TAG_ENCODING", NULL };
12974   int offset;
12975   char *name;
12976   gchar *data;
12977   gdouble longitude, latitude, altitude;
12978   gint len;
12979
12980   len = QT_UINT32 (node->data);
12981   if (len <= 14)
12982     goto short_read;
12983
12984   data = node->data;
12985   offset = 14;
12986
12987   /* TODO: language code skipped */
12988
12989   name = gst_tag_freeform_string_to_utf8 (data + offset, -1, env_vars);
12990
12991   if (!name) {
12992     /* do not alarm in trivial case, but bail out otherwise */
12993     if (*(data + offset) != 0) {
12994       GST_DEBUG_OBJECT (qtdemux, "failed to convert %s tag to UTF-8, "
12995           "giving up", tag);
12996     }
12997   } else {
12998     gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE,
12999         GST_TAG_GEO_LOCATION_NAME, name, NULL);
13000     offset += strlen (name);
13001     g_free (name);
13002   }
13003
13004   if (len < offset + 2 + 4 + 4 + 4)
13005     goto short_read;
13006
13007   /* +1 +1 = skip null-terminator and location role byte */
13008   offset += 1 + 1;
13009   /* table in spec says unsigned, semantics say negative has meaning ... */
13010   longitude = QT_SFP32 (data + offset);
13011
13012   offset += 4;
13013   latitude = QT_SFP32 (data + offset);
13014
13015   offset += 4;
13016   altitude = QT_SFP32 (data + offset);
13017
13018   /* one invalid means all are invalid */
13019   if (longitude >= -180.0 && longitude <= 180.0 &&
13020       latitude >= -90.0 && latitude <= 90.0) {
13021     gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE,
13022         GST_TAG_GEO_LOCATION_LATITUDE, latitude,
13023         GST_TAG_GEO_LOCATION_LONGITUDE, longitude,
13024         GST_TAG_GEO_LOCATION_ELEVATION, altitude, NULL);
13025   }
13026
13027   /* TODO: no GST_TAG_, so astronomical body and additional notes skipped */
13028
13029   return;
13030
13031   /* ERRORS */
13032 short_read:
13033   {
13034     GST_DEBUG_OBJECT (qtdemux, "short read parsing 3GP location");
13035     return;
13036   }
13037 }
13038
13039
13040 static void
13041 qtdemux_tag_add_year (GstQTDemux * qtdemux, GstTagList * taglist,
13042     const char *tag, const char *dummy, GNode * node)
13043 {
13044   guint16 y;
13045   GDate *date;
13046   gint len;
13047
13048   len = QT_UINT32 (node->data);
13049   if (len < 14)
13050     return;
13051
13052   y = QT_UINT16 ((guint8 *) node->data + 12);
13053   if (y == 0) {
13054     GST_DEBUG_OBJECT (qtdemux, "year: %u is not a valid year", y);
13055     return;
13056   }
13057   GST_DEBUG_OBJECT (qtdemux, "year: %u", y);
13058
13059   date = g_date_new_dmy (1, 1, y);
13060   gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag, date, NULL);
13061   g_date_free (date);
13062 }
13063
13064 static void
13065 qtdemux_tag_add_classification (GstQTDemux * qtdemux, GstTagList * taglist,
13066     const char *tag, const char *dummy, GNode * node)
13067 {
13068   int offset;
13069   char *tag_str = NULL;
13070   guint8 *entity;
13071   guint16 table;
13072   gint len;
13073
13074   len = QT_UINT32 (node->data);
13075   if (len <= 20)
13076     goto short_read;
13077
13078   offset = 12;
13079   entity = (guint8 *) node->data + offset;
13080   if (entity[0] == 0 || entity[1] == 0 || entity[2] == 0 || entity[3] == 0) {
13081     GST_DEBUG_OBJECT (qtdemux,
13082         "classification info: %c%c%c%c invalid classification entity",
13083         entity[0], entity[1], entity[2], entity[3]);
13084     return;
13085   }
13086
13087   offset += 4;
13088   table = QT_UINT16 ((guint8 *) node->data + offset);
13089
13090   /* Language code skipped */
13091
13092   offset += 4;
13093
13094   /* Tag format: "XXXX://Y[YYYY]/classification info string"
13095    * XXXX: classification entity, fixed length 4 chars.
13096    * Y[YYYY]: classification table, max 5 chars.
13097    */
13098   tag_str = g_strdup_printf ("----://%u/%s",
13099       table, (char *) node->data + offset);
13100
13101   /* memcpy To be sure we're preserving byte order */
13102   memcpy (tag_str, entity, 4);
13103   GST_DEBUG_OBJECT (qtdemux, "classification info: %s", tag_str);
13104
13105   gst_tag_list_add (taglist, GST_TAG_MERGE_APPEND, tag, tag_str, NULL);
13106
13107   g_free (tag_str);
13108
13109   return;
13110
13111   /* ERRORS */
13112 short_read:
13113   {
13114     GST_DEBUG_OBJECT (qtdemux, "short read parsing 3GP classification");
13115     return;
13116   }
13117 }
13118
13119 static gboolean
13120 qtdemux_tag_add_str_full (GstQTDemux * qtdemux, GstTagList * taglist,
13121     const char *tag, const char *dummy, GNode * node)
13122 {
13123   const gchar *env_vars[] = { "GST_QT_TAG_ENCODING", "GST_TAG_ENCODING", NULL };
13124   GNode *data;
13125   char *s;
13126   int len;
13127   guint32 type;
13128   int offset;
13129   gboolean ret = TRUE;
13130   const gchar *charset = NULL;
13131
13132   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
13133   if (data) {
13134     len = QT_UINT32 (data->data);
13135     type = QT_UINT32 ((guint8 *) data->data + 8);
13136     if (type == 0x00000001 && len > 16) {
13137       s = gst_tag_freeform_string_to_utf8 ((char *) data->data + 16, len - 16,
13138           env_vars);
13139       if (s) {
13140         GST_DEBUG_OBJECT (qtdemux, "adding tag %s", GST_STR_NULL (s));
13141         gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag, s, NULL);
13142         g_free (s);
13143       } else {
13144         GST_DEBUG_OBJECT (qtdemux, "failed to convert %s tag to UTF-8", tag);
13145       }
13146     }
13147   } else {
13148     len = QT_UINT32 (node->data);
13149     type = QT_UINT32 ((guint8 *) node->data + 4);
13150     if ((type >> 24) == 0xa9 && len > 8 + 4) {
13151       gint str_len;
13152       gint lang_code;
13153
13154       /* Type starts with the (C) symbol, so the next data is a list
13155        * of (string size(16), language code(16), string) */
13156
13157       str_len = QT_UINT16 ((guint8 *) node->data + 8);
13158       lang_code = QT_UINT16 ((guint8 *) node->data + 10);
13159
13160       /* the string + fourcc + size + 2 16bit fields,
13161        * means that there are more tags in this atom */
13162       if (len > str_len + 8 + 4) {
13163         /* TODO how to represent the same tag in different languages? */
13164         GST_WARNING_OBJECT (qtdemux, "Ignoring metadata entry with multiple "
13165             "text alternatives, reading only first one");
13166       }
13167
13168       offset = 12;
13169       len = MIN (len, str_len + 8 + 4); /* remove trailing strings that we don't use */
13170       GST_DEBUG_OBJECT (qtdemux, "found international text tag");
13171
13172       if (lang_code < 0x800) {  /* MAC encoded string */
13173         charset = "mac";
13174       }
13175     } else if (len > 14 && qtdemux_is_string_tag_3gp (qtdemux,
13176             QT_FOURCC ((guint8 *) node->data + 4))) {
13177       guint32 type = QT_UINT32 ((guint8 *) node->data + 8);
13178
13179       /* we go for 3GP style encoding if major brands claims so,
13180        * or if no hope for data be ok UTF-8, and compatible 3GP brand present */
13181       if (qtdemux_is_brand_3gp (qtdemux, TRUE) ||
13182           (qtdemux_is_brand_3gp (qtdemux, FALSE) &&
13183               ((type & 0x00FFFFFF) == 0x0) && (type >> 24 <= 0xF))) {
13184         offset = 14;
13185         /* 16-bit Language code is ignored here as well */
13186         GST_DEBUG_OBJECT (qtdemux, "found 3gpp text tag");
13187       } else {
13188         goto normal;
13189       }
13190     } else {
13191     normal:
13192       offset = 8;
13193       GST_DEBUG_OBJECT (qtdemux, "found normal text tag");
13194       ret = FALSE;              /* may have to fallback */
13195     }
13196     if (charset) {
13197       GError *err = NULL;
13198
13199       s = g_convert ((gchar *) node->data + offset, len - offset, "utf8",
13200           charset, NULL, NULL, &err);
13201       if (err) {
13202         GST_DEBUG_OBJECT (qtdemux, "Failed to convert string from charset %s:"
13203             " %s(%d): %s", charset, g_quark_to_string (err->domain), err->code,
13204             err->message);
13205         g_error_free (err);
13206       }
13207     } else {
13208       s = gst_tag_freeform_string_to_utf8 ((char *) node->data + offset,
13209           len - offset, env_vars);
13210     }
13211     if (s) {
13212       GST_DEBUG_OBJECT (qtdemux, "adding tag %s", GST_STR_NULL (s));
13213       gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag, s, NULL);
13214       g_free (s);
13215       ret = TRUE;
13216     } else {
13217       GST_DEBUG_OBJECT (qtdemux, "failed to convert %s tag to UTF-8", tag);
13218     }
13219   }
13220   return ret;
13221 }
13222
13223 static void
13224 qtdemux_tag_add_str (GstQTDemux * qtdemux, GstTagList * taglist,
13225     const char *tag, const char *dummy, GNode * node)
13226 {
13227   qtdemux_tag_add_str_full (qtdemux, taglist, tag, dummy, node);
13228 }
13229
13230 static void
13231 qtdemux_tag_add_keywords (GstQTDemux * qtdemux, GstTagList * taglist,
13232     const char *tag, const char *dummy, GNode * node)
13233 {
13234   const gchar *env_vars[] = { "GST_QT_TAG_ENCODING", "GST_TAG_ENCODING", NULL };
13235   guint8 *data;
13236   char *s, *t, *k = NULL;
13237   int len;
13238   int offset;
13239   int count;
13240
13241   /* first try normal string tag if major brand not 3GP */
13242   if (!qtdemux_is_brand_3gp (qtdemux, TRUE)) {
13243     if (!qtdemux_tag_add_str_full (qtdemux, taglist, tag, dummy, node)) {
13244       /* hm, that did not work, maybe 3gpp storage in non-3gpp major brand;
13245        * let's try it 3gpp way after minor safety check */
13246       data = node->data;
13247       if (QT_UINT32 (data) < 15 || !qtdemux_is_brand_3gp (qtdemux, FALSE))
13248         return;
13249     } else
13250       return;
13251   }
13252
13253   GST_DEBUG_OBJECT (qtdemux, "found 3gpp keyword tag");
13254
13255   data = node->data;
13256
13257   len = QT_UINT32 (data);
13258   if (len < 15)
13259     goto short_read;
13260
13261   count = QT_UINT8 (data + 14);
13262   offset = 15;
13263   for (; count; count--) {
13264     gint slen;
13265
13266     if (offset + 1 > len)
13267       goto short_read;
13268     slen = QT_UINT8 (data + offset);
13269     offset += 1;
13270     if (offset + slen > len)
13271       goto short_read;
13272     s = gst_tag_freeform_string_to_utf8 ((char *) node->data + offset,
13273         slen, env_vars);
13274     if (s) {
13275       GST_DEBUG_OBJECT (qtdemux, "adding keyword %s", GST_STR_NULL (s));
13276       if (k) {
13277         t = g_strjoin (",", k, s, NULL);
13278         g_free (s);
13279         g_free (k);
13280         k = t;
13281       } else {
13282         k = s;
13283       }
13284     } else {
13285       GST_DEBUG_OBJECT (qtdemux, "failed to convert keyword to UTF-8");
13286     }
13287     offset += slen;
13288   }
13289
13290 done:
13291   if (k) {
13292     GST_DEBUG_OBJECT (qtdemux, "adding tag %s", GST_STR_NULL (k));
13293     gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag, k, NULL);
13294   }
13295   g_free (k);
13296
13297   return;
13298
13299   /* ERRORS */
13300 short_read:
13301   {
13302     GST_DEBUG_OBJECT (qtdemux, "short read parsing 3GP keywords");
13303     goto done;
13304   }
13305 }
13306
13307 static void
13308 qtdemux_tag_add_num (GstQTDemux * qtdemux, GstTagList * taglist,
13309     const char *tag1, const char *tag2, GNode * node)
13310 {
13311   GNode *data;
13312   int len;
13313   int type;
13314   int n1, n2;
13315
13316   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
13317   if (data) {
13318     len = QT_UINT32 (data->data);
13319     type = QT_UINT32 ((guint8 *) data->data + 8);
13320     if (type == 0x00000000 && len >= 22) {
13321       n1 = QT_UINT16 ((guint8 *) data->data + 18);
13322       n2 = QT_UINT16 ((guint8 *) data->data + 20);
13323       if (n1 > 0) {
13324         GST_DEBUG_OBJECT (qtdemux, "adding tag %s=%d", tag1, n1);
13325         gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag1, n1, NULL);
13326       }
13327       if (n2 > 0) {
13328         GST_DEBUG_OBJECT (qtdemux, "adding tag %s=%d", tag2, n2);
13329         gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag2, n2, NULL);
13330       }
13331     }
13332   }
13333 }
13334
13335 static void
13336 qtdemux_tag_add_tmpo (GstQTDemux * qtdemux, GstTagList * taglist,
13337     const char *tag1, const char *dummy, GNode * node)
13338 {
13339   GNode *data;
13340   int len;
13341   int type;
13342   int n1;
13343
13344   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
13345   if (data) {
13346     len = QT_UINT32 (data->data);
13347     type = QT_UINT32 ((guint8 *) data->data + 8);
13348     GST_DEBUG_OBJECT (qtdemux, "have tempo tag, type=%d,len=%d", type, len);
13349     /* some files wrongly have a type 0x0f=15, but it should be 0x15 */
13350     if ((type == 0x00000015 || type == 0x0000000f) && len >= 18) {
13351       n1 = QT_UINT16 ((guint8 *) data->data + 16);
13352       if (n1) {
13353         /* do not add bpm=0 */
13354         GST_DEBUG_OBJECT (qtdemux, "adding tag %d", n1);
13355         gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag1, (gdouble) n1,
13356             NULL);
13357       }
13358     }
13359   }
13360 }
13361
13362 static void
13363 qtdemux_tag_add_uint32 (GstQTDemux * qtdemux, GstTagList * taglist,
13364     const char *tag1, const char *dummy, GNode * node)
13365 {
13366   GNode *data;
13367   int len;
13368   int type;
13369   guint32 num;
13370
13371   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
13372   if (data) {
13373     len = QT_UINT32 (data->data);
13374     type = QT_UINT32 ((guint8 *) data->data + 8);
13375     GST_DEBUG_OBJECT (qtdemux, "have %s tag, type=%d,len=%d", tag1, type, len);
13376     /* some files wrongly have a type 0x0f=15, but it should be 0x15 */
13377     if ((type == 0x00000015 || type == 0x0000000f) && len >= 20) {
13378       num = QT_UINT32 ((guint8 *) data->data + 16);
13379       if (num) {
13380         /* do not add num=0 */
13381         GST_DEBUG_OBJECT (qtdemux, "adding tag %d", num);
13382         gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag1, num, NULL);
13383       }
13384     }
13385   }
13386 }
13387
13388 static void
13389 qtdemux_tag_add_covr (GstQTDemux * qtdemux, GstTagList * taglist,
13390     const char *tag1, const char *dummy, GNode * node)
13391 {
13392   GNode *data;
13393   int len;
13394   int type;
13395   GstSample *sample;
13396
13397   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
13398   if (data) {
13399     len = QT_UINT32 (data->data);
13400     type = QT_UINT32 ((guint8 *) data->data + 8);
13401     GST_DEBUG_OBJECT (qtdemux, "have covr tag, type=%d,len=%d", type, len);
13402     if ((type == 0x0000000d || type == 0x0000000e) && len > 16) {
13403       GstTagImageType image_type;
13404
13405       if (gst_tag_list_get_tag_size (taglist, GST_TAG_IMAGE) == 0)
13406         image_type = GST_TAG_IMAGE_TYPE_FRONT_COVER;
13407       else
13408         image_type = GST_TAG_IMAGE_TYPE_NONE;
13409
13410       if ((sample =
13411               gst_tag_image_data_to_image_sample ((guint8 *) data->data + 16,
13412                   len - 16, image_type))) {
13413         GST_DEBUG_OBJECT (qtdemux, "adding tag size %d", len - 16);
13414         gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag1, sample, NULL);
13415         gst_sample_unref (sample);
13416       }
13417     }
13418   }
13419 }
13420
13421 static void
13422 qtdemux_tag_add_date (GstQTDemux * qtdemux, GstTagList * taglist,
13423     const char *tag, const char *dummy, GNode * node)
13424 {
13425   GNode *data;
13426   GstDateTime *datetime = NULL;
13427   char *s;
13428   int len;
13429   int type;
13430
13431   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
13432   if (data) {
13433     len = QT_UINT32 (data->data);
13434     type = QT_UINT32 ((guint8 *) data->data + 8);
13435     if (type == 0x00000001 && len > 16) {
13436       guint y, m = 1, d = 1;
13437       gint ret;
13438
13439       s = g_strndup ((char *) data->data + 16, len - 16);
13440       GST_DEBUG_OBJECT (qtdemux, "adding date '%s'", s);
13441       datetime = gst_date_time_new_from_iso8601_string (s);
13442       if (datetime != NULL) {
13443         gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, GST_TAG_DATE_TIME,
13444             datetime, NULL);
13445         gst_date_time_unref (datetime);
13446       }
13447
13448       ret = sscanf (s, "%u-%u-%u", &y, &m, &d);
13449       if (ret >= 1 && y > 1500 && y < 3000) {
13450         GDate *date;
13451
13452         date = g_date_new_dmy (d, m, y);
13453         gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag, date, NULL);
13454         g_date_free (date);
13455       } else {
13456         GST_DEBUG_OBJECT (qtdemux, "could not parse date string '%s'", s);
13457       }
13458       g_free (s);
13459     }
13460   }
13461 }
13462
13463 static void
13464 qtdemux_tag_add_gnre (GstQTDemux * qtdemux, GstTagList * taglist,
13465     const char *tag, const char *dummy, GNode * node)
13466 {
13467   GNode *data;
13468
13469   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
13470
13471   /* re-route to normal string tag if major brand says so
13472    * or no data atom and compatible brand suggests so */
13473   if (qtdemux_is_brand_3gp (qtdemux, TRUE) ||
13474       (qtdemux_is_brand_3gp (qtdemux, FALSE) && !data)) {
13475     qtdemux_tag_add_str (qtdemux, taglist, tag, dummy, node);
13476     return;
13477   }
13478
13479   if (data) {
13480     guint len, type, n;
13481
13482     len = QT_UINT32 (data->data);
13483     type = QT_UINT32 ((guint8 *) data->data + 8);
13484     if (type == 0x00000000 && len >= 18) {
13485       n = QT_UINT16 ((guint8 *) data->data + 16);
13486       if (n > 0) {
13487         const gchar *genre;
13488
13489         genre = gst_tag_id3_genre_get (n - 1);
13490         if (genre != NULL) {
13491           GST_DEBUG_OBJECT (qtdemux, "adding %d [%s]", n, genre);
13492           gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag, genre, NULL);
13493         }
13494       }
13495     }
13496   }
13497 }
13498
13499 static void
13500 qtdemux_add_double_tag_from_str (GstQTDemux * demux, GstTagList * taglist,
13501     const gchar * tag, guint8 * data, guint32 datasize)
13502 {
13503   gdouble value;
13504   gchar *datacopy;
13505
13506   /* make a copy to have \0 at the end */
13507   datacopy = g_strndup ((gchar *) data, datasize);
13508
13509   /* convert the str to double */
13510   if (sscanf (datacopy, "%lf", &value) == 1) {
13511     GST_DEBUG_OBJECT (demux, "adding tag: %s [%s]", tag, datacopy);
13512     gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag, value, NULL);
13513   } else {
13514     GST_WARNING_OBJECT (demux, "Failed to parse double from string: %s",
13515         datacopy);
13516   }
13517   g_free (datacopy);
13518 }
13519
13520
13521 static void
13522 qtdemux_tag_add_revdns (GstQTDemux * demux, GstTagList * taglist,
13523     const char *tag, const char *tag_bis, GNode * node)
13524 {
13525   GNode *mean;
13526   GNode *name;
13527   GNode *data;
13528   guint32 meansize;
13529   guint32 namesize;
13530   guint32 datatype;
13531   guint32 datasize;
13532   const gchar *meanstr;
13533   const gchar *namestr;
13534
13535   /* checking the whole ---- atom size for consistency */
13536   if (QT_UINT32 (node->data) <= 4 + 12 + 12 + 16) {
13537     GST_WARNING_OBJECT (demux, "Tag ---- atom is too small, ignoring");
13538     return;
13539   }
13540
13541   mean = qtdemux_tree_get_child_by_type (node, FOURCC_mean);
13542   if (!mean) {
13543     GST_WARNING_OBJECT (demux, "No 'mean' atom found");
13544     return;
13545   }
13546
13547   meansize = QT_UINT32 (mean->data);
13548   if (meansize <= 12) {
13549     GST_WARNING_OBJECT (demux, "Small mean atom, ignoring the whole tag");
13550     return;
13551   }
13552   meanstr = ((gchar *) mean->data) + 12;
13553   meansize -= 12;
13554
13555   name = qtdemux_tree_get_child_by_type (node, FOURCC_name);
13556   if (!name) {
13557     GST_WARNING_OBJECT (demux, "'name' atom not found, ignoring tag");
13558     return;
13559   }
13560
13561   namesize = QT_UINT32 (name->data);
13562   if (namesize <= 12) {
13563     GST_WARNING_OBJECT (demux, "'name' atom is too small, ignoring tag");
13564     return;
13565   }
13566   namestr = ((gchar *) name->data) + 12;
13567   namesize -= 12;
13568
13569   /*
13570    * Data atom is:
13571    * uint32 - size
13572    * uint32 - name
13573    * uint8  - version
13574    * uint24 - data type
13575    * uint32 - all 0
13576    * rest   - the data
13577    */
13578   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
13579   if (!data) {
13580     GST_WARNING_OBJECT (demux, "No data atom in this tag");
13581     return;
13582   }
13583   datasize = QT_UINT32 (data->data);
13584   if (datasize <= 16) {
13585     GST_WARNING_OBJECT (demux, "Data atom too small");
13586     return;
13587   }
13588   datatype = QT_UINT32 (((gchar *) data->data) + 8) & 0xFFFFFF;
13589
13590   if ((strncmp (meanstr, "com.apple.iTunes", meansize) == 0) ||
13591       (strncmp (meanstr, "org.hydrogenaudio.replaygain", meansize) == 0)) {
13592     static const struct
13593     {
13594       const gchar name[28];
13595       const gchar tag[28];
13596     } tags[] = {
13597       {
13598       "replaygain_track_gain", GST_TAG_TRACK_GAIN}, {
13599       "replaygain_track_peak", GST_TAG_TRACK_PEAK}, {
13600       "replaygain_album_gain", GST_TAG_ALBUM_GAIN}, {
13601       "replaygain_album_peak", GST_TAG_ALBUM_PEAK}, {
13602       "MusicBrainz Track Id", GST_TAG_MUSICBRAINZ_TRACKID}, {
13603       "MusicBrainz Artist Id", GST_TAG_MUSICBRAINZ_ARTISTID}, {
13604       "MusicBrainz Album Id", GST_TAG_MUSICBRAINZ_ALBUMID}, {
13605       "MusicBrainz Album Artist Id", GST_TAG_MUSICBRAINZ_ALBUMARTISTID}
13606     };
13607     int i;
13608
13609     for (i = 0; i < G_N_ELEMENTS (tags); ++i) {
13610       if (!g_ascii_strncasecmp (tags[i].name, namestr, namesize)) {
13611         switch (gst_tag_get_type (tags[i].tag)) {
13612           case G_TYPE_DOUBLE:
13613             qtdemux_add_double_tag_from_str (demux, taglist, tags[i].tag,
13614                 ((guint8 *) data->data) + 16, datasize - 16);
13615             break;
13616           case G_TYPE_STRING:
13617             qtdemux_tag_add_str (demux, taglist, tags[i].tag, NULL, node);
13618             break;
13619           default:
13620             /* not reached */
13621             break;
13622         }
13623         break;
13624       }
13625     }
13626     if (i == G_N_ELEMENTS (tags))
13627       goto unknown_tag;
13628   } else {
13629     goto unknown_tag;
13630   }
13631
13632   return;
13633
13634 /* errors */
13635 unknown_tag:
13636 #ifndef GST_DISABLE_GST_DEBUG
13637   {
13638     gchar *namestr_dbg;
13639     gchar *meanstr_dbg;
13640
13641     meanstr_dbg = g_strndup (meanstr, meansize);
13642     namestr_dbg = g_strndup (namestr, namesize);
13643
13644     GST_WARNING_OBJECT (demux, "This tag %s:%s type:%u is not mapped, "
13645         "file a bug at bugzilla.gnome.org", meanstr_dbg, namestr_dbg, datatype);
13646
13647     g_free (namestr_dbg);
13648     g_free (meanstr_dbg);
13649   }
13650 #endif
13651   return;
13652 }
13653
13654 static void
13655 qtdemux_tag_add_id32 (GstQTDemux * demux, GstTagList * taglist, const char *tag,
13656     const char *tag_bis, GNode * node)
13657 {
13658   guint8 *data;
13659   GstBuffer *buf;
13660   guint len;
13661   GstTagList *id32_taglist = NULL;
13662
13663   GST_LOG_OBJECT (demux, "parsing ID32");
13664
13665   data = node->data;
13666   len = GST_READ_UINT32_BE (data);
13667
13668   /* need at least full box and language tag */
13669   if (len < 12 + 2)
13670     return;
13671
13672   buf = gst_buffer_new_allocate (NULL, len - 14, NULL);
13673   gst_buffer_fill (buf, 0, data + 14, len - 14);
13674
13675   id32_taglist = gst_tag_list_from_id3v2_tag (buf);
13676   if (id32_taglist) {
13677     GST_LOG_OBJECT (demux, "parsing ok");
13678     gst_tag_list_insert (taglist, id32_taglist, GST_TAG_MERGE_KEEP);
13679     gst_tag_list_unref (id32_taglist);
13680   } else {
13681     GST_LOG_OBJECT (demux, "parsing failed");
13682   }
13683
13684   gst_buffer_unref (buf);
13685 }
13686
13687 typedef void (*GstQTDemuxAddTagFunc) (GstQTDemux * demux, GstTagList * taglist,
13688     const char *tag, const char *tag_bis, GNode * node);
13689
13690 /* unmapped tags
13691 FOURCC_pcst -> if media is a podcast -> bool
13692 FOURCC_cpil -> if media is part of a compilation -> bool
13693 FOURCC_pgap -> if media is part of a gapless context -> bool
13694 FOURCC_tven -> the tv episode id e.g. S01E23 -> str
13695 */
13696
13697 static const struct
13698 {
13699   guint32 fourcc;
13700   const gchar *gst_tag;
13701   const gchar *gst_tag_bis;
13702   const GstQTDemuxAddTagFunc func;
13703 } add_funcs[] = {
13704   {
13705   FOURCC__nam, GST_TAG_TITLE, NULL, qtdemux_tag_add_str}, {
13706   FOURCC_titl, GST_TAG_TITLE, NULL, qtdemux_tag_add_str}, {
13707   FOURCC__grp, GST_TAG_GROUPING, NULL, qtdemux_tag_add_str}, {
13708   FOURCC__wrt, GST_TAG_COMPOSER, NULL, qtdemux_tag_add_str}, {
13709   FOURCC__ART, GST_TAG_ARTIST, NULL, qtdemux_tag_add_str}, {
13710   FOURCC_aART, GST_TAG_ALBUM_ARTIST, NULL, qtdemux_tag_add_str}, {
13711   FOURCC_perf, GST_TAG_ARTIST, NULL, qtdemux_tag_add_str}, {
13712   FOURCC_auth, GST_TAG_COMPOSER, NULL, qtdemux_tag_add_str}, {
13713   FOURCC__alb, GST_TAG_ALBUM, NULL, qtdemux_tag_add_str}, {
13714   FOURCC_albm, GST_TAG_ALBUM, NULL, qtdemux_tag_add_str}, {
13715   FOURCC_cprt, GST_TAG_COPYRIGHT, NULL, qtdemux_tag_add_str}, {
13716   FOURCC__cpy, GST_TAG_COPYRIGHT, NULL, qtdemux_tag_add_str}, {
13717   FOURCC__cmt, GST_TAG_COMMENT, NULL, qtdemux_tag_add_str}, {
13718   FOURCC__des, GST_TAG_DESCRIPTION, NULL, qtdemux_tag_add_str}, {
13719   FOURCC_desc, GST_TAG_DESCRIPTION, NULL, qtdemux_tag_add_str}, {
13720   FOURCC_dscp, GST_TAG_DESCRIPTION, NULL, qtdemux_tag_add_str}, {
13721   FOURCC__lyr, GST_TAG_LYRICS, NULL, qtdemux_tag_add_str}, {
13722   FOURCC__day, GST_TAG_DATE, NULL, qtdemux_tag_add_date}, {
13723   FOURCC_yrrc, GST_TAG_DATE, NULL, qtdemux_tag_add_year}, {
13724   FOURCC__too, GST_TAG_ENCODER, NULL, qtdemux_tag_add_str}, {
13725   FOURCC__inf, GST_TAG_COMMENT, NULL, qtdemux_tag_add_str}, {
13726   FOURCC_trkn, GST_TAG_TRACK_NUMBER, GST_TAG_TRACK_COUNT, qtdemux_tag_add_num}, {
13727   FOURCC_disk, GST_TAG_ALBUM_VOLUME_NUMBER, GST_TAG_ALBUM_VOLUME_COUNT,
13728         qtdemux_tag_add_num}, {
13729   FOURCC_disc, GST_TAG_ALBUM_VOLUME_NUMBER, GST_TAG_ALBUM_VOLUME_COUNT,
13730         qtdemux_tag_add_num}, {
13731   FOURCC__gen, GST_TAG_GENRE, NULL, qtdemux_tag_add_str}, {
13732   FOURCC_gnre, GST_TAG_GENRE, NULL, qtdemux_tag_add_gnre}, {
13733   FOURCC_tmpo, GST_TAG_BEATS_PER_MINUTE, NULL, qtdemux_tag_add_tmpo}, {
13734   FOURCC_covr, GST_TAG_IMAGE, NULL, qtdemux_tag_add_covr}, {
13735   FOURCC_sonm, GST_TAG_TITLE_SORTNAME, NULL, qtdemux_tag_add_str}, {
13736   FOURCC_soal, GST_TAG_ALBUM_SORTNAME, NULL, qtdemux_tag_add_str}, {
13737   FOURCC_soar, GST_TAG_ARTIST_SORTNAME, NULL, qtdemux_tag_add_str}, {
13738   FOURCC_soaa, GST_TAG_ALBUM_ARTIST_SORTNAME, NULL, qtdemux_tag_add_str}, {
13739   FOURCC_soco, GST_TAG_COMPOSER_SORTNAME, NULL, qtdemux_tag_add_str}, {
13740   FOURCC_sosn, GST_TAG_SHOW_SORTNAME, NULL, qtdemux_tag_add_str}, {
13741   FOURCC_tvsh, GST_TAG_SHOW_NAME, NULL, qtdemux_tag_add_str}, {
13742   FOURCC_tvsn, GST_TAG_SHOW_SEASON_NUMBER, NULL, qtdemux_tag_add_uint32}, {
13743   FOURCC_tves, GST_TAG_SHOW_EPISODE_NUMBER, NULL, qtdemux_tag_add_uint32}, {
13744   FOURCC_kywd, GST_TAG_KEYWORDS, NULL, qtdemux_tag_add_keywords}, {
13745   FOURCC_keyw, GST_TAG_KEYWORDS, NULL, qtdemux_tag_add_str}, {
13746   FOURCC__enc, GST_TAG_ENCODER, NULL, qtdemux_tag_add_str}, {
13747   FOURCC_loci, GST_TAG_GEO_LOCATION_NAME, NULL, qtdemux_tag_add_location}, {
13748   FOURCC_clsf, GST_QT_DEMUX_CLASSIFICATION_TAG, NULL,
13749         qtdemux_tag_add_classification}, {
13750   FOURCC__mak, GST_TAG_DEVICE_MANUFACTURER, NULL, qtdemux_tag_add_str}, {
13751   FOURCC__mod, GST_TAG_DEVICE_MODEL, NULL, qtdemux_tag_add_str}, {
13752   FOURCC__swr, GST_TAG_APPLICATION_NAME, NULL, qtdemux_tag_add_str}, {
13753
13754     /* This is a special case, some tags are stored in this
13755      * 'reverse dns naming', according to:
13756      * http://atomicparsley.sourceforge.net/mpeg-4files.html and
13757      * bug #614471
13758      */
13759   FOURCC_____, "", NULL, qtdemux_tag_add_revdns}, {
13760     /* see http://www.mp4ra.org/specs.html for ID32 in meta box */
13761   FOURCC_ID32, "", NULL, qtdemux_tag_add_id32}
13762 };
13763
13764 struct _GstQtDemuxTagList
13765 {
13766   GstQTDemux *demux;
13767   GstTagList *taglist;
13768 };
13769 typedef struct _GstQtDemuxTagList GstQtDemuxTagList;
13770
13771 static void
13772 qtdemux_tag_add_blob (GNode * node, GstQtDemuxTagList * qtdemuxtaglist)
13773 {
13774   gint len;
13775   guint8 *data;
13776   GstBuffer *buf;
13777   gchar *media_type;
13778   const gchar *style;
13779   GstSample *sample;
13780   GstStructure *s;
13781   guint i;
13782   guint8 ndata[4];
13783   GstQTDemux *demux = qtdemuxtaglist->demux;
13784   GstTagList *taglist = qtdemuxtaglist->taglist;
13785
13786   data = node->data;
13787   len = QT_UINT32 (data);
13788   buf = gst_buffer_new_and_alloc (len);
13789   gst_buffer_fill (buf, 0, data, len);
13790
13791   /* heuristic to determine style of tag */
13792   if (QT_FOURCC (data + 4) == FOURCC_____ ||
13793       (len > 8 + 12 && QT_FOURCC (data + 12) == FOURCC_data))
13794     style = "itunes";
13795   else if (demux->major_brand == FOURCC_qt__)
13796     style = "quicktime";
13797   /* fall back to assuming iso/3gp tag style */
13798   else
13799     style = "iso";
13800
13801   /* santize the name for the caps. */
13802   for (i = 0; i < 4; i++) {
13803     guint8 d = data[4 + i];
13804     if (g_ascii_isalnum (d))
13805       ndata[i] = g_ascii_tolower (d);
13806     else
13807       ndata[i] = '_';
13808   }
13809
13810   media_type = g_strdup_printf ("application/x-gst-qt-%c%c%c%c-tag",
13811       ndata[0], ndata[1], ndata[2], ndata[3]);
13812   GST_DEBUG_OBJECT (demux, "media type %s", media_type);
13813
13814   s = gst_structure_new (media_type, "style", G_TYPE_STRING, style, NULL);
13815   sample = gst_sample_new (buf, NULL, NULL, s);
13816   gst_buffer_unref (buf);
13817   g_free (media_type);
13818
13819   GST_DEBUG_OBJECT (demux, "adding private tag; size %d, info %" GST_PTR_FORMAT,
13820       len, s);
13821
13822   gst_tag_list_add (taglist, GST_TAG_MERGE_APPEND,
13823       GST_QT_DEMUX_PRIVATE_TAG, sample, NULL);
13824
13825   gst_sample_unref (sample);
13826 }
13827
13828 static void
13829 qtdemux_parse_udta (GstQTDemux * qtdemux, GstTagList * taglist, GNode * udta)
13830 {
13831   GNode *meta;
13832   GNode *ilst;
13833   GNode *xmp_;
13834   GNode *node;
13835   gint i;
13836   GstQtDemuxTagList demuxtaglist;
13837
13838   demuxtaglist.demux = qtdemux;
13839   demuxtaglist.taglist = taglist;
13840
13841   meta = qtdemux_tree_get_child_by_type (udta, FOURCC_meta);
13842   if (meta != NULL) {
13843     ilst = qtdemux_tree_get_child_by_type (meta, FOURCC_ilst);
13844     if (ilst == NULL) {
13845       GST_LOG_OBJECT (qtdemux, "no ilst");
13846       return;
13847     }
13848   } else {
13849     ilst = udta;
13850     GST_LOG_OBJECT (qtdemux, "no meta so using udta itself");
13851   }
13852
13853   i = 0;
13854   while (i < G_N_ELEMENTS (add_funcs)) {
13855     node = qtdemux_tree_get_child_by_type (ilst, add_funcs[i].fourcc);
13856     if (node) {
13857       gint len;
13858
13859       len = QT_UINT32 (node->data);
13860       if (len < 12) {
13861         GST_DEBUG_OBJECT (qtdemux, "too small tag atom %" GST_FOURCC_FORMAT,
13862             GST_FOURCC_ARGS (add_funcs[i].fourcc));
13863       } else {
13864         add_funcs[i].func (qtdemux, taglist, add_funcs[i].gst_tag,
13865             add_funcs[i].gst_tag_bis, node);
13866       }
13867       g_node_destroy (node);
13868     } else {
13869       i++;
13870     }
13871   }
13872
13873   /* parsed nodes have been removed, pass along remainder as blob */
13874   g_node_children_foreach (ilst, G_TRAVERSE_ALL,
13875       (GNodeForeachFunc) qtdemux_tag_add_blob, &demuxtaglist);
13876
13877   /* parse up XMP_ node if existing */
13878   xmp_ = qtdemux_tree_get_child_by_type (udta, FOURCC_XMP_);
13879   if (xmp_ != NULL) {
13880     GstBuffer *buf;
13881     GstTagList *xmptaglist;
13882
13883     buf = _gst_buffer_new_wrapped (((guint8 *) xmp_->data) + 8,
13884         QT_UINT32 ((guint8 *) xmp_->data) - 8, NULL);
13885     xmptaglist = gst_tag_list_from_xmp_buffer (buf);
13886     gst_buffer_unref (buf);
13887
13888     qtdemux_handle_xmp_taglist (qtdemux, taglist, xmptaglist);
13889   } else {
13890     GST_DEBUG_OBJECT (qtdemux, "No XMP_ node found");
13891   }
13892 }
13893
13894 typedef struct
13895 {
13896   GstStructure *structure;      /* helper for sort function */
13897   gchar *location;
13898   guint min_req_bitrate;
13899   guint min_req_qt_version;
13900 } GstQtReference;
13901
13902 static gint
13903 qtdemux_redirects_sort_func (gconstpointer a, gconstpointer b)
13904 {
13905   GstQtReference *ref_a = (GstQtReference *) a;
13906   GstQtReference *ref_b = (GstQtReference *) b;
13907
13908   if (ref_b->min_req_qt_version != ref_a->min_req_qt_version)
13909     return ref_b->min_req_qt_version - ref_a->min_req_qt_version;
13910
13911   /* known bitrates go before unknown; higher bitrates go first */
13912   return ref_b->min_req_bitrate - ref_a->min_req_bitrate;
13913 }
13914
13915 /* sort the redirects and post a message for the application.
13916  */
13917 static void
13918 qtdemux_process_redirects (GstQTDemux * qtdemux, GList * references)
13919 {
13920   GstQtReference *best;
13921   GstStructure *s;
13922   GstMessage *msg;
13923   GValue list_val = { 0, };
13924   GList *l;
13925
13926   g_assert (references != NULL);
13927
13928   references = g_list_sort (references, qtdemux_redirects_sort_func);
13929
13930   best = (GstQtReference *) references->data;
13931
13932   g_value_init (&list_val, GST_TYPE_LIST);
13933
13934   for (l = references; l != NULL; l = l->next) {
13935     GstQtReference *ref = (GstQtReference *) l->data;
13936     GValue struct_val = { 0, };
13937
13938     ref->structure = gst_structure_new ("redirect",
13939         "new-location", G_TYPE_STRING, ref->location, NULL);
13940
13941     if (ref->min_req_bitrate > 0) {
13942       gst_structure_set (ref->structure, "minimum-bitrate", G_TYPE_INT,
13943           ref->min_req_bitrate, NULL);
13944     }
13945
13946     g_value_init (&struct_val, GST_TYPE_STRUCTURE);
13947     g_value_set_boxed (&struct_val, ref->structure);
13948     gst_value_list_append_value (&list_val, &struct_val);
13949     g_value_unset (&struct_val);
13950     /* don't free anything here yet, since we need best->structure below */
13951   }
13952
13953   g_assert (best != NULL);
13954   s = gst_structure_copy (best->structure);
13955
13956   if (g_list_length (references) > 1) {
13957     gst_structure_set_value (s, "locations", &list_val);
13958   }
13959
13960   g_value_unset (&list_val);
13961
13962   for (l = references; l != NULL; l = l->next) {
13963     GstQtReference *ref = (GstQtReference *) l->data;
13964
13965     gst_structure_free (ref->structure);
13966     g_free (ref->location);
13967     g_free (ref);
13968   }
13969   g_list_free (references);
13970
13971   GST_INFO_OBJECT (qtdemux, "posting redirect message: %" GST_PTR_FORMAT, s);
13972   msg = gst_message_new_element (GST_OBJECT_CAST (qtdemux), s);
13973   gst_element_post_message (GST_ELEMENT_CAST (qtdemux), msg);
13974   qtdemux->posted_redirect = TRUE;
13975 }
13976
13977 /* look for redirect nodes, collect all redirect information and
13978  * process it.
13979  */
13980 static gboolean
13981 qtdemux_parse_redirects (GstQTDemux * qtdemux)
13982 {
13983   GNode *rmra, *rmda, *rdrf;
13984
13985   rmra = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_rmra);
13986   if (rmra) {
13987     GList *redirects = NULL;
13988
13989     rmda = qtdemux_tree_get_child_by_type (rmra, FOURCC_rmda);
13990     while (rmda) {
13991       GstQtReference ref = { NULL, NULL, 0, 0 };
13992       GNode *rmdr, *rmvc;
13993
13994       if ((rmdr = qtdemux_tree_get_child_by_type (rmda, FOURCC_rmdr))) {
13995         ref.min_req_bitrate = QT_UINT32 ((guint8 *) rmdr->data + 12);
13996         GST_LOG_OBJECT (qtdemux, "data rate atom, required bitrate = %u",
13997             ref.min_req_bitrate);
13998       }
13999
14000       if ((rmvc = qtdemux_tree_get_child_by_type (rmda, FOURCC_rmvc))) {
14001         guint32 package = QT_FOURCC ((guint8 *) rmvc->data + 12);
14002         guint version = QT_UINT32 ((guint8 *) rmvc->data + 16);
14003
14004 #ifndef GST_DISABLE_GST_DEBUG
14005         guint bitmask = QT_UINT32 ((guint8 *) rmvc->data + 20);
14006 #endif
14007         guint check_type = QT_UINT16 ((guint8 *) rmvc->data + 24);
14008
14009         GST_LOG_OBJECT (qtdemux,
14010             "version check atom [%" GST_FOURCC_FORMAT "], version=0x%08x"
14011             ", mask=%08x, check_type=%u", GST_FOURCC_ARGS (package), version,
14012             bitmask, check_type);
14013         if (package == FOURCC_qtim && check_type == 0) {
14014           ref.min_req_qt_version = version;
14015         }
14016       }
14017
14018       rdrf = qtdemux_tree_get_child_by_type (rmda, FOURCC_rdrf);
14019       if (rdrf) {
14020         guint32 ref_type;
14021         guint8 *ref_data;
14022         guint ref_len;
14023
14024         ref_len = QT_UINT32 ((guint8 *) rdrf->data);
14025         if (ref_len > 20) {
14026           ref_type = QT_FOURCC ((guint8 *) rdrf->data + 12);
14027           ref_data = (guint8 *) rdrf->data + 20;
14028           if (ref_type == FOURCC_alis) {
14029             guint record_len, record_version, fn_len;
14030
14031             if (ref_len > 70) {
14032               /* MacOSX alias record, google for alias-layout.txt */
14033               record_len = QT_UINT16 (ref_data + 4);
14034               record_version = QT_UINT16 (ref_data + 4 + 2);
14035               fn_len = QT_UINT8 (ref_data + 50);
14036               if (record_len > 50 && record_version == 2 && fn_len > 0) {
14037                 ref.location = g_strndup ((gchar *) ref_data + 51, fn_len);
14038               }
14039             } else {
14040               GST_WARNING_OBJECT (qtdemux, "Invalid rdrf/alis size (%u < 70)",
14041                   ref_len);
14042             }
14043           } else if (ref_type == FOURCC_url_) {
14044             ref.location = g_strndup ((gchar *) ref_data, ref_len - 8);
14045           } else {
14046             GST_DEBUG_OBJECT (qtdemux,
14047                 "unknown rdrf reference type %" GST_FOURCC_FORMAT,
14048                 GST_FOURCC_ARGS (ref_type));
14049           }
14050           if (ref.location != NULL) {
14051             GST_INFO_OBJECT (qtdemux, "New location: %s", ref.location);
14052             redirects =
14053                 g_list_prepend (redirects, g_memdup (&ref, sizeof (ref)));
14054           } else {
14055             GST_WARNING_OBJECT (qtdemux,
14056                 "Failed to extract redirect location from rdrf atom");
14057           }
14058         } else {
14059           GST_WARNING_OBJECT (qtdemux, "Invalid rdrf size (%u < 20)", ref_len);
14060         }
14061       }
14062
14063       /* look for others */
14064       rmda = qtdemux_tree_get_sibling_by_type (rmda, FOURCC_rmda);
14065     }
14066
14067     if (redirects != NULL) {
14068       qtdemux_process_redirects (qtdemux, redirects);
14069     }
14070   }
14071   return TRUE;
14072 }
14073
14074 static GstTagList *
14075 qtdemux_add_container_format (GstQTDemux * qtdemux, GstTagList * tags)
14076 {
14077   const gchar *fmt;
14078
14079   if (tags == NULL) {
14080     tags = gst_tag_list_new_empty ();
14081     gst_tag_list_set_scope (tags, GST_TAG_SCOPE_GLOBAL);
14082   }
14083
14084   if (qtdemux->major_brand == FOURCC_mjp2)
14085     fmt = "Motion JPEG 2000";
14086   else if ((qtdemux->major_brand & 0xffff) == FOURCC_3g__)
14087     fmt = "3GP";
14088   else if (qtdemux->major_brand == FOURCC_qt__)
14089     fmt = "Quicktime";
14090   else if (qtdemux->fragmented)
14091     fmt = "ISO fMP4";
14092   else
14093     fmt = "ISO MP4/M4A";
14094
14095   GST_LOG_OBJECT (qtdemux, "mapped %" GST_FOURCC_FORMAT " to '%s'",
14096       GST_FOURCC_ARGS (qtdemux->major_brand), fmt);
14097
14098   gst_tag_list_add (tags, GST_TAG_MERGE_REPLACE, GST_TAG_CONTAINER_FORMAT,
14099       fmt, NULL);
14100
14101   return tags;
14102 }
14103
14104 /* we have read the complete moov node now.
14105  * This function parses all of the relevant info, creates the traks and
14106  * prepares all data structures for playback
14107  */
14108 static gboolean
14109 qtdemux_parse_tree (GstQTDemux * qtdemux)
14110 {
14111   GNode *mvhd;
14112   GNode *trak;
14113   GNode *udta;
14114   GNode *mvex;
14115   GNode *pssh;
14116   guint64 creation_time;
14117   GstDateTime *datetime = NULL;
14118   gint version;
14119
14120   /* make sure we have a usable taglist */
14121   qtdemux->tag_list = gst_tag_list_make_writable (qtdemux->tag_list);
14122
14123   mvhd = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_mvhd);
14124   if (mvhd == NULL) {
14125     GST_LOG_OBJECT (qtdemux, "No mvhd node found, looking for redirects.");
14126     return qtdemux_parse_redirects (qtdemux);
14127   }
14128
14129   version = QT_UINT8 ((guint8 *) mvhd->data + 8);
14130   if (version == 1) {
14131     creation_time = QT_UINT64 ((guint8 *) mvhd->data + 12);
14132     qtdemux->timescale = QT_UINT32 ((guint8 *) mvhd->data + 28);
14133     qtdemux->duration = QT_UINT64 ((guint8 *) mvhd->data + 32);
14134   } else if (version == 0) {
14135     creation_time = QT_UINT32 ((guint8 *) mvhd->data + 12);
14136     qtdemux->timescale = QT_UINT32 ((guint8 *) mvhd->data + 20);
14137     qtdemux->duration = QT_UINT32 ((guint8 *) mvhd->data + 24);
14138   } else {
14139     GST_WARNING_OBJECT (qtdemux, "Unhandled mvhd version %d", version);
14140     return FALSE;
14141   }
14142
14143   /* Moving qt creation time (secs since 1904) to unix time */
14144   if (creation_time != 0) {
14145     /* Try to use epoch first as it should be faster and more commonly found */
14146     if (creation_time >= QTDEMUX_SECONDS_FROM_1904_TO_1970) {
14147       GTimeVal now;
14148
14149       creation_time -= QTDEMUX_SECONDS_FROM_1904_TO_1970;
14150       /* some data cleansing sanity */
14151       g_get_current_time (&now);
14152       if (now.tv_sec + 24 * 3600 < creation_time) {
14153         GST_DEBUG_OBJECT (qtdemux, "discarding bogus future creation time");
14154       } else {
14155         datetime = gst_date_time_new_from_unix_epoch_utc (creation_time);
14156       }
14157     } else {
14158       GDateTime *base_dt = g_date_time_new_utc (1904, 1, 1, 0, 0, 0);
14159       GDateTime *dt, *dt_local;
14160
14161       dt = g_date_time_add_seconds (base_dt, creation_time);
14162       dt_local = g_date_time_to_local (dt);
14163       datetime = gst_date_time_new_from_g_date_time (dt_local);
14164
14165       g_date_time_unref (base_dt);
14166       g_date_time_unref (dt);
14167     }
14168   }
14169   if (datetime) {
14170     /* Use KEEP as explicit tags should have a higher priority than mvhd tag */
14171     gst_tag_list_add (qtdemux->tag_list, GST_TAG_MERGE_KEEP, GST_TAG_DATE_TIME,
14172         datetime, NULL);
14173     gst_date_time_unref (datetime);
14174   }
14175
14176   GST_INFO_OBJECT (qtdemux, "timescale: %u", qtdemux->timescale);
14177   GST_INFO_OBJECT (qtdemux, "duration: %" G_GUINT64_FORMAT, qtdemux->duration);
14178
14179   /* check for fragmented file and get some (default) data */
14180   mvex = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_mvex);
14181   if (mvex) {
14182     GNode *mehd;
14183     GstByteReader mehd_data;
14184
14185     /* let track parsing or anyone know weird stuff might happen ... */
14186     qtdemux->fragmented = TRUE;
14187
14188     /* compensate for total duration */
14189     mehd = qtdemux_tree_get_child_by_type_full (mvex, FOURCC_mehd, &mehd_data);
14190     if (mehd)
14191       qtdemux_parse_mehd (qtdemux, &mehd_data);
14192   }
14193
14194   /* Update the movie segment duration, unless it was directly given to us
14195    * by upstream. Otherwise let it as is, as we don't want to mangle the
14196    * duration provided by upstream that may come e.g. from a MPD file. */
14197   if (!qtdemux->upstream_format_is_time) {
14198     GstClockTime duration;
14199     /* set duration in the segment info */
14200     gst_qtdemux_get_duration (qtdemux, &duration);
14201     qtdemux->segment.duration = duration;
14202     /* also do not exceed duration; stop is set that way post seek anyway,
14203      * and segment activation falls back to duration,
14204      * whereas loop only checks stop, so let's align this here as well */
14205     qtdemux->segment.stop = duration;
14206   }
14207
14208   /* parse all traks */
14209   trak = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_trak);
14210   while (trak) {
14211     qtdemux_parse_trak (qtdemux, trak);
14212     /* iterate all siblings */
14213     trak = qtdemux_tree_get_sibling_by_type (trak, FOURCC_trak);
14214   }
14215
14216   qtdemux->tag_list = gst_tag_list_make_writable (qtdemux->tag_list);
14217
14218   /* find tags */
14219   udta = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_udta);
14220   if (udta) {
14221     qtdemux_parse_udta (qtdemux, qtdemux->tag_list, udta);
14222   } else {
14223     GST_LOG_OBJECT (qtdemux, "No udta node found.");
14224   }
14225
14226   /* maybe also some tags in meta box */
14227   udta = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_meta);
14228   if (udta) {
14229     GST_DEBUG_OBJECT (qtdemux, "Parsing meta box for tags.");
14230     qtdemux_parse_udta (qtdemux, qtdemux->tag_list, udta);
14231   } else {
14232     GST_LOG_OBJECT (qtdemux, "No meta node found.");
14233   }
14234
14235   /* parse any protection system info */
14236   pssh = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_pssh);
14237   while (pssh) {
14238     GST_LOG_OBJECT (qtdemux, "Parsing pssh box.");
14239     qtdemux_parse_pssh (qtdemux, pssh);
14240     pssh = qtdemux_tree_get_sibling_by_type (pssh, FOURCC_pssh);
14241   }
14242
14243   qtdemux->tag_list = qtdemux_add_container_format (qtdemux, qtdemux->tag_list);
14244
14245   return TRUE;
14246 }
14247
14248 /* taken from ffmpeg */
14249 static int
14250 read_descr_size (guint8 * ptr, guint8 * end, guint8 ** end_out)
14251 {
14252   int count = 4;
14253   int len = 0;
14254
14255   while (count--) {
14256     int c;
14257
14258     if (ptr >= end)
14259       return -1;
14260
14261     c = *ptr++;
14262     len = (len << 7) | (c & 0x7f);
14263     if (!(c & 0x80))
14264       break;
14265   }
14266   *end_out = ptr;
14267   return len;
14268 }
14269
14270 static GList *
14271 parse_xiph_stream_headers (GstQTDemux * qtdemux, gpointer codec_data,
14272     gsize codec_data_size)
14273 {
14274   GList *list = NULL;
14275   guint8 *p = codec_data;
14276   gint i, offset, num_packets;
14277   guint *length, last;
14278
14279   GST_MEMDUMP_OBJECT (qtdemux, "xiph codec data", codec_data, codec_data_size);
14280
14281   if (codec_data == NULL || codec_data_size == 0)
14282     goto error;
14283
14284   /* start of the stream and vorbis audio or theora video, need to
14285    * send the codec_priv data as first three packets */
14286   num_packets = p[0] + 1;
14287   GST_DEBUG_OBJECT (qtdemux,
14288       "%u stream headers, total length=%" G_GSIZE_FORMAT " bytes",
14289       (guint) num_packets, codec_data_size);
14290
14291   /* Let's put some limits, Don't think there even is a xiph codec
14292    * with more than 3-4 headers */
14293   if (G_UNLIKELY (num_packets > 16)) {
14294     GST_WARNING_OBJECT (qtdemux,
14295         "Unlikely number of xiph headers, most likely not valid");
14296     goto error;
14297   }
14298
14299   length = g_alloca (num_packets * sizeof (guint));
14300   last = 0;
14301   offset = 1;
14302
14303   /* first packets, read length values */
14304   for (i = 0; i < num_packets - 1; i++) {
14305     length[i] = 0;
14306     while (offset < codec_data_size) {
14307       length[i] += p[offset];
14308       if (p[offset++] != 0xff)
14309         break;
14310     }
14311     last += length[i];
14312   }
14313   if (offset + last > codec_data_size)
14314     goto error;
14315
14316   /* last packet is the remaining size */
14317   length[i] = codec_data_size - offset - last;
14318
14319   for (i = 0; i < num_packets; i++) {
14320     GstBuffer *hdr;
14321
14322     GST_DEBUG_OBJECT (qtdemux, "buffer %d: %u bytes", i, (guint) length[i]);
14323
14324     if (offset + length[i] > codec_data_size)
14325       goto error;
14326
14327     hdr = gst_buffer_new_wrapped (g_memdup (p + offset, length[i]), length[i]);
14328     list = g_list_append (list, hdr);
14329
14330     offset += length[i];
14331   }
14332
14333   return list;
14334
14335   /* ERRORS */
14336 error:
14337   {
14338     if (list != NULL)
14339       g_list_free_full (list, (GDestroyNotify) gst_buffer_unref);
14340     return NULL;
14341   }
14342
14343 }
14344
14345 /* this can change the codec originally present in @list */
14346 static void
14347 gst_qtdemux_handle_esds (GstQTDemux * qtdemux, QtDemuxStream * stream,
14348     QtDemuxStreamStsdEntry * entry, GNode * esds, GstTagList * list)
14349 {
14350   int len = QT_UINT32 (esds->data);
14351   guint8 *ptr = esds->data;
14352   guint8 *end = ptr + len;
14353   int tag;
14354   guint8 *data_ptr = NULL;
14355   int data_len = 0;
14356   guint8 object_type_id = 0;
14357   guint8 stream_type = 0;
14358   const char *codec_name = NULL;
14359   GstCaps *caps = NULL;
14360
14361   GST_MEMDUMP_OBJECT (qtdemux, "esds", ptr, len);
14362   ptr += 8;
14363   GST_DEBUG_OBJECT (qtdemux, "version/flags = %08x", QT_UINT32 (ptr));
14364   ptr += 4;
14365   while (ptr + 1 < end) {
14366     tag = QT_UINT8 (ptr);
14367     GST_DEBUG_OBJECT (qtdemux, "tag = %02x", tag);
14368     ptr++;
14369     len = read_descr_size (ptr, end, &ptr);
14370     GST_DEBUG_OBJECT (qtdemux, "len = %d", len);
14371
14372     /* Check the stated amount of data is available for reading */
14373     if (len < 0 || ptr + len > end)
14374       break;
14375
14376     switch (tag) {
14377       case ES_DESCRIPTOR_TAG:
14378         GST_DEBUG_OBJECT (qtdemux, "ID 0x%04x", QT_UINT16 (ptr));
14379         GST_DEBUG_OBJECT (qtdemux, "priority 0x%04x", QT_UINT8 (ptr + 2));
14380         ptr += 3;
14381         break;
14382       case DECODER_CONFIG_DESC_TAG:{
14383         guint max_bitrate, avg_bitrate;
14384
14385         object_type_id = QT_UINT8 (ptr);
14386         stream_type = QT_UINT8 (ptr + 1) >> 2;
14387         max_bitrate = QT_UINT32 (ptr + 5);
14388         avg_bitrate = QT_UINT32 (ptr + 9);
14389         GST_DEBUG_OBJECT (qtdemux, "object_type_id %02x", object_type_id);
14390         GST_DEBUG_OBJECT (qtdemux, "stream_type %02x", stream_type);
14391         GST_DEBUG_OBJECT (qtdemux, "buffer_size_db %02x", QT_UINT24 (ptr + 2));
14392         GST_DEBUG_OBJECT (qtdemux, "max bitrate %u", max_bitrate);
14393         GST_DEBUG_OBJECT (qtdemux, "avg bitrate %u", avg_bitrate);
14394         if (max_bitrate > 0 && max_bitrate < G_MAXUINT32) {
14395           gst_tag_list_add (list, GST_TAG_MERGE_REPLACE,
14396               GST_TAG_MAXIMUM_BITRATE, max_bitrate, NULL);
14397         }
14398         if (avg_bitrate > 0 && avg_bitrate < G_MAXUINT32) {
14399           gst_tag_list_add (list, GST_TAG_MERGE_REPLACE, GST_TAG_BITRATE,
14400               avg_bitrate, NULL);
14401         }
14402         ptr += 13;
14403         break;
14404       }
14405       case DECODER_SPECIFIC_INFO_TAG:
14406         GST_MEMDUMP_OBJECT (qtdemux, "data", ptr, len);
14407         if (object_type_id == 0xe0 && len == 0x40) {
14408           guint8 *data;
14409           GstStructure *s;
14410           guint32 clut[16];
14411           gint i;
14412
14413           GST_DEBUG_OBJECT (qtdemux,
14414               "Have VOBSUB palette. Creating palette event");
14415           /* move to decConfigDescr data and read palette */
14416           data = ptr;
14417           for (i = 0; i < 16; i++) {
14418             clut[i] = QT_UINT32 (data);
14419             data += 4;
14420           }
14421
14422           s = gst_structure_new ("application/x-gst-dvd", "event",
14423               G_TYPE_STRING, "dvd-spu-clut-change",
14424               "clut00", G_TYPE_INT, clut[0], "clut01", G_TYPE_INT, clut[1],
14425               "clut02", G_TYPE_INT, clut[2], "clut03", G_TYPE_INT, clut[3],
14426               "clut04", G_TYPE_INT, clut[4], "clut05", G_TYPE_INT, clut[5],
14427               "clut06", G_TYPE_INT, clut[6], "clut07", G_TYPE_INT, clut[7],
14428               "clut08", G_TYPE_INT, clut[8], "clut09", G_TYPE_INT, clut[9],
14429               "clut10", G_TYPE_INT, clut[10], "clut11", G_TYPE_INT, clut[11],
14430               "clut12", G_TYPE_INT, clut[12], "clut13", G_TYPE_INT, clut[13],
14431               "clut14", G_TYPE_INT, clut[14], "clut15", G_TYPE_INT, clut[15],
14432               NULL);
14433
14434           /* store event and trigger custom processing */
14435           stream->pending_event =
14436               gst_event_new_custom (GST_EVENT_CUSTOM_DOWNSTREAM, s);
14437         } else {
14438           /* Generic codec_data handler puts it on the caps */
14439           data_ptr = ptr;
14440           data_len = len;
14441         }
14442
14443         ptr += len;
14444         break;
14445       case SL_CONFIG_DESC_TAG:
14446         GST_DEBUG_OBJECT (qtdemux, "data %02x", QT_UINT8 (ptr));
14447         ptr += 1;
14448         break;
14449       default:
14450         GST_DEBUG_OBJECT (qtdemux, "Unknown/unhandled descriptor tag %02x",
14451             tag);
14452         GST_MEMDUMP_OBJECT (qtdemux, "descriptor data", ptr, len);
14453         ptr += len;
14454         break;
14455     }
14456   }
14457
14458   /* object_type_id in the esds atom in mp4a and mp4v tells us which codec is
14459    * in use, and should also be used to override some other parameters for some
14460    * codecs. */
14461   switch (object_type_id) {
14462     case 0x20:                 /* MPEG-4 */
14463       /* 4 bytes for the visual_object_sequence_start_code and 1 byte for the
14464        * profile_and_level_indication */
14465       if (data_ptr != NULL && data_len >= 5 &&
14466           GST_READ_UINT32_BE (data_ptr) == 0x000001b0) {
14467         gst_codec_utils_mpeg4video_caps_set_level_and_profile (entry->caps,
14468             data_ptr + 4, data_len - 4);
14469       }
14470       break;                    /* Nothing special needed here */
14471     case 0x21:                 /* H.264 */
14472       codec_name = "H.264 / AVC";
14473       caps = gst_caps_new_simple ("video/x-h264",
14474           "stream-format", G_TYPE_STRING, "avc",
14475           "alignment", G_TYPE_STRING, "au", NULL);
14476       break;
14477     case 0x40:                 /* AAC (any) */
14478     case 0x66:                 /* AAC Main */
14479     case 0x67:                 /* AAC LC */
14480     case 0x68:                 /* AAC SSR */
14481       /* Override channels and rate based on the codec_data, as it's often
14482        * wrong. */
14483       /* Only do so for basic setup without HE-AAC extension */
14484       if (data_ptr && data_len == 2) {
14485         guint channels, rate;
14486
14487         channels = gst_codec_utils_aac_get_channels (data_ptr, data_len);
14488         if (channels > 0)
14489           entry->n_channels = channels;
14490
14491         rate = gst_codec_utils_aac_get_sample_rate (data_ptr, data_len);
14492         if (rate > 0)
14493           entry->rate = rate;
14494       }
14495
14496       /* Set level and profile if possible */
14497       if (data_ptr != NULL && data_len >= 2) {
14498         gst_codec_utils_aac_caps_set_level_and_profile (entry->caps,
14499             data_ptr, data_len);
14500       } else {
14501         const gchar *profile_str = NULL;
14502         GstBuffer *buffer;
14503         GstMapInfo map;
14504         guint8 *codec_data;
14505         gint rate_idx, profile;
14506
14507         /* No codec_data, let's invent something.
14508          * FIXME: This is wrong for SBR! */
14509
14510         GST_WARNING_OBJECT (qtdemux, "No codec_data for AAC available");
14511
14512         buffer = gst_buffer_new_and_alloc (2);
14513         gst_buffer_map (buffer, &map, GST_MAP_WRITE);
14514         codec_data = map.data;
14515
14516         rate_idx =
14517             gst_codec_utils_aac_get_index_from_sample_rate (CUR_STREAM
14518             (stream)->rate);
14519
14520         switch (object_type_id) {
14521           case 0x66:
14522             profile_str = "main";
14523             profile = 0;
14524             break;
14525           case 0x67:
14526             profile_str = "lc";
14527             profile = 1;
14528             break;
14529           case 0x68:
14530             profile_str = "ssr";
14531             profile = 2;
14532             break;
14533           default:
14534             profile = 3;
14535             break;
14536         }
14537
14538         codec_data[0] = ((profile + 1) << 3) | ((rate_idx & 0xE) >> 1);
14539         codec_data[1] =
14540             ((rate_idx & 0x1) << 7) | (CUR_STREAM (stream)->n_channels << 3);
14541
14542         gst_buffer_unmap (buffer, &map);
14543         gst_caps_set_simple (CUR_STREAM (stream)->caps, "codec_data",
14544             GST_TYPE_BUFFER, buffer, NULL);
14545         gst_buffer_unref (buffer);
14546
14547         if (profile_str) {
14548           gst_caps_set_simple (CUR_STREAM (stream)->caps, "profile",
14549               G_TYPE_STRING, profile_str, NULL);
14550         }
14551       }
14552       break;
14553     case 0x60:                 /* MPEG-2, various profiles */
14554     case 0x61:
14555     case 0x62:
14556     case 0x63:
14557     case 0x64:
14558     case 0x65:
14559       codec_name = "MPEG-2 video";
14560       caps = gst_caps_new_simple ("video/mpeg",
14561           "mpegversion", G_TYPE_INT, 2,
14562           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
14563       break;
14564     case 0x69:                 /* MPEG-2 BC audio */
14565     case 0x6B:                 /* MPEG-1 audio */
14566       caps = gst_caps_new_simple ("audio/mpeg",
14567           "mpegversion", G_TYPE_INT, 1, NULL);
14568       codec_name = "MPEG-1 audio";
14569       break;
14570     case 0x6A:                 /* MPEG-1 */
14571       codec_name = "MPEG-1 video";
14572       caps = gst_caps_new_simple ("video/mpeg",
14573           "mpegversion", G_TYPE_INT, 1,
14574           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
14575       break;
14576     case 0x6C:                 /* MJPEG */
14577       caps =
14578           gst_caps_new_simple ("image/jpeg", "parsed", G_TYPE_BOOLEAN, TRUE,
14579           NULL);
14580       codec_name = "Motion-JPEG";
14581       break;
14582     case 0x6D:                 /* PNG */
14583       caps =
14584           gst_caps_new_simple ("image/png", "parsed", G_TYPE_BOOLEAN, TRUE,
14585           NULL);
14586       codec_name = "PNG still images";
14587       break;
14588     case 0x6E:                 /* JPEG2000 */
14589       codec_name = "JPEG-2000";
14590       caps = gst_caps_new_simple ("image/x-j2c", "fields", G_TYPE_INT, 1, NULL);
14591       break;
14592     case 0xA4:                 /* Dirac */
14593       codec_name = "Dirac";
14594       caps = gst_caps_new_empty_simple ("video/x-dirac");
14595       break;
14596     case 0xA5:                 /* AC3 */
14597       codec_name = "AC-3 audio";
14598       caps = gst_caps_new_simple ("audio/x-ac3",
14599           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
14600       break;
14601     case 0xA9:                 /* AC3 */
14602       codec_name = "DTS audio";
14603       caps = gst_caps_new_simple ("audio/x-dts",
14604           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
14605       break;
14606     case 0xDD:
14607       if (stream_type == 0x05 && data_ptr) {
14608         GList *headers =
14609             parse_xiph_stream_headers (qtdemux, data_ptr, data_len);
14610         if (headers) {
14611           GList *tmp;
14612           GValue arr_val = G_VALUE_INIT;
14613           GValue buf_val = G_VALUE_INIT;
14614           GstStructure *s;
14615
14616           /* Let's assume it's vorbis if it's an audio stream of type 0xdd and we have codec data that extracts properly */
14617           codec_name = "Vorbis";
14618           caps = gst_caps_new_empty_simple ("audio/x-vorbis");
14619           g_value_init (&arr_val, GST_TYPE_ARRAY);
14620           g_value_init (&buf_val, GST_TYPE_BUFFER);
14621           for (tmp = headers; tmp; tmp = tmp->next) {
14622             g_value_set_boxed (&buf_val, (GstBuffer *) tmp->data);
14623             gst_value_array_append_value (&arr_val, &buf_val);
14624           }
14625           s = gst_caps_get_structure (caps, 0);
14626           gst_structure_take_value (s, "streamheader", &arr_val);
14627           g_value_unset (&buf_val);
14628           g_list_free (headers);
14629
14630           data_ptr = NULL;
14631           data_len = 0;
14632         }
14633       }
14634       break;
14635     case 0xE1:                 /* QCELP */
14636       /* QCELP, the codec_data is a riff tag (little endian) with
14637        * 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). */
14638       caps = gst_caps_new_empty_simple ("audio/qcelp");
14639       codec_name = "QCELP";
14640       break;
14641     default:
14642       break;
14643   }
14644
14645   /* If we have a replacement caps, then change our caps for this stream */
14646   if (caps) {
14647     gst_caps_unref (entry->caps);
14648     entry->caps = caps;
14649   }
14650
14651   if (codec_name && list)
14652     gst_tag_list_add (list, GST_TAG_MERGE_REPLACE,
14653         GST_TAG_AUDIO_CODEC, codec_name, NULL);
14654
14655   /* Add the codec_data attribute to caps, if we have it */
14656   if (data_ptr) {
14657     GstBuffer *buffer;
14658
14659     buffer = gst_buffer_new_and_alloc (data_len);
14660     gst_buffer_fill (buffer, 0, data_ptr, data_len);
14661
14662     GST_DEBUG_OBJECT (qtdemux, "setting codec_data from esds");
14663     GST_MEMDUMP_OBJECT (qtdemux, "codec_data from esds", data_ptr, data_len);
14664
14665     gst_caps_set_simple (entry->caps, "codec_data", GST_TYPE_BUFFER,
14666         buffer, NULL);
14667     gst_buffer_unref (buffer);
14668   }
14669
14670 }
14671
14672 static inline GstCaps *
14673 _get_unknown_codec_name (const gchar * type, guint32 fourcc)
14674 {
14675   GstCaps *caps;
14676   guint i;
14677   char *s, fourstr[5];
14678
14679   g_snprintf (fourstr, 5, "%" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (fourcc));
14680   for (i = 0; i < 4; i++) {
14681     if (!g_ascii_isalnum (fourstr[i]))
14682       fourstr[i] = '_';
14683   }
14684   s = g_strdup_printf ("%s/x-gst-fourcc-%s", type, g_strstrip (fourstr));
14685   caps = gst_caps_new_empty_simple (s);
14686   g_free (s);
14687   return caps;
14688 }
14689
14690 #define _codec(name) \
14691   do { \
14692     if (codec_name) { \
14693       *codec_name = g_strdup (name); \
14694     } \
14695   } while (0)
14696
14697 static GstCaps *
14698 qtdemux_video_caps (GstQTDemux * qtdemux, QtDemuxStream * stream,
14699     QtDemuxStreamStsdEntry * entry, guint32 fourcc,
14700     const guint8 * stsd_entry_data, gchar ** codec_name)
14701 {
14702   GstCaps *caps = NULL;
14703   GstVideoFormat format = GST_VIDEO_FORMAT_UNKNOWN;
14704
14705   switch (fourcc) {
14706     case FOURCC_png:
14707       _codec ("PNG still images");
14708       caps = gst_caps_new_empty_simple ("image/png");
14709       break;
14710     case FOURCC_jpeg:
14711       _codec ("JPEG still images");
14712       caps =
14713           gst_caps_new_simple ("image/jpeg", "parsed", G_TYPE_BOOLEAN, TRUE,
14714           NULL);
14715       break;
14716     case GST_MAKE_FOURCC ('m', 'j', 'p', 'a'):
14717     case GST_MAKE_FOURCC ('A', 'V', 'D', 'J'):
14718     case GST_MAKE_FOURCC ('M', 'J', 'P', 'G'):
14719     case GST_MAKE_FOURCC ('d', 'm', 'b', '1'):
14720       _codec ("Motion-JPEG");
14721       caps =
14722           gst_caps_new_simple ("image/jpeg", "parsed", G_TYPE_BOOLEAN, TRUE,
14723           NULL);
14724       break;
14725     case GST_MAKE_FOURCC ('m', 'j', 'p', 'b'):
14726       _codec ("Motion-JPEG format B");
14727       caps = gst_caps_new_empty_simple ("video/x-mjpeg-b");
14728       break;
14729     case FOURCC_mjp2:
14730       _codec ("JPEG-2000");
14731       /* override to what it should be according to spec, avoid palette_data */
14732       entry->bits_per_sample = 24;
14733       caps = gst_caps_new_simple ("image/x-j2c", "fields", G_TYPE_INT, 1, NULL);
14734       break;
14735     case FOURCC_SVQ3:
14736       _codec ("Sorensen video v.3");
14737       caps = gst_caps_new_simple ("video/x-svq",
14738           "svqversion", G_TYPE_INT, 3, NULL);
14739       break;
14740     case GST_MAKE_FOURCC ('s', 'v', 'q', 'i'):
14741     case GST_MAKE_FOURCC ('S', 'V', 'Q', '1'):
14742       _codec ("Sorensen video v.1");
14743       caps = gst_caps_new_simple ("video/x-svq",
14744           "svqversion", G_TYPE_INT, 1, NULL);
14745       break;
14746     case GST_MAKE_FOURCC ('W', 'R', 'A', 'W'):
14747       caps = gst_caps_new_empty_simple ("video/x-raw");
14748       gst_caps_set_simple (caps, "format", G_TYPE_STRING, "RGB8P", NULL);
14749       _codec ("Windows Raw RGB");
14750       stream->alignment = 32;
14751       break;
14752     case FOURCC_raw_:
14753     {
14754       guint16 bps;
14755
14756       bps = QT_UINT16 (stsd_entry_data + 82);
14757       switch (bps) {
14758         case 15:
14759           format = GST_VIDEO_FORMAT_RGB15;
14760           break;
14761         case 16:
14762           format = GST_VIDEO_FORMAT_RGB16;
14763           break;
14764         case 24:
14765           format = GST_VIDEO_FORMAT_RGB;
14766           break;
14767         case 32:
14768           format = GST_VIDEO_FORMAT_ARGB;
14769           break;
14770         default:
14771           /* unknown */
14772           break;
14773       }
14774       break;
14775     }
14776     case GST_MAKE_FOURCC ('y', 'v', '1', '2'):
14777       format = GST_VIDEO_FORMAT_I420;
14778       break;
14779     case GST_MAKE_FOURCC ('y', 'u', 'v', '2'):
14780     case GST_MAKE_FOURCC ('Y', 'u', 'v', '2'):
14781       format = GST_VIDEO_FORMAT_I420;
14782       break;
14783     case FOURCC_2vuy:
14784     case GST_MAKE_FOURCC ('2', 'V', 'u', 'y'):
14785       format = GST_VIDEO_FORMAT_UYVY;
14786       break;
14787     case GST_MAKE_FOURCC ('v', '3', '0', '8'):
14788       format = GST_VIDEO_FORMAT_v308;
14789       break;
14790     case GST_MAKE_FOURCC ('v', '2', '1', '6'):
14791       format = GST_VIDEO_FORMAT_v216;
14792       break;
14793     case FOURCC_v210:
14794       format = GST_VIDEO_FORMAT_v210;
14795       break;
14796     case GST_MAKE_FOURCC ('r', '2', '1', '0'):
14797       format = GST_VIDEO_FORMAT_r210;
14798       break;
14799       /* Packed YUV 4:4:4 10 bit in 32 bits, complex
14800          case GST_MAKE_FOURCC ('v', '4', '1', '0'):
14801          format = GST_VIDEO_FORMAT_v410;
14802          break;
14803        */
14804       /* Packed YUV 4:4:4:4 8 bit in 32 bits
14805        * but different order than AYUV
14806        case GST_MAKE_FOURCC ('v', '4', '0', '8'):
14807        format = GST_VIDEO_FORMAT_v408;
14808        break;
14809        */
14810     case GST_MAKE_FOURCC ('m', 'p', 'e', 'g'):
14811     case GST_MAKE_FOURCC ('m', 'p', 'g', '1'):
14812       _codec ("MPEG-1 video");
14813       caps = gst_caps_new_simple ("video/mpeg", "mpegversion", G_TYPE_INT, 1,
14814           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
14815       break;
14816     case GST_MAKE_FOURCC ('h', 'd', 'v', '1'): /* HDV 720p30 */
14817     case GST_MAKE_FOURCC ('h', 'd', 'v', '2'): /* HDV 1080i60 */
14818     case GST_MAKE_FOURCC ('h', 'd', 'v', '3'): /* HDV 1080i50 */
14819     case GST_MAKE_FOURCC ('h', 'd', 'v', '4'): /* HDV 720p24 */
14820     case GST_MAKE_FOURCC ('h', 'd', 'v', '5'): /* HDV 720p25 */
14821     case GST_MAKE_FOURCC ('h', 'd', 'v', '6'): /* HDV 1080p24 */
14822     case GST_MAKE_FOURCC ('h', 'd', 'v', '7'): /* HDV 1080p25 */
14823     case GST_MAKE_FOURCC ('h', 'd', 'v', '8'): /* HDV 1080p30 */
14824     case GST_MAKE_FOURCC ('h', 'd', 'v', '9'): /* HDV 720p60 */
14825     case GST_MAKE_FOURCC ('h', 'd', 'v', 'a'): /* HDV 720p50 */
14826     case GST_MAKE_FOURCC ('m', 'x', '5', 'n'): /* MPEG2 IMX NTSC 525/60 50mb/s produced by FCP */
14827     case GST_MAKE_FOURCC ('m', 'x', '5', 'p'): /* MPEG2 IMX PAL 625/60 50mb/s produced by FCP */
14828     case GST_MAKE_FOURCC ('m', 'x', '4', 'n'): /* MPEG2 IMX NTSC 525/60 40mb/s produced by FCP */
14829     case GST_MAKE_FOURCC ('m', 'x', '4', 'p'): /* MPEG2 IMX PAL 625/60 40mb/s produced by FCP */
14830     case GST_MAKE_FOURCC ('m', 'x', '3', 'n'): /* MPEG2 IMX NTSC 525/60 30mb/s produced by FCP */
14831     case GST_MAKE_FOURCC ('m', 'x', '3', 'p'): /* MPEG2 IMX PAL 625/50 30mb/s produced by FCP */
14832     case GST_MAKE_FOURCC ('x', 'd', 'v', '1'): /* XDCAM HD 720p30 35Mb/s */
14833     case GST_MAKE_FOURCC ('x', 'd', 'v', '2'): /* XDCAM HD 1080i60 35Mb/s */
14834     case GST_MAKE_FOURCC ('x', 'd', 'v', '3'): /* XDCAM HD 1080i50 35Mb/s */
14835     case GST_MAKE_FOURCC ('x', 'd', 'v', '4'): /* XDCAM HD 720p24 35Mb/s */
14836     case GST_MAKE_FOURCC ('x', 'd', 'v', '5'): /* XDCAM HD 720p25 35Mb/s */
14837     case GST_MAKE_FOURCC ('x', 'd', 'v', '6'): /* XDCAM HD 1080p24 35Mb/s */
14838     case GST_MAKE_FOURCC ('x', 'd', 'v', '7'): /* XDCAM HD 1080p25 35Mb/s */
14839     case GST_MAKE_FOURCC ('x', 'd', 'v', '8'): /* XDCAM HD 1080p30 35Mb/s */
14840     case GST_MAKE_FOURCC ('x', 'd', 'v', '9'): /* XDCAM HD 720p60 35Mb/s */
14841     case GST_MAKE_FOURCC ('x', 'd', 'v', 'a'): /* XDCAM HD 720p50 35Mb/s */
14842     case GST_MAKE_FOURCC ('x', 'd', 'v', 'b'): /* XDCAM EX 1080i60 50Mb/s CBR */
14843     case GST_MAKE_FOURCC ('x', 'd', 'v', 'c'): /* XDCAM EX 1080i50 50Mb/s CBR */
14844     case GST_MAKE_FOURCC ('x', 'd', 'v', 'd'): /* XDCAM HD 1080p24 50Mb/s CBR */
14845     case GST_MAKE_FOURCC ('x', 'd', 'v', 'e'): /* XDCAM HD 1080p25 50Mb/s CBR */
14846     case GST_MAKE_FOURCC ('x', 'd', 'v', 'f'): /* XDCAM HD 1080p30 50Mb/s CBR */
14847     case GST_MAKE_FOURCC ('x', 'd', '5', '1'): /* XDCAM HD422 720p30 50Mb/s CBR */
14848     case GST_MAKE_FOURCC ('x', 'd', '5', '4'): /* XDCAM HD422 720p24 50Mb/s CBR */
14849     case GST_MAKE_FOURCC ('x', 'd', '5', '5'): /* XDCAM HD422 720p25 50Mb/s CBR */
14850     case GST_MAKE_FOURCC ('x', 'd', '5', '9'): /* XDCAM HD422 720p60 50Mb/s CBR */
14851     case GST_MAKE_FOURCC ('x', 'd', '5', 'a'): /* XDCAM HD422 720p50 50Mb/s CBR */
14852     case GST_MAKE_FOURCC ('x', 'd', '5', 'b'): /* XDCAM HD422 1080i50 50Mb/s CBR */
14853     case GST_MAKE_FOURCC ('x', 'd', '5', 'c'): /* XDCAM HD422 1080i50 50Mb/s CBR */
14854     case GST_MAKE_FOURCC ('x', 'd', '5', 'd'): /* XDCAM HD422 1080p24 50Mb/s CBR */
14855     case GST_MAKE_FOURCC ('x', 'd', '5', 'e'): /* XDCAM HD422 1080p25 50Mb/s CBR */
14856     case GST_MAKE_FOURCC ('x', 'd', '5', 'f'): /* XDCAM HD422 1080p30 50Mb/s CBR */
14857     case GST_MAKE_FOURCC ('x', 'd', 'h', 'd'): /* XDCAM HD 540p */
14858     case GST_MAKE_FOURCC ('x', 'd', 'h', '2'): /* XDCAM HD422 540p */
14859     case GST_MAKE_FOURCC ('A', 'V', 'm', 'p'): /* AVID IMX PAL */
14860     case GST_MAKE_FOURCC ('m', 'p', 'g', '2'): /* AVID IMX PAL */
14861     case GST_MAKE_FOURCC ('m', 'p', '2', 'v'): /* AVID IMX PAL */
14862     case GST_MAKE_FOURCC ('m', '2', 'v', '1'):
14863       _codec ("MPEG-2 video");
14864       caps = gst_caps_new_simple ("video/mpeg", "mpegversion", G_TYPE_INT, 2,
14865           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
14866       break;
14867     case GST_MAKE_FOURCC ('g', 'i', 'f', ' '):
14868       _codec ("GIF still images");
14869       caps = gst_caps_new_empty_simple ("image/gif");
14870       break;
14871     case FOURCC_h263:
14872     case GST_MAKE_FOURCC ('H', '2', '6', '3'):
14873     case FOURCC_s263:
14874     case GST_MAKE_FOURCC ('U', '2', '6', '3'):
14875       _codec ("H.263");
14876       /* ffmpeg uses the height/width props, don't know why */
14877       caps = gst_caps_new_simple ("video/x-h263",
14878           "variant", G_TYPE_STRING, "itu", NULL);
14879       break;
14880     case FOURCC_mp4v:
14881     case FOURCC_MP4V:
14882       _codec ("MPEG-4 video");
14883       caps = gst_caps_new_simple ("video/mpeg", "mpegversion", G_TYPE_INT, 4,
14884           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
14885       break;
14886     case GST_MAKE_FOURCC ('3', 'i', 'v', 'd'):
14887     case GST_MAKE_FOURCC ('3', 'I', 'V', 'D'):
14888       _codec ("Microsoft MPEG-4 4.3");  /* FIXME? */
14889       caps = gst_caps_new_simple ("video/x-msmpeg",
14890           "msmpegversion", G_TYPE_INT, 43, NULL);
14891       break;
14892     case GST_MAKE_FOURCC ('D', 'I', 'V', '3'):
14893       _codec ("DivX 3");
14894       caps = gst_caps_new_simple ("video/x-divx",
14895           "divxversion", G_TYPE_INT, 3, NULL);
14896       break;
14897     case GST_MAKE_FOURCC ('D', 'I', 'V', 'X'):
14898     case GST_MAKE_FOURCC ('d', 'i', 'v', 'x'):
14899       _codec ("DivX 4");
14900       caps = gst_caps_new_simple ("video/x-divx",
14901           "divxversion", G_TYPE_INT, 4, NULL);
14902       break;
14903     case GST_MAKE_FOURCC ('D', 'X', '5', '0'):
14904       _codec ("DivX 5");
14905       caps = gst_caps_new_simple ("video/x-divx",
14906           "divxversion", G_TYPE_INT, 5, NULL);
14907       break;
14908
14909     case GST_MAKE_FOURCC ('F', 'F', 'V', '1'):
14910       _codec ("FFV1");
14911       caps = gst_caps_new_simple ("video/x-ffv",
14912           "ffvversion", G_TYPE_INT, 1, NULL);
14913       break;
14914
14915     case GST_MAKE_FOURCC ('3', 'I', 'V', '1'):
14916     case GST_MAKE_FOURCC ('3', 'I', 'V', '2'):
14917     case FOURCC_XVID:
14918     case FOURCC_xvid:
14919     case FOURCC_FMP4:
14920     case FOURCC_fmp4:
14921     case GST_MAKE_FOURCC ('U', 'M', 'P', '4'):
14922       caps = gst_caps_new_simple ("video/mpeg", "mpegversion", G_TYPE_INT, 4,
14923           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
14924       _codec ("MPEG-4");
14925       break;
14926
14927     case GST_MAKE_FOURCC ('c', 'v', 'i', 'd'):
14928       _codec ("Cinepak");
14929       caps = gst_caps_new_empty_simple ("video/x-cinepak");
14930       break;
14931     case GST_MAKE_FOURCC ('q', 'd', 'r', 'w'):
14932       _codec ("Apple QuickDraw");
14933       caps = gst_caps_new_empty_simple ("video/x-qdrw");
14934       break;
14935     case GST_MAKE_FOURCC ('r', 'p', 'z', 'a'):
14936       _codec ("Apple video");
14937       caps = gst_caps_new_empty_simple ("video/x-apple-video");
14938       break;
14939     case FOURCC_H264:
14940     case FOURCC_avc1:
14941       _codec ("H.264 / AVC");
14942       caps = gst_caps_new_simple ("video/x-h264",
14943           "stream-format", G_TYPE_STRING, "avc",
14944           "alignment", G_TYPE_STRING, "au", NULL);
14945       break;
14946     case FOURCC_avc3:
14947       _codec ("H.264 / AVC");
14948       caps = gst_caps_new_simple ("video/x-h264",
14949           "stream-format", G_TYPE_STRING, "avc3",
14950           "alignment", G_TYPE_STRING, "au", NULL);
14951       break;
14952     case FOURCC_H265:
14953     case FOURCC_hvc1:
14954       _codec ("H.265 / HEVC");
14955       caps = gst_caps_new_simple ("video/x-h265",
14956           "stream-format", G_TYPE_STRING, "hvc1",
14957           "alignment", G_TYPE_STRING, "au", NULL);
14958       break;
14959     case FOURCC_hev1:
14960       _codec ("H.265 / HEVC");
14961       caps = gst_caps_new_simple ("video/x-h265",
14962           "stream-format", G_TYPE_STRING, "hev1",
14963           "alignment", G_TYPE_STRING, "au", NULL);
14964       break;
14965     case FOURCC_rle_:
14966       _codec ("Run-length encoding");
14967       caps = gst_caps_new_simple ("video/x-rle",
14968           "layout", G_TYPE_STRING, "quicktime", NULL);
14969       break;
14970     case FOURCC_WRLE:
14971       _codec ("Run-length encoding");
14972       caps = gst_caps_new_simple ("video/x-rle",
14973           "layout", G_TYPE_STRING, "microsoft", NULL);
14974       break;
14975     case GST_MAKE_FOURCC ('I', 'V', '3', '2'):
14976     case GST_MAKE_FOURCC ('i', 'v', '3', '2'):
14977       _codec ("Indeo Video 3");
14978       caps = gst_caps_new_simple ("video/x-indeo",
14979           "indeoversion", G_TYPE_INT, 3, NULL);
14980       break;
14981     case GST_MAKE_FOURCC ('I', 'V', '4', '1'):
14982     case GST_MAKE_FOURCC ('i', 'v', '4', '1'):
14983       _codec ("Intel Video 4");
14984       caps = gst_caps_new_simple ("video/x-indeo",
14985           "indeoversion", G_TYPE_INT, 4, NULL);
14986       break;
14987     case FOURCC_dvcp:
14988     case FOURCC_dvc_:
14989     case GST_MAKE_FOURCC ('d', 'v', 's', 'd'):
14990     case GST_MAKE_FOURCC ('D', 'V', 'S', 'D'):
14991     case GST_MAKE_FOURCC ('d', 'v', 'c', 's'):
14992     case GST_MAKE_FOURCC ('D', 'V', 'C', 'S'):
14993     case GST_MAKE_FOURCC ('d', 'v', '2', '5'):
14994     case GST_MAKE_FOURCC ('d', 'v', 'p', 'p'):
14995       _codec ("DV Video");
14996       caps = gst_caps_new_simple ("video/x-dv", "dvversion", G_TYPE_INT, 25,
14997           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
14998       break;
14999     case FOURCC_dv5n:          /* DVCPRO50 NTSC */
15000     case FOURCC_dv5p:          /* DVCPRO50 PAL */
15001       _codec ("DVCPro50 Video");
15002       caps = gst_caps_new_simple ("video/x-dv", "dvversion", G_TYPE_INT, 50,
15003           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
15004       break;
15005     case GST_MAKE_FOURCC ('d', 'v', 'h', '5'): /* DVCPRO HD 50i produced by FCP */
15006     case GST_MAKE_FOURCC ('d', 'v', 'h', '6'): /* DVCPRO HD 60i produced by FCP */
15007       _codec ("DVCProHD Video");
15008       caps = gst_caps_new_simple ("video/x-dv", "dvversion", G_TYPE_INT, 100,
15009           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
15010       break;
15011     case GST_MAKE_FOURCC ('s', 'm', 'c', ' '):
15012       _codec ("Apple Graphics (SMC)");
15013       caps = gst_caps_new_empty_simple ("video/x-smc");
15014       break;
15015     case GST_MAKE_FOURCC ('V', 'P', '3', '1'):
15016       _codec ("VP3");
15017       caps = gst_caps_new_empty_simple ("video/x-vp3");
15018       break;
15019     case GST_MAKE_FOURCC ('V', 'P', '6', 'F'):
15020       _codec ("VP6 Flash");
15021       caps = gst_caps_new_empty_simple ("video/x-vp6-flash");
15022       break;
15023     case FOURCC_XiTh:
15024       _codec ("Theora");
15025       caps = gst_caps_new_empty_simple ("video/x-theora");
15026       /* theora uses one byte of padding in the data stream because it does not
15027        * allow 0 sized packets while theora does */
15028       entry->padding = 1;
15029       break;
15030     case FOURCC_drac:
15031       _codec ("Dirac");
15032       caps = gst_caps_new_empty_simple ("video/x-dirac");
15033       break;
15034     case GST_MAKE_FOURCC ('t', 'i', 'f', 'f'):
15035       _codec ("TIFF still images");
15036       caps = gst_caps_new_empty_simple ("image/tiff");
15037       break;
15038     case GST_MAKE_FOURCC ('i', 'c', 'o', 'd'):
15039       _codec ("Apple Intermediate Codec");
15040       caps = gst_caps_from_string ("video/x-apple-intermediate-codec");
15041       break;
15042     case GST_MAKE_FOURCC ('A', 'V', 'd', 'n'):
15043       _codec ("AVID DNxHD");
15044       caps = gst_caps_from_string ("video/x-dnxhd");
15045       break;
15046     case FOURCC_VP80:
15047     case FOURCC_vp08:
15048       _codec ("On2 VP8");
15049       caps = gst_caps_from_string ("video/x-vp8");
15050       break;
15051     case FOURCC_vp09:
15052       _codec ("Google VP9");
15053       caps = gst_caps_from_string ("video/x-vp9");
15054       break;
15055     case FOURCC_apcs:
15056       _codec ("Apple ProRes LT");
15057       caps =
15058           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING, "lt",
15059           NULL);
15060       break;
15061     case FOURCC_apch:
15062       _codec ("Apple ProRes HQ");
15063       caps =
15064           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING, "hq",
15065           NULL);
15066       break;
15067     case FOURCC_apcn:
15068       _codec ("Apple ProRes");
15069       caps =
15070           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING,
15071           "standard", NULL);
15072       break;
15073     case FOURCC_apco:
15074       _codec ("Apple ProRes Proxy");
15075       caps =
15076           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING,
15077           "proxy", NULL);
15078       break;
15079     case FOURCC_ap4h:
15080       _codec ("Apple ProRes 4444");
15081       caps =
15082           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING,
15083           "4444", NULL);
15084       break;
15085     case FOURCC_ap4x:
15086       _codec ("Apple ProRes 4444 XQ");
15087       caps =
15088           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING,
15089           "4444xq", NULL);
15090       break;
15091     case FOURCC_cfhd:
15092       _codec ("GoPro CineForm");
15093       caps = gst_caps_from_string ("video/x-cineform");
15094       break;
15095     case FOURCC_vc_1:
15096     case FOURCC_ovc1:
15097       _codec ("VC-1");
15098       caps = gst_caps_new_simple ("video/x-wmv",
15099           "wmvversion", G_TYPE_INT, 3, "format", G_TYPE_STRING, "WVC1", NULL);
15100       break;
15101     case FOURCC_av01:
15102       _codec ("AV1");
15103       caps = gst_caps_new_empty_simple ("video/x-av1");
15104       break;
15105     case GST_MAKE_FOURCC ('k', 'p', 'c', 'd'):
15106     default:
15107     {
15108       caps = _get_unknown_codec_name ("video", fourcc);
15109       break;
15110     }
15111   }
15112
15113   if (format != GST_VIDEO_FORMAT_UNKNOWN) {
15114     GstVideoInfo info;
15115
15116     gst_video_info_init (&info);
15117     gst_video_info_set_format (&info, format, entry->width, entry->height);
15118
15119     caps = gst_video_info_to_caps (&info);
15120     *codec_name = gst_pb_utils_get_codec_description (caps);
15121
15122     /* enable clipping for raw video streams */
15123     stream->need_clip = TRUE;
15124     stream->alignment = 32;
15125   }
15126
15127   return caps;
15128 }
15129
15130 static guint
15131 round_up_pow2 (guint n)
15132 {
15133   n = n - 1;
15134   n = n | (n >> 1);
15135   n = n | (n >> 2);
15136   n = n | (n >> 4);
15137   n = n | (n >> 8);
15138   n = n | (n >> 16);
15139   return n + 1;
15140 }
15141
15142 static GstCaps *
15143 qtdemux_audio_caps (GstQTDemux * qtdemux, QtDemuxStream * stream,
15144     QtDemuxStreamStsdEntry * entry, guint32 fourcc, const guint8 * data,
15145     int len, gchar ** codec_name)
15146 {
15147   GstCaps *caps;
15148   const GstStructure *s;
15149   const gchar *name;
15150   gint endian = 0;
15151   GstAudioFormat format = 0;
15152   gint depth;
15153
15154   GST_DEBUG_OBJECT (qtdemux, "resolve fourcc 0x%08x", GUINT32_TO_BE (fourcc));
15155
15156   depth = entry->bytes_per_packet * 8;
15157
15158   switch (fourcc) {
15159     case GST_MAKE_FOURCC ('N', 'O', 'N', 'E'):
15160     case FOURCC_raw_:
15161       /* 8-bit audio is unsigned */
15162       if (depth == 8)
15163         format = GST_AUDIO_FORMAT_U8;
15164       /* otherwise it's signed and big-endian just like 'twos' */
15165     case FOURCC_twos:
15166       endian = G_BIG_ENDIAN;
15167       /* fall-through */
15168     case FOURCC_sowt:
15169     {
15170       gchar *str;
15171
15172       if (!endian)
15173         endian = G_LITTLE_ENDIAN;
15174
15175       if (!format)
15176         format = gst_audio_format_build_integer (TRUE, endian, depth, depth);
15177
15178       str = g_strdup_printf ("Raw %d-bit PCM audio", depth);
15179       _codec (str);
15180       g_free (str);
15181
15182       caps = gst_caps_new_simple ("audio/x-raw",
15183           "format", G_TYPE_STRING, gst_audio_format_to_string (format),
15184           "layout", G_TYPE_STRING, "interleaved", NULL);
15185       stream->alignment = GST_ROUND_UP_8 (depth);
15186       stream->alignment = round_up_pow2 (stream->alignment);
15187       break;
15188     }
15189     case GST_MAKE_FOURCC ('f', 'l', '6', '4'):
15190       _codec ("Raw 64-bit floating-point audio");
15191       caps = gst_caps_new_simple ("audio/x-raw",
15192           "format", G_TYPE_STRING, "F64BE",
15193           "layout", G_TYPE_STRING, "interleaved", NULL);
15194       stream->alignment = 8;
15195       break;
15196     case GST_MAKE_FOURCC ('f', 'l', '3', '2'):
15197       _codec ("Raw 32-bit floating-point audio");
15198       caps = gst_caps_new_simple ("audio/x-raw",
15199           "format", G_TYPE_STRING, "F32BE",
15200           "layout", G_TYPE_STRING, "interleaved", NULL);
15201       stream->alignment = 4;
15202       break;
15203     case FOURCC_in24:
15204       _codec ("Raw 24-bit PCM audio");
15205       /* we assume BIG ENDIAN, an enda box will tell us to change this to little
15206        * endian later */
15207       caps = gst_caps_new_simple ("audio/x-raw",
15208           "format", G_TYPE_STRING, "S24BE",
15209           "layout", G_TYPE_STRING, "interleaved", NULL);
15210       stream->alignment = 4;
15211       break;
15212     case GST_MAKE_FOURCC ('i', 'n', '3', '2'):
15213       _codec ("Raw 32-bit PCM audio");
15214       caps = gst_caps_new_simple ("audio/x-raw",
15215           "format", G_TYPE_STRING, "S32BE",
15216           "layout", G_TYPE_STRING, "interleaved", NULL);
15217       stream->alignment = 4;
15218       break;
15219     case GST_MAKE_FOURCC ('s', '1', '6', 'l'):
15220       _codec ("Raw 16-bit PCM audio");
15221       caps = gst_caps_new_simple ("audio/x-raw",
15222           "format", G_TYPE_STRING, "S16LE",
15223           "layout", G_TYPE_STRING, "interleaved", NULL);
15224       stream->alignment = 2;
15225       break;
15226     case FOURCC_ulaw:
15227       _codec ("Mu-law audio");
15228       caps = gst_caps_new_empty_simple ("audio/x-mulaw");
15229       break;
15230     case FOURCC_alaw:
15231       _codec ("A-law audio");
15232       caps = gst_caps_new_empty_simple ("audio/x-alaw");
15233       break;
15234     case 0x0200736d:
15235     case 0x6d730002:
15236       _codec ("Microsoft ADPCM");
15237       /* Microsoft ADPCM-ACM code 2 */
15238       caps = gst_caps_new_simple ("audio/x-adpcm",
15239           "layout", G_TYPE_STRING, "microsoft", NULL);
15240       break;
15241     case 0x1100736d:
15242     case 0x6d730011:
15243       _codec ("DVI/IMA ADPCM");
15244       caps = gst_caps_new_simple ("audio/x-adpcm",
15245           "layout", G_TYPE_STRING, "dvi", NULL);
15246       break;
15247     case 0x1700736d:
15248     case 0x6d730017:
15249       _codec ("DVI/Intel IMA ADPCM");
15250       /* FIXME DVI/Intel IMA ADPCM/ACM code 17 */
15251       caps = gst_caps_new_simple ("audio/x-adpcm",
15252           "layout", G_TYPE_STRING, "quicktime", NULL);
15253       break;
15254     case 0x5500736d:
15255     case 0x6d730055:
15256       /* MPEG layer 3, CBR only (pre QT4.1) */
15257     case FOURCC__mp3:
15258       _codec ("MPEG-1 layer 3");
15259       /* MPEG layer 3, CBR & VBR (QT4.1 and later) */
15260       caps = gst_caps_new_simple ("audio/mpeg", "layer", G_TYPE_INT, 3,
15261           "mpegversion", G_TYPE_INT, 1, NULL);
15262       break;
15263     case GST_MAKE_FOURCC ('.', 'm', 'p', '2'):
15264       _codec ("MPEG-1 layer 2");
15265       /* MPEG layer 2 */
15266       caps = gst_caps_new_simple ("audio/mpeg", "layer", G_TYPE_INT, 2,
15267           "mpegversion", G_TYPE_INT, 1, NULL);
15268       break;
15269     case 0x20736d:
15270     case GST_MAKE_FOURCC ('e', 'c', '-', '3'):
15271       _codec ("EAC-3 audio");
15272       caps = gst_caps_new_simple ("audio/x-eac3",
15273           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
15274       entry->sampled = TRUE;
15275       break;
15276     case GST_MAKE_FOURCC ('s', 'a', 'c', '3'): // Nero Recode
15277     case FOURCC_ac_3:
15278       _codec ("AC-3 audio");
15279       caps = gst_caps_new_simple ("audio/x-ac3",
15280           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
15281       entry->sampled = TRUE;
15282       break;
15283     case GST_MAKE_FOURCC ('d', 't', 's', 'c'):
15284     case GST_MAKE_FOURCC ('D', 'T', 'S', ' '):
15285       _codec ("DTS audio");
15286       caps = gst_caps_new_simple ("audio/x-dts",
15287           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
15288       entry->sampled = TRUE;
15289       break;
15290     case GST_MAKE_FOURCC ('d', 't', 's', 'h'): // DTS-HD
15291     case GST_MAKE_FOURCC ('d', 't', 's', 'l'): // DTS-HD Lossless
15292       _codec ("DTS-HD audio");
15293       caps = gst_caps_new_simple ("audio/x-dts",
15294           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
15295       entry->sampled = TRUE;
15296       break;
15297     case FOURCC_MAC3:
15298       _codec ("MACE-3");
15299       caps = gst_caps_new_simple ("audio/x-mace",
15300           "maceversion", G_TYPE_INT, 3, NULL);
15301       break;
15302     case FOURCC_MAC6:
15303       _codec ("MACE-6");
15304       caps = gst_caps_new_simple ("audio/x-mace",
15305           "maceversion", G_TYPE_INT, 6, NULL);
15306       break;
15307     case GST_MAKE_FOURCC ('O', 'g', 'g', 'V'):
15308       /* ogg/vorbis */
15309       caps = gst_caps_new_empty_simple ("application/ogg");
15310       break;
15311     case GST_MAKE_FOURCC ('d', 'v', 'c', 'a'):
15312       _codec ("DV audio");
15313       caps = gst_caps_new_empty_simple ("audio/x-dv");
15314       break;
15315     case FOURCC_mp4a:
15316       _codec ("MPEG-4 AAC audio");
15317       caps = gst_caps_new_simple ("audio/mpeg",
15318           "mpegversion", G_TYPE_INT, 4, "framed", G_TYPE_BOOLEAN, TRUE,
15319           "stream-format", G_TYPE_STRING, "raw", NULL);
15320       break;
15321     case GST_MAKE_FOURCC ('Q', 'D', 'M', 'C'):
15322       _codec ("QDesign Music");
15323       caps = gst_caps_new_empty_simple ("audio/x-qdm");
15324       break;
15325     case FOURCC_QDM2:
15326       _codec ("QDesign Music v.2");
15327       /* FIXME: QDesign music version 2 (no constant) */
15328       if (FALSE && data) {
15329         caps = gst_caps_new_simple ("audio/x-qdm2",
15330             "framesize", G_TYPE_INT, QT_UINT32 (data + 52),
15331             "bitrate", G_TYPE_INT, QT_UINT32 (data + 40),
15332             "blocksize", G_TYPE_INT, QT_UINT32 (data + 44), NULL);
15333       } else {
15334         caps = gst_caps_new_empty_simple ("audio/x-qdm2");
15335       }
15336       break;
15337     case FOURCC_agsm:
15338       _codec ("GSM audio");
15339       caps = gst_caps_new_empty_simple ("audio/x-gsm");
15340       break;
15341     case FOURCC_samr:
15342       _codec ("AMR audio");
15343       caps = gst_caps_new_empty_simple ("audio/AMR");
15344       break;
15345     case FOURCC_sawb:
15346       _codec ("AMR-WB audio");
15347       caps = gst_caps_new_empty_simple ("audio/AMR-WB");
15348       break;
15349     case FOURCC_ima4:
15350       _codec ("Quicktime IMA ADPCM");
15351       caps = gst_caps_new_simple ("audio/x-adpcm",
15352           "layout", G_TYPE_STRING, "quicktime", NULL);
15353       break;
15354     case FOURCC_alac:
15355       _codec ("Apple lossless audio");
15356       caps = gst_caps_new_empty_simple ("audio/x-alac");
15357       break;
15358     case FOURCC_fLaC:
15359       _codec ("Free Lossless Audio Codec");
15360       caps = gst_caps_new_simple ("audio/x-flac",
15361           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
15362       break;
15363     case GST_MAKE_FOURCC ('Q', 'c', 'l', 'p'):
15364       _codec ("QualComm PureVoice");
15365       caps = gst_caps_from_string ("audio/qcelp");
15366       break;
15367     case FOURCC_wma_:
15368     case FOURCC_owma:
15369       _codec ("WMA");
15370       caps = gst_caps_new_empty_simple ("audio/x-wma");
15371       break;
15372     case FOURCC_opus:
15373       _codec ("Opus");
15374       caps = gst_caps_new_empty_simple ("audio/x-opus");
15375       break;
15376     case FOURCC_lpcm:
15377     {
15378       guint32 flags = 0;
15379       guint32 depth = 0;
15380       guint32 width = 0;
15381       GstAudioFormat format;
15382       enum
15383       {
15384         FLAG_IS_FLOAT = 0x1,
15385         FLAG_IS_BIG_ENDIAN = 0x2,
15386         FLAG_IS_SIGNED = 0x4,
15387         FLAG_IS_PACKED = 0x8,
15388         FLAG_IS_ALIGNED_HIGH = 0x10,
15389         FLAG_IS_NON_INTERLEAVED = 0x20
15390       };
15391       _codec ("Raw LPCM audio");
15392
15393       if (data && len >= 36) {
15394         depth = QT_UINT32 (data + 24);
15395         flags = QT_UINT32 (data + 28);
15396         width = QT_UINT32 (data + 32) * 8 / entry->n_channels;
15397       }
15398       if ((flags & FLAG_IS_FLOAT) == 0) {
15399         if (depth == 0)
15400           depth = 16;
15401         if (width == 0)
15402           width = 16;
15403         if ((flags & FLAG_IS_ALIGNED_HIGH))
15404           depth = width;
15405
15406         format = gst_audio_format_build_integer ((flags & FLAG_IS_SIGNED) ?
15407             TRUE : FALSE, (flags & FLAG_IS_BIG_ENDIAN) ?
15408             G_BIG_ENDIAN : G_LITTLE_ENDIAN, width, depth);
15409         caps = gst_caps_new_simple ("audio/x-raw",
15410             "format", G_TYPE_STRING,
15411             format !=
15412             GST_AUDIO_FORMAT_UNKNOWN ? gst_audio_format_to_string (format) :
15413             "UNKNOWN", "layout", G_TYPE_STRING,
15414             (flags & FLAG_IS_NON_INTERLEAVED) ? "non-interleaved" :
15415             "interleaved", NULL);
15416         stream->alignment = GST_ROUND_UP_8 (depth);
15417         stream->alignment = round_up_pow2 (stream->alignment);
15418       } else {
15419         if (width == 0)
15420           width = 32;
15421         if (width == 64) {
15422           if (flags & FLAG_IS_BIG_ENDIAN)
15423             format = GST_AUDIO_FORMAT_F64BE;
15424           else
15425             format = GST_AUDIO_FORMAT_F64LE;
15426         } else {
15427           if (flags & FLAG_IS_BIG_ENDIAN)
15428             format = GST_AUDIO_FORMAT_F32BE;
15429           else
15430             format = GST_AUDIO_FORMAT_F32LE;
15431         }
15432         caps = gst_caps_new_simple ("audio/x-raw",
15433             "format", G_TYPE_STRING, gst_audio_format_to_string (format),
15434             "layout", G_TYPE_STRING, (flags & FLAG_IS_NON_INTERLEAVED) ?
15435             "non-interleaved" : "interleaved", NULL);
15436         stream->alignment = width / 8;
15437       }
15438       break;
15439     }
15440     case GST_MAKE_FOURCC ('q', 't', 'v', 'r'):
15441       /* ? */
15442     default:
15443     {
15444       caps = _get_unknown_codec_name ("audio", fourcc);
15445       break;
15446     }
15447   }
15448
15449   if (caps) {
15450     GstCaps *templ_caps =
15451         gst_static_pad_template_get_caps (&gst_qtdemux_audiosrc_template);
15452     GstCaps *intersection = gst_caps_intersect (caps, templ_caps);
15453     gst_caps_unref (caps);
15454     gst_caps_unref (templ_caps);
15455     caps = intersection;
15456   }
15457
15458   /* enable clipping for raw audio streams */
15459   s = gst_caps_get_structure (caps, 0);
15460   name = gst_structure_get_name (s);
15461   if (g_str_has_prefix (name, "audio/x-raw")) {
15462     stream->need_clip = TRUE;
15463     stream->max_buffer_size = 4096 * entry->bytes_per_frame;
15464     GST_DEBUG ("setting max buffer size to %d", stream->max_buffer_size);
15465   }
15466   return caps;
15467 }
15468
15469 static GstCaps *
15470 qtdemux_sub_caps (GstQTDemux * qtdemux, QtDemuxStream * stream,
15471     QtDemuxStreamStsdEntry * entry, guint32 fourcc,
15472     const guint8 * stsd_entry_data, gchar ** codec_name)
15473 {
15474   GstCaps *caps;
15475
15476   GST_DEBUG_OBJECT (qtdemux, "resolve fourcc 0x%08x", GUINT32_TO_BE (fourcc));
15477
15478   switch (fourcc) {
15479     case FOURCC_mp4s:
15480       _codec ("DVD subtitle");
15481       caps = gst_caps_new_empty_simple ("subpicture/x-dvd");
15482       stream->need_process = TRUE;
15483       break;
15484     case FOURCC_text:
15485       _codec ("Quicktime timed text");
15486       goto text;
15487     case FOURCC_tx3g:
15488       _codec ("3GPP timed text");
15489     text:
15490       caps = gst_caps_new_simple ("text/x-raw", "format", G_TYPE_STRING,
15491           "utf8", NULL);
15492       /* actual text piece needs to be extracted */
15493       stream->need_process = TRUE;
15494       break;
15495     case FOURCC_stpp:
15496       _codec ("XML subtitles");
15497       caps = gst_caps_new_empty_simple ("application/ttml+xml");
15498       break;
15499     case FOURCC_c608:
15500       _codec ("CEA 608 Closed Caption");
15501       caps =
15502           gst_caps_new_simple ("closedcaption/x-cea-608", "format",
15503           G_TYPE_STRING, "s334-1a", NULL);
15504       stream->need_process = TRUE;
15505       stream->need_split = TRUE;
15506       break;
15507     case FOURCC_c708:
15508       _codec ("CEA 708 Closed Caption");
15509       caps =
15510           gst_caps_new_simple ("closedcaption/x-cea-708", "format",
15511           G_TYPE_STRING, "cdp", NULL);
15512       stream->need_process = TRUE;
15513       break;
15514
15515     default:
15516     {
15517       caps = _get_unknown_codec_name ("text", fourcc);
15518       break;
15519     }
15520   }
15521   return caps;
15522 }
15523
15524 static GstCaps *
15525 qtdemux_generic_caps (GstQTDemux * qtdemux, QtDemuxStream * stream,
15526     QtDemuxStreamStsdEntry * entry, guint32 fourcc,
15527     const guint8 * stsd_entry_data, gchar ** codec_name)
15528 {
15529   GstCaps *caps;
15530
15531   switch (fourcc) {
15532     case FOURCC_m1v:
15533       _codec ("MPEG 1 video");
15534       caps = gst_caps_new_simple ("video/mpeg", "mpegversion", G_TYPE_INT, 1,
15535           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
15536       break;
15537     default:
15538       caps = NULL;
15539       break;
15540   }
15541   return caps;
15542 }
15543
15544 static void
15545 gst_qtdemux_append_protection_system_id (GstQTDemux * qtdemux,
15546     const gchar * system_id)
15547 {
15548   gint i;
15549
15550   if (!qtdemux->protection_system_ids)
15551     qtdemux->protection_system_ids =
15552         g_ptr_array_new_with_free_func ((GDestroyNotify) g_free);
15553   /* Check whether we already have an entry for this system ID. */
15554   for (i = 0; i < qtdemux->protection_system_ids->len; ++i) {
15555     const gchar *id = g_ptr_array_index (qtdemux->protection_system_ids, i);
15556     if (g_ascii_strcasecmp (system_id, id) == 0) {
15557       return;
15558     }
15559   }
15560   GST_DEBUG_OBJECT (qtdemux, "Adding cenc protection system ID %s", system_id);
15561   g_ptr_array_add (qtdemux->protection_system_ids, g_ascii_strdown (system_id,
15562           -1));
15563 }