qtdemux: Put framerate into the closedcaption caps if it can be calculated from the...
[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
353   /* current position */
354   guint32 segment_index;
355   guint32 sample_index;
356   GstClockTime time_position;   /* in gst time */
357   guint64 accumulated_base;
358
359   /* the Gst segment we are processing out, used for clipping */
360   GstSegment segment;
361
362   /* quicktime segments */
363   guint32 n_segments;
364   QtDemuxSegment *segments;
365   gboolean dummy_segment;
366   guint32 from_sample;
367   guint32 to_sample;
368
369   gboolean sent_eos;
370   GstTagList *stream_tags;
371   gboolean send_global_tags;
372
373   GstEvent *pending_event;
374
375   GstByteReader stco;
376   GstByteReader stsz;
377   GstByteReader stsc;
378   GstByteReader stts;
379   GstByteReader stss;
380   GstByteReader stps;
381   GstByteReader ctts;
382
383   gboolean chunks_are_samples;  /* TRUE means treat chunks as samples */
384   gint64 stbl_index;
385   /* stco */
386   guint co_size;
387   GstByteReader co_chunk;
388   guint32 first_chunk;
389   guint32 current_chunk;
390   guint32 last_chunk;
391   guint32 samples_per_chunk;
392   guint32 stsd_sample_description_id;
393   guint32 stco_sample_index;
394   /* stsz */
395   guint32 sample_size;          /* 0 means variable sizes are stored in stsz */
396   /* stsc */
397   guint32 stsc_index;
398   guint32 n_samples_per_chunk;
399   guint32 stsc_chunk_index;
400   guint32 stsc_sample_index;
401   guint64 chunk_offset;
402   /* stts */
403   guint32 stts_index;
404   guint32 stts_samples;
405   guint32 n_sample_times;
406   guint32 stts_sample_index;
407   guint64 stts_time;
408   guint32 stts_duration;
409   /* stss */
410   gboolean stss_present;
411   guint32 n_sample_syncs;
412   guint32 stss_index;
413   /* stps */
414   gboolean stps_present;
415   guint32 n_sample_partial_syncs;
416   guint32 stps_index;
417   QtDemuxRandomAccessEntry *ra_entries;
418   guint n_ra_entries;
419
420   const QtDemuxRandomAccessEntry *pending_seek;
421
422   /* ctts */
423   gboolean ctts_present;
424   guint32 n_composition_times;
425   guint32 ctts_index;
426   guint32 ctts_sample_index;
427   guint32 ctts_count;
428   gint32 ctts_soffset;
429
430   /* cslg */
431   guint32 cslg_shift;
432
433   /* fragmented */
434   gboolean parsed_trex;
435   guint32 def_sample_description_index; /* index is 1-based */
436   guint32 def_sample_duration;
437   guint32 def_sample_size;
438   guint32 def_sample_flags;
439
440   gboolean disabled;
441
442   /* stereoscopic video streams */
443   GstVideoMultiviewMode multiview_mode;
444   GstVideoMultiviewFlags multiview_flags;
445
446   /* protected streams */
447   gboolean protected;
448   guint32 protection_scheme_type;
449   guint32 protection_scheme_version;
450   gpointer protection_scheme_info;      /* specific to the protection scheme */
451   GQueue protection_scheme_event_queue;
452
453   gint ref_count;               /* atomic */
454 };
455
456 /* Contains properties and cryptographic info for a set of samples from a
457  * track protected using Common Encryption (cenc) */
458 struct _QtDemuxCencSampleSetInfo
459 {
460   GstStructure *default_properties;
461
462   /* @crypto_info holds one GstStructure per sample */
463   GPtrArray *crypto_info;
464 };
465
466 static const gchar *
467 qt_demux_state_string (enum QtDemuxState state)
468 {
469   switch (state) {
470     case QTDEMUX_STATE_INITIAL:
471       return "<INITIAL>";
472     case QTDEMUX_STATE_HEADER:
473       return "<HEADER>";
474     case QTDEMUX_STATE_MOVIE:
475       return "<MOVIE>";
476     case QTDEMUX_STATE_BUFFER_MDAT:
477       return "<BUFFER_MDAT>";
478     default:
479       return "<UNKNOWN>";
480   }
481 }
482
483 static GNode *qtdemux_tree_get_child_by_type (GNode * node, guint32 fourcc);
484 static GNode *qtdemux_tree_get_child_by_type_full (GNode * node,
485     guint32 fourcc, GstByteReader * parser);
486 static GNode *qtdemux_tree_get_sibling_by_type (GNode * node, guint32 fourcc);
487 static GNode *qtdemux_tree_get_sibling_by_type_full (GNode * node,
488     guint32 fourcc, GstByteReader * parser);
489
490 static GstFlowReturn qtdemux_add_fragmented_samples (GstQTDemux * qtdemux);
491
492 static void gst_qtdemux_check_send_pending_segment (GstQTDemux * demux);
493
494 static GstStaticPadTemplate gst_qtdemux_sink_template =
495     GST_STATIC_PAD_TEMPLATE ("sink",
496     GST_PAD_SINK,
497     GST_PAD_ALWAYS,
498     GST_STATIC_CAPS ("video/quicktime; video/mj2; audio/x-m4a; "
499         "application/x-3gp")
500     );
501
502 static GstStaticPadTemplate gst_qtdemux_videosrc_template =
503 GST_STATIC_PAD_TEMPLATE ("video_%u",
504     GST_PAD_SRC,
505     GST_PAD_SOMETIMES,
506     GST_STATIC_CAPS_ANY);
507
508 static GstStaticPadTemplate gst_qtdemux_audiosrc_template =
509 GST_STATIC_PAD_TEMPLATE ("audio_%u",
510     GST_PAD_SRC,
511     GST_PAD_SOMETIMES,
512     GST_STATIC_CAPS_ANY);
513
514 static GstStaticPadTemplate gst_qtdemux_subsrc_template =
515 GST_STATIC_PAD_TEMPLATE ("subtitle_%u",
516     GST_PAD_SRC,
517     GST_PAD_SOMETIMES,
518     GST_STATIC_CAPS_ANY);
519
520 #define gst_qtdemux_parent_class parent_class
521 G_DEFINE_TYPE (GstQTDemux, gst_qtdemux, GST_TYPE_ELEMENT);
522
523 static void gst_qtdemux_dispose (GObject * object);
524
525 static guint32
526 gst_qtdemux_find_index_linear (GstQTDemux * qtdemux, QtDemuxStream * str,
527     GstClockTime media_time);
528 static guint32
529 gst_qtdemux_find_index_for_given_media_offset_linear (GstQTDemux * qtdemux,
530     QtDemuxStream * str, gint64 media_offset);
531
532 #if 0
533 static void gst_qtdemux_set_index (GstElement * element, GstIndex * index);
534 static GstIndex *gst_qtdemux_get_index (GstElement * element);
535 #endif
536 static GstStateChangeReturn gst_qtdemux_change_state (GstElement * element,
537     GstStateChange transition);
538 static void gst_qtdemux_set_context (GstElement * element,
539     GstContext * context);
540 static gboolean qtdemux_sink_activate (GstPad * sinkpad, GstObject * parent);
541 static gboolean qtdemux_sink_activate_mode (GstPad * sinkpad,
542     GstObject * parent, GstPadMode mode, gboolean active);
543
544 static void gst_qtdemux_loop (GstPad * pad);
545 static GstFlowReturn gst_qtdemux_chain (GstPad * sinkpad, GstObject * parent,
546     GstBuffer * inbuf);
547 static gboolean gst_qtdemux_handle_sink_event (GstPad * pad, GstObject * parent,
548     GstEvent * event);
549 static gboolean gst_qtdemux_handle_sink_query (GstPad * pad, GstObject * parent,
550     GstQuery * query);
551 static gboolean gst_qtdemux_setcaps (GstQTDemux * qtdemux, GstCaps * caps);
552 static gboolean gst_qtdemux_configure_stream (GstQTDemux * qtdemux,
553     QtDemuxStream * stream);
554 static void gst_qtdemux_stream_check_and_change_stsd_index (GstQTDemux * demux,
555     QtDemuxStream * stream);
556 static GstFlowReturn gst_qtdemux_process_adapter (GstQTDemux * demux,
557     gboolean force);
558
559 static void gst_qtdemux_check_seekability (GstQTDemux * demux);
560
561 static gboolean qtdemux_parse_moov (GstQTDemux * qtdemux,
562     const guint8 * buffer, guint length);
563 static gboolean qtdemux_parse_node (GstQTDemux * qtdemux, GNode * node,
564     const guint8 * buffer, guint length);
565 static gboolean qtdemux_parse_tree (GstQTDemux * qtdemux);
566 static void qtdemux_parse_udta (GstQTDemux * qtdemux, GstTagList * taglist,
567     GNode * udta);
568
569 static void gst_qtdemux_handle_esds (GstQTDemux * qtdemux,
570     QtDemuxStream * stream, QtDemuxStreamStsdEntry * entry, GNode * esds,
571     GstTagList * list);
572 static GstCaps *qtdemux_video_caps (GstQTDemux * qtdemux,
573     QtDemuxStream * stream, QtDemuxStreamStsdEntry * entry, guint32 fourcc,
574     const guint8 * stsd_entry_data, gchar ** codec_name);
575 static GstCaps *qtdemux_audio_caps (GstQTDemux * qtdemux,
576     QtDemuxStream * stream, QtDemuxStreamStsdEntry * entry, guint32 fourcc,
577     const guint8 * data, int len, gchar ** codec_name);
578 static GstCaps *qtdemux_sub_caps (GstQTDemux * qtdemux, QtDemuxStream * stream,
579     QtDemuxStreamStsdEntry * entry, guint32 fourcc, const guint8 * data,
580     gchar ** codec_name);
581 static GstCaps *qtdemux_generic_caps (GstQTDemux * qtdemux,
582     QtDemuxStream * stream, QtDemuxStreamStsdEntry * entry, guint32 fourcc,
583     const guint8 * stsd_entry_data, gchar ** codec_name);
584
585 static gboolean qtdemux_parse_samples (GstQTDemux * qtdemux,
586     QtDemuxStream * stream, guint32 n);
587 static GstFlowReturn qtdemux_expose_streams (GstQTDemux * qtdemux);
588 static QtDemuxStream *gst_qtdemux_stream_ref (QtDemuxStream * stream);
589 static void gst_qtdemux_stream_unref (QtDemuxStream * stream);
590 static void gst_qtdemux_stream_clear (QtDemuxStream * stream);
591 static GstFlowReturn qtdemux_prepare_streams (GstQTDemux * qtdemux);
592 static void qtdemux_do_allocation (QtDemuxStream * stream,
593     GstQTDemux * qtdemux);
594 static gboolean gst_qtdemux_activate_segment (GstQTDemux * qtdemux,
595     QtDemuxStream * stream, guint32 seg_idx, GstClockTime offset);
596 static gboolean gst_qtdemux_stream_update_segment (GstQTDemux * qtdemux,
597     QtDemuxStream * stream, gint seg_idx, GstClockTime offset,
598     GstClockTime * _start, GstClockTime * _stop);
599 static void gst_qtdemux_send_gap_for_segment (GstQTDemux * demux,
600     QtDemuxStream * stream, gint segment_index, GstClockTime pos);
601
602 static gboolean qtdemux_pull_mfro_mfra (GstQTDemux * qtdemux);
603 static void check_update_duration (GstQTDemux * qtdemux, GstClockTime duration);
604
605 static gchar *qtdemux_uuid_bytes_to_string (gconstpointer uuid_bytes);
606
607 static GstStructure *qtdemux_get_cenc_sample_properties (GstQTDemux * qtdemux,
608     QtDemuxStream * stream, guint sample_index);
609 static void gst_qtdemux_append_protection_system_id (GstQTDemux * qtdemux,
610     const gchar * id);
611 static void qtdemux_gst_structure_free (GstStructure * gststructure);
612 static void gst_qtdemux_reset (GstQTDemux * qtdemux, gboolean hard);
613
614 static void
615 gst_qtdemux_class_init (GstQTDemuxClass * klass)
616 {
617   GObjectClass *gobject_class;
618   GstElementClass *gstelement_class;
619
620   gobject_class = (GObjectClass *) klass;
621   gstelement_class = (GstElementClass *) klass;
622
623   parent_class = g_type_class_peek_parent (klass);
624
625   gobject_class->dispose = gst_qtdemux_dispose;
626
627   gstelement_class->change_state = GST_DEBUG_FUNCPTR (gst_qtdemux_change_state);
628 #if 0
629   gstelement_class->set_index = GST_DEBUG_FUNCPTR (gst_qtdemux_set_index);
630   gstelement_class->get_index = GST_DEBUG_FUNCPTR (gst_qtdemux_get_index);
631 #endif
632   gstelement_class->set_context = GST_DEBUG_FUNCPTR (gst_qtdemux_set_context);
633
634   gst_tag_register_musicbrainz_tags ();
635
636   gst_element_class_add_static_pad_template (gstelement_class,
637       &gst_qtdemux_sink_template);
638   gst_element_class_add_static_pad_template (gstelement_class,
639       &gst_qtdemux_videosrc_template);
640   gst_element_class_add_static_pad_template (gstelement_class,
641       &gst_qtdemux_audiosrc_template);
642   gst_element_class_add_static_pad_template (gstelement_class,
643       &gst_qtdemux_subsrc_template);
644   gst_element_class_set_static_metadata (gstelement_class, "QuickTime demuxer",
645       "Codec/Demuxer",
646       "Demultiplex a QuickTime file into audio and video streams",
647       "David Schleef <ds@schleef.org>, Wim Taymans <wim@fluendo.com>");
648
649   GST_DEBUG_CATEGORY_INIT (qtdemux_debug, "qtdemux", 0, "qtdemux plugin");
650   gst_riff_init ();
651 }
652
653 static void
654 gst_qtdemux_init (GstQTDemux * qtdemux)
655 {
656   qtdemux->sinkpad =
657       gst_pad_new_from_static_template (&gst_qtdemux_sink_template, "sink");
658   gst_pad_set_activate_function (qtdemux->sinkpad, qtdemux_sink_activate);
659   gst_pad_set_activatemode_function (qtdemux->sinkpad,
660       qtdemux_sink_activate_mode);
661   gst_pad_set_chain_function (qtdemux->sinkpad, gst_qtdemux_chain);
662   gst_pad_set_event_function (qtdemux->sinkpad, gst_qtdemux_handle_sink_event);
663   gst_pad_set_query_function (qtdemux->sinkpad, gst_qtdemux_handle_sink_query);
664   gst_element_add_pad (GST_ELEMENT_CAST (qtdemux), qtdemux->sinkpad);
665
666   qtdemux->adapter = gst_adapter_new ();
667   g_queue_init (&qtdemux->protection_event_queue);
668   qtdemux->flowcombiner = gst_flow_combiner_new ();
669   g_mutex_init (&qtdemux->expose_lock);
670
671   qtdemux->active_streams = g_ptr_array_new_with_free_func
672       ((GDestroyNotify) gst_qtdemux_stream_unref);
673   qtdemux->old_streams = g_ptr_array_new_with_free_func
674       ((GDestroyNotify) gst_qtdemux_stream_unref);
675
676   GST_OBJECT_FLAG_SET (qtdemux, GST_ELEMENT_FLAG_INDEXABLE);
677
678   gst_qtdemux_reset (qtdemux, TRUE);
679 }
680
681 static void
682 gst_qtdemux_dispose (GObject * object)
683 {
684   GstQTDemux *qtdemux = GST_QTDEMUX (object);
685
686   if (qtdemux->adapter) {
687     g_object_unref (G_OBJECT (qtdemux->adapter));
688     qtdemux->adapter = NULL;
689   }
690   gst_tag_list_unref (qtdemux->tag_list);
691   gst_flow_combiner_free (qtdemux->flowcombiner);
692   g_queue_foreach (&qtdemux->protection_event_queue, (GFunc) gst_event_unref,
693       NULL);
694   g_queue_clear (&qtdemux->protection_event_queue);
695
696   g_free (qtdemux->cenc_aux_info_sizes);
697   qtdemux->cenc_aux_info_sizes = NULL;
698   g_mutex_clear (&qtdemux->expose_lock);
699
700   g_ptr_array_free (qtdemux->active_streams, TRUE);
701   g_ptr_array_free (qtdemux->old_streams, TRUE);
702
703   G_OBJECT_CLASS (parent_class)->dispose (object);
704 }
705
706 static void
707 gst_qtdemux_post_no_playable_stream_error (GstQTDemux * qtdemux)
708 {
709   if (qtdemux->posted_redirect) {
710     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
711         (_("This file contains no playable streams.")),
712         ("no known streams found, a redirect message has been posted"));
713   } else {
714     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
715         (_("This file contains no playable streams.")),
716         ("no known streams found"));
717   }
718 }
719
720 static GstBuffer *
721 _gst_buffer_new_wrapped (gpointer mem, gsize size, GFreeFunc free_func)
722 {
723   return gst_buffer_new_wrapped_full (free_func ? 0 : GST_MEMORY_FLAG_READONLY,
724       mem, size, 0, size, mem, free_func);
725 }
726
727 static GstFlowReturn
728 gst_qtdemux_pull_atom (GstQTDemux * qtdemux, guint64 offset, guint64 size,
729     GstBuffer ** buf)
730 {
731   GstFlowReturn flow;
732   GstMapInfo map;
733   gsize bsize;
734
735   if (G_UNLIKELY (size == 0)) {
736     GstFlowReturn ret;
737     GstBuffer *tmp = NULL;
738
739     ret = gst_qtdemux_pull_atom (qtdemux, offset, sizeof (guint32), &tmp);
740     if (ret != GST_FLOW_OK)
741       return ret;
742
743     gst_buffer_map (tmp, &map, GST_MAP_READ);
744     size = QT_UINT32 (map.data);
745     GST_DEBUG_OBJECT (qtdemux, "size 0x%08" G_GINT64_MODIFIER "x", size);
746
747     gst_buffer_unmap (tmp, &map);
748     gst_buffer_unref (tmp);
749   }
750
751   /* Sanity check: catch bogus sizes (fuzzed/broken files) */
752   if (G_UNLIKELY (size > QTDEMUX_MAX_ATOM_SIZE)) {
753     if (qtdemux->state != QTDEMUX_STATE_MOVIE && qtdemux->got_moov) {
754       /* we're pulling header but already got most interesting bits,
755        * so never mind the rest (e.g. tags) (that much) */
756       GST_WARNING_OBJECT (qtdemux, "atom has bogus size %" G_GUINT64_FORMAT,
757           size);
758       return GST_FLOW_EOS;
759     } else {
760       GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
761           (_("This file is invalid and cannot be played.")),
762           ("atom has bogus size %" G_GUINT64_FORMAT, size));
763       return GST_FLOW_ERROR;
764     }
765   }
766
767   flow = gst_pad_pull_range (qtdemux->sinkpad, offset, size, buf);
768
769   if (G_UNLIKELY (flow != GST_FLOW_OK))
770     return flow;
771
772   bsize = gst_buffer_get_size (*buf);
773   /* Catch short reads - we don't want any partial atoms */
774   if (G_UNLIKELY (bsize < size)) {
775     GST_WARNING_OBJECT (qtdemux,
776         "short read: %" G_GSIZE_FORMAT " < %" G_GUINT64_FORMAT, bsize, size);
777     gst_buffer_unref (*buf);
778     *buf = NULL;
779     return GST_FLOW_EOS;
780   }
781
782   return flow;
783 }
784
785 #if 1
786 static gboolean
787 gst_qtdemux_src_convert (GstQTDemux * qtdemux, GstPad * pad,
788     GstFormat src_format, gint64 src_value, GstFormat dest_format,
789     gint64 * dest_value)
790 {
791   gboolean res = TRUE;
792   QtDemuxStream *stream = gst_pad_get_element_private (pad);
793   gint32 index;
794
795   if (stream->subtype != FOURCC_vide) {
796     res = FALSE;
797     goto done;
798   }
799
800   switch (src_format) {
801     case GST_FORMAT_TIME:
802       switch (dest_format) {
803         case GST_FORMAT_BYTES:{
804           index = gst_qtdemux_find_index_linear (qtdemux, stream, src_value);
805           if (-1 == index) {
806             res = FALSE;
807             goto done;
808           }
809
810           *dest_value = stream->samples[index].offset;
811
812           GST_DEBUG_OBJECT (qtdemux, "Format Conversion Time->Offset :%"
813               GST_TIME_FORMAT "->%" G_GUINT64_FORMAT,
814               GST_TIME_ARGS (src_value), *dest_value);
815           break;
816         }
817         default:
818           res = FALSE;
819           break;
820       }
821       break;
822     case GST_FORMAT_BYTES:
823       switch (dest_format) {
824         case GST_FORMAT_TIME:{
825           index =
826               gst_qtdemux_find_index_for_given_media_offset_linear (qtdemux,
827               stream, src_value);
828
829           if (-1 == index) {
830             res = FALSE;
831             goto done;
832           }
833
834           *dest_value =
835               QTSTREAMTIME_TO_GSTTIME (stream,
836               stream->samples[index].timestamp);
837           GST_DEBUG_OBJECT (qtdemux,
838               "Format Conversion Offset->Time :%" G_GUINT64_FORMAT "->%"
839               GST_TIME_FORMAT, src_value, GST_TIME_ARGS (*dest_value));
840           break;
841         }
842         default:
843           res = FALSE;
844           break;
845       }
846       break;
847     default:
848       res = FALSE;
849       break;
850   }
851
852 done:
853   return res;
854 }
855 #endif
856
857 static gboolean
858 gst_qtdemux_get_duration (GstQTDemux * qtdemux, GstClockTime * duration)
859 {
860   gboolean res = FALSE;
861
862   *duration = GST_CLOCK_TIME_NONE;
863
864   if (qtdemux->duration != 0 &&
865       qtdemux->duration != G_MAXINT64 && qtdemux->timescale != 0) {
866     *duration = QTTIME_TO_GSTTIME (qtdemux, qtdemux->duration);
867     res = TRUE;
868   } else {
869     *duration = GST_CLOCK_TIME_NONE;
870   }
871
872   return res;
873 }
874
875 static gboolean
876 gst_qtdemux_handle_src_query (GstPad * pad, GstObject * parent,
877     GstQuery * query)
878 {
879   gboolean res = FALSE;
880   GstQTDemux *qtdemux = GST_QTDEMUX (parent);
881
882   GST_LOG_OBJECT (pad, "%s query", GST_QUERY_TYPE_NAME (query));
883
884   switch (GST_QUERY_TYPE (query)) {
885     case GST_QUERY_POSITION:{
886       GstFormat fmt;
887
888       gst_query_parse_position (query, &fmt, NULL);
889       if (fmt == GST_FORMAT_TIME
890           && GST_CLOCK_TIME_IS_VALID (qtdemux->segment.position)) {
891         gst_query_set_position (query, GST_FORMAT_TIME,
892             qtdemux->segment.position);
893         res = TRUE;
894       }
895     }
896       break;
897     case GST_QUERY_DURATION:{
898       GstFormat fmt;
899
900       gst_query_parse_duration (query, &fmt, NULL);
901       if (fmt == GST_FORMAT_TIME) {
902         /* First try to query upstream */
903         res = gst_pad_query_default (pad, parent, query);
904         if (!res) {
905           GstClockTime duration;
906           if (gst_qtdemux_get_duration (qtdemux, &duration) && duration > 0) {
907             gst_query_set_duration (query, GST_FORMAT_TIME, duration);
908             res = TRUE;
909           }
910         }
911       }
912       break;
913     }
914     case GST_QUERY_CONVERT:{
915       GstFormat src_fmt, dest_fmt;
916       gint64 src_value, dest_value = 0;
917
918       gst_query_parse_convert (query, &src_fmt, &src_value, &dest_fmt, NULL);
919
920       res = gst_qtdemux_src_convert (qtdemux, pad,
921           src_fmt, src_value, dest_fmt, &dest_value);
922       if (res)
923         gst_query_set_convert (query, src_fmt, src_value, dest_fmt, dest_value);
924
925       break;
926     }
927     case GST_QUERY_FORMATS:
928       gst_query_set_formats (query, 2, GST_FORMAT_TIME, GST_FORMAT_BYTES);
929       res = TRUE;
930       break;
931     case GST_QUERY_SEEKING:{
932       GstFormat fmt;
933       gboolean seekable;
934
935       /* try upstream first */
936       res = gst_pad_query_default (pad, parent, query);
937
938       if (!res) {
939         gst_query_parse_seeking (query, &fmt, NULL, NULL, NULL);
940         if (fmt == GST_FORMAT_TIME) {
941           GstClockTime duration;
942
943           gst_qtdemux_get_duration (qtdemux, &duration);
944           seekable = TRUE;
945           if (!qtdemux->pullbased) {
946             GstQuery *q;
947
948             /* we might be able with help from upstream */
949             seekable = FALSE;
950             q = gst_query_new_seeking (GST_FORMAT_BYTES);
951             if (gst_pad_peer_query (qtdemux->sinkpad, q)) {
952               gst_query_parse_seeking (q, &fmt, &seekable, NULL, NULL);
953               GST_LOG_OBJECT (qtdemux, "upstream BYTE seekable %d", seekable);
954             }
955             gst_query_unref (q);
956           }
957           gst_query_set_seeking (query, GST_FORMAT_TIME, seekable, 0, duration);
958           res = TRUE;
959         }
960       }
961       break;
962     }
963     case GST_QUERY_SEGMENT:
964     {
965       GstFormat format;
966       gint64 start, stop;
967
968       format = qtdemux->segment.format;
969
970       start =
971           gst_segment_to_stream_time (&qtdemux->segment, format,
972           qtdemux->segment.start);
973       if ((stop = qtdemux->segment.stop) == -1)
974         stop = qtdemux->segment.duration;
975       else
976         stop = gst_segment_to_stream_time (&qtdemux->segment, format, stop);
977
978       gst_query_set_segment (query, qtdemux->segment.rate, format, start, stop);
979       res = TRUE;
980       break;
981     }
982     default:
983       res = gst_pad_query_default (pad, parent, query);
984       break;
985   }
986
987   return res;
988 }
989
990 static void
991 gst_qtdemux_push_tags (GstQTDemux * qtdemux, QtDemuxStream * stream)
992 {
993   if (G_LIKELY (stream->pad)) {
994     GST_DEBUG_OBJECT (qtdemux, "Checking pad %s:%s for tags",
995         GST_DEBUG_PAD_NAME (stream->pad));
996
997     if (!gst_tag_list_is_empty (stream->stream_tags)) {
998       GST_DEBUG_OBJECT (qtdemux, "Sending tags %" GST_PTR_FORMAT,
999           stream->stream_tags);
1000       gst_pad_push_event (stream->pad,
1001           gst_event_new_tag (gst_tag_list_ref (stream->stream_tags)));
1002     }
1003
1004     if (G_UNLIKELY (stream->send_global_tags)) {
1005       GST_DEBUG_OBJECT (qtdemux, "Sending global tags %" GST_PTR_FORMAT,
1006           qtdemux->tag_list);
1007       gst_pad_push_event (stream->pad,
1008           gst_event_new_tag (gst_tag_list_ref (qtdemux->tag_list)));
1009       stream->send_global_tags = FALSE;
1010     }
1011   }
1012 }
1013
1014 /* push event on all source pads; takes ownership of the event */
1015 static void
1016 gst_qtdemux_push_event (GstQTDemux * qtdemux, GstEvent * event)
1017 {
1018   gboolean has_valid_stream = FALSE;
1019   GstEventType etype = GST_EVENT_TYPE (event);
1020   guint i;
1021
1022   GST_DEBUG_OBJECT (qtdemux, "pushing %s event on all source pads",
1023       GST_EVENT_TYPE_NAME (event));
1024
1025   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
1026     GstPad *pad;
1027     QtDemuxStream *stream = QTDEMUX_NTH_STREAM (qtdemux, i);
1028     GST_DEBUG_OBJECT (qtdemux, "pushing on track-id %u", stream->track_id);
1029
1030     if ((pad = stream->pad)) {
1031       has_valid_stream = TRUE;
1032
1033       if (etype == GST_EVENT_EOS) {
1034         /* let's not send twice */
1035         if (stream->sent_eos)
1036           continue;
1037         stream->sent_eos = TRUE;
1038       }
1039
1040       gst_pad_push_event (pad, gst_event_ref (event));
1041     }
1042   }
1043
1044   gst_event_unref (event);
1045
1046   /* if it is EOS and there are no pads, post an error */
1047   if (!has_valid_stream && etype == GST_EVENT_EOS) {
1048     gst_qtdemux_post_no_playable_stream_error (qtdemux);
1049   }
1050 }
1051
1052 typedef struct
1053 {
1054   guint64 media_time;
1055 } FindData;
1056
1057 static gint
1058 find_func (QtDemuxSample * s1, gint64 * media_time, gpointer user_data)
1059 {
1060   if ((gint64) s1->timestamp > *media_time)
1061     return 1;
1062   if ((gint64) s1->timestamp == *media_time)
1063     return 0;
1064
1065   return -1;
1066 }
1067
1068 /* find the index of the sample that includes the data for @media_time using a
1069  * binary search.  Only to be called in optimized cases of linear search below.
1070  *
1071  * Returns the index of the sample with the corresponding *DTS*.
1072  */
1073 static guint32
1074 gst_qtdemux_find_index (GstQTDemux * qtdemux, QtDemuxStream * str,
1075     guint64 media_time)
1076 {
1077   QtDemuxSample *result;
1078   guint32 index;
1079
1080   /* convert media_time to mov format */
1081   media_time =
1082       gst_util_uint64_scale_ceil (media_time, str->timescale, GST_SECOND);
1083
1084   result = gst_util_array_binary_search (str->samples, str->stbl_index + 1,
1085       sizeof (QtDemuxSample), (GCompareDataFunc) find_func,
1086       GST_SEARCH_MODE_BEFORE, &media_time, NULL);
1087
1088   if (G_LIKELY (result))
1089     index = result - str->samples;
1090   else
1091     index = 0;
1092
1093   return index;
1094 }
1095
1096
1097
1098 /* find the index of the sample that includes the data for @media_offset using a
1099  * linear search
1100  *
1101  * Returns the index of the sample.
1102  */
1103 static guint32
1104 gst_qtdemux_find_index_for_given_media_offset_linear (GstQTDemux * qtdemux,
1105     QtDemuxStream * str, gint64 media_offset)
1106 {
1107   QtDemuxSample *result = str->samples;
1108   guint32 index = 0;
1109
1110   if (result == NULL || str->n_samples == 0)
1111     return -1;
1112
1113   if (media_offset == result->offset)
1114     return index;
1115
1116   result++;
1117   while (index < str->n_samples - 1) {
1118     if (!qtdemux_parse_samples (qtdemux, str, index + 1))
1119       goto parse_failed;
1120
1121     if (media_offset < result->offset)
1122       break;
1123
1124     index++;
1125     result++;
1126   }
1127   return index;
1128
1129   /* ERRORS */
1130 parse_failed:
1131   {
1132     GST_LOG_OBJECT (qtdemux, "Parsing of index %u failed!", index + 1);
1133     return -1;
1134   }
1135 }
1136
1137 /* find the index of the sample that includes the data for @media_time using a
1138  * linear search, and keeping in mind that not all samples may have been parsed
1139  * yet.  If possible, it will delegate to binary search.
1140  *
1141  * Returns the index of the sample.
1142  */
1143 static guint32
1144 gst_qtdemux_find_index_linear (GstQTDemux * qtdemux, QtDemuxStream * str,
1145     GstClockTime media_time)
1146 {
1147   guint32 index = 0;
1148   guint64 mov_time;
1149   QtDemuxSample *sample;
1150
1151   /* convert media_time to mov format */
1152   mov_time =
1153       gst_util_uint64_scale_ceil (media_time, str->timescale, GST_SECOND);
1154
1155   sample = str->samples;
1156   if (mov_time == sample->timestamp + sample->pts_offset)
1157     return index;
1158
1159   /* use faster search if requested time in already parsed range */
1160   sample = str->samples + str->stbl_index;
1161   if (str->stbl_index >= 0 && mov_time <= sample->timestamp) {
1162     index = gst_qtdemux_find_index (qtdemux, str, media_time);
1163     sample = str->samples + index;
1164   } else {
1165     while (index < str->n_samples - 1) {
1166       if (!qtdemux_parse_samples (qtdemux, str, index + 1))
1167         goto parse_failed;
1168
1169       sample = str->samples + index + 1;
1170       if (mov_time < sample->timestamp) {
1171         sample = str->samples + index;
1172         break;
1173       }
1174
1175       index++;
1176     }
1177   }
1178
1179   /* sample->timestamp is now <= media_time, need to find the corresponding
1180    * PTS now by looking backwards */
1181   while (index > 0 && sample->timestamp + sample->pts_offset > mov_time) {
1182     index--;
1183     sample = str->samples + index;
1184   }
1185
1186   return index;
1187
1188   /* ERRORS */
1189 parse_failed:
1190   {
1191     GST_LOG_OBJECT (qtdemux, "Parsing of index %u failed!", index + 1);
1192     return -1;
1193   }
1194 }
1195
1196 /* find the index of the keyframe needed to decode the sample at @index
1197  * of stream @str, or of a subsequent keyframe (depending on @next)
1198  *
1199  * Returns the index of the keyframe.
1200  */
1201 static guint32
1202 gst_qtdemux_find_keyframe (GstQTDemux * qtdemux, QtDemuxStream * str,
1203     guint32 index, gboolean next)
1204 {
1205   guint32 new_index = index;
1206
1207   if (index >= str->n_samples) {
1208     new_index = str->n_samples;
1209     goto beach;
1210   }
1211
1212   /* all keyframes, return index */
1213   if (str->all_keyframe) {
1214     new_index = index;
1215     goto beach;
1216   }
1217
1218   /* else search until we have a keyframe */
1219   while (new_index < str->n_samples) {
1220     if (next && !qtdemux_parse_samples (qtdemux, str, new_index))
1221       goto parse_failed;
1222
1223     if (str->samples[new_index].keyframe)
1224       break;
1225
1226     if (new_index == 0)
1227       break;
1228
1229     if (next)
1230       new_index++;
1231     else
1232       new_index--;
1233   }
1234
1235   if (new_index == str->n_samples) {
1236     GST_DEBUG_OBJECT (qtdemux, "no next keyframe");
1237     new_index = -1;
1238   }
1239
1240 beach:
1241   GST_DEBUG_OBJECT (qtdemux, "searching for keyframe index %s index %u "
1242       "gave %u", next ? "after" : "before", index, new_index);
1243
1244   return new_index;
1245
1246   /* ERRORS */
1247 parse_failed:
1248   {
1249     GST_LOG_OBJECT (qtdemux, "Parsing of index %u failed!", new_index);
1250     return -1;
1251   }
1252 }
1253
1254 /* find the segment for @time_position for @stream
1255  *
1256  * Returns the index of the segment containing @time_position.
1257  * Returns the last segment and sets the @eos variable to TRUE
1258  * if the time is beyond the end. @eos may be NULL
1259  */
1260 static guint32
1261 gst_qtdemux_find_segment (GstQTDemux * qtdemux, QtDemuxStream * stream,
1262     GstClockTime time_position)
1263 {
1264   gint i;
1265   guint32 seg_idx;
1266
1267   GST_LOG_OBJECT (stream->pad, "finding segment for %" GST_TIME_FORMAT,
1268       GST_TIME_ARGS (time_position));
1269
1270   seg_idx = -1;
1271   for (i = 0; i < stream->n_segments; i++) {
1272     QtDemuxSegment *segment = &stream->segments[i];
1273
1274     GST_LOG_OBJECT (stream->pad,
1275         "looking at segment %" GST_TIME_FORMAT "-%" GST_TIME_FORMAT,
1276         GST_TIME_ARGS (segment->time), GST_TIME_ARGS (segment->stop_time));
1277
1278     /* For the last segment we include stop_time in the last segment */
1279     if (i < stream->n_segments - 1) {
1280       if (segment->time <= time_position && time_position < segment->stop_time) {
1281         GST_LOG_OBJECT (stream->pad, "segment %d matches", i);
1282         seg_idx = i;
1283         break;
1284       }
1285     } else {
1286       /* Last segment always matches */
1287       seg_idx = i;
1288       break;
1289     }
1290   }
1291   return seg_idx;
1292 }
1293
1294 /* move the stream @str to the sample position @index.
1295  *
1296  * Updates @str->sample_index and marks discontinuity if needed.
1297  */
1298 static void
1299 gst_qtdemux_move_stream (GstQTDemux * qtdemux, QtDemuxStream * str,
1300     guint32 index)
1301 {
1302   /* no change needed */
1303   if (index == str->sample_index)
1304     return;
1305
1306   GST_DEBUG_OBJECT (qtdemux, "moving to sample %u of %u", index,
1307       str->n_samples);
1308
1309   /* position changed, we have a discont */
1310   str->sample_index = index;
1311   str->offset_in_sample = 0;
1312   /* Each time we move in the stream we store the position where we are
1313    * starting from */
1314   str->from_sample = index;
1315   str->discont = TRUE;
1316 }
1317
1318 static void
1319 gst_qtdemux_adjust_seek (GstQTDemux * qtdemux, gint64 desired_time,
1320     gboolean use_sparse, gboolean next, gint64 * key_time, gint64 * key_offset)
1321 {
1322   guint64 min_offset;
1323   gint64 min_byte_offset = -1;
1324   guint i;
1325
1326   min_offset = desired_time;
1327
1328   /* for each stream, find the index of the sample in the segment
1329    * and move back to the previous keyframe. */
1330   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
1331     QtDemuxStream *str;
1332     guint32 index, kindex;
1333     guint32 seg_idx;
1334     GstClockTime media_start;
1335     GstClockTime media_time;
1336     GstClockTime seg_time;
1337     QtDemuxSegment *seg;
1338     gboolean empty_segment = FALSE;
1339
1340     str = QTDEMUX_NTH_STREAM (qtdemux, i);
1341
1342     if (CUR_STREAM (str)->sparse && !use_sparse)
1343       continue;
1344
1345     seg_idx = gst_qtdemux_find_segment (qtdemux, str, desired_time);
1346     GST_DEBUG_OBJECT (qtdemux, "align segment %d", seg_idx);
1347
1348     /* get segment and time in the segment */
1349     seg = &str->segments[seg_idx];
1350     seg_time = (desired_time - seg->time) * seg->rate;
1351
1352     while (QTSEGMENT_IS_EMPTY (seg)) {
1353       seg_time = 0;
1354       empty_segment = TRUE;
1355       GST_DEBUG_OBJECT (str->pad, "Segment %d is empty, moving to next one",
1356           seg_idx);
1357       seg_idx++;
1358       if (seg_idx == str->n_segments)
1359         break;
1360       seg = &str->segments[seg_idx];
1361     }
1362
1363     if (seg_idx == str->n_segments) {
1364       /* FIXME track shouldn't have the last segment as empty, but if it
1365        * happens we better handle it */
1366       continue;
1367     }
1368
1369     /* get the media time in the segment */
1370     media_start = seg->media_start + seg_time;
1371
1372     /* get the index of the sample with media time */
1373     index = gst_qtdemux_find_index_linear (qtdemux, str, media_start);
1374     GST_DEBUG_OBJECT (qtdemux, "sample for %" GST_TIME_FORMAT " at %u"
1375         " at offset %" G_GUINT64_FORMAT " (empty segment: %d)",
1376         GST_TIME_ARGS (media_start), index, str->samples[index].offset,
1377         empty_segment);
1378
1379     /* shift to next frame if we are looking for next keyframe */
1380     if (next && QTSAMPLE_PTS_NO_CSLG (str, &str->samples[index]) < media_start
1381         && index < str->stbl_index)
1382       index++;
1383
1384     if (!empty_segment) {
1385       /* find previous keyframe */
1386       kindex = gst_qtdemux_find_keyframe (qtdemux, str, index, next);
1387
1388       /* we will settle for one before if none found after */
1389       if (next && kindex == -1)
1390         kindex = gst_qtdemux_find_keyframe (qtdemux, str, index, FALSE);
1391
1392       /* if the keyframe is at a different position, we need to update the
1393        * requested seek time */
1394       if (index != kindex) {
1395         index = kindex;
1396
1397         /* get timestamp of keyframe */
1398         media_time = QTSAMPLE_PTS_NO_CSLG (str, &str->samples[kindex]);
1399         GST_DEBUG_OBJECT (qtdemux,
1400             "keyframe at %u with time %" GST_TIME_FORMAT " at offset %"
1401             G_GUINT64_FORMAT, kindex, GST_TIME_ARGS (media_time),
1402             str->samples[kindex].offset);
1403
1404         /* keyframes in the segment get a chance to change the
1405          * desired_offset. keyframes out of the segment are
1406          * ignored. */
1407         if (media_time >= seg->media_start) {
1408           GstClockTime seg_time;
1409
1410           /* this keyframe is inside the segment, convert back to
1411            * segment time */
1412           seg_time = (media_time - seg->media_start) + seg->time;
1413           if ((!next && (seg_time < min_offset)) ||
1414               (next && (seg_time > min_offset)))
1415             min_offset = seg_time;
1416         }
1417       }
1418     }
1419
1420     if (min_byte_offset < 0 || str->samples[index].offset < min_byte_offset)
1421       min_byte_offset = str->samples[index].offset;
1422   }
1423
1424   if (key_time)
1425     *key_time = min_offset;
1426   if (key_offset)
1427     *key_offset = min_byte_offset;
1428 }
1429
1430 static gboolean
1431 gst_qtdemux_convert_seek (GstPad * pad, GstFormat * format,
1432     GstSeekType cur_type, gint64 * cur, GstSeekType stop_type, gint64 * stop)
1433 {
1434   gboolean res;
1435
1436   g_return_val_if_fail (format != NULL, FALSE);
1437   g_return_val_if_fail (cur != NULL, FALSE);
1438   g_return_val_if_fail (stop != NULL, FALSE);
1439
1440   if (*format == GST_FORMAT_TIME)
1441     return TRUE;
1442
1443   res = TRUE;
1444   if (cur_type != GST_SEEK_TYPE_NONE)
1445     res = gst_pad_query_convert (pad, *format, *cur, GST_FORMAT_TIME, cur);
1446   if (res && stop_type != GST_SEEK_TYPE_NONE)
1447     res = gst_pad_query_convert (pad, *format, *stop, GST_FORMAT_TIME, stop);
1448
1449   if (res)
1450     *format = GST_FORMAT_TIME;
1451
1452   return res;
1453 }
1454
1455 /* perform seek in push based mode:
1456    find BYTE position to move to based on time and delegate to upstream
1457 */
1458 static gboolean
1459 gst_qtdemux_do_push_seek (GstQTDemux * qtdemux, GstPad * pad, GstEvent * event)
1460 {
1461   gdouble rate;
1462   GstFormat format;
1463   GstSeekFlags flags;
1464   GstSeekType cur_type, stop_type;
1465   gint64 cur, stop, key_cur;
1466   gboolean res;
1467   gint64 byte_cur;
1468   gint64 original_stop;
1469   guint32 seqnum;
1470
1471   GST_DEBUG_OBJECT (qtdemux, "doing push-based seek");
1472
1473   gst_event_parse_seek (event, &rate, &format, &flags,
1474       &cur_type, &cur, &stop_type, &stop);
1475   seqnum = gst_event_get_seqnum (event);
1476
1477   /* only forward streaming and seeking is possible */
1478   if (rate <= 0)
1479     goto unsupported_seek;
1480
1481   /* convert to TIME if needed and possible */
1482   if (!gst_qtdemux_convert_seek (pad, &format, cur_type, &cur,
1483           stop_type, &stop))
1484     goto no_format;
1485
1486   /* Upstream seek in bytes will have undefined stop, but qtdemux stores
1487    * the original stop position to use when upstream pushes the new segment
1488    * for this seek */
1489   original_stop = stop;
1490   stop = -1;
1491
1492   /* find reasonable corresponding BYTE position,
1493    * also try to mind about keyframes, since we can not go back a bit for them
1494    * later on */
1495   /* determining @next here based on SNAP_BEFORE/SNAP_AFTER should
1496    * mostly just work, but let's not yet boldly go there  ... */
1497   gst_qtdemux_adjust_seek (qtdemux, cur, FALSE, FALSE, &key_cur, &byte_cur);
1498
1499   if (byte_cur == -1)
1500     goto abort_seek;
1501
1502   GST_DEBUG_OBJECT (qtdemux, "Pushing BYTE seek rate %g, "
1503       "start %" G_GINT64_FORMAT ", stop %" G_GINT64_FORMAT, rate, byte_cur,
1504       stop);
1505
1506   GST_OBJECT_LOCK (qtdemux);
1507   qtdemux->seek_offset = byte_cur;
1508   if (!(flags & GST_SEEK_FLAG_KEY_UNIT)) {
1509     qtdemux->push_seek_start = cur;
1510   } else {
1511     qtdemux->push_seek_start = key_cur;
1512   }
1513
1514   if (stop_type == GST_SEEK_TYPE_NONE) {
1515     qtdemux->push_seek_stop = qtdemux->segment.stop;
1516   } else {
1517     qtdemux->push_seek_stop = original_stop;
1518   }
1519   GST_OBJECT_UNLOCK (qtdemux);
1520
1521   qtdemux->segment_seqnum = seqnum;
1522   /* BYTE seek event */
1523   event = gst_event_new_seek (rate, GST_FORMAT_BYTES, flags, cur_type, byte_cur,
1524       stop_type, stop);
1525   gst_event_set_seqnum (event, seqnum);
1526   res = gst_pad_push_event (qtdemux->sinkpad, event);
1527
1528   return res;
1529
1530   /* ERRORS */
1531 abort_seek:
1532   {
1533     GST_DEBUG_OBJECT (qtdemux, "could not determine byte position to seek to, "
1534         "seek aborted.");
1535     return FALSE;
1536   }
1537 unsupported_seek:
1538   {
1539     GST_DEBUG_OBJECT (qtdemux, "unsupported seek, seek aborted.");
1540     return FALSE;
1541   }
1542 no_format:
1543   {
1544     GST_DEBUG_OBJECT (qtdemux, "unsupported format given, seek aborted.");
1545     return FALSE;
1546   }
1547 }
1548
1549 /* perform the seek.
1550  *
1551  * We set all segment_indexes in the streams to unknown and
1552  * adjust the time_position to the desired position. this is enough
1553  * to trigger a segment switch in the streaming thread to start
1554  * streaming from the desired position.
1555  *
1556  * Keyframe seeking is a little more complicated when dealing with
1557  * segments. Ideally we want to move to the previous keyframe in
1558  * the segment but there might not be a keyframe in the segment. In
1559  * fact, none of the segments could contain a keyframe. We take a
1560  * practical approach: seek to the previous keyframe in the segment,
1561  * if there is none, seek to the beginning of the segment.
1562  *
1563  * Called with STREAM_LOCK
1564  */
1565 static gboolean
1566 gst_qtdemux_perform_seek (GstQTDemux * qtdemux, GstSegment * segment,
1567     guint32 seqnum, GstSeekFlags flags)
1568 {
1569   gint64 desired_offset;
1570   guint i;
1571
1572   desired_offset = segment->position;
1573
1574   GST_DEBUG_OBJECT (qtdemux, "seeking to %" GST_TIME_FORMAT,
1575       GST_TIME_ARGS (desired_offset));
1576
1577   /* may not have enough fragmented info to do this adjustment,
1578    * and we can't scan (and probably should not) at this time with
1579    * possibly flushing upstream */
1580   if ((flags & GST_SEEK_FLAG_KEY_UNIT) && !qtdemux->fragmented) {
1581     gint64 min_offset;
1582     gboolean next, before, after;
1583
1584     before = ! !(flags & GST_SEEK_FLAG_SNAP_BEFORE);
1585     after = ! !(flags & GST_SEEK_FLAG_SNAP_AFTER);
1586     next = after && !before;
1587     if (segment->rate < 0)
1588       next = !next;
1589
1590     gst_qtdemux_adjust_seek (qtdemux, desired_offset, TRUE, next, &min_offset,
1591         NULL);
1592     GST_DEBUG_OBJECT (qtdemux, "keyframe seek, align to %"
1593         GST_TIME_FORMAT, GST_TIME_ARGS (min_offset));
1594     desired_offset = min_offset;
1595   }
1596
1597   /* and set all streams to the final position */
1598   gst_flow_combiner_reset (qtdemux->flowcombiner);
1599   qtdemux->segment_seqnum = seqnum;
1600   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
1601     QtDemuxStream *stream = QTDEMUX_NTH_STREAM (qtdemux, i);
1602
1603     stream->time_position = desired_offset;
1604     stream->accumulated_base = 0;
1605     stream->sample_index = -1;
1606     stream->offset_in_sample = 0;
1607     stream->segment_index = -1;
1608     stream->sent_eos = FALSE;
1609
1610     if (segment->flags & GST_SEEK_FLAG_FLUSH)
1611       gst_segment_init (&stream->segment, GST_FORMAT_TIME);
1612   }
1613   segment->position = desired_offset;
1614   segment->time = desired_offset;
1615   if (segment->rate >= 0) {
1616     segment->start = desired_offset;
1617
1618     /* we stop at the end */
1619     if (segment->stop == -1)
1620       segment->stop = segment->duration;
1621   } else {
1622     segment->stop = desired_offset;
1623   }
1624
1625   if (qtdemux->fragmented)
1626     qtdemux->fragmented_seek_pending = TRUE;
1627
1628   return TRUE;
1629 }
1630
1631 /* do a seek in pull based mode */
1632 static gboolean
1633 gst_qtdemux_do_seek (GstQTDemux * qtdemux, GstPad * pad, GstEvent * event)
1634 {
1635   gdouble rate;
1636   GstFormat format;
1637   GstSeekFlags flags;
1638   GstSeekType cur_type, stop_type;
1639   gint64 cur, stop;
1640   gboolean flush;
1641   gboolean update;
1642   GstSegment seeksegment;
1643   guint32 seqnum = GST_SEQNUM_INVALID;
1644   GstEvent *flush_event;
1645   gboolean ret;
1646
1647   if (event) {
1648     GST_DEBUG_OBJECT (qtdemux, "doing seek with event");
1649
1650     gst_event_parse_seek (event, &rate, &format, &flags,
1651         &cur_type, &cur, &stop_type, &stop);
1652     seqnum = gst_event_get_seqnum (event);
1653
1654     /* we have to have a format as the segment format. Try to convert
1655      * if not. */
1656     if (!gst_qtdemux_convert_seek (pad, &format, cur_type, &cur,
1657             stop_type, &stop))
1658       goto no_format;
1659
1660     GST_DEBUG_OBJECT (qtdemux, "seek format %s", gst_format_get_name (format));
1661   } else {
1662     GST_DEBUG_OBJECT (qtdemux, "doing seek without event");
1663     flags = 0;
1664   }
1665
1666   flush = flags & GST_SEEK_FLAG_FLUSH;
1667
1668   /* stop streaming, either by flushing or by pausing the task */
1669   if (flush) {
1670     flush_event = gst_event_new_flush_start ();
1671     if (seqnum != GST_SEQNUM_INVALID)
1672       gst_event_set_seqnum (flush_event, seqnum);
1673     /* unlock upstream pull_range */
1674     gst_pad_push_event (qtdemux->sinkpad, gst_event_ref (flush_event));
1675     /* make sure out loop function exits */
1676     gst_qtdemux_push_event (qtdemux, flush_event);
1677   } else {
1678     /* non flushing seek, pause the task */
1679     gst_pad_pause_task (qtdemux->sinkpad);
1680   }
1681
1682   /* wait for streaming to finish */
1683   GST_PAD_STREAM_LOCK (qtdemux->sinkpad);
1684
1685   /* copy segment, we need this because we still need the old
1686    * segment when we close the current segment. */
1687   memcpy (&seeksegment, &qtdemux->segment, sizeof (GstSegment));
1688
1689   if (event) {
1690     /* configure the segment with the seek variables */
1691     GST_DEBUG_OBJECT (qtdemux, "configuring seek");
1692     if (!gst_segment_do_seek (&seeksegment, rate, format, flags,
1693             cur_type, cur, stop_type, stop, &update)) {
1694       ret = FALSE;
1695       GST_ERROR_OBJECT (qtdemux, "inconsistent seek values, doing nothing");
1696     } else {
1697       /* now do the seek */
1698       ret = gst_qtdemux_perform_seek (qtdemux, &seeksegment, seqnum, flags);
1699     }
1700   } else {
1701     /* now do the seek */
1702     ret = gst_qtdemux_perform_seek (qtdemux, &seeksegment, seqnum, flags);
1703   }
1704
1705   /* prepare for streaming again */
1706   if (flush) {
1707     flush_event = gst_event_new_flush_stop (TRUE);
1708     if (seqnum != GST_SEQNUM_INVALID)
1709       gst_event_set_seqnum (flush_event, seqnum);
1710
1711     gst_pad_push_event (qtdemux->sinkpad, gst_event_ref (flush_event));
1712     gst_qtdemux_push_event (qtdemux, flush_event);
1713   }
1714
1715   /* commit the new segment */
1716   memcpy (&qtdemux->segment, &seeksegment, sizeof (GstSegment));
1717
1718   if (qtdemux->segment.flags & GST_SEEK_FLAG_SEGMENT) {
1719     GstMessage *msg = gst_message_new_segment_start (GST_OBJECT_CAST (qtdemux),
1720         qtdemux->segment.format, qtdemux->segment.position);
1721     if (seqnum != GST_SEQNUM_INVALID)
1722       gst_message_set_seqnum (msg, seqnum);
1723     gst_element_post_message (GST_ELEMENT_CAST (qtdemux), msg);
1724   }
1725
1726   /* restart streaming, NEWSEGMENT will be sent from the streaming thread. */
1727   gst_pad_start_task (qtdemux->sinkpad, (GstTaskFunction) gst_qtdemux_loop,
1728       qtdemux->sinkpad, NULL);
1729
1730   GST_PAD_STREAM_UNLOCK (qtdemux->sinkpad);
1731
1732   return ret;
1733
1734   /* ERRORS */
1735 no_format:
1736   {
1737     GST_DEBUG_OBJECT (qtdemux, "unsupported format given, seek aborted.");
1738     return FALSE;
1739   }
1740 }
1741
1742 static gboolean
1743 qtdemux_ensure_index (GstQTDemux * qtdemux)
1744 {
1745   guint i;
1746
1747   GST_DEBUG_OBJECT (qtdemux, "collecting all metadata for all streams");
1748
1749   /* Build complete index */
1750   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
1751     QtDemuxStream *stream = QTDEMUX_NTH_STREAM (qtdemux, i);
1752
1753     if (!qtdemux_parse_samples (qtdemux, stream, stream->n_samples - 1)) {
1754       GST_LOG_OBJECT (qtdemux,
1755           "Building complete index of track-id %u for seeking failed!",
1756           stream->track_id);
1757       return FALSE;
1758     }
1759   }
1760
1761   return TRUE;
1762 }
1763
1764 static gboolean
1765 gst_qtdemux_handle_src_event (GstPad * pad, GstObject * parent,
1766     GstEvent * event)
1767 {
1768   gboolean res = TRUE;
1769   GstQTDemux *qtdemux = GST_QTDEMUX (parent);
1770
1771   switch (GST_EVENT_TYPE (event)) {
1772     case GST_EVENT_SEEK:
1773     {
1774 #ifndef GST_DISABLE_GST_DEBUG
1775       GstClockTime ts = gst_util_get_timestamp ();
1776 #endif
1777       guint32 seqnum = gst_event_get_seqnum (event);
1778
1779       qtdemux->received_seek = TRUE;
1780
1781       if (seqnum == qtdemux->segment_seqnum) {
1782         GST_LOG_OBJECT (pad,
1783             "Drop duplicated SEEK event seqnum %" G_GUINT32_FORMAT, seqnum);
1784         gst_event_unref (event);
1785         return TRUE;
1786       }
1787
1788       if (qtdemux->upstream_format_is_time && qtdemux->fragmented) {
1789         /* seek should be handled by upstream, we might need to re-download fragments */
1790         GST_DEBUG_OBJECT (qtdemux,
1791             "let upstream handle seek for fragmented playback");
1792         goto upstream;
1793       }
1794
1795       /* Build complete index for seeking;
1796        * if not a fragmented file at least */
1797       if (!qtdemux->fragmented)
1798         if (!qtdemux_ensure_index (qtdemux))
1799           goto index_failed;
1800 #ifndef GST_DISABLE_GST_DEBUG
1801       ts = gst_util_get_timestamp () - ts;
1802       GST_INFO_OBJECT (qtdemux,
1803           "Time taken to parse index %" GST_TIME_FORMAT, GST_TIME_ARGS (ts));
1804 #endif
1805     }
1806       if (qtdemux->pullbased) {
1807         res = gst_qtdemux_do_seek (qtdemux, pad, event);
1808       } else if (gst_pad_push_event (qtdemux->sinkpad, gst_event_ref (event))) {
1809         GST_DEBUG_OBJECT (qtdemux, "Upstream successfully seeked");
1810         res = TRUE;
1811       } else if (qtdemux->state == QTDEMUX_STATE_MOVIE
1812           && QTDEMUX_N_STREAMS (qtdemux)
1813           && !qtdemux->fragmented) {
1814         res = gst_qtdemux_do_push_seek (qtdemux, pad, event);
1815       } else {
1816         GST_DEBUG_OBJECT (qtdemux,
1817             "ignoring seek in push mode in current state");
1818         res = FALSE;
1819       }
1820       gst_event_unref (event);
1821       break;
1822     default:
1823     upstream:
1824       res = gst_pad_event_default (pad, parent, event);
1825       break;
1826   }
1827
1828 done:
1829   return res;
1830
1831   /* ERRORS */
1832 index_failed:
1833   {
1834     GST_ERROR_OBJECT (qtdemux, "Index failed");
1835     gst_event_unref (event);
1836     res = FALSE;
1837     goto done;
1838   }
1839 }
1840
1841 /* Find, for each track, the first sample in coding order that has a file offset >= @byte_pos.
1842  *
1843  * If @fw is false, the coding order is explored backwards.
1844  *
1845  * If @set is true, each stream will be moved to its matched sample, or EOS if no matching
1846  * sample is found for that track.
1847  *
1848  * The stream and sample index of the sample with the minimum offset in the direction explored
1849  * (see @fw) is returned in the output parameters @_stream and @_index respectively.
1850  *
1851  * @_time is set to the QTSAMPLE_PTS of the matched sample with the minimum QTSAMPLE_PTS in the
1852  * direction explored, which may not always match the QTSAMPLE_PTS of the sample returned in
1853  * @_stream and @_index. */
1854 static void
1855 gst_qtdemux_find_sample (GstQTDemux * qtdemux, gint64 byte_pos, gboolean fw,
1856     gboolean set, QtDemuxStream ** _stream, gint * _index, gint64 * _time)
1857 {
1858   gint i, index;
1859   gint64 time, min_time;
1860   QtDemuxStream *stream;
1861   gint iter;
1862
1863   min_time = -1;
1864   stream = NULL;
1865   index = -1;
1866
1867   for (iter = 0; iter < QTDEMUX_N_STREAMS (qtdemux); iter++) {
1868     QtDemuxStream *str;
1869     gint inc;
1870     gboolean set_sample;
1871
1872     str = QTDEMUX_NTH_STREAM (qtdemux, iter);
1873     set_sample = !set;
1874
1875     if (fw) {
1876       i = 0;
1877       inc = 1;
1878     } else {
1879       i = str->n_samples - 1;
1880       inc = -1;
1881     }
1882
1883     for (; (i >= 0) && (i < str->n_samples); i += inc) {
1884       if (str->samples[i].size == 0)
1885         continue;
1886
1887       if (fw && (str->samples[i].offset < byte_pos))
1888         continue;
1889
1890       if (!fw && (str->samples[i].offset + str->samples[i].size > byte_pos))
1891         continue;
1892
1893       /* move stream to first available sample */
1894       if (set) {
1895         gst_qtdemux_move_stream (qtdemux, str, i);
1896         set_sample = TRUE;
1897       }
1898
1899       /* avoid index from sparse streams since they might be far away */
1900       if (!CUR_STREAM (str)->sparse) {
1901         /* determine min/max time */
1902         time = QTSAMPLE_PTS (str, &str->samples[i]);
1903         if (min_time == -1 || (!fw && time > min_time) ||
1904             (fw && time < min_time)) {
1905           min_time = time;
1906         }
1907
1908         /* determine stream with leading sample, to get its position */
1909         if (!stream ||
1910             (fw && (str->samples[i].offset < stream->samples[index].offset)) ||
1911             (!fw && (str->samples[i].offset > stream->samples[index].offset))) {
1912           stream = str;
1913           index = i;
1914         }
1915       }
1916       break;
1917     }
1918
1919     /* no sample for this stream, mark eos */
1920     if (!set_sample)
1921       gst_qtdemux_move_stream (qtdemux, str, str->n_samples);
1922   }
1923
1924   if (_time)
1925     *_time = min_time;
1926   if (_stream)
1927     *_stream = stream;
1928   if (_index)
1929     *_index = index;
1930 }
1931
1932 /* Copied from mpegtsbase code */
1933 /* FIXME: replace this function when we add new util function for stream-id creation */
1934 static gchar *
1935 _get_upstream_id (GstQTDemux * demux)
1936 {
1937   gchar *upstream_id = gst_pad_get_stream_id (demux->sinkpad);
1938
1939   if (!upstream_id) {
1940     /* Try to create one from the upstream URI, else use a randome number */
1941     GstQuery *query;
1942     gchar *uri = NULL;
1943
1944     /* Try to generate one from the URI query and
1945      * if it fails take a random number instead */
1946     query = gst_query_new_uri ();
1947     if (gst_element_query (GST_ELEMENT_CAST (demux), query)) {
1948       gst_query_parse_uri (query, &uri);
1949     }
1950
1951     if (uri) {
1952       GChecksum *cs;
1953
1954       /* And then generate an SHA256 sum of the URI */
1955       cs = g_checksum_new (G_CHECKSUM_SHA256);
1956       g_checksum_update (cs, (const guchar *) uri, strlen (uri));
1957       g_free (uri);
1958       upstream_id = g_strdup (g_checksum_get_string (cs));
1959       g_checksum_free (cs);
1960     } else {
1961       /* Just get some random number if the URI query fails */
1962       GST_FIXME_OBJECT (demux, "Creating random stream-id, consider "
1963           "implementing a deterministic way of creating a stream-id");
1964       upstream_id =
1965           g_strdup_printf ("%08x%08x%08x%08x", g_random_int (), g_random_int (),
1966           g_random_int (), g_random_int ());
1967     }
1968
1969     gst_query_unref (query);
1970   }
1971   return upstream_id;
1972 }
1973
1974 static QtDemuxStream *
1975 _create_stream (GstQTDemux * demux, guint32 track_id)
1976 {
1977   QtDemuxStream *stream;
1978   gchar *upstream_id;
1979
1980   stream = g_new0 (QtDemuxStream, 1);
1981   stream->demux = demux;
1982   stream->track_id = track_id;
1983   upstream_id = _get_upstream_id (demux);
1984   stream->stream_id = g_strdup_printf ("%s/%03u", upstream_id, track_id);
1985   g_free (upstream_id);
1986   /* new streams always need a discont */
1987   stream->discont = TRUE;
1988   /* we enable clipping for raw audio/video streams */
1989   stream->need_clip = FALSE;
1990   stream->need_process = FALSE;
1991   stream->segment_index = -1;
1992   stream->time_position = 0;
1993   stream->sample_index = -1;
1994   stream->offset_in_sample = 0;
1995   stream->new_stream = TRUE;
1996   stream->multiview_mode = GST_VIDEO_MULTIVIEW_MODE_NONE;
1997   stream->multiview_flags = GST_VIDEO_MULTIVIEW_FLAGS_NONE;
1998   stream->protected = FALSE;
1999   stream->protection_scheme_type = 0;
2000   stream->protection_scheme_version = 0;
2001   stream->protection_scheme_info = NULL;
2002   stream->n_samples_moof = 0;
2003   stream->duration_moof = 0;
2004   stream->duration_last_moof = 0;
2005   stream->alignment = 1;
2006   stream->stream_tags = gst_tag_list_new_empty ();
2007   gst_tag_list_set_scope (stream->stream_tags, GST_TAG_SCOPE_STREAM);
2008   g_queue_init (&stream->protection_scheme_event_queue);
2009   stream->ref_count = 1;
2010   /* consistent default for push based mode */
2011   gst_segment_init (&stream->segment, GST_FORMAT_TIME);
2012   return stream;
2013 }
2014
2015 static gboolean
2016 gst_qtdemux_setcaps (GstQTDemux * demux, GstCaps * caps)
2017 {
2018   GstStructure *structure;
2019   const gchar *variant;
2020   const GstCaps *mediacaps = NULL;
2021
2022   GST_DEBUG_OBJECT (demux, "Sink set caps: %" GST_PTR_FORMAT, caps);
2023
2024   structure = gst_caps_get_structure (caps, 0);
2025   variant = gst_structure_get_string (structure, "variant");
2026
2027   if (variant && strcmp (variant, "mss-fragmented") == 0) {
2028     QtDemuxStream *stream;
2029     const GValue *value;
2030
2031     demux->fragmented = TRUE;
2032     demux->mss_mode = TRUE;
2033
2034     if (QTDEMUX_N_STREAMS (demux) > 1) {
2035       /* can't do this, we can only renegotiate for another mss format */
2036       return FALSE;
2037     }
2038
2039     value = gst_structure_get_value (structure, "media-caps");
2040     /* create stream */
2041     if (value) {
2042       const GValue *timescale_v;
2043
2044       /* TODO update when stream changes during playback */
2045
2046       if (QTDEMUX_N_STREAMS (demux) == 0) {
2047         stream = _create_stream (demux, 1);
2048         g_ptr_array_add (demux->active_streams, stream);
2049         /* mss has no stsd/stsd entry, use id 0 as default */
2050         stream->stsd_entries_length = 1;
2051         stream->stsd_sample_description_id = stream->cur_stsd_entry_index = 0;
2052         stream->stsd_entries = g_new0 (QtDemuxStreamStsdEntry, 1);
2053       } else {
2054         stream = QTDEMUX_NTH_STREAM (demux, 0);
2055       }
2056
2057       timescale_v = gst_structure_get_value (structure, "timescale");
2058       if (timescale_v) {
2059         stream->timescale = g_value_get_uint64 (timescale_v);
2060       } else {
2061         /* default mss timescale */
2062         stream->timescale = 10000000;
2063       }
2064       demux->timescale = stream->timescale;
2065
2066       mediacaps = gst_value_get_caps (value);
2067       if (!CUR_STREAM (stream)->caps
2068           || !gst_caps_is_equal_fixed (mediacaps, CUR_STREAM (stream)->caps)) {
2069         GST_DEBUG_OBJECT (demux, "We have a new caps %" GST_PTR_FORMAT,
2070             mediacaps);
2071         stream->new_caps = TRUE;
2072       }
2073       gst_caps_replace (&CUR_STREAM (stream)->caps, (GstCaps *) mediacaps);
2074       structure = gst_caps_get_structure (mediacaps, 0);
2075       if (g_str_has_prefix (gst_structure_get_name (structure), "video")) {
2076         stream->subtype = FOURCC_vide;
2077
2078         gst_structure_get_int (structure, "width", &CUR_STREAM (stream)->width);
2079         gst_structure_get_int (structure, "height",
2080             &CUR_STREAM (stream)->height);
2081         gst_structure_get_fraction (structure, "framerate",
2082             &CUR_STREAM (stream)->fps_n, &CUR_STREAM (stream)->fps_d);
2083       } else if (g_str_has_prefix (gst_structure_get_name (structure), "audio")) {
2084         gint rate = 0;
2085         stream->subtype = FOURCC_soun;
2086         gst_structure_get_int (structure, "channels",
2087             &CUR_STREAM (stream)->n_channels);
2088         gst_structure_get_int (structure, "rate", &rate);
2089         CUR_STREAM (stream)->rate = rate;
2090       }
2091     }
2092     gst_caps_replace (&demux->media_caps, (GstCaps *) mediacaps);
2093   } else {
2094     demux->mss_mode = FALSE;
2095   }
2096
2097   return TRUE;
2098 }
2099
2100 static void
2101 gst_qtdemux_reset (GstQTDemux * qtdemux, gboolean hard)
2102 {
2103   gint i;
2104
2105   GST_DEBUG_OBJECT (qtdemux, "Resetting demux");
2106   gst_pad_stop_task (qtdemux->sinkpad);
2107
2108   if (hard || qtdemux->upstream_format_is_time) {
2109     qtdemux->state = QTDEMUX_STATE_INITIAL;
2110     qtdemux->neededbytes = 16;
2111     qtdemux->todrop = 0;
2112     qtdemux->pullbased = FALSE;
2113     qtdemux->posted_redirect = FALSE;
2114     qtdemux->first_mdat = -1;
2115     qtdemux->header_size = 0;
2116     qtdemux->mdatoffset = -1;
2117     qtdemux->restoredata_offset = -1;
2118     if (qtdemux->mdatbuffer)
2119       gst_buffer_unref (qtdemux->mdatbuffer);
2120     if (qtdemux->restoredata_buffer)
2121       gst_buffer_unref (qtdemux->restoredata_buffer);
2122     qtdemux->mdatbuffer = NULL;
2123     qtdemux->restoredata_buffer = NULL;
2124     qtdemux->mdatleft = 0;
2125     qtdemux->mdatsize = 0;
2126     if (qtdemux->comp_brands)
2127       gst_buffer_unref (qtdemux->comp_brands);
2128     qtdemux->comp_brands = NULL;
2129     qtdemux->last_moov_offset = -1;
2130     if (qtdemux->moov_node_compressed) {
2131       g_node_destroy (qtdemux->moov_node_compressed);
2132       if (qtdemux->moov_node)
2133         g_free (qtdemux->moov_node->data);
2134     }
2135     qtdemux->moov_node_compressed = NULL;
2136     if (qtdemux->moov_node)
2137       g_node_destroy (qtdemux->moov_node);
2138     qtdemux->moov_node = NULL;
2139     if (qtdemux->tag_list)
2140       gst_mini_object_unref (GST_MINI_OBJECT_CAST (qtdemux->tag_list));
2141     qtdemux->tag_list = gst_tag_list_new_empty ();
2142     gst_tag_list_set_scope (qtdemux->tag_list, GST_TAG_SCOPE_GLOBAL);
2143 #if 0
2144     if (qtdemux->element_index)
2145       gst_object_unref (qtdemux->element_index);
2146     qtdemux->element_index = NULL;
2147 #endif
2148     qtdemux->major_brand = 0;
2149     qtdemux->upstream_format_is_time = FALSE;
2150     qtdemux->upstream_seekable = FALSE;
2151     qtdemux->upstream_size = 0;
2152
2153     qtdemux->fragment_start = -1;
2154     qtdemux->fragment_start_offset = -1;
2155     qtdemux->duration = 0;
2156     qtdemux->moof_offset = 0;
2157     qtdemux->chapters_track_id = 0;
2158     qtdemux->have_group_id = FALSE;
2159     qtdemux->group_id = G_MAXUINT;
2160
2161     g_queue_foreach (&qtdemux->protection_event_queue, (GFunc) gst_event_unref,
2162         NULL);
2163     g_queue_clear (&qtdemux->protection_event_queue);
2164
2165     qtdemux->received_seek = FALSE;
2166     qtdemux->first_moof_already_parsed = FALSE;
2167   }
2168   qtdemux->offset = 0;
2169   gst_adapter_clear (qtdemux->adapter);
2170   gst_segment_init (&qtdemux->segment, GST_FORMAT_TIME);
2171   qtdemux->need_segment = TRUE;
2172
2173   if (hard) {
2174     qtdemux->segment_seqnum = GST_SEQNUM_INVALID;
2175     g_ptr_array_remove_range (qtdemux->active_streams,
2176         0, qtdemux->active_streams->len);
2177     g_ptr_array_remove_range (qtdemux->old_streams,
2178         0, qtdemux->old_streams->len);
2179     qtdemux->n_video_streams = 0;
2180     qtdemux->n_audio_streams = 0;
2181     qtdemux->n_sub_streams = 0;
2182     qtdemux->exposed = FALSE;
2183     qtdemux->fragmented = FALSE;
2184     qtdemux->mss_mode = FALSE;
2185     gst_caps_replace (&qtdemux->media_caps, NULL);
2186     qtdemux->timescale = 0;
2187     qtdemux->got_moov = FALSE;
2188     qtdemux->cenc_aux_info_offset = 0;
2189     qtdemux->cenc_aux_info_sizes = NULL;
2190     qtdemux->cenc_aux_sample_count = 0;
2191     if (qtdemux->protection_system_ids) {
2192       g_ptr_array_free (qtdemux->protection_system_ids, TRUE);
2193       qtdemux->protection_system_ids = NULL;
2194     }
2195     qtdemux->streams_aware = GST_OBJECT_PARENT (qtdemux)
2196         && GST_OBJECT_FLAG_IS_SET (GST_OBJECT_PARENT (qtdemux),
2197         GST_BIN_FLAG_STREAMS_AWARE);
2198
2199     if (qtdemux->preferred_protection_system_id) {
2200       g_free (qtdemux->preferred_protection_system_id);
2201       qtdemux->preferred_protection_system_id = NULL;
2202     }
2203   } else if (qtdemux->mss_mode) {
2204     gst_flow_combiner_reset (qtdemux->flowcombiner);
2205     g_ptr_array_foreach (qtdemux->active_streams,
2206         (GFunc) gst_qtdemux_stream_clear, NULL);
2207   } else {
2208     gst_flow_combiner_reset (qtdemux->flowcombiner);
2209     for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
2210       QtDemuxStream *stream = QTDEMUX_NTH_STREAM (qtdemux, i);
2211       stream->sent_eos = FALSE;
2212       stream->time_position = 0;
2213       stream->accumulated_base = 0;
2214     }
2215   }
2216 }
2217
2218
2219 /* Maps the @segment to the qt edts internal segments and pushes
2220  * the correspnding segment event.
2221  *
2222  * If it ends up being at a empty segment, a gap will be pushed and the next
2223  * edts segment will be activated in sequence.
2224  *
2225  * To be used in push-mode only */
2226 static void
2227 gst_qtdemux_map_and_push_segments (GstQTDemux * qtdemux, GstSegment * segment)
2228 {
2229   gint i, iter;
2230
2231   for (iter = 0; iter < QTDEMUX_N_STREAMS (qtdemux); iter++) {
2232     QtDemuxStream *stream = QTDEMUX_NTH_STREAM (qtdemux, iter);
2233
2234     stream->time_position = segment->start;
2235
2236     /* in push mode we should be guaranteed that we will have empty segments
2237      * at the beginning and then one segment after, other scenarios are not
2238      * supported and are discarded when parsing the edts */
2239     for (i = 0; i < stream->n_segments; i++) {
2240       if (stream->segments[i].stop_time > segment->start) {
2241         /* push the empty segment and move to the next one */
2242         gst_qtdemux_activate_segment (qtdemux, stream, i,
2243             stream->time_position);
2244         if (QTSEGMENT_IS_EMPTY (&stream->segments[i])) {
2245           gst_qtdemux_send_gap_for_segment (qtdemux, stream, i,
2246               stream->time_position);
2247
2248           /* accumulate previous segments */
2249           if (GST_CLOCK_TIME_IS_VALID (stream->segment.stop))
2250             stream->accumulated_base +=
2251                 (stream->segment.stop -
2252                 stream->segment.start) / ABS (stream->segment.rate);
2253           continue;
2254         }
2255
2256         g_assert (i == stream->n_segments - 1);
2257       }
2258     }
2259   }
2260 }
2261
2262 static void
2263 gst_qtdemux_stream_concat (GstQTDemux * qtdemux, GPtrArray * dest,
2264     GPtrArray * src)
2265 {
2266   guint i;
2267   guint len;
2268
2269   len = src->len;
2270
2271   if (len == 0)
2272     return;
2273
2274   for (i = 0; i < len; i++) {
2275     QtDemuxStream *stream = g_ptr_array_index (src, i);
2276
2277 #ifndef GST_DISABLE_GST_DEBUG
2278     GST_DEBUG_OBJECT (qtdemux, "Move stream %p (stream-id %s) to %p",
2279         stream, GST_STR_NULL (stream->stream_id), dest);
2280 #endif
2281     g_ptr_array_add (dest, gst_qtdemux_stream_ref (stream));
2282   }
2283
2284   g_ptr_array_remove_range (src, 0, len);
2285 }
2286
2287 static gboolean
2288 gst_qtdemux_handle_sink_event (GstPad * sinkpad, GstObject * parent,
2289     GstEvent * event)
2290 {
2291   GstQTDemux *demux = GST_QTDEMUX (parent);
2292   gboolean res = TRUE;
2293
2294   GST_LOG_OBJECT (demux, "handling %s event", GST_EVENT_TYPE_NAME (event));
2295
2296   switch (GST_EVENT_TYPE (event)) {
2297     case GST_EVENT_SEGMENT:
2298     {
2299       gint64 offset = 0;
2300       QtDemuxStream *stream;
2301       gint idx;
2302       GstSegment segment;
2303
2304       /* some debug output */
2305       gst_event_copy_segment (event, &segment);
2306       GST_DEBUG_OBJECT (demux, "received newsegment %" GST_SEGMENT_FORMAT,
2307           &segment);
2308
2309       if (segment.format == GST_FORMAT_TIME) {
2310         demux->upstream_format_is_time = TRUE;
2311         demux->segment_seqnum = gst_event_get_seqnum (event);
2312       } else {
2313         GST_DEBUG_OBJECT (demux, "Not storing upstream newsegment, "
2314             "not in time format");
2315
2316         /* chain will send initial newsegment after pads have been added */
2317         if (demux->state != QTDEMUX_STATE_MOVIE || !QTDEMUX_N_STREAMS (demux)) {
2318           GST_DEBUG_OBJECT (demux, "still starting, eating event");
2319           goto exit;
2320         }
2321       }
2322
2323       /* check if this matches a time seek we received previously
2324        * FIXME for backwards compatibility reasons we use the
2325        * seek_offset here to compare. In the future we might want to
2326        * change this to use the seqnum as it uniquely should identify
2327        * the segment that corresponds to the seek. */
2328       GST_DEBUG_OBJECT (demux, "Stored seek offset: %" G_GINT64_FORMAT
2329           ", received segment offset %" G_GINT64_FORMAT,
2330           demux->seek_offset, segment.start);
2331       if (segment.format == GST_FORMAT_BYTES
2332           && demux->seek_offset == segment.start) {
2333         GST_OBJECT_LOCK (demux);
2334         offset = segment.start;
2335
2336         segment.format = GST_FORMAT_TIME;
2337         segment.start = demux->push_seek_start;
2338         segment.stop = demux->push_seek_stop;
2339         GST_DEBUG_OBJECT (demux, "Replaced segment with stored seek "
2340             "segment %" GST_TIME_FORMAT " - %" GST_TIME_FORMAT,
2341             GST_TIME_ARGS (segment.start), GST_TIME_ARGS (segment.stop));
2342         GST_OBJECT_UNLOCK (demux);
2343       }
2344
2345       /* we only expect a BYTE segment, e.g. following a seek */
2346       if (segment.format == GST_FORMAT_BYTES) {
2347         if (GST_CLOCK_TIME_IS_VALID (segment.start)) {
2348           offset = segment.start;
2349
2350           gst_qtdemux_find_sample (demux, segment.start, TRUE, FALSE, NULL,
2351               NULL, (gint64 *) & segment.start);
2352           if ((gint64) segment.start < 0)
2353             segment.start = 0;
2354         }
2355         if (GST_CLOCK_TIME_IS_VALID (segment.stop)) {
2356           gst_qtdemux_find_sample (demux, segment.stop, FALSE, FALSE, NULL,
2357               NULL, (gint64 *) & segment.stop);
2358           /* keyframe seeking should already arrange for start >= stop,
2359            * but make sure in other rare cases */
2360           segment.stop = MAX (segment.stop, segment.start);
2361         }
2362       } else if (segment.format == GST_FORMAT_TIME) {
2363         /* push all data on the adapter before starting this
2364          * new segment */
2365         gst_qtdemux_process_adapter (demux, TRUE);
2366       } else {
2367         GST_DEBUG_OBJECT (demux, "unsupported segment format, ignoring");
2368         goto exit;
2369       }
2370
2371       /* We shouldn't modify upstream driven TIME FORMAT segment */
2372       if (!demux->upstream_format_is_time) {
2373         /* accept upstream's notion of segment and distribute along */
2374         segment.format = GST_FORMAT_TIME;
2375         segment.position = segment.time = segment.start;
2376         segment.duration = demux->segment.duration;
2377         segment.base = gst_segment_to_running_time (&demux->segment,
2378             GST_FORMAT_TIME, demux->segment.position);
2379       }
2380
2381       gst_segment_copy_into (&segment, &demux->segment);
2382       GST_DEBUG_OBJECT (demux, "Pushing newseg %" GST_SEGMENT_FORMAT, &segment);
2383
2384       /* map segment to internal qt segments and push on each stream */
2385       if (QTDEMUX_N_STREAMS (demux)) {
2386         demux->need_segment = TRUE;
2387         gst_qtdemux_check_send_pending_segment (demux);
2388       }
2389
2390       /* clear leftover in current segment, if any */
2391       gst_adapter_clear (demux->adapter);
2392
2393       /* set up streaming thread */
2394       demux->offset = offset;
2395       if (demux->upstream_format_is_time) {
2396         GST_DEBUG_OBJECT (demux, "Upstream is driving in time format, "
2397             "set values to restart reading from a new atom");
2398         demux->neededbytes = 16;
2399         demux->todrop = 0;
2400       } else {
2401         gst_qtdemux_find_sample (demux, offset, TRUE, TRUE, &stream, &idx,
2402             NULL);
2403         if (stream) {
2404           demux->todrop = stream->samples[idx].offset - offset;
2405           demux->neededbytes = demux->todrop + stream->samples[idx].size;
2406         } else {
2407           /* set up for EOS */
2408           demux->neededbytes = -1;
2409           demux->todrop = 0;
2410         }
2411       }
2412     exit:
2413       gst_event_unref (event);
2414       res = TRUE;
2415       goto drop;
2416     }
2417     case GST_EVENT_FLUSH_START:
2418     {
2419       if (gst_event_get_seqnum (event) == demux->offset_seek_seqnum) {
2420         gst_event_unref (event);
2421         goto drop;
2422       }
2423       QTDEMUX_EXPOSE_LOCK (demux);
2424       res = gst_pad_event_default (demux->sinkpad, parent, event);
2425       QTDEMUX_EXPOSE_UNLOCK (demux);
2426       goto drop;
2427     }
2428     case GST_EVENT_FLUSH_STOP:
2429     {
2430       guint64 dur;
2431
2432       dur = demux->segment.duration;
2433       gst_qtdemux_reset (demux, FALSE);
2434       demux->segment.duration = dur;
2435
2436       if (gst_event_get_seqnum (event) == demux->offset_seek_seqnum) {
2437         gst_event_unref (event);
2438         goto drop;
2439       }
2440       break;
2441     }
2442     case GST_EVENT_EOS:
2443       /* If we are in push mode, and get an EOS before we've seen any streams,
2444        * then error out - we have nowhere to send the EOS */
2445       if (!demux->pullbased) {
2446         gint i;
2447         gboolean has_valid_stream = FALSE;
2448         for (i = 0; i < QTDEMUX_N_STREAMS (demux); i++) {
2449           if (QTDEMUX_NTH_STREAM (demux, i)->pad != NULL) {
2450             has_valid_stream = TRUE;
2451             break;
2452           }
2453         }
2454         if (!has_valid_stream)
2455           gst_qtdemux_post_no_playable_stream_error (demux);
2456         else {
2457           GST_DEBUG_OBJECT (demux, "Data still available after EOS: %u",
2458               (guint) gst_adapter_available (demux->adapter));
2459           if (gst_qtdemux_process_adapter (demux, TRUE) != GST_FLOW_OK) {
2460             res = FALSE;
2461           }
2462         }
2463       }
2464       break;
2465     case GST_EVENT_CAPS:{
2466       GstCaps *caps = NULL;
2467
2468       gst_event_parse_caps (event, &caps);
2469       gst_qtdemux_setcaps (demux, caps);
2470       res = TRUE;
2471       gst_event_unref (event);
2472       goto drop;
2473     }
2474     case GST_EVENT_PROTECTION:
2475     {
2476       const gchar *system_id = NULL;
2477
2478       gst_event_parse_protection (event, &system_id, NULL, NULL);
2479       GST_DEBUG_OBJECT (demux, "Received protection event for system ID %s",
2480           system_id);
2481       gst_qtdemux_append_protection_system_id (demux, system_id);
2482       /* save the event for later, for source pads that have not been created */
2483       g_queue_push_tail (&demux->protection_event_queue, gst_event_ref (event));
2484       /* send it to all pads that already exist */
2485       gst_qtdemux_push_event (demux, event);
2486       res = TRUE;
2487       goto drop;
2488     }
2489     case GST_EVENT_STREAM_START:
2490     {
2491       res = TRUE;
2492       gst_event_unref (event);
2493
2494       /* Drain all the buffers */
2495       gst_qtdemux_process_adapter (demux, TRUE);
2496       gst_qtdemux_reset (demux, FALSE);
2497       /* We expect new moov box after new stream-start event */
2498       if (demux->exposed) {
2499         gst_qtdemux_stream_concat (demux,
2500             demux->old_streams, demux->active_streams);
2501       }
2502
2503       goto drop;
2504     }
2505     default:
2506       break;
2507   }
2508
2509   res = gst_pad_event_default (demux->sinkpad, parent, event) & res;
2510
2511 drop:
2512   return res;
2513 }
2514
2515 static gboolean
2516 gst_qtdemux_handle_sink_query (GstPad * pad, GstObject * parent,
2517     GstQuery * query)
2518 {
2519   GstQTDemux *demux = GST_QTDEMUX (parent);
2520   gboolean res = FALSE;
2521
2522   switch (GST_QUERY_TYPE (query)) {
2523     case GST_QUERY_BITRATE:
2524     {
2525       GstClockTime duration;
2526
2527       /* populate demux->upstream_size if not done yet */
2528       gst_qtdemux_check_seekability (demux);
2529
2530       if (demux->upstream_size != -1
2531           && gst_qtdemux_get_duration (demux, &duration)) {
2532         guint bitrate =
2533             gst_util_uint64_scale (8 * demux->upstream_size, GST_SECOND,
2534             duration);
2535
2536         GST_LOG_OBJECT (demux, "bitrate query byte length: %" G_GUINT64_FORMAT
2537             " duration %" GST_TIME_FORMAT " resulting a bitrate of %u",
2538             demux->upstream_size, GST_TIME_ARGS (duration), bitrate);
2539
2540         /* TODO: better results based on ranges/index tables */
2541         gst_query_set_bitrate (query, bitrate);
2542         res = TRUE;
2543       }
2544       break;
2545     }
2546     default:
2547       res = gst_pad_query_default (pad, (GstObject *) demux, query);
2548       break;
2549   }
2550
2551   return res;
2552 }
2553
2554
2555 #if 0
2556 static void
2557 gst_qtdemux_set_index (GstElement * element, GstIndex * index)
2558 {
2559   GstQTDemux *demux = GST_QTDEMUX (element);
2560
2561   GST_OBJECT_LOCK (demux);
2562   if (demux->element_index)
2563     gst_object_unref (demux->element_index);
2564   if (index) {
2565     demux->element_index = gst_object_ref (index);
2566   } else {
2567     demux->element_index = NULL;
2568   }
2569   GST_OBJECT_UNLOCK (demux);
2570   /* object lock might be taken again */
2571   if (index)
2572     gst_index_get_writer_id (index, GST_OBJECT (element), &demux->index_id);
2573   GST_DEBUG_OBJECT (demux, "Set index %" GST_PTR_FORMAT "for writer id %d",
2574       demux->element_index, demux->index_id);
2575 }
2576
2577 static GstIndex *
2578 gst_qtdemux_get_index (GstElement * element)
2579 {
2580   GstIndex *result = NULL;
2581   GstQTDemux *demux = GST_QTDEMUX (element);
2582
2583   GST_OBJECT_LOCK (demux);
2584   if (demux->element_index)
2585     result = gst_object_ref (demux->element_index);
2586   GST_OBJECT_UNLOCK (demux);
2587
2588   GST_DEBUG_OBJECT (demux, "Returning index %" GST_PTR_FORMAT, result);
2589
2590   return result;
2591 }
2592 #endif
2593
2594 static void
2595 gst_qtdemux_stbl_free (QtDemuxStream * stream)
2596 {
2597   g_free ((gpointer) stream->stco.data);
2598   stream->stco.data = NULL;
2599   g_free ((gpointer) stream->stsz.data);
2600   stream->stsz.data = NULL;
2601   g_free ((gpointer) stream->stsc.data);
2602   stream->stsc.data = NULL;
2603   g_free ((gpointer) stream->stts.data);
2604   stream->stts.data = NULL;
2605   g_free ((gpointer) stream->stss.data);
2606   stream->stss.data = NULL;
2607   g_free ((gpointer) stream->stps.data);
2608   stream->stps.data = NULL;
2609   g_free ((gpointer) stream->ctts.data);
2610   stream->ctts.data = NULL;
2611 }
2612
2613 static void
2614 gst_qtdemux_stream_flush_segments_data (QtDemuxStream * stream)
2615 {
2616   g_free (stream->segments);
2617   stream->segments = NULL;
2618   stream->segment_index = -1;
2619   stream->accumulated_base = 0;
2620 }
2621
2622 static void
2623 gst_qtdemux_stream_flush_samples_data (QtDemuxStream * stream)
2624 {
2625   g_free (stream->samples);
2626   stream->samples = NULL;
2627   gst_qtdemux_stbl_free (stream);
2628
2629   /* fragments */
2630   g_free (stream->ra_entries);
2631   stream->ra_entries = NULL;
2632   stream->n_ra_entries = 0;
2633
2634   stream->sample_index = -1;
2635   stream->stbl_index = -1;
2636   stream->n_samples = 0;
2637   stream->time_position = 0;
2638
2639   stream->n_samples_moof = 0;
2640   stream->duration_moof = 0;
2641   stream->duration_last_moof = 0;
2642 }
2643
2644 static void
2645 gst_qtdemux_stream_clear (QtDemuxStream * stream)
2646 {
2647   gint i;
2648   if (stream->allocator)
2649     gst_object_unref (stream->allocator);
2650   while (stream->buffers) {
2651     gst_buffer_unref (GST_BUFFER_CAST (stream->buffers->data));
2652     stream->buffers = g_slist_delete_link (stream->buffers, stream->buffers);
2653   }
2654   for (i = 0; i < stream->stsd_entries_length; i++) {
2655     QtDemuxStreamStsdEntry *entry = &stream->stsd_entries[i];
2656     if (entry->rgb8_palette) {
2657       gst_memory_unref (entry->rgb8_palette);
2658       entry->rgb8_palette = NULL;
2659     }
2660     entry->sparse = FALSE;
2661   }
2662
2663   if (stream->stream_tags)
2664     gst_tag_list_unref (stream->stream_tags);
2665
2666   stream->stream_tags = gst_tag_list_new_empty ();
2667   gst_tag_list_set_scope (stream->stream_tags, GST_TAG_SCOPE_STREAM);
2668   g_free (stream->redirect_uri);
2669   stream->redirect_uri = NULL;
2670   stream->sent_eos = FALSE;
2671   stream->protected = FALSE;
2672   if (stream->protection_scheme_info) {
2673     if (stream->protection_scheme_type == FOURCC_cenc) {
2674       QtDemuxCencSampleSetInfo *info =
2675           (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
2676       if (info->default_properties)
2677         gst_structure_free (info->default_properties);
2678       if (info->crypto_info)
2679         g_ptr_array_free (info->crypto_info, TRUE);
2680     }
2681     g_free (stream->protection_scheme_info);
2682     stream->protection_scheme_info = NULL;
2683   }
2684   stream->protection_scheme_type = 0;
2685   stream->protection_scheme_version = 0;
2686   g_queue_foreach (&stream->protection_scheme_event_queue,
2687       (GFunc) gst_event_unref, NULL);
2688   g_queue_clear (&stream->protection_scheme_event_queue);
2689   gst_qtdemux_stream_flush_segments_data (stream);
2690   gst_qtdemux_stream_flush_samples_data (stream);
2691 }
2692
2693 static void
2694 gst_qtdemux_stream_reset (QtDemuxStream * stream)
2695 {
2696   gint i;
2697   gst_qtdemux_stream_clear (stream);
2698   for (i = 0; i < stream->stsd_entries_length; i++) {
2699     QtDemuxStreamStsdEntry *entry = &stream->stsd_entries[i];
2700     if (entry->caps) {
2701       gst_caps_unref (entry->caps);
2702       entry->caps = NULL;
2703     }
2704   }
2705   g_free (stream->stsd_entries);
2706   stream->stsd_entries = NULL;
2707   stream->stsd_entries_length = 0;
2708 }
2709
2710 static QtDemuxStream *
2711 gst_qtdemux_stream_ref (QtDemuxStream * stream)
2712 {
2713   g_atomic_int_add (&stream->ref_count, 1);
2714
2715   return stream;
2716 }
2717
2718 static void
2719 gst_qtdemux_stream_unref (QtDemuxStream * stream)
2720 {
2721   if (g_atomic_int_dec_and_test (&stream->ref_count)) {
2722     gst_qtdemux_stream_reset (stream);
2723     gst_tag_list_unref (stream->stream_tags);
2724     if (stream->pad) {
2725       GstQTDemux *demux = stream->demux;
2726       gst_element_remove_pad (GST_ELEMENT_CAST (demux), stream->pad);
2727       gst_flow_combiner_remove_pad (demux->flowcombiner, stream->pad);
2728     }
2729     g_free (stream->stream_id);
2730     g_free (stream);
2731   }
2732 }
2733
2734 static GstStateChangeReturn
2735 gst_qtdemux_change_state (GstElement * element, GstStateChange transition)
2736 {
2737   GstQTDemux *qtdemux = GST_QTDEMUX (element);
2738   GstStateChangeReturn result = GST_STATE_CHANGE_FAILURE;
2739
2740   switch (transition) {
2741     case GST_STATE_CHANGE_READY_TO_PAUSED:
2742       gst_qtdemux_reset (qtdemux, TRUE);
2743       break;
2744     default:
2745       break;
2746   }
2747
2748   result = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
2749
2750   switch (transition) {
2751     case GST_STATE_CHANGE_PAUSED_TO_READY:{
2752       gst_qtdemux_reset (qtdemux, TRUE);
2753       break;
2754     }
2755     default:
2756       break;
2757   }
2758
2759   return result;
2760 }
2761
2762 static void
2763 gst_qtdemux_set_context (GstElement * element, GstContext * context)
2764 {
2765   GstQTDemux *qtdemux = GST_QTDEMUX (element);
2766
2767   g_return_if_fail (GST_IS_CONTEXT (context));
2768
2769   if (gst_context_has_context_type (context,
2770           "drm-preferred-decryption-system-id")) {
2771     const GstStructure *s;
2772
2773     s = gst_context_get_structure (context);
2774     g_free (qtdemux->preferred_protection_system_id);
2775     qtdemux->preferred_protection_system_id =
2776         g_strdup (gst_structure_get_string (s, "decryption-system-id"));
2777     GST_DEBUG_OBJECT (element, "set preferred decryption system to %s",
2778         qtdemux->preferred_protection_system_id);
2779   }
2780
2781   GST_ELEMENT_CLASS (parent_class)->set_context (element, context);
2782 }
2783
2784 static void
2785 qtdemux_parse_ftyp (GstQTDemux * qtdemux, const guint8 * buffer, gint length)
2786 {
2787   /* counts as header data */
2788   qtdemux->header_size += length;
2789
2790   /* only consider at least a sufficiently complete ftyp atom */
2791   if (length >= 20) {
2792     GstBuffer *buf;
2793
2794     qtdemux->major_brand = QT_FOURCC (buffer + 8);
2795     GST_DEBUG_OBJECT (qtdemux, "major brand: %" GST_FOURCC_FORMAT,
2796         GST_FOURCC_ARGS (qtdemux->major_brand));
2797     if (qtdemux->comp_brands)
2798       gst_buffer_unref (qtdemux->comp_brands);
2799     buf = qtdemux->comp_brands = gst_buffer_new_and_alloc (length - 16);
2800     gst_buffer_fill (buf, 0, buffer + 16, length - 16);
2801   }
2802 }
2803
2804 static void
2805 qtdemux_handle_xmp_taglist (GstQTDemux * qtdemux, GstTagList * taglist,
2806     GstTagList * xmptaglist)
2807 {
2808   /* Strip out bogus fields */
2809   if (xmptaglist) {
2810     if (gst_tag_list_get_scope (taglist) == GST_TAG_SCOPE_GLOBAL) {
2811       gst_tag_list_remove_tag (xmptaglist, GST_TAG_VIDEO_CODEC);
2812       gst_tag_list_remove_tag (xmptaglist, GST_TAG_AUDIO_CODEC);
2813     } else {
2814       gst_tag_list_remove_tag (xmptaglist, GST_TAG_CONTAINER_FORMAT);
2815     }
2816
2817     GST_DEBUG_OBJECT (qtdemux, "Found XMP tags %" GST_PTR_FORMAT, xmptaglist);
2818
2819     /* prioritize native tags using _KEEP mode */
2820     gst_tag_list_insert (taglist, xmptaglist, GST_TAG_MERGE_KEEP);
2821     gst_tag_list_unref (xmptaglist);
2822   }
2823 }
2824
2825 static void
2826 qtdemux_update_default_sample_encryption_settings (GstQTDemux * qtdemux,
2827     QtDemuxCencSampleSetInfo * info, guint32 is_encrypted, guint8 iv_size,
2828     const guint8 * kid)
2829 {
2830   GstBuffer *kid_buf = gst_buffer_new_allocate (NULL, 16, NULL);
2831   gst_buffer_fill (kid_buf, 0, kid, 16);
2832   if (info->default_properties)
2833     gst_structure_free (info->default_properties);
2834   info->default_properties =
2835       gst_structure_new ("application/x-cenc",
2836       "iv_size", G_TYPE_UINT, iv_size,
2837       "encrypted", G_TYPE_BOOLEAN, (is_encrypted == 1),
2838       "kid", GST_TYPE_BUFFER, kid_buf, NULL);
2839   GST_DEBUG_OBJECT (qtdemux, "default sample properties: "
2840       "is_encrypted=%u, iv_size=%u", is_encrypted, iv_size);
2841   gst_buffer_unref (kid_buf);
2842 }
2843
2844 static gboolean
2845 qtdemux_update_default_piff_encryption_settings (GstQTDemux * qtdemux,
2846     QtDemuxCencSampleSetInfo * info, GstByteReader * br)
2847 {
2848   guint32 algorithm_id = 0;
2849   const guint8 *kid;
2850   gboolean is_encrypted = TRUE;
2851   guint8 iv_size = 8;
2852
2853   if (!gst_byte_reader_get_uint24_le (br, &algorithm_id)) {
2854     GST_ERROR_OBJECT (qtdemux, "Error getting box's algorithm ID field");
2855     return FALSE;
2856   }
2857
2858   algorithm_id >>= 8;
2859   if (algorithm_id == 0) {
2860     is_encrypted = FALSE;
2861   } else if (algorithm_id == 1) {
2862     GST_DEBUG_OBJECT (qtdemux, "AES 128-bits CTR encrypted stream");
2863   } else if (algorithm_id == 2) {
2864     GST_DEBUG_OBJECT (qtdemux, "AES 128-bits CBC encrypted stream");
2865   }
2866
2867   if (!gst_byte_reader_get_uint8 (br, &iv_size))
2868     return FALSE;
2869
2870   if (!gst_byte_reader_get_data (br, 16, &kid))
2871     return FALSE;
2872
2873   qtdemux_update_default_sample_encryption_settings (qtdemux, info,
2874       is_encrypted, iv_size, kid);
2875   gst_structure_set (info->default_properties, "piff_algorithm_id",
2876       G_TYPE_UINT, algorithm_id, NULL);
2877   return TRUE;
2878 }
2879
2880
2881 static void
2882 qtdemux_parse_piff (GstQTDemux * qtdemux, const guint8 * buffer, gint length,
2883     guint offset)
2884 {
2885   GstByteReader br;
2886   guint8 version;
2887   guint32 flags = 0;
2888   guint i;
2889   guint iv_size = 8;
2890   QtDemuxStream *stream;
2891   GstStructure *structure;
2892   QtDemuxCencSampleSetInfo *ss_info = NULL;
2893   const gchar *system_id;
2894   gboolean uses_sub_sample_encryption = FALSE;
2895   guint32 sample_count;
2896
2897   if (QTDEMUX_N_STREAMS (qtdemux) == 0)
2898     return;
2899
2900   stream = QTDEMUX_NTH_STREAM (qtdemux, 0);
2901
2902   structure = gst_caps_get_structure (CUR_STREAM (stream)->caps, 0);
2903   if (!gst_structure_has_name (structure, "application/x-cenc")) {
2904     GST_WARNING_OBJECT (qtdemux,
2905         "Attempting PIFF box parsing on an unencrypted stream.");
2906     return;
2907   }
2908
2909   gst_structure_get (structure, GST_PROTECTION_SYSTEM_ID_CAPS_FIELD,
2910       G_TYPE_STRING, &system_id, NULL);
2911   gst_qtdemux_append_protection_system_id (qtdemux, system_id);
2912
2913   stream->protected = TRUE;
2914   stream->protection_scheme_type = FOURCC_cenc;
2915
2916   if (!stream->protection_scheme_info)
2917     stream->protection_scheme_info = g_new0 (QtDemuxCencSampleSetInfo, 1);
2918
2919   ss_info = (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
2920   if (!ss_info->default_properties) {
2921     ss_info->default_properties =
2922         gst_structure_new ("application/x-cenc",
2923         "iv_size", G_TYPE_UINT, iv_size, "encrypted", G_TYPE_BOOLEAN, TRUE,
2924         NULL);
2925
2926   }
2927
2928   if (ss_info->crypto_info) {
2929     GST_LOG_OBJECT (qtdemux, "unreffing existing crypto_info");
2930     g_ptr_array_free (ss_info->crypto_info, TRUE);
2931     ss_info->crypto_info = NULL;
2932   }
2933
2934   /* skip UUID */
2935   gst_byte_reader_init (&br, buffer + offset + 16, length - offset - 16);
2936
2937   if (!gst_byte_reader_get_uint8 (&br, &version)) {
2938     GST_ERROR_OBJECT (qtdemux, "Error getting box's version field");
2939     return;
2940   }
2941
2942   if (!gst_byte_reader_get_uint24_be (&br, &flags)) {
2943     GST_ERROR_OBJECT (qtdemux, "Error getting box's flags field");
2944     return;
2945   }
2946
2947   if ((flags & 0x000001)) {
2948     if (!qtdemux_update_default_piff_encryption_settings (qtdemux, ss_info,
2949             &br))
2950       return;
2951   } else if ((flags & 0x000002)) {
2952     uses_sub_sample_encryption = TRUE;
2953   }
2954
2955   if (!gst_structure_get_uint (ss_info->default_properties, "iv_size",
2956           &iv_size)) {
2957     GST_ERROR_OBJECT (qtdemux, "Error getting encryption IV size field");
2958     return;
2959   }
2960
2961   if (!gst_byte_reader_get_uint32_be (&br, &sample_count)) {
2962     GST_ERROR_OBJECT (qtdemux, "Error getting box's sample count field");
2963     return;
2964   }
2965
2966   ss_info->crypto_info =
2967       g_ptr_array_new_full (sample_count,
2968       (GDestroyNotify) qtdemux_gst_structure_free);
2969
2970   for (i = 0; i < sample_count; ++i) {
2971     GstStructure *properties;
2972     guint8 *data;
2973     GstBuffer *buf;
2974
2975     properties = qtdemux_get_cenc_sample_properties (qtdemux, stream, i);
2976     if (properties == NULL) {
2977       GST_ERROR_OBJECT (qtdemux, "failed to get properties for sample %u", i);
2978       qtdemux->cenc_aux_sample_count = i;
2979       return;
2980     }
2981
2982     if (!gst_byte_reader_dup_data (&br, iv_size, &data)) {
2983       GST_ERROR_OBJECT (qtdemux, "IV data not present for sample %u", i);
2984       gst_structure_free (properties);
2985       qtdemux->cenc_aux_sample_count = i;
2986       return;
2987     }
2988     buf = gst_buffer_new_wrapped (data, iv_size);
2989     gst_structure_set (properties, "iv", GST_TYPE_BUFFER, buf, NULL);
2990     gst_buffer_unref (buf);
2991
2992     if (uses_sub_sample_encryption) {
2993       guint16 n_subsamples;
2994       const GValue *kid_buf_value;
2995
2996       if (!gst_byte_reader_get_uint16_be (&br, &n_subsamples)
2997           || n_subsamples == 0) {
2998         GST_ERROR_OBJECT (qtdemux,
2999             "failed to get subsample count for sample %u", i);
3000         gst_structure_free (properties);
3001         qtdemux->cenc_aux_sample_count = i;
3002         return;
3003       }
3004       GST_LOG_OBJECT (qtdemux, "subsample count: %u", n_subsamples);
3005       if (!gst_byte_reader_dup_data (&br, n_subsamples * 6, &data)) {
3006         GST_ERROR_OBJECT (qtdemux, "failed to get subsample data for sample %u",
3007             i);
3008         gst_structure_free (properties);
3009         qtdemux->cenc_aux_sample_count = i;
3010         return;
3011       }
3012       buf = gst_buffer_new_wrapped (data, n_subsamples * 6);
3013
3014       kid_buf_value =
3015           gst_structure_get_value (ss_info->default_properties, "kid");
3016
3017       gst_structure_set (properties,
3018           "subsample_count", G_TYPE_UINT, n_subsamples,
3019           "subsamples", GST_TYPE_BUFFER, buf, NULL);
3020       gst_structure_set_value (properties, "kid", kid_buf_value);
3021       gst_buffer_unref (buf);
3022     } else {
3023       gst_structure_set (properties, "subsample_count", G_TYPE_UINT, 0, NULL);
3024     }
3025
3026     g_ptr_array_add (ss_info->crypto_info, properties);
3027   }
3028
3029   qtdemux->cenc_aux_sample_count = sample_count;
3030 }
3031
3032 static void
3033 qtdemux_parse_uuid (GstQTDemux * qtdemux, const guint8 * buffer, gint length)
3034 {
3035   static const guint8 xmp_uuid[] = { 0xBE, 0x7A, 0xCF, 0xCB,
3036     0x97, 0xA9, 0x42, 0xE8,
3037     0x9C, 0x71, 0x99, 0x94,
3038     0x91, 0xE3, 0xAF, 0xAC
3039   };
3040   static const guint8 playready_uuid[] = {
3041     0xd0, 0x8a, 0x4f, 0x18, 0x10, 0xf3, 0x4a, 0x82,
3042     0xb6, 0xc8, 0x32, 0xd8, 0xab, 0xa1, 0x83, 0xd3
3043   };
3044
3045   static const guint8 piff_sample_encryption_uuid[] = {
3046     0xa2, 0x39, 0x4f, 0x52, 0x5a, 0x9b, 0x4f, 0x14,
3047     0xa2, 0x44, 0x6c, 0x42, 0x7c, 0x64, 0x8d, 0xf4
3048   };
3049
3050   guint offset;
3051
3052   /* counts as header data */
3053   qtdemux->header_size += length;
3054
3055   offset = (QT_UINT32 (buffer) == 0) ? 16 : 8;
3056
3057   if (length <= offset + 16) {
3058     GST_DEBUG_OBJECT (qtdemux, "uuid atom is too short, skipping");
3059     return;
3060   }
3061
3062   if (memcmp (buffer + offset, xmp_uuid, 16) == 0) {
3063     GstBuffer *buf;
3064     GstTagList *taglist;
3065
3066     buf = _gst_buffer_new_wrapped ((guint8 *) buffer + offset + 16,
3067         length - offset - 16, NULL);
3068     taglist = gst_tag_list_from_xmp_buffer (buf);
3069     gst_buffer_unref (buf);
3070
3071     /* make sure we have a usable taglist */
3072     qtdemux->tag_list = gst_tag_list_make_writable (qtdemux->tag_list);
3073
3074     qtdemux_handle_xmp_taglist (qtdemux, qtdemux->tag_list, taglist);
3075
3076   } else if (memcmp (buffer + offset, playready_uuid, 16) == 0) {
3077     int len;
3078     const gunichar2 *s_utf16;
3079     char *contents;
3080
3081     len = GST_READ_UINT16_LE (buffer + offset + 0x30);
3082     s_utf16 = (const gunichar2 *) (buffer + offset + 0x32);
3083     contents = g_utf16_to_utf8 (s_utf16, len / 2, NULL, NULL, NULL);
3084     GST_ERROR_OBJECT (qtdemux, "contents: %s", contents);
3085
3086     g_free (contents);
3087
3088     GST_ELEMENT_ERROR (qtdemux, STREAM, DECRYPT,
3089         (_("Cannot play stream because it is encrypted with PlayReady DRM.")),
3090         (NULL));
3091   } else if (memcmp (buffer + offset, piff_sample_encryption_uuid, 16) == 0) {
3092     qtdemux_parse_piff (qtdemux, buffer, length, offset);
3093   } else {
3094     GST_DEBUG_OBJECT (qtdemux, "Ignoring unknown uuid: %08x-%08x-%08x-%08x",
3095         GST_READ_UINT32_LE (buffer + offset),
3096         GST_READ_UINT32_LE (buffer + offset + 4),
3097         GST_READ_UINT32_LE (buffer + offset + 8),
3098         GST_READ_UINT32_LE (buffer + offset + 12));
3099   }
3100 }
3101
3102 static void
3103 qtdemux_parse_sidx (GstQTDemux * qtdemux, const guint8 * buffer, gint length)
3104 {
3105   GstSidxParser sidx_parser;
3106   GstIsoffParserResult res;
3107   guint consumed;
3108
3109   gst_isoff_qt_sidx_parser_init (&sidx_parser);
3110
3111   res =
3112       gst_isoff_qt_sidx_parser_add_data (&sidx_parser, buffer, length,
3113       &consumed);
3114   GST_DEBUG_OBJECT (qtdemux, "sidx parse result: %d", res);
3115   if (res == GST_ISOFF_QT_PARSER_DONE) {
3116     check_update_duration (qtdemux, sidx_parser.cumulative_pts);
3117   }
3118   gst_isoff_qt_sidx_parser_clear (&sidx_parser);
3119 }
3120
3121 /* caller verifies at least 8 bytes in buf */
3122 static void
3123 extract_initial_length_and_fourcc (const guint8 * data, guint size,
3124     guint64 * plength, guint32 * pfourcc)
3125 {
3126   guint64 length;
3127   guint32 fourcc;
3128
3129   length = QT_UINT32 (data);
3130   GST_DEBUG ("length 0x%08" G_GINT64_MODIFIER "x", length);
3131   fourcc = QT_FOURCC (data + 4);
3132   GST_DEBUG ("atom type %" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (fourcc));
3133
3134   if (length == 0) {
3135     length = G_MAXUINT64;
3136   } else if (length == 1 && size >= 16) {
3137     /* this means we have an extended size, which is the 64 bit value of
3138      * the next 8 bytes */
3139     length = QT_UINT64 (data + 8);
3140     GST_DEBUG ("length 0x%08" G_GINT64_MODIFIER "x", length);
3141   }
3142
3143   if (plength)
3144     *plength = length;
3145   if (pfourcc)
3146     *pfourcc = fourcc;
3147 }
3148
3149 static gboolean
3150 qtdemux_parse_mehd (GstQTDemux * qtdemux, GstByteReader * br)
3151 {
3152   guint32 version = 0;
3153   GstClockTime duration = 0;
3154
3155   if (!gst_byte_reader_get_uint32_be (br, &version))
3156     goto failed;
3157
3158   version >>= 24;
3159   if (version == 1) {
3160     if (!gst_byte_reader_get_uint64_be (br, &duration))
3161       goto failed;
3162   } else {
3163     guint32 dur = 0;
3164
3165     if (!gst_byte_reader_get_uint32_be (br, &dur))
3166       goto failed;
3167     duration = dur;
3168   }
3169
3170   GST_INFO_OBJECT (qtdemux, "mehd duration: %" G_GUINT64_FORMAT, duration);
3171   qtdemux->duration = duration;
3172
3173   return TRUE;
3174
3175 failed:
3176   {
3177     GST_DEBUG_OBJECT (qtdemux, "parsing mehd failed");
3178     return FALSE;
3179   }
3180 }
3181
3182 static gboolean
3183 qtdemux_parse_trex (GstQTDemux * qtdemux, QtDemuxStream * stream,
3184     guint32 * ds_duration, guint32 * ds_size, guint32 * ds_flags)
3185 {
3186   if (!stream->parsed_trex && qtdemux->moov_node) {
3187     GNode *mvex, *trex;
3188     GstByteReader trex_data;
3189
3190     mvex = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_mvex);
3191     if (mvex) {
3192       trex = qtdemux_tree_get_child_by_type_full (mvex, FOURCC_trex,
3193           &trex_data);
3194       while (trex) {
3195         guint32 id = 0, sdi = 0, dur = 0, size = 0, flags = 0;
3196
3197         /* skip version/flags */
3198         if (!gst_byte_reader_skip (&trex_data, 4))
3199           goto next;
3200         if (!gst_byte_reader_get_uint32_be (&trex_data, &id))
3201           goto next;
3202         if (id != stream->track_id)
3203           goto next;
3204         if (!gst_byte_reader_get_uint32_be (&trex_data, &sdi))
3205           goto next;
3206         if (!gst_byte_reader_get_uint32_be (&trex_data, &dur))
3207           goto next;
3208         if (!gst_byte_reader_get_uint32_be (&trex_data, &size))
3209           goto next;
3210         if (!gst_byte_reader_get_uint32_be (&trex_data, &flags))
3211           goto next;
3212
3213         GST_DEBUG_OBJECT (qtdemux, "fragment defaults for stream %d; "
3214             "duration %d,  size %d, flags 0x%x", stream->track_id,
3215             dur, size, flags);
3216
3217         stream->parsed_trex = TRUE;
3218         stream->def_sample_description_index = sdi;
3219         stream->def_sample_duration = dur;
3220         stream->def_sample_size = size;
3221         stream->def_sample_flags = flags;
3222
3223       next:
3224         /* iterate all siblings */
3225         trex = qtdemux_tree_get_sibling_by_type_full (trex, FOURCC_trex,
3226             &trex_data);
3227       }
3228     }
3229   }
3230
3231   *ds_duration = stream->def_sample_duration;
3232   *ds_size = stream->def_sample_size;
3233   *ds_flags = stream->def_sample_flags;
3234
3235   /* even then, above values are better than random ... */
3236   if (G_UNLIKELY (!stream->parsed_trex)) {
3237     GST_WARNING_OBJECT (qtdemux,
3238         "failed to find fragment defaults for stream %d", stream->track_id);
3239     return FALSE;
3240   }
3241
3242   return TRUE;
3243 }
3244
3245 /* This method should be called whenever a more accurate duration might
3246  * have been found. It will update all relevant variables if/where needed
3247  */
3248 static void
3249 check_update_duration (GstQTDemux * qtdemux, GstClockTime duration)
3250 {
3251   guint i;
3252   guint64 movdur;
3253   GstClockTime prevdur;
3254
3255   movdur = GSTTIME_TO_QTTIME (qtdemux, duration);
3256
3257   if (movdur > qtdemux->duration) {
3258     prevdur = QTTIME_TO_GSTTIME (qtdemux, qtdemux->duration);
3259     GST_DEBUG_OBJECT (qtdemux,
3260         "Updating total duration to %" GST_TIME_FORMAT " was %" GST_TIME_FORMAT,
3261         GST_TIME_ARGS (duration), GST_TIME_ARGS (prevdur));
3262     qtdemux->duration = movdur;
3263     GST_DEBUG_OBJECT (qtdemux,
3264         "qtdemux->segment.duration: %" GST_TIME_FORMAT " .stop: %"
3265         GST_TIME_FORMAT, GST_TIME_ARGS (qtdemux->segment.duration),
3266         GST_TIME_ARGS (qtdemux->segment.stop));
3267     if (qtdemux->segment.duration == prevdur) {
3268       /* If the current segment has duration/stop identical to previous duration
3269        * update them also (because they were set at that point in time with
3270        * the wrong duration */
3271       /* We convert the value *from* the timescale version to avoid rounding errors */
3272       GstClockTime fixeddur = QTTIME_TO_GSTTIME (qtdemux, movdur);
3273       GST_DEBUG_OBJECT (qtdemux, "Updated segment.duration and segment.stop");
3274       qtdemux->segment.duration = fixeddur;
3275       qtdemux->segment.stop = fixeddur;
3276     }
3277   }
3278
3279   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
3280     QtDemuxStream *stream = QTDEMUX_NTH_STREAM (qtdemux, i);
3281
3282     movdur = GSTTIME_TO_QTSTREAMTIME (stream, duration);
3283     if (movdur > stream->duration) {
3284       GST_DEBUG_OBJECT (qtdemux,
3285           "Updating stream #%d duration to %" GST_TIME_FORMAT, i,
3286           GST_TIME_ARGS (duration));
3287       stream->duration = movdur;
3288       /* internal duration tracking state has been updated above, so */
3289       /* preserve an open-ended dummy segment rather than repeatedly updating
3290        * it and spamming downstream accordingly with segment events */
3291       if (stream->dummy_segment &&
3292           GST_CLOCK_TIME_IS_VALID (stream->segments[0].duration)) {
3293         /* Update all dummy values to new duration */
3294         stream->segments[0].stop_time = duration;
3295         stream->segments[0].duration = duration;
3296         stream->segments[0].media_stop = duration;
3297
3298         /* let downstream know we possibly have a new stop time */
3299         if (stream->segment_index != -1) {
3300           GstClockTime pos;
3301
3302           if (qtdemux->segment.rate >= 0) {
3303             pos = stream->segment.start;
3304           } else {
3305             pos = stream->segment.stop;
3306           }
3307
3308           gst_qtdemux_stream_update_segment (qtdemux, stream,
3309               stream->segment_index, pos, NULL, NULL);
3310         }
3311       }
3312     }
3313   }
3314 }
3315
3316 static gboolean
3317 qtdemux_parse_trun (GstQTDemux * qtdemux, GstByteReader * trun,
3318     QtDemuxStream * stream, guint32 d_sample_duration, guint32 d_sample_size,
3319     guint32 d_sample_flags, gint64 moof_offset, gint64 moof_length,
3320     gint64 * base_offset, gint64 * running_offset, gint64 decode_ts,
3321     gboolean has_tfdt)
3322 {
3323   GstClockTime gst_ts = GST_CLOCK_TIME_NONE;
3324   guint64 timestamp;
3325   gint32 data_offset = 0;
3326   guint32 flags = 0, first_flags = 0, samples_count = 0;
3327   gint i;
3328   guint8 *data;
3329   guint entry_size, dur_offset, size_offset, flags_offset = 0, ct_offset = 0;
3330   QtDemuxSample *sample;
3331   gboolean ismv = FALSE;
3332   gint64 initial_offset;
3333
3334   GST_LOG_OBJECT (qtdemux, "parsing trun track-id %d; "
3335       "default dur %d, size %d, flags 0x%x, base offset %" G_GINT64_FORMAT ", "
3336       "decode ts %" G_GINT64_FORMAT, stream->track_id, d_sample_duration,
3337       d_sample_size, d_sample_flags, *base_offset, decode_ts);
3338
3339   if (stream->pending_seek && moof_offset < stream->pending_seek->moof_offset) {
3340     GST_INFO_OBJECT (stream->pad, "skipping trun before seek target fragment");
3341     return TRUE;
3342   }
3343
3344   /* presence of stss or not can't really tell us much,
3345    * and flags and so on tend to be marginally reliable in these files */
3346   if (stream->subtype == FOURCC_soun) {
3347     GST_DEBUG_OBJECT (qtdemux,
3348         "sound track in fragmented file; marking all keyframes");
3349     stream->all_keyframe = TRUE;
3350   }
3351
3352   if (!gst_byte_reader_skip (trun, 1) ||
3353       !gst_byte_reader_get_uint24_be (trun, &flags))
3354     goto fail;
3355
3356   if (!gst_byte_reader_get_uint32_be (trun, &samples_count))
3357     goto fail;
3358
3359   if (flags & TR_DATA_OFFSET) {
3360     /* note this is really signed */
3361     if (!gst_byte_reader_get_int32_be (trun, &data_offset))
3362       goto fail;
3363     GST_LOG_OBJECT (qtdemux, "trun data offset %d", data_offset);
3364     /* default base offset = first byte of moof */
3365     if (*base_offset == -1) {
3366       GST_LOG_OBJECT (qtdemux, "base_offset at moof");
3367       *base_offset = moof_offset;
3368     }
3369     *running_offset = *base_offset + data_offset;
3370   } else {
3371     /* if no offset at all, that would mean data starts at moof start,
3372      * which is a bit wrong and is ismv crappy way, so compensate
3373      * assuming data is in mdat following moof */
3374     if (*base_offset == -1) {
3375       *base_offset = moof_offset + moof_length + 8;
3376       GST_LOG_OBJECT (qtdemux, "base_offset assumed in mdat after moof");
3377       ismv = TRUE;
3378     }
3379     if (*running_offset == -1)
3380       *running_offset = *base_offset;
3381   }
3382
3383   GST_LOG_OBJECT (qtdemux, "running offset now %" G_GINT64_FORMAT,
3384       *running_offset);
3385   GST_LOG_OBJECT (qtdemux, "trun offset %d, flags 0x%x, entries %d",
3386       data_offset, flags, samples_count);
3387
3388   if (flags & TR_FIRST_SAMPLE_FLAGS) {
3389     if (G_UNLIKELY (flags & TR_SAMPLE_FLAGS)) {
3390       GST_DEBUG_OBJECT (qtdemux,
3391           "invalid flags; SAMPLE and FIRST_SAMPLE present, discarding latter");
3392       flags ^= TR_FIRST_SAMPLE_FLAGS;
3393     } else {
3394       if (!gst_byte_reader_get_uint32_be (trun, &first_flags))
3395         goto fail;
3396       GST_LOG_OBJECT (qtdemux, "first flags: 0x%x", first_flags);
3397     }
3398   }
3399
3400   /* FIXME ? spec says other bits should also be checked to determine
3401    * entry size (and prefix size for that matter) */
3402   entry_size = 0;
3403   dur_offset = size_offset = 0;
3404   if (flags & TR_SAMPLE_DURATION) {
3405     GST_LOG_OBJECT (qtdemux, "entry duration present");
3406     dur_offset = entry_size;
3407     entry_size += 4;
3408   }
3409   if (flags & TR_SAMPLE_SIZE) {
3410     GST_LOG_OBJECT (qtdemux, "entry size present");
3411     size_offset = entry_size;
3412     entry_size += 4;
3413   }
3414   if (flags & TR_SAMPLE_FLAGS) {
3415     GST_LOG_OBJECT (qtdemux, "entry flags present");
3416     flags_offset = entry_size;
3417     entry_size += 4;
3418   }
3419   if (flags & TR_COMPOSITION_TIME_OFFSETS) {
3420     GST_LOG_OBJECT (qtdemux, "entry ct offset present");
3421     ct_offset = entry_size;
3422     entry_size += 4;
3423   }
3424
3425   if (!qt_atom_parser_has_chunks (trun, samples_count, entry_size))
3426     goto fail;
3427   data = (guint8 *) gst_byte_reader_peek_data_unchecked (trun);
3428
3429   if (stream->n_samples + samples_count >=
3430       QTDEMUX_MAX_SAMPLE_INDEX_SIZE / sizeof (QtDemuxSample))
3431     goto index_too_big;
3432
3433   GST_DEBUG_OBJECT (qtdemux, "allocating n_samples %u * %u (%.2f MB)",
3434       stream->n_samples + samples_count, (guint) sizeof (QtDemuxSample),
3435       (stream->n_samples + samples_count) *
3436       sizeof (QtDemuxSample) / (1024.0 * 1024.0));
3437
3438   /* create a new array of samples if it's the first sample parsed */
3439   if (stream->n_samples == 0) {
3440     g_assert (stream->samples == NULL);
3441     stream->samples = g_try_new0 (QtDemuxSample, samples_count);
3442     /* or try to reallocate it with space enough to insert the new samples */
3443   } else
3444     stream->samples = g_try_renew (QtDemuxSample, stream->samples,
3445         stream->n_samples + samples_count);
3446   if (stream->samples == NULL)
3447     goto out_of_memory;
3448
3449   if (qtdemux->fragment_start != -1) {
3450     timestamp = GSTTIME_TO_QTSTREAMTIME (stream, qtdemux->fragment_start);
3451     qtdemux->fragment_start = -1;
3452   } else {
3453     if (stream->n_samples == 0) {
3454       if (decode_ts > 0) {
3455         timestamp = decode_ts;
3456       } else if (stream->pending_seek != NULL) {
3457         /* if we don't have a timestamp from a tfdt box, we'll use the one
3458          * from the mfra seek table */
3459         GST_INFO_OBJECT (stream->pad, "pending seek ts = %" GST_TIME_FORMAT,
3460             GST_TIME_ARGS (stream->pending_seek->ts));
3461
3462         /* FIXME: this is not fully correct, the timestamp refers to the random
3463          * access sample refered to in the tfra entry, which may not necessarily
3464          * be the first sample in the tfrag/trun (but hopefully/usually is) */
3465         timestamp = GSTTIME_TO_QTSTREAMTIME (stream, stream->pending_seek->ts);
3466       } else {
3467         timestamp = 0;
3468       }
3469
3470       gst_ts = QTSTREAMTIME_TO_GSTTIME (stream, timestamp);
3471       GST_INFO_OBJECT (stream->pad, "first sample ts %" GST_TIME_FORMAT,
3472           GST_TIME_ARGS (gst_ts));
3473     } else {
3474       /* subsequent fragments extend stream */
3475       timestamp =
3476           stream->samples[stream->n_samples - 1].timestamp +
3477           stream->samples[stream->n_samples - 1].duration;
3478
3479       /* If this is a GST_FORMAT_BYTES stream and there's a significant
3480        * difference (1 sec.) between decode_ts and timestamp, prefer the
3481        * former */
3482       if (has_tfdt && !qtdemux->upstream_format_is_time
3483           && ABSDIFF (decode_ts, timestamp) >
3484           MAX (stream->duration_last_moof / 2,
3485               GSTTIME_TO_QTSTREAMTIME (stream, GST_SECOND))) {
3486         GST_INFO_OBJECT (qtdemux,
3487             "decode_ts (%" GST_TIME_FORMAT ") and timestamp (%" GST_TIME_FORMAT
3488             ") are significantly different (more than %" GST_TIME_FORMAT
3489             "), using decode_ts",
3490             GST_TIME_ARGS (QTSTREAMTIME_TO_GSTTIME (stream, decode_ts)),
3491             GST_TIME_ARGS (QTSTREAMTIME_TO_GSTTIME (stream, timestamp)),
3492             GST_TIME_ARGS (QTSTREAMTIME_TO_GSTTIME (stream,
3493                     MAX (stream->duration_last_moof / 2,
3494                         GSTTIME_TO_QTSTREAMTIME (stream, GST_SECOND)))));
3495         timestamp = decode_ts;
3496       }
3497
3498       gst_ts = QTSTREAMTIME_TO_GSTTIME (stream, timestamp);
3499       GST_INFO_OBJECT (qtdemux, "first sample ts %" GST_TIME_FORMAT
3500           " (extends previous samples)", GST_TIME_ARGS (gst_ts));
3501     }
3502   }
3503
3504   initial_offset = *running_offset;
3505
3506   sample = stream->samples + stream->n_samples;
3507   for (i = 0; i < samples_count; i++) {
3508     guint32 dur, size, sflags, ct;
3509
3510     /* first read sample data */
3511     if (flags & TR_SAMPLE_DURATION) {
3512       dur = QT_UINT32 (data + dur_offset);
3513     } else {
3514       dur = d_sample_duration;
3515     }
3516     if (flags & TR_SAMPLE_SIZE) {
3517       size = QT_UINT32 (data + size_offset);
3518     } else {
3519       size = d_sample_size;
3520     }
3521     if (flags & TR_FIRST_SAMPLE_FLAGS) {
3522       if (i == 0) {
3523         sflags = first_flags;
3524       } else {
3525         sflags = d_sample_flags;
3526       }
3527     } else if (flags & TR_SAMPLE_FLAGS) {
3528       sflags = QT_UINT32 (data + flags_offset);
3529     } else {
3530       sflags = d_sample_flags;
3531     }
3532     if (flags & TR_COMPOSITION_TIME_OFFSETS) {
3533       ct = QT_UINT32 (data + ct_offset);
3534     } else {
3535       ct = 0;
3536     }
3537     data += entry_size;
3538
3539     /* fill the sample information */
3540     sample->offset = *running_offset;
3541     sample->pts_offset = ct;
3542     sample->size = size;
3543     sample->timestamp = timestamp;
3544     sample->duration = dur;
3545     /* sample-is-difference-sample */
3546     /* ismv seems to use 0x40 for keyframe, 0xc0 for non-keyframe,
3547      * now idea how it relates to bitfield other than massive LE/BE confusion */
3548     sample->keyframe = ismv ? ((sflags & 0xff) == 0x40) : !(sflags & 0x10000);
3549     *running_offset += size;
3550     timestamp += dur;
3551     stream->duration_moof += dur;
3552     sample++;
3553   }
3554
3555   /* Update total duration if needed */
3556   check_update_duration (qtdemux, QTSTREAMTIME_TO_GSTTIME (stream, timestamp));
3557
3558   /* Pre-emptively figure out size of mdat based on trun information.
3559    * If the [mdat] atom is effectivelly read, it will be replaced by the actual
3560    * size, else we will still be able to use this when dealing with gap'ed
3561    * input */
3562   qtdemux->mdatleft = *running_offset - initial_offset;
3563   qtdemux->mdatoffset = initial_offset;
3564   qtdemux->mdatsize = qtdemux->mdatleft;
3565
3566   stream->n_samples += samples_count;
3567   stream->n_samples_moof += samples_count;
3568
3569   if (stream->pending_seek != NULL)
3570     stream->pending_seek = NULL;
3571
3572   return TRUE;
3573
3574 fail:
3575   {
3576     GST_WARNING_OBJECT (qtdemux, "failed to parse trun");
3577     return FALSE;
3578   }
3579 out_of_memory:
3580   {
3581     GST_WARNING_OBJECT (qtdemux, "failed to allocate %d samples",
3582         stream->n_samples);
3583     return FALSE;
3584   }
3585 index_too_big:
3586   {
3587     GST_WARNING_OBJECT (qtdemux, "not allocating index of %d samples, would "
3588         "be larger than %uMB (broken file?)", stream->n_samples,
3589         QTDEMUX_MAX_SAMPLE_INDEX_SIZE >> 20);
3590     return FALSE;
3591   }
3592 }
3593
3594 /* find stream with @id */
3595 static inline QtDemuxStream *
3596 qtdemux_find_stream (GstQTDemux * qtdemux, guint32 id)
3597 {
3598   QtDemuxStream *stream;
3599   gint i;
3600
3601   /* check */
3602   if (G_UNLIKELY (!id)) {
3603     GST_DEBUG_OBJECT (qtdemux, "invalid track id 0");
3604     return NULL;
3605   }
3606
3607   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
3608     stream = QTDEMUX_NTH_STREAM (qtdemux, i);
3609     if (stream->track_id == id)
3610       return stream;
3611   }
3612   if (qtdemux->mss_mode) {
3613     /* mss should have only 1 stream anyway */
3614     return QTDEMUX_NTH_STREAM (qtdemux, 0);
3615   }
3616
3617   return NULL;
3618 }
3619
3620 static gboolean
3621 qtdemux_parse_mfhd (GstQTDemux * qtdemux, GstByteReader * mfhd,
3622     guint32 * fragment_number)
3623 {
3624   if (!gst_byte_reader_skip (mfhd, 4))
3625     goto fail;
3626   if (!gst_byte_reader_get_uint32_be (mfhd, fragment_number))
3627     goto fail;
3628   return TRUE;
3629 fail:
3630   {
3631     GST_WARNING_OBJECT (qtdemux, "Failed to parse mfhd atom");
3632     return FALSE;
3633   }
3634 }
3635
3636 static gboolean
3637 qtdemux_parse_tfhd (GstQTDemux * qtdemux, GstByteReader * tfhd,
3638     QtDemuxStream ** stream, guint32 * default_sample_duration,
3639     guint32 * default_sample_size, guint32 * default_sample_flags,
3640     gint64 * base_offset)
3641 {
3642   guint32 flags = 0;
3643   guint32 track_id = 0;
3644
3645   if (!gst_byte_reader_skip (tfhd, 1) ||
3646       !gst_byte_reader_get_uint24_be (tfhd, &flags))
3647     goto invalid_track;
3648
3649   if (!gst_byte_reader_get_uint32_be (tfhd, &track_id))
3650     goto invalid_track;
3651
3652   *stream = qtdemux_find_stream (qtdemux, track_id);
3653   if (G_UNLIKELY (!*stream))
3654     goto unknown_stream;
3655
3656   if (flags & TF_DEFAULT_BASE_IS_MOOF)
3657     *base_offset = qtdemux->moof_offset;
3658
3659   if (flags & TF_BASE_DATA_OFFSET)
3660     if (!gst_byte_reader_get_uint64_be (tfhd, (guint64 *) base_offset))
3661       goto invalid_track;
3662
3663   /* obtain stream defaults */
3664   qtdemux_parse_trex (qtdemux, *stream,
3665       default_sample_duration, default_sample_size, default_sample_flags);
3666
3667   (*stream)->stsd_sample_description_id =
3668       (*stream)->def_sample_description_index - 1;
3669
3670   if (flags & TF_SAMPLE_DESCRIPTION_INDEX) {
3671     guint32 sample_description_index;
3672     if (!gst_byte_reader_get_uint32_be (tfhd, &sample_description_index))
3673       goto invalid_track;
3674     (*stream)->stsd_sample_description_id = sample_description_index - 1;
3675   }
3676
3677   if (qtdemux->mss_mode) {
3678     /* mss has no stsd entry */
3679     (*stream)->stsd_sample_description_id = 0;
3680   }
3681
3682   if (flags & TF_DEFAULT_SAMPLE_DURATION)
3683     if (!gst_byte_reader_get_uint32_be (tfhd, default_sample_duration))
3684       goto invalid_track;
3685
3686   if (flags & TF_DEFAULT_SAMPLE_SIZE)
3687     if (!gst_byte_reader_get_uint32_be (tfhd, default_sample_size))
3688       goto invalid_track;
3689
3690   if (flags & TF_DEFAULT_SAMPLE_FLAGS)
3691     if (!gst_byte_reader_get_uint32_be (tfhd, default_sample_flags))
3692       goto invalid_track;
3693
3694   return TRUE;
3695
3696 invalid_track:
3697   {
3698     GST_WARNING_OBJECT (qtdemux, "invalid track fragment header");
3699     return FALSE;
3700   }
3701 unknown_stream:
3702   {
3703     GST_DEBUG_OBJECT (qtdemux, "unknown stream in tfhd");
3704     return TRUE;
3705   }
3706 }
3707
3708 static gboolean
3709 qtdemux_parse_tfdt (GstQTDemux * qtdemux, GstByteReader * br,
3710     guint64 * decode_time)
3711 {
3712   guint32 version = 0;
3713
3714   if (!gst_byte_reader_get_uint32_be (br, &version))
3715     return FALSE;
3716
3717   version >>= 24;
3718   if (version == 1) {
3719     if (!gst_byte_reader_get_uint64_be (br, decode_time))
3720       goto failed;
3721   } else {
3722     guint32 dec_time = 0;
3723     if (!gst_byte_reader_get_uint32_be (br, &dec_time))
3724       goto failed;
3725     *decode_time = dec_time;
3726   }
3727
3728   GST_INFO_OBJECT (qtdemux, "Track fragment decode time: %" G_GUINT64_FORMAT,
3729       *decode_time);
3730
3731   return TRUE;
3732
3733 failed:
3734   {
3735     GST_DEBUG_OBJECT (qtdemux, "parsing tfdt failed");
3736     return FALSE;
3737   }
3738 }
3739
3740 /* Returns a pointer to a GstStructure containing the properties of
3741  * the stream sample identified by @sample_index. The caller must unref
3742  * the returned object after use. Returns NULL if unsuccessful. */
3743 static GstStructure *
3744 qtdemux_get_cenc_sample_properties (GstQTDemux * qtdemux,
3745     QtDemuxStream * stream, guint sample_index)
3746 {
3747   QtDemuxCencSampleSetInfo *info = NULL;
3748
3749   g_return_val_if_fail (stream != NULL, NULL);
3750   g_return_val_if_fail (stream->protected, NULL);
3751   g_return_val_if_fail (stream->protection_scheme_info != NULL, NULL);
3752
3753   info = (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
3754
3755   /* Currently, cenc properties for groups of samples are not supported, so
3756    * simply return a copy of the default sample properties */
3757   return gst_structure_copy (info->default_properties);
3758 }
3759
3760 /* Parses the sizes of sample auxiliary information contained within a stream,
3761  * as given in a saiz box. Returns array of sample_count guint8 size values,
3762  * or NULL on failure */
3763 static guint8 *
3764 qtdemux_parse_saiz (GstQTDemux * qtdemux, QtDemuxStream * stream,
3765     GstByteReader * br, guint32 * sample_count)
3766 {
3767   guint32 flags = 0;
3768   guint8 *info_sizes;
3769   guint8 default_info_size;
3770
3771   g_return_val_if_fail (qtdemux != NULL, NULL);
3772   g_return_val_if_fail (stream != NULL, NULL);
3773   g_return_val_if_fail (br != NULL, NULL);
3774   g_return_val_if_fail (sample_count != NULL, NULL);
3775
3776   if (!gst_byte_reader_get_uint32_be (br, &flags))
3777     return NULL;
3778
3779   if (flags & 0x1) {
3780     /* aux_info_type and aux_info_type_parameter are ignored */
3781     if (!gst_byte_reader_skip (br, 8))
3782       return NULL;
3783   }
3784
3785   if (!gst_byte_reader_get_uint8 (br, &default_info_size))
3786     return NULL;
3787   GST_DEBUG_OBJECT (qtdemux, "default_info_size: %u", default_info_size);
3788
3789   if (!gst_byte_reader_get_uint32_be (br, sample_count))
3790     return NULL;
3791   GST_DEBUG_OBJECT (qtdemux, "sample_count: %u", *sample_count);
3792
3793
3794   if (default_info_size == 0) {
3795     if (!gst_byte_reader_dup_data (br, *sample_count, &info_sizes)) {
3796       return NULL;
3797     }
3798   } else {
3799     info_sizes = g_new (guint8, *sample_count);
3800     memset (info_sizes, default_info_size, *sample_count);
3801   }
3802
3803   return info_sizes;
3804 }
3805
3806 /* Parses the offset of sample auxiliary information contained within a stream,
3807  * as given in a saio box. Returns TRUE if successful; FALSE otherwise. */
3808 static gboolean
3809 qtdemux_parse_saio (GstQTDemux * qtdemux, QtDemuxStream * stream,
3810     GstByteReader * br, guint32 * info_type, guint32 * info_type_parameter,
3811     guint64 * offset)
3812 {
3813   guint8 version = 0;
3814   guint32 flags = 0;
3815   guint32 aux_info_type = 0;
3816   guint32 aux_info_type_parameter = 0;
3817   guint32 entry_count;
3818   guint32 off_32;
3819   guint64 off_64;
3820   const guint8 *aux_info_type_data = NULL;
3821
3822   g_return_val_if_fail (qtdemux != NULL, FALSE);
3823   g_return_val_if_fail (stream != NULL, FALSE);
3824   g_return_val_if_fail (br != NULL, FALSE);
3825   g_return_val_if_fail (offset != NULL, FALSE);
3826
3827   if (!gst_byte_reader_get_uint8 (br, &version))
3828     return FALSE;
3829
3830   if (!gst_byte_reader_get_uint24_be (br, &flags))
3831     return FALSE;
3832
3833   if (flags & 0x1) {
3834
3835     if (!gst_byte_reader_get_data (br, 4, &aux_info_type_data))
3836       return FALSE;
3837     aux_info_type = QT_FOURCC (aux_info_type_data);
3838
3839     if (!gst_byte_reader_get_uint32_be (br, &aux_info_type_parameter))
3840       return FALSE;
3841   } else if (stream->protected) {
3842     aux_info_type = stream->protection_scheme_type;
3843   } else {
3844     aux_info_type = CUR_STREAM (stream)->fourcc;
3845   }
3846
3847   if (info_type)
3848     *info_type = aux_info_type;
3849   if (info_type_parameter)
3850     *info_type_parameter = aux_info_type_parameter;
3851
3852   GST_DEBUG_OBJECT (qtdemux, "aux_info_type: '%" GST_FOURCC_FORMAT "', "
3853       "aux_info_type_parameter:  %#06x",
3854       GST_FOURCC_ARGS (aux_info_type), aux_info_type_parameter);
3855
3856   if (!gst_byte_reader_get_uint32_be (br, &entry_count))
3857     return FALSE;
3858
3859   if (entry_count != 1) {
3860     GST_ERROR_OBJECT (qtdemux, "multiple offsets are not supported");
3861     return FALSE;
3862   }
3863
3864   if (version == 0) {
3865     if (!gst_byte_reader_get_uint32_be (br, &off_32))
3866       return FALSE;
3867     *offset = (guint64) off_32;
3868   } else {
3869     if (!gst_byte_reader_get_uint64_be (br, &off_64))
3870       return FALSE;
3871     *offset = off_64;
3872   }
3873
3874   GST_DEBUG_OBJECT (qtdemux, "offset: %" G_GUINT64_FORMAT, *offset);
3875   return TRUE;
3876 }
3877
3878 static void
3879 qtdemux_gst_structure_free (GstStructure * gststructure)
3880 {
3881   if (gststructure) {
3882     gst_structure_free (gststructure);
3883   }
3884 }
3885
3886 /* Parses auxiliary information relating to samples protected using Common
3887  * Encryption (cenc); the format of this information is defined in
3888  * ISO/IEC 23001-7. Returns TRUE if successful; FALSE otherwise. */
3889 static gboolean
3890 qtdemux_parse_cenc_aux_info (GstQTDemux * qtdemux, QtDemuxStream * stream,
3891     GstByteReader * br, guint8 * info_sizes, guint32 sample_count)
3892 {
3893   QtDemuxCencSampleSetInfo *ss_info = NULL;
3894   guint8 size;
3895   gint i;
3896   GPtrArray *old_crypto_info = NULL;
3897   guint old_entries = 0;
3898
3899   g_return_val_if_fail (qtdemux != NULL, FALSE);
3900   g_return_val_if_fail (stream != NULL, FALSE);
3901   g_return_val_if_fail (br != NULL, FALSE);
3902   g_return_val_if_fail (stream->protected, FALSE);
3903   g_return_val_if_fail (stream->protection_scheme_info != NULL, FALSE);
3904
3905   ss_info = (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
3906
3907   if (ss_info->crypto_info) {
3908     old_crypto_info = ss_info->crypto_info;
3909     /* Count number of non-null entries remaining at the tail end */
3910     for (i = old_crypto_info->len - 1; i >= 0; i--) {
3911       if (g_ptr_array_index (old_crypto_info, i) == NULL)
3912         break;
3913       old_entries++;
3914     }
3915   }
3916
3917   ss_info->crypto_info =
3918       g_ptr_array_new_full (sample_count + old_entries,
3919       (GDestroyNotify) qtdemux_gst_structure_free);
3920
3921   /* We preserve old entries because we parse the next moof in advance
3922    * of consuming all samples from the previous moof, and otherwise
3923    * we'd discard the corresponding crypto info for the samples
3924    * from the previous fragment. */
3925   if (old_entries) {
3926     GST_DEBUG_OBJECT (qtdemux, "Preserving %d old crypto info entries",
3927         old_entries);
3928     for (i = old_crypto_info->len - old_entries; i < old_crypto_info->len; i++) {
3929       g_ptr_array_add (ss_info->crypto_info, g_ptr_array_index (old_crypto_info,
3930               i));
3931       g_ptr_array_index (old_crypto_info, i) = NULL;
3932     }
3933   }
3934
3935   if (old_crypto_info) {
3936     /* Everything now belongs to the new array */
3937     g_ptr_array_free (old_crypto_info, TRUE);
3938   }
3939
3940   for (i = 0; i < sample_count; ++i) {
3941     GstStructure *properties;
3942     guint16 n_subsamples = 0;
3943     guint8 *data;
3944     guint iv_size;
3945     GstBuffer *buf;
3946
3947     properties = qtdemux_get_cenc_sample_properties (qtdemux, stream, i);
3948     if (properties == NULL) {
3949       GST_ERROR_OBJECT (qtdemux, "failed to get properties for sample %u", i);
3950       return FALSE;
3951     }
3952     if (!gst_structure_get_uint (properties, "iv_size", &iv_size)) {
3953       GST_ERROR_OBJECT (qtdemux, "failed to get iv_size for sample %u", i);
3954       gst_structure_free (properties);
3955       return FALSE;
3956     }
3957     if (!gst_byte_reader_dup_data (br, iv_size, &data)) {
3958       GST_ERROR_OBJECT (qtdemux, "failed to get IV for sample %u", i);
3959       gst_structure_free (properties);
3960       return FALSE;
3961     }
3962     buf = gst_buffer_new_wrapped (data, iv_size);
3963     gst_structure_set (properties, "iv", GST_TYPE_BUFFER, buf, NULL);
3964     gst_buffer_unref (buf);
3965     size = info_sizes[i];
3966     if (size > iv_size) {
3967       if (!gst_byte_reader_get_uint16_be (br, &n_subsamples)
3968           || !(n_subsamples > 0)) {
3969         gst_structure_free (properties);
3970         GST_ERROR_OBJECT (qtdemux,
3971             "failed to get subsample count for sample %u", i);
3972         return FALSE;
3973       }
3974       GST_LOG_OBJECT (qtdemux, "subsample count: %u", n_subsamples);
3975       if (!gst_byte_reader_dup_data (br, n_subsamples * 6, &data)) {
3976         GST_ERROR_OBJECT (qtdemux, "failed to get subsample data for sample %u",
3977             i);
3978         gst_structure_free (properties);
3979         return FALSE;
3980       }
3981       buf = gst_buffer_new_wrapped (data, n_subsamples * 6);
3982       if (!buf) {
3983         gst_structure_free (properties);
3984         return FALSE;
3985       }
3986       gst_structure_set (properties,
3987           "subsample_count", G_TYPE_UINT, n_subsamples,
3988           "subsamples", GST_TYPE_BUFFER, buf, NULL);
3989       gst_buffer_unref (buf);
3990     } else {
3991       gst_structure_set (properties, "subsample_count", G_TYPE_UINT, 0, NULL);
3992     }
3993     g_ptr_array_add (ss_info->crypto_info, properties);
3994   }
3995   return TRUE;
3996 }
3997
3998 /* Converts a UUID in raw byte form to a string representation, as defined in
3999  * RFC 4122. The caller takes ownership of the returned string and is
4000  * responsible for freeing it after use. */
4001 static gchar *
4002 qtdemux_uuid_bytes_to_string (gconstpointer uuid_bytes)
4003 {
4004   const guint8 *uuid = (const guint8 *) uuid_bytes;
4005
4006   return g_strdup_printf ("%02x%02x%02x%02x-%02x%02x-%02x%02x-"
4007       "%02x%02x-%02x%02x%02x%02x%02x%02x",
4008       uuid[0], uuid[1], uuid[2], uuid[3],
4009       uuid[4], uuid[5], uuid[6], uuid[7],
4010       uuid[8], uuid[9], uuid[10], uuid[11],
4011       uuid[12], uuid[13], uuid[14], uuid[15]);
4012 }
4013
4014 /* Parses a Protection System Specific Header box (pssh), as defined in the
4015  * Common Encryption (cenc) standard (ISO/IEC 23001-7), which contains
4016  * information needed by a specific content protection system in order to
4017  * decrypt cenc-protected tracks. Returns TRUE if successful; FALSE
4018  * otherwise. */
4019 static gboolean
4020 qtdemux_parse_pssh (GstQTDemux * qtdemux, GNode * node)
4021 {
4022   gchar *sysid_string;
4023   guint32 pssh_size = QT_UINT32 (node->data);
4024   GstBuffer *pssh = NULL;
4025   GstEvent *event = NULL;
4026   guint32 parent_box_type;
4027   gint i;
4028
4029   if (G_UNLIKELY (pssh_size < 32U)) {
4030     GST_ERROR_OBJECT (qtdemux, "invalid box size");
4031     return FALSE;
4032   }
4033
4034   sysid_string =
4035       qtdemux_uuid_bytes_to_string ((const guint8 *) node->data + 12);
4036
4037   gst_qtdemux_append_protection_system_id (qtdemux, sysid_string);
4038
4039   pssh = gst_buffer_new_wrapped (g_memdup (node->data, pssh_size), pssh_size);
4040   GST_LOG_OBJECT (qtdemux, "cenc pssh size: %" G_GSIZE_FORMAT,
4041       gst_buffer_get_size (pssh));
4042
4043   parent_box_type = QT_FOURCC ((const guint8 *) node->parent->data + 4);
4044
4045   /* Push an event containing the pssh box onto the queues of all streams. */
4046   event = gst_event_new_protection (sysid_string, pssh,
4047       (parent_box_type == FOURCC_moov) ? "isobmff/moov" : "isobmff/moof");
4048   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
4049     QtDemuxStream *stream = QTDEMUX_NTH_STREAM (qtdemux, i);
4050     GST_TRACE_OBJECT (qtdemux,
4051         "adding protection event for stream %s and system %s",
4052         stream->stream_id, sysid_string);
4053     g_queue_push_tail (&stream->protection_scheme_event_queue,
4054         gst_event_ref (event));
4055   }
4056   g_free (sysid_string);
4057   gst_event_unref (event);
4058   gst_buffer_unref (pssh);
4059   return TRUE;
4060 }
4061
4062 static gboolean
4063 qtdemux_parse_moof (GstQTDemux * qtdemux, const guint8 * buffer, guint length,
4064     guint64 moof_offset, QtDemuxStream * stream)
4065 {
4066   GNode *moof_node, *traf_node, *tfhd_node, *trun_node, *tfdt_node, *mfhd_node;
4067   GNode *uuid_node;
4068   GstByteReader mfhd_data, trun_data, tfhd_data, tfdt_data;
4069   GNode *saiz_node, *saio_node, *pssh_node;
4070   GstByteReader saiz_data, saio_data;
4071   guint32 ds_size = 0, ds_duration = 0, ds_flags = 0;
4072   gint64 base_offset, running_offset;
4073   guint32 frag_num;
4074   GstClockTime min_dts = GST_CLOCK_TIME_NONE;
4075
4076   /* NOTE @stream ignored */
4077
4078   moof_node = g_node_new ((guint8 *) buffer);
4079   qtdemux_parse_node (qtdemux, moof_node, buffer, length);
4080   qtdemux_node_dump (qtdemux, moof_node);
4081
4082   /* Get fragment number from mfhd and check it's valid */
4083   mfhd_node =
4084       qtdemux_tree_get_child_by_type_full (moof_node, FOURCC_mfhd, &mfhd_data);
4085   if (mfhd_node == NULL)
4086     goto missing_mfhd;
4087   if (!qtdemux_parse_mfhd (qtdemux, &mfhd_data, &frag_num))
4088     goto fail;
4089   GST_DEBUG_OBJECT (qtdemux, "Fragment #%d", frag_num);
4090
4091   /* unknown base_offset to start with */
4092   base_offset = running_offset = -1;
4093   traf_node = qtdemux_tree_get_child_by_type (moof_node, FOURCC_traf);
4094   while (traf_node) {
4095     guint64 decode_time = 0;
4096
4097     /* Fragment Header node */
4098     tfhd_node =
4099         qtdemux_tree_get_child_by_type_full (traf_node, FOURCC_tfhd,
4100         &tfhd_data);
4101     if (!tfhd_node)
4102       goto missing_tfhd;
4103     if (!qtdemux_parse_tfhd (qtdemux, &tfhd_data, &stream, &ds_duration,
4104             &ds_size, &ds_flags, &base_offset))
4105       goto missing_tfhd;
4106
4107     /* The following code assumes at most a single set of sample auxiliary
4108      * data in the fragment (consisting of a saiz box and a corresponding saio
4109      * box); in theory, however, there could be multiple sets of sample
4110      * auxiliary data in a fragment. */
4111     saiz_node =
4112         qtdemux_tree_get_child_by_type_full (traf_node, FOURCC_saiz,
4113         &saiz_data);
4114     if (saiz_node) {
4115       guint32 info_type = 0;
4116       guint64 offset = 0;
4117       guint32 info_type_parameter = 0;
4118
4119       g_free (qtdemux->cenc_aux_info_sizes);
4120
4121       qtdemux->cenc_aux_info_sizes =
4122           qtdemux_parse_saiz (qtdemux, stream, &saiz_data,
4123           &qtdemux->cenc_aux_sample_count);
4124       if (qtdemux->cenc_aux_info_sizes == NULL) {
4125         GST_ERROR_OBJECT (qtdemux, "failed to parse saiz box");
4126         goto fail;
4127       }
4128       saio_node =
4129           qtdemux_tree_get_child_by_type_full (traf_node, FOURCC_saio,
4130           &saio_data);
4131       if (!saio_node) {
4132         GST_ERROR_OBJECT (qtdemux, "saiz box without a corresponding saio box");
4133         g_free (qtdemux->cenc_aux_info_sizes);
4134         qtdemux->cenc_aux_info_sizes = NULL;
4135         goto fail;
4136       }
4137
4138       if (G_UNLIKELY (!qtdemux_parse_saio (qtdemux, stream, &saio_data,
4139                   &info_type, &info_type_parameter, &offset))) {
4140         GST_ERROR_OBJECT (qtdemux, "failed to parse saio box");
4141         g_free (qtdemux->cenc_aux_info_sizes);
4142         qtdemux->cenc_aux_info_sizes = NULL;
4143         goto fail;
4144       }
4145       if (base_offset > -1 && base_offset > qtdemux->moof_offset)
4146         offset += (guint64) (base_offset - qtdemux->moof_offset);
4147       if (info_type == FOURCC_cenc && info_type_parameter == 0U) {
4148         GstByteReader br;
4149         if (offset > length) {
4150           GST_DEBUG_OBJECT (qtdemux, "cenc auxiliary info stored out of moof");
4151           qtdemux->cenc_aux_info_offset = offset;
4152         } else {
4153           gst_byte_reader_init (&br, buffer + offset, length - offset);
4154           if (!qtdemux_parse_cenc_aux_info (qtdemux, stream, &br,
4155                   qtdemux->cenc_aux_info_sizes,
4156                   qtdemux->cenc_aux_sample_count)) {
4157             GST_ERROR_OBJECT (qtdemux, "failed to parse cenc auxiliary info");
4158             g_free (qtdemux->cenc_aux_info_sizes);
4159             qtdemux->cenc_aux_info_sizes = NULL;
4160             goto fail;
4161           }
4162         }
4163       }
4164     }
4165
4166     tfdt_node =
4167         qtdemux_tree_get_child_by_type_full (traf_node, FOURCC_tfdt,
4168         &tfdt_data);
4169     if (tfdt_node) {
4170       /* We'll use decode_time to interpolate timestamps
4171        * in case the input timestamps are missing */
4172       qtdemux_parse_tfdt (qtdemux, &tfdt_data, &decode_time);
4173
4174       GST_DEBUG_OBJECT (qtdemux, "decode time %" G_GINT64_FORMAT
4175           " (%" GST_TIME_FORMAT ")", decode_time,
4176           GST_TIME_ARGS (stream ? QTSTREAMTIME_TO_GSTTIME (stream,
4177                   decode_time) : GST_CLOCK_TIME_NONE));
4178
4179       /* Discard the fragment buffer timestamp info to avoid using it.
4180        * Rely on tfdt instead as it is more accurate than the timestamp
4181        * that is fetched from a manifest/playlist and is usually
4182        * less accurate. */
4183       qtdemux->fragment_start = -1;
4184     }
4185
4186     if (G_UNLIKELY (!stream)) {
4187       /* we lost track of offset, we'll need to regain it,
4188        * but can delay complaining until later or avoid doing so altogether */
4189       base_offset = -2;
4190       goto next;
4191     }
4192     if (G_UNLIKELY (base_offset < -1))
4193       goto lost_offset;
4194
4195     min_dts = MIN (min_dts, QTSTREAMTIME_TO_GSTTIME (stream, decode_time));
4196
4197     if (!qtdemux->pullbased) {
4198       /* Sample tables can grow enough to be problematic if the system memory
4199        * is very low (e.g. embedded devices) and the videos very long
4200        * (~8 MiB/hour for 25-30 fps video + typical AAC audio frames).
4201        * Fortunately, we can easily discard them for each new fragment when
4202        * we know qtdemux will not receive seeks outside of the current fragment.
4203        * adaptivedemux honors this assumption.
4204        * This optimization is also useful for applications that use qtdemux as
4205        * a push-based simple demuxer, like Media Source Extensions. */
4206       gst_qtdemux_stream_flush_samples_data (stream);
4207     }
4208
4209     /* initialise moof sample data */
4210     stream->n_samples_moof = 0;
4211     stream->duration_last_moof = stream->duration_moof;
4212     stream->duration_moof = 0;
4213
4214     /* Track Run node */
4215     trun_node =
4216         qtdemux_tree_get_child_by_type_full (traf_node, FOURCC_trun,
4217         &trun_data);
4218     while (trun_node) {
4219       qtdemux_parse_trun (qtdemux, &trun_data, stream,
4220           ds_duration, ds_size, ds_flags, moof_offset, length, &base_offset,
4221           &running_offset, decode_time, (tfdt_node != NULL));
4222       /* iterate all siblings */
4223       trun_node = qtdemux_tree_get_sibling_by_type_full (trun_node, FOURCC_trun,
4224           &trun_data);
4225     }
4226
4227     uuid_node = qtdemux_tree_get_child_by_type (traf_node, FOURCC_uuid);
4228     if (uuid_node) {
4229       guint8 *uuid_buffer = (guint8 *) uuid_node->data;
4230       guint32 box_length = QT_UINT32 (uuid_buffer);
4231
4232       qtdemux_parse_uuid (qtdemux, uuid_buffer, box_length);
4233     }
4234
4235     /* if no new base_offset provided for next traf,
4236      * base is end of current traf */
4237     base_offset = running_offset;
4238     running_offset = -1;
4239
4240     if (stream->n_samples_moof && stream->duration_moof)
4241       stream->new_caps = TRUE;
4242
4243   next:
4244     /* iterate all siblings */
4245     traf_node = qtdemux_tree_get_sibling_by_type (traf_node, FOURCC_traf);
4246   }
4247
4248   /* parse any protection system info */
4249   pssh_node = qtdemux_tree_get_child_by_type (moof_node, FOURCC_pssh);
4250   while (pssh_node) {
4251     GST_LOG_OBJECT (qtdemux, "Parsing pssh box.");
4252     qtdemux_parse_pssh (qtdemux, pssh_node);
4253     pssh_node = qtdemux_tree_get_sibling_by_type (pssh_node, FOURCC_pssh);
4254   }
4255
4256   if (!qtdemux->upstream_format_is_time && !qtdemux->first_moof_already_parsed
4257       && !qtdemux->received_seek && GST_CLOCK_TIME_IS_VALID (min_dts)
4258       && min_dts != 0) {
4259     /* Unless the user has explictly requested another seek, perform an
4260      * internal seek to the time specified in the tfdt.
4261      *
4262      * This way if the user opens a file where the first tfdt is 1 hour
4263      * into the presentation, they will not have to wait 1 hour for run
4264      * time to catch up and actual playback to start. */
4265     gint i;
4266
4267     GST_DEBUG_OBJECT (qtdemux, "First fragment has a non-zero tfdt, "
4268         "performing an internal seek to %" GST_TIME_FORMAT,
4269         GST_TIME_ARGS (min_dts));
4270
4271     qtdemux->segment.start = min_dts;
4272     qtdemux->segment.time = qtdemux->segment.position = min_dts;
4273
4274     for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
4275       QtDemuxStream *stream = QTDEMUX_NTH_STREAM (qtdemux, i);
4276       stream->time_position = min_dts;
4277     }
4278
4279     /* Before this code was run a segment was already sent when the moov was
4280      * parsed... which is OK -- some apps (mostly tests) expect a segment to
4281      * be emitted after a moov, and we can emit a second segment anyway for
4282      * special cases like this. */
4283     qtdemux->need_segment = TRUE;
4284   }
4285
4286   qtdemux->first_moof_already_parsed = TRUE;
4287
4288   g_node_destroy (moof_node);
4289   return TRUE;
4290
4291 missing_tfhd:
4292   {
4293     GST_DEBUG_OBJECT (qtdemux, "missing tfhd box");
4294     goto fail;
4295   }
4296 missing_mfhd:
4297   {
4298     GST_DEBUG_OBJECT (qtdemux, "Missing mfhd box");
4299     goto fail;
4300   }
4301 lost_offset:
4302   {
4303     GST_DEBUG_OBJECT (qtdemux, "lost offset");
4304     goto fail;
4305   }
4306 fail:
4307   {
4308     g_node_destroy (moof_node);
4309     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
4310         (_("This file is corrupt and cannot be played.")), (NULL));
4311     return FALSE;
4312   }
4313 }
4314
4315 #if 0
4316 /* might be used if some day we actually use mfra & co
4317  * for random access to fragments,
4318  * but that will require quite some modifications and much less relying
4319  * on a sample array */
4320 #endif
4321
4322 static gboolean
4323 qtdemux_parse_tfra (GstQTDemux * qtdemux, GNode * tfra_node)
4324 {
4325   QtDemuxStream *stream;
4326   guint32 ver_flags, track_id, len, num_entries, i;
4327   guint value_size, traf_size, trun_size, sample_size;
4328   guint64 time = 0, moof_offset = 0;
4329 #if 0
4330   GstBuffer *buf = NULL;
4331   GstFlowReturn ret;
4332 #endif
4333   GstByteReader tfra;
4334
4335   gst_byte_reader_init (&tfra, tfra_node->data, QT_UINT32 (tfra_node->data));
4336
4337   if (!gst_byte_reader_skip (&tfra, 8))
4338     return FALSE;
4339
4340   if (!gst_byte_reader_get_uint32_be (&tfra, &ver_flags))
4341     return FALSE;
4342
4343   if (!gst_byte_reader_get_uint32_be (&tfra, &track_id)
4344       || !gst_byte_reader_get_uint32_be (&tfra, &len)
4345       || !gst_byte_reader_get_uint32_be (&tfra, &num_entries))
4346     return FALSE;
4347
4348   GST_DEBUG_OBJECT (qtdemux, "parsing tfra box for track id %u", track_id);
4349
4350   stream = qtdemux_find_stream (qtdemux, track_id);
4351   if (stream == NULL)
4352     goto unknown_trackid;
4353
4354   value_size = ((ver_flags >> 24) == 1) ? sizeof (guint64) : sizeof (guint32);
4355   sample_size = (len & 3) + 1;
4356   trun_size = ((len & 12) >> 2) + 1;
4357   traf_size = ((len & 48) >> 4) + 1;
4358
4359   GST_DEBUG_OBJECT (qtdemux, "%u entries, sizes: value %u, traf %u, trun %u, "
4360       "sample %u", num_entries, value_size, traf_size, trun_size, sample_size);
4361
4362   if (num_entries == 0)
4363     goto no_samples;
4364
4365   if (!qt_atom_parser_has_chunks (&tfra, num_entries,
4366           value_size + value_size + traf_size + trun_size + sample_size))
4367     goto corrupt_file;
4368
4369   g_free (stream->ra_entries);
4370   stream->ra_entries = g_new (QtDemuxRandomAccessEntry, num_entries);
4371   stream->n_ra_entries = num_entries;
4372
4373   for (i = 0; i < num_entries; i++) {
4374     qt_atom_parser_get_offset (&tfra, value_size, &time);
4375     qt_atom_parser_get_offset (&tfra, value_size, &moof_offset);
4376     qt_atom_parser_get_uint_with_size_unchecked (&tfra, traf_size);
4377     qt_atom_parser_get_uint_with_size_unchecked (&tfra, trun_size);
4378     qt_atom_parser_get_uint_with_size_unchecked (&tfra, sample_size);
4379
4380     time = QTSTREAMTIME_TO_GSTTIME (stream, time);
4381
4382     GST_LOG_OBJECT (qtdemux, "fragment time: %" GST_TIME_FORMAT ", "
4383         " moof_offset: %" G_GUINT64_FORMAT, GST_TIME_ARGS (time), moof_offset);
4384
4385     stream->ra_entries[i].ts = time;
4386     stream->ra_entries[i].moof_offset = moof_offset;
4387
4388     /* don't want to go through the entire file and read all moofs at startup */
4389 #if 0
4390     ret = gst_qtdemux_pull_atom (qtdemux, moof_offset, 0, &buf);
4391     if (ret != GST_FLOW_OK)
4392       goto corrupt_file;
4393     qtdemux_parse_moof (qtdemux, GST_BUFFER_DATA (buf), GST_BUFFER_SIZE (buf),
4394         moof_offset, stream);
4395     gst_buffer_unref (buf);
4396 #endif
4397   }
4398
4399   check_update_duration (qtdemux, time);
4400
4401   return TRUE;
4402
4403 /* ERRORS */
4404 unknown_trackid:
4405   {
4406     GST_WARNING_OBJECT (qtdemux, "Couldn't find stream for track %u", track_id);
4407     return FALSE;
4408   }
4409 corrupt_file:
4410   {
4411     GST_WARNING_OBJECT (qtdemux, "broken traf box, ignoring");
4412     return FALSE;
4413   }
4414 no_samples:
4415   {
4416     GST_WARNING_OBJECT (qtdemux, "stream has no samples");
4417     return FALSE;
4418   }
4419 }
4420
4421 static gboolean
4422 qtdemux_pull_mfro_mfra (GstQTDemux * qtdemux)
4423 {
4424   GstMapInfo mfro_map = GST_MAP_INFO_INIT;
4425   GstMapInfo mfra_map = GST_MAP_INFO_INIT;
4426   GstBuffer *mfro = NULL, *mfra = NULL;
4427   GstFlowReturn flow;
4428   gboolean ret = FALSE;
4429   GNode *mfra_node, *tfra_node;
4430   guint64 mfra_offset = 0;
4431   guint32 fourcc, mfra_size;
4432   gint64 len;
4433
4434   /* query upstream size in bytes */
4435   if (!gst_pad_peer_query_duration (qtdemux->sinkpad, GST_FORMAT_BYTES, &len))
4436     goto size_query_failed;
4437
4438   /* mfro box should be at the very end of the file */
4439   flow = gst_qtdemux_pull_atom (qtdemux, len - 16, 16, &mfro);
4440   if (flow != GST_FLOW_OK)
4441     goto exit;
4442
4443   gst_buffer_map (mfro, &mfro_map, GST_MAP_READ);
4444
4445   fourcc = QT_FOURCC (mfro_map.data + 4);
4446   if (fourcc != FOURCC_mfro)
4447     goto exit;
4448
4449   GST_INFO_OBJECT (qtdemux, "Found mfro box");
4450   if (mfro_map.size < 16)
4451     goto invalid_mfro_size;
4452
4453   mfra_size = QT_UINT32 (mfro_map.data + 12);
4454   if (mfra_size >= len)
4455     goto invalid_mfra_size;
4456
4457   mfra_offset = len - mfra_size;
4458
4459   GST_INFO_OBJECT (qtdemux, "mfra offset: %" G_GUINT64_FORMAT ", size %u",
4460       mfra_offset, mfra_size);
4461
4462   /* now get and parse mfra box */
4463   flow = gst_qtdemux_pull_atom (qtdemux, mfra_offset, mfra_size, &mfra);
4464   if (flow != GST_FLOW_OK)
4465     goto broken_file;
4466
4467   gst_buffer_map (mfra, &mfra_map, GST_MAP_READ);
4468
4469   mfra_node = g_node_new ((guint8 *) mfra_map.data);
4470   qtdemux_parse_node (qtdemux, mfra_node, mfra_map.data, mfra_map.size);
4471
4472   tfra_node = qtdemux_tree_get_child_by_type (mfra_node, FOURCC_tfra);
4473
4474   while (tfra_node) {
4475     qtdemux_parse_tfra (qtdemux, tfra_node);
4476     /* iterate all siblings */
4477     tfra_node = qtdemux_tree_get_sibling_by_type (tfra_node, FOURCC_tfra);
4478   }
4479   g_node_destroy (mfra_node);
4480
4481   GST_INFO_OBJECT (qtdemux, "parsed movie fragment random access box (mfra)");
4482   ret = TRUE;
4483
4484 exit:
4485
4486   if (mfro) {
4487     if (mfro_map.memory != NULL)
4488       gst_buffer_unmap (mfro, &mfro_map);
4489     gst_buffer_unref (mfro);
4490   }
4491   if (mfra) {
4492     if (mfra_map.memory != NULL)
4493       gst_buffer_unmap (mfra, &mfra_map);
4494     gst_buffer_unref (mfra);
4495   }
4496   return ret;
4497
4498 /* ERRORS */
4499 size_query_failed:
4500   {
4501     GST_WARNING_OBJECT (qtdemux, "could not query upstream size");
4502     goto exit;
4503   }
4504 invalid_mfro_size:
4505   {
4506     GST_WARNING_OBJECT (qtdemux, "mfro size is too small");
4507     goto exit;
4508   }
4509 invalid_mfra_size:
4510   {
4511     GST_WARNING_OBJECT (qtdemux, "mfra_size in mfro box is invalid");
4512     goto exit;
4513   }
4514 broken_file:
4515   {
4516     GST_WARNING_OBJECT (qtdemux, "bogus mfra offset or size, broken file");
4517     goto exit;
4518   }
4519 }
4520
4521 static guint64
4522 add_offset (guint64 offset, guint64 advance)
4523 {
4524   /* Avoid 64-bit overflow by clamping */
4525   if (offset > G_MAXUINT64 - advance)
4526     return G_MAXUINT64;
4527   return offset + advance;
4528 }
4529
4530 static GstFlowReturn
4531 gst_qtdemux_loop_state_header (GstQTDemux * qtdemux)
4532 {
4533   guint64 length = 0;
4534   guint32 fourcc = 0;
4535   GstBuffer *buf = NULL;
4536   GstFlowReturn ret = GST_FLOW_OK;
4537   guint64 cur_offset = qtdemux->offset;
4538   GstMapInfo map;
4539
4540   ret = gst_pad_pull_range (qtdemux->sinkpad, cur_offset, 16, &buf);
4541   if (G_UNLIKELY (ret != GST_FLOW_OK))
4542     goto beach;
4543   gst_buffer_map (buf, &map, GST_MAP_READ);
4544   if (G_LIKELY (map.size >= 8))
4545     extract_initial_length_and_fourcc (map.data, map.size, &length, &fourcc);
4546   gst_buffer_unmap (buf, &map);
4547   gst_buffer_unref (buf);
4548
4549   /* maybe we already got most we needed, so only consider this eof */
4550   if (G_UNLIKELY (length == 0)) {
4551     GST_ELEMENT_WARNING (qtdemux, STREAM, DEMUX,
4552         (_("Invalid atom size.")),
4553         ("Header atom '%" GST_FOURCC_FORMAT "' has empty length",
4554             GST_FOURCC_ARGS (fourcc)));
4555     ret = GST_FLOW_EOS;
4556     goto beach;
4557   }
4558
4559   switch (fourcc) {
4560     case FOURCC_moof:
4561       /* record for later parsing when needed */
4562       if (!qtdemux->moof_offset) {
4563         qtdemux->moof_offset = qtdemux->offset;
4564       }
4565       if (qtdemux_pull_mfro_mfra (qtdemux)) {
4566         /* FIXME */
4567       } else {
4568         qtdemux->offset += length;      /* skip moof and keep going */
4569       }
4570       if (qtdemux->got_moov) {
4571         GST_INFO_OBJECT (qtdemux, "moof header, got moov, done with headers");
4572         ret = GST_FLOW_EOS;
4573         goto beach;
4574       }
4575       break;
4576     case FOURCC_mdat:
4577     case FOURCC_free:
4578     case FOURCC_skip:
4579     case FOURCC_wide:
4580     case FOURCC_PICT:
4581     case FOURCC_pnot:
4582     {
4583       GST_LOG_OBJECT (qtdemux,
4584           "skipping atom '%" GST_FOURCC_FORMAT "' at %" G_GUINT64_FORMAT,
4585           GST_FOURCC_ARGS (fourcc), cur_offset);
4586       qtdemux->offset = add_offset (qtdemux->offset, length);
4587       break;
4588     }
4589     case FOURCC_moov:
4590     {
4591       GstBuffer *moov = NULL;
4592
4593       if (qtdemux->got_moov) {
4594         GST_DEBUG_OBJECT (qtdemux, "Skipping moov atom as we have one already");
4595         qtdemux->offset = add_offset (qtdemux->offset, length);
4596         goto beach;
4597       }
4598
4599       ret = gst_pad_pull_range (qtdemux->sinkpad, cur_offset, length, &moov);
4600       if (ret != GST_FLOW_OK)
4601         goto beach;
4602       gst_buffer_map (moov, &map, GST_MAP_READ);
4603
4604       if (length != map.size) {
4605         /* Some files have a 'moov' atom at the end of the file which contains
4606          * a terminal 'free' atom where the body of the atom is missing.
4607          * Check for, and permit, this special case.
4608          */
4609         if (map.size >= 8) {
4610           guint8 *final_data = map.data + (map.size - 8);
4611           guint32 final_length = QT_UINT32 (final_data);
4612           guint32 final_fourcc = QT_FOURCC (final_data + 4);
4613
4614           if (final_fourcc == FOURCC_free
4615               && map.size + final_length - 8 == length) {
4616             /* Ok, we've found that special case. Allocate a new buffer with
4617              * that free atom actually present. */
4618             GstBuffer *newmoov = gst_buffer_new_and_alloc (length);
4619             gst_buffer_fill (newmoov, 0, map.data, map.size);
4620             gst_buffer_memset (newmoov, map.size, 0, final_length - 8);
4621             gst_buffer_unmap (moov, &map);
4622             gst_buffer_unref (moov);
4623             moov = newmoov;
4624             gst_buffer_map (moov, &map, GST_MAP_READ);
4625           }
4626         }
4627       }
4628
4629       if (length != map.size) {
4630         GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
4631             (_("This file is incomplete and cannot be played.")),
4632             ("We got less than expected (received %" G_GSIZE_FORMAT
4633                 ", wanted %u, offset %" G_GUINT64_FORMAT ")", map.size,
4634                 (guint) length, cur_offset));
4635         gst_buffer_unmap (moov, &map);
4636         gst_buffer_unref (moov);
4637         ret = GST_FLOW_ERROR;
4638         goto beach;
4639       }
4640       qtdemux->offset += length;
4641
4642       qtdemux_parse_moov (qtdemux, map.data, length);
4643       qtdemux_node_dump (qtdemux, qtdemux->moov_node);
4644
4645       qtdemux_parse_tree (qtdemux);
4646       if (qtdemux->moov_node_compressed) {
4647         g_node_destroy (qtdemux->moov_node_compressed);
4648         g_free (qtdemux->moov_node->data);
4649       }
4650       qtdemux->moov_node_compressed = NULL;
4651       g_node_destroy (qtdemux->moov_node);
4652       qtdemux->moov_node = NULL;
4653       gst_buffer_unmap (moov, &map);
4654       gst_buffer_unref (moov);
4655       qtdemux->got_moov = TRUE;
4656
4657       break;
4658     }
4659     case FOURCC_ftyp:
4660     {
4661       GstBuffer *ftyp = NULL;
4662
4663       /* extract major brand; might come in handy for ISO vs QT issues */
4664       ret = gst_qtdemux_pull_atom (qtdemux, cur_offset, length, &ftyp);
4665       if (ret != GST_FLOW_OK)
4666         goto beach;
4667       qtdemux->offset += length;
4668       gst_buffer_map (ftyp, &map, GST_MAP_READ);
4669       qtdemux_parse_ftyp (qtdemux, map.data, map.size);
4670       gst_buffer_unmap (ftyp, &map);
4671       gst_buffer_unref (ftyp);
4672       break;
4673     }
4674     case FOURCC_uuid:
4675     {
4676       GstBuffer *uuid = NULL;
4677
4678       /* uuid are extension atoms */
4679       ret = gst_qtdemux_pull_atom (qtdemux, cur_offset, length, &uuid);
4680       if (ret != GST_FLOW_OK)
4681         goto beach;
4682       qtdemux->offset += length;
4683       gst_buffer_map (uuid, &map, GST_MAP_READ);
4684       qtdemux_parse_uuid (qtdemux, map.data, map.size);
4685       gst_buffer_unmap (uuid, &map);
4686       gst_buffer_unref (uuid);
4687       break;
4688     }
4689     case FOURCC_sidx:
4690     {
4691       GstBuffer *sidx = NULL;
4692       ret = gst_qtdemux_pull_atom (qtdemux, cur_offset, length, &sidx);
4693       if (ret != GST_FLOW_OK)
4694         goto beach;
4695       qtdemux->offset += length;
4696       gst_buffer_map (sidx, &map, GST_MAP_READ);
4697       qtdemux_parse_sidx (qtdemux, map.data, map.size);
4698       gst_buffer_unmap (sidx, &map);
4699       gst_buffer_unref (sidx);
4700       break;
4701     }
4702     default:
4703     {
4704       GstBuffer *unknown = NULL;
4705
4706       GST_LOG_OBJECT (qtdemux,
4707           "unknown %08x '%" GST_FOURCC_FORMAT "' of size %" G_GUINT64_FORMAT
4708           " at %" G_GUINT64_FORMAT, fourcc, GST_FOURCC_ARGS (fourcc), length,
4709           cur_offset);
4710       ret = gst_qtdemux_pull_atom (qtdemux, cur_offset, length, &unknown);
4711       if (ret != GST_FLOW_OK)
4712         goto beach;
4713       gst_buffer_map (unknown, &map, GST_MAP_READ);
4714       GST_MEMDUMP ("Unknown tag", map.data, map.size);
4715       gst_buffer_unmap (unknown, &map);
4716       gst_buffer_unref (unknown);
4717       qtdemux->offset += length;
4718       break;
4719     }
4720   }
4721
4722 beach:
4723   if (ret == GST_FLOW_EOS && (qtdemux->got_moov || qtdemux->media_caps)) {
4724     /* digested all data, show what we have */
4725     qtdemux_prepare_streams (qtdemux);
4726     QTDEMUX_EXPOSE_LOCK (qtdemux);
4727     ret = qtdemux_expose_streams (qtdemux);
4728     QTDEMUX_EXPOSE_UNLOCK (qtdemux);
4729
4730     qtdemux->state = QTDEMUX_STATE_MOVIE;
4731     GST_DEBUG_OBJECT (qtdemux, "switching state to STATE_MOVIE (%d)",
4732         qtdemux->state);
4733     return ret;
4734   }
4735   return ret;
4736 }
4737
4738 /* Seeks to the previous keyframe of the indexed stream and
4739  * aligns other streams with respect to the keyframe timestamp
4740  * of indexed stream. Only called in case of Reverse Playback
4741  */
4742 static GstFlowReturn
4743 gst_qtdemux_seek_to_previous_keyframe (GstQTDemux * qtdemux)
4744 {
4745   guint32 seg_idx = 0, k_index = 0;
4746   guint32 ref_seg_idx, ref_k_index;
4747   GstClockTime k_pos = 0, last_stop = 0;
4748   QtDemuxSegment *seg = NULL;
4749   QtDemuxStream *ref_str = NULL;
4750   guint64 seg_media_start_mov;  /* segment media start time in mov format */
4751   guint64 target_ts;
4752   gint i;
4753
4754   /* Now we choose an arbitrary stream, get the previous keyframe timestamp
4755    * and finally align all the other streams on that timestamp with their
4756    * respective keyframes */
4757   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
4758     QtDemuxStream *str = QTDEMUX_NTH_STREAM (qtdemux, i);
4759
4760     /* No candidate yet, take the first stream */
4761     if (!ref_str) {
4762       ref_str = str;
4763       continue;
4764     }
4765
4766     /* So that stream has a segment, we prefer video streams */
4767     if (str->subtype == FOURCC_vide) {
4768       ref_str = str;
4769       break;
4770     }
4771   }
4772
4773   if (G_UNLIKELY (!ref_str)) {
4774     GST_DEBUG_OBJECT (qtdemux, "couldn't find any stream");
4775     goto eos;
4776   }
4777
4778   if (G_UNLIKELY (!ref_str->from_sample)) {
4779     GST_DEBUG_OBJECT (qtdemux, "reached the beginning of the file");
4780     goto eos;
4781   }
4782
4783   /* So that stream has been playing from from_sample to to_sample. We will
4784    * get the timestamp of the previous sample and search for a keyframe before
4785    * that. For audio streams we do an arbitrary jump in the past (10 samples) */
4786   if (ref_str->subtype == FOURCC_vide) {
4787     k_index = gst_qtdemux_find_keyframe (qtdemux, ref_str,
4788         ref_str->from_sample - 1, FALSE);
4789   } else {
4790     if (ref_str->from_sample >= 10)
4791       k_index = ref_str->from_sample - 10;
4792     else
4793       k_index = 0;
4794   }
4795
4796   target_ts =
4797       ref_str->samples[k_index].timestamp +
4798       ref_str->samples[k_index].pts_offset;
4799
4800   /* get current segment for that stream */
4801   seg = &ref_str->segments[ref_str->segment_index];
4802   /* Use segment start in original timescale for comparisons */
4803   seg_media_start_mov = seg->trak_media_start;
4804
4805   GST_LOG_OBJECT (qtdemux, "keyframe index %u ts %" G_GUINT64_FORMAT
4806       " seg start %" G_GUINT64_FORMAT " %" GST_TIME_FORMAT "\n",
4807       k_index, target_ts, seg_media_start_mov,
4808       GST_TIME_ARGS (seg->media_start));
4809
4810   /* Crawl back through segments to find the one containing this I frame */
4811   while (target_ts < seg_media_start_mov) {
4812     GST_DEBUG_OBJECT (qtdemux,
4813         "keyframe position (sample %u) is out of segment %u " " target %"
4814         G_GUINT64_FORMAT " seg start %" G_GUINT64_FORMAT, k_index,
4815         ref_str->segment_index, target_ts, seg_media_start_mov);
4816
4817     if (G_UNLIKELY (!ref_str->segment_index)) {
4818       /* Reached first segment, let's consider it's EOS */
4819       goto eos;
4820     }
4821     ref_str->segment_index--;
4822     seg = &ref_str->segments[ref_str->segment_index];
4823     /* Use segment start in original timescale for comparisons */
4824     seg_media_start_mov = seg->trak_media_start;
4825   }
4826   /* Calculate time position of the keyframe and where we should stop */
4827   k_pos =
4828       QTSTREAMTIME_TO_GSTTIME (ref_str,
4829       target_ts - seg->trak_media_start) + seg->time;
4830   last_stop =
4831       QTSTREAMTIME_TO_GSTTIME (ref_str,
4832       ref_str->samples[ref_str->from_sample].timestamp -
4833       seg->trak_media_start) + seg->time;
4834
4835   GST_DEBUG_OBJECT (qtdemux, "preferred stream played from sample %u, "
4836       "now going to sample %u (pts %" GST_TIME_FORMAT ")", ref_str->from_sample,
4837       k_index, GST_TIME_ARGS (k_pos));
4838
4839   /* Set last_stop with the keyframe timestamp we pushed of that stream */
4840   qtdemux->segment.position = last_stop;
4841   GST_DEBUG_OBJECT (qtdemux, "last_stop now is %" GST_TIME_FORMAT,
4842       GST_TIME_ARGS (last_stop));
4843
4844   if (G_UNLIKELY (last_stop < qtdemux->segment.start)) {
4845     GST_DEBUG_OBJECT (qtdemux, "reached the beginning of segment");
4846     goto eos;
4847   }
4848
4849   ref_seg_idx = ref_str->segment_index;
4850   ref_k_index = k_index;
4851
4852   /* Align them all on this */
4853   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
4854     guint32 index = 0;
4855     GstClockTime seg_time = 0;
4856     QtDemuxStream *str = QTDEMUX_NTH_STREAM (qtdemux, i);
4857
4858     /* aligning reference stream again might lead to backing up to yet another
4859      * keyframe (due to timestamp rounding issues),
4860      * potentially putting more load on downstream; so let's try to avoid */
4861     if (str == ref_str) {
4862       seg_idx = ref_seg_idx;
4863       seg = &str->segments[seg_idx];
4864       k_index = ref_k_index;
4865       GST_DEBUG_OBJECT (qtdemux, "reference track-id %u segment %d, "
4866           "sample at index %d", str->track_id, ref_str->segment_index, k_index);
4867     } else {
4868       seg_idx = gst_qtdemux_find_segment (qtdemux, str, k_pos);
4869       GST_DEBUG_OBJECT (qtdemux,
4870           "track-id %u align segment %d for keyframe pos %" GST_TIME_FORMAT,
4871           str->track_id, seg_idx, GST_TIME_ARGS (k_pos));
4872
4873       /* get segment and time in the segment */
4874       seg = &str->segments[seg_idx];
4875       seg_time = k_pos - seg->time;
4876
4877       /* get the media time in the segment.
4878        * No adjustment for empty "filler" segments */
4879       if (seg->media_start != GST_CLOCK_TIME_NONE)
4880         seg_time += seg->media_start;
4881
4882       /* get the index of the sample with media time */
4883       index = gst_qtdemux_find_index_linear (qtdemux, str, seg_time);
4884       GST_DEBUG_OBJECT (qtdemux,
4885           "track-id %u sample for %" GST_TIME_FORMAT " at %u", str->track_id,
4886           GST_TIME_ARGS (seg_time), index);
4887
4888       /* find previous keyframe */
4889       k_index = gst_qtdemux_find_keyframe (qtdemux, str, index, FALSE);
4890     }
4891
4892     /* Remember until where we want to go */
4893     str->to_sample = str->from_sample - 1;
4894     /* Define our time position */
4895     target_ts =
4896         str->samples[k_index].timestamp + str->samples[k_index].pts_offset;
4897     str->time_position = QTSTREAMTIME_TO_GSTTIME (str, target_ts) + seg->time;
4898     if (seg->media_start != GST_CLOCK_TIME_NONE)
4899       str->time_position -= seg->media_start;
4900
4901     /* Now seek back in time */
4902     gst_qtdemux_move_stream (qtdemux, str, k_index);
4903     GST_DEBUG_OBJECT (qtdemux, "track-id %u keyframe at %u, time position %"
4904         GST_TIME_FORMAT " playing from sample %u to %u", str->track_id, k_index,
4905         GST_TIME_ARGS (str->time_position), str->from_sample, str->to_sample);
4906   }
4907
4908   return GST_FLOW_OK;
4909
4910 eos:
4911   return GST_FLOW_EOS;
4912 }
4913
4914 /*
4915  * Gets the current qt segment start, stop and position for the
4916  * given time offset. This is used in update_segment()
4917  */
4918 static void
4919 gst_qtdemux_stream_segment_get_boundaries (GstQTDemux * qtdemux,
4920     QtDemuxStream * stream, GstClockTime offset,
4921     GstClockTime * _start, GstClockTime * _stop, GstClockTime * _time)
4922 {
4923   GstClockTime seg_time;
4924   GstClockTime start, stop, time;
4925   QtDemuxSegment *segment;
4926
4927   segment = &stream->segments[stream->segment_index];
4928
4929   /* get time in this segment */
4930   seg_time = (offset - segment->time) * segment->rate;
4931
4932   GST_LOG_OBJECT (stream->pad, "seg_time %" GST_TIME_FORMAT,
4933       GST_TIME_ARGS (seg_time));
4934
4935   if (G_UNLIKELY (seg_time > segment->duration)) {
4936     GST_LOG_OBJECT (stream->pad,
4937         "seg_time > segment->duration %" GST_TIME_FORMAT,
4938         GST_TIME_ARGS (segment->duration));
4939     seg_time = segment->duration;
4940   }
4941
4942   /* qtdemux->segment.stop is in outside-time-realm, whereas
4943    * segment->media_stop is in track-time-realm.
4944    *
4945    * In order to compare the two, we need to bring segment.stop
4946    * into the track-time-realm
4947    *
4948    * FIXME - does this comment still hold? Don't see any conversion here */
4949
4950   stop = qtdemux->segment.stop;
4951   if (stop == GST_CLOCK_TIME_NONE)
4952     stop = qtdemux->segment.duration;
4953   if (stop == GST_CLOCK_TIME_NONE)
4954     stop = segment->media_stop;
4955   else
4956     stop =
4957         MIN (segment->media_stop, stop - segment->time + segment->media_start);
4958
4959   if (G_UNLIKELY (QTSEGMENT_IS_EMPTY (segment))) {
4960     start = segment->time + seg_time;
4961     time = offset;
4962     stop = start - seg_time + segment->duration;
4963   } else if (qtdemux->segment.rate >= 0) {
4964     start = MIN (segment->media_start + seg_time, stop);
4965     time = offset;
4966   } else {
4967     if (segment->media_start >= qtdemux->segment.start) {
4968       time = segment->time;
4969     } else {
4970       time = segment->time + (qtdemux->segment.start - segment->media_start);
4971     }
4972
4973     start = MAX (segment->media_start, qtdemux->segment.start);
4974     stop = MIN (segment->media_start + seg_time, stop);
4975   }
4976
4977   *_start = start;
4978   *_stop = stop;
4979   *_time = time;
4980 }
4981
4982 /*
4983  * Updates the qt segment used for the stream and pushes a new segment event
4984  * downstream on this stream's pad.
4985  */
4986 static gboolean
4987 gst_qtdemux_stream_update_segment (GstQTDemux * qtdemux, QtDemuxStream * stream,
4988     gint seg_idx, GstClockTime offset, GstClockTime * _start,
4989     GstClockTime * _stop)
4990 {
4991   QtDemuxSegment *segment;
4992   GstClockTime start = 0, stop = GST_CLOCK_TIME_NONE, time = 0;
4993   gdouble rate;
4994   GstEvent *event;
4995
4996   /* update the current segment */
4997   stream->segment_index = seg_idx;
4998
4999   /* get the segment */
5000   segment = &stream->segments[seg_idx];
5001
5002   if (G_UNLIKELY (offset < segment->time)) {
5003     GST_WARNING_OBJECT (stream->pad, "offset < segment->time %" GST_TIME_FORMAT,
5004         GST_TIME_ARGS (segment->time));
5005     return FALSE;
5006   }
5007
5008   /* segment lies beyond total indicated duration */
5009   if (G_UNLIKELY (qtdemux->segment.duration != GST_CLOCK_TIME_NONE &&
5010           segment->time > qtdemux->segment.duration)) {
5011     GST_WARNING_OBJECT (stream->pad, "file duration %" GST_TIME_FORMAT
5012         " < segment->time %" GST_TIME_FORMAT,
5013         GST_TIME_ARGS (qtdemux->segment.duration),
5014         GST_TIME_ARGS (segment->time));
5015     return FALSE;
5016   }
5017
5018   gst_qtdemux_stream_segment_get_boundaries (qtdemux, stream, offset,
5019       &start, &stop, &time);
5020
5021   GST_DEBUG_OBJECT (stream->pad, "new segment %d from %" GST_TIME_FORMAT
5022       " to %" GST_TIME_FORMAT ", time %" GST_TIME_FORMAT, seg_idx,
5023       GST_TIME_ARGS (start), GST_TIME_ARGS (stop), GST_TIME_ARGS (time));
5024
5025   /* combine global rate with that of the segment */
5026   rate = segment->rate * qtdemux->segment.rate;
5027
5028   /* Copy flags from main segment */
5029   stream->segment.flags = qtdemux->segment.flags;
5030
5031   /* update the segment values used for clipping */
5032   stream->segment.offset = qtdemux->segment.offset;
5033   stream->segment.base = qtdemux->segment.base + stream->accumulated_base;
5034   stream->segment.applied_rate = qtdemux->segment.applied_rate;
5035   stream->segment.rate = rate;
5036   stream->segment.start = start + QTSTREAMTIME_TO_GSTTIME (stream,
5037       stream->cslg_shift);
5038   stream->segment.stop = stop + QTSTREAMTIME_TO_GSTTIME (stream,
5039       stream->cslg_shift);
5040   stream->segment.time = time;
5041   stream->segment.position = stream->segment.start;
5042
5043   GST_DEBUG_OBJECT (stream->pad, "New segment: %" GST_SEGMENT_FORMAT,
5044       &stream->segment);
5045
5046   /* now prepare and send the segment */
5047   if (stream->pad) {
5048     event = gst_event_new_segment (&stream->segment);
5049     if (qtdemux->segment_seqnum != GST_SEQNUM_INVALID) {
5050       gst_event_set_seqnum (event, qtdemux->segment_seqnum);
5051     }
5052     gst_pad_push_event (stream->pad, event);
5053     /* assume we can send more data now */
5054     GST_PAD_LAST_FLOW_RETURN (stream->pad) = GST_FLOW_OK;
5055     /* clear to send tags on this pad now */
5056     gst_qtdemux_push_tags (qtdemux, stream);
5057   }
5058
5059   if (_start)
5060     *_start = start;
5061   if (_stop)
5062     *_stop = stop;
5063
5064   return TRUE;
5065 }
5066
5067 /* activate the given segment number @seg_idx of @stream at time @offset.
5068  * @offset is an absolute global position over all the segments.
5069  *
5070  * This will push out a NEWSEGMENT event with the right values and
5071  * position the stream index to the first decodable sample before
5072  * @offset.
5073  */
5074 static gboolean
5075 gst_qtdemux_activate_segment (GstQTDemux * qtdemux, QtDemuxStream * stream,
5076     guint32 seg_idx, GstClockTime offset)
5077 {
5078   QtDemuxSegment *segment;
5079   guint32 index, kf_index;
5080   GstClockTime start = 0, stop = GST_CLOCK_TIME_NONE;
5081
5082   GST_LOG_OBJECT (stream->pad, "activate segment %d, offset %" GST_TIME_FORMAT,
5083       seg_idx, GST_TIME_ARGS (offset));
5084
5085   if (!gst_qtdemux_stream_update_segment (qtdemux, stream, seg_idx, offset,
5086           &start, &stop))
5087     return FALSE;
5088
5089   segment = &stream->segments[stream->segment_index];
5090
5091   /* in the fragmented case, we pick a fragment that starts before our
5092    * desired position and rely on downstream to wait for a keyframe
5093    * (FIXME: doesn't seem to work so well with ismv and wmv, as no parser; the
5094    * tfra entries tells us which trun/sample the key unit is in, but we don't
5095    * make use of this additional information at the moment) */
5096   if (qtdemux->fragmented && !qtdemux->fragmented_seek_pending) {
5097     stream->to_sample = G_MAXUINT32;
5098     return TRUE;
5099   } else {
5100     /* well, it will be taken care of below */
5101     qtdemux->fragmented_seek_pending = FALSE;
5102     /* FIXME ideally the do_fragmented_seek can be done right here,
5103      * rather than at loop level
5104      * (which might even allow handling edit lists in a fragmented file) */
5105   }
5106
5107   /* We don't need to look for a sample in push-based */
5108   if (!qtdemux->pullbased)
5109     return TRUE;
5110
5111   /* and move to the keyframe before the indicated media time of the
5112    * segment */
5113   if (G_LIKELY (!QTSEGMENT_IS_EMPTY (segment))) {
5114     if (qtdemux->segment.rate >= 0) {
5115       index = gst_qtdemux_find_index_linear (qtdemux, stream, start);
5116       stream->to_sample = G_MAXUINT32;
5117       GST_DEBUG_OBJECT (stream->pad,
5118           "moving data pointer to %" GST_TIME_FORMAT ", index: %u, pts %"
5119           GST_TIME_FORMAT, GST_TIME_ARGS (start), index,
5120           GST_TIME_ARGS (QTSAMPLE_PTS (stream, &stream->samples[index])));
5121     } else {
5122       index = gst_qtdemux_find_index_linear (qtdemux, stream, stop);
5123       stream->to_sample = index;
5124       GST_DEBUG_OBJECT (stream->pad,
5125           "moving data pointer to %" GST_TIME_FORMAT ", index: %u, pts %"
5126           GST_TIME_FORMAT, GST_TIME_ARGS (stop), index,
5127           GST_TIME_ARGS (QTSAMPLE_PTS (stream, &stream->samples[index])));
5128     }
5129   } else {
5130     GST_DEBUG_OBJECT (stream->pad, "No need to look for keyframe, "
5131         "this is an empty segment");
5132     return TRUE;
5133   }
5134
5135   /* gst_qtdemux_parse_sample () called from gst_qtdemux_find_index_linear ()
5136    * encountered an error and printed a message so we return appropriately */
5137   if (index == -1)
5138     return FALSE;
5139
5140   /* we're at the right spot */
5141   if (index == stream->sample_index) {
5142     GST_DEBUG_OBJECT (stream->pad, "we are at the right index");
5143     return TRUE;
5144   }
5145
5146   /* find keyframe of the target index */
5147   kf_index = gst_qtdemux_find_keyframe (qtdemux, stream, index, FALSE);
5148
5149 /* *INDENT-OFF* */
5150 /* indent does stupid stuff with stream->samples[].timestamp */
5151
5152   /* if we move forwards, we don't have to go back to the previous
5153    * keyframe since we already sent that. We can also just jump to
5154    * the keyframe right before the target index if there is one. */
5155   if (index > stream->sample_index) {
5156     /* moving forwards check if we move past a keyframe */
5157     if (kf_index > stream->sample_index) {
5158       GST_DEBUG_OBJECT (stream->pad,
5159            "moving forwards to keyframe at %u (pts %" GST_TIME_FORMAT " dts %"GST_TIME_FORMAT" )", kf_index,
5160            GST_TIME_ARGS (QTSAMPLE_PTS(stream, &stream->samples[kf_index])),
5161            GST_TIME_ARGS (QTSAMPLE_DTS(stream, &stream->samples[kf_index])));
5162       gst_qtdemux_move_stream (qtdemux, stream, kf_index);
5163     } else {
5164       GST_DEBUG_OBJECT (stream->pad,
5165           "moving forwards, keyframe at %u (pts %" GST_TIME_FORMAT " dts %"GST_TIME_FORMAT" ) already sent", kf_index,
5166           GST_TIME_ARGS (QTSAMPLE_PTS (stream, &stream->samples[kf_index])),
5167           GST_TIME_ARGS (QTSAMPLE_DTS (stream, &stream->samples[kf_index])));
5168     }
5169   } else {
5170     GST_DEBUG_OBJECT (stream->pad,
5171         "moving backwards to keyframe at %u (pts %" GST_TIME_FORMAT " dts %"GST_TIME_FORMAT" )", kf_index,
5172         GST_TIME_ARGS (QTSAMPLE_PTS(stream, &stream->samples[kf_index])),
5173         GST_TIME_ARGS (QTSAMPLE_DTS(stream, &stream->samples[kf_index])));
5174     gst_qtdemux_move_stream (qtdemux, stream, kf_index);
5175   }
5176
5177 /* *INDENT-ON* */
5178
5179   return TRUE;
5180 }
5181
5182 /* prepare to get the current sample of @stream, getting essential values.
5183  *
5184  * This function will also prepare and send the segment when needed.
5185  *
5186  * Return FALSE if the stream is EOS.
5187  *
5188  * PULL-BASED
5189  */
5190 static gboolean
5191 gst_qtdemux_prepare_current_sample (GstQTDemux * qtdemux,
5192     QtDemuxStream * stream, gboolean * empty, guint64 * offset, guint * size,
5193     GstClockTime * dts, GstClockTime * pts, GstClockTime * duration,
5194     gboolean * keyframe)
5195 {
5196   QtDemuxSample *sample;
5197   GstClockTime time_position;
5198   guint32 seg_idx;
5199
5200   g_return_val_if_fail (stream != NULL, FALSE);
5201
5202   time_position = stream->time_position;
5203   if (G_UNLIKELY (time_position == GST_CLOCK_TIME_NONE))
5204     goto eos;
5205
5206   seg_idx = stream->segment_index;
5207   if (G_UNLIKELY (seg_idx == -1)) {
5208     /* find segment corresponding to time_position if we are looking
5209      * for a segment. */
5210     seg_idx = gst_qtdemux_find_segment (qtdemux, stream, time_position);
5211   }
5212
5213   /* different segment, activate it, sample_index will be set. */
5214   if (G_UNLIKELY (stream->segment_index != seg_idx))
5215     gst_qtdemux_activate_segment (qtdemux, stream, seg_idx, time_position);
5216
5217   if (G_UNLIKELY (QTSEGMENT_IS_EMPTY (&stream->
5218               segments[stream->segment_index]))) {
5219     QtDemuxSegment *seg = &stream->segments[stream->segment_index];
5220
5221     GST_LOG_OBJECT (qtdemux, "Empty segment activated,"
5222         " prepare empty sample");
5223
5224     *empty = TRUE;
5225     *pts = *dts = time_position;
5226     *duration = seg->duration - (time_position - seg->time);
5227
5228     return TRUE;
5229   }
5230
5231   *empty = FALSE;
5232
5233   if (stream->sample_index == -1)
5234     stream->sample_index = 0;
5235
5236   GST_LOG_OBJECT (qtdemux, "segment active, index = %u of %u",
5237       stream->sample_index, stream->n_samples);
5238
5239   if (G_UNLIKELY (stream->sample_index >= stream->n_samples)) {
5240     if (!qtdemux->fragmented)
5241       goto eos;
5242
5243     GST_INFO_OBJECT (qtdemux, "out of samples, trying to add more");
5244     do {
5245       GstFlowReturn flow;
5246
5247       GST_OBJECT_LOCK (qtdemux);
5248       flow = qtdemux_add_fragmented_samples (qtdemux);
5249       GST_OBJECT_UNLOCK (qtdemux);
5250
5251       if (flow != GST_FLOW_OK)
5252         goto eos;
5253     }
5254     while (stream->sample_index >= stream->n_samples);
5255   }
5256
5257   if (!qtdemux_parse_samples (qtdemux, stream, stream->sample_index)) {
5258     GST_LOG_OBJECT (qtdemux, "Parsing of index %u failed!",
5259         stream->sample_index);
5260     return FALSE;
5261   }
5262
5263   /* now get the info for the sample we're at */
5264   sample = &stream->samples[stream->sample_index];
5265
5266   *dts = QTSAMPLE_DTS (stream, sample);
5267   *pts = QTSAMPLE_PTS (stream, sample);
5268   *offset = sample->offset;
5269   *size = sample->size;
5270   *duration = QTSAMPLE_DUR_DTS (stream, sample, *dts);
5271   *keyframe = QTSAMPLE_KEYFRAME (stream, sample);
5272
5273   return TRUE;
5274
5275   /* special cases */
5276 eos:
5277   {
5278     stream->time_position = GST_CLOCK_TIME_NONE;
5279     return FALSE;
5280   }
5281 }
5282
5283 /* move to the next sample in @stream.
5284  *
5285  * Moves to the next segment when needed.
5286  */
5287 static void
5288 gst_qtdemux_advance_sample (GstQTDemux * qtdemux, QtDemuxStream * stream)
5289 {
5290   QtDemuxSample *sample;
5291   QtDemuxSegment *segment;
5292
5293   /* get current segment */
5294   segment = &stream->segments[stream->segment_index];
5295
5296   if (G_UNLIKELY (QTSEGMENT_IS_EMPTY (segment))) {
5297     GST_DEBUG_OBJECT (qtdemux, "Empty segment, no samples to advance");
5298     goto next_segment;
5299   }
5300
5301   if (G_UNLIKELY (stream->sample_index >= stream->to_sample)) {
5302     /* Mark the stream as EOS */
5303     GST_DEBUG_OBJECT (qtdemux,
5304         "reached max allowed sample %u, mark EOS", stream->to_sample);
5305     stream->time_position = GST_CLOCK_TIME_NONE;
5306     return;
5307   }
5308
5309   /* move to next sample */
5310   stream->sample_index++;
5311   stream->offset_in_sample = 0;
5312
5313   /* reached the last sample, we need the next segment */
5314   if (G_UNLIKELY (stream->sample_index >= stream->n_samples))
5315     goto next_segment;
5316
5317   if (!qtdemux_parse_samples (qtdemux, stream, stream->sample_index)) {
5318     GST_LOG_OBJECT (qtdemux, "Parsing of index %u failed!",
5319         stream->sample_index);
5320     return;
5321   }
5322
5323   /* get next sample */
5324   sample = &stream->samples[stream->sample_index];
5325
5326   /* see if we are past the segment */
5327   if (G_UNLIKELY (QTSAMPLE_DTS (stream, sample) >= segment->media_stop))
5328     goto next_segment;
5329
5330   if (QTSAMPLE_DTS (stream, sample) >= segment->media_start) {
5331     /* inside the segment, update time_position, looks very familiar to
5332      * GStreamer segments, doesn't it? */
5333     stream->time_position =
5334         QTSAMPLE_DTS (stream, sample) - segment->media_start + segment->time;
5335   } else {
5336     /* not yet in segment, time does not yet increment. This means
5337      * that we are still prerolling keyframes to the decoder so it can
5338      * decode the first sample of the segment. */
5339     stream->time_position = segment->time;
5340   }
5341   return;
5342
5343   /* move to the next segment */
5344 next_segment:
5345   {
5346     GST_DEBUG_OBJECT (qtdemux, "segment %d ended ", stream->segment_index);
5347
5348     if (stream->segment_index == stream->n_segments - 1) {
5349       /* are we at the end of the last segment, we're EOS */
5350       stream->time_position = GST_CLOCK_TIME_NONE;
5351     } else {
5352       /* else we're only at the end of the current segment */
5353       stream->time_position = segment->stop_time;
5354     }
5355     /* make sure we select a new segment */
5356
5357     /* accumulate previous segments */
5358     if (GST_CLOCK_TIME_IS_VALID (stream->segment.stop))
5359       stream->accumulated_base +=
5360           (stream->segment.stop -
5361           stream->segment.start) / ABS (stream->segment.rate);
5362
5363     stream->segment_index = -1;
5364   }
5365 }
5366
5367 static void
5368 gst_qtdemux_sync_streams (GstQTDemux * demux)
5369 {
5370   gint i;
5371
5372   if (QTDEMUX_N_STREAMS (demux) <= 1)
5373     return;
5374
5375   for (i = 0; i < QTDEMUX_N_STREAMS (demux); i++) {
5376     QtDemuxStream *stream;
5377     GstClockTime end_time;
5378
5379     stream = QTDEMUX_NTH_STREAM (demux, i);
5380
5381     if (!stream->pad)
5382       continue;
5383
5384     /* TODO advance time on subtitle streams here, if any some day */
5385
5386     /* some clips/trailers may have unbalanced streams at the end,
5387      * so send EOS on shorter stream to prevent stalling others */
5388
5389     /* do not mess with EOS if SEGMENT seeking */
5390     if (demux->segment.flags & GST_SEEK_FLAG_SEGMENT)
5391       continue;
5392
5393     if (demux->pullbased) {
5394       /* loop mode is sample time based */
5395       if (!STREAM_IS_EOS (stream))
5396         continue;
5397     } else {
5398       /* push mode is byte position based */
5399       if (stream->n_samples &&
5400           stream->samples[stream->n_samples - 1].offset >= demux->offset)
5401         continue;
5402     }
5403
5404     if (stream->sent_eos)
5405       continue;
5406
5407     /* only act if some gap */
5408     end_time = stream->segments[stream->n_segments - 1].stop_time;
5409     GST_LOG_OBJECT (demux, "current position: %" GST_TIME_FORMAT
5410         ", stream end: %" GST_TIME_FORMAT,
5411         GST_TIME_ARGS (demux->segment.position), GST_TIME_ARGS (end_time));
5412     if (GST_CLOCK_TIME_IS_VALID (end_time)
5413         && (end_time + 2 * GST_SECOND < demux->segment.position)) {
5414       GstEvent *event;
5415
5416       GST_DEBUG_OBJECT (demux, "sending EOS for stream %s",
5417           GST_PAD_NAME (stream->pad));
5418       stream->sent_eos = TRUE;
5419       event = gst_event_new_eos ();
5420       if (demux->segment_seqnum != GST_SEQNUM_INVALID)
5421         gst_event_set_seqnum (event, demux->segment_seqnum);
5422       gst_pad_push_event (stream->pad, event);
5423     }
5424   }
5425 }
5426
5427 /* EOS and NOT_LINKED need to be combined. This means that we return:
5428  *
5429  *  GST_FLOW_NOT_LINKED: when all pads NOT_LINKED.
5430  *  GST_FLOW_EOS: when all pads EOS or NOT_LINKED.
5431  */
5432 static GstFlowReturn
5433 gst_qtdemux_combine_flows (GstQTDemux * demux, QtDemuxStream * stream,
5434     GstFlowReturn ret)
5435 {
5436   GST_LOG_OBJECT (demux, "flow return: %s", gst_flow_get_name (ret));
5437
5438   if (stream->pad)
5439     ret = gst_flow_combiner_update_pad_flow (demux->flowcombiner, stream->pad,
5440         ret);
5441   else
5442     ret = gst_flow_combiner_update_flow (demux->flowcombiner, ret);
5443
5444   GST_LOG_OBJECT (demux, "combined flow return: %s", gst_flow_get_name (ret));
5445   return ret;
5446 }
5447
5448 /* the input buffer metadata must be writable. Returns NULL when the buffer is
5449  * completely clipped
5450  *
5451  * Should be used only with raw buffers */
5452 static GstBuffer *
5453 gst_qtdemux_clip_buffer (GstQTDemux * qtdemux, QtDemuxStream * stream,
5454     GstBuffer * buf)
5455 {
5456   guint64 start, stop, cstart, cstop, diff;
5457   GstClockTime pts, duration;
5458   gsize size, osize;
5459   gint num_rate, denom_rate;
5460   gint frame_size;
5461   gboolean clip_data;
5462   guint offset;
5463
5464   osize = size = gst_buffer_get_size (buf);
5465   offset = 0;
5466
5467   /* depending on the type, setup the clip parameters */
5468   if (stream->subtype == FOURCC_soun) {
5469     frame_size = CUR_STREAM (stream)->bytes_per_frame;
5470     num_rate = GST_SECOND;
5471     denom_rate = (gint) CUR_STREAM (stream)->rate;
5472     clip_data = TRUE;
5473   } else if (stream->subtype == FOURCC_vide) {
5474     frame_size = size;
5475     num_rate = CUR_STREAM (stream)->fps_n;
5476     denom_rate = CUR_STREAM (stream)->fps_d;
5477     clip_data = FALSE;
5478   } else
5479     goto wrong_type;
5480
5481   if (frame_size <= 0)
5482     goto bad_frame_size;
5483
5484   /* we can only clip if we have a valid pts */
5485   pts = GST_BUFFER_PTS (buf);
5486   if (G_UNLIKELY (!GST_CLOCK_TIME_IS_VALID (pts)))
5487     goto no_pts;
5488
5489   duration = GST_BUFFER_DURATION (buf);
5490
5491   if (G_UNLIKELY (!GST_CLOCK_TIME_IS_VALID (duration))) {
5492     duration =
5493         gst_util_uint64_scale_int (size / frame_size, num_rate, denom_rate);
5494   }
5495
5496   start = pts;
5497   stop = start + duration;
5498
5499   if (G_UNLIKELY (!gst_segment_clip (&stream->segment,
5500               GST_FORMAT_TIME, start, stop, &cstart, &cstop)))
5501     goto clipped;
5502
5503   /* see if some clipping happened */
5504   diff = cstart - start;
5505   if (diff > 0) {
5506     pts += diff;
5507     duration -= diff;
5508
5509     if (clip_data) {
5510       /* bring clipped time to samples and to bytes */
5511       diff = gst_util_uint64_scale_int (diff, denom_rate, num_rate);
5512       diff *= frame_size;
5513
5514       GST_DEBUG_OBJECT (qtdemux,
5515           "clipping start to %" GST_TIME_FORMAT " %"
5516           G_GUINT64_FORMAT " bytes", GST_TIME_ARGS (cstart), diff);
5517
5518       offset = diff;
5519       size -= diff;
5520     }
5521   }
5522   diff = stop - cstop;
5523   if (diff > 0) {
5524     duration -= diff;
5525
5526     if (clip_data) {
5527       /* bring clipped time to samples and then to bytes */
5528       diff = gst_util_uint64_scale_int (diff, denom_rate, num_rate);
5529       diff *= frame_size;
5530       GST_DEBUG_OBJECT (qtdemux,
5531           "clipping stop to %" GST_TIME_FORMAT " %" G_GUINT64_FORMAT
5532           " bytes", GST_TIME_ARGS (cstop), diff);
5533       size -= diff;
5534     }
5535   }
5536
5537   if (offset != 0 || size != osize)
5538     gst_buffer_resize (buf, offset, size);
5539
5540   GST_BUFFER_DTS (buf) = GST_CLOCK_TIME_NONE;
5541   GST_BUFFER_PTS (buf) = pts;
5542   GST_BUFFER_DURATION (buf) = duration;
5543
5544   return buf;
5545
5546   /* dropped buffer */
5547 wrong_type:
5548   {
5549     GST_DEBUG_OBJECT (qtdemux, "unknown stream type");
5550     return buf;
5551   }
5552 bad_frame_size:
5553   {
5554     GST_DEBUG_OBJECT (qtdemux, "bad frame size");
5555     return buf;
5556   }
5557 no_pts:
5558   {
5559     GST_DEBUG_OBJECT (qtdemux, "no pts on buffer");
5560     return buf;
5561   }
5562 clipped:
5563   {
5564     GST_DEBUG_OBJECT (qtdemux, "clipped buffer");
5565     gst_buffer_unref (buf);
5566     return NULL;
5567   }
5568 }
5569
5570 static GstBuffer *
5571 gst_qtdemux_align_buffer (GstQTDemux * demux,
5572     GstBuffer * buffer, gsize alignment)
5573 {
5574   GstMapInfo map;
5575
5576   gst_buffer_map (buffer, &map, GST_MAP_READ);
5577
5578   if (map.size < sizeof (guintptr)) {
5579     gst_buffer_unmap (buffer, &map);
5580     return buffer;
5581   }
5582
5583   if (((guintptr) map.data) & (alignment - 1)) {
5584     GstBuffer *new_buffer;
5585     GstAllocationParams params = { 0, alignment - 1, 0, 0, };
5586
5587     new_buffer = gst_buffer_new_allocate (NULL,
5588         gst_buffer_get_size (buffer), &params);
5589
5590     /* Copy data "by hand", so ensure alignment is kept: */
5591     gst_buffer_fill (new_buffer, 0, map.data, map.size);
5592
5593     gst_buffer_copy_into (new_buffer, buffer, GST_BUFFER_COPY_METADATA, 0, -1);
5594     GST_DEBUG_OBJECT (demux,
5595         "We want output aligned on %" G_GSIZE_FORMAT ", reallocated",
5596         alignment);
5597
5598     gst_buffer_unmap (buffer, &map);
5599     gst_buffer_unref (buffer);
5600
5601     return new_buffer;
5602   }
5603
5604   gst_buffer_unmap (buffer, &map);
5605   return buffer;
5606 }
5607
5608 static guint8 *
5609 convert_to_ccdata (const guint8 * ccpair, guint8 ccpair_size, guint field,
5610     gsize * res)
5611 {
5612   guint8 *storage;
5613   gsize i;
5614
5615   /* We are converting from pairs to triplets */
5616   *res = ccpair_size / 2 * 3;
5617   storage = g_malloc (*res);
5618   for (i = 0; i * 2 < ccpair_size; i += 1) {
5619     if (field == 1)
5620       storage[i * 3] = 0xfc;
5621     else
5622       storage[i * 3] = 0xfd;
5623     storage[i * 3 + 1] = ccpair[i * 2];
5624     storage[i * 3 + 2] = ccpair[i * 2 + 1];
5625   }
5626
5627   return storage;
5628 }
5629
5630 static guint8 *
5631 extract_cc_from_data (QtDemuxStream * stream, const guint8 * data, gsize size,
5632     gsize * cclen)
5633 {
5634   guint8 *res = NULL;
5635   guint32 atom_length, fourcc;
5636   QtDemuxStreamStsdEntry *stsd_entry;
5637
5638   GST_MEMDUMP ("caption atom", data, size);
5639
5640   /* There might be multiple atoms */
5641
5642   *cclen = 0;
5643   if (size < 8)
5644     goto invalid_cdat;
5645   atom_length = QT_UINT32 (data);
5646   fourcc = QT_FOURCC (data + 4);
5647   if (G_UNLIKELY (atom_length > size || atom_length == 8))
5648     goto invalid_cdat;
5649
5650   GST_DEBUG_OBJECT (stream->pad, "here");
5651
5652   /* Check if we have somethig compatible */
5653   stsd_entry = CUR_STREAM (stream);
5654   switch (stsd_entry->fourcc) {
5655     case FOURCC_c608:{
5656       guint8 *cdat = NULL, *cdt2 = NULL;
5657       gsize cdat_size = 0, cdt2_size = 0;
5658       /* Should be cdat or cdt2 */
5659       if (fourcc != FOURCC_cdat && fourcc != FOURCC_cdt2) {
5660         GST_WARNING_OBJECT (stream->pad,
5661             "Unknown data atom (%" GST_FOURCC_FORMAT ") for CEA608",
5662             GST_FOURCC_ARGS (fourcc));
5663         goto invalid_cdat;
5664       }
5665
5666       /* Convert to cc_data triplet */
5667       if (fourcc == FOURCC_cdat)
5668         cdat = convert_to_ccdata (data + 8, atom_length - 8, 1, &cdat_size);
5669       else
5670         cdt2 = convert_to_ccdata (data + 8, atom_length - 8, 2, &cdt2_size);
5671       GST_DEBUG_OBJECT (stream->pad, "size:%" G_GSIZE_FORMAT " atom_length:%u",
5672           size, atom_length);
5673
5674       /* Check for another atom ? */
5675       if (size > atom_length + 8) {
5676         guint32 new_atom_length = QT_UINT32 (data + atom_length);
5677         if (size >= atom_length + new_atom_length) {
5678           fourcc = QT_FOURCC (data + atom_length + 4);
5679           if (fourcc == FOURCC_cdat) {
5680             if (cdat == NULL)
5681               cdat =
5682                   convert_to_ccdata (data + atom_length + 8,
5683                   new_atom_length - 8, 1, &cdat_size);
5684             else
5685               GST_WARNING_OBJECT (stream->pad,
5686                   "Got multiple [cdat] atoms in a c608 sample. This is unsupported for now. Please file a bug");
5687           } else {
5688             if (cdt2 == NULL)
5689               cdt2 =
5690                   convert_to_ccdata (data + atom_length + 8,
5691                   new_atom_length - 8, 2, &cdt2_size);
5692             else
5693               GST_WARNING_OBJECT (stream->pad,
5694                   "Got multiple [cdt2] atoms in a c608 sample. This is unsupported for now. Please file a bug");
5695           }
5696         }
5697       }
5698
5699       *cclen = cdat_size + cdt2_size;
5700       res = g_malloc (*cclen);
5701       if (cdat_size)
5702         memcpy (res, cdat, cdat_size);
5703       if (cdt2_size)
5704         memcpy (res + cdat_size, cdt2, cdt2_size);
5705       g_free (cdat);
5706       g_free (cdt2);
5707     }
5708       break;
5709     case FOURCC_c708:
5710       if (fourcc != FOURCC_ccdp) {
5711         GST_WARNING_OBJECT (stream->pad,
5712             "Unknown data atom (%" GST_FOURCC_FORMAT ") for CEA708",
5713             GST_FOURCC_ARGS (fourcc));
5714         goto invalid_cdat;
5715       }
5716       *cclen = atom_length - 8;
5717       res = g_memdup (data + 8, *cclen);
5718       break;
5719     default:
5720       /* Keep this here in case other closed caption formats are added */
5721       g_assert_not_reached ();
5722       break;
5723   }
5724
5725   GST_MEMDUMP ("Output", res, *cclen);
5726   return res;
5727
5728   /* Errors */
5729 invalid_cdat:
5730   GST_WARNING ("[cdat] atom is too small or invalid");
5731   return NULL;
5732 }
5733
5734 /* the input buffer metadata must be writable,
5735  * but time/duration etc not yet set and need not be preserved */
5736 static GstBuffer *
5737 gst_qtdemux_process_buffer (GstQTDemux * qtdemux, QtDemuxStream * stream,
5738     GstBuffer * buf)
5739 {
5740   GstMapInfo map;
5741   guint nsize = 0;
5742   gchar *str;
5743
5744   /* not many cases for now */
5745   if (G_UNLIKELY (CUR_STREAM (stream)->fourcc == FOURCC_mp4s)) {
5746     /* send a one time dvd clut event */
5747     if (stream->pending_event && stream->pad)
5748       gst_pad_push_event (stream->pad, stream->pending_event);
5749     stream->pending_event = NULL;
5750   }
5751
5752   if (G_UNLIKELY (stream->subtype != FOURCC_text
5753           && stream->subtype != FOURCC_sbtl &&
5754           stream->subtype != FOURCC_subp && stream->subtype != FOURCC_clcp)) {
5755     return buf;
5756   }
5757
5758   gst_buffer_map (buf, &map, GST_MAP_READ);
5759
5760   /* empty buffer is sent to terminate previous subtitle */
5761   if (map.size <= 2) {
5762     gst_buffer_unmap (buf, &map);
5763     gst_buffer_unref (buf);
5764     return NULL;
5765   }
5766   if (stream->subtype == FOURCC_subp) {
5767     /* That's all the processing needed for subpictures */
5768     gst_buffer_unmap (buf, &map);
5769     return buf;
5770   }
5771
5772   if (stream->subtype == FOURCC_clcp) {
5773     guint8 *cc;
5774     gsize cclen = 0;
5775     /* For closed caption, we need to extract the information from the
5776      * [cdat],[cdt2] or [ccdp] atom */
5777     cc = extract_cc_from_data (stream, map.data, map.size, &cclen);
5778     gst_buffer_unmap (buf, &map);
5779     gst_buffer_unref (buf);
5780     if (cc) {
5781       buf = _gst_buffer_new_wrapped (cc, cclen, g_free);
5782     } else {
5783       /* Conversion failed or there's nothing */
5784       buf = NULL;
5785     }
5786     return buf;
5787   }
5788
5789   nsize = GST_READ_UINT16_BE (map.data);
5790   nsize = MIN (nsize, map.size - 2);
5791
5792   GST_LOG_OBJECT (qtdemux, "3GPP timed text subtitle: %d/%" G_GSIZE_FORMAT "",
5793       nsize, map.size);
5794
5795   /* takes care of UTF-8 validation or UTF-16 recognition,
5796    * no other encoding expected */
5797   str = gst_tag_freeform_string_to_utf8 ((gchar *) map.data + 2, nsize, NULL);
5798   gst_buffer_unmap (buf, &map);
5799   if (str) {
5800     gst_buffer_unref (buf);
5801     buf = _gst_buffer_new_wrapped (str, strlen (str), g_free);
5802   } else {
5803     /* this should not really happen unless the subtitle is corrupted */
5804     gst_buffer_unref (buf);
5805     buf = NULL;
5806   }
5807
5808   /* FIXME ? convert optional subsequent style info to markup */
5809
5810   return buf;
5811 }
5812
5813 /* Sets a buffer's attributes properly and pushes it downstream.
5814  * Also checks for additional actions and custom processing that may
5815  * need to be done first.
5816  */
5817 static GstFlowReturn
5818 gst_qtdemux_decorate_and_push_buffer (GstQTDemux * qtdemux,
5819     QtDemuxStream * stream, GstBuffer * buf,
5820     GstClockTime dts, GstClockTime pts, GstClockTime duration,
5821     gboolean keyframe, GstClockTime position, guint64 byte_position)
5822 {
5823   GstFlowReturn ret = GST_FLOW_OK;
5824
5825   /* offset the timestamps according to the edit list */
5826
5827   if (G_UNLIKELY (CUR_STREAM (stream)->fourcc == FOURCC_rtsp)) {
5828     gchar *url;
5829     GstMapInfo map;
5830
5831     gst_buffer_map (buf, &map, GST_MAP_READ);
5832     url = g_strndup ((gchar *) map.data, map.size);
5833     gst_buffer_unmap (buf, &map);
5834     if (url != NULL && strlen (url) != 0) {
5835       /* we have RTSP redirect now */
5836       gst_element_post_message (GST_ELEMENT_CAST (qtdemux),
5837           gst_message_new_element (GST_OBJECT_CAST (qtdemux),
5838               gst_structure_new ("redirect",
5839                   "new-location", G_TYPE_STRING, url, NULL)));
5840       qtdemux->posted_redirect = TRUE;
5841     } else {
5842       GST_WARNING_OBJECT (qtdemux, "Redirect URI of stream is empty, not "
5843           "posting");
5844     }
5845     g_free (url);
5846   }
5847
5848   /* position reporting */
5849   if (qtdemux->segment.rate >= 0) {
5850     qtdemux->segment.position = position;
5851     gst_qtdemux_sync_streams (qtdemux);
5852   }
5853
5854   if (G_UNLIKELY (!stream->pad)) {
5855     GST_DEBUG_OBJECT (qtdemux, "No output pad for stream, ignoring");
5856     gst_buffer_unref (buf);
5857     goto exit;
5858   }
5859
5860   /* send out pending buffers */
5861   while (stream->buffers) {
5862     GstBuffer *buffer = (GstBuffer *) stream->buffers->data;
5863
5864     if (G_UNLIKELY (stream->discont)) {
5865       GST_LOG_OBJECT (qtdemux, "marking discont buffer");
5866       GST_BUFFER_FLAG_SET (buffer, GST_BUFFER_FLAG_DISCONT);
5867       stream->discont = FALSE;
5868     } else {
5869       GST_BUFFER_FLAG_UNSET (buf, GST_BUFFER_FLAG_DISCONT);
5870     }
5871
5872     if (stream->alignment > 1)
5873       buffer = gst_qtdemux_align_buffer (qtdemux, buffer, stream->alignment);
5874     gst_pad_push (stream->pad, buffer);
5875
5876     stream->buffers = g_slist_delete_link (stream->buffers, stream->buffers);
5877   }
5878
5879   /* we're going to modify the metadata */
5880   buf = gst_buffer_make_writable (buf);
5881
5882   if (G_UNLIKELY (stream->need_process))
5883     buf = gst_qtdemux_process_buffer (qtdemux, stream, buf);
5884
5885   if (!buf) {
5886     goto exit;
5887   }
5888
5889   GST_BUFFER_DTS (buf) = dts;
5890   GST_BUFFER_PTS (buf) = pts;
5891   GST_BUFFER_DURATION (buf) = duration;
5892   GST_BUFFER_OFFSET (buf) = -1;
5893   GST_BUFFER_OFFSET_END (buf) = -1;
5894
5895   if (G_UNLIKELY (CUR_STREAM (stream)->rgb8_palette))
5896     gst_buffer_append_memory (buf,
5897         gst_memory_ref (CUR_STREAM (stream)->rgb8_palette));
5898
5899   if (G_UNLIKELY (CUR_STREAM (stream)->padding)) {
5900     gst_buffer_resize (buf, CUR_STREAM (stream)->padding, -1);
5901   }
5902 #if 0
5903   if (G_UNLIKELY (qtdemux->element_index)) {
5904     GstClockTime stream_time;
5905
5906     stream_time =
5907         gst_segment_to_stream_time (&stream->segment, GST_FORMAT_TIME,
5908         timestamp);
5909     if (GST_CLOCK_TIME_IS_VALID (stream_time)) {
5910       GST_LOG_OBJECT (qtdemux,
5911           "adding association %" GST_TIME_FORMAT "-> %"
5912           G_GUINT64_FORMAT, GST_TIME_ARGS (stream_time), byte_position);
5913       gst_index_add_association (qtdemux->element_index,
5914           qtdemux->index_id,
5915           keyframe ? GST_ASSOCIATION_FLAG_KEY_UNIT :
5916           GST_ASSOCIATION_FLAG_DELTA_UNIT, GST_FORMAT_TIME, stream_time,
5917           GST_FORMAT_BYTES, byte_position, NULL);
5918     }
5919   }
5920 #endif
5921
5922   if (stream->need_clip)
5923     buf = gst_qtdemux_clip_buffer (qtdemux, stream, buf);
5924
5925   if (G_UNLIKELY (buf == NULL))
5926     goto exit;
5927
5928   if (G_UNLIKELY (stream->discont)) {
5929     GST_LOG_OBJECT (qtdemux, "marking discont buffer");
5930     GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_DISCONT);
5931     stream->discont = FALSE;
5932   } else {
5933     GST_BUFFER_FLAG_UNSET (buf, GST_BUFFER_FLAG_DISCONT);
5934   }
5935
5936   if (!keyframe) {
5937     GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_DELTA_UNIT);
5938     stream->on_keyframe = FALSE;
5939   } else {
5940     stream->on_keyframe = TRUE;
5941   }
5942
5943
5944   GST_LOG_OBJECT (qtdemux,
5945       "Pushing buffer with dts %" GST_TIME_FORMAT ", pts %" GST_TIME_FORMAT
5946       ", duration %" GST_TIME_FORMAT " on pad %s", GST_TIME_ARGS (dts),
5947       GST_TIME_ARGS (pts), GST_TIME_ARGS (duration),
5948       GST_PAD_NAME (stream->pad));
5949
5950   if (stream->protected && stream->protection_scheme_type == FOURCC_cenc) {
5951     GstStructure *crypto_info;
5952     QtDemuxCencSampleSetInfo *info =
5953         (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
5954     gint index;
5955     GstEvent *event;
5956
5957     while ((event = g_queue_pop_head (&stream->protection_scheme_event_queue))) {
5958       GST_TRACE_OBJECT (stream->pad, "pushing protection event: %"
5959           GST_PTR_FORMAT, event);
5960       gst_pad_push_event (stream->pad, event);
5961     }
5962
5963     if (info->crypto_info == NULL) {
5964       GST_DEBUG_OBJECT (qtdemux,
5965           "cenc metadata hasn't been parsed yet, pushing buffer as if it wasn't encrypted");
5966     } else {
5967       /* The end of the crypto_info array matches our n_samples position,
5968        * so count backward from there */
5969       index = stream->sample_index - stream->n_samples + info->crypto_info->len;
5970       if (G_LIKELY (index >= 0 && index < info->crypto_info->len)) {
5971         /* steal structure from array */
5972         crypto_info = g_ptr_array_index (info->crypto_info, index);
5973         g_ptr_array_index (info->crypto_info, index) = NULL;
5974         GST_LOG_OBJECT (qtdemux, "attaching cenc metadata [%u/%u]", index,
5975             info->crypto_info->len);
5976         if (!crypto_info || !gst_buffer_add_protection_meta (buf, crypto_info))
5977           GST_ERROR_OBJECT (qtdemux,
5978               "failed to attach cenc metadata to buffer");
5979       } else {
5980         GST_INFO_OBJECT (qtdemux, "No crypto info with index %d and sample %d",
5981             index, stream->sample_index);
5982       }
5983     }
5984   }
5985
5986   if (stream->alignment > 1)
5987     buf = gst_qtdemux_align_buffer (qtdemux, buf, stream->alignment);
5988
5989   ret = gst_pad_push (stream->pad, buf);
5990
5991   if (GST_CLOCK_TIME_IS_VALID (pts) && GST_CLOCK_TIME_IS_VALID (duration)) {
5992     /* mark position in stream, we'll need this to know when to send GAP event */
5993     stream->segment.position = pts + duration;
5994   }
5995
5996 exit:
5997   return ret;
5998 }
5999
6000 static const QtDemuxRandomAccessEntry *
6001 gst_qtdemux_stream_seek_fragment (GstQTDemux * qtdemux, QtDemuxStream * stream,
6002     GstClockTime pos, gboolean after)
6003 {
6004   QtDemuxRandomAccessEntry *entries = stream->ra_entries;
6005   guint n_entries = stream->n_ra_entries;
6006   guint i;
6007
6008   /* we assume the table is sorted */
6009   for (i = 0; i < n_entries; ++i) {
6010     if (entries[i].ts > pos)
6011       break;
6012   }
6013
6014   /* FIXME: maybe save first moof_offset somewhere instead, but for now it's
6015    * probably okay to assume that the index lists the very first fragment */
6016   if (i == 0)
6017     return &entries[0];
6018
6019   if (after)
6020     return &entries[i];
6021   else
6022     return &entries[i - 1];
6023 }
6024
6025 static gboolean
6026 gst_qtdemux_do_fragmented_seek (GstQTDemux * qtdemux)
6027 {
6028   const QtDemuxRandomAccessEntry *best_entry = NULL;
6029   gint i;
6030
6031   GST_OBJECT_LOCK (qtdemux);
6032
6033   g_assert (QTDEMUX_N_STREAMS (qtdemux) > 0);
6034
6035   /* first see if we can determine where to go to using mfra,
6036    * before we start clearing things */
6037   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
6038     const QtDemuxRandomAccessEntry *entry;
6039     QtDemuxStream *stream;
6040     gboolean is_audio_or_video;
6041
6042     stream = QTDEMUX_NTH_STREAM (qtdemux, i);
6043
6044     if (stream->ra_entries == NULL)
6045       continue;
6046
6047     if (stream->subtype == FOURCC_vide || stream->subtype == FOURCC_soun)
6048       is_audio_or_video = TRUE;
6049     else
6050       is_audio_or_video = FALSE;
6051
6052     entry =
6053         gst_qtdemux_stream_seek_fragment (qtdemux, stream,
6054         stream->time_position, !is_audio_or_video);
6055
6056     GST_INFO_OBJECT (stream->pad, "%" GST_TIME_FORMAT " at offset "
6057         "%" G_GUINT64_FORMAT, GST_TIME_ARGS (entry->ts), entry->moof_offset);
6058
6059     stream->pending_seek = entry;
6060
6061     /* decide position to jump to just based on audio/video tracks, not subs */
6062     if (!is_audio_or_video)
6063       continue;
6064
6065     if (best_entry == NULL || entry->moof_offset < best_entry->moof_offset)
6066       best_entry = entry;
6067   }
6068
6069   /* no luck, will handle seek otherwise */
6070   if (best_entry == NULL) {
6071     GST_OBJECT_UNLOCK (qtdemux);
6072     return FALSE;
6073   }
6074
6075   /* ok, now we can prepare for processing as of located moof */
6076   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
6077     QtDemuxStream *stream;
6078
6079     stream = QTDEMUX_NTH_STREAM (qtdemux, i);
6080
6081     g_free (stream->samples);
6082     stream->samples = NULL;
6083     stream->n_samples = 0;
6084     stream->stbl_index = -1;    /* no samples have yet been parsed */
6085     stream->sample_index = -1;
6086
6087     if (stream->protection_scheme_info) {
6088       /* Clear out any old cenc crypto info entries as we'll move to a new moof */
6089       if (stream->protection_scheme_type == FOURCC_cenc) {
6090         QtDemuxCencSampleSetInfo *info =
6091             (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
6092         if (info->crypto_info) {
6093           g_ptr_array_free (info->crypto_info, TRUE);
6094           info->crypto_info = NULL;
6095         }
6096       }
6097     }
6098   }
6099
6100   GST_INFO_OBJECT (qtdemux, "seek to %" GST_TIME_FORMAT ", best fragment "
6101       "moof offset: %" G_GUINT64_FORMAT ", ts %" GST_TIME_FORMAT,
6102       GST_TIME_ARGS (QTDEMUX_NTH_STREAM (qtdemux, 0)->time_position),
6103       best_entry->moof_offset, GST_TIME_ARGS (best_entry->ts));
6104
6105   qtdemux->moof_offset = best_entry->moof_offset;
6106
6107   qtdemux_add_fragmented_samples (qtdemux);
6108
6109   GST_OBJECT_UNLOCK (qtdemux);
6110   return TRUE;
6111 }
6112
6113 static GstFlowReturn
6114 gst_qtdemux_loop_state_movie (GstQTDemux * qtdemux)
6115 {
6116   GstFlowReturn ret = GST_FLOW_OK;
6117   GstBuffer *buf = NULL;
6118   QtDemuxStream *stream, *target_stream = NULL;
6119   GstClockTime min_time;
6120   guint64 offset = 0;
6121   GstClockTime dts = GST_CLOCK_TIME_NONE;
6122   GstClockTime pts = GST_CLOCK_TIME_NONE;
6123   GstClockTime duration = 0;
6124   gboolean keyframe = FALSE;
6125   guint sample_size = 0;
6126   gboolean empty = 0;
6127   guint size;
6128   gint i;
6129
6130   if (qtdemux->fragmented_seek_pending) {
6131     GST_INFO_OBJECT (qtdemux, "pending fragmented seek");
6132     if (gst_qtdemux_do_fragmented_seek (qtdemux)) {
6133       GST_INFO_OBJECT (qtdemux, "fragmented seek done!");
6134       qtdemux->fragmented_seek_pending = FALSE;
6135     } else {
6136       GST_INFO_OBJECT (qtdemux, "fragmented seek still pending");
6137     }
6138   }
6139
6140   /* Figure out the next stream sample to output, min_time is expressed in
6141    * global time and runs over the edit list segments. */
6142   min_time = G_MAXUINT64;
6143   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
6144     GstClockTime position;
6145
6146     stream = QTDEMUX_NTH_STREAM (qtdemux, i);
6147     position = stream->time_position;
6148
6149     /* position of -1 is EOS */
6150     if (position != GST_CLOCK_TIME_NONE && position < min_time) {
6151       min_time = position;
6152       target_stream = stream;
6153     }
6154   }
6155   /* all are EOS */
6156   if (G_UNLIKELY (target_stream == NULL)) {
6157     GST_DEBUG_OBJECT (qtdemux, "all streams are EOS");
6158     goto eos;
6159   }
6160
6161   /* check for segment end */
6162   if (G_UNLIKELY (qtdemux->segment.stop != -1
6163           && ((qtdemux->segment.rate >= 0 && qtdemux->segment.stop <= min_time)
6164               || (qtdemux->segment.rate < 0
6165                   && qtdemux->segment.start > min_time))
6166           && target_stream->on_keyframe)) {
6167     GST_DEBUG_OBJECT (qtdemux, "we reached the end of our segment.");
6168     target_stream->time_position = GST_CLOCK_TIME_NONE;
6169     goto eos_stream;
6170   }
6171
6172   /* gap events for subtitle streams */
6173   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
6174     stream = QTDEMUX_NTH_STREAM (qtdemux, i);
6175     if (stream->pad && (stream->subtype == FOURCC_subp
6176             || stream->subtype == FOURCC_text
6177             || stream->subtype == FOURCC_sbtl)) {
6178       /* send one second gap events until the stream catches up */
6179       /* gaps can only be sent after segment is activated (segment.stop is no longer -1) */
6180       while (GST_CLOCK_TIME_IS_VALID (stream->segment.stop) &&
6181           GST_CLOCK_TIME_IS_VALID (stream->segment.position) &&
6182           stream->segment.position + GST_SECOND < min_time) {
6183         GstEvent *gap =
6184             gst_event_new_gap (stream->segment.position, GST_SECOND);
6185         gst_pad_push_event (stream->pad, gap);
6186         stream->segment.position += GST_SECOND;
6187       }
6188     }
6189   }
6190
6191   stream = target_stream;
6192   /* fetch info for the current sample of this stream */
6193   if (G_UNLIKELY (!gst_qtdemux_prepare_current_sample (qtdemux, stream, &empty,
6194               &offset, &sample_size, &dts, &pts, &duration, &keyframe)))
6195     goto eos_stream;
6196
6197   gst_qtdemux_stream_check_and_change_stsd_index (qtdemux, stream);
6198   if (stream->new_caps) {
6199     gst_qtdemux_configure_stream (qtdemux, stream);
6200     qtdemux_do_allocation (stream, qtdemux);
6201   }
6202
6203   /* If we're doing a keyframe-only trickmode, only push keyframes on video streams */
6204   if (G_UNLIKELY (qtdemux->segment.
6205           flags & GST_SEGMENT_FLAG_TRICKMODE_KEY_UNITS)) {
6206     if (stream->subtype == FOURCC_vide && !keyframe) {
6207       GST_LOG_OBJECT (qtdemux, "Skipping non-keyframe on track-id %u",
6208           stream->track_id);
6209       goto next;
6210     }
6211   }
6212
6213   GST_DEBUG_OBJECT (qtdemux,
6214       "pushing from track-id %u, empty %d offset %" G_GUINT64_FORMAT
6215       ", size %d, dts=%" GST_TIME_FORMAT ", pts=%" GST_TIME_FORMAT
6216       ", duration %" GST_TIME_FORMAT, stream->track_id, empty, offset,
6217       sample_size, GST_TIME_ARGS (dts), GST_TIME_ARGS (pts),
6218       GST_TIME_ARGS (duration));
6219
6220   if (G_UNLIKELY (empty)) {
6221     /* empty segment, push a gap if there's a second or more
6222      * difference and move to the next one */
6223     if ((pts + duration - stream->segment.position) >= GST_SECOND)
6224       gst_pad_push_event (stream->pad, gst_event_new_gap (pts, duration));
6225     stream->segment.position = pts + duration;
6226     goto next;
6227   }
6228
6229   /* hmm, empty sample, skip and move to next sample */
6230   if (G_UNLIKELY (sample_size <= 0))
6231     goto next;
6232
6233   /* last pushed sample was out of boundary, goto next sample */
6234   if (G_UNLIKELY (GST_PAD_LAST_FLOW_RETURN (stream->pad) == GST_FLOW_EOS))
6235     goto next;
6236
6237   if (stream->max_buffer_size == 0 || sample_size <= stream->max_buffer_size) {
6238     size = sample_size;
6239   } else {
6240     GST_DEBUG_OBJECT (qtdemux,
6241         "size %d larger than stream max_buffer_size %d, trimming",
6242         sample_size, stream->max_buffer_size);
6243     size =
6244         MIN (sample_size - stream->offset_in_sample, stream->max_buffer_size);
6245   }
6246
6247   if (qtdemux->cenc_aux_info_offset > 0) {
6248     GstMapInfo map;
6249     GstByteReader br;
6250     GstBuffer *aux_info = NULL;
6251
6252     /* pull the data stored before the sample */
6253     ret =
6254         gst_qtdemux_pull_atom (qtdemux, qtdemux->offset,
6255         offset + stream->offset_in_sample - qtdemux->offset, &aux_info);
6256     if (G_UNLIKELY (ret != GST_FLOW_OK))
6257       goto beach;
6258     gst_buffer_map (aux_info, &map, GST_MAP_READ);
6259     GST_DEBUG_OBJECT (qtdemux, "parsing cenc auxiliary info");
6260     gst_byte_reader_init (&br, map.data + 8, map.size);
6261     if (!qtdemux_parse_cenc_aux_info (qtdemux, stream, &br,
6262             qtdemux->cenc_aux_info_sizes, qtdemux->cenc_aux_sample_count)) {
6263       GST_ERROR_OBJECT (qtdemux, "failed to parse cenc auxiliary info");
6264       gst_buffer_unmap (aux_info, &map);
6265       gst_buffer_unref (aux_info);
6266       ret = GST_FLOW_ERROR;
6267       goto beach;
6268     }
6269     gst_buffer_unmap (aux_info, &map);
6270     gst_buffer_unref (aux_info);
6271   }
6272
6273   GST_LOG_OBJECT (qtdemux, "reading %d bytes @ %" G_GUINT64_FORMAT, size,
6274       offset);
6275
6276   if (stream->use_allocator) {
6277     /* if we have a per-stream allocator, use it */
6278     buf = gst_buffer_new_allocate (stream->allocator, size, &stream->params);
6279   }
6280
6281   ret = gst_qtdemux_pull_atom (qtdemux, offset + stream->offset_in_sample,
6282       size, &buf);
6283   if (G_UNLIKELY (ret != GST_FLOW_OK))
6284     goto beach;
6285
6286   if (size != sample_size) {
6287     pts += gst_util_uint64_scale_int (GST_SECOND,
6288         stream->offset_in_sample / CUR_STREAM (stream)->bytes_per_frame,
6289         stream->timescale);
6290     dts +=
6291         gst_util_uint64_scale_int (GST_SECOND,
6292         stream->offset_in_sample / CUR_STREAM (stream)->bytes_per_frame,
6293         stream->timescale);
6294     duration =
6295         gst_util_uint64_scale_int (GST_SECOND,
6296         size / CUR_STREAM (stream)->bytes_per_frame, stream->timescale);
6297   }
6298
6299   ret = gst_qtdemux_decorate_and_push_buffer (qtdemux, stream, buf,
6300       dts, pts, duration, keyframe, min_time, offset);
6301
6302   if (size != sample_size) {
6303     QtDemuxSample *sample = &stream->samples[stream->sample_index];
6304     QtDemuxSegment *segment = &stream->segments[stream->segment_index];
6305
6306     GstClockTime time_position = QTSTREAMTIME_TO_GSTTIME (stream,
6307         sample->timestamp +
6308         stream->offset_in_sample / CUR_STREAM (stream)->bytes_per_frame);
6309     if (time_position >= segment->media_start) {
6310       /* inside the segment, update time_position, looks very familiar to
6311        * GStreamer segments, doesn't it? */
6312       stream->time_position = (time_position - segment->media_start) +
6313           segment->time;
6314     } else {
6315       /* not yet in segment, time does not yet increment. This means
6316        * that we are still prerolling keyframes to the decoder so it can
6317        * decode the first sample of the segment. */
6318       stream->time_position = segment->time;
6319     }
6320   }
6321
6322   /* combine flows */
6323   ret = gst_qtdemux_combine_flows (qtdemux, stream, ret);
6324   /* ignore unlinked, we will not push on the pad anymore and we will EOS when
6325    * we have no more data for the pad to push */
6326   if (ret == GST_FLOW_EOS)
6327     ret = GST_FLOW_OK;
6328
6329   stream->offset_in_sample += size;
6330   if (stream->offset_in_sample >= sample_size) {
6331     gst_qtdemux_advance_sample (qtdemux, stream);
6332   }
6333   goto beach;
6334
6335 next:
6336   gst_qtdemux_advance_sample (qtdemux, stream);
6337
6338 beach:
6339   return ret;
6340
6341   /* special cases */
6342 eos:
6343   {
6344     GST_DEBUG_OBJECT (qtdemux, "No samples left for any streams - EOS");
6345     ret = GST_FLOW_EOS;
6346     goto beach;
6347   }
6348 eos_stream:
6349   {
6350     GST_DEBUG_OBJECT (qtdemux, "No samples left for stream");
6351     /* EOS will be raised if all are EOS */
6352     ret = GST_FLOW_OK;
6353     goto beach;
6354   }
6355 }
6356
6357 static void
6358 gst_qtdemux_loop (GstPad * pad)
6359 {
6360   GstQTDemux *qtdemux;
6361   guint64 cur_offset;
6362   GstFlowReturn ret;
6363
6364   qtdemux = GST_QTDEMUX (gst_pad_get_parent (pad));
6365
6366   cur_offset = qtdemux->offset;
6367   GST_LOG_OBJECT (qtdemux, "loop at position %" G_GUINT64_FORMAT ", state %s",
6368       cur_offset, qt_demux_state_string (qtdemux->state));
6369
6370   switch (qtdemux->state) {
6371     case QTDEMUX_STATE_INITIAL:
6372     case QTDEMUX_STATE_HEADER:
6373       ret = gst_qtdemux_loop_state_header (qtdemux);
6374       break;
6375     case QTDEMUX_STATE_MOVIE:
6376       ret = gst_qtdemux_loop_state_movie (qtdemux);
6377       if (qtdemux->segment.rate < 0 && ret == GST_FLOW_EOS) {
6378         ret = gst_qtdemux_seek_to_previous_keyframe (qtdemux);
6379       }
6380       break;
6381     default:
6382       /* ouch */
6383       goto invalid_state;
6384   }
6385
6386   /* if something went wrong, pause */
6387   if (ret != GST_FLOW_OK)
6388     goto pause;
6389
6390 done:
6391   gst_object_unref (qtdemux);
6392   return;
6393
6394   /* ERRORS */
6395 invalid_state:
6396   {
6397     GST_ELEMENT_ERROR (qtdemux, STREAM, FAILED,
6398         (NULL), ("streaming stopped, invalid state"));
6399     gst_pad_pause_task (pad);
6400     gst_qtdemux_push_event (qtdemux, gst_event_new_eos ());
6401     goto done;
6402   }
6403 pause:
6404   {
6405     const gchar *reason = gst_flow_get_name (ret);
6406
6407     GST_LOG_OBJECT (qtdemux, "pausing task, reason %s", reason);
6408
6409     gst_pad_pause_task (pad);
6410
6411     /* fatal errors need special actions */
6412     /* check EOS */
6413     if (ret == GST_FLOW_EOS) {
6414       if (QTDEMUX_N_STREAMS (qtdemux) == 0) {
6415         /* we have no streams, post an error */
6416         gst_qtdemux_post_no_playable_stream_error (qtdemux);
6417       }
6418       if (qtdemux->segment.flags & GST_SEEK_FLAG_SEGMENT) {
6419         gint64 stop;
6420
6421         if ((stop = qtdemux->segment.stop) == -1)
6422           stop = qtdemux->segment.duration;
6423
6424         if (qtdemux->segment.rate >= 0) {
6425           GstMessage *message;
6426           GstEvent *event;
6427
6428           GST_LOG_OBJECT (qtdemux, "Sending segment done, at end of segment");
6429           message = gst_message_new_segment_done (GST_OBJECT_CAST (qtdemux),
6430               GST_FORMAT_TIME, stop);
6431           event = gst_event_new_segment_done (GST_FORMAT_TIME, stop);
6432           if (qtdemux->segment_seqnum != GST_SEQNUM_INVALID) {
6433             gst_message_set_seqnum (message, qtdemux->segment_seqnum);
6434             gst_event_set_seqnum (event, qtdemux->segment_seqnum);
6435           }
6436           gst_element_post_message (GST_ELEMENT_CAST (qtdemux), message);
6437           gst_qtdemux_push_event (qtdemux, event);
6438         } else {
6439           GstMessage *message;
6440           GstEvent *event;
6441
6442           /*  For Reverse Playback */
6443           GST_LOG_OBJECT (qtdemux, "Sending segment done, at start of segment");
6444           message = gst_message_new_segment_done (GST_OBJECT_CAST (qtdemux),
6445               GST_FORMAT_TIME, qtdemux->segment.start);
6446           event = gst_event_new_segment_done (GST_FORMAT_TIME,
6447               qtdemux->segment.start);
6448           if (qtdemux->segment_seqnum != GST_SEQNUM_INVALID) {
6449             gst_message_set_seqnum (message, qtdemux->segment_seqnum);
6450             gst_event_set_seqnum (event, qtdemux->segment_seqnum);
6451           }
6452           gst_element_post_message (GST_ELEMENT_CAST (qtdemux), message);
6453           gst_qtdemux_push_event (qtdemux, event);
6454         }
6455       } else {
6456         GstEvent *event;
6457
6458         GST_LOG_OBJECT (qtdemux, "Sending EOS at end of segment");
6459         event = gst_event_new_eos ();
6460         if (qtdemux->segment_seqnum != GST_SEQNUM_INVALID)
6461           gst_event_set_seqnum (event, qtdemux->segment_seqnum);
6462         gst_qtdemux_push_event (qtdemux, event);
6463       }
6464     } else if (ret == GST_FLOW_NOT_LINKED || ret < GST_FLOW_EOS) {
6465       GST_ELEMENT_FLOW_ERROR (qtdemux, ret);
6466       gst_qtdemux_push_event (qtdemux, gst_event_new_eos ());
6467     }
6468     goto done;
6469   }
6470 }
6471
6472 /*
6473  * has_next_entry
6474  *
6475  * Returns if there are samples to be played.
6476  */
6477 static gboolean
6478 has_next_entry (GstQTDemux * demux)
6479 {
6480   QtDemuxStream *stream;
6481   gint i;
6482
6483   GST_DEBUG_OBJECT (demux, "Checking if there are samples not played yet");
6484
6485   for (i = 0; i < QTDEMUX_N_STREAMS (demux); i++) {
6486     stream = QTDEMUX_NTH_STREAM (demux, i);
6487
6488     if (stream->sample_index == -1) {
6489       stream->sample_index = 0;
6490       stream->offset_in_sample = 0;
6491     }
6492
6493     if (stream->sample_index >= stream->n_samples) {
6494       GST_LOG_OBJECT (demux, "track-id %u samples exhausted", stream->track_id);
6495       continue;
6496     }
6497     GST_DEBUG_OBJECT (demux, "Found a sample");
6498     return TRUE;
6499   }
6500
6501   GST_DEBUG_OBJECT (demux, "There wasn't any next sample");
6502   return FALSE;
6503 }
6504
6505 /*
6506  * next_entry_size
6507  *
6508  * Returns the size of the first entry at the current offset.
6509  * If -1, there are none (which means EOS or empty file).
6510  */
6511 static guint64
6512 next_entry_size (GstQTDemux * demux)
6513 {
6514   QtDemuxStream *stream, *target_stream = NULL;
6515   guint64 smalloffs = (guint64) - 1;
6516   QtDemuxSample *sample;
6517   gint i;
6518
6519   GST_LOG_OBJECT (demux, "Finding entry at offset %" G_GUINT64_FORMAT,
6520       demux->offset);
6521
6522   for (i = 0; i < QTDEMUX_N_STREAMS (demux); i++) {
6523     stream = QTDEMUX_NTH_STREAM (demux, i);
6524
6525     if (stream->sample_index == -1) {
6526       stream->sample_index = 0;
6527       stream->offset_in_sample = 0;
6528     }
6529
6530     if (stream->sample_index >= stream->n_samples) {
6531       GST_LOG_OBJECT (demux, "track-id %u samples exhausted", stream->track_id);
6532       continue;
6533     }
6534
6535     if (!qtdemux_parse_samples (demux, stream, stream->sample_index)) {
6536       GST_LOG_OBJECT (demux, "Parsing of index %u from stbl atom failed!",
6537           stream->sample_index);
6538       return -1;
6539     }
6540
6541     sample = &stream->samples[stream->sample_index];
6542
6543     GST_LOG_OBJECT (demux,
6544         "Checking track-id %u (sample_index:%d / offset:%" G_GUINT64_FORMAT
6545         " / size:%" G_GUINT32_FORMAT ")", stream->track_id,
6546         stream->sample_index, sample->offset, sample->size);
6547
6548     if (((smalloffs == -1)
6549             || (sample->offset < smalloffs)) && (sample->size)) {
6550       smalloffs = sample->offset;
6551       target_stream = stream;
6552     }
6553   }
6554
6555   if (!target_stream)
6556     return -1;
6557
6558   GST_LOG_OBJECT (demux,
6559       "track-id %u offset %" G_GUINT64_FORMAT " demux->offset :%"
6560       G_GUINT64_FORMAT, target_stream->track_id, smalloffs, demux->offset);
6561
6562   stream = target_stream;
6563   sample = &stream->samples[stream->sample_index];
6564
6565   if (sample->offset >= demux->offset) {
6566     demux->todrop = sample->offset - demux->offset;
6567     return sample->size + demux->todrop;
6568   }
6569
6570   GST_DEBUG_OBJECT (demux,
6571       "There wasn't any entry at offset %" G_GUINT64_FORMAT, demux->offset);
6572   return -1;
6573 }
6574
6575 static void
6576 gst_qtdemux_post_progress (GstQTDemux * demux, gint num, gint denom)
6577 {
6578   gint perc = (gint) ((gdouble) num * 100.0 / (gdouble) denom);
6579
6580   gst_element_post_message (GST_ELEMENT_CAST (demux),
6581       gst_message_new_element (GST_OBJECT_CAST (demux),
6582           gst_structure_new ("progress", "percent", G_TYPE_INT, perc, NULL)));
6583 }
6584
6585 static gboolean
6586 qtdemux_seek_offset (GstQTDemux * demux, guint64 offset)
6587 {
6588   GstEvent *event;
6589   gboolean res = 0;
6590
6591   GST_DEBUG_OBJECT (demux, "Seeking to %" G_GUINT64_FORMAT, offset);
6592
6593   event =
6594       gst_event_new_seek (1.0, GST_FORMAT_BYTES,
6595       GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_ACCURATE, GST_SEEK_TYPE_SET, offset,
6596       GST_SEEK_TYPE_NONE, -1);
6597
6598   /* store seqnum to drop flush events, they don't need to reach downstream */
6599   demux->offset_seek_seqnum = gst_event_get_seqnum (event);
6600   res = gst_pad_push_event (demux->sinkpad, event);
6601   demux->offset_seek_seqnum = GST_SEQNUM_INVALID;
6602
6603   return res;
6604 }
6605
6606 /* check for seekable upstream, above and beyond a mere query */
6607 static void
6608 gst_qtdemux_check_seekability (GstQTDemux * demux)
6609 {
6610   GstQuery *query;
6611   gboolean seekable = FALSE;
6612   gint64 start = -1, stop = -1;
6613
6614   if (demux->upstream_size)
6615     return;
6616
6617   if (demux->upstream_format_is_time)
6618     return;
6619
6620   query = gst_query_new_seeking (GST_FORMAT_BYTES);
6621   if (!gst_pad_peer_query (demux->sinkpad, query)) {
6622     GST_DEBUG_OBJECT (demux, "seeking query failed");
6623     goto done;
6624   }
6625
6626   gst_query_parse_seeking (query, NULL, &seekable, &start, &stop);
6627
6628   /* try harder to query upstream size if we didn't get it the first time */
6629   if (seekable && stop == -1) {
6630     GST_DEBUG_OBJECT (demux, "doing duration query to fix up unset stop");
6631     gst_pad_peer_query_duration (demux->sinkpad, GST_FORMAT_BYTES, &stop);
6632   }
6633
6634   /* if upstream doesn't know the size, it's likely that it's not seekable in
6635    * practice even if it technically may be seekable */
6636   if (seekable && (start != 0 || stop <= start)) {
6637     GST_DEBUG_OBJECT (demux, "seekable but unknown start/stop -> disable");
6638     seekable = FALSE;
6639   }
6640
6641 done:
6642   gst_query_unref (query);
6643
6644   GST_DEBUG_OBJECT (demux, "seekable: %d (%" G_GUINT64_FORMAT " - %"
6645       G_GUINT64_FORMAT ")", seekable, start, stop);
6646   demux->upstream_seekable = seekable;
6647   demux->upstream_size = seekable ? stop : -1;
6648 }
6649
6650 static void
6651 gst_qtdemux_drop_data (GstQTDemux * demux, gint bytes)
6652 {
6653   g_return_if_fail (bytes <= demux->todrop);
6654
6655   GST_LOG_OBJECT (demux, "Dropping %d bytes", bytes);
6656   gst_adapter_flush (demux->adapter, bytes);
6657   demux->neededbytes -= bytes;
6658   demux->offset += bytes;
6659   demux->todrop -= bytes;
6660 }
6661
6662 /* PUSH-MODE only: Send a segment, if not done already. */
6663 static void
6664 gst_qtdemux_check_send_pending_segment (GstQTDemux * demux)
6665 {
6666   if (G_UNLIKELY (demux->need_segment)) {
6667     gint i;
6668
6669     if (!demux->upstream_format_is_time) {
6670       gst_qtdemux_map_and_push_segments (demux, &demux->segment);
6671     } else {
6672       GstEvent *segment_event;
6673       segment_event = gst_event_new_segment (&demux->segment);
6674       if (demux->segment_seqnum != GST_SEQNUM_INVALID)
6675         gst_event_set_seqnum (segment_event, demux->segment_seqnum);
6676       gst_qtdemux_push_event (demux, segment_event);
6677     }
6678
6679     demux->need_segment = FALSE;
6680
6681     /* clear to send tags on all streams */
6682     for (i = 0; i < QTDEMUX_N_STREAMS (demux); i++) {
6683       QtDemuxStream *stream = QTDEMUX_NTH_STREAM (demux, i);
6684       gst_qtdemux_push_tags (demux, stream);
6685       if (CUR_STREAM (stream)->sparse) {
6686         GST_INFO_OBJECT (demux, "Sending gap event on stream %d", i);
6687         gst_pad_push_event (stream->pad,
6688             gst_event_new_gap (stream->segment.position, GST_CLOCK_TIME_NONE));
6689       }
6690     }
6691   }
6692 }
6693
6694 /* Used for push mode only. */
6695 static void
6696 gst_qtdemux_send_gap_for_segment (GstQTDemux * demux,
6697     QtDemuxStream * stream, gint segment_index, GstClockTime pos)
6698 {
6699   GstClockTime ts, dur;
6700
6701   ts = pos;
6702   dur =
6703       stream->segments[segment_index].duration - (pos -
6704       stream->segments[segment_index].time);
6705   stream->time_position += dur;
6706
6707   /* Only gaps with a duration of at least one second are propagated.
6708    * Same workaround as in pull mode.
6709    * (See 2e45926a96ec5298c6ef29bf912e5e6a06dc3e0e) */
6710   if (dur >= GST_SECOND) {
6711     GstEvent *gap;
6712     gap = gst_event_new_gap (ts, dur);
6713
6714     GST_DEBUG_OBJECT (stream->pad, "Pushing gap for empty "
6715         "segment: %" GST_PTR_FORMAT, gap);
6716     gst_pad_push_event (stream->pad, gap);
6717   }
6718 }
6719
6720 static GstFlowReturn
6721 gst_qtdemux_chain (GstPad * sinkpad, GstObject * parent, GstBuffer * inbuf)
6722 {
6723   GstQTDemux *demux;
6724
6725   demux = GST_QTDEMUX (parent);
6726
6727   GST_DEBUG_OBJECT (demux,
6728       "Received buffer pts:%" GST_TIME_FORMAT " dts:%" GST_TIME_FORMAT
6729       " offset:%" G_GUINT64_FORMAT " size:%" G_GSIZE_FORMAT " demux offset:%"
6730       G_GUINT64_FORMAT, GST_TIME_ARGS (GST_BUFFER_PTS (inbuf)),
6731       GST_TIME_ARGS (GST_BUFFER_DTS (inbuf)), GST_BUFFER_OFFSET (inbuf),
6732       gst_buffer_get_size (inbuf), demux->offset);
6733
6734   if (GST_BUFFER_FLAG_IS_SET (inbuf, GST_BUFFER_FLAG_DISCONT)) {
6735     gboolean is_gap_input = FALSE;
6736     gint i;
6737
6738     GST_DEBUG_OBJECT (demux, "Got DISCONT, marking all streams as DISCONT");
6739
6740     for (i = 0; i < QTDEMUX_N_STREAMS (demux); i++) {
6741       QTDEMUX_NTH_STREAM (demux, i)->discont = TRUE;
6742     }
6743
6744     /* Check if we can land back on our feet in the case where upstream is
6745      * handling the seeking/pushing of samples with gaps in between (like
6746      * in the case of trick-mode DASH for example) */
6747     if (demux->upstream_format_is_time
6748         && GST_BUFFER_OFFSET (inbuf) != GST_BUFFER_OFFSET_NONE) {
6749       for (i = 0; i < QTDEMUX_N_STREAMS (demux); i++) {
6750         guint32 res;
6751         QtDemuxStream *stream = QTDEMUX_NTH_STREAM (demux, i);
6752         GST_LOG_OBJECT (demux,
6753             "track-id #%u , checking if offset %" G_GUINT64_FORMAT
6754             " is a sample start", stream->track_id, GST_BUFFER_OFFSET (inbuf));
6755         res =
6756             gst_qtdemux_find_index_for_given_media_offset_linear (demux,
6757             stream, GST_BUFFER_OFFSET (inbuf));
6758         if (res != -1) {
6759           QtDemuxSample *sample = &stream->samples[res];
6760           GST_LOG_OBJECT (demux,
6761               "Checking if sample %d from track-id %u is valid (offset:%"
6762               G_GUINT64_FORMAT " size:%" G_GUINT32_FORMAT ")", res,
6763               stream->track_id, sample->offset, sample->size);
6764           if (sample->offset == GST_BUFFER_OFFSET (inbuf)) {
6765             GST_LOG_OBJECT (demux,
6766                 "new buffer corresponds to a valid sample : %" G_GUINT32_FORMAT,
6767                 res);
6768             is_gap_input = TRUE;
6769             /* We can go back to standard playback mode */
6770             demux->state = QTDEMUX_STATE_MOVIE;
6771             /* Remember which sample this stream is at */
6772             stream->sample_index = res;
6773             /* Finally update all push-based values to the expected values */
6774             demux->neededbytes = stream->samples[res].size;
6775             demux->offset = GST_BUFFER_OFFSET (inbuf);
6776             demux->mdatleft =
6777                 demux->mdatsize - demux->offset + demux->mdatoffset;
6778             demux->todrop = 0;
6779           }
6780         }
6781       }
6782       if (!is_gap_input) {
6783         GST_DEBUG_OBJECT (demux, "Resetting, actual DISCONT");
6784         /* Reset state if it's a real discont */
6785         demux->neededbytes = 16;
6786         demux->state = QTDEMUX_STATE_INITIAL;
6787         demux->offset = GST_BUFFER_OFFSET (inbuf);
6788         gst_adapter_clear (demux->adapter);
6789       }
6790     }
6791     /* Reverse fragmented playback, need to flush all we have before
6792      * consuming a new fragment.
6793      * The samples array have the timestamps calculated by accumulating the
6794      * durations but this won't work for reverse playback of fragments as
6795      * the timestamps of a subsequent fragment should be smaller than the
6796      * previously received one. */
6797     if (!is_gap_input && demux->fragmented && demux->segment.rate < 0) {
6798       gst_qtdemux_process_adapter (demux, TRUE);
6799       g_ptr_array_foreach (demux->active_streams,
6800           (GFunc) gst_qtdemux_stream_flush_samples_data, NULL);
6801     }
6802   }
6803
6804   gst_adapter_push (demux->adapter, inbuf);
6805
6806   GST_DEBUG_OBJECT (demux,
6807       "pushing in inbuf %p, neededbytes:%u, available:%" G_GSIZE_FORMAT, inbuf,
6808       demux->neededbytes, gst_adapter_available (demux->adapter));
6809
6810   return gst_qtdemux_process_adapter (demux, FALSE);
6811 }
6812
6813 static GstFlowReturn
6814 gst_qtdemux_process_adapter (GstQTDemux * demux, gboolean force)
6815 {
6816   GstFlowReturn ret = GST_FLOW_OK;
6817
6818   /* we never really mean to buffer that much */
6819   if (demux->neededbytes == -1) {
6820     goto eos;
6821   }
6822
6823   while (((gst_adapter_available (demux->adapter)) >= demux->neededbytes) &&
6824       (ret == GST_FLOW_OK || (ret == GST_FLOW_NOT_LINKED && force))) {
6825
6826 #ifndef GST_DISABLE_GST_DEBUG
6827     {
6828       guint64 discont_offset, distance_from_discont;
6829
6830       discont_offset = gst_adapter_offset_at_discont (demux->adapter);
6831       distance_from_discont =
6832           gst_adapter_distance_from_discont (demux->adapter);
6833
6834       GST_DEBUG_OBJECT (demux,
6835           "state:%s , demux->neededbytes:%d, demux->offset:%" G_GUINT64_FORMAT
6836           " adapter offset :%" G_GUINT64_FORMAT " (+ %" G_GUINT64_FORMAT
6837           " bytes)", qt_demux_state_string (demux->state), demux->neededbytes,
6838           demux->offset, discont_offset, distance_from_discont);
6839     }
6840 #endif
6841
6842     switch (demux->state) {
6843       case QTDEMUX_STATE_INITIAL:{
6844         const guint8 *data;
6845         guint32 fourcc;
6846         guint64 size;
6847
6848         gst_qtdemux_check_seekability (demux);
6849
6850         data = gst_adapter_map (demux->adapter, demux->neededbytes);
6851
6852         /* get fourcc/length, set neededbytes */
6853         extract_initial_length_and_fourcc ((guint8 *) data, demux->neededbytes,
6854             &size, &fourcc);
6855         gst_adapter_unmap (demux->adapter);
6856         data = NULL;
6857         GST_DEBUG_OBJECT (demux, "Peeking found [%" GST_FOURCC_FORMAT "] "
6858             "size: %" G_GUINT64_FORMAT, GST_FOURCC_ARGS (fourcc), size);
6859         if (size == 0) {
6860           GST_ELEMENT_ERROR (demux, STREAM, DEMUX,
6861               (_("This file is invalid and cannot be played.")),
6862               ("initial atom '%" GST_FOURCC_FORMAT "' has empty length",
6863                   GST_FOURCC_ARGS (fourcc)));
6864           ret = GST_FLOW_ERROR;
6865           break;
6866         }
6867         if (fourcc == FOURCC_mdat) {
6868           gint next_entry = next_entry_size (demux);
6869           if (QTDEMUX_N_STREAMS (demux) > 0 && (next_entry != -1
6870                   || !demux->fragmented)) {
6871             /* we have the headers, start playback */
6872             demux->state = QTDEMUX_STATE_MOVIE;
6873             demux->neededbytes = next_entry;
6874             demux->mdatleft = size;
6875             demux->mdatsize = demux->mdatleft;
6876           } else {
6877             /* no headers yet, try to get them */
6878             guint bs;
6879             gboolean res;
6880             guint64 old, target;
6881
6882           buffer_data:
6883             old = demux->offset;
6884             target = old + size;
6885
6886             /* try to jump over the atom with a seek */
6887             /* only bother if it seems worth doing so,
6888              * and avoids possible upstream/server problems */
6889             if (demux->upstream_seekable &&
6890                 demux->upstream_size > 4 * (1 << 20)) {
6891               res = qtdemux_seek_offset (demux, target);
6892             } else {
6893               GST_DEBUG_OBJECT (demux, "skipping seek");
6894               res = FALSE;
6895             }
6896
6897             if (res) {
6898               GST_DEBUG_OBJECT (demux, "seek success");
6899               /* remember the offset fo the first mdat so we can seek back to it
6900                * after we have the headers */
6901               if (fourcc == FOURCC_mdat && demux->first_mdat == -1) {
6902                 demux->first_mdat = old;
6903                 GST_DEBUG_OBJECT (demux, "first mdat at %" G_GUINT64_FORMAT,
6904                     demux->first_mdat);
6905               }
6906               /* seek worked, continue reading */
6907               demux->offset = target;
6908               demux->neededbytes = 16;
6909               demux->state = QTDEMUX_STATE_INITIAL;
6910             } else {
6911               /* seek failed, need to buffer */
6912               demux->offset = old;
6913               GST_DEBUG_OBJECT (demux, "seek failed/skipped");
6914               /* there may be multiple mdat (or alike) buffers */
6915               /* sanity check */
6916               if (demux->mdatbuffer)
6917                 bs = gst_buffer_get_size (demux->mdatbuffer);
6918               else
6919                 bs = 0;
6920               if (size + bs > 10 * (1 << 20))
6921                 goto no_moov;
6922               demux->state = QTDEMUX_STATE_BUFFER_MDAT;
6923               demux->neededbytes = size;
6924               if (!demux->mdatbuffer)
6925                 demux->mdatoffset = demux->offset;
6926             }
6927           }
6928         } else if (G_UNLIKELY (size > QTDEMUX_MAX_ATOM_SIZE)) {
6929           GST_ELEMENT_ERROR (demux, STREAM, DEMUX,
6930               (_("This file is invalid and cannot be played.")),
6931               ("atom %" GST_FOURCC_FORMAT " has bogus size %" G_GUINT64_FORMAT,
6932                   GST_FOURCC_ARGS (fourcc), size));
6933           ret = GST_FLOW_ERROR;
6934           break;
6935         } else {
6936           /* this means we already started buffering and still no moov header,
6937            * let's continue buffering everything till we get moov */
6938           if (demux->mdatbuffer && !(fourcc == FOURCC_moov
6939                   || fourcc == FOURCC_moof))
6940             goto buffer_data;
6941           demux->neededbytes = size;
6942           demux->state = QTDEMUX_STATE_HEADER;
6943         }
6944         break;
6945       }
6946       case QTDEMUX_STATE_HEADER:{
6947         const guint8 *data;
6948         guint32 fourcc;
6949
6950         GST_DEBUG_OBJECT (demux, "In header");
6951
6952         data = gst_adapter_map (demux->adapter, demux->neededbytes);
6953
6954         /* parse the header */
6955         extract_initial_length_and_fourcc (data, demux->neededbytes, NULL,
6956             &fourcc);
6957         if (fourcc == FOURCC_moov) {
6958           /* in usual fragmented setup we could try to scan for more
6959            * and end up at the the moov (after mdat) again */
6960           if (demux->got_moov && QTDEMUX_N_STREAMS (demux) > 0 &&
6961               (!demux->fragmented
6962                   || demux->last_moov_offset == demux->offset)) {
6963             GST_DEBUG_OBJECT (demux,
6964                 "Skipping moov atom as we have (this) one already");
6965           } else {
6966             GST_DEBUG_OBJECT (demux, "Parsing [moov]");
6967
6968             if (demux->got_moov && demux->fragmented) {
6969               GST_DEBUG_OBJECT (demux,
6970                   "Got a second moov, clean up data from old one");
6971               if (demux->moov_node_compressed) {
6972                 g_node_destroy (demux->moov_node_compressed);
6973                 if (demux->moov_node)
6974                   g_free (demux->moov_node->data);
6975               }
6976               demux->moov_node_compressed = NULL;
6977               if (demux->moov_node)
6978                 g_node_destroy (demux->moov_node);
6979               demux->moov_node = NULL;
6980             }
6981
6982             demux->last_moov_offset = demux->offset;
6983
6984             /* Update streams with new moov */
6985             gst_qtdemux_stream_concat (demux,
6986                 demux->old_streams, demux->active_streams);
6987
6988             qtdemux_parse_moov (demux, data, demux->neededbytes);
6989             qtdemux_node_dump (demux, demux->moov_node);
6990             qtdemux_parse_tree (demux);
6991             qtdemux_prepare_streams (demux);
6992             QTDEMUX_EXPOSE_LOCK (demux);
6993             qtdemux_expose_streams (demux);
6994             QTDEMUX_EXPOSE_UNLOCK (demux);
6995
6996             demux->got_moov = TRUE;
6997
6998             gst_qtdemux_check_send_pending_segment (demux);
6999
7000             if (demux->moov_node_compressed) {
7001               g_node_destroy (demux->moov_node_compressed);
7002               g_free (demux->moov_node->data);
7003             }
7004             demux->moov_node_compressed = NULL;
7005             g_node_destroy (demux->moov_node);
7006             demux->moov_node = NULL;
7007             GST_DEBUG_OBJECT (demux, "Finished parsing the header");
7008           }
7009         } else if (fourcc == FOURCC_moof) {
7010           if ((demux->got_moov || demux->media_caps) && demux->fragmented) {
7011             guint64 dist = 0;
7012             GstClockTime prev_pts;
7013             guint64 prev_offset;
7014             guint64 adapter_discont_offset, adapter_discont_dist;
7015
7016             GST_DEBUG_OBJECT (demux, "Parsing [moof]");
7017
7018             /*
7019              * The timestamp of the moof buffer is relevant as some scenarios
7020              * won't have the initial timestamp in the atoms. Whenever a new
7021              * buffer has started, we get that buffer's PTS and use it as a base
7022              * timestamp for the trun entries.
7023              *
7024              * To keep track of the current buffer timestamp and starting point
7025              * we use gst_adapter_prev_pts that gives us the PTS and the distance
7026              * from the beggining of the buffer, with the distance and demux->offset
7027              * we know if it is still the same buffer or not.
7028              */
7029             prev_pts = gst_adapter_prev_pts (demux->adapter, &dist);
7030             prev_offset = demux->offset - dist;
7031             if (demux->fragment_start_offset == -1
7032                 || prev_offset > demux->fragment_start_offset) {
7033               demux->fragment_start_offset = prev_offset;
7034               demux->fragment_start = prev_pts;
7035               GST_DEBUG_OBJECT (demux,
7036                   "New fragment start found at: %" G_GUINT64_FORMAT " : %"
7037                   GST_TIME_FORMAT, demux->fragment_start_offset,
7038                   GST_TIME_ARGS (demux->fragment_start));
7039             }
7040
7041             /* We can't use prev_offset() here because this would require
7042              * upstream to set consistent and correct offsets on all buffers
7043              * since the discont. Nothing ever did that in the past and we
7044              * would break backwards compatibility here then.
7045              * Instead take the offset we had at the last discont and count
7046              * the bytes from there. This works with old code as there would
7047              * be no discont between moov and moof, and also works with
7048              * adaptivedemux which correctly sets offset and will set the
7049              * DISCONT flag accordingly when needed.
7050              *
7051              * We also only do this for upstream TIME segments as otherwise
7052              * there are potential backwards compatibility problems with
7053              * seeking in PUSH mode and upstream providing inconsistent
7054              * timestamps. */
7055             adapter_discont_offset =
7056                 gst_adapter_offset_at_discont (demux->adapter);
7057             adapter_discont_dist =
7058                 gst_adapter_distance_from_discont (demux->adapter);
7059
7060             GST_DEBUG_OBJECT (demux,
7061                 "demux offset %" G_GUINT64_FORMAT " adapter offset %"
7062                 G_GUINT64_FORMAT " (+ %" G_GUINT64_FORMAT " bytes)",
7063                 demux->offset, adapter_discont_offset, adapter_discont_dist);
7064
7065             if (demux->upstream_format_is_time) {
7066               demux->moof_offset = adapter_discont_offset;
7067               if (demux->moof_offset != GST_BUFFER_OFFSET_NONE)
7068                 demux->moof_offset += adapter_discont_dist;
7069               if (demux->moof_offset == GST_BUFFER_OFFSET_NONE)
7070                 demux->moof_offset = demux->offset;
7071             } else {
7072               demux->moof_offset = demux->offset;
7073             }
7074
7075             if (!qtdemux_parse_moof (demux, data, demux->neededbytes,
7076                     demux->moof_offset, NULL)) {
7077               gst_adapter_unmap (demux->adapter);
7078               ret = GST_FLOW_ERROR;
7079               goto done;
7080             }
7081
7082             /* in MSS we need to expose the pads after the first moof as we won't get a moov */
7083             if (demux->mss_mode && !demux->exposed) {
7084               QTDEMUX_EXPOSE_LOCK (demux);
7085               qtdemux_expose_streams (demux);
7086               QTDEMUX_EXPOSE_UNLOCK (demux);
7087             }
7088
7089             gst_qtdemux_check_send_pending_segment (demux);
7090           } else {
7091             GST_DEBUG_OBJECT (demux, "Discarding [moof]");
7092           }
7093         } else if (fourcc == FOURCC_ftyp) {
7094           GST_DEBUG_OBJECT (demux, "Parsing [ftyp]");
7095           qtdemux_parse_ftyp (demux, data, demux->neededbytes);
7096         } else if (fourcc == FOURCC_uuid) {
7097           GST_DEBUG_OBJECT (demux, "Parsing [uuid]");
7098           qtdemux_parse_uuid (demux, data, demux->neededbytes);
7099         } else if (fourcc == FOURCC_sidx) {
7100           GST_DEBUG_OBJECT (demux, "Parsing [sidx]");
7101           qtdemux_parse_sidx (demux, data, demux->neededbytes);
7102         } else {
7103           switch (fourcc) {
7104             case FOURCC_styp:
7105               /* [styp] is like a [ftyp], but in fragment header. We ignore it for now
7106                * FALLTHROUGH */
7107             case FOURCC_skip:
7108             case FOURCC_free:
7109               /* [free] and [skip] are padding atoms */
7110               GST_DEBUG_OBJECT (demux,
7111                   "Skipping fourcc while parsing header : %" GST_FOURCC_FORMAT,
7112                   GST_FOURCC_ARGS (fourcc));
7113               break;
7114             default:
7115               GST_WARNING_OBJECT (demux,
7116                   "Unknown fourcc while parsing header : %" GST_FOURCC_FORMAT,
7117                   GST_FOURCC_ARGS (fourcc));
7118               /* Let's jump that one and go back to initial state */
7119               break;
7120           }
7121         }
7122         gst_adapter_unmap (demux->adapter);
7123         data = NULL;
7124
7125         if (demux->mdatbuffer && QTDEMUX_N_STREAMS (demux)) {
7126           gsize remaining_data_size = 0;
7127
7128           /* the mdat was before the header */
7129           GST_DEBUG_OBJECT (demux, "We have n_streams:%d and mdatbuffer:%p",
7130               QTDEMUX_N_STREAMS (demux), demux->mdatbuffer);
7131           /* restore our adapter/offset view of things with upstream;
7132            * put preceding buffered data ahead of current moov data.
7133            * This should also handle evil mdat, moov, mdat cases and alike */
7134           gst_adapter_flush (demux->adapter, demux->neededbytes);
7135
7136           /* Store any remaining data after the mdat for later usage */
7137           remaining_data_size = gst_adapter_available (demux->adapter);
7138           if (remaining_data_size > 0) {
7139             g_assert (demux->restoredata_buffer == NULL);
7140             demux->restoredata_buffer =
7141                 gst_adapter_take_buffer (demux->adapter, remaining_data_size);
7142             demux->restoredata_offset = demux->offset + demux->neededbytes;
7143             GST_DEBUG_OBJECT (demux,
7144                 "Stored %" G_GSIZE_FORMAT " post mdat bytes at offset %"
7145                 G_GUINT64_FORMAT, remaining_data_size,
7146                 demux->restoredata_offset);
7147           }
7148
7149           gst_adapter_push (demux->adapter, demux->mdatbuffer);
7150           demux->mdatbuffer = NULL;
7151           demux->offset = demux->mdatoffset;
7152           demux->neededbytes = next_entry_size (demux);
7153           demux->state = QTDEMUX_STATE_MOVIE;
7154           demux->mdatleft = gst_adapter_available (demux->adapter);
7155           demux->mdatsize = demux->mdatleft;
7156         } else {
7157           GST_DEBUG_OBJECT (demux, "Carrying on normally");
7158           gst_adapter_flush (demux->adapter, demux->neededbytes);
7159
7160           /* only go back to the mdat if there are samples to play */
7161           if (demux->got_moov && demux->first_mdat != -1
7162               && has_next_entry (demux)) {
7163             gboolean res;
7164
7165             /* we need to seek back */
7166             res = qtdemux_seek_offset (demux, demux->first_mdat);
7167             if (res) {
7168               demux->offset = demux->first_mdat;
7169             } else {
7170               GST_DEBUG_OBJECT (demux, "Seek back failed");
7171             }
7172           } else {
7173             demux->offset += demux->neededbytes;
7174           }
7175           demux->neededbytes = 16;
7176           demux->state = QTDEMUX_STATE_INITIAL;
7177         }
7178
7179         break;
7180       }
7181       case QTDEMUX_STATE_BUFFER_MDAT:{
7182         GstBuffer *buf;
7183         guint8 fourcc[4];
7184
7185         GST_DEBUG_OBJECT (demux, "Got our buffer at offset %" G_GUINT64_FORMAT,
7186             demux->offset);
7187         buf = gst_adapter_take_buffer (demux->adapter, demux->neededbytes);
7188         gst_buffer_extract (buf, 0, fourcc, 4);
7189         GST_DEBUG_OBJECT (demux, "mdatbuffer starts with %" GST_FOURCC_FORMAT,
7190             GST_FOURCC_ARGS (QT_FOURCC (fourcc)));
7191         if (demux->mdatbuffer)
7192           demux->mdatbuffer = gst_buffer_append (demux->mdatbuffer, buf);
7193         else
7194           demux->mdatbuffer = buf;
7195         demux->offset += demux->neededbytes;
7196         demux->neededbytes = 16;
7197         demux->state = QTDEMUX_STATE_INITIAL;
7198         gst_qtdemux_post_progress (demux, 1, 1);
7199
7200         break;
7201       }
7202       case QTDEMUX_STATE_MOVIE:{
7203         QtDemuxStream *stream = NULL;
7204         QtDemuxSample *sample;
7205         GstClockTime dts, pts, duration;
7206         gboolean keyframe;
7207         gint i;
7208
7209         GST_DEBUG_OBJECT (demux,
7210             "BEGIN // in MOVIE for offset %" G_GUINT64_FORMAT, demux->offset);
7211
7212         if (demux->fragmented) {
7213           GST_DEBUG_OBJECT (demux, "mdat remaining %" G_GUINT64_FORMAT,
7214               demux->mdatleft);
7215           if (G_LIKELY (demux->todrop < demux->mdatleft)) {
7216             /* if needed data starts within this atom,
7217              * then it should not exceed this atom */
7218             if (G_UNLIKELY (demux->neededbytes > demux->mdatleft)) {
7219               GST_ELEMENT_ERROR (demux, STREAM, DEMUX,
7220                   (_("This file is invalid and cannot be played.")),
7221                   ("sample data crosses atom boundary"));
7222               ret = GST_FLOW_ERROR;
7223               break;
7224             }
7225             demux->mdatleft -= demux->neededbytes;
7226           } else {
7227             GST_DEBUG_OBJECT (demux, "data atom emptied; resuming atom scan");
7228             /* so we are dropping more than left in this atom */
7229             gst_qtdemux_drop_data (demux, demux->mdatleft);
7230             demux->mdatleft = 0;
7231
7232             /* need to resume atom parsing so we do not miss any other pieces */
7233             demux->state = QTDEMUX_STATE_INITIAL;
7234             demux->neededbytes = 16;
7235
7236             /* check if there was any stored post mdat data from previous buffers */
7237             if (demux->restoredata_buffer) {
7238               g_assert (gst_adapter_available (demux->adapter) == 0);
7239
7240               gst_adapter_push (demux->adapter, demux->restoredata_buffer);
7241               demux->restoredata_buffer = NULL;
7242               demux->offset = demux->restoredata_offset;
7243             }
7244
7245             break;
7246           }
7247         }
7248
7249         if (demux->todrop) {
7250           if (demux->cenc_aux_info_offset > 0) {
7251             GstByteReader br;
7252             const guint8 *data;
7253
7254             GST_DEBUG_OBJECT (demux, "parsing cenc auxiliary info");
7255             data = gst_adapter_map (demux->adapter, demux->todrop);
7256             gst_byte_reader_init (&br, data + 8, demux->todrop);
7257             if (!qtdemux_parse_cenc_aux_info (demux,
7258                     QTDEMUX_NTH_STREAM (demux, 0), &br,
7259                     demux->cenc_aux_info_sizes, demux->cenc_aux_sample_count)) {
7260               GST_ERROR_OBJECT (demux, "failed to parse cenc auxiliary info");
7261               ret = GST_FLOW_ERROR;
7262               gst_adapter_unmap (demux->adapter);
7263               g_free (demux->cenc_aux_info_sizes);
7264               demux->cenc_aux_info_sizes = NULL;
7265               goto done;
7266             }
7267             demux->cenc_aux_info_offset = 0;
7268             g_free (demux->cenc_aux_info_sizes);
7269             demux->cenc_aux_info_sizes = NULL;
7270             gst_adapter_unmap (demux->adapter);
7271           }
7272           gst_qtdemux_drop_data (demux, demux->todrop);
7273         }
7274
7275         /* first buffer? */
7276         /* initial newsegment sent here after having added pads,
7277          * possible others in sink_event */
7278         gst_qtdemux_check_send_pending_segment (demux);
7279
7280         /* Figure out which stream this packet belongs to */
7281         for (i = 0; i < QTDEMUX_N_STREAMS (demux); i++) {
7282           stream = QTDEMUX_NTH_STREAM (demux, i);
7283           if (stream->sample_index >= stream->n_samples) {
7284             /* reset to be checked below G_UNLIKELY (stream == NULL) */
7285             stream = NULL;
7286             continue;
7287           }
7288           GST_LOG_OBJECT (demux,
7289               "Checking track-id %u (sample_index:%d / offset:%"
7290               G_GUINT64_FORMAT " / size:%d)", stream->track_id,
7291               stream->sample_index,
7292               stream->samples[stream->sample_index].offset,
7293               stream->samples[stream->sample_index].size);
7294
7295           if (stream->samples[stream->sample_index].offset == demux->offset)
7296             break;
7297         }
7298
7299         if (G_UNLIKELY (stream == NULL))
7300           goto unknown_stream;
7301
7302         gst_qtdemux_stream_check_and_change_stsd_index (demux, stream);
7303
7304         if (stream->new_caps) {
7305           gst_qtdemux_configure_stream (demux, stream);
7306         }
7307
7308         /* Put data in a buffer, set timestamps, caps, ... */
7309         sample = &stream->samples[stream->sample_index];
7310
7311         if (G_LIKELY (!(STREAM_IS_EOS (stream)))) {
7312           GST_DEBUG_OBJECT (demux, "stream : %" GST_FOURCC_FORMAT,
7313               GST_FOURCC_ARGS (CUR_STREAM (stream)->fourcc));
7314
7315           dts = QTSAMPLE_DTS (stream, sample);
7316           pts = QTSAMPLE_PTS (stream, sample);
7317           duration = QTSAMPLE_DUR_DTS (stream, sample, dts);
7318           keyframe = QTSAMPLE_KEYFRAME (stream, sample);
7319
7320           /* check for segment end */
7321           if (G_UNLIKELY (demux->segment.stop != -1
7322                   && demux->segment.stop <= pts && stream->on_keyframe)
7323               && !(demux->upstream_format_is_time && demux->segment.rate < 0)) {
7324             GST_DEBUG_OBJECT (demux, "we reached the end of our segment.");
7325             stream->time_position = GST_CLOCK_TIME_NONE;        /* this means EOS */
7326
7327             /* skip this data, stream is EOS */
7328             gst_adapter_flush (demux->adapter, demux->neededbytes);
7329             demux->offset += demux->neededbytes;
7330
7331             /* check if all streams are eos */
7332             ret = GST_FLOW_EOS;
7333             for (i = 0; i < QTDEMUX_N_STREAMS (demux); i++) {
7334               if (!STREAM_IS_EOS (QTDEMUX_NTH_STREAM (demux, i))) {
7335                 ret = GST_FLOW_OK;
7336                 break;
7337               }
7338             }
7339           } else {
7340             GstBuffer *outbuf;
7341
7342             outbuf =
7343                 gst_adapter_take_buffer (demux->adapter, demux->neededbytes);
7344
7345             /* FIXME: should either be an assert or a plain check */
7346             g_return_val_if_fail (outbuf != NULL, GST_FLOW_ERROR);
7347
7348             ret = gst_qtdemux_decorate_and_push_buffer (demux, stream, outbuf,
7349                 dts, pts, duration, keyframe, dts, demux->offset);
7350           }
7351
7352           /* combine flows */
7353           ret = gst_qtdemux_combine_flows (demux, stream, ret);
7354         } else {
7355           /* skip this data, stream is EOS */
7356           gst_adapter_flush (demux->adapter, demux->neededbytes);
7357         }
7358
7359         stream->sample_index++;
7360         stream->offset_in_sample = 0;
7361
7362         /* update current offset and figure out size of next buffer */
7363         GST_LOG_OBJECT (demux, "increasing offset %" G_GUINT64_FORMAT " by %u",
7364             demux->offset, demux->neededbytes);
7365         demux->offset += demux->neededbytes;
7366         GST_LOG_OBJECT (demux, "offset is now %" G_GUINT64_FORMAT,
7367             demux->offset);
7368
7369
7370         if (ret == GST_FLOW_EOS) {
7371           GST_DEBUG_OBJECT (demux, "All streams are EOS, signal upstream");
7372           demux->neededbytes = -1;
7373           goto eos;
7374         }
7375
7376         if ((demux->neededbytes = next_entry_size (demux)) == -1) {
7377           if (demux->fragmented) {
7378             GST_DEBUG_OBJECT (demux, "(temporarily) out of fragmented samples");
7379             /* there may be more to follow, only finish this atom */
7380             demux->todrop = demux->mdatleft;
7381             demux->neededbytes = demux->todrop;
7382             break;
7383           }
7384           goto eos;
7385         }
7386         if (ret != GST_FLOW_OK && ret != GST_FLOW_NOT_LINKED) {
7387           goto non_ok_unlinked_flow;
7388         }
7389         break;
7390       }
7391       default:
7392         goto invalid_state;
7393     }
7394   }
7395
7396   /* when buffering movie data, at least show user something is happening */
7397   if (ret == GST_FLOW_OK && demux->state == QTDEMUX_STATE_BUFFER_MDAT &&
7398       gst_adapter_available (demux->adapter) <= demux->neededbytes) {
7399     gst_qtdemux_post_progress (demux, gst_adapter_available (demux->adapter),
7400         demux->neededbytes);
7401   }
7402 done:
7403
7404   return ret;
7405
7406   /* ERRORS */
7407 non_ok_unlinked_flow:
7408   {
7409     GST_DEBUG_OBJECT (demux, "Stopping, combined return flow %s",
7410         gst_flow_get_name (ret));
7411     return ret;
7412   }
7413 unknown_stream:
7414   {
7415     GST_ELEMENT_ERROR (demux, STREAM, FAILED, (NULL), ("unknown stream found"));
7416     ret = GST_FLOW_ERROR;
7417     goto done;
7418   }
7419 eos:
7420   {
7421     GST_DEBUG_OBJECT (demux, "no next entry, EOS");
7422     ret = GST_FLOW_EOS;
7423     goto done;
7424   }
7425 invalid_state:
7426   {
7427     GST_ELEMENT_ERROR (demux, STREAM, FAILED,
7428         (NULL), ("qtdemuxer invalid state %d", demux->state));
7429     ret = GST_FLOW_ERROR;
7430     goto done;
7431   }
7432 no_moov:
7433   {
7434     GST_ELEMENT_ERROR (demux, STREAM, FAILED,
7435         (NULL), ("no 'moov' atom within the first 10 MB"));
7436     ret = GST_FLOW_ERROR;
7437     goto done;
7438   }
7439 }
7440
7441 static gboolean
7442 qtdemux_sink_activate (GstPad * sinkpad, GstObject * parent)
7443 {
7444   GstQuery *query;
7445   gboolean pull_mode;
7446
7447   query = gst_query_new_scheduling ();
7448
7449   if (!gst_pad_peer_query (sinkpad, query)) {
7450     gst_query_unref (query);
7451     goto activate_push;
7452   }
7453
7454   pull_mode = gst_query_has_scheduling_mode_with_flags (query,
7455       GST_PAD_MODE_PULL, GST_SCHEDULING_FLAG_SEEKABLE);
7456   gst_query_unref (query);
7457
7458   if (!pull_mode)
7459     goto activate_push;
7460
7461   GST_DEBUG_OBJECT (sinkpad, "activating pull");
7462   return gst_pad_activate_mode (sinkpad, GST_PAD_MODE_PULL, TRUE);
7463
7464 activate_push:
7465   {
7466     GST_DEBUG_OBJECT (sinkpad, "activating push");
7467     return gst_pad_activate_mode (sinkpad, GST_PAD_MODE_PUSH, TRUE);
7468   }
7469 }
7470
7471 static gboolean
7472 qtdemux_sink_activate_mode (GstPad * sinkpad, GstObject * parent,
7473     GstPadMode mode, gboolean active)
7474 {
7475   gboolean res;
7476   GstQTDemux *demux = GST_QTDEMUX (parent);
7477
7478   switch (mode) {
7479     case GST_PAD_MODE_PUSH:
7480       demux->pullbased = FALSE;
7481       res = TRUE;
7482       break;
7483     case GST_PAD_MODE_PULL:
7484       if (active) {
7485         demux->pullbased = TRUE;
7486         res = gst_pad_start_task (sinkpad, (GstTaskFunction) gst_qtdemux_loop,
7487             sinkpad, NULL);
7488       } else {
7489         res = gst_pad_stop_task (sinkpad);
7490       }
7491       break;
7492     default:
7493       res = FALSE;
7494       break;
7495   }
7496   return res;
7497 }
7498
7499 #ifdef HAVE_ZLIB
7500 static void *
7501 qtdemux_inflate (void *z_buffer, guint z_length, guint * length)
7502 {
7503   guint8 *buffer;
7504   z_stream z;
7505   int ret;
7506
7507   memset (&z, 0, sizeof (z));
7508   z.zalloc = NULL;
7509   z.zfree = NULL;
7510   z.opaque = NULL;
7511
7512   if ((ret = inflateInit (&z)) != Z_OK) {
7513     GST_ERROR ("inflateInit() returned %d", ret);
7514     return NULL;
7515   }
7516
7517   z.next_in = z_buffer;
7518   z.avail_in = z_length;
7519
7520   buffer = (guint8 *) g_malloc (*length);
7521   z.avail_out = *length;
7522   z.next_out = (Bytef *) buffer;
7523   do {
7524     ret = inflate (&z, Z_NO_FLUSH);
7525     if (ret == Z_STREAM_END) {
7526       break;
7527     } else if (ret != Z_OK) {
7528       GST_WARNING ("inflate() returned %d", ret);
7529       break;
7530     }
7531
7532     *length += 4096;
7533     buffer = (guint8 *) g_realloc (buffer, *length);
7534     z.next_out = (Bytef *) (buffer + z.total_out);
7535     z.avail_out += 4096;
7536   } while (z.avail_in > 0);
7537
7538   if (ret != Z_STREAM_END) {
7539     g_free (buffer);
7540     buffer = NULL;
7541     *length = 0;
7542   } else {
7543     *length = z.total_out;
7544   }
7545
7546   inflateEnd (&z);
7547
7548   return buffer;
7549 }
7550 #endif /* HAVE_ZLIB */
7551
7552 static gboolean
7553 qtdemux_parse_moov (GstQTDemux * qtdemux, const guint8 * buffer, guint length)
7554 {
7555   GNode *cmov;
7556
7557   qtdemux->moov_node = g_node_new ((guint8 *) buffer);
7558
7559   /* counts as header data */
7560   qtdemux->header_size += length;
7561
7562   GST_DEBUG_OBJECT (qtdemux, "parsing 'moov' atom");
7563   qtdemux_parse_node (qtdemux, qtdemux->moov_node, buffer, length);
7564
7565   cmov = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_cmov);
7566   if (cmov) {
7567     guint32 method;
7568     GNode *dcom;
7569     GNode *cmvd;
7570     guint32 dcom_len;
7571
7572     dcom = qtdemux_tree_get_child_by_type (cmov, FOURCC_dcom);
7573     cmvd = qtdemux_tree_get_child_by_type (cmov, FOURCC_cmvd);
7574     if (dcom == NULL || cmvd == NULL)
7575       goto invalid_compression;
7576
7577     dcom_len = QT_UINT32 (dcom->data);
7578     if (dcom_len < 12)
7579       goto invalid_compression;
7580
7581     method = QT_FOURCC ((guint8 *) dcom->data + 8);
7582     switch (method) {
7583 #ifdef HAVE_ZLIB
7584       case FOURCC_zlib:{
7585         guint uncompressed_length;
7586         guint compressed_length;
7587         guint8 *buf;
7588         guint32 cmvd_len;
7589
7590         cmvd_len = QT_UINT32 ((guint8 *) cmvd->data);
7591         if (cmvd_len < 12)
7592           goto invalid_compression;
7593
7594         uncompressed_length = QT_UINT32 ((guint8 *) cmvd->data + 8);
7595         compressed_length = cmvd_len - 12;
7596         GST_LOG ("length = %u", uncompressed_length);
7597
7598         buf =
7599             (guint8 *) qtdemux_inflate ((guint8 *) cmvd->data + 12,
7600             compressed_length, &uncompressed_length);
7601
7602         if (buf) {
7603           qtdemux->moov_node_compressed = qtdemux->moov_node;
7604           qtdemux->moov_node = g_node_new (buf);
7605
7606           qtdemux_parse_node (qtdemux, qtdemux->moov_node, buf,
7607               uncompressed_length);
7608         }
7609         break;
7610       }
7611 #endif /* HAVE_ZLIB */
7612       default:
7613         GST_WARNING_OBJECT (qtdemux, "unknown or unhandled header compression "
7614             "type %" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (method));
7615         break;
7616     }
7617   }
7618   return TRUE;
7619
7620   /* ERRORS */
7621 invalid_compression:
7622   {
7623     GST_ERROR_OBJECT (qtdemux, "invalid compressed header");
7624     return FALSE;
7625   }
7626 }
7627
7628 static gboolean
7629 qtdemux_parse_container (GstQTDemux * qtdemux, GNode * node, const guint8 * buf,
7630     const guint8 * end)
7631 {
7632   while (G_UNLIKELY (buf < end)) {
7633     GNode *child;
7634     guint32 len;
7635
7636     if (G_UNLIKELY (buf + 4 > end)) {
7637       GST_LOG_OBJECT (qtdemux, "buffer overrun");
7638       break;
7639     }
7640     len = QT_UINT32 (buf);
7641     if (G_UNLIKELY (len == 0)) {
7642       GST_LOG_OBJECT (qtdemux, "empty container");
7643       break;
7644     }
7645     if (G_UNLIKELY (len < 8)) {
7646       GST_WARNING_OBJECT (qtdemux, "length too short (%d < 8)", len);
7647       break;
7648     }
7649     if (G_UNLIKELY (len > (end - buf))) {
7650       GST_WARNING_OBJECT (qtdemux, "length too long (%d > %d)", len,
7651           (gint) (end - buf));
7652       break;
7653     }
7654
7655     child = g_node_new ((guint8 *) buf);
7656     g_node_append (node, child);
7657     GST_LOG_OBJECT (qtdemux, "adding new node of len %d", len);
7658     qtdemux_parse_node (qtdemux, child, buf, len);
7659
7660     buf += len;
7661   }
7662   return TRUE;
7663 }
7664
7665 static gboolean
7666 qtdemux_parse_theora_extension (GstQTDemux * qtdemux, QtDemuxStream * stream,
7667     GNode * xdxt)
7668 {
7669   int len = QT_UINT32 (xdxt->data);
7670   guint8 *buf = xdxt->data;
7671   guint8 *end = buf + len;
7672   GstBuffer *buffer;
7673
7674   /* skip size and type */
7675   buf += 8;
7676   end -= 8;
7677
7678   while (buf < end) {
7679     gint size;
7680     guint32 type;
7681
7682     size = QT_UINT32 (buf);
7683     type = QT_FOURCC (buf + 4);
7684
7685     GST_LOG_OBJECT (qtdemux, "%p %p", buf, end);
7686
7687     if (buf + size > end || size <= 0)
7688       break;
7689
7690     buf += 8;
7691     size -= 8;
7692
7693     GST_WARNING_OBJECT (qtdemux, "have cookie %" GST_FOURCC_FORMAT,
7694         GST_FOURCC_ARGS (type));
7695
7696     switch (type) {
7697       case FOURCC_tCtH:
7698         buffer = gst_buffer_new_and_alloc (size);
7699         gst_buffer_fill (buffer, 0, buf, size);
7700         stream->buffers = g_slist_append (stream->buffers, buffer);
7701         GST_LOG_OBJECT (qtdemux, "parsing theora header");
7702         break;
7703       case FOURCC_tCt_:
7704         buffer = gst_buffer_new_and_alloc (size);
7705         gst_buffer_fill (buffer, 0, buf, size);
7706         stream->buffers = g_slist_append (stream->buffers, buffer);
7707         GST_LOG_OBJECT (qtdemux, "parsing theora comment");
7708         break;
7709       case FOURCC_tCtC:
7710         buffer = gst_buffer_new_and_alloc (size);
7711         gst_buffer_fill (buffer, 0, buf, size);
7712         stream->buffers = g_slist_append (stream->buffers, buffer);
7713         GST_LOG_OBJECT (qtdemux, "parsing theora codebook");
7714         break;
7715       default:
7716         GST_WARNING_OBJECT (qtdemux,
7717             "unknown theora cookie %" GST_FOURCC_FORMAT,
7718             GST_FOURCC_ARGS (type));
7719         break;
7720     }
7721     buf += size;
7722   }
7723   return TRUE;
7724 }
7725
7726 static gboolean
7727 qtdemux_parse_node (GstQTDemux * qtdemux, GNode * node, const guint8 * buffer,
7728     guint length)
7729 {
7730   guint32 fourcc = 0;
7731   guint32 node_length = 0;
7732   const QtNodeType *type;
7733   const guint8 *end;
7734
7735   GST_LOG_OBJECT (qtdemux, "qtdemux_parse buffer %p length %u", buffer, length);
7736
7737   if (G_UNLIKELY (length < 8))
7738     goto not_enough_data;
7739
7740   node_length = QT_UINT32 (buffer);
7741   fourcc = QT_FOURCC (buffer + 4);
7742
7743   /* ignore empty nodes */
7744   if (G_UNLIKELY (fourcc == 0 || node_length == 8))
7745     return TRUE;
7746
7747   type = qtdemux_type_get (fourcc);
7748
7749   end = buffer + length;
7750
7751   GST_LOG_OBJECT (qtdemux,
7752       "parsing '%" GST_FOURCC_FORMAT "', length=%u, name '%s'",
7753       GST_FOURCC_ARGS (fourcc), node_length, type->name);
7754
7755   if (node_length > length)
7756     goto broken_atom_size;
7757
7758   if (type->flags & QT_FLAG_CONTAINER) {
7759     qtdemux_parse_container (qtdemux, node, buffer + 8, end);
7760   } else {
7761     switch (fourcc) {
7762       case FOURCC_stsd:
7763       {
7764         if (node_length < 20) {
7765           GST_LOG_OBJECT (qtdemux, "skipping small stsd box");
7766           break;
7767         }
7768         GST_DEBUG_OBJECT (qtdemux,
7769             "parsing stsd (sample table, sample description) atom");
7770         /* Skip over 8 byte atom hdr + 1 byte version, 3 bytes flags, 4 byte num_entries */
7771         qtdemux_parse_container (qtdemux, node, buffer + 16, end);
7772         break;
7773       }
7774       case FOURCC_mp4a:
7775       case FOURCC_alac:
7776       case FOURCC_fLaC:
7777       {
7778         guint32 version;
7779         guint32 offset;
7780         guint min_size;
7781
7782         /* also read alac (or whatever) in stead of mp4a in the following,
7783          * since a similar layout is used in other cases as well */
7784         if (fourcc == FOURCC_mp4a)
7785           min_size = 20;
7786         else if (fourcc == FOURCC_fLaC)
7787           min_size = 86;
7788         else
7789           min_size = 40;
7790
7791         /* There are two things we might encounter here: a true mp4a atom, and
7792            an mp4a entry in an stsd atom. The latter is what we're interested
7793            in, and it looks like an atom, but isn't really one. The true mp4a
7794            atom is short, so we detect it based on length here. */
7795         if (length < min_size) {
7796           GST_LOG_OBJECT (qtdemux, "skipping small %" GST_FOURCC_FORMAT " box",
7797               GST_FOURCC_ARGS (fourcc));
7798           break;
7799         }
7800
7801         /* 'version' here is the sound sample description version. Types 0 and
7802            1 are documented in the QTFF reference, but type 2 is not: it's
7803            described in Apple header files instead (struct SoundDescriptionV2
7804            in Movies.h) */
7805         version = QT_UINT16 (buffer + 16);
7806
7807         GST_DEBUG_OBJECT (qtdemux, "%" GST_FOURCC_FORMAT " version 0x%08x",
7808             GST_FOURCC_ARGS (fourcc), version);
7809
7810         /* parse any esds descriptors */
7811         switch (version) {
7812           case 0:
7813             offset = 0x24;
7814             break;
7815           case 1:
7816             offset = 0x34;
7817             break;
7818           case 2:
7819             offset = 0x48;
7820             break;
7821           default:
7822             GST_WARNING_OBJECT (qtdemux,
7823                 "unhandled %" GST_FOURCC_FORMAT " version 0x%08x",
7824                 GST_FOURCC_ARGS (fourcc), version);
7825             offset = 0;
7826             break;
7827         }
7828         if (offset)
7829           qtdemux_parse_container (qtdemux, node, buffer + offset, end);
7830         break;
7831       }
7832       case FOURCC_mp4v:
7833       case FOURCC_MP4V:
7834       case FOURCC_fmp4:
7835       case FOURCC_FMP4:
7836       case FOURCC_apcs:
7837       case FOURCC_apch:
7838       case FOURCC_apcn:
7839       case FOURCC_apco:
7840       case FOURCC_ap4h:
7841       case FOURCC_xvid:
7842       case FOURCC_XVID:
7843       case FOURCC_H264:
7844       case FOURCC_avc1:
7845       case FOURCC_avc3:
7846       case FOURCC_H265:
7847       case FOURCC_hvc1:
7848       case FOURCC_hev1:
7849       case FOURCC_mjp2:
7850       case FOURCC_encv:
7851       {
7852         guint32 version;
7853         guint32 str_len;
7854
7855         /* codec_data is contained inside these atoms, which all have
7856          * the same format. */
7857         /* video sample description size is 86 bytes without extension.
7858          * node_length have to be bigger than 86 bytes because video sample
7859          * description can include extenstions such as esds, fiel, glbl, etc. */
7860         if (node_length < 86) {
7861           GST_WARNING_OBJECT (qtdemux, "%" GST_FOURCC_FORMAT
7862               " sample description length too short (%u < 86)",
7863               GST_FOURCC_ARGS (fourcc), node_length);
7864           break;
7865         }
7866
7867         GST_DEBUG_OBJECT (qtdemux, "parsing in %" GST_FOURCC_FORMAT,
7868             GST_FOURCC_ARGS (fourcc));
7869
7870         /* version (2 bytes) : this is set to 0, unless a compressor has changed
7871          *              its data format.
7872          * revision level (2 bytes) : must be set to 0. */
7873         version = QT_UINT32 (buffer + 16);
7874         GST_DEBUG_OBJECT (qtdemux, "version %08x", version);
7875
7876         /* compressor name : PASCAL string and informative purposes
7877          * first byte : the number of bytes to be displayed.
7878          *              it has to be less than 32 because it is reserved
7879          *              space of 32 bytes total including itself. */
7880         str_len = QT_UINT8 (buffer + 50);
7881         if (str_len < 32)
7882           GST_DEBUG_OBJECT (qtdemux, "compressorname = %.*s", str_len,
7883               (char *) buffer + 51);
7884         else
7885           GST_WARNING_OBJECT (qtdemux,
7886               "compressorname length too big (%u > 31)", str_len);
7887
7888         GST_MEMDUMP_OBJECT (qtdemux, "video sample description", buffer,
7889             end - buffer);
7890         qtdemux_parse_container (qtdemux, node, buffer + 86, end);
7891         break;
7892       }
7893       case FOURCC_meta:
7894       {
7895         GST_DEBUG_OBJECT (qtdemux, "parsing meta atom");
7896
7897         /* You are reading this correctly. QTFF specifies that the
7898          * metadata atom is a short atom, whereas ISO BMFF specifies
7899          * it's a full atom. But since so many people are doing things
7900          * differently, we actually peek into the atom to see which
7901          * variant it is */
7902         if (length < 16) {
7903           GST_LOG_OBJECT (qtdemux, "skipping small %" GST_FOURCC_FORMAT " box",
7904               GST_FOURCC_ARGS (fourcc));
7905           break;
7906         }
7907         if (QT_FOURCC (buffer + 12) == FOURCC_hdlr) {
7908           /* Variant 1: What QTFF specifies. 'meta' is a short header which
7909            * starts with a 'hdlr' atom */
7910           qtdemux_parse_container (qtdemux, node, buffer + 8, end);
7911         } else if (QT_UINT32 (buffer + 8) == 0x00000000) {
7912           /* Variant 2: What ISO BMFF specifies. 'meta' is a _full_ atom
7913            * with version/flags both set to zero */
7914           qtdemux_parse_container (qtdemux, node, buffer + 12, end);
7915         } else
7916           GST_WARNING_OBJECT (qtdemux, "Unknown 'meta' atom format");
7917         break;
7918       }
7919       case FOURCC_mp4s:
7920       {
7921         GST_MEMDUMP_OBJECT (qtdemux, "mp4s", buffer, end - buffer);
7922         /* Skip 8 byte header, plus 8 byte version + flags + entry_count */
7923         qtdemux_parse_container (qtdemux, node, buffer + 16, end);
7924         break;
7925       }
7926       case FOURCC_XiTh:
7927       {
7928         guint32 version;
7929         guint32 offset;
7930
7931         if (length < 16) {
7932           GST_LOG_OBJECT (qtdemux, "skipping small %" GST_FOURCC_FORMAT " box",
7933               GST_FOURCC_ARGS (fourcc));
7934           break;
7935         }
7936
7937         version = QT_UINT32 (buffer + 12);
7938         GST_DEBUG_OBJECT (qtdemux, "parsing XiTh atom version 0x%08x", version);
7939
7940         switch (version) {
7941           case 0x00000001:
7942             offset = 0x62;
7943             break;
7944           default:
7945             GST_DEBUG_OBJECT (qtdemux, "unknown version 0x%08x", version);
7946             offset = 0;
7947             break;
7948         }
7949         if (offset) {
7950           if (length < offset) {
7951             GST_WARNING_OBJECT (qtdemux,
7952                 "skipping too small %" GST_FOURCC_FORMAT " box",
7953                 GST_FOURCC_ARGS (fourcc));
7954             break;
7955           }
7956           qtdemux_parse_container (qtdemux, node, buffer + offset, end);
7957         }
7958         break;
7959       }
7960       case FOURCC_in24:
7961       {
7962         qtdemux_parse_container (qtdemux, node, buffer + 0x34, end);
7963         break;
7964       }
7965       case FOURCC_uuid:
7966       {
7967         qtdemux_parse_uuid (qtdemux, buffer, end - buffer);
7968         break;
7969       }
7970       case FOURCC_enca:
7971       {
7972         qtdemux_parse_container (qtdemux, node, buffer + 36, end);
7973         break;
7974       }
7975       default:
7976         if (!strcmp (type->name, "unknown"))
7977           GST_MEMDUMP ("Unknown tag", buffer + 4, end - buffer - 4);
7978         break;
7979     }
7980   }
7981   GST_LOG_OBJECT (qtdemux, "parsed '%" GST_FOURCC_FORMAT "'",
7982       GST_FOURCC_ARGS (fourcc));
7983   return TRUE;
7984
7985 /* ERRORS */
7986 not_enough_data:
7987   {
7988     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
7989         (_("This file is corrupt and cannot be played.")),
7990         ("Not enough data for an atom header, got only %u bytes", length));
7991     return FALSE;
7992   }
7993 broken_atom_size:
7994   {
7995     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
7996         (_("This file is corrupt and cannot be played.")),
7997         ("Atom '%" GST_FOURCC_FORMAT "' has size of %u bytes, but we have only "
7998             "%u bytes available.", GST_FOURCC_ARGS (fourcc), node_length,
7999             length));
8000     return FALSE;
8001   }
8002 }
8003
8004 static GNode *
8005 qtdemux_tree_get_child_by_type (GNode * node, guint32 fourcc)
8006 {
8007   GNode *child;
8008   guint8 *buffer;
8009   guint32 child_fourcc;
8010
8011   for (child = g_node_first_child (node); child;
8012       child = g_node_next_sibling (child)) {
8013     buffer = (guint8 *) child->data;
8014
8015     child_fourcc = QT_FOURCC (buffer + 4);
8016
8017     if (G_UNLIKELY (child_fourcc == fourcc)) {
8018       return child;
8019     }
8020   }
8021   return NULL;
8022 }
8023
8024 static GNode *
8025 qtdemux_tree_get_child_by_type_full (GNode * node, guint32 fourcc,
8026     GstByteReader * parser)
8027 {
8028   GNode *child;
8029   guint8 *buffer;
8030   guint32 child_fourcc, child_len;
8031
8032   for (child = g_node_first_child (node); child;
8033       child = g_node_next_sibling (child)) {
8034     buffer = (guint8 *) child->data;
8035
8036     child_len = QT_UINT32 (buffer);
8037     child_fourcc = QT_FOURCC (buffer + 4);
8038
8039     if (G_UNLIKELY (child_fourcc == fourcc)) {
8040       if (G_UNLIKELY (child_len < (4 + 4)))
8041         return NULL;
8042       /* FIXME: must verify if atom length < parent atom length */
8043       gst_byte_reader_init (parser, buffer + (4 + 4), child_len - (4 + 4));
8044       return child;
8045     }
8046   }
8047   return NULL;
8048 }
8049
8050 static GNode *
8051 qtdemux_tree_get_child_by_index (GNode * node, guint index)
8052 {
8053   return g_node_nth_child (node, index);
8054 }
8055
8056 static GNode *
8057 qtdemux_tree_get_sibling_by_type_full (GNode * node, guint32 fourcc,
8058     GstByteReader * parser)
8059 {
8060   GNode *child;
8061   guint8 *buffer;
8062   guint32 child_fourcc, child_len;
8063
8064   for (child = g_node_next_sibling (node); child;
8065       child = g_node_next_sibling (child)) {
8066     buffer = (guint8 *) child->data;
8067
8068     child_fourcc = QT_FOURCC (buffer + 4);
8069
8070     if (child_fourcc == fourcc) {
8071       if (parser) {
8072         child_len = QT_UINT32 (buffer);
8073         if (G_UNLIKELY (child_len < (4 + 4)))
8074           return NULL;
8075         /* FIXME: must verify if atom length < parent atom length */
8076         gst_byte_reader_init (parser, buffer + (4 + 4), child_len - (4 + 4));
8077       }
8078       return child;
8079     }
8080   }
8081   return NULL;
8082 }
8083
8084 static GNode *
8085 qtdemux_tree_get_sibling_by_type (GNode * node, guint32 fourcc)
8086 {
8087   return qtdemux_tree_get_sibling_by_type_full (node, fourcc, NULL);
8088 }
8089
8090 static void
8091 qtdemux_do_allocation (QtDemuxStream * stream, GstQTDemux * qtdemux)
8092 {
8093 /* FIXME: This can only reliably work if demuxers have a
8094  * separate streaming thread per srcpad. This should be
8095  * done in a demuxer base class, which integrates parts
8096  * of multiqueue
8097  *
8098  * https://bugzilla.gnome.org/show_bug.cgi?id=701856
8099  */
8100 #if 0
8101   GstQuery *query;
8102
8103   query = gst_query_new_allocation (stream->caps, FALSE);
8104
8105   if (!gst_pad_peer_query (stream->pad, query)) {
8106     /* not a problem, just debug a little */
8107     GST_DEBUG_OBJECT (qtdemux, "peer ALLOCATION query failed");
8108   }
8109
8110   if (stream->allocator)
8111     gst_object_unref (stream->allocator);
8112
8113   if (gst_query_get_n_allocation_params (query) > 0) {
8114     /* try the allocator */
8115     gst_query_parse_nth_allocation_param (query, 0, &stream->allocator,
8116         &stream->params);
8117     stream->use_allocator = TRUE;
8118   } else {
8119     stream->allocator = NULL;
8120     gst_allocation_params_init (&stream->params);
8121     stream->use_allocator = FALSE;
8122   }
8123   gst_query_unref (query);
8124 #endif
8125 }
8126
8127 static gboolean
8128 pad_query (const GValue * item, GValue * value, gpointer user_data)
8129 {
8130   GstPad *pad = g_value_get_object (item);
8131   GstQuery *query = user_data;
8132   gboolean res;
8133
8134   res = gst_pad_peer_query (pad, query);
8135
8136   if (res) {
8137     g_value_set_boolean (value, TRUE);
8138     return FALSE;
8139   }
8140
8141   GST_INFO_OBJECT (pad, "pad peer query failed");
8142   return TRUE;
8143 }
8144
8145 static gboolean
8146 gst_qtdemux_run_query (GstElement * element, GstQuery * query,
8147     GstPadDirection direction)
8148 {
8149   GstIterator *it;
8150   GstIteratorFoldFunction func = pad_query;
8151   GValue res = { 0, };
8152
8153   g_value_init (&res, G_TYPE_BOOLEAN);
8154   g_value_set_boolean (&res, FALSE);
8155
8156   /* Ask neighbor */
8157   if (direction == GST_PAD_SRC)
8158     it = gst_element_iterate_src_pads (element);
8159   else
8160     it = gst_element_iterate_sink_pads (element);
8161
8162   while (gst_iterator_fold (it, func, &res, query) == GST_ITERATOR_RESYNC)
8163     gst_iterator_resync (it);
8164
8165   gst_iterator_free (it);
8166
8167   return g_value_get_boolean (&res);
8168 }
8169
8170 static void
8171 gst_qtdemux_request_protection_context (GstQTDemux * qtdemux,
8172     QtDemuxStream * stream)
8173 {
8174   GstQuery *query;
8175   GstContext *ctxt;
8176   GstElement *element = GST_ELEMENT (qtdemux);
8177   GstStructure *st;
8178   gchar **filtered_sys_ids;
8179   GValue event_list = G_VALUE_INIT;
8180   GList *walk;
8181
8182   /* 1. Check if we already have the context. */
8183   if (qtdemux->preferred_protection_system_id != NULL) {
8184     GST_LOG_OBJECT (element,
8185         "already have the protection context, no need to request it again");
8186     return;
8187   }
8188
8189   g_ptr_array_add (qtdemux->protection_system_ids, NULL);
8190   filtered_sys_ids = gst_protection_filter_systems_by_available_decryptors (
8191       (const gchar **) qtdemux->protection_system_ids->pdata);
8192
8193   g_ptr_array_remove_index (qtdemux->protection_system_ids,
8194       qtdemux->protection_system_ids->len - 1);
8195   GST_TRACE_OBJECT (qtdemux, "detected %u protection systems, we have "
8196       "decryptors for %u of them, running context request",
8197       qtdemux->protection_system_ids->len,
8198       filtered_sys_ids ? g_strv_length (filtered_sys_ids) : 0);
8199
8200
8201   if (stream->protection_scheme_event_queue.length) {
8202     GST_TRACE_OBJECT (qtdemux, "using stream event queue, length %u",
8203         stream->protection_scheme_event_queue.length);
8204     walk = stream->protection_scheme_event_queue.tail;
8205   } else {
8206     GST_TRACE_OBJECT (qtdemux, "using demuxer event queue, length %u",
8207         qtdemux->protection_event_queue.length);
8208     walk = qtdemux->protection_event_queue.tail;
8209   }
8210
8211   g_value_init (&event_list, GST_TYPE_LIST);
8212   for (; walk; walk = g_list_previous (walk)) {
8213     GValue *event_value = g_new0 (GValue, 1);
8214     g_value_init (event_value, GST_TYPE_EVENT);
8215     g_value_set_boxed (event_value, walk->data);
8216     gst_value_list_append_and_take_value (&event_list, event_value);
8217   }
8218
8219   /*  2a) Query downstream with GST_QUERY_CONTEXT for the context and
8220    *      check if downstream already has a context of the specific type
8221    *  2b) Query upstream as above.
8222    */
8223   query = gst_query_new_context ("drm-preferred-decryption-system-id");
8224   st = gst_query_writable_structure (query);
8225   gst_structure_set (st, "track-id", G_TYPE_UINT, stream->track_id,
8226       "available-stream-encryption-systems", G_TYPE_STRV, filtered_sys_ids,
8227       NULL);
8228   gst_structure_set_value (st, "stream-encryption-events", &event_list);
8229   if (gst_qtdemux_run_query (element, query, GST_PAD_SRC)) {
8230     gst_query_parse_context (query, &ctxt);
8231     GST_INFO_OBJECT (element, "found context (%p) in downstream query", ctxt);
8232     gst_element_set_context (element, ctxt);
8233   } else if (gst_qtdemux_run_query (element, query, GST_PAD_SINK)) {
8234     gst_query_parse_context (query, &ctxt);
8235     GST_INFO_OBJECT (element, "found context (%p) in upstream query", ctxt);
8236     gst_element_set_context (element, ctxt);
8237   } else {
8238     /* 3) Post a GST_MESSAGE_NEED_CONTEXT message on the bus with
8239      *    the required context type and afterwards check if a
8240      *    usable context was set now as in 1). The message could
8241      *    be handled by the parent bins of the element and the
8242      *    application.
8243      */
8244     GstMessage *msg;
8245
8246     GST_INFO_OBJECT (element, "posting need context message");
8247     msg = gst_message_new_need_context (GST_OBJECT_CAST (element),
8248         "drm-preferred-decryption-system-id");
8249     st = (GstStructure *) gst_message_get_structure (msg);
8250     gst_structure_set (st, "track-id", G_TYPE_UINT, stream->track_id,
8251         "available-stream-encryption-systems", G_TYPE_STRV, filtered_sys_ids,
8252         NULL);
8253
8254     gst_structure_set_value (st, "stream-encryption-events", &event_list);
8255     gst_element_post_message (element, msg);
8256   }
8257
8258   g_strfreev (filtered_sys_ids);
8259   g_value_unset (&event_list);
8260   gst_query_unref (query);
8261 }
8262
8263 static gboolean
8264 gst_qtdemux_configure_protected_caps (GstQTDemux * qtdemux,
8265     QtDemuxStream * stream)
8266 {
8267   GstStructure *s;
8268   const gchar *selected_system = NULL;
8269
8270   g_return_val_if_fail (qtdemux != NULL, FALSE);
8271   g_return_val_if_fail (stream != NULL, FALSE);
8272   g_return_val_if_fail (gst_caps_get_size (CUR_STREAM (stream)->caps) == 1,
8273       FALSE);
8274
8275   if (stream->protection_scheme_type != FOURCC_cenc) {
8276     GST_ERROR_OBJECT (qtdemux,
8277         "unsupported protection scheme: %" GST_FOURCC_FORMAT,
8278         GST_FOURCC_ARGS (stream->protection_scheme_type));
8279     return FALSE;
8280   }
8281   if (qtdemux->protection_system_ids == NULL) {
8282     GST_ERROR_OBJECT (qtdemux, "stream is protected using cenc, but no "
8283         "cenc protection system information has been found");
8284     return FALSE;
8285   }
8286
8287   gst_qtdemux_request_protection_context (qtdemux, stream);
8288   if (qtdemux->preferred_protection_system_id != NULL) {
8289     const gchar *preferred_system_array[] =
8290         { qtdemux->preferred_protection_system_id, NULL };
8291
8292     selected_system = gst_protection_select_system (preferred_system_array);
8293
8294     if (selected_system) {
8295       GST_TRACE_OBJECT (qtdemux, "selected preferred system %s",
8296           qtdemux->preferred_protection_system_id);
8297     } else {
8298       GST_WARNING_OBJECT (qtdemux, "could not select preferred system %s "
8299           "because there is no available decryptor",
8300           qtdemux->preferred_protection_system_id);
8301     }
8302   }
8303
8304   if (!selected_system) {
8305     g_ptr_array_add (qtdemux->protection_system_ids, NULL);
8306     selected_system = gst_protection_select_system ((const gchar **)
8307         qtdemux->protection_system_ids->pdata);
8308     g_ptr_array_remove_index (qtdemux->protection_system_ids,
8309         qtdemux->protection_system_ids->len - 1);
8310   }
8311
8312   if (!selected_system) {
8313     GST_ERROR_OBJECT (qtdemux, "stream is protected, but no "
8314         "suitable decryptor element has been found");
8315     return FALSE;
8316   }
8317
8318   GST_DEBUG_OBJECT (qtdemux, "selected protection system is %s",
8319       selected_system);
8320
8321   s = gst_caps_get_structure (CUR_STREAM (stream)->caps, 0);
8322   if (!gst_structure_has_name (s, "application/x-cenc")) {
8323     gst_structure_set (s,
8324         "original-media-type", G_TYPE_STRING, gst_structure_get_name (s),
8325         GST_PROTECTION_SYSTEM_ID_CAPS_FIELD, G_TYPE_STRING, selected_system,
8326         NULL);
8327     gst_structure_set_name (s, "application/x-cenc");
8328   }
8329   return TRUE;
8330 }
8331
8332 static gboolean
8333 gst_qtdemux_guess_framerate (GstQTDemux * qtdemux, QtDemuxStream * stream)
8334 {
8335   /* fps is calculated base on the duration of the average framerate since
8336    * qt does not have a fixed framerate. */
8337   gboolean fps_available = TRUE;
8338   guint32 first_duration = 0;
8339
8340   if (stream->n_samples > 0)
8341     first_duration = stream->samples[0].duration;
8342
8343   if ((stream->n_samples == 1 && first_duration == 0)
8344       || (qtdemux->fragmented && stream->n_samples_moof == 1)) {
8345     /* still frame */
8346     CUR_STREAM (stream)->fps_n = 0;
8347     CUR_STREAM (stream)->fps_d = 1;
8348   } else {
8349     if (stream->duration == 0 || stream->n_samples < 2) {
8350       CUR_STREAM (stream)->fps_n = stream->timescale;
8351       CUR_STREAM (stream)->fps_d = 1;
8352       fps_available = FALSE;
8353     } else {
8354       GstClockTime avg_duration;
8355       guint64 duration;
8356       guint32 n_samples;
8357
8358       /* duration and n_samples can be updated for fragmented format
8359        * so, framerate of fragmented format is calculated using data in a moof */
8360       if (qtdemux->fragmented && stream->n_samples_moof > 0
8361           && stream->duration_moof > 0) {
8362         n_samples = stream->n_samples_moof;
8363         duration = stream->duration_moof;
8364       } else {
8365         n_samples = stream->n_samples;
8366         duration = stream->duration;
8367       }
8368
8369       /* Calculate a framerate, ignoring the first sample which is sometimes truncated */
8370       /* stream->duration is guint64, timescale, n_samples are guint32 */
8371       avg_duration =
8372           gst_util_uint64_scale_round (duration -
8373           first_duration, GST_SECOND,
8374           (guint64) (stream->timescale) * (n_samples - 1));
8375
8376       GST_LOG_OBJECT (qtdemux,
8377           "Calculating avg sample duration based on stream (or moof) duration %"
8378           G_GUINT64_FORMAT
8379           " minus first sample %u, leaving %d samples gives %"
8380           GST_TIME_FORMAT, duration, first_duration,
8381           n_samples - 1, GST_TIME_ARGS (avg_duration));
8382
8383       gst_video_guess_framerate (avg_duration, &CUR_STREAM (stream)->fps_n,
8384           &CUR_STREAM (stream)->fps_d);
8385
8386       GST_DEBUG_OBJECT (qtdemux,
8387           "Calculating framerate, timescale %u gave fps_n %d fps_d %d",
8388           stream->timescale, CUR_STREAM (stream)->fps_n,
8389           CUR_STREAM (stream)->fps_d);
8390     }
8391   }
8392
8393   return fps_available;
8394 }
8395
8396 static gboolean
8397 gst_qtdemux_configure_stream (GstQTDemux * qtdemux, QtDemuxStream * stream)
8398 {
8399   if (stream->subtype == FOURCC_vide) {
8400     gboolean fps_available = gst_qtdemux_guess_framerate (qtdemux, stream);
8401
8402     if (CUR_STREAM (stream)->caps) {
8403       CUR_STREAM (stream)->caps =
8404           gst_caps_make_writable (CUR_STREAM (stream)->caps);
8405
8406       if (CUR_STREAM (stream)->width && CUR_STREAM (stream)->height)
8407         gst_caps_set_simple (CUR_STREAM (stream)->caps,
8408             "width", G_TYPE_INT, CUR_STREAM (stream)->width,
8409             "height", G_TYPE_INT, CUR_STREAM (stream)->height, NULL);
8410
8411       /* set framerate if calculated framerate is reliable */
8412       if (fps_available) {
8413         gst_caps_set_simple (CUR_STREAM (stream)->caps,
8414             "framerate", GST_TYPE_FRACTION, CUR_STREAM (stream)->fps_n,
8415             CUR_STREAM (stream)->fps_d, NULL);
8416       }
8417
8418       /* calculate pixel-aspect-ratio using display width and height */
8419       GST_DEBUG_OBJECT (qtdemux,
8420           "video size %dx%d, target display size %dx%d",
8421           CUR_STREAM (stream)->width, CUR_STREAM (stream)->height,
8422           stream->display_width, stream->display_height);
8423       /* qt file might have pasp atom */
8424       if (CUR_STREAM (stream)->par_w > 0 && CUR_STREAM (stream)->par_h > 0) {
8425         GST_DEBUG_OBJECT (qtdemux, "par %d:%d", CUR_STREAM (stream)->par_w,
8426             CUR_STREAM (stream)->par_h);
8427         gst_caps_set_simple (CUR_STREAM (stream)->caps, "pixel-aspect-ratio",
8428             GST_TYPE_FRACTION, CUR_STREAM (stream)->par_w,
8429             CUR_STREAM (stream)->par_h, NULL);
8430       } else if (stream->display_width > 0 && stream->display_height > 0
8431           && CUR_STREAM (stream)->width > 0
8432           && CUR_STREAM (stream)->height > 0) {
8433         gint n, d;
8434
8435         /* calculate the pixel aspect ratio using the display and pixel w/h */
8436         n = stream->display_width * CUR_STREAM (stream)->height;
8437         d = stream->display_height * CUR_STREAM (stream)->width;
8438         if (n == d)
8439           n = d = 1;
8440         GST_DEBUG_OBJECT (qtdemux, "setting PAR to %d/%d", n, d);
8441         CUR_STREAM (stream)->par_w = n;
8442         CUR_STREAM (stream)->par_h = d;
8443         gst_caps_set_simple (CUR_STREAM (stream)->caps, "pixel-aspect-ratio",
8444             GST_TYPE_FRACTION, CUR_STREAM (stream)->par_w,
8445             CUR_STREAM (stream)->par_h, NULL);
8446       }
8447
8448       if (CUR_STREAM (stream)->interlace_mode > 0) {
8449         if (CUR_STREAM (stream)->interlace_mode == 1) {
8450           gst_caps_set_simple (CUR_STREAM (stream)->caps, "interlace-mode",
8451               G_TYPE_STRING, "progressive", NULL);
8452         } else if (CUR_STREAM (stream)->interlace_mode == 2) {
8453           gst_caps_set_simple (CUR_STREAM (stream)->caps, "interlace-mode",
8454               G_TYPE_STRING, "interleaved", NULL);
8455           if (CUR_STREAM (stream)->field_order == 9) {
8456             gst_caps_set_simple (CUR_STREAM (stream)->caps, "field-order",
8457                 G_TYPE_STRING, "top-field-first", NULL);
8458           } else if (CUR_STREAM (stream)->field_order == 14) {
8459             gst_caps_set_simple (CUR_STREAM (stream)->caps, "field-order",
8460                 G_TYPE_STRING, "bottom-field-first", NULL);
8461           }
8462         }
8463       }
8464
8465       /* Create incomplete colorimetry here if needed */
8466       if (CUR_STREAM (stream)->colorimetry.range ||
8467           CUR_STREAM (stream)->colorimetry.matrix ||
8468           CUR_STREAM (stream)->colorimetry.transfer
8469           || CUR_STREAM (stream)->colorimetry.primaries) {
8470         gchar *colorimetry =
8471             gst_video_colorimetry_to_string (&CUR_STREAM (stream)->colorimetry);
8472         gst_caps_set_simple (CUR_STREAM (stream)->caps, "colorimetry",
8473             G_TYPE_STRING, colorimetry, NULL);
8474         g_free (colorimetry);
8475       }
8476
8477       if (stream->multiview_mode != GST_VIDEO_MULTIVIEW_MODE_NONE) {
8478         guint par_w = 1, par_h = 1;
8479
8480         if (CUR_STREAM (stream)->par_w > 0 && CUR_STREAM (stream)->par_h > 0) {
8481           par_w = CUR_STREAM (stream)->par_w;
8482           par_h = CUR_STREAM (stream)->par_h;
8483         }
8484
8485         if (gst_video_multiview_guess_half_aspect (stream->multiview_mode,
8486                 CUR_STREAM (stream)->width, CUR_STREAM (stream)->height, par_w,
8487                 par_h)) {
8488           stream->multiview_flags |= GST_VIDEO_MULTIVIEW_FLAGS_HALF_ASPECT;
8489         }
8490
8491         gst_caps_set_simple (CUR_STREAM (stream)->caps,
8492             "multiview-mode", G_TYPE_STRING,
8493             gst_video_multiview_mode_to_caps_string (stream->multiview_mode),
8494             "multiview-flags", GST_TYPE_VIDEO_MULTIVIEW_FLAGSET,
8495             stream->multiview_flags, GST_FLAG_SET_MASK_EXACT, NULL);
8496       }
8497     }
8498   }
8499
8500   else if (stream->subtype == FOURCC_soun) {
8501     if (CUR_STREAM (stream)->caps) {
8502       CUR_STREAM (stream)->caps =
8503           gst_caps_make_writable (CUR_STREAM (stream)->caps);
8504       if (CUR_STREAM (stream)->rate > 0)
8505         gst_caps_set_simple (CUR_STREAM (stream)->caps,
8506             "rate", G_TYPE_INT, (int) CUR_STREAM (stream)->rate, NULL);
8507       if (CUR_STREAM (stream)->n_channels > 0)
8508         gst_caps_set_simple (CUR_STREAM (stream)->caps,
8509             "channels", G_TYPE_INT, CUR_STREAM (stream)->n_channels, NULL);
8510       if (CUR_STREAM (stream)->n_channels > 2) {
8511         /* FIXME: Need to parse the 'chan' atom to get channel layouts
8512          * correctly; this is just the minimum we can do - assume
8513          * we don't actually have any channel positions. */
8514         gst_caps_set_simple (CUR_STREAM (stream)->caps,
8515             "channel-mask", GST_TYPE_BITMASK, G_GUINT64_CONSTANT (0), NULL);
8516       }
8517     }
8518   }
8519
8520   else if (stream->subtype == FOURCC_clcp) {
8521     gboolean fps_available = gst_qtdemux_guess_framerate (qtdemux, stream);
8522
8523     if (CUR_STREAM (stream)->caps) {
8524       CUR_STREAM (stream)->caps =
8525           gst_caps_make_writable (CUR_STREAM (stream)->caps);
8526
8527       /* set framerate if calculated framerate is reliable */
8528       if (fps_available) {
8529         gst_caps_set_simple (CUR_STREAM (stream)->caps,
8530             "framerate", GST_TYPE_FRACTION, CUR_STREAM (stream)->fps_n,
8531             CUR_STREAM (stream)->fps_d, NULL);
8532       }
8533     }
8534   }
8535
8536   if (stream->pad) {
8537     GstCaps *prev_caps = NULL;
8538
8539     GST_PAD_ELEMENT_PRIVATE (stream->pad) = stream;
8540     gst_pad_set_event_function (stream->pad, gst_qtdemux_handle_src_event);
8541     gst_pad_set_query_function (stream->pad, gst_qtdemux_handle_src_query);
8542     gst_pad_set_active (stream->pad, TRUE);
8543
8544     gst_pad_use_fixed_caps (stream->pad);
8545
8546     if (stream->protected) {
8547       if (!gst_qtdemux_configure_protected_caps (qtdemux, stream)) {
8548         GST_ERROR_OBJECT (qtdemux,
8549             "Failed to configure protected stream caps.");
8550         return FALSE;
8551       }
8552     }
8553
8554     GST_DEBUG_OBJECT (qtdemux, "setting caps %" GST_PTR_FORMAT,
8555         CUR_STREAM (stream)->caps);
8556     if (stream->new_stream) {
8557       GstEvent *event;
8558       GstStreamFlags stream_flags = GST_STREAM_FLAG_NONE;
8559
8560       event =
8561           gst_pad_get_sticky_event (qtdemux->sinkpad, GST_EVENT_STREAM_START,
8562           0);
8563       if (event) {
8564         gst_event_parse_stream_flags (event, &stream_flags);
8565         if (gst_event_parse_group_id (event, &qtdemux->group_id))
8566           qtdemux->have_group_id = TRUE;
8567         else
8568           qtdemux->have_group_id = FALSE;
8569         gst_event_unref (event);
8570       } else if (!qtdemux->have_group_id) {
8571         qtdemux->have_group_id = TRUE;
8572         qtdemux->group_id = gst_util_group_id_next ();
8573       }
8574
8575       stream->new_stream = FALSE;
8576       event = gst_event_new_stream_start (stream->stream_id);
8577       if (qtdemux->have_group_id)
8578         gst_event_set_group_id (event, qtdemux->group_id);
8579       if (stream->disabled)
8580         stream_flags |= GST_STREAM_FLAG_UNSELECT;
8581       if (CUR_STREAM (stream)->sparse) {
8582         stream_flags |= GST_STREAM_FLAG_SPARSE;
8583       } else {
8584         stream_flags &= ~GST_STREAM_FLAG_SPARSE;
8585       }
8586       gst_event_set_stream_flags (event, stream_flags);
8587       gst_pad_push_event (stream->pad, event);
8588     }
8589
8590     prev_caps = gst_pad_get_current_caps (stream->pad);
8591
8592     if (CUR_STREAM (stream)->caps) {
8593       if (!prev_caps
8594           || !gst_caps_is_equal_fixed (prev_caps, CUR_STREAM (stream)->caps)) {
8595         GST_DEBUG_OBJECT (qtdemux, "setting caps %" GST_PTR_FORMAT,
8596             CUR_STREAM (stream)->caps);
8597         gst_pad_set_caps (stream->pad, CUR_STREAM (stream)->caps);
8598       } else {
8599         GST_DEBUG_OBJECT (qtdemux, "ignore duplicated caps");
8600       }
8601     } else {
8602       GST_WARNING_OBJECT (qtdemux, "stream without caps");
8603     }
8604
8605     if (prev_caps)
8606       gst_caps_unref (prev_caps);
8607     stream->new_caps = FALSE;
8608   }
8609   return TRUE;
8610 }
8611
8612 static void
8613 gst_qtdemux_stream_check_and_change_stsd_index (GstQTDemux * demux,
8614     QtDemuxStream * stream)
8615 {
8616   if (stream->cur_stsd_entry_index == stream->stsd_sample_description_id)
8617     return;
8618
8619   GST_DEBUG_OBJECT (stream->pad, "Changing stsd index from '%u' to '%u'",
8620       stream->cur_stsd_entry_index, stream->stsd_sample_description_id);
8621   if (G_UNLIKELY (stream->stsd_sample_description_id >=
8622           stream->stsd_entries_length)) {
8623     GST_ELEMENT_ERROR (demux, STREAM, DEMUX,
8624         (_("This file is invalid and cannot be played.")),
8625         ("New sample description id is out of bounds (%d >= %d)",
8626             stream->stsd_sample_description_id, stream->stsd_entries_length));
8627   } else {
8628     stream->cur_stsd_entry_index = stream->stsd_sample_description_id;
8629     stream->new_caps = TRUE;
8630   }
8631 }
8632
8633 static gboolean
8634 gst_qtdemux_add_stream (GstQTDemux * qtdemux,
8635     QtDemuxStream * stream, GstTagList * list)
8636 {
8637   gboolean ret = TRUE;
8638
8639   if (stream->subtype == FOURCC_vide) {
8640     gchar *name = g_strdup_printf ("video_%u", qtdemux->n_video_streams);
8641
8642     stream->pad =
8643         gst_pad_new_from_static_template (&gst_qtdemux_videosrc_template, name);
8644     g_free (name);
8645
8646     if (!gst_qtdemux_configure_stream (qtdemux, stream)) {
8647       gst_object_unref (stream->pad);
8648       stream->pad = NULL;
8649       ret = FALSE;
8650       goto done;
8651     }
8652
8653     qtdemux->n_video_streams++;
8654   } else if (stream->subtype == FOURCC_soun) {
8655     gchar *name = g_strdup_printf ("audio_%u", qtdemux->n_audio_streams);
8656
8657     stream->pad =
8658         gst_pad_new_from_static_template (&gst_qtdemux_audiosrc_template, name);
8659     g_free (name);
8660     if (!gst_qtdemux_configure_stream (qtdemux, stream)) {
8661       gst_object_unref (stream->pad);
8662       stream->pad = NULL;
8663       ret = FALSE;
8664       goto done;
8665     }
8666     qtdemux->n_audio_streams++;
8667   } else if (stream->subtype == FOURCC_strm) {
8668     GST_DEBUG_OBJECT (qtdemux, "stream type, not creating pad");
8669   } else if (stream->subtype == FOURCC_subp || stream->subtype == FOURCC_text
8670       || stream->subtype == FOURCC_sbtl || stream->subtype == FOURCC_subt
8671       || stream->subtype == FOURCC_clcp) {
8672     gchar *name = g_strdup_printf ("subtitle_%u", qtdemux->n_sub_streams);
8673
8674     stream->pad =
8675         gst_pad_new_from_static_template (&gst_qtdemux_subsrc_template, name);
8676     g_free (name);
8677     if (!gst_qtdemux_configure_stream (qtdemux, stream)) {
8678       gst_object_unref (stream->pad);
8679       stream->pad = NULL;
8680       ret = FALSE;
8681       goto done;
8682     }
8683     qtdemux->n_sub_streams++;
8684   } else if (CUR_STREAM (stream)->caps) {
8685     gchar *name = g_strdup_printf ("video_%u", qtdemux->n_video_streams);
8686
8687     stream->pad =
8688         gst_pad_new_from_static_template (&gst_qtdemux_videosrc_template, name);
8689     g_free (name);
8690     if (!gst_qtdemux_configure_stream (qtdemux, stream)) {
8691       gst_object_unref (stream->pad);
8692       stream->pad = NULL;
8693       ret = FALSE;
8694       goto done;
8695     }
8696     qtdemux->n_video_streams++;
8697   } else {
8698     GST_DEBUG_OBJECT (qtdemux, "unknown stream type");
8699     goto done;
8700   }
8701
8702   if (stream->pad) {
8703     GList *l;
8704
8705     GST_DEBUG_OBJECT (qtdemux, "adding pad %s %p to qtdemux %p",
8706         GST_OBJECT_NAME (stream->pad), stream->pad, qtdemux);
8707     gst_element_add_pad (GST_ELEMENT_CAST (qtdemux), stream->pad);
8708     gst_flow_combiner_add_pad (qtdemux->flowcombiner, stream->pad);
8709
8710     if (stream->stream_tags)
8711       gst_tag_list_unref (stream->stream_tags);
8712     stream->stream_tags = list;
8713     list = NULL;
8714     /* global tags go on each pad anyway */
8715     stream->send_global_tags = TRUE;
8716     /* send upstream GST_EVENT_PROTECTION events that were received before
8717        this source pad was created */
8718     for (l = qtdemux->protection_event_queue.head; l != NULL; l = l->next)
8719       gst_pad_push_event (stream->pad, gst_event_ref (l->data));
8720   }
8721 done:
8722   if (list)
8723     gst_tag_list_unref (list);
8724   return ret;
8725 }
8726
8727 /* find next atom with @fourcc starting at @offset */
8728 static GstFlowReturn
8729 qtdemux_find_atom (GstQTDemux * qtdemux, guint64 * offset,
8730     guint64 * length, guint32 fourcc)
8731 {
8732   GstFlowReturn ret;
8733   guint32 lfourcc;
8734   GstBuffer *buf;
8735
8736   GST_LOG_OBJECT (qtdemux, "finding fourcc %" GST_FOURCC_FORMAT " at offset %"
8737       G_GUINT64_FORMAT, GST_FOURCC_ARGS (fourcc), *offset);
8738
8739   while (TRUE) {
8740     GstMapInfo map;
8741
8742     buf = NULL;
8743     ret = gst_pad_pull_range (qtdemux->sinkpad, *offset, 16, &buf);
8744     if (G_UNLIKELY (ret != GST_FLOW_OK))
8745       goto locate_failed;
8746     if (G_UNLIKELY (gst_buffer_get_size (buf) != 16)) {
8747       /* likely EOF */
8748       ret = GST_FLOW_EOS;
8749       gst_buffer_unref (buf);
8750       goto locate_failed;
8751     }
8752     gst_buffer_map (buf, &map, GST_MAP_READ);
8753     extract_initial_length_and_fourcc (map.data, 16, length, &lfourcc);
8754     gst_buffer_unmap (buf, &map);
8755     gst_buffer_unref (buf);
8756
8757     if (G_UNLIKELY (*length == 0)) {
8758       GST_DEBUG_OBJECT (qtdemux, "invalid length 0");
8759       ret = GST_FLOW_ERROR;
8760       goto locate_failed;
8761     }
8762
8763     if (lfourcc == fourcc) {
8764       GST_DEBUG_OBJECT (qtdemux, "found fourcc at offset %" G_GUINT64_FORMAT,
8765           *offset);
8766       break;
8767     } else {
8768       GST_LOG_OBJECT (qtdemux,
8769           "skipping atom '%" GST_FOURCC_FORMAT "' at %" G_GUINT64_FORMAT,
8770           GST_FOURCC_ARGS (fourcc), *offset);
8771       *offset += *length;
8772     }
8773   }
8774
8775   return GST_FLOW_OK;
8776
8777 locate_failed:
8778   {
8779     /* might simply have had last one */
8780     GST_DEBUG_OBJECT (qtdemux, "fourcc not found");
8781     return ret;
8782   }
8783 }
8784
8785 /* should only do something in pull mode */
8786 /* call with OBJECT lock */
8787 static GstFlowReturn
8788 qtdemux_add_fragmented_samples (GstQTDemux * qtdemux)
8789 {
8790   guint64 length, offset;
8791   GstBuffer *buf = NULL;
8792   GstFlowReturn ret = GST_FLOW_OK;
8793   GstFlowReturn res = GST_FLOW_OK;
8794   GstMapInfo map;
8795
8796   offset = qtdemux->moof_offset;
8797   GST_DEBUG_OBJECT (qtdemux, "next moof at offset %" G_GUINT64_FORMAT, offset);
8798
8799   if (!offset) {
8800     GST_DEBUG_OBJECT (qtdemux, "no next moof");
8801     return GST_FLOW_EOS;
8802   }
8803
8804   /* best not do pull etc with lock held */
8805   GST_OBJECT_UNLOCK (qtdemux);
8806
8807   ret = qtdemux_find_atom (qtdemux, &offset, &length, FOURCC_moof);
8808   if (ret != GST_FLOW_OK)
8809     goto flow_failed;
8810
8811   ret = gst_qtdemux_pull_atom (qtdemux, offset, length, &buf);
8812   if (G_UNLIKELY (ret != GST_FLOW_OK))
8813     goto flow_failed;
8814   gst_buffer_map (buf, &map, GST_MAP_READ);
8815   if (!qtdemux_parse_moof (qtdemux, map.data, map.size, offset, NULL)) {
8816     gst_buffer_unmap (buf, &map);
8817     gst_buffer_unref (buf);
8818     buf = NULL;
8819     goto parse_failed;
8820   }
8821
8822   gst_buffer_unmap (buf, &map);
8823   gst_buffer_unref (buf);
8824   buf = NULL;
8825
8826   offset += length;
8827   /* look for next moof */
8828   ret = qtdemux_find_atom (qtdemux, &offset, &length, FOURCC_moof);
8829   if (G_UNLIKELY (ret != GST_FLOW_OK))
8830     goto flow_failed;
8831
8832 exit:
8833   GST_OBJECT_LOCK (qtdemux);
8834
8835   qtdemux->moof_offset = offset;
8836
8837   return res;
8838
8839 parse_failed:
8840   {
8841     GST_DEBUG_OBJECT (qtdemux, "failed to parse moof");
8842     offset = 0;
8843     res = GST_FLOW_ERROR;
8844     goto exit;
8845   }
8846 flow_failed:
8847   {
8848     /* maybe upstream temporarily flushing */
8849     if (ret != GST_FLOW_FLUSHING) {
8850       GST_DEBUG_OBJECT (qtdemux, "no next moof");
8851       offset = 0;
8852     } else {
8853       GST_DEBUG_OBJECT (qtdemux, "upstream WRONG_STATE");
8854       /* resume at current position next time */
8855     }
8856     res = ret;
8857     goto exit;
8858   }
8859 }
8860
8861 /* initialise bytereaders for stbl sub-atoms */
8862 static gboolean
8863 qtdemux_stbl_init (GstQTDemux * qtdemux, QtDemuxStream * stream, GNode * stbl)
8864 {
8865   stream->stbl_index = -1;      /* no samples have yet been parsed */
8866   stream->sample_index = -1;
8867
8868   /* time-to-sample atom */
8869   if (!qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stts, &stream->stts))
8870     goto corrupt_file;
8871
8872   /* copy atom data into a new buffer for later use */
8873   stream->stts.data = g_memdup (stream->stts.data, stream->stts.size);
8874
8875   /* skip version + flags */
8876   if (!gst_byte_reader_skip (&stream->stts, 1 + 3) ||
8877       !gst_byte_reader_get_uint32_be (&stream->stts, &stream->n_sample_times))
8878     goto corrupt_file;
8879   GST_LOG_OBJECT (qtdemux, "%u timestamp blocks", stream->n_sample_times);
8880
8881   /* make sure there's enough data */
8882   if (!qt_atom_parser_has_chunks (&stream->stts, stream->n_sample_times, 8)) {
8883     stream->n_sample_times = gst_byte_reader_get_remaining (&stream->stts) / 8;
8884     GST_LOG_OBJECT (qtdemux, "overriding to %u timestamp blocks",
8885         stream->n_sample_times);
8886     if (!stream->n_sample_times)
8887       goto corrupt_file;
8888   }
8889
8890   /* sync sample atom */
8891   stream->stps_present = FALSE;
8892   if ((stream->stss_present =
8893           ! !qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stss,
8894               &stream->stss) ? TRUE : FALSE) == TRUE) {
8895     /* copy atom data into a new buffer for later use */
8896     stream->stss.data = g_memdup (stream->stss.data, stream->stss.size);
8897
8898     /* skip version + flags */
8899     if (!gst_byte_reader_skip (&stream->stss, 1 + 3) ||
8900         !gst_byte_reader_get_uint32_be (&stream->stss, &stream->n_sample_syncs))
8901       goto corrupt_file;
8902
8903     if (stream->n_sample_syncs) {
8904       /* make sure there's enough data */
8905       if (!qt_atom_parser_has_chunks (&stream->stss, stream->n_sample_syncs, 4))
8906         goto corrupt_file;
8907     }
8908
8909     /* partial sync sample atom */
8910     if ((stream->stps_present =
8911             ! !qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stps,
8912                 &stream->stps) ? TRUE : FALSE) == TRUE) {
8913       /* copy atom data into a new buffer for later use */
8914       stream->stps.data = g_memdup (stream->stps.data, stream->stps.size);
8915
8916       /* skip version + flags */
8917       if (!gst_byte_reader_skip (&stream->stps, 1 + 3) ||
8918           !gst_byte_reader_get_uint32_be (&stream->stps,
8919               &stream->n_sample_partial_syncs))
8920         goto corrupt_file;
8921
8922       /* if there are no entries, the stss table contains the real
8923        * sync samples */
8924       if (stream->n_sample_partial_syncs) {
8925         /* make sure there's enough data */
8926         if (!qt_atom_parser_has_chunks (&stream->stps,
8927                 stream->n_sample_partial_syncs, 4))
8928           goto corrupt_file;
8929       }
8930     }
8931   }
8932
8933   /* sample size */
8934   if (!qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stsz, &stream->stsz))
8935     goto no_samples;
8936
8937   /* copy atom data into a new buffer for later use */
8938   stream->stsz.data = g_memdup (stream->stsz.data, stream->stsz.size);
8939
8940   /* skip version + flags */
8941   if (!gst_byte_reader_skip (&stream->stsz, 1 + 3) ||
8942       !gst_byte_reader_get_uint32_be (&stream->stsz, &stream->sample_size))
8943     goto corrupt_file;
8944
8945   if (!gst_byte_reader_get_uint32_be (&stream->stsz, &stream->n_samples))
8946     goto corrupt_file;
8947
8948   if (!stream->n_samples)
8949     goto no_samples;
8950
8951   /* sample-to-chunk atom */
8952   if (!qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stsc, &stream->stsc))
8953     goto corrupt_file;
8954
8955   /* copy atom data into a new buffer for later use */
8956   stream->stsc.data = g_memdup (stream->stsc.data, stream->stsc.size);
8957
8958   /* skip version + flags */
8959   if (!gst_byte_reader_skip (&stream->stsc, 1 + 3) ||
8960       !gst_byte_reader_get_uint32_be (&stream->stsc,
8961           &stream->n_samples_per_chunk))
8962     goto corrupt_file;
8963
8964   GST_DEBUG_OBJECT (qtdemux, "n_samples_per_chunk %u",
8965       stream->n_samples_per_chunk);
8966
8967   /* make sure there's enough data */
8968   if (!qt_atom_parser_has_chunks (&stream->stsc, stream->n_samples_per_chunk,
8969           12))
8970     goto corrupt_file;
8971
8972
8973   /* chunk offset */
8974   if (qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stco, &stream->stco))
8975     stream->co_size = sizeof (guint32);
8976   else if (qtdemux_tree_get_child_by_type_full (stbl, FOURCC_co64,
8977           &stream->stco))
8978     stream->co_size = sizeof (guint64);
8979   else
8980     goto corrupt_file;
8981
8982   /* copy atom data into a new buffer for later use */
8983   stream->stco.data = g_memdup (stream->stco.data, stream->stco.size);
8984
8985   /* skip version + flags */
8986   if (!gst_byte_reader_skip (&stream->stco, 1 + 3))
8987     goto corrupt_file;
8988
8989   /* chunks_are_samples == TRUE means treat chunks as samples */
8990   stream->chunks_are_samples = stream->sample_size
8991       && !CUR_STREAM (stream)->sampled;
8992   if (stream->chunks_are_samples) {
8993     /* treat chunks as samples */
8994     if (!gst_byte_reader_get_uint32_be (&stream->stco, &stream->n_samples))
8995       goto corrupt_file;
8996   } else {
8997     /* skip number of entries */
8998     if (!gst_byte_reader_skip (&stream->stco, 4))
8999       goto corrupt_file;
9000
9001     /* make sure there are enough data in the stsz atom */
9002     if (!stream->sample_size) {
9003       /* different sizes for each sample */
9004       if (!qt_atom_parser_has_chunks (&stream->stsz, stream->n_samples, 4))
9005         goto corrupt_file;
9006     }
9007   }
9008
9009   GST_DEBUG_OBJECT (qtdemux, "allocating n_samples %u * %u (%.2f MB)",
9010       stream->n_samples, (guint) sizeof (QtDemuxSample),
9011       stream->n_samples * sizeof (QtDemuxSample) / (1024.0 * 1024.0));
9012
9013   if (stream->n_samples >=
9014       QTDEMUX_MAX_SAMPLE_INDEX_SIZE / sizeof (QtDemuxSample)) {
9015     GST_WARNING_OBJECT (qtdemux, "not allocating index of %d samples, would "
9016         "be larger than %uMB (broken file?)", stream->n_samples,
9017         QTDEMUX_MAX_SAMPLE_INDEX_SIZE >> 20);
9018     return FALSE;
9019   }
9020
9021   g_assert (stream->samples == NULL);
9022   stream->samples = g_try_new0 (QtDemuxSample, stream->n_samples);
9023   if (!stream->samples) {
9024     GST_WARNING_OBJECT (qtdemux, "failed to allocate %d samples",
9025         stream->n_samples);
9026     return FALSE;
9027   }
9028
9029   /* composition time-to-sample */
9030   if ((stream->ctts_present =
9031           ! !qtdemux_tree_get_child_by_type_full (stbl, FOURCC_ctts,
9032               &stream->ctts) ? TRUE : FALSE) == TRUE) {
9033     GstByteReader cslg = GST_BYTE_READER_INIT (NULL, 0);
9034
9035     /* copy atom data into a new buffer for later use */
9036     stream->ctts.data = g_memdup (stream->ctts.data, stream->ctts.size);
9037
9038     /* skip version + flags */
9039     if (!gst_byte_reader_skip (&stream->ctts, 1 + 3)
9040         || !gst_byte_reader_get_uint32_be (&stream->ctts,
9041             &stream->n_composition_times))
9042       goto corrupt_file;
9043
9044     /* make sure there's enough data */
9045     if (!qt_atom_parser_has_chunks (&stream->ctts, stream->n_composition_times,
9046             4 + 4))
9047       goto corrupt_file;
9048
9049     /* This is optional, if missing we iterate the ctts */
9050     if (qtdemux_tree_get_child_by_type_full (stbl, FOURCC_cslg, &cslg)) {
9051       if (!gst_byte_reader_skip (&cslg, 1 + 3)
9052           || !gst_byte_reader_get_uint32_be (&cslg, &stream->cslg_shift)) {
9053         g_free ((gpointer) cslg.data);
9054         goto corrupt_file;
9055       }
9056     } else {
9057       gint32 cslg_least = 0;
9058       guint num_entries, pos;
9059       gint i;
9060
9061       pos = gst_byte_reader_get_pos (&stream->ctts);
9062       num_entries = stream->n_composition_times;
9063
9064       stream->cslg_shift = 0;
9065
9066       for (i = 0; i < num_entries; i++) {
9067         gint32 offset;
9068
9069         gst_byte_reader_skip_unchecked (&stream->ctts, 4);
9070         offset = gst_byte_reader_get_int32_be_unchecked (&stream->ctts);
9071         /* HACK: if sample_offset is larger than 2 * duration, ignore the box.
9072          * slightly inaccurate PTS could be more usable than corrupted one */
9073         if (G_UNLIKELY ((ABS (offset) / 2) > stream->duration)) {
9074           GST_WARNING_OBJECT (qtdemux,
9075               "Ignore corrupted ctts, sample_offset %" G_GINT32_FORMAT
9076               " larger than duration %" G_GUINT64_FORMAT,
9077               offset, stream->duration);
9078
9079           stream->cslg_shift = 0;
9080           stream->ctts_present = FALSE;
9081           return TRUE;
9082         }
9083
9084         if (offset < cslg_least)
9085           cslg_least = offset;
9086       }
9087
9088       if (cslg_least < 0)
9089         stream->cslg_shift = ABS (cslg_least);
9090       else
9091         stream->cslg_shift = 0;
9092
9093       /* reset the reader so we can generate sample table */
9094       gst_byte_reader_set_pos (&stream->ctts, pos);
9095     }
9096   } else {
9097     /* Ensure the cslg_shift value is consistent so we can use it
9098      * unconditionnally to produce TS and Segment */
9099     stream->cslg_shift = 0;
9100   }
9101
9102   return TRUE;
9103
9104 corrupt_file:
9105   {
9106     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
9107         (_("This file is corrupt and cannot be played.")), (NULL));
9108     return FALSE;
9109   }
9110 no_samples:
9111   {
9112     gst_qtdemux_stbl_free (stream);
9113     if (!qtdemux->fragmented) {
9114       /* not quite good */
9115       GST_WARNING_OBJECT (qtdemux, "stream has no samples");
9116       return FALSE;
9117     } else {
9118       /* may pick up samples elsewhere */
9119       return TRUE;
9120     }
9121   }
9122 }
9123
9124 /* collect samples from the next sample to be parsed up to sample @n for @stream
9125  * by reading the info from @stbl
9126  *
9127  * This code can be executed from both the streaming thread and the seeking
9128  * thread so it takes the object lock to protect itself
9129  */
9130 static gboolean
9131 qtdemux_parse_samples (GstQTDemux * qtdemux, QtDemuxStream * stream, guint32 n)
9132 {
9133   gint i, j, k;
9134   QtDemuxSample *samples, *first, *cur, *last;
9135   guint32 n_samples_per_chunk;
9136   guint32 n_samples;
9137
9138   GST_LOG_OBJECT (qtdemux, "parsing samples for stream fourcc %"
9139       GST_FOURCC_FORMAT ", pad %s",
9140       GST_FOURCC_ARGS (CUR_STREAM (stream)->fourcc),
9141       stream->pad ? GST_PAD_NAME (stream->pad) : "(NULL)");
9142
9143   n_samples = stream->n_samples;
9144
9145   if (n >= n_samples)
9146     goto out_of_samples;
9147
9148   GST_OBJECT_LOCK (qtdemux);
9149   if (n <= stream->stbl_index)
9150     goto already_parsed;
9151
9152   GST_DEBUG_OBJECT (qtdemux, "parsing up to sample %u", n);
9153
9154   if (!stream->stsz.data) {
9155     /* so we already parsed and passed all the moov samples;
9156      * onto fragmented ones */
9157     g_assert (qtdemux->fragmented);
9158     goto done;
9159   }
9160
9161   /* pointer to the sample table */
9162   samples = stream->samples;
9163
9164   /* starts from -1, moves to the next sample index to parse */
9165   stream->stbl_index++;
9166
9167   /* keep track of the first and last sample to fill */
9168   first = &samples[stream->stbl_index];
9169   last = &samples[n];
9170
9171   if (!stream->chunks_are_samples) {
9172     /* set the sample sizes */
9173     if (stream->sample_size == 0) {
9174       /* different sizes for each sample */
9175       for (cur = first; cur <= last; cur++) {
9176         cur->size = gst_byte_reader_get_uint32_be_unchecked (&stream->stsz);
9177         GST_LOG_OBJECT (qtdemux, "sample %d has size %u",
9178             (guint) (cur - samples), cur->size);
9179       }
9180     } else {
9181       /* samples have the same size */
9182       GST_LOG_OBJECT (qtdemux, "all samples have size %u", stream->sample_size);
9183       for (cur = first; cur <= last; cur++)
9184         cur->size = stream->sample_size;
9185     }
9186   }
9187
9188   n_samples_per_chunk = stream->n_samples_per_chunk;
9189   cur = first;
9190
9191   for (i = stream->stsc_index; i < n_samples_per_chunk; i++) {
9192     guint32 last_chunk;
9193
9194     if (stream->stsc_chunk_index >= stream->last_chunk
9195         || stream->stsc_chunk_index < stream->first_chunk) {
9196       stream->first_chunk =
9197           gst_byte_reader_get_uint32_be_unchecked (&stream->stsc);
9198       stream->samples_per_chunk =
9199           gst_byte_reader_get_uint32_be_unchecked (&stream->stsc);
9200       /* starts from 1 */
9201       stream->stsd_sample_description_id =
9202           gst_byte_reader_get_uint32_be_unchecked (&stream->stsc) - 1;
9203
9204       /* chunk numbers are counted from 1 it seems */
9205       if (G_UNLIKELY (stream->first_chunk == 0))
9206         goto corrupt_file;
9207
9208       --stream->first_chunk;
9209
9210       /* the last chunk of each entry is calculated by taking the first chunk
9211        * of the next entry; except if there is no next, where we fake it with
9212        * INT_MAX */
9213       if (G_UNLIKELY (i == (stream->n_samples_per_chunk - 1))) {
9214         stream->last_chunk = G_MAXUINT32;
9215       } else {
9216         stream->last_chunk =
9217             gst_byte_reader_peek_uint32_be_unchecked (&stream->stsc);
9218         if (G_UNLIKELY (stream->last_chunk == 0))
9219           goto corrupt_file;
9220
9221         --stream->last_chunk;
9222       }
9223
9224       GST_LOG_OBJECT (qtdemux,
9225           "entry %d has first_chunk %d, last_chunk %d, samples_per_chunk %d"
9226           "sample desc ID: %d", i, stream->first_chunk, stream->last_chunk,
9227           stream->samples_per_chunk, stream->stsd_sample_description_id);
9228
9229       if (G_UNLIKELY (stream->last_chunk < stream->first_chunk))
9230         goto corrupt_file;
9231
9232       if (stream->last_chunk != G_MAXUINT32) {
9233         if (!qt_atom_parser_peek_sub (&stream->stco,
9234                 stream->first_chunk * stream->co_size,
9235                 (stream->last_chunk - stream->first_chunk) * stream->co_size,
9236                 &stream->co_chunk))
9237           goto corrupt_file;
9238
9239       } else {
9240         stream->co_chunk = stream->stco;
9241         if (!gst_byte_reader_skip (&stream->co_chunk,
9242                 stream->first_chunk * stream->co_size))
9243           goto corrupt_file;
9244       }
9245
9246       stream->stsc_chunk_index = stream->first_chunk;
9247     }
9248
9249     last_chunk = stream->last_chunk;
9250
9251     if (stream->chunks_are_samples) {
9252       cur = &samples[stream->stsc_chunk_index];
9253
9254       for (j = stream->stsc_chunk_index; j < last_chunk; j++) {
9255         if (j > n) {
9256           /* save state */
9257           stream->stsc_chunk_index = j;
9258           goto done;
9259         }
9260
9261         cur->offset =
9262             qt_atom_parser_get_offset_unchecked (&stream->co_chunk,
9263             stream->co_size);
9264
9265         GST_LOG_OBJECT (qtdemux, "Created entry %d with offset "
9266             "%" G_GUINT64_FORMAT, j, cur->offset);
9267
9268         if (CUR_STREAM (stream)->samples_per_frame > 0 &&
9269             CUR_STREAM (stream)->bytes_per_frame > 0) {
9270           cur->size =
9271               (stream->samples_per_chunk * CUR_STREAM (stream)->n_channels) /
9272               CUR_STREAM (stream)->samples_per_frame *
9273               CUR_STREAM (stream)->bytes_per_frame;
9274         } else {
9275           cur->size = stream->samples_per_chunk;
9276         }
9277
9278         GST_DEBUG_OBJECT (qtdemux,
9279             "keyframe sample %d: timestamp %" GST_TIME_FORMAT ", size %u",
9280             j, GST_TIME_ARGS (QTSTREAMTIME_TO_GSTTIME (stream,
9281                     stream->stco_sample_index)), cur->size);
9282
9283         cur->timestamp = stream->stco_sample_index;
9284         cur->duration = stream->samples_per_chunk;
9285         cur->keyframe = TRUE;
9286         cur++;
9287
9288         stream->stco_sample_index += stream->samples_per_chunk;
9289       }
9290       stream->stsc_chunk_index = j;
9291     } else {
9292       for (j = stream->stsc_chunk_index; j < last_chunk; j++) {
9293         guint32 samples_per_chunk;
9294         guint64 chunk_offset;
9295
9296         if (!stream->stsc_sample_index
9297             && !qt_atom_parser_get_offset (&stream->co_chunk, stream->co_size,
9298                 &stream->chunk_offset))
9299           goto corrupt_file;
9300
9301         samples_per_chunk = stream->samples_per_chunk;
9302         chunk_offset = stream->chunk_offset;
9303
9304         for (k = stream->stsc_sample_index; k < samples_per_chunk; k++) {
9305           GST_LOG_OBJECT (qtdemux, "creating entry %d with offset %"
9306               G_GUINT64_FORMAT " and size %d",
9307               (guint) (cur - samples), chunk_offset, cur->size);
9308
9309           cur->offset = chunk_offset;
9310           chunk_offset += cur->size;
9311           cur++;
9312
9313           if (G_UNLIKELY (cur > last)) {
9314             /* save state */
9315             stream->stsc_sample_index = k + 1;
9316             stream->chunk_offset = chunk_offset;
9317             stream->stsc_chunk_index = j;
9318             goto done2;
9319           }
9320         }
9321         stream->stsc_sample_index = 0;
9322       }
9323       stream->stsc_chunk_index = j;
9324     }
9325     stream->stsc_index++;
9326   }
9327
9328   if (stream->chunks_are_samples)
9329     goto ctts;
9330 done2:
9331   {
9332     guint32 n_sample_times;
9333
9334     n_sample_times = stream->n_sample_times;
9335     cur = first;
9336
9337     for (i = stream->stts_index; i < n_sample_times; i++) {
9338       guint32 stts_samples;
9339       gint32 stts_duration;
9340       gint64 stts_time;
9341
9342       if (stream->stts_sample_index >= stream->stts_samples
9343           || !stream->stts_sample_index) {
9344
9345         stream->stts_samples =
9346             gst_byte_reader_get_uint32_be_unchecked (&stream->stts);
9347         stream->stts_duration =
9348             gst_byte_reader_get_uint32_be_unchecked (&stream->stts);
9349
9350         GST_LOG_OBJECT (qtdemux, "block %d, %u timestamps, duration %u",
9351             i, stream->stts_samples, stream->stts_duration);
9352
9353         stream->stts_sample_index = 0;
9354       }
9355
9356       stts_samples = stream->stts_samples;
9357       stts_duration = stream->stts_duration;
9358       stts_time = stream->stts_time;
9359
9360       for (j = stream->stts_sample_index; j < stts_samples; j++) {
9361         GST_DEBUG_OBJECT (qtdemux,
9362             "sample %d: index %d, timestamp %" GST_TIME_FORMAT,
9363             (guint) (cur - samples), j,
9364             GST_TIME_ARGS (QTSTREAMTIME_TO_GSTTIME (stream, stts_time)));
9365
9366         cur->timestamp = stts_time;
9367         cur->duration = stts_duration;
9368
9369         /* avoid 32-bit wrap-around,
9370          * but still mind possible 'negative' duration */
9371         stts_time += (gint64) stts_duration;
9372         cur++;
9373
9374         if (G_UNLIKELY (cur > last)) {
9375           /* save values */
9376           stream->stts_time = stts_time;
9377           stream->stts_sample_index = j + 1;
9378           if (stream->stts_sample_index >= stream->stts_samples)
9379             stream->stts_index++;
9380           goto done3;
9381         }
9382       }
9383       stream->stts_sample_index = 0;
9384       stream->stts_time = stts_time;
9385       stream->stts_index++;
9386     }
9387     /* fill up empty timestamps with the last timestamp, this can happen when
9388      * the last samples do not decode and so we don't have timestamps for them.
9389      * We however look at the last timestamp to estimate the track length so we
9390      * need something in here. */
9391     for (; cur < last; cur++) {
9392       GST_DEBUG_OBJECT (qtdemux,
9393           "fill sample %d: timestamp %" GST_TIME_FORMAT,
9394           (guint) (cur - samples),
9395           GST_TIME_ARGS (QTSTREAMTIME_TO_GSTTIME (stream, stream->stts_time)));
9396       cur->timestamp = stream->stts_time;
9397       cur->duration = -1;
9398     }
9399   }
9400 done3:
9401   {
9402     /* sample sync, can be NULL */
9403     if (stream->stss_present == TRUE) {
9404       guint32 n_sample_syncs;
9405
9406       n_sample_syncs = stream->n_sample_syncs;
9407
9408       if (!n_sample_syncs) {
9409         GST_DEBUG_OBJECT (qtdemux, "all samples are keyframes");
9410         stream->all_keyframe = TRUE;
9411       } else {
9412         for (i = stream->stss_index; i < n_sample_syncs; i++) {
9413           /* note that the first sample is index 1, not 0 */
9414           guint32 index;
9415
9416           index = gst_byte_reader_get_uint32_be_unchecked (&stream->stss);
9417
9418           if (G_LIKELY (index > 0 && index <= n_samples)) {
9419             index -= 1;
9420             samples[index].keyframe = TRUE;
9421             GST_DEBUG_OBJECT (qtdemux, "samples at %u is keyframe", index);
9422             /* and exit if we have enough samples */
9423             if (G_UNLIKELY (index >= n)) {
9424               i++;
9425               break;
9426             }
9427           }
9428         }
9429         /* save state */
9430         stream->stss_index = i;
9431       }
9432
9433       /* stps marks partial sync frames like open GOP I-Frames */
9434       if (stream->stps_present == TRUE) {
9435         guint32 n_sample_partial_syncs;
9436
9437         n_sample_partial_syncs = stream->n_sample_partial_syncs;
9438
9439         /* if there are no entries, the stss table contains the real
9440          * sync samples */
9441         if (n_sample_partial_syncs) {
9442           for (i = stream->stps_index; i < n_sample_partial_syncs; i++) {
9443             /* note that the first sample is index 1, not 0 */
9444             guint32 index;
9445
9446             index = gst_byte_reader_get_uint32_be_unchecked (&stream->stps);
9447
9448             if (G_LIKELY (index > 0 && index <= n_samples)) {
9449               index -= 1;
9450               samples[index].keyframe = TRUE;
9451               GST_DEBUG_OBJECT (qtdemux, "samples at %u is keyframe", index);
9452               /* and exit if we have enough samples */
9453               if (G_UNLIKELY (index >= n)) {
9454                 i++;
9455                 break;
9456               }
9457             }
9458           }
9459           /* save state */
9460           stream->stps_index = i;
9461         }
9462       }
9463     } else {
9464       /* no stss, all samples are keyframes */
9465       stream->all_keyframe = TRUE;
9466       GST_DEBUG_OBJECT (qtdemux, "setting all keyframes");
9467     }
9468   }
9469
9470 ctts:
9471   /* composition time to sample */
9472   if (stream->ctts_present == TRUE) {
9473     guint32 n_composition_times;
9474     guint32 ctts_count;
9475     gint32 ctts_soffset;
9476
9477     /* Fill in the pts_offsets */
9478     cur = first;
9479     n_composition_times = stream->n_composition_times;
9480
9481     for (i = stream->ctts_index; i < n_composition_times; i++) {
9482       if (stream->ctts_sample_index >= stream->ctts_count
9483           || !stream->ctts_sample_index) {
9484         stream->ctts_count =
9485             gst_byte_reader_get_uint32_be_unchecked (&stream->ctts);
9486         stream->ctts_soffset =
9487             gst_byte_reader_get_int32_be_unchecked (&stream->ctts);
9488         stream->ctts_sample_index = 0;
9489       }
9490
9491       ctts_count = stream->ctts_count;
9492       ctts_soffset = stream->ctts_soffset;
9493
9494       for (j = stream->ctts_sample_index; j < ctts_count; j++) {
9495         cur->pts_offset = ctts_soffset;
9496         cur++;
9497
9498         if (G_UNLIKELY (cur > last)) {
9499           /* save state */
9500           stream->ctts_sample_index = j + 1;
9501           goto done;
9502         }
9503       }
9504       stream->ctts_sample_index = 0;
9505       stream->ctts_index++;
9506     }
9507   }
9508 done:
9509   stream->stbl_index = n;
9510   /* if index has been completely parsed, free data that is no-longer needed */
9511   if (n + 1 == stream->n_samples) {
9512     gst_qtdemux_stbl_free (stream);
9513     GST_DEBUG_OBJECT (qtdemux, "parsed all available samples;");
9514     if (qtdemux->pullbased) {
9515       GST_DEBUG_OBJECT (qtdemux, "checking for more samples");
9516       while (n + 1 == stream->n_samples)
9517         if (qtdemux_add_fragmented_samples (qtdemux) != GST_FLOW_OK)
9518           break;
9519     }
9520   }
9521   GST_OBJECT_UNLOCK (qtdemux);
9522
9523   return TRUE;
9524
9525   /* SUCCESS */
9526 already_parsed:
9527   {
9528     GST_LOG_OBJECT (qtdemux,
9529         "Tried to parse up to sample %u but this sample has already been parsed",
9530         n);
9531     /* if fragmented, there may be more */
9532     if (qtdemux->fragmented && n == stream->stbl_index)
9533       goto done;
9534     GST_OBJECT_UNLOCK (qtdemux);
9535     return TRUE;
9536   }
9537   /* ERRORS */
9538 out_of_samples:
9539   {
9540     GST_LOG_OBJECT (qtdemux,
9541         "Tried to parse up to sample %u but there are only %u samples", n + 1,
9542         stream->n_samples);
9543     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
9544         (_("This file is corrupt and cannot be played.")), (NULL));
9545     return FALSE;
9546   }
9547 corrupt_file:
9548   {
9549     GST_OBJECT_UNLOCK (qtdemux);
9550     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
9551         (_("This file is corrupt and cannot be played.")), (NULL));
9552     return FALSE;
9553   }
9554 }
9555
9556 /* collect all segment info for @stream.
9557  */
9558 static gboolean
9559 qtdemux_parse_segments (GstQTDemux * qtdemux, QtDemuxStream * stream,
9560     GNode * trak)
9561 {
9562   GNode *edts;
9563   /* accept edts if they contain gaps at start and there is only
9564    * one media segment */
9565   gboolean allow_pushbased_edts = TRUE;
9566   gint media_segments_count = 0;
9567
9568   /* parse and prepare segment info from the edit list */
9569   GST_DEBUG_OBJECT (qtdemux, "looking for edit list container");
9570   stream->n_segments = 0;
9571   stream->segments = NULL;
9572   if ((edts = qtdemux_tree_get_child_by_type (trak, FOURCC_edts))) {
9573     GNode *elst;
9574     gint n_segments;
9575     gint segment_number, entry_size;
9576     guint64 time;
9577     GstClockTime stime;
9578     const guint8 *buffer;
9579     guint8 version;
9580     guint32 size;
9581
9582     GST_DEBUG_OBJECT (qtdemux, "looking for edit list");
9583     if (!(elst = qtdemux_tree_get_child_by_type (edts, FOURCC_elst)))
9584       goto done;
9585
9586     buffer = elst->data;
9587
9588     size = QT_UINT32 (buffer);
9589     /* version, flags, n_segments */
9590     if (size < 16) {
9591       GST_WARNING_OBJECT (qtdemux, "Invalid edit list");
9592       goto done;
9593     }
9594     version = QT_UINT8 (buffer + 8);
9595     entry_size = (version == 1) ? 20 : 12;
9596
9597     n_segments = QT_UINT32 (buffer + 12);
9598
9599     if (n_segments > 100000 || size < 16 + n_segments * entry_size) {
9600       GST_WARNING_OBJECT (qtdemux, "Invalid edit list");
9601       goto done;
9602     }
9603
9604     /* we might allocate a bit too much, at least allocate 1 segment */
9605     stream->segments = g_new (QtDemuxSegment, MAX (n_segments, 1));
9606
9607     /* segments always start from 0 */
9608     time = 0;
9609     stime = 0;
9610     buffer += 16;
9611     for (segment_number = 0; segment_number < n_segments; segment_number++) {
9612       guint64 duration;
9613       guint64 media_time;
9614       gboolean empty_edit = FALSE;
9615       QtDemuxSegment *segment;
9616       guint32 rate_int;
9617       GstClockTime media_start = GST_CLOCK_TIME_NONE;
9618
9619       if (version == 1) {
9620         media_time = QT_UINT64 (buffer + 8);
9621         duration = QT_UINT64 (buffer);
9622         if (media_time == G_MAXUINT64)
9623           empty_edit = TRUE;
9624       } else {
9625         media_time = QT_UINT32 (buffer + 4);
9626         duration = QT_UINT32 (buffer);
9627         if (media_time == G_MAXUINT32)
9628           empty_edit = TRUE;
9629       }
9630
9631       if (!empty_edit)
9632         media_start = QTSTREAMTIME_TO_GSTTIME (stream, media_time);
9633
9634       segment = &stream->segments[segment_number];
9635
9636       /* time and duration expressed in global timescale */
9637       segment->time = stime;
9638       if (duration != 0 || empty_edit) {
9639         /* edge case: empty edits with duration=zero are treated here.
9640          * (files should not have these anyway). */
9641
9642         /* add non scaled values so we don't cause roundoff errors */
9643         time += duration;
9644         stime = QTTIME_TO_GSTTIME (qtdemux, time);
9645         segment->duration = stime - segment->time;
9646       } else {
9647         /* zero duration does not imply media_start == media_stop
9648          * but, only specify media_start. The edit ends with the track. */
9649         stime = segment->duration = GST_CLOCK_TIME_NONE;
9650         /* Don't allow more edits after this one. */
9651         n_segments = segment_number + 1;
9652       }
9653       segment->stop_time = stime;
9654
9655       segment->trak_media_start = media_time;
9656       /* media_time expressed in stream timescale */
9657       if (!empty_edit) {
9658         segment->media_start = media_start;
9659         segment->media_stop = GST_CLOCK_TIME_IS_VALID (segment->duration)
9660             ? segment->media_start + segment->duration : GST_CLOCK_TIME_NONE;
9661         media_segments_count++;
9662       } else {
9663         segment->media_start = GST_CLOCK_TIME_NONE;
9664         segment->media_stop = GST_CLOCK_TIME_NONE;
9665       }
9666       rate_int = QT_UINT32 (buffer + ((version == 1) ? 16 : 8));
9667
9668       if (rate_int <= 1) {
9669         /* 0 is not allowed, some programs write 1 instead of the floating point
9670          * value */
9671         GST_WARNING_OBJECT (qtdemux, "found suspicious rate %" G_GUINT32_FORMAT,
9672             rate_int);
9673         segment->rate = 1;
9674       } else {
9675         segment->rate = rate_int / 65536.0;
9676       }
9677
9678       GST_DEBUG_OBJECT (qtdemux, "created segment %d time %" GST_TIME_FORMAT
9679           ", duration %" GST_TIME_FORMAT ", media_start %" GST_TIME_FORMAT
9680           " (%" G_GUINT64_FORMAT ") , media_stop %" GST_TIME_FORMAT
9681           " stop_time %" GST_TIME_FORMAT " rate %g, (%d) timescale %u",
9682           segment_number, GST_TIME_ARGS (segment->time),
9683           GST_TIME_ARGS (segment->duration),
9684           GST_TIME_ARGS (segment->media_start), media_time,
9685           GST_TIME_ARGS (segment->media_stop),
9686           GST_TIME_ARGS (segment->stop_time), segment->rate, rate_int,
9687           stream->timescale);
9688       if (segment->stop_time > qtdemux->segment.stop &&
9689           !qtdemux->upstream_format_is_time) {
9690         GST_WARNING_OBJECT (qtdemux, "Segment %d "
9691             " extends to %" GST_TIME_FORMAT
9692             " past the end of the declared movie duration %" GST_TIME_FORMAT
9693             " movie segment will be extended", segment_number,
9694             GST_TIME_ARGS (segment->stop_time),
9695             GST_TIME_ARGS (qtdemux->segment.stop));
9696         qtdemux->segment.stop = qtdemux->segment.duration = segment->stop_time;
9697       }
9698
9699       buffer += entry_size;
9700     }
9701     GST_DEBUG_OBJECT (qtdemux, "found %d segments", n_segments);
9702     stream->n_segments = n_segments;
9703     if (media_segments_count != 1)
9704       allow_pushbased_edts = FALSE;
9705   }
9706 done:
9707
9708   /* push based does not handle segments, so act accordingly here,
9709    * and warn if applicable */
9710   if (!qtdemux->pullbased && !allow_pushbased_edts) {
9711     GST_WARNING_OBJECT (qtdemux, "streaming; discarding edit list segments");
9712     /* remove and use default one below, we stream like it anyway */
9713     g_free (stream->segments);
9714     stream->segments = NULL;
9715     stream->n_segments = 0;
9716   }
9717
9718   /* no segments, create one to play the complete trak */
9719   if (stream->n_segments == 0) {
9720     GstClockTime stream_duration =
9721         QTSTREAMTIME_TO_GSTTIME (stream, stream->duration);
9722
9723     if (stream->segments == NULL)
9724       stream->segments = g_new (QtDemuxSegment, 1);
9725
9726     /* represent unknown our way */
9727     if (stream_duration == 0)
9728       stream_duration = GST_CLOCK_TIME_NONE;
9729
9730     stream->segments[0].time = 0;
9731     stream->segments[0].stop_time = stream_duration;
9732     stream->segments[0].duration = stream_duration;
9733     stream->segments[0].media_start = 0;
9734     stream->segments[0].media_stop = stream_duration;
9735     stream->segments[0].rate = 1.0;
9736     stream->segments[0].trak_media_start = 0;
9737
9738     GST_DEBUG_OBJECT (qtdemux, "created dummy segment %" GST_TIME_FORMAT,
9739         GST_TIME_ARGS (stream_duration));
9740     stream->n_segments = 1;
9741     stream->dummy_segment = TRUE;
9742   }
9743   GST_DEBUG_OBJECT (qtdemux, "using %d segments", stream->n_segments);
9744
9745   return TRUE;
9746 }
9747
9748 /*
9749  * Parses the stsd atom of a svq3 trak looking for
9750  * the SMI and gama atoms.
9751  */
9752 static void
9753 qtdemux_parse_svq3_stsd_data (GstQTDemux * qtdemux,
9754     const guint8 * stsd_entry_data, const guint8 ** gamma, GstBuffer ** seqh)
9755 {
9756   const guint8 *_gamma = NULL;
9757   GstBuffer *_seqh = NULL;
9758   const guint8 *stsd_data = stsd_entry_data;
9759   guint32 length = QT_UINT32 (stsd_data);
9760   guint16 version;
9761
9762   if (length < 32) {
9763     GST_WARNING_OBJECT (qtdemux, "stsd too short");
9764     goto end;
9765   }
9766
9767   stsd_data += 16;
9768   length -= 16;
9769   version = QT_UINT16 (stsd_data);
9770   if (version == 3) {
9771     if (length >= 70) {
9772       length -= 70;
9773       stsd_data += 70;
9774       while (length > 8) {
9775         guint32 fourcc, size;
9776         const guint8 *data;
9777         size = QT_UINT32 (stsd_data);
9778         fourcc = QT_FOURCC (stsd_data + 4);
9779         data = stsd_data + 8;
9780
9781         if (size == 0) {
9782           GST_WARNING_OBJECT (qtdemux, "Atom of size 0 found, aborting "
9783               "svq3 atom parsing");
9784           goto end;
9785         }
9786
9787         switch (fourcc) {
9788           case FOURCC_gama:{
9789             if (size == 12) {
9790               _gamma = data;
9791             } else {
9792               GST_WARNING_OBJECT (qtdemux, "Unexpected size %" G_GUINT32_FORMAT
9793                   " for gama atom, expected 12", size);
9794             }
9795             break;
9796           }
9797           case FOURCC_SMI_:{
9798             if (size > 16 && QT_FOURCC (data) == FOURCC_SEQH) {
9799               guint32 seqh_size;
9800               if (_seqh != NULL) {
9801                 GST_WARNING_OBJECT (qtdemux, "Unexpected second SEQH SMI atom "
9802                     " found, ignoring");
9803               } else {
9804                 seqh_size = QT_UINT32 (data + 4);
9805                 if (seqh_size > 0) {
9806                   _seqh = gst_buffer_new_and_alloc (seqh_size);
9807                   gst_buffer_fill (_seqh, 0, data + 8, seqh_size);
9808                 }
9809               }
9810             }
9811             break;
9812           }
9813           default:{
9814             GST_WARNING_OBJECT (qtdemux, "Unhandled atom %" GST_FOURCC_FORMAT
9815                 " in SVQ3 entry in stsd atom", GST_FOURCC_ARGS (fourcc));
9816           }
9817         }
9818
9819         if (size <= length) {
9820           length -= size;
9821           stsd_data += size;
9822         }
9823       }
9824     } else {
9825       GST_WARNING_OBJECT (qtdemux, "SVQ3 entry too short in stsd atom");
9826     }
9827   } else {
9828     GST_WARNING_OBJECT (qtdemux, "Unexpected version for SVQ3 entry %"
9829         G_GUINT16_FORMAT, version);
9830     goto end;
9831   }
9832
9833 end:
9834   if (gamma) {
9835     *gamma = _gamma;
9836   }
9837   if (seqh) {
9838     *seqh = _seqh;
9839   } else if (_seqh) {
9840     gst_buffer_unref (_seqh);
9841   }
9842 }
9843
9844 static gchar *
9845 qtdemux_get_rtsp_uri_from_hndl (GstQTDemux * qtdemux, GNode * minf)
9846 {
9847   GNode *dinf;
9848   GstByteReader dref;
9849   gchar *uri = NULL;
9850
9851   /*
9852    * Get 'dinf', to get its child 'dref', that might contain a 'hndl'
9853    * atom that might contain a 'data' atom with the rtsp uri.
9854    * This case was reported in bug #597497, some info about
9855    * the hndl atom can be found in TN1195
9856    */
9857   dinf = qtdemux_tree_get_child_by_type (minf, FOURCC_dinf);
9858   GST_DEBUG_OBJECT (qtdemux, "Trying to obtain rtsp URI for stream trak");
9859
9860   if (dinf) {
9861     guint32 dref_num_entries = 0;
9862     if (qtdemux_tree_get_child_by_type_full (dinf, FOURCC_dref, &dref) &&
9863         gst_byte_reader_skip (&dref, 4) &&
9864         gst_byte_reader_get_uint32_be (&dref, &dref_num_entries)) {
9865       gint i;
9866
9867       /* search dref entries for hndl atom */
9868       for (i = 0; i < dref_num_entries; i++) {
9869         guint32 size = 0, type;
9870         guint8 string_len = 0;
9871         if (gst_byte_reader_get_uint32_be (&dref, &size) &&
9872             qt_atom_parser_get_fourcc (&dref, &type)) {
9873           if (type == FOURCC_hndl) {
9874             GST_DEBUG_OBJECT (qtdemux, "Found hndl atom");
9875
9876             /* skip data reference handle bytes and the
9877              * following pascal string and some extra 4
9878              * bytes I have no idea what are */
9879             if (!gst_byte_reader_skip (&dref, 4) ||
9880                 !gst_byte_reader_get_uint8 (&dref, &string_len) ||
9881                 !gst_byte_reader_skip (&dref, string_len + 4)) {
9882               GST_WARNING_OBJECT (qtdemux, "Failed to parse hndl atom");
9883               break;
9884             }
9885
9886             /* iterate over the atoms to find the data atom */
9887             while (gst_byte_reader_get_remaining (&dref) >= 8) {
9888               guint32 atom_size;
9889               guint32 atom_type;
9890
9891               if (gst_byte_reader_get_uint32_be (&dref, &atom_size) &&
9892                   qt_atom_parser_get_fourcc (&dref, &atom_type)) {
9893                 if (atom_type == FOURCC_data) {
9894                   const guint8 *uri_aux = NULL;
9895
9896                   /* found the data atom that might contain the rtsp uri */
9897                   GST_DEBUG_OBJECT (qtdemux, "Found data atom inside "
9898                       "hndl atom, interpreting it as an URI");
9899                   if (gst_byte_reader_peek_data (&dref, atom_size - 8,
9900                           &uri_aux)) {
9901                     if (g_strstr_len ((gchar *) uri_aux, 7, "rtsp://") != NULL)
9902                       uri = g_strndup ((gchar *) uri_aux, atom_size - 8);
9903                     else
9904                       GST_WARNING_OBJECT (qtdemux, "Data atom in hndl atom "
9905                           "didn't contain a rtsp address");
9906                   } else {
9907                     GST_WARNING_OBJECT (qtdemux, "Failed to get the data "
9908                         "atom contents");
9909                   }
9910                   break;
9911                 }
9912                 /* skipping to the next entry */
9913                 if (!gst_byte_reader_skip (&dref, atom_size - 8))
9914                   break;
9915               } else {
9916                 GST_WARNING_OBJECT (qtdemux, "Failed to parse hndl child "
9917                     "atom header");
9918                 break;
9919               }
9920             }
9921             break;
9922           }
9923           /* skip to the next entry */
9924           if (!gst_byte_reader_skip (&dref, size - 8))
9925             break;
9926         } else {
9927           GST_WARNING_OBJECT (qtdemux, "Error parsing dref atom");
9928         }
9929       }
9930       GST_DEBUG_OBJECT (qtdemux, "Finished parsing dref atom");
9931     }
9932   }
9933   return uri;
9934 }
9935
9936 #define AMR_NB_ALL_MODES        0x81ff
9937 #define AMR_WB_ALL_MODES        0x83ff
9938 static guint
9939 qtdemux_parse_amr_bitrate (GstBuffer * buf, gboolean wb)
9940 {
9941   /* The 'damr' atom is of the form:
9942    *
9943    * | vendor | decoder_ver | mode_set | mode_change_period | frames/sample |
9944    *    32 b       8 b          16 b           8 b                 8 b
9945    *
9946    * The highest set bit of the first 7 (AMR-NB) or 8 (AMR-WB) bits of mode_set
9947    * represents the highest mode used in the stream (and thus the maximum
9948    * bitrate), with a couple of special cases as seen below.
9949    */
9950
9951   /* Map of frame type ID -> bitrate */
9952   static const guint nb_bitrates[] = {
9953     4750, 5150, 5900, 6700, 7400, 7950, 10200, 12200
9954   };
9955   static const guint wb_bitrates[] = {
9956     6600, 8850, 12650, 14250, 15850, 18250, 19850, 23050, 23850
9957   };
9958   GstMapInfo map;
9959   gsize max_mode;
9960   guint16 mode_set;
9961
9962   gst_buffer_map (buf, &map, GST_MAP_READ);
9963
9964   if (map.size != 0x11) {
9965     GST_DEBUG ("Atom should have size 0x11, not %" G_GSIZE_FORMAT, map.size);
9966     goto bad_data;
9967   }
9968
9969   if (QT_FOURCC (map.data + 4) != FOURCC_damr) {
9970     GST_DEBUG ("Unknown atom in %" GST_FOURCC_FORMAT,
9971         GST_FOURCC_ARGS (QT_UINT32 (map.data + 4)));
9972     goto bad_data;
9973   }
9974
9975   mode_set = QT_UINT16 (map.data + 13);
9976
9977   if (mode_set == (wb ? AMR_WB_ALL_MODES : AMR_NB_ALL_MODES))
9978     max_mode = 7 + (wb ? 1 : 0);
9979   else
9980     /* AMR-NB modes fo from 0-7, and AMR-WB modes go from 0-8 */
9981     max_mode = g_bit_nth_msf ((gulong) mode_set & (wb ? 0x1ff : 0xff), -1);
9982
9983   if (max_mode == -1) {
9984     GST_DEBUG ("No mode indication was found (mode set) = %x",
9985         (guint) mode_set);
9986     goto bad_data;
9987   }
9988
9989   gst_buffer_unmap (buf, &map);
9990   return wb ? wb_bitrates[max_mode] : nb_bitrates[max_mode];
9991
9992 bad_data:
9993   gst_buffer_unmap (buf, &map);
9994   return 0;
9995 }
9996
9997 static gboolean
9998 qtdemux_parse_transformation_matrix (GstQTDemux * qtdemux,
9999     GstByteReader * reader, guint32 * matrix, const gchar * atom)
10000 {
10001   /*
10002    * 9 values of 32 bits (fixed point 16.16, except 2 5 and 8 that are 2.30)
10003    * [0 1 2]
10004    * [3 4 5]
10005    * [6 7 8]
10006    */
10007
10008   if (gst_byte_reader_get_remaining (reader) < 36)
10009     return FALSE;
10010
10011   matrix[0] = gst_byte_reader_get_uint32_be_unchecked (reader);
10012   matrix[1] = gst_byte_reader_get_uint32_be_unchecked (reader);
10013   matrix[2] = gst_byte_reader_get_uint32_be_unchecked (reader);
10014   matrix[3] = gst_byte_reader_get_uint32_be_unchecked (reader);
10015   matrix[4] = gst_byte_reader_get_uint32_be_unchecked (reader);
10016   matrix[5] = gst_byte_reader_get_uint32_be_unchecked (reader);
10017   matrix[6] = gst_byte_reader_get_uint32_be_unchecked (reader);
10018   matrix[7] = gst_byte_reader_get_uint32_be_unchecked (reader);
10019   matrix[8] = gst_byte_reader_get_uint32_be_unchecked (reader);
10020
10021   GST_DEBUG_OBJECT (qtdemux, "Transformation matrix from atom %s", atom);
10022   GST_DEBUG_OBJECT (qtdemux, "%u.%u %u.%u %u.%u", matrix[0] >> 16,
10023       matrix[0] & 0xFFFF, matrix[1] >> 16, matrix[1] & 0xFF, matrix[2] >> 16,
10024       matrix[2] & 0xFF);
10025   GST_DEBUG_OBJECT (qtdemux, "%u.%u %u.%u %u.%u", matrix[3] >> 16,
10026       matrix[3] & 0xFFFF, matrix[4] >> 16, matrix[4] & 0xFF, matrix[5] >> 16,
10027       matrix[5] & 0xFF);
10028   GST_DEBUG_OBJECT (qtdemux, "%u.%u %u.%u %u.%u", matrix[6] >> 16,
10029       matrix[6] & 0xFFFF, matrix[7] >> 16, matrix[7] & 0xFF, matrix[8] >> 16,
10030       matrix[8] & 0xFF);
10031
10032   return TRUE;
10033 }
10034
10035 static void
10036 qtdemux_inspect_transformation_matrix (GstQTDemux * qtdemux,
10037     QtDemuxStream * stream, guint32 * matrix, GstTagList ** taglist)
10038 {
10039
10040 /* [a b c]
10041  * [d e f]
10042  * [g h i]
10043  *
10044  * This macro will only compare value abdegh, it expects cfi to have already
10045  * been checked
10046  */
10047 #define QTCHECK_MATRIX(m,a,b,d,e) ((m)[0] == (a << 16) && (m)[1] == (b << 16) && \
10048                                    (m)[3] == (d << 16) && (m)[4] == (e << 16))
10049
10050   /* only handle the cases where the last column has standard values */
10051   if (matrix[2] == 0 && matrix[5] == 0 && matrix[8] == 1 << 30) {
10052     const gchar *rotation_tag = NULL;
10053
10054     /* no rotation needed */
10055     if (QTCHECK_MATRIX (matrix, 1, 0, 0, 1)) {
10056       /* NOP */
10057     } else if (QTCHECK_MATRIX (matrix, 0, 1, G_MAXUINT16, 0)) {
10058       rotation_tag = "rotate-90";
10059     } else if (QTCHECK_MATRIX (matrix, G_MAXUINT16, 0, 0, G_MAXUINT16)) {
10060       rotation_tag = "rotate-180";
10061     } else if (QTCHECK_MATRIX (matrix, 0, G_MAXUINT16, 1, 0)) {
10062       rotation_tag = "rotate-270";
10063     } else {
10064       GST_FIXME_OBJECT (qtdemux, "Unhandled transformation matrix values");
10065     }
10066
10067     GST_DEBUG_OBJECT (qtdemux, "Transformation matrix rotation %s",
10068         rotation_tag);
10069     if (rotation_tag != NULL) {
10070       if (*taglist == NULL)
10071         *taglist = gst_tag_list_new_empty ();
10072       gst_tag_list_add (*taglist, GST_TAG_MERGE_REPLACE,
10073           GST_TAG_IMAGE_ORIENTATION, rotation_tag, NULL);
10074     }
10075   } else {
10076     GST_FIXME_OBJECT (qtdemux, "Unhandled transformation matrix values");
10077   }
10078 }
10079
10080 /* Parses the boxes defined in ISO/IEC 14496-12 that enable support for
10081  * protected streams (sinf, frma, schm and schi); if the protection scheme is
10082  * Common Encryption (cenc), the function will also parse the tenc box (defined
10083  * in ISO/IEC 23001-7). @container points to the node that contains these boxes
10084  * (typically an enc[v|a|t|s] sample entry); the function will set
10085  * @original_fmt to the fourcc of the original unencrypted stream format.
10086  * Returns TRUE if successful; FALSE otherwise. */
10087 static gboolean
10088 qtdemux_parse_protection_scheme_info (GstQTDemux * qtdemux,
10089     QtDemuxStream * stream, GNode * container, guint32 * original_fmt)
10090 {
10091   GNode *sinf;
10092   GNode *frma;
10093   GNode *schm;
10094   GNode *schi;
10095   QtDemuxCencSampleSetInfo *info;
10096   GNode *tenc;
10097   const guint8 *tenc_data;
10098
10099   g_return_val_if_fail (qtdemux != NULL, FALSE);
10100   g_return_val_if_fail (stream != NULL, FALSE);
10101   g_return_val_if_fail (container != NULL, FALSE);
10102   g_return_val_if_fail (original_fmt != NULL, FALSE);
10103
10104   sinf = qtdemux_tree_get_child_by_type (container, FOURCC_sinf);
10105   if (G_UNLIKELY (!sinf)) {
10106     if (stream->protection_scheme_type == FOURCC_cenc) {
10107       GST_ERROR_OBJECT (qtdemux, "sinf box does not contain schi box, which is "
10108           "mandatory for Common Encryption");
10109       return FALSE;
10110     }
10111     return TRUE;
10112   }
10113
10114   frma = qtdemux_tree_get_child_by_type (sinf, FOURCC_frma);
10115   if (G_UNLIKELY (!frma)) {
10116     GST_ERROR_OBJECT (qtdemux, "sinf box does not contain mandatory frma box");
10117     return FALSE;
10118   }
10119
10120   *original_fmt = QT_FOURCC ((const guint8 *) frma->data + 8);
10121   GST_DEBUG_OBJECT (qtdemux, "original stream format: '%" GST_FOURCC_FORMAT "'",
10122       GST_FOURCC_ARGS (*original_fmt));
10123
10124   schm = qtdemux_tree_get_child_by_type (sinf, FOURCC_schm);
10125   if (!schm) {
10126     GST_DEBUG_OBJECT (qtdemux, "sinf box does not contain schm box");
10127     return FALSE;
10128   }
10129   stream->protection_scheme_type = QT_FOURCC ((const guint8 *) schm->data + 12);
10130   stream->protection_scheme_version =
10131       QT_UINT32 ((const guint8 *) schm->data + 16);
10132
10133   GST_DEBUG_OBJECT (qtdemux,
10134       "protection_scheme_type: %" GST_FOURCC_FORMAT ", "
10135       "protection_scheme_version: %#010x",
10136       GST_FOURCC_ARGS (stream->protection_scheme_type),
10137       stream->protection_scheme_version);
10138
10139   schi = qtdemux_tree_get_child_by_type (sinf, FOURCC_schi);
10140   if (!schi) {
10141     GST_DEBUG_OBJECT (qtdemux, "sinf box does not contain schi box");
10142     return FALSE;
10143   }
10144   if (stream->protection_scheme_type != FOURCC_cenc &&
10145       stream->protection_scheme_type != FOURCC_piff) {
10146     GST_ERROR_OBJECT (qtdemux,
10147         "Invalid protection_scheme_type: %" GST_FOURCC_FORMAT,
10148         GST_FOURCC_ARGS (stream->protection_scheme_type));
10149     return FALSE;
10150   }
10151
10152   if (G_UNLIKELY (!stream->protection_scheme_info))
10153     stream->protection_scheme_info =
10154         g_malloc0 (sizeof (QtDemuxCencSampleSetInfo));
10155
10156   info = (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
10157
10158   if (stream->protection_scheme_type == FOURCC_cenc) {
10159     guint32 is_encrypted;
10160     guint8 iv_size;
10161     const guint8 *default_kid;
10162
10163     tenc = qtdemux_tree_get_child_by_type (schi, FOURCC_tenc);
10164     if (!tenc) {
10165       GST_ERROR_OBJECT (qtdemux, "schi box does not contain tenc box, "
10166           "which is mandatory for Common Encryption");
10167       return FALSE;
10168     }
10169     tenc_data = (const guint8 *) tenc->data + 12;
10170     is_encrypted = QT_UINT24 (tenc_data);
10171     iv_size = QT_UINT8 (tenc_data + 3);
10172     default_kid = (tenc_data + 4);
10173     qtdemux_update_default_sample_encryption_settings (qtdemux, info,
10174         is_encrypted, iv_size, default_kid);
10175   } else if (stream->protection_scheme_type == FOURCC_piff) {
10176     GstByteReader br;
10177     static const guint8 piff_track_encryption_uuid[] = {
10178       0x89, 0x74, 0xdb, 0xce, 0x7b, 0xe7, 0x4c, 0x51,
10179       0x84, 0xf9, 0x71, 0x48, 0xf9, 0x88, 0x25, 0x54
10180     };
10181
10182     tenc = qtdemux_tree_get_child_by_type (schi, FOURCC_uuid);
10183     if (!tenc) {
10184       GST_ERROR_OBJECT (qtdemux, "schi box does not contain tenc box, "
10185           "which is mandatory for Common Encryption");
10186       return FALSE;
10187     }
10188
10189     tenc_data = (const guint8 *) tenc->data + 8;
10190     if (memcmp (tenc_data, piff_track_encryption_uuid, 16) != 0) {
10191       gchar *box_uuid = qtdemux_uuid_bytes_to_string (tenc_data);
10192       GST_ERROR_OBJECT (qtdemux,
10193           "Unsupported track encryption box with uuid: %s", box_uuid);
10194       g_free (box_uuid);
10195       return FALSE;
10196     }
10197     tenc_data = (const guint8 *) tenc->data + 16 + 12;
10198     gst_byte_reader_init (&br, tenc_data, 20);
10199     if (!qtdemux_update_default_piff_encryption_settings (qtdemux, info, &br)) {
10200       GST_ERROR_OBJECT (qtdemux, "PIFF track box parsing error");
10201       return FALSE;
10202     }
10203     stream->protection_scheme_type = FOURCC_cenc;
10204   }
10205
10206   return TRUE;
10207 }
10208
10209 static gint
10210 qtdemux_track_id_compare_func (QtDemuxStream ** stream1,
10211     QtDemuxStream ** stream2)
10212 {
10213   return (gint) (*stream1)->track_id - (gint) (*stream2)->track_id;
10214 }
10215
10216 /* parse the traks.
10217  * With each track we associate a new QtDemuxStream that contains all the info
10218  * about the trak.
10219  * traks that do not decode to something (like strm traks) will not have a pad.
10220  */
10221 static gboolean
10222 qtdemux_parse_trak (GstQTDemux * qtdemux, GNode * trak)
10223 {
10224   GstByteReader tkhd;
10225   int offset;
10226   GNode *mdia;
10227   GNode *mdhd;
10228   GNode *hdlr;
10229   GNode *minf;
10230   GNode *stbl;
10231   GNode *stsd;
10232   GNode *mp4a;
10233   GNode *mp4v;
10234   GNode *esds;
10235   GNode *tref;
10236   GNode *udta;
10237   GNode *svmi;
10238
10239   QtDemuxStream *stream = NULL;
10240   const guint8 *stsd_data;
10241   const guint8 *stsd_entry_data;
10242   guint remaining_stsd_len;
10243   guint stsd_entry_count;
10244   guint stsd_index;
10245   guint16 lang_code;            /* quicktime lang code or packed iso code */
10246   guint32 version;
10247   guint32 tkhd_flags = 0;
10248   guint8 tkhd_version = 0;
10249   guint32 w = 0, h = 0;
10250   guint value_size, stsd_len, len;
10251   guint32 track_id;
10252   guint32 dummy;
10253
10254   GST_DEBUG_OBJECT (qtdemux, "parse_trak");
10255
10256   if (!qtdemux_tree_get_child_by_type_full (trak, FOURCC_tkhd, &tkhd)
10257       || !gst_byte_reader_get_uint8 (&tkhd, &tkhd_version)
10258       || !gst_byte_reader_get_uint24_be (&tkhd, &tkhd_flags))
10259     goto corrupt_file;
10260
10261   /* pick between 64 or 32 bits */
10262   value_size = tkhd_version == 1 ? 8 : 4;
10263   if (!gst_byte_reader_skip (&tkhd, value_size * 2) ||
10264       !gst_byte_reader_get_uint32_be (&tkhd, &track_id))
10265     goto corrupt_file;
10266
10267   /* Check if current moov has duplicated track_id */
10268   if (qtdemux_find_stream (qtdemux, track_id))
10269     goto existing_stream;
10270
10271   stream = _create_stream (qtdemux, track_id);
10272   stream->stream_tags = gst_tag_list_make_writable (stream->stream_tags);
10273
10274   /* need defaults for fragments */
10275   qtdemux_parse_trex (qtdemux, stream, &dummy, &dummy, &dummy);
10276
10277   if ((tkhd_flags & 1) == 0)
10278     stream->disabled = TRUE;
10279
10280   GST_LOG_OBJECT (qtdemux, "track[tkhd] version/flags/id: 0x%02x/%06x/%u",
10281       tkhd_version, tkhd_flags, stream->track_id);
10282
10283   if (!(mdia = qtdemux_tree_get_child_by_type (trak, FOURCC_mdia)))
10284     goto corrupt_file;
10285
10286   if (!(mdhd = qtdemux_tree_get_child_by_type (mdia, FOURCC_mdhd))) {
10287     /* be nice for some crooked mjp2 files that use mhdr for mdhd */
10288     if (qtdemux->major_brand != FOURCC_mjp2 ||
10289         !(mdhd = qtdemux_tree_get_child_by_type (mdia, FOURCC_mhdr)))
10290       goto corrupt_file;
10291   }
10292
10293   len = QT_UINT32 ((guint8 *) mdhd->data);
10294   version = QT_UINT32 ((guint8 *) mdhd->data + 8);
10295   GST_LOG_OBJECT (qtdemux, "track version/flags: %08x", version);
10296   if (version == 0x01000000) {
10297     if (len < 38)
10298       goto corrupt_file;
10299     stream->timescale = QT_UINT32 ((guint8 *) mdhd->data + 28);
10300     stream->duration = QT_UINT64 ((guint8 *) mdhd->data + 32);
10301     lang_code = QT_UINT16 ((guint8 *) mdhd->data + 36);
10302   } else {
10303     if (len < 30)
10304       goto corrupt_file;
10305     stream->timescale = QT_UINT32 ((guint8 *) mdhd->data + 20);
10306     stream->duration = QT_UINT32 ((guint8 *) mdhd->data + 24);
10307     lang_code = QT_UINT16 ((guint8 *) mdhd->data + 28);
10308   }
10309
10310   if (lang_code < 0x400) {
10311     qtdemux_lang_map_qt_code_to_iso (stream->lang_id, lang_code);
10312   } else if (lang_code == 0x7fff) {
10313     stream->lang_id[0] = 0;     /* unspecified */
10314   } else {
10315     stream->lang_id[0] = 0x60 + ((lang_code >> 10) & 0x1F);
10316     stream->lang_id[1] = 0x60 + ((lang_code >> 5) & 0x1F);
10317     stream->lang_id[2] = 0x60 + (lang_code & 0x1F);
10318     stream->lang_id[3] = 0;
10319   }
10320
10321   GST_LOG_OBJECT (qtdemux, "track timescale: %" G_GUINT32_FORMAT,
10322       stream->timescale);
10323   GST_LOG_OBJECT (qtdemux, "track duration: %" G_GUINT64_FORMAT,
10324       stream->duration);
10325   GST_LOG_OBJECT (qtdemux, "track language code/id: 0x%04x/%s",
10326       lang_code, stream->lang_id);
10327
10328   if (G_UNLIKELY (stream->timescale == 0 || qtdemux->timescale == 0))
10329     goto corrupt_file;
10330
10331   if ((tref = qtdemux_tree_get_child_by_type (trak, FOURCC_tref))) {
10332     /* chapters track reference */
10333     GNode *chap = qtdemux_tree_get_child_by_type (tref, FOURCC_chap);
10334     if (chap) {
10335       gsize length = GST_READ_UINT32_BE (chap->data);
10336       if (qtdemux->chapters_track_id)
10337         GST_FIXME_OBJECT (qtdemux, "Multiple CHAP tracks");
10338
10339       if (length >= 12) {
10340         qtdemux->chapters_track_id =
10341             GST_READ_UINT32_BE ((gint8 *) chap->data + 8);
10342       }
10343     }
10344   }
10345
10346   /* fragmented files may have bogus duration in moov */
10347   if (!qtdemux->fragmented &&
10348       qtdemux->duration != G_MAXINT64 && stream->duration != G_MAXINT32) {
10349     guint64 tdur1, tdur2;
10350
10351     /* don't overflow */
10352     tdur1 = stream->timescale * (guint64) qtdemux->duration;
10353     tdur2 = qtdemux->timescale * (guint64) stream->duration;
10354
10355     /* HACK:
10356      * some of those trailers, nowadays, have prologue images that are
10357      * themselves video tracks as well. I haven't really found a way to
10358      * identify those yet, except for just looking at their duration. */
10359     if (tdur1 != 0 && (tdur2 * 10 / tdur1) < 2) {
10360       GST_WARNING_OBJECT (qtdemux,
10361           "Track shorter than 20%% (%" G_GUINT64_FORMAT "/%" G_GUINT32_FORMAT
10362           " vs. %" G_GUINT64_FORMAT "/%" G_GUINT32_FORMAT ") of the stream "
10363           "found, assuming preview image or something; skipping track",
10364           stream->duration, stream->timescale, qtdemux->duration,
10365           qtdemux->timescale);
10366       gst_qtdemux_stream_unref (stream);
10367       return TRUE;
10368     }
10369   }
10370
10371   if (!(hdlr = qtdemux_tree_get_child_by_type (mdia, FOURCC_hdlr)))
10372     goto corrupt_file;
10373
10374   GST_LOG_OBJECT (qtdemux, "track type: %" GST_FOURCC_FORMAT,
10375       GST_FOURCC_ARGS (QT_FOURCC ((guint8 *) hdlr->data + 12)));
10376
10377   len = QT_UINT32 ((guint8 *) hdlr->data);
10378   if (len >= 20)
10379     stream->subtype = QT_FOURCC ((guint8 *) hdlr->data + 16);
10380   GST_LOG_OBJECT (qtdemux, "track subtype: %" GST_FOURCC_FORMAT,
10381       GST_FOURCC_ARGS (stream->subtype));
10382
10383   if (!(minf = qtdemux_tree_get_child_by_type (mdia, FOURCC_minf)))
10384     goto corrupt_file;
10385
10386   if (!(stbl = qtdemux_tree_get_child_by_type (minf, FOURCC_stbl)))
10387     goto corrupt_file;
10388
10389   /*parse svmi header if existing */
10390   svmi = qtdemux_tree_get_child_by_type (stbl, FOURCC_svmi);
10391   if (svmi) {
10392     len = QT_UINT32 ((guint8 *) svmi->data);
10393     version = QT_UINT32 ((guint8 *) svmi->data + 8);
10394     if (!version) {
10395       GstVideoMultiviewMode mode = GST_VIDEO_MULTIVIEW_MODE_NONE;
10396       GstVideoMultiviewFlags flags = GST_VIDEO_MULTIVIEW_FLAGS_NONE;
10397       guint8 frame_type, frame_layout;
10398
10399       /* MPEG-A stereo video */
10400       if (qtdemux->major_brand == FOURCC_ss02)
10401         flags |= GST_VIDEO_MULTIVIEW_FLAGS_MIXED_MONO;
10402
10403       frame_type = QT_UINT8 ((guint8 *) svmi->data + 12);
10404       frame_layout = QT_UINT8 ((guint8 *) svmi->data + 13) & 0x01;
10405       switch (frame_type) {
10406         case 0:
10407           mode = GST_VIDEO_MULTIVIEW_MODE_SIDE_BY_SIDE;
10408           break;
10409         case 1:
10410           mode = GST_VIDEO_MULTIVIEW_MODE_ROW_INTERLEAVED;
10411           break;
10412         case 2:
10413           mode = GST_VIDEO_MULTIVIEW_MODE_FRAME_BY_FRAME;
10414           break;
10415         case 3:
10416           /* mode 3 is primary/secondary view sequence, ie
10417            * left/right views in separate tracks. See section 7.2
10418            * of ISO/IEC 23000-11:2009 */
10419           GST_FIXME_OBJECT (qtdemux,
10420               "Implement stereo video in separate streams");
10421       }
10422
10423       if ((frame_layout & 0x1) == 0)
10424         flags |= GST_VIDEO_MULTIVIEW_FLAGS_RIGHT_VIEW_FIRST;
10425
10426       GST_LOG_OBJECT (qtdemux,
10427           "StereoVideo: composition type: %u, is_left_first: %u",
10428           frame_type, frame_layout);
10429       stream->multiview_mode = mode;
10430       stream->multiview_flags = flags;
10431     }
10432   }
10433
10434   /* parse rest of tkhd */
10435   if (stream->subtype == FOURCC_vide) {
10436     guint32 matrix[9];
10437
10438     /* version 1 uses some 64-bit ints */
10439     if (!gst_byte_reader_skip (&tkhd, 20 + value_size))
10440       goto corrupt_file;
10441
10442     if (!qtdemux_parse_transformation_matrix (qtdemux, &tkhd, matrix, "tkhd"))
10443       goto corrupt_file;
10444
10445     if (!gst_byte_reader_get_uint32_be (&tkhd, &w)
10446         || !gst_byte_reader_get_uint32_be (&tkhd, &h))
10447       goto corrupt_file;
10448
10449     qtdemux_inspect_transformation_matrix (qtdemux, stream, matrix,
10450         &stream->stream_tags);
10451   }
10452
10453   /* parse stsd */
10454   if (!(stsd = qtdemux_tree_get_child_by_type (stbl, FOURCC_stsd)))
10455     goto corrupt_file;
10456   stsd_data = (const guint8 *) stsd->data;
10457
10458   /* stsd should at least have one entry */
10459   stsd_len = QT_UINT32 (stsd_data);
10460   if (stsd_len < 24) {
10461     /* .. but skip stream with empty stsd produced by some Vivotek cameras */
10462     if (stream->subtype == FOURCC_vivo) {
10463       gst_qtdemux_stream_unref (stream);
10464       return TRUE;
10465     } else {
10466       goto corrupt_file;
10467     }
10468   }
10469
10470   stream->stsd_entries_length = stsd_entry_count = QT_UINT32 (stsd_data + 12);
10471   stream->stsd_entries = g_new0 (QtDemuxStreamStsdEntry, stsd_entry_count);
10472   GST_LOG_OBJECT (qtdemux, "stsd len:           %d", stsd_len);
10473   GST_LOG_OBJECT (qtdemux, "stsd entry count:   %u", stsd_entry_count);
10474
10475   stsd_entry_data = stsd_data + 16;
10476   remaining_stsd_len = stsd_len - 16;
10477   for (stsd_index = 0; stsd_index < stsd_entry_count; stsd_index++) {
10478     guint32 fourcc;
10479     gchar *codec = NULL;
10480     QtDemuxStreamStsdEntry *entry = &stream->stsd_entries[stsd_index];
10481
10482     /* and that entry should fit within stsd */
10483     len = QT_UINT32 (stsd_entry_data);
10484     if (len > remaining_stsd_len)
10485       goto corrupt_file;
10486
10487     entry->fourcc = fourcc = QT_FOURCC (stsd_entry_data + 4);
10488     GST_LOG_OBJECT (qtdemux, "stsd type:          %" GST_FOURCC_FORMAT,
10489         GST_FOURCC_ARGS (entry->fourcc));
10490     GST_LOG_OBJECT (qtdemux, "stsd type len:      %d", len);
10491
10492     if ((fourcc == FOURCC_drms) || (fourcc == FOURCC_drmi))
10493       goto error_encrypted;
10494
10495     if (fourcc == FOURCC_encv || fourcc == FOURCC_enca) {
10496       /* FIXME this looks wrong, there might be multiple children
10497        * with the same type */
10498       GNode *enc = qtdemux_tree_get_child_by_type (stsd, fourcc);
10499       stream->protected = TRUE;
10500       if (!qtdemux_parse_protection_scheme_info (qtdemux, stream, enc, &fourcc))
10501         GST_ERROR_OBJECT (qtdemux, "Failed to parse protection scheme info");
10502     }
10503
10504     if (stream->subtype == FOURCC_vide) {
10505       GNode *colr;
10506       GNode *fiel;
10507       GNode *pasp;
10508       gboolean gray;
10509       gint depth, palette_size, palette_count;
10510       guint32 *palette_data = NULL;
10511
10512       entry->sampled = TRUE;
10513
10514       stream->display_width = w >> 16;
10515       stream->display_height = h >> 16;
10516
10517       offset = 16;
10518       if (len < 86)             /* TODO verify */
10519         goto corrupt_file;
10520
10521       entry->width = QT_UINT16 (stsd_entry_data + offset + 16);
10522       entry->height = QT_UINT16 (stsd_entry_data + offset + 18);
10523       entry->fps_n = 0;         /* this is filled in later */
10524       entry->fps_d = 0;         /* this is filled in later */
10525       entry->bits_per_sample = QT_UINT16 (stsd_entry_data + offset + 66);
10526       entry->color_table_id = QT_UINT16 (stsd_entry_data + offset + 68);
10527
10528       /* if color_table_id is 0, ctab atom must follow; however some files
10529        * produced by TMPEGEnc have color_table_id = 0 and no ctab atom, so
10530        * if color table is not present we'll correct the value */
10531       if (entry->color_table_id == 0 &&
10532           (len < 90
10533               || QT_FOURCC (stsd_entry_data + offset + 70) != FOURCC_ctab)) {
10534         entry->color_table_id = -1;
10535       }
10536
10537       GST_LOG_OBJECT (qtdemux, "width %d, height %d, bps %d, color table id %d",
10538           entry->width, entry->height, entry->bits_per_sample,
10539           entry->color_table_id);
10540
10541       depth = entry->bits_per_sample;
10542
10543       /* more than 32 bits means grayscale */
10544       gray = (depth > 32);
10545       /* low 32 bits specify the depth  */
10546       depth &= 0x1F;
10547
10548       /* different number of palette entries is determined by depth. */
10549       palette_count = 0;
10550       if ((depth == 1) || (depth == 2) || (depth == 4) || (depth == 8))
10551         palette_count = (1 << depth);
10552       palette_size = palette_count * 4;
10553
10554       if (entry->color_table_id) {
10555         switch (palette_count) {
10556           case 0:
10557             break;
10558           case 2:
10559             palette_data = g_memdup (ff_qt_default_palette_2, palette_size);
10560             break;
10561           case 4:
10562             palette_data = g_memdup (ff_qt_default_palette_4, palette_size);
10563             break;
10564           case 16:
10565             if (gray)
10566               palette_data =
10567                   g_memdup (ff_qt_grayscale_palette_16, palette_size);
10568             else
10569               palette_data = g_memdup (ff_qt_default_palette_16, palette_size);
10570             break;
10571           case 256:
10572             if (gray)
10573               palette_data =
10574                   g_memdup (ff_qt_grayscale_palette_256, palette_size);
10575             else
10576               palette_data = g_memdup (ff_qt_default_palette_256, palette_size);
10577             break;
10578           default:
10579             GST_ELEMENT_WARNING (qtdemux, STREAM, DEMUX,
10580                 (_("The video in this file might not play correctly.")),
10581                 ("unsupported palette depth %d", depth));
10582             break;
10583         }
10584       } else {
10585         gint i, j, start, end;
10586
10587         if (len < 94)
10588           goto corrupt_file;
10589
10590         /* read table */
10591         start = QT_UINT32 (stsd_entry_data + offset + 70);
10592         palette_count = QT_UINT16 (stsd_entry_data + offset + 74);
10593         end = QT_UINT16 (stsd_entry_data + offset + 76);
10594
10595         GST_LOG_OBJECT (qtdemux, "start %d, end %d, palette_count %d",
10596             start, end, palette_count);
10597
10598         if (end > 255)
10599           end = 255;
10600         if (start > end)
10601           start = end;
10602
10603         if (len < 94 + (end - start) * 8)
10604           goto corrupt_file;
10605
10606         /* palette is always the same size */
10607         palette_data = g_malloc0 (256 * 4);
10608         palette_size = 256 * 4;
10609
10610         for (j = 0, i = start; i <= end; j++, i++) {
10611           guint32 a, r, g, b;
10612
10613           a = QT_UINT16 (stsd_entry_data + offset + 78 + (j * 8));
10614           r = QT_UINT16 (stsd_entry_data + offset + 80 + (j * 8));
10615           g = QT_UINT16 (stsd_entry_data + offset + 82 + (j * 8));
10616           b = QT_UINT16 (stsd_entry_data + offset + 84 + (j * 8));
10617
10618           palette_data[i] = ((a & 0xff00) << 16) | ((r & 0xff00) << 8) |
10619               (g & 0xff00) | (b >> 8);
10620         }
10621       }
10622
10623       if (entry->caps)
10624         gst_caps_unref (entry->caps);
10625
10626       entry->caps =
10627           qtdemux_video_caps (qtdemux, stream, entry, fourcc, stsd_entry_data,
10628           &codec);
10629       if (G_UNLIKELY (!entry->caps)) {
10630         g_free (palette_data);
10631         goto unknown_stream;
10632       }
10633
10634       if (codec) {
10635         gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
10636             GST_TAG_VIDEO_CODEC, codec, NULL);
10637         g_free (codec);
10638         codec = NULL;
10639       }
10640
10641       if (palette_data) {
10642         GstStructure *s;
10643
10644         if (entry->rgb8_palette)
10645           gst_memory_unref (entry->rgb8_palette);
10646         entry->rgb8_palette = gst_memory_new_wrapped (GST_MEMORY_FLAG_READONLY,
10647             palette_data, palette_size, 0, palette_size, palette_data, g_free);
10648
10649         s = gst_caps_get_structure (entry->caps, 0);
10650
10651         /* non-raw video has a palette_data property. raw video has the palette as
10652          * an extra plane that we append to the output buffers before we push
10653          * them*/
10654         if (!gst_structure_has_name (s, "video/x-raw")) {
10655           GstBuffer *palette;
10656
10657           palette = gst_buffer_new ();
10658           gst_buffer_append_memory (palette, entry->rgb8_palette);
10659           entry->rgb8_palette = NULL;
10660
10661           gst_caps_set_simple (entry->caps, "palette_data",
10662               GST_TYPE_BUFFER, palette, NULL);
10663           gst_buffer_unref (palette);
10664         }
10665       } else if (palette_count != 0) {
10666         GST_ELEMENT_WARNING (qtdemux, STREAM, NOT_IMPLEMENTED,
10667             (NULL), ("Unsupported palette depth %d", depth));
10668       }
10669
10670       GST_LOG_OBJECT (qtdemux, "frame count:   %u",
10671           QT_UINT16 (stsd_entry_data + offset + 32));
10672
10673       esds = NULL;
10674       pasp = NULL;
10675       colr = NULL;
10676       fiel = NULL;
10677       /* pick 'the' stsd child */
10678       mp4v = qtdemux_tree_get_child_by_index (stsd, stsd_index);
10679       if (!stream->protected) {
10680         if (QTDEMUX_TREE_NODE_FOURCC (mp4v) != fourcc) {
10681           mp4v = NULL;
10682         }
10683       } else {
10684         if (QTDEMUX_TREE_NODE_FOURCC (mp4v) != FOURCC_encv) {
10685           mp4v = NULL;
10686         }
10687       }
10688
10689       if (mp4v) {
10690         esds = qtdemux_tree_get_child_by_type (mp4v, FOURCC_esds);
10691         pasp = qtdemux_tree_get_child_by_type (mp4v, FOURCC_pasp);
10692         colr = qtdemux_tree_get_child_by_type (mp4v, FOURCC_colr);
10693         fiel = qtdemux_tree_get_child_by_type (mp4v, FOURCC_fiel);
10694       }
10695
10696       if (pasp) {
10697         const guint8 *pasp_data = (const guint8 *) pasp->data;
10698         gint len = QT_UINT32 (pasp_data);
10699
10700         if (len == 16) {
10701           CUR_STREAM (stream)->par_w = QT_UINT32 (pasp_data + 8);
10702           CUR_STREAM (stream)->par_h = QT_UINT32 (pasp_data + 12);
10703         } else {
10704           CUR_STREAM (stream)->par_w = 0;
10705           CUR_STREAM (stream)->par_h = 0;
10706         }
10707       } else {
10708         CUR_STREAM (stream)->par_w = 0;
10709         CUR_STREAM (stream)->par_h = 0;
10710       }
10711
10712       if (fiel) {
10713         const guint8 *fiel_data = (const guint8 *) fiel->data;
10714         gint len = QT_UINT32 (fiel_data);
10715
10716         if (len == 10) {
10717           CUR_STREAM (stream)->interlace_mode = GST_READ_UINT8 (fiel_data + 8);
10718           CUR_STREAM (stream)->field_order = GST_READ_UINT8 (fiel_data + 9);
10719         }
10720       }
10721
10722       if (colr) {
10723         const guint8 *colr_data = (const guint8 *) colr->data;
10724         gint len = QT_UINT32 (colr_data);
10725
10726         if (len == 19 || len == 18) {
10727           guint32 color_type = GST_READ_UINT32_LE (colr_data + 8);
10728
10729           if (color_type == FOURCC_nclx || color_type == FOURCC_nclc) {
10730             guint16 primaries = GST_READ_UINT16_BE (colr_data + 12);
10731             guint16 transfer_function = GST_READ_UINT16_BE (colr_data + 14);
10732             guint16 matrix = GST_READ_UINT16_BE (colr_data + 16);
10733             gboolean full_range = len == 19 ? colr_data[17] >> 7 : FALSE;
10734
10735             switch (primaries) {
10736               case 1:
10737                 CUR_STREAM (stream)->colorimetry.primaries =
10738                     GST_VIDEO_COLOR_PRIMARIES_BT709;
10739                 break;
10740               case 5:
10741                 CUR_STREAM (stream)->colorimetry.primaries =
10742                     GST_VIDEO_COLOR_PRIMARIES_BT470BG;
10743                 break;
10744               case 6:
10745                 CUR_STREAM (stream)->colorimetry.primaries =
10746                     GST_VIDEO_COLOR_PRIMARIES_SMPTE170M;
10747                 break;
10748               case 9:
10749                 CUR_STREAM (stream)->colorimetry.primaries =
10750                     GST_VIDEO_COLOR_PRIMARIES_BT2020;
10751                 break;
10752               default:
10753                 break;
10754             }
10755
10756             switch (transfer_function) {
10757               case 1:
10758                 CUR_STREAM (stream)->colorimetry.transfer =
10759                     GST_VIDEO_TRANSFER_BT709;
10760                 break;
10761               case 7:
10762                 CUR_STREAM (stream)->colorimetry.transfer =
10763                     GST_VIDEO_TRANSFER_SMPTE240M;
10764                 break;
10765               default:
10766                 break;
10767             }
10768
10769             switch (matrix) {
10770               case 1:
10771                 CUR_STREAM (stream)->colorimetry.matrix =
10772                     GST_VIDEO_COLOR_MATRIX_BT709;
10773                 break;
10774               case 6:
10775                 CUR_STREAM (stream)->colorimetry.matrix =
10776                     GST_VIDEO_COLOR_MATRIX_BT601;
10777                 break;
10778               case 7:
10779                 CUR_STREAM (stream)->colorimetry.matrix =
10780                     GST_VIDEO_COLOR_MATRIX_SMPTE240M;
10781                 break;
10782               case 9:
10783                 CUR_STREAM (stream)->colorimetry.matrix =
10784                     GST_VIDEO_COLOR_MATRIX_BT2020;
10785                 break;
10786               default:
10787                 break;
10788             }
10789
10790             CUR_STREAM (stream)->colorimetry.range =
10791                 full_range ? GST_VIDEO_COLOR_RANGE_0_255 :
10792                 GST_VIDEO_COLOR_RANGE_16_235;
10793           } else {
10794             GST_DEBUG_OBJECT (qtdemux, "Unsupported color type");
10795           }
10796         } else {
10797           GST_WARNING_OBJECT (qtdemux, "Invalid colr atom size");
10798         }
10799       }
10800
10801       if (esds) {
10802         gst_qtdemux_handle_esds (qtdemux, stream, entry, esds,
10803             stream->stream_tags);
10804       } else {
10805         switch (fourcc) {
10806           case FOURCC_H264:
10807           case FOURCC_avc1:
10808           case FOURCC_avc3:
10809           {
10810             gint len = QT_UINT32 (stsd_entry_data) - 0x56;
10811             const guint8 *avc_data = stsd_entry_data + 0x56;
10812
10813             /* find avcC */
10814             while (len >= 0x8) {
10815               gint size;
10816
10817               if (QT_UINT32 (avc_data) <= len)
10818                 size = QT_UINT32 (avc_data) - 0x8;
10819               else
10820                 size = len - 0x8;
10821
10822               if (size < 1)
10823                 /* No real data, so break out */
10824                 break;
10825
10826               switch (QT_FOURCC (avc_data + 0x4)) {
10827                 case FOURCC_avcC:
10828                 {
10829                   /* parse, if found */
10830                   GstBuffer *buf;
10831
10832                   GST_DEBUG_OBJECT (qtdemux, "found avcC codec_data in stsd");
10833
10834                   /* First 4 bytes are the length of the atom, the next 4 bytes
10835                    * are the fourcc, the next 1 byte is the version, and the
10836                    * subsequent bytes are profile_tier_level structure like data. */
10837                   gst_codec_utils_h264_caps_set_level_and_profile (entry->caps,
10838                       avc_data + 8 + 1, size - 1);
10839                   buf = gst_buffer_new_and_alloc (size);
10840                   gst_buffer_fill (buf, 0, avc_data + 0x8, size);
10841                   gst_caps_set_simple (entry->caps,
10842                       "codec_data", GST_TYPE_BUFFER, buf, NULL);
10843                   gst_buffer_unref (buf);
10844
10845                   break;
10846                 }
10847                 case FOURCC_strf:
10848                 {
10849                   GstBuffer *buf;
10850
10851                   GST_DEBUG_OBJECT (qtdemux, "found strf codec_data in stsd");
10852
10853                   /* First 4 bytes are the length of the atom, the next 4 bytes
10854                    * are the fourcc, next 40 bytes are BITMAPINFOHEADER,
10855                    * next 1 byte is the version, and the
10856                    * subsequent bytes are sequence parameter set like data. */
10857
10858                   size -= 40;   /* we'll be skipping BITMAPINFOHEADER */
10859                   if (size > 1) {
10860                     gst_codec_utils_h264_caps_set_level_and_profile
10861                         (entry->caps, avc_data + 8 + 40 + 1, size - 1);
10862
10863                     buf = gst_buffer_new_and_alloc (size);
10864                     gst_buffer_fill (buf, 0, avc_data + 8 + 40, size);
10865                     gst_caps_set_simple (entry->caps,
10866                         "codec_data", GST_TYPE_BUFFER, buf, NULL);
10867                     gst_buffer_unref (buf);
10868                   }
10869                   break;
10870                 }
10871                 case FOURCC_btrt:
10872                 {
10873                   guint avg_bitrate, max_bitrate;
10874
10875                   /* bufferSizeDB, maxBitrate and avgBitrate - 4 bytes each */
10876                   if (size < 12)
10877                     break;
10878
10879                   max_bitrate = QT_UINT32 (avc_data + 0xc);
10880                   avg_bitrate = QT_UINT32 (avc_data + 0x10);
10881
10882                   if (!max_bitrate && !avg_bitrate)
10883                     break;
10884
10885                   /* Some muxers seem to swap the average and maximum bitrates
10886                    * (I'm looking at you, YouTube), so we swap for sanity. */
10887                   if (max_bitrate > 0 && max_bitrate < avg_bitrate) {
10888                     guint temp = avg_bitrate;
10889
10890                     avg_bitrate = max_bitrate;
10891                     max_bitrate = temp;
10892                   }
10893
10894                   if (max_bitrate > 0 && max_bitrate < G_MAXUINT32) {
10895                     gst_tag_list_add (stream->stream_tags,
10896                         GST_TAG_MERGE_REPLACE, GST_TAG_MAXIMUM_BITRATE,
10897                         max_bitrate, NULL);
10898                   }
10899                   if (avg_bitrate > 0 && avg_bitrate < G_MAXUINT32) {
10900                     gst_tag_list_add (stream->stream_tags,
10901                         GST_TAG_MERGE_REPLACE, GST_TAG_BITRATE, avg_bitrate,
10902                         NULL);
10903                   }
10904
10905                   break;
10906                 }
10907
10908                 default:
10909                   break;
10910               }
10911
10912               len -= size + 8;
10913               avc_data += size + 8;
10914             }
10915
10916             break;
10917           }
10918           case FOURCC_H265:
10919           case FOURCC_hvc1:
10920           case FOURCC_hev1:
10921           {
10922             gint len = QT_UINT32 (stsd_entry_data) - 0x56;
10923             const guint8 *hevc_data = stsd_entry_data + 0x56;
10924
10925             /* find hevc */
10926             while (len >= 0x8) {
10927               gint size;
10928
10929               if (QT_UINT32 (hevc_data) <= len)
10930                 size = QT_UINT32 (hevc_data) - 0x8;
10931               else
10932                 size = len - 0x8;
10933
10934               if (size < 1)
10935                 /* No real data, so break out */
10936                 break;
10937
10938               switch (QT_FOURCC (hevc_data + 0x4)) {
10939                 case FOURCC_hvcC:
10940                 {
10941                   /* parse, if found */
10942                   GstBuffer *buf;
10943
10944                   GST_DEBUG_OBJECT (qtdemux, "found hvcC codec_data in stsd");
10945
10946                   /* First 4 bytes are the length of the atom, the next 4 bytes
10947                    * are the fourcc, the next 1 byte is the version, and the
10948                    * subsequent bytes are sequence parameter set like data. */
10949                   gst_codec_utils_h265_caps_set_level_tier_and_profile
10950                       (entry->caps, hevc_data + 8 + 1, size - 1);
10951
10952                   buf = gst_buffer_new_and_alloc (size);
10953                   gst_buffer_fill (buf, 0, hevc_data + 0x8, size);
10954                   gst_caps_set_simple (entry->caps,
10955                       "codec_data", GST_TYPE_BUFFER, buf, NULL);
10956                   gst_buffer_unref (buf);
10957                   break;
10958                 }
10959                 default:
10960                   break;
10961               }
10962               len -= size + 8;
10963               hevc_data += size + 8;
10964             }
10965             break;
10966           }
10967           case FOURCC_mp4v:
10968           case FOURCC_MP4V:
10969           case FOURCC_fmp4:
10970           case FOURCC_FMP4:
10971           case FOURCC_xvid:
10972           case FOURCC_XVID:
10973           {
10974             GNode *glbl;
10975
10976             GST_DEBUG_OBJECT (qtdemux, "found %" GST_FOURCC_FORMAT,
10977                 GST_FOURCC_ARGS (fourcc));
10978
10979             /* codec data might be in glbl extension atom */
10980             glbl = mp4v ?
10981                 qtdemux_tree_get_child_by_type (mp4v, FOURCC_glbl) : NULL;
10982             if (glbl) {
10983               guint8 *data;
10984               GstBuffer *buf;
10985               gint len;
10986
10987               GST_DEBUG_OBJECT (qtdemux, "found glbl data in stsd");
10988               data = glbl->data;
10989               len = QT_UINT32 (data);
10990               if (len > 0x8) {
10991                 len -= 0x8;
10992                 buf = gst_buffer_new_and_alloc (len);
10993                 gst_buffer_fill (buf, 0, data + 8, len);
10994                 gst_caps_set_simple (entry->caps,
10995                     "codec_data", GST_TYPE_BUFFER, buf, NULL);
10996                 gst_buffer_unref (buf);
10997               }
10998             }
10999             break;
11000           }
11001           case FOURCC_mjp2:
11002           {
11003             /* see annex I of the jpeg2000 spec */
11004             GNode *jp2h, *ihdr, *colr, *mjp2, *field, *prefix, *cmap, *cdef;
11005             const guint8 *data;
11006             const gchar *colorspace = NULL;
11007             gint ncomp = 0;
11008             guint32 ncomp_map = 0;
11009             gint32 *comp_map = NULL;
11010             guint32 nchan_def = 0;
11011             gint32 *chan_def = NULL;
11012
11013             GST_DEBUG_OBJECT (qtdemux, "found mjp2");
11014             /* some required atoms */
11015             mjp2 = qtdemux_tree_get_child_by_index (stsd, stsd_index);
11016             if (!mjp2)
11017               break;
11018             jp2h = qtdemux_tree_get_child_by_type (mjp2, FOURCC_jp2h);
11019             if (!jp2h)
11020               break;
11021
11022             /* number of components; redundant with info in codestream, but useful
11023                to a muxer */
11024             ihdr = qtdemux_tree_get_child_by_type (jp2h, FOURCC_ihdr);
11025             if (!ihdr || QT_UINT32 (ihdr->data) != 22)
11026               break;
11027             ncomp = QT_UINT16 (((guint8 *) ihdr->data) + 16);
11028
11029             colr = qtdemux_tree_get_child_by_type (jp2h, FOURCC_colr);
11030             if (!colr)
11031               break;
11032             GST_DEBUG_OBJECT (qtdemux, "found colr");
11033             /* extract colour space info */
11034             if (QT_UINT8 ((guint8 *) colr->data + 8) == 1) {
11035               switch (QT_UINT32 ((guint8 *) colr->data + 11)) {
11036                 case 16:
11037                   colorspace = "sRGB";
11038                   break;
11039                 case 17:
11040                   colorspace = "GRAY";
11041                   break;
11042                 case 18:
11043                   colorspace = "sYUV";
11044                   break;
11045                 default:
11046                   colorspace = NULL;
11047                   break;
11048               }
11049             }
11050             if (!colorspace)
11051               /* colr is required, and only values 16, 17, and 18 are specified,
11052                  so error if we have no colorspace */
11053               break;
11054
11055             /* extract component mapping */
11056             cmap = qtdemux_tree_get_child_by_type (jp2h, FOURCC_cmap);
11057             if (cmap) {
11058               guint32 cmap_len = 0;
11059               int i;
11060               cmap_len = QT_UINT32 (cmap->data);
11061               if (cmap_len >= 8) {
11062                 /* normal box, subtract off header */
11063                 cmap_len -= 8;
11064                 /* cmap: { u16 cmp; u8 mtyp; u8 pcol; }* */
11065                 if (cmap_len % 4 == 0) {
11066                   ncomp_map = (cmap_len / 4);
11067                   comp_map = g_new0 (gint32, ncomp_map);
11068                   for (i = 0; i < ncomp_map; i++) {
11069                     guint16 cmp;
11070                     guint8 mtyp, pcol;
11071                     cmp = QT_UINT16 (((guint8 *) cmap->data) + 8 + i * 4);
11072                     mtyp = QT_UINT8 (((guint8 *) cmap->data) + 8 + i * 4 + 2);
11073                     pcol = QT_UINT8 (((guint8 *) cmap->data) + 8 + i * 4 + 3);
11074                     comp_map[i] = (mtyp << 24) | (pcol << 16) | cmp;
11075                   }
11076                 }
11077               }
11078             }
11079             /* extract channel definitions */
11080             cdef = qtdemux_tree_get_child_by_type (jp2h, FOURCC_cdef);
11081             if (cdef) {
11082               guint32 cdef_len = 0;
11083               int i;
11084               cdef_len = QT_UINT32 (cdef->data);
11085               if (cdef_len >= 10) {
11086                 /* normal box, subtract off header and len */
11087                 cdef_len -= 10;
11088                 /* cdef: u16 n; { u16 cn; u16 typ; u16 asoc; }* */
11089                 if (cdef_len % 6 == 0) {
11090                   nchan_def = (cdef_len / 6);
11091                   chan_def = g_new0 (gint32, nchan_def);
11092                   for (i = 0; i < nchan_def; i++)
11093                     chan_def[i] = -1;
11094                   for (i = 0; i < nchan_def; i++) {
11095                     guint16 cn, typ, asoc;
11096                     cn = QT_UINT16 (((guint8 *) cdef->data) + 10 + i * 6);
11097                     typ = QT_UINT16 (((guint8 *) cdef->data) + 10 + i * 6 + 2);
11098                     asoc = QT_UINT16 (((guint8 *) cdef->data) + 10 + i * 6 + 4);
11099                     if (cn < nchan_def) {
11100                       switch (typ) {
11101                         case 0:
11102                           chan_def[cn] = asoc;
11103                           break;
11104                         case 1:
11105                           chan_def[cn] = 0;     /* alpha */
11106                           break;
11107                         default:
11108                           chan_def[cn] = -typ;
11109                       }
11110                     }
11111                   }
11112                 }
11113               }
11114             }
11115
11116             gst_caps_set_simple (entry->caps,
11117                 "num-components", G_TYPE_INT, ncomp, NULL);
11118             gst_caps_set_simple (entry->caps,
11119                 "colorspace", G_TYPE_STRING, colorspace, NULL);
11120
11121             if (comp_map) {
11122               GValue arr = { 0, };
11123               GValue elt = { 0, };
11124               int i;
11125               g_value_init (&arr, GST_TYPE_ARRAY);
11126               g_value_init (&elt, G_TYPE_INT);
11127               for (i = 0; i < ncomp_map; i++) {
11128                 g_value_set_int (&elt, comp_map[i]);
11129                 gst_value_array_append_value (&arr, &elt);
11130               }
11131               gst_structure_set_value (gst_caps_get_structure (entry->caps, 0),
11132                   "component-map", &arr);
11133               g_value_unset (&elt);
11134               g_value_unset (&arr);
11135               g_free (comp_map);
11136             }
11137
11138             if (chan_def) {
11139               GValue arr = { 0, };
11140               GValue elt = { 0, };
11141               int i;
11142               g_value_init (&arr, GST_TYPE_ARRAY);
11143               g_value_init (&elt, G_TYPE_INT);
11144               for (i = 0; i < nchan_def; i++) {
11145                 g_value_set_int (&elt, chan_def[i]);
11146                 gst_value_array_append_value (&arr, &elt);
11147               }
11148               gst_structure_set_value (gst_caps_get_structure (entry->caps, 0),
11149                   "channel-definitions", &arr);
11150               g_value_unset (&elt);
11151               g_value_unset (&arr);
11152               g_free (chan_def);
11153             }
11154
11155             /* some optional atoms */
11156             field = qtdemux_tree_get_child_by_type (mjp2, FOURCC_fiel);
11157             prefix = qtdemux_tree_get_child_by_type (mjp2, FOURCC_jp2x);
11158
11159             /* indicate possible fields in caps */
11160             if (field) {
11161               data = (guint8 *) field->data + 8;
11162               if (*data != 1)
11163                 gst_caps_set_simple (entry->caps, "fields", G_TYPE_INT,
11164                     (gint) * data, NULL);
11165             }
11166             /* add codec_data if provided */
11167             if (prefix) {
11168               GstBuffer *buf;
11169               gint len;
11170
11171               GST_DEBUG_OBJECT (qtdemux, "found prefix data in stsd");
11172               data = prefix->data;
11173               len = QT_UINT32 (data);
11174               if (len > 0x8) {
11175                 len -= 0x8;
11176                 buf = gst_buffer_new_and_alloc (len);
11177                 gst_buffer_fill (buf, 0, data + 8, len);
11178                 gst_caps_set_simple (entry->caps,
11179                     "codec_data", GST_TYPE_BUFFER, buf, NULL);
11180                 gst_buffer_unref (buf);
11181               }
11182             }
11183             break;
11184           }
11185           case FOURCC_SVQ3:
11186           case FOURCC_VP31:
11187           {
11188             GstBuffer *buf;
11189             GstBuffer *seqh = NULL;
11190             const guint8 *gamma_data = NULL;
11191             gint len = QT_UINT32 (stsd_data);   /* FIXME review - why put the whole stsd in codec data? */
11192
11193             qtdemux_parse_svq3_stsd_data (qtdemux, stsd_entry_data, &gamma_data,
11194                 &seqh);
11195             if (gamma_data) {
11196               gst_caps_set_simple (entry->caps, "applied-gamma", G_TYPE_DOUBLE,
11197                   QT_FP32 (gamma_data), NULL);
11198             }
11199             if (seqh) {
11200               /* sorry for the bad name, but we don't know what this is, other
11201                * than its own fourcc */
11202               gst_caps_set_simple (entry->caps, "seqh", GST_TYPE_BUFFER, seqh,
11203                   NULL);
11204               gst_buffer_unref (seqh);
11205             }
11206
11207             GST_DEBUG_OBJECT (qtdemux, "found codec_data in stsd");
11208             buf = gst_buffer_new_and_alloc (len);
11209             gst_buffer_fill (buf, 0, stsd_data, len);
11210             gst_caps_set_simple (entry->caps,
11211                 "codec_data", GST_TYPE_BUFFER, buf, NULL);
11212             gst_buffer_unref (buf);
11213             break;
11214           }
11215           case FOURCC_jpeg:
11216           {
11217             /* https://developer.apple.com/standards/qtff-2001.pdf,
11218              * page 92, "Video Sample Description", under table 3.1 */
11219             GstByteReader br;
11220
11221             const gint compressor_offset =
11222                 16 + 4 + 4 * 3 + 2 * 2 + 2 * 4 + 4 + 2;
11223             const gint min_size = compressor_offset + 32 + 2 + 2;
11224             GNode *jpeg;
11225             guint32 len;
11226             guint16 color_table_id = 0;
11227             gboolean ok;
11228
11229             GST_DEBUG_OBJECT (qtdemux, "found jpeg");
11230
11231             /* recover information on interlaced/progressive */
11232             jpeg = qtdemux_tree_get_child_by_type (stsd, FOURCC_jpeg);
11233             if (!jpeg)
11234               break;
11235
11236             len = QT_UINT32 (jpeg->data);
11237             GST_DEBUG_OBJECT (qtdemux, "Found jpeg: len %u, need %d", len,
11238                 min_size);
11239             if (len >= min_size) {
11240               gst_byte_reader_init (&br, jpeg->data, len);
11241
11242               gst_byte_reader_skip (&br, compressor_offset + 32 + 2);
11243               gst_byte_reader_get_uint16_le (&br, &color_table_id);
11244               if (color_table_id != 0) {
11245                 /* the spec says there can be concatenated chunks in the data, and we want
11246                  * to find one called field. Walk through them. */
11247                 gint offset = min_size;
11248                 while (offset + 8 < len) {
11249                   guint32 size = 0, tag;
11250                   ok = gst_byte_reader_get_uint32_le (&br, &size);
11251                   ok &= gst_byte_reader_get_uint32_le (&br, &tag);
11252                   if (!ok || size < 8) {
11253                     GST_WARNING_OBJECT (qtdemux,
11254                         "Failed to walk optional chunk list");
11255                     break;
11256                   }
11257                   GST_DEBUG_OBJECT (qtdemux,
11258                       "Found optional %4.4s chunk, size %u",
11259                       (const char *) &tag, size);
11260                   if (tag == FOURCC_fiel) {
11261                     guint8 n_fields = 0, ordering = 0;
11262                     gst_byte_reader_get_uint8 (&br, &n_fields);
11263                     gst_byte_reader_get_uint8 (&br, &ordering);
11264                     if (n_fields == 1 || n_fields == 2) {
11265                       GST_DEBUG_OBJECT (qtdemux,
11266                           "Found fiel tag with %u fields, ordering %u",
11267                           n_fields, ordering);
11268                       if (n_fields == 2)
11269                         gst_caps_set_simple (CUR_STREAM (stream)->caps,
11270                             "interlace-mode", G_TYPE_STRING, "interleaved",
11271                             NULL);
11272                     } else {
11273                       GST_WARNING_OBJECT (qtdemux,
11274                           "Found fiel tag with invalid fields (%u)", n_fields);
11275                     }
11276                   }
11277                   offset += size;
11278                 }
11279               } else {
11280                 GST_DEBUG_OBJECT (qtdemux,
11281                     "Color table ID is 0, not trying to get interlacedness");
11282               }
11283             } else {
11284               GST_WARNING_OBJECT (qtdemux,
11285                   "Length of jpeg chunk is too small, not trying to get interlacedness");
11286             }
11287
11288             break;
11289           }
11290           case FOURCC_rle_:
11291           case FOURCC_WRLE:
11292           {
11293             gst_caps_set_simple (entry->caps,
11294                 "depth", G_TYPE_INT, QT_UINT16 (stsd_entry_data + offset + 66),
11295                 NULL);
11296             break;
11297           }
11298           case FOURCC_XiTh:
11299           {
11300             GNode *xith, *xdxt;
11301
11302             GST_DEBUG_OBJECT (qtdemux, "found XiTh");
11303             xith = qtdemux_tree_get_child_by_index (stsd, stsd_index);
11304             if (!xith)
11305               break;
11306
11307             xdxt = qtdemux_tree_get_child_by_type (xith, FOURCC_XdxT);
11308             if (!xdxt)
11309               break;
11310
11311             GST_DEBUG_OBJECT (qtdemux, "found XdxT node");
11312             /* collect the headers and store them in a stream list so that we can
11313              * send them out first */
11314             qtdemux_parse_theora_extension (qtdemux, stream, xdxt);
11315             break;
11316           }
11317           case FOURCC_ovc1:
11318           {
11319             GNode *ovc1;
11320             guint8 *ovc1_data;
11321             guint ovc1_len;
11322             GstBuffer *buf;
11323
11324             GST_DEBUG_OBJECT (qtdemux, "parse ovc1 header");
11325             ovc1 = qtdemux_tree_get_child_by_index (stsd, stsd_index);
11326             if (!ovc1)
11327               break;
11328             ovc1_data = ovc1->data;
11329             ovc1_len = QT_UINT32 (ovc1_data);
11330             if (ovc1_len <= 198) {
11331               GST_WARNING_OBJECT (qtdemux, "Too small ovc1 header, skipping");
11332               break;
11333             }
11334             buf = gst_buffer_new_and_alloc (ovc1_len - 198);
11335             gst_buffer_fill (buf, 0, ovc1_data + 198, ovc1_len - 198);
11336             gst_caps_set_simple (entry->caps,
11337                 "codec_data", GST_TYPE_BUFFER, buf, NULL);
11338             gst_buffer_unref (buf);
11339             break;
11340           }
11341           case FOURCC_vc_1:
11342           {
11343             gint len = QT_UINT32 (stsd_entry_data) - 0x56;
11344             const guint8 *vc1_data = stsd_entry_data + 0x56;
11345
11346             /* find dvc1 */
11347             while (len >= 8) {
11348               gint size;
11349
11350               if (QT_UINT32 (vc1_data) <= len)
11351                 size = QT_UINT32 (vc1_data) - 8;
11352               else
11353                 size = len - 8;
11354
11355               if (size < 1)
11356                 /* No real data, so break out */
11357                 break;
11358
11359               switch (QT_FOURCC (vc1_data + 0x4)) {
11360                 case GST_MAKE_FOURCC ('d', 'v', 'c', '1'):
11361                 {
11362                   GstBuffer *buf;
11363
11364                   GST_DEBUG_OBJECT (qtdemux, "found dvc1 codec_data in stsd");
11365                   buf = gst_buffer_new_and_alloc (size);
11366                   gst_buffer_fill (buf, 0, vc1_data + 8, size);
11367                   gst_caps_set_simple (entry->caps,
11368                       "codec_data", GST_TYPE_BUFFER, buf, NULL);
11369                   gst_buffer_unref (buf);
11370                   break;
11371                 }
11372                 default:
11373                   break;
11374               }
11375               len -= size + 8;
11376               vc1_data += size + 8;
11377             }
11378             break;
11379           }
11380           case FOURCC_av01:
11381           {
11382             gint len = QT_UINT32 (stsd_entry_data) - 0x56;
11383             const guint8 *av1_data = stsd_entry_data + 0x56;
11384
11385             /* find av1C */
11386             while (len >= 0x8) {
11387               gint size;
11388
11389               if (QT_UINT32 (av1_data) <= len)
11390                 size = QT_UINT32 (av1_data) - 0x8;
11391               else
11392                 size = len - 0x8;
11393
11394               if (size < 1)
11395                 /* No real data, so break out */
11396                 break;
11397
11398               switch (QT_FOURCC (av1_data + 0x4)) {
11399                 case FOURCC_av1C:
11400                 {
11401                   /* parse, if found */
11402                   GstBuffer *buf;
11403                   guint8 pres_delay_field;
11404
11405                   GST_DEBUG_OBJECT (qtdemux,
11406                       "found av1C codec_data in stsd of size %d", size);
11407
11408                   /* not enough data, just ignore and hope for the best */
11409                   if (size < 5)
11410                     break;
11411
11412                   /* Content is:
11413                    * 4 bytes: atom length
11414                    * 4 bytes: fourcc
11415                    * 1 byte: version
11416                    * 3 bytes: flags
11417                    * 3 bits: reserved
11418                    * 1 bits:  initial_presentation_delay_present
11419                    * 4 bits: initial_presentation_delay (if present else reserved
11420                    * rest: OBUs.
11421                    */
11422
11423                   if (av1_data[9] != 0) {
11424                     GST_WARNING ("Unknown version %d of av1C box", av1_data[9]);
11425                     break;
11426                   }
11427
11428                   /* We skip initial_presentation_delay* for now */
11429                   pres_delay_field = *(av1_data + 12);
11430                   if (pres_delay_field & (1 << 5)) {
11431                     gst_caps_set_simple (entry->caps,
11432                         "presentation-delay", G_TYPE_INT,
11433                         (gint) (pres_delay_field & 0x0F) + 1, NULL);
11434                   }
11435                   if (size > 5) {
11436                     buf = gst_buffer_new_and_alloc (size - 5);
11437                     GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_HEADER);
11438                     gst_buffer_fill (buf, 0, av1_data + 13, size - 5);
11439                     gst_caps_set_simple (entry->caps,
11440                         "codec_data", GST_TYPE_BUFFER, buf, NULL);
11441                     gst_buffer_unref (buf);
11442                   }
11443                   break;
11444                 }
11445                 default:
11446                   break;
11447               }
11448
11449               len -= size + 8;
11450               av1_data += size + 8;
11451             }
11452
11453             break;
11454           }
11455           default:
11456             break;
11457         }
11458       }
11459
11460       GST_INFO_OBJECT (qtdemux,
11461           "type %" GST_FOURCC_FORMAT " caps %" GST_PTR_FORMAT,
11462           GST_FOURCC_ARGS (fourcc), entry->caps);
11463
11464     } else if (stream->subtype == FOURCC_soun) {
11465       GNode *wave;
11466       int version, samplesize;
11467       guint16 compression_id;
11468       gboolean amrwb = FALSE;
11469
11470       offset = 16;
11471       /* sample description entry (16) + sound sample description v0 (20) */
11472       if (len < 36)
11473         goto corrupt_file;
11474
11475       version = QT_UINT32 (stsd_entry_data + offset);
11476       entry->n_channels = QT_UINT16 (stsd_entry_data + offset + 8);
11477       samplesize = QT_UINT16 (stsd_entry_data + offset + 10);
11478       compression_id = QT_UINT16 (stsd_entry_data + offset + 12);
11479       entry->rate = QT_FP32 (stsd_entry_data + offset + 16);
11480
11481       GST_LOG_OBJECT (qtdemux, "version/rev:      %08x", version);
11482       GST_LOG_OBJECT (qtdemux, "vendor:           %08x",
11483           QT_UINT32 (stsd_entry_data + offset + 4));
11484       GST_LOG_OBJECT (qtdemux, "n_channels:       %d", entry->n_channels);
11485       GST_LOG_OBJECT (qtdemux, "sample_size:      %d", samplesize);
11486       GST_LOG_OBJECT (qtdemux, "compression_id:   %d", compression_id);
11487       GST_LOG_OBJECT (qtdemux, "packet size:      %d",
11488           QT_UINT16 (stsd_entry_data + offset + 14));
11489       GST_LOG_OBJECT (qtdemux, "sample rate:      %g", entry->rate);
11490
11491       if (compression_id == 0xfffe)
11492         entry->sampled = TRUE;
11493
11494       /* first assume uncompressed audio */
11495       entry->bytes_per_sample = samplesize / 8;
11496       entry->samples_per_frame = entry->n_channels;
11497       entry->bytes_per_frame = entry->n_channels * entry->bytes_per_sample;
11498       entry->samples_per_packet = entry->samples_per_frame;
11499       entry->bytes_per_packet = entry->bytes_per_sample;
11500
11501       offset = 36;
11502       switch (fourcc) {
11503           /* Yes, these have to be hard-coded */
11504         case FOURCC_MAC6:
11505         {
11506           entry->samples_per_packet = 6;
11507           entry->bytes_per_packet = 1;
11508           entry->bytes_per_frame = 1 * entry->n_channels;
11509           entry->bytes_per_sample = 1;
11510           entry->samples_per_frame = 6 * entry->n_channels;
11511           break;
11512         }
11513         case FOURCC_MAC3:
11514         {
11515           entry->samples_per_packet = 3;
11516           entry->bytes_per_packet = 1;
11517           entry->bytes_per_frame = 1 * entry->n_channels;
11518           entry->bytes_per_sample = 1;
11519           entry->samples_per_frame = 3 * entry->n_channels;
11520           break;
11521         }
11522         case FOURCC_ima4:
11523         {
11524           entry->samples_per_packet = 64;
11525           entry->bytes_per_packet = 34;
11526           entry->bytes_per_frame = 34 * entry->n_channels;
11527           entry->bytes_per_sample = 2;
11528           entry->samples_per_frame = 64 * entry->n_channels;
11529           break;
11530         }
11531         case FOURCC_ulaw:
11532         case FOURCC_alaw:
11533         {
11534           entry->samples_per_packet = 1;
11535           entry->bytes_per_packet = 1;
11536           entry->bytes_per_frame = 1 * entry->n_channels;
11537           entry->bytes_per_sample = 1;
11538           entry->samples_per_frame = 1 * entry->n_channels;
11539           break;
11540         }
11541         case FOURCC_agsm:
11542         {
11543           entry->samples_per_packet = 160;
11544           entry->bytes_per_packet = 33;
11545           entry->bytes_per_frame = 33 * entry->n_channels;
11546           entry->bytes_per_sample = 2;
11547           entry->samples_per_frame = 160 * entry->n_channels;
11548           break;
11549         }
11550         default:
11551           break;
11552       }
11553
11554       if (version == 0x00010000) {
11555         /* sample description entry (16) + sound sample description v1 (20+16) */
11556         if (len < 52)
11557           goto corrupt_file;
11558
11559         switch (fourcc) {
11560           case FOURCC_twos:
11561           case FOURCC_sowt:
11562           case FOURCC_raw_:
11563           case FOURCC_lpcm:
11564             break;
11565           default:
11566           {
11567             /* only parse extra decoding config for non-pcm audio */
11568             entry->samples_per_packet = QT_UINT32 (stsd_entry_data + offset);
11569             entry->bytes_per_packet = QT_UINT32 (stsd_entry_data + offset + 4);
11570             entry->bytes_per_frame = QT_UINT32 (stsd_entry_data + offset + 8);
11571             entry->bytes_per_sample = QT_UINT32 (stsd_entry_data + offset + 12);
11572
11573             GST_LOG_OBJECT (qtdemux, "samples/packet:   %d",
11574                 entry->samples_per_packet);
11575             GST_LOG_OBJECT (qtdemux, "bytes/packet:     %d",
11576                 entry->bytes_per_packet);
11577             GST_LOG_OBJECT (qtdemux, "bytes/frame:      %d",
11578                 entry->bytes_per_frame);
11579             GST_LOG_OBJECT (qtdemux, "bytes/sample:     %d",
11580                 entry->bytes_per_sample);
11581
11582             if (!entry->sampled && entry->bytes_per_packet) {
11583               entry->samples_per_frame = (entry->bytes_per_frame /
11584                   entry->bytes_per_packet) * entry->samples_per_packet;
11585               GST_LOG_OBJECT (qtdemux, "samples/frame:    %d",
11586                   entry->samples_per_frame);
11587             }
11588             break;
11589           }
11590         }
11591       } else if (version == 0x00020000) {
11592         union
11593         {
11594           gdouble fp;
11595           guint64 val;
11596         } qtfp;
11597
11598         /* sample description entry (16) + sound sample description v2 (56) */
11599         if (len < 72)
11600           goto corrupt_file;
11601
11602         qtfp.val = QT_UINT64 (stsd_entry_data + offset + 4);
11603         entry->rate = qtfp.fp;
11604         entry->n_channels = QT_UINT32 (stsd_entry_data + offset + 12);
11605
11606         GST_LOG_OBJECT (qtdemux, "Sound sample description Version 2");
11607         GST_LOG_OBJECT (qtdemux, "sample rate:        %g", entry->rate);
11608         GST_LOG_OBJECT (qtdemux, "n_channels:         %d", entry->n_channels);
11609         GST_LOG_OBJECT (qtdemux, "bits/channel:       %d",
11610             QT_UINT32 (stsd_entry_data + offset + 20));
11611         GST_LOG_OBJECT (qtdemux, "format flags:       %X",
11612             QT_UINT32 (stsd_entry_data + offset + 24));
11613         GST_LOG_OBJECT (qtdemux, "bytes/packet:       %d",
11614             QT_UINT32 (stsd_entry_data + offset + 28));
11615         GST_LOG_OBJECT (qtdemux, "LPCM frames/packet: %d",
11616             QT_UINT32 (stsd_entry_data + offset + 32));
11617       } else if (version != 0x00000) {
11618         GST_WARNING_OBJECT (qtdemux, "unknown audio STSD version %08x",
11619             version);
11620       }
11621
11622       if (entry->caps)
11623         gst_caps_unref (entry->caps);
11624
11625       entry->caps = qtdemux_audio_caps (qtdemux, stream, entry, fourcc,
11626           stsd_entry_data + 32, len - 16, &codec);
11627
11628       switch (fourcc) {
11629         case FOURCC_in24:
11630         {
11631           GNode *enda;
11632           GNode *in24;
11633
11634           in24 = qtdemux_tree_get_child_by_type (stsd, FOURCC_in24);
11635
11636           enda = qtdemux_tree_get_child_by_type (in24, FOURCC_enda);
11637           if (!enda) {
11638             wave = qtdemux_tree_get_child_by_type (in24, FOURCC_wave);
11639             if (wave)
11640               enda = qtdemux_tree_get_child_by_type (wave, FOURCC_enda);
11641           }
11642           if (enda) {
11643             int enda_value = QT_UINT16 ((guint8 *) enda->data + 8);
11644             gst_caps_set_simple (entry->caps,
11645                 "format", G_TYPE_STRING, (enda_value) ? "S24LE" : "S24BE",
11646                 NULL);
11647           }
11648           break;
11649         }
11650         case FOURCC_owma:
11651         {
11652           const guint8 *owma_data;
11653           const gchar *codec_name = NULL;
11654           guint owma_len;
11655           GstBuffer *buf;
11656           gint version = 1;
11657           /* from http://msdn.microsoft.com/en-us/library/dd757720(VS.85).aspx */
11658           /* FIXME this should also be gst_riff_strf_auds,
11659            * but the latter one is actually missing bits-per-sample :( */
11660           typedef struct
11661           {
11662             gint16 wFormatTag;
11663             gint16 nChannels;
11664             gint32 nSamplesPerSec;
11665             gint32 nAvgBytesPerSec;
11666             gint16 nBlockAlign;
11667             gint16 wBitsPerSample;
11668             gint16 cbSize;
11669           } WAVEFORMATEX;
11670           WAVEFORMATEX *wfex;
11671
11672           GST_DEBUG_OBJECT (qtdemux, "parse owma");
11673           owma_data = stsd_entry_data;
11674           owma_len = QT_UINT32 (owma_data);
11675           if (owma_len <= 54) {
11676             GST_WARNING_OBJECT (qtdemux, "Too small owma header, skipping");
11677             break;
11678           }
11679           wfex = (WAVEFORMATEX *) (owma_data + 36);
11680           buf = gst_buffer_new_and_alloc (owma_len - 54);
11681           gst_buffer_fill (buf, 0, owma_data + 54, owma_len - 54);
11682           if (wfex->wFormatTag == 0x0161) {
11683             codec_name = "Windows Media Audio";
11684             version = 2;
11685           } else if (wfex->wFormatTag == 0x0162) {
11686             codec_name = "Windows Media Audio 9 Pro";
11687             version = 3;
11688           } else if (wfex->wFormatTag == 0x0163) {
11689             codec_name = "Windows Media Audio 9 Lossless";
11690             /* is that correct? gstffmpegcodecmap.c is missing it, but
11691              * fluendo codec seems to support it */
11692             version = 4;
11693           }
11694
11695           gst_caps_set_simple (entry->caps,
11696               "codec_data", GST_TYPE_BUFFER, buf,
11697               "wmaversion", G_TYPE_INT, version,
11698               "block_align", G_TYPE_INT,
11699               GST_READ_UINT16_LE (&wfex->nBlockAlign), "bitrate", G_TYPE_INT,
11700               GST_READ_UINT32_LE (&wfex->nAvgBytesPerSec), "width", G_TYPE_INT,
11701               GST_READ_UINT16_LE (&wfex->wBitsPerSample), "depth", G_TYPE_INT,
11702               GST_READ_UINT16_LE (&wfex->wBitsPerSample), NULL);
11703           gst_buffer_unref (buf);
11704
11705           if (codec_name) {
11706             g_free (codec);
11707             codec = g_strdup (codec_name);
11708           }
11709           break;
11710         }
11711         case FOURCC_wma_:
11712         {
11713           gint len = QT_UINT32 (stsd_entry_data) - offset;
11714           const guint8 *wfex_data = stsd_entry_data + offset;
11715           const gchar *codec_name = NULL;
11716           gint version = 1;
11717           /* from http://msdn.microsoft.com/en-us/library/dd757720(VS.85).aspx */
11718           /* FIXME this should also be gst_riff_strf_auds,
11719            * but the latter one is actually missing bits-per-sample :( */
11720           typedef struct
11721           {
11722             gint16 wFormatTag;
11723             gint16 nChannels;
11724             gint32 nSamplesPerSec;
11725             gint32 nAvgBytesPerSec;
11726             gint16 nBlockAlign;
11727             gint16 wBitsPerSample;
11728             gint16 cbSize;
11729           } WAVEFORMATEX;
11730           WAVEFORMATEX wfex;
11731
11732           /* FIXME: unify with similar wavformatex parsing code above */
11733           GST_DEBUG_OBJECT (qtdemux, "parse wma, looking for wfex");
11734
11735           /* find wfex */
11736           while (len >= 8) {
11737             gint size;
11738
11739             if (QT_UINT32 (wfex_data) <= len)
11740               size = QT_UINT32 (wfex_data) - 8;
11741             else
11742               size = len - 8;
11743
11744             if (size < 1)
11745               /* No real data, so break out */
11746               break;
11747
11748             switch (QT_FOURCC (wfex_data + 4)) {
11749               case GST_MAKE_FOURCC ('w', 'f', 'e', 'x'):
11750               {
11751                 GST_DEBUG_OBJECT (qtdemux, "found wfex in stsd");
11752
11753                 if (size < 8 + 18)
11754                   break;
11755
11756                 wfex.wFormatTag = GST_READ_UINT16_LE (wfex_data + 8 + 0);
11757                 wfex.nChannels = GST_READ_UINT16_LE (wfex_data + 8 + 2);
11758                 wfex.nSamplesPerSec = GST_READ_UINT32_LE (wfex_data + 8 + 4);
11759                 wfex.nAvgBytesPerSec = GST_READ_UINT32_LE (wfex_data + 8 + 8);
11760                 wfex.nBlockAlign = GST_READ_UINT16_LE (wfex_data + 8 + 12);
11761                 wfex.wBitsPerSample = GST_READ_UINT16_LE (wfex_data + 8 + 14);
11762                 wfex.cbSize = GST_READ_UINT16_LE (wfex_data + 8 + 16);
11763
11764                 GST_LOG_OBJECT (qtdemux, "Found wfex box in stsd:");
11765                 GST_LOG_OBJECT (qtdemux, "FormatTag = 0x%04x, Channels = %u, "
11766                     "SamplesPerSec = %u, AvgBytesPerSec = %u, BlockAlign = %u, "
11767                     "BitsPerSample = %u, Size = %u", wfex.wFormatTag,
11768                     wfex.nChannels, wfex.nSamplesPerSec, wfex.nAvgBytesPerSec,
11769                     wfex.nBlockAlign, wfex.wBitsPerSample, wfex.cbSize);
11770
11771                 if (wfex.wFormatTag == 0x0161) {
11772                   codec_name = "Windows Media Audio";
11773                   version = 2;
11774                 } else if (wfex.wFormatTag == 0x0162) {
11775                   codec_name = "Windows Media Audio 9 Pro";
11776                   version = 3;
11777                 } else if (wfex.wFormatTag == 0x0163) {
11778                   codec_name = "Windows Media Audio 9 Lossless";
11779                   /* is that correct? gstffmpegcodecmap.c is missing it, but
11780                    * fluendo codec seems to support it */
11781                   version = 4;
11782                 }
11783
11784                 gst_caps_set_simple (entry->caps,
11785                     "wmaversion", G_TYPE_INT, version,
11786                     "block_align", G_TYPE_INT, wfex.nBlockAlign,
11787                     "bitrate", G_TYPE_INT, wfex.nAvgBytesPerSec,
11788                     "width", G_TYPE_INT, wfex.wBitsPerSample,
11789                     "depth", G_TYPE_INT, wfex.wBitsPerSample, NULL);
11790
11791                 if (size > wfex.cbSize) {
11792                   GstBuffer *buf;
11793
11794                   buf = gst_buffer_new_and_alloc (size - wfex.cbSize);
11795                   gst_buffer_fill (buf, 0, wfex_data + 8 + wfex.cbSize,
11796                       size - wfex.cbSize);
11797                   gst_caps_set_simple (entry->caps,
11798                       "codec_data", GST_TYPE_BUFFER, buf, NULL);
11799                   gst_buffer_unref (buf);
11800                 } else {
11801                   GST_WARNING_OBJECT (qtdemux, "no codec data");
11802                 }
11803
11804                 if (codec_name) {
11805                   g_free (codec);
11806                   codec = g_strdup (codec_name);
11807                 }
11808                 break;
11809               }
11810               default:
11811                 break;
11812             }
11813             len -= size + 8;
11814             wfex_data += size + 8;
11815           }
11816           break;
11817         }
11818         case FOURCC_opus:
11819         {
11820           const guint8 *opus_data;
11821           guint8 *channel_mapping = NULL;
11822           guint32 rate;
11823           guint8 channels;
11824           guint8 channel_mapping_family;
11825           guint8 stream_count;
11826           guint8 coupled_count;
11827           guint8 i;
11828
11829           opus_data = stsd_entry_data;
11830
11831           channels = GST_READ_UINT8 (opus_data + 45);
11832           rate = GST_READ_UINT32_LE (opus_data + 48);
11833           channel_mapping_family = GST_READ_UINT8 (opus_data + 54);
11834           stream_count = GST_READ_UINT8 (opus_data + 55);
11835           coupled_count = GST_READ_UINT8 (opus_data + 56);
11836
11837           if (channels > 0) {
11838             channel_mapping = g_malloc (channels * sizeof (guint8));
11839             for (i = 0; i < channels; i++)
11840               channel_mapping[i] = GST_READ_UINT8 (opus_data + i + 57);
11841           }
11842
11843           entry->caps = gst_codec_utils_opus_create_caps (rate, channels,
11844               channel_mapping_family, stream_count, coupled_count,
11845               channel_mapping);
11846           break;
11847         }
11848         default:
11849           break;
11850       }
11851
11852       if (codec) {
11853         GstStructure *s;
11854         gint bitrate = 0;
11855
11856         gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
11857             GST_TAG_AUDIO_CODEC, codec, NULL);
11858         g_free (codec);
11859         codec = NULL;
11860
11861         /* some bitrate info may have ended up in caps */
11862         s = gst_caps_get_structure (entry->caps, 0);
11863         gst_structure_get_int (s, "bitrate", &bitrate);
11864         if (bitrate > 0)
11865           gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
11866               GST_TAG_BITRATE, bitrate, NULL);
11867       }
11868
11869       mp4a = qtdemux_tree_get_child_by_index (stsd, stsd_index);
11870       if (!stream->protected) {
11871       } else {
11872         if (QTDEMUX_TREE_NODE_FOURCC (mp4v) != FOURCC_encv) {
11873           mp4v = NULL;
11874         }
11875       }
11876       if (stream->protected && fourcc == FOURCC_mp4a) {
11877         if (QTDEMUX_TREE_NODE_FOURCC (mp4a) != FOURCC_enca) {
11878           mp4a = NULL;
11879         }
11880       } else {
11881         if (QTDEMUX_TREE_NODE_FOURCC (mp4a) != FOURCC_mp4a) {
11882           mp4a = NULL;
11883         }
11884       }
11885
11886       wave = NULL;
11887       esds = NULL;
11888       if (mp4a) {
11889         wave = qtdemux_tree_get_child_by_type (mp4a, FOURCC_wave);
11890         if (wave)
11891           esds = qtdemux_tree_get_child_by_type (wave, FOURCC_esds);
11892         if (!esds)
11893           esds = qtdemux_tree_get_child_by_type (mp4a, FOURCC_esds);
11894       }
11895
11896
11897       /* If the fourcc's bottom 16 bits gives 'sm', then the top
11898          16 bits is a byte-swapped wave-style codec identifier,
11899          and we can find a WAVE header internally to a 'wave' atom here.
11900          This can more clearly be thought of as 'ms' as the top 16 bits, and a
11901          codec id as the bottom 16 bits - but byte-swapped to store in QT (which
11902          is big-endian).
11903        */
11904       if ((fourcc & 0xffff) == (('s' << 8) | 'm')) {
11905         if (len < offset + 20) {
11906           GST_WARNING_OBJECT (qtdemux, "No wave atom in MS-style audio");
11907         } else {
11908           guint32 datalen = QT_UINT32 (stsd_entry_data + offset + 16);
11909           const guint8 *data = stsd_entry_data + offset + 16;
11910           GNode *wavenode;
11911           GNode *waveheadernode;
11912
11913           wavenode = g_node_new ((guint8 *) data);
11914           if (qtdemux_parse_node (qtdemux, wavenode, data, datalen)) {
11915             const guint8 *waveheader;
11916             guint32 headerlen;
11917
11918             waveheadernode = qtdemux_tree_get_child_by_type (wavenode, fourcc);
11919             if (waveheadernode) {
11920               waveheader = (const guint8 *) waveheadernode->data;
11921               headerlen = QT_UINT32 (waveheader);
11922
11923               if (headerlen > 8) {
11924                 gst_riff_strf_auds *header = NULL;
11925                 GstBuffer *headerbuf;
11926                 GstBuffer *extra;
11927
11928                 waveheader += 8;
11929                 headerlen -= 8;
11930
11931                 headerbuf = gst_buffer_new_and_alloc (headerlen);
11932                 gst_buffer_fill (headerbuf, 0, waveheader, headerlen);
11933
11934                 if (gst_riff_parse_strf_auds (GST_ELEMENT_CAST (qtdemux),
11935                         headerbuf, &header, &extra)) {
11936                   gst_caps_unref (entry->caps);
11937                   /* FIXME: Need to do something with the channel reorder map */
11938                   entry->caps =
11939                       gst_riff_create_audio_caps (header->format, NULL, header,
11940                       extra, NULL, NULL, NULL);
11941
11942                   if (extra)
11943                     gst_buffer_unref (extra);
11944                   g_free (header);
11945                 }
11946               }
11947             } else
11948               GST_DEBUG ("Didn't find waveheadernode for this codec");
11949           }
11950           g_node_destroy (wavenode);
11951         }
11952       } else if (esds) {
11953         gst_qtdemux_handle_esds (qtdemux, stream, entry, esds,
11954             stream->stream_tags);
11955       } else {
11956         switch (fourcc) {
11957 #if 0
11958             /* FIXME: what is in the chunk? */
11959           case FOURCC_QDMC:
11960           {
11961             gint len = QT_UINT32 (stsd_data);
11962
11963             /* seems to be always = 116 = 0x74 */
11964             break;
11965           }
11966 #endif
11967           case FOURCC_QDM2:
11968           {
11969             gint len = QT_UINT32 (stsd_entry_data);
11970
11971             if (len > 0x3C) {
11972               GstBuffer *buf = gst_buffer_new_and_alloc (len - 0x3C);
11973
11974               gst_buffer_fill (buf, 0, stsd_entry_data + 0x3C, len - 0x3C);
11975               gst_caps_set_simple (entry->caps,
11976                   "codec_data", GST_TYPE_BUFFER, buf, NULL);
11977               gst_buffer_unref (buf);
11978             }
11979             gst_caps_set_simple (entry->caps,
11980                 "samplesize", G_TYPE_INT, samplesize, NULL);
11981             break;
11982           }
11983           case FOURCC_alac:
11984           {
11985             GNode *alac, *wave = NULL;
11986
11987             /* apparently, m4a has this atom appended directly in the stsd entry,
11988              * while mov has it in a wave atom */
11989             alac = qtdemux_tree_get_child_by_type (stsd, FOURCC_alac);
11990             if (alac) {
11991               /* alac now refers to stsd entry atom */
11992               wave = qtdemux_tree_get_child_by_type (alac, FOURCC_wave);
11993               if (wave)
11994                 alac = qtdemux_tree_get_child_by_type (wave, FOURCC_alac);
11995               else
11996                 alac = qtdemux_tree_get_child_by_type (alac, FOURCC_alac);
11997             }
11998             if (alac) {
11999               const guint8 *alac_data = alac->data;
12000               gint len = QT_UINT32 (alac->data);
12001               GstBuffer *buf;
12002
12003               if (len < 36) {
12004                 GST_DEBUG_OBJECT (qtdemux,
12005                     "discarding alac atom with unexpected len %d", len);
12006               } else {
12007                 /* codec-data contains alac atom size and prefix,
12008                  * ffmpeg likes it that way, not quite gst-ish though ...*/
12009                 buf = gst_buffer_new_and_alloc (len);
12010                 gst_buffer_fill (buf, 0, alac->data, len);
12011                 gst_caps_set_simple (entry->caps,
12012                     "codec_data", GST_TYPE_BUFFER, buf, NULL);
12013                 gst_buffer_unref (buf);
12014
12015                 entry->bytes_per_frame = QT_UINT32 (alac_data + 12);
12016                 entry->n_channels = QT_UINT8 (alac_data + 21);
12017                 entry->rate = QT_UINT32 (alac_data + 32);
12018               }
12019             }
12020             gst_caps_set_simple (entry->caps,
12021                 "samplesize", G_TYPE_INT, samplesize, NULL);
12022             break;
12023           }
12024           case FOURCC_fLaC:
12025           {
12026             /* The codingname of the sample entry is 'fLaC' */
12027             GNode *flac = qtdemux_tree_get_child_by_type (stsd, FOURCC_fLaC);
12028
12029             if (flac) {
12030               /* The 'dfLa' box is added to the sample entry to convey
12031                  initializing information for the decoder. */
12032               const GNode *dfla =
12033                   qtdemux_tree_get_child_by_type (flac, FOURCC_dfLa);
12034
12035               if (dfla) {
12036                 const guint32 len = QT_UINT32 (dfla->data);
12037
12038                 /* Must contain at least dfLa box header (12),
12039                  * METADATA_BLOCK_HEADER (4), METADATA_BLOCK_STREAMINFO (34) */
12040                 if (len < 50) {
12041                   GST_DEBUG_OBJECT (qtdemux,
12042                       "discarding dfla atom with unexpected len %d", len);
12043                 } else {
12044                   /* skip dfLa header to get the METADATA_BLOCKs */
12045                   const guint8 *metadata_blocks = (guint8 *) dfla->data + 12;
12046                   const guint32 metadata_blocks_len = len - 12;
12047
12048                   gchar *stream_marker = g_strdup ("fLaC");
12049                   GstBuffer *block = gst_buffer_new_wrapped (stream_marker,
12050                       strlen (stream_marker));
12051
12052                   guint32 index = 0;
12053                   guint32 remainder = 0;
12054                   guint32 block_size = 0;
12055                   gboolean is_last = FALSE;
12056
12057                   GValue array = G_VALUE_INIT;
12058                   GValue value = G_VALUE_INIT;
12059
12060                   g_value_init (&array, GST_TYPE_ARRAY);
12061                   g_value_init (&value, GST_TYPE_BUFFER);
12062
12063                   gst_value_set_buffer (&value, block);
12064                   gst_value_array_append_value (&array, &value);
12065                   g_value_reset (&value);
12066
12067                   gst_buffer_unref (block);
12068
12069                   /* check there's at least one METADATA_BLOCK_HEADER's worth
12070                    * of data, and we haven't already finished parsing */
12071                   while (!is_last && ((index + 3) < metadata_blocks_len)) {
12072                     remainder = metadata_blocks_len - index;
12073
12074                     /* add the METADATA_BLOCK_HEADER size to the signalled size */
12075                     block_size = 4 +
12076                         (metadata_blocks[index + 1] << 16) +
12077                         (metadata_blocks[index + 2] << 8) +
12078                         metadata_blocks[index + 3];
12079
12080                     /* be careful not to read off end of box */
12081                     if (block_size > remainder) {
12082                       break;
12083                     }
12084
12085                     is_last = metadata_blocks[index] >> 7;
12086
12087                     block = gst_buffer_new_and_alloc (block_size);
12088
12089                     gst_buffer_fill (block, 0, &metadata_blocks[index],
12090                         block_size);
12091
12092                     gst_value_set_buffer (&value, block);
12093                     gst_value_array_append_value (&array, &value);
12094                     g_value_reset (&value);
12095
12096                     gst_buffer_unref (block);
12097
12098                     index += block_size;
12099                   }
12100
12101                   /* only append the metadata if we successfully read all of it */
12102                   if (is_last) {
12103                     gst_structure_set_value (gst_caps_get_structure (CUR_STREAM
12104                             (stream)->caps, 0), "streamheader", &array);
12105                   } else {
12106                     GST_WARNING_OBJECT (qtdemux,
12107                         "discarding all METADATA_BLOCKs due to invalid "
12108                         "block_size %d at idx %d, rem %d", block_size, index,
12109                         remainder);
12110                   }
12111
12112                   g_value_unset (&value);
12113                   g_value_unset (&array);
12114
12115                   /* The sample rate obtained from the stsd may not be accurate
12116                    * since it cannot represent rates greater than 65535Hz, so
12117                    * override that value with the sample rate from the
12118                    * METADATA_BLOCK_STREAMINFO block */
12119                   CUR_STREAM (stream)->rate =
12120                       (QT_UINT32 (metadata_blocks + 14) >> 12) & 0xFFFFF;
12121                 }
12122               }
12123             }
12124             break;
12125           }
12126           case FOURCC_sawb:
12127             /* Fallthrough! */
12128             amrwb = TRUE;
12129           case FOURCC_samr:
12130           {
12131             gint len = QT_UINT32 (stsd_entry_data);
12132
12133             if (len > 0x24) {
12134               GstBuffer *buf = gst_buffer_new_and_alloc (len - 0x24);
12135               guint bitrate;
12136
12137               gst_buffer_fill (buf, 0, stsd_entry_data + 0x24, len - 0x24);
12138
12139               /* If we have enough data, let's try to get the 'damr' atom. See
12140                * the 3GPP container spec (26.244) for more details. */
12141               if ((len - 0x34) > 8 &&
12142                   (bitrate = qtdemux_parse_amr_bitrate (buf, amrwb))) {
12143                 gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
12144                     GST_TAG_MAXIMUM_BITRATE, bitrate, NULL);
12145               }
12146
12147               gst_caps_set_simple (entry->caps,
12148                   "codec_data", GST_TYPE_BUFFER, buf, NULL);
12149               gst_buffer_unref (buf);
12150             }
12151             break;
12152           }
12153           case FOURCC_mp4a:
12154           {
12155             /* mp4a atom withtout ESDS; Attempt to build codec data from atom */
12156             gint len = QT_UINT32 (stsd_entry_data);
12157
12158             if (len >= 34) {
12159               guint16 sound_version = QT_UINT16 (stsd_entry_data + 16);
12160
12161               if (sound_version == 1) {
12162                 guint16 channels = QT_UINT16 (stsd_entry_data + 24);
12163                 guint32 time_scale = QT_UINT32 (stsd_entry_data + 30);
12164                 guint8 codec_data[2];
12165                 GstBuffer *buf;
12166                 gint profile = 2;       /* FIXME: Can this be determined somehow? There doesn't seem to be anything in mp4a atom that specifis compression */
12167
12168                 gint sample_rate_index =
12169                     gst_codec_utils_aac_get_index_from_sample_rate (time_scale);
12170
12171                 /* build AAC codec data */
12172                 codec_data[0] = profile << 3;
12173                 codec_data[0] |= ((sample_rate_index >> 1) & 0x7);
12174                 codec_data[1] = (sample_rate_index & 0x01) << 7;
12175                 codec_data[1] |= (channels & 0xF) << 3;
12176
12177                 buf = gst_buffer_new_and_alloc (2);
12178                 gst_buffer_fill (buf, 0, codec_data, 2);
12179                 gst_caps_set_simple (entry->caps,
12180                     "codec_data", GST_TYPE_BUFFER, buf, NULL);
12181                 gst_buffer_unref (buf);
12182               }
12183             }
12184             break;
12185           }
12186           case FOURCC_lpcm:
12187             /* Fully handled elsewhere */
12188             break;
12189           default:
12190             GST_INFO_OBJECT (qtdemux,
12191                 "unhandled type %" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (fourcc));
12192             break;
12193         }
12194       }
12195       GST_INFO_OBJECT (qtdemux,
12196           "type %" GST_FOURCC_FORMAT " caps %" GST_PTR_FORMAT,
12197           GST_FOURCC_ARGS (fourcc), entry->caps);
12198
12199     } else if (stream->subtype == FOURCC_strm) {
12200       if (fourcc == FOURCC_rtsp) {
12201         stream->redirect_uri = qtdemux_get_rtsp_uri_from_hndl (qtdemux, minf);
12202       } else {
12203         GST_INFO_OBJECT (qtdemux, "unhandled stream type %" GST_FOURCC_FORMAT,
12204             GST_FOURCC_ARGS (fourcc));
12205         goto unknown_stream;
12206       }
12207       entry->sampled = TRUE;
12208     } else if (stream->subtype == FOURCC_subp || stream->subtype == FOURCC_text
12209         || stream->subtype == FOURCC_sbtl || stream->subtype == FOURCC_subt
12210         || stream->subtype == FOURCC_clcp) {
12211
12212       entry->sampled = TRUE;
12213       entry->sparse = TRUE;
12214
12215       entry->caps =
12216           qtdemux_sub_caps (qtdemux, stream, entry, fourcc, stsd_entry_data,
12217           &codec);
12218       if (codec) {
12219         gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
12220             GST_TAG_SUBTITLE_CODEC, codec, NULL);
12221         g_free (codec);
12222         codec = NULL;
12223       }
12224
12225       /* hunt for sort-of codec data */
12226       switch (fourcc) {
12227         case FOURCC_mp4s:
12228         {
12229           GNode *mp4s = NULL;
12230           GNode *esds = NULL;
12231
12232           /* look for palette in a stsd->mp4s->esds sub-atom */
12233           mp4s = qtdemux_tree_get_child_by_type (stsd, FOURCC_mp4s);
12234           if (mp4s)
12235             esds = qtdemux_tree_get_child_by_type (mp4s, FOURCC_esds);
12236           if (esds == NULL) {
12237             /* Invalid STSD */
12238             GST_LOG_OBJECT (qtdemux, "Skipping invalid stsd: no esds child");
12239             break;
12240           }
12241
12242           gst_qtdemux_handle_esds (qtdemux, stream, entry, esds,
12243               stream->stream_tags);
12244           break;
12245         }
12246         default:
12247           GST_INFO_OBJECT (qtdemux,
12248               "unhandled type %" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (fourcc));
12249           break;
12250       }
12251       GST_INFO_OBJECT (qtdemux,
12252           "type %" GST_FOURCC_FORMAT " caps %" GST_PTR_FORMAT,
12253           GST_FOURCC_ARGS (fourcc), entry->caps);
12254     } else {
12255       /* everything in 1 sample */
12256       entry->sampled = TRUE;
12257
12258       entry->caps =
12259           qtdemux_generic_caps (qtdemux, stream, entry, fourcc, stsd_entry_data,
12260           &codec);
12261
12262       if (entry->caps == NULL)
12263         goto unknown_stream;
12264
12265       if (codec) {
12266         gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
12267             GST_TAG_SUBTITLE_CODEC, codec, NULL);
12268         g_free (codec);
12269         codec = NULL;
12270       }
12271     }
12272
12273     /* promote to sampled format */
12274     if (entry->fourcc == FOURCC_samr) {
12275       /* force mono 8000 Hz for AMR */
12276       entry->sampled = TRUE;
12277       entry->n_channels = 1;
12278       entry->rate = 8000;
12279     } else if (entry->fourcc == FOURCC_sawb) {
12280       /* force mono 16000 Hz for AMR-WB */
12281       entry->sampled = TRUE;
12282       entry->n_channels = 1;
12283       entry->rate = 16000;
12284     } else if (entry->fourcc == FOURCC_mp4a) {
12285       entry->sampled = TRUE;
12286     }
12287
12288
12289     stsd_entry_data += len;
12290     remaining_stsd_len -= len;
12291
12292   }
12293
12294   /* collect sample information */
12295   if (!qtdemux_stbl_init (qtdemux, stream, stbl))
12296     goto samples_failed;
12297
12298   if (qtdemux->fragmented) {
12299     guint64 offset;
12300
12301     /* need all moov samples as basis; probably not many if any at all */
12302     /* prevent moof parsing taking of at this time */
12303     offset = qtdemux->moof_offset;
12304     qtdemux->moof_offset = 0;
12305     if (stream->n_samples &&
12306         !qtdemux_parse_samples (qtdemux, stream, stream->n_samples - 1)) {
12307       qtdemux->moof_offset = offset;
12308       goto samples_failed;
12309     }
12310     qtdemux->moof_offset = 0;
12311     /* movie duration more reliable in this case (e.g. mehd) */
12312     if (qtdemux->segment.duration &&
12313         GST_CLOCK_TIME_IS_VALID (qtdemux->segment.duration))
12314       stream->duration =
12315           GSTTIME_TO_QTSTREAMTIME (stream, qtdemux->segment.duration);
12316   }
12317
12318   /* configure segments */
12319   if (!qtdemux_parse_segments (qtdemux, stream, trak))
12320     goto segments_failed;
12321
12322   /* add some language tag, if useful */
12323   if (stream->lang_id[0] != '\0' && strcmp (stream->lang_id, "unk") &&
12324       strcmp (stream->lang_id, "und")) {
12325     const gchar *lang_code;
12326
12327     /* convert ISO 639-2 code to ISO 639-1 */
12328     lang_code = gst_tag_get_language_code (stream->lang_id);
12329     gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
12330         GST_TAG_LANGUAGE_CODE, (lang_code) ? lang_code : stream->lang_id, NULL);
12331   }
12332
12333   /* Check for UDTA tags */
12334   if ((udta = qtdemux_tree_get_child_by_type (trak, FOURCC_udta))) {
12335     qtdemux_parse_udta (qtdemux, stream->stream_tags, udta);
12336   }
12337
12338   /* Insert and sort new stream in track-id order.
12339    * This will help in comparing old/new streams during stream update check */
12340   g_ptr_array_add (qtdemux->active_streams, stream);
12341   g_ptr_array_sort (qtdemux->active_streams,
12342       (GCompareFunc) qtdemux_track_id_compare_func);
12343   GST_DEBUG_OBJECT (qtdemux, "n_streams is now %d",
12344       QTDEMUX_N_STREAMS (qtdemux));
12345
12346   return TRUE;
12347
12348 /* ERRORS */
12349 corrupt_file:
12350   {
12351     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
12352         (_("This file is corrupt and cannot be played.")), (NULL));
12353     if (stream)
12354       gst_qtdemux_stream_unref (stream);
12355     return FALSE;
12356   }
12357 error_encrypted:
12358   {
12359     GST_ELEMENT_ERROR (qtdemux, STREAM, DECRYPT, (NULL), (NULL));
12360     gst_qtdemux_stream_unref (stream);
12361     return FALSE;
12362   }
12363 samples_failed:
12364 segments_failed:
12365   {
12366     /* we posted an error already */
12367     /* free stbl sub-atoms */
12368     gst_qtdemux_stbl_free (stream);
12369     gst_qtdemux_stream_unref (stream);
12370     return FALSE;
12371   }
12372 existing_stream:
12373   {
12374     GST_INFO_OBJECT (qtdemux, "stream with track id %i already exists",
12375         track_id);
12376     return TRUE;
12377   }
12378 unknown_stream:
12379   {
12380     GST_INFO_OBJECT (qtdemux, "unknown subtype %" GST_FOURCC_FORMAT,
12381         GST_FOURCC_ARGS (stream->subtype));
12382     gst_qtdemux_stream_unref (stream);
12383     return TRUE;
12384   }
12385 }
12386
12387 /* If we can estimate the overall bitrate, and don't have information about the
12388  * stream bitrate for exactly one stream, this guesses the stream bitrate as
12389  * the overall bitrate minus the sum of the bitrates of all other streams. This
12390  * should be useful for the common case where we have one audio and one video
12391  * stream and can estimate the bitrate of one, but not the other. */
12392 static void
12393 gst_qtdemux_guess_bitrate (GstQTDemux * qtdemux)
12394 {
12395   QtDemuxStream *stream = NULL;
12396   gint64 size, sys_bitrate, sum_bitrate = 0;
12397   GstClockTime duration;
12398   guint bitrate;
12399   gint i;
12400
12401   if (qtdemux->fragmented)
12402     return;
12403
12404   GST_DEBUG_OBJECT (qtdemux, "Looking for streams with unknown bitrate");
12405
12406   if (!gst_pad_peer_query_duration (qtdemux->sinkpad, GST_FORMAT_BYTES, &size)
12407       || size <= 0) {
12408     GST_DEBUG_OBJECT (qtdemux,
12409         "Size in bytes of the stream not known - bailing");
12410     return;
12411   }
12412
12413   /* Subtract the header size */
12414   GST_DEBUG_OBJECT (qtdemux, "Total size %" G_GINT64_FORMAT ", header size %u",
12415       size, qtdemux->header_size);
12416
12417   if (size < qtdemux->header_size)
12418     return;
12419
12420   size = size - qtdemux->header_size;
12421
12422   if (!gst_qtdemux_get_duration (qtdemux, &duration)) {
12423     GST_DEBUG_OBJECT (qtdemux, "Stream duration not known - bailing");
12424     return;
12425   }
12426
12427   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
12428     QtDemuxStream *str = QTDEMUX_NTH_STREAM (qtdemux, i);
12429     switch (str->subtype) {
12430       case FOURCC_soun:
12431       case FOURCC_vide:
12432         GST_DEBUG_OBJECT (qtdemux, "checking bitrate for %" GST_PTR_FORMAT,
12433             CUR_STREAM (str)->caps);
12434         /* retrieve bitrate, prefer avg then max */
12435         bitrate = 0;
12436         if (str->stream_tags) {
12437           if (gst_tag_list_get_uint (str->stream_tags,
12438                   GST_TAG_MAXIMUM_BITRATE, &bitrate))
12439             GST_DEBUG_OBJECT (qtdemux, "max-bitrate: %u", bitrate);
12440           if (gst_tag_list_get_uint (str->stream_tags,
12441                   GST_TAG_NOMINAL_BITRATE, &bitrate))
12442             GST_DEBUG_OBJECT (qtdemux, "nominal-bitrate: %u", bitrate);
12443           if (gst_tag_list_get_uint (str->stream_tags,
12444                   GST_TAG_BITRATE, &bitrate))
12445             GST_DEBUG_OBJECT (qtdemux, "bitrate: %u", bitrate);
12446         }
12447         if (bitrate)
12448           sum_bitrate += bitrate;
12449         else {
12450           if (stream) {
12451             GST_DEBUG_OBJECT (qtdemux,
12452                 ">1 stream with unknown bitrate - bailing");
12453             return;
12454           } else
12455             stream = str;
12456         }
12457
12458       default:
12459         /* For other subtypes, we assume no significant impact on bitrate */
12460         break;
12461     }
12462   }
12463
12464   if (!stream) {
12465     GST_DEBUG_OBJECT (qtdemux, "All stream bitrates are known");
12466     return;
12467   }
12468
12469   sys_bitrate = gst_util_uint64_scale (size, GST_SECOND * 8, duration);
12470
12471   if (sys_bitrate < sum_bitrate) {
12472     /* This can happen, since sum_bitrate might be derived from maximum
12473      * bitrates and not average bitrates */
12474     GST_DEBUG_OBJECT (qtdemux,
12475         "System bitrate less than sum bitrate - bailing");
12476     return;
12477   }
12478
12479   bitrate = sys_bitrate - sum_bitrate;
12480   GST_DEBUG_OBJECT (qtdemux, "System bitrate = %" G_GINT64_FORMAT
12481       ", Stream bitrate = %u", sys_bitrate, bitrate);
12482
12483   if (!stream->stream_tags)
12484     stream->stream_tags = gst_tag_list_new_empty ();
12485   else
12486     stream->stream_tags = gst_tag_list_make_writable (stream->stream_tags);
12487
12488   gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
12489       GST_TAG_BITRATE, bitrate, NULL);
12490 }
12491
12492 static GstFlowReturn
12493 qtdemux_prepare_streams (GstQTDemux * qtdemux)
12494 {
12495   GstFlowReturn ret = GST_FLOW_OK;
12496   gint i;
12497
12498   GST_DEBUG_OBJECT (qtdemux, "prepare streams");
12499
12500   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
12501     QtDemuxStream *stream = QTDEMUX_NTH_STREAM (qtdemux, i);
12502     guint32 sample_num = 0;
12503
12504     GST_DEBUG_OBJECT (qtdemux, "track-id %u, fourcc %" GST_FOURCC_FORMAT,
12505         stream->track_id, GST_FOURCC_ARGS (CUR_STREAM (stream)->fourcc));
12506
12507     if (qtdemux->fragmented) {
12508       /* need all moov samples first */
12509       GST_OBJECT_LOCK (qtdemux);
12510       while (stream->n_samples == 0)
12511         if ((ret = qtdemux_add_fragmented_samples (qtdemux)) != GST_FLOW_OK)
12512           break;
12513       GST_OBJECT_UNLOCK (qtdemux);
12514     } else {
12515       /* discard any stray moof */
12516       qtdemux->moof_offset = 0;
12517     }
12518
12519     /* prepare braking */
12520     if (ret != GST_FLOW_ERROR)
12521       ret = GST_FLOW_OK;
12522
12523     /* in pull mode, we should have parsed some sample info by now;
12524      * and quite some code will not handle no samples.
12525      * in push mode, we'll just have to deal with it */
12526     if (G_UNLIKELY (qtdemux->pullbased && !stream->n_samples)) {
12527       GST_DEBUG_OBJECT (qtdemux, "no samples for stream; discarding");
12528       g_ptr_array_remove_index (qtdemux->active_streams, i);
12529       i--;
12530       continue;
12531     } else if (stream->track_id == qtdemux->chapters_track_id &&
12532         (stream->subtype == FOURCC_text || stream->subtype == FOURCC_sbtl)) {
12533       /* TODO - parse chapters track and expose it as GstToc; For now just ignore it
12534          so that it doesn't look like a subtitle track */
12535       g_ptr_array_remove_index (qtdemux->active_streams, i);
12536       i--;
12537       continue;
12538     }
12539
12540     /* parse the initial sample for use in setting the frame rate cap */
12541     while (sample_num == 0 && sample_num < stream->n_samples) {
12542       if (!qtdemux_parse_samples (qtdemux, stream, sample_num))
12543         break;
12544       ++sample_num;
12545     }
12546   }
12547
12548   return ret;
12549 }
12550
12551 static gboolean
12552 _stream_equal_func (const QtDemuxStream * stream, const gchar * stream_id)
12553 {
12554   return g_strcmp0 (stream->stream_id, stream_id) == 0;
12555 }
12556
12557 static gboolean
12558 qtdemux_is_streams_update (GstQTDemux * qtdemux)
12559 {
12560   gint i;
12561
12562   /* Different length, updated */
12563   if (QTDEMUX_N_STREAMS (qtdemux) != qtdemux->old_streams->len)
12564     return TRUE;
12565
12566   /* streams in list are sorted in track-id order */
12567   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
12568     /* Different stream-id, updated */
12569     if (g_strcmp0 (QTDEMUX_NTH_STREAM (qtdemux, i)->stream_id,
12570             QTDEMUX_NTH_OLD_STREAM (qtdemux, i)->stream_id))
12571       return TRUE;
12572   }
12573
12574   return FALSE;
12575 }
12576
12577 static gboolean
12578 qtdemux_reuse_and_configure_stream (GstQTDemux * qtdemux,
12579     QtDemuxStream * oldstream, QtDemuxStream * newstream)
12580 {
12581   /* Connect old stream's srcpad to new stream */
12582   newstream->pad = oldstream->pad;
12583   oldstream->pad = NULL;
12584
12585   /* unset new_stream to prevent stream-start event */
12586   newstream->new_stream = FALSE;
12587
12588   return gst_qtdemux_configure_stream (qtdemux, newstream);
12589 }
12590
12591 /* g_ptr_array_find_with_equal_func is available since 2.54,
12592  * replacement until we can depend unconditionally on the real one in GLib */
12593 #if !GLIB_CHECK_VERSION(2,54,0)
12594 #define g_ptr_array_find_with_equal_func qtdemux_ptr_array_find_with_equal_func
12595 static gboolean
12596 qtdemux_ptr_array_find_with_equal_func (GPtrArray * haystack,
12597     gconstpointer needle, GEqualFunc equal_func, guint * index_)
12598 {
12599   guint i;
12600
12601   g_return_val_if_fail (haystack != NULL, FALSE);
12602
12603   if (equal_func == NULL)
12604     equal_func = g_direct_equal;
12605
12606   for (i = 0; i < haystack->len; i++) {
12607     if (equal_func (g_ptr_array_index (haystack, i), needle)) {
12608       if (index_ != NULL)
12609         *index_ = i;
12610       return TRUE;
12611     }
12612   }
12613
12614   return FALSE;
12615 }
12616 #endif
12617
12618 static gboolean
12619 qtdemux_update_streams (GstQTDemux * qtdemux)
12620 {
12621   gint i;
12622   g_assert (qtdemux->streams_aware);
12623
12624   /* At below, figure out which stream in active_streams has identical stream-id
12625    * with that of in old_streams. If there is matching stream-id,
12626    * corresponding newstream will not be exposed again,
12627    * but demux will reuse srcpad of matched old stream
12628    *
12629    * active_streams : newly created streams from the latest moov
12630    * old_streams : existing streams (belong to previous moov)
12631    */
12632
12633   for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
12634     QtDemuxStream *stream = QTDEMUX_NTH_STREAM (qtdemux, i);
12635     QtDemuxStream *oldstream = NULL;
12636     guint target;
12637
12638     GST_DEBUG_OBJECT (qtdemux, "track-id %u, fourcc %" GST_FOURCC_FORMAT,
12639         stream->track_id, GST_FOURCC_ARGS (CUR_STREAM (stream)->fourcc));
12640
12641     if (g_ptr_array_find_with_equal_func (qtdemux->old_streams,
12642             stream->stream_id, (GEqualFunc) _stream_equal_func, &target)) {
12643       oldstream = QTDEMUX_NTH_OLD_STREAM (qtdemux, target);
12644
12645       /* null pad stream cannot be reused */
12646       if (oldstream->pad == NULL)
12647         oldstream = NULL;
12648     }
12649
12650     if (oldstream) {
12651       GST_DEBUG_OBJECT (qtdemux, "Reuse track-id %d", oldstream->track_id);
12652
12653       if (!qtdemux_reuse_and_configure_stream (qtdemux, oldstream, stream))
12654         return FALSE;
12655
12656       /* we don't need to preserve order of old streams */
12657       g_ptr_array_remove_fast (qtdemux->old_streams, oldstream);
12658     } else {
12659       GstTagList *list;
12660
12661       /* now we have all info and can expose */
12662       list = stream->stream_tags;
12663       stream->stream_tags = NULL;
12664       if (!gst_qtdemux_add_stream (qtdemux, stream, list))
12665         return FALSE;
12666     }
12667   }
12668
12669   return TRUE;
12670 }
12671
12672 /* Must be called with expose lock */
12673 static GstFlowReturn
12674 qtdemux_expose_streams (GstQTDemux * qtdemux)
12675 {
12676   gint i;
12677
12678   GST_DEBUG_OBJECT (qtdemux, "exposing streams");
12679
12680   if (!qtdemux_is_streams_update (qtdemux)) {
12681     GST_DEBUG_OBJECT (qtdemux, "Reuse all streams");
12682     for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
12683       QtDemuxStream *new_stream = QTDEMUX_NTH_STREAM (qtdemux, i);
12684       QtDemuxStream *old_stream = QTDEMUX_NTH_OLD_STREAM (qtdemux, i);
12685       if (!qtdemux_reuse_and_configure_stream (qtdemux, old_stream, new_stream))
12686         return GST_FLOW_ERROR;
12687     }
12688
12689     g_ptr_array_remove_range (qtdemux->old_streams,
12690         0, qtdemux->old_streams->len);
12691
12692     qtdemux->need_segment = TRUE;
12693
12694     return GST_FLOW_OK;
12695   }
12696
12697   if (qtdemux->streams_aware) {
12698     if (!qtdemux_update_streams (qtdemux))
12699       return GST_FLOW_ERROR;
12700   } else {
12701     for (i = 0; i < QTDEMUX_N_STREAMS (qtdemux); i++) {
12702       QtDemuxStream *stream = QTDEMUX_NTH_STREAM (qtdemux, i);
12703       GstTagList *list;
12704
12705       /* now we have all info and can expose */
12706       list = stream->stream_tags;
12707       stream->stream_tags = NULL;
12708       if (!gst_qtdemux_add_stream (qtdemux, stream, list))
12709         return GST_FLOW_ERROR;
12710
12711     }
12712   }
12713
12714   gst_qtdemux_guess_bitrate (qtdemux);
12715
12716   gst_element_no_more_pads (GST_ELEMENT_CAST (qtdemux));
12717
12718   /* If we have still old_streams, it's no more used stream */
12719   for (i = 0; i < qtdemux->old_streams->len; i++) {
12720     QtDemuxStream *stream = QTDEMUX_NTH_OLD_STREAM (qtdemux, i);
12721
12722     if (stream->pad) {
12723       GstEvent *event;
12724
12725       event = gst_event_new_eos ();
12726       if (qtdemux->segment_seqnum)
12727         gst_event_set_seqnum (event, qtdemux->segment_seqnum);
12728
12729       gst_pad_push_event (stream->pad, event);
12730     }
12731   }
12732
12733   g_ptr_array_remove_range (qtdemux->old_streams, 0, qtdemux->old_streams->len);
12734
12735   /* check if we should post a redirect in case there is a single trak
12736    * and it is a redirecting trak */
12737   if (QTDEMUX_N_STREAMS (qtdemux) == 1 &&
12738       QTDEMUX_NTH_STREAM (qtdemux, 0)->redirect_uri != NULL) {
12739     GstMessage *m;
12740
12741     GST_INFO_OBJECT (qtdemux, "Issuing a redirect due to a single track with "
12742         "an external content");
12743     m = gst_message_new_element (GST_OBJECT_CAST (qtdemux),
12744         gst_structure_new ("redirect",
12745             "new-location", G_TYPE_STRING,
12746             QTDEMUX_NTH_STREAM (qtdemux, 0)->redirect_uri, NULL));
12747     gst_element_post_message (GST_ELEMENT_CAST (qtdemux), m);
12748     qtdemux->posted_redirect = TRUE;
12749   }
12750
12751   g_ptr_array_foreach (qtdemux->active_streams,
12752       (GFunc) qtdemux_do_allocation, qtdemux);
12753
12754   qtdemux->need_segment = TRUE;
12755
12756   qtdemux->exposed = TRUE;
12757   return GST_FLOW_OK;
12758 }
12759
12760 /* check if major or compatible brand is 3GP */
12761 static inline gboolean
12762 qtdemux_is_brand_3gp (GstQTDemux * qtdemux, gboolean major)
12763 {
12764   if (major) {
12765     return ((qtdemux->major_brand & GST_MAKE_FOURCC (255, 255, 0, 0)) ==
12766         FOURCC_3g__);
12767   } else if (qtdemux->comp_brands != NULL) {
12768     GstMapInfo map;
12769     guint8 *data;
12770     gsize size;
12771     gboolean res = FALSE;
12772
12773     gst_buffer_map (qtdemux->comp_brands, &map, GST_MAP_READ);
12774     data = map.data;
12775     size = map.size;
12776     while (size >= 4) {
12777       res = res || ((QT_FOURCC (data) & GST_MAKE_FOURCC (255, 255, 0, 0)) ==
12778           FOURCC_3g__);
12779       data += 4;
12780       size -= 4;
12781     }
12782     gst_buffer_unmap (qtdemux->comp_brands, &map);
12783     return res;
12784   } else {
12785     return FALSE;
12786   }
12787 }
12788
12789 /* check if tag is a spec'ed 3GP tag keyword storing a string */
12790 static inline gboolean
12791 qtdemux_is_string_tag_3gp (GstQTDemux * qtdemux, guint32 fourcc)
12792 {
12793   return fourcc == FOURCC_cprt || fourcc == FOURCC_gnre || fourcc == FOURCC_titl
12794       || fourcc == FOURCC_dscp || fourcc == FOURCC_perf || fourcc == FOURCC_auth
12795       || fourcc == FOURCC_albm;
12796 }
12797
12798 static void
12799 qtdemux_tag_add_location (GstQTDemux * qtdemux, GstTagList * taglist,
12800     const char *tag, const char *dummy, GNode * node)
12801 {
12802   const gchar *env_vars[] = { "GST_QT_TAG_ENCODING", "GST_TAG_ENCODING", NULL };
12803   int offset;
12804   char *name;
12805   gchar *data;
12806   gdouble longitude, latitude, altitude;
12807   gint len;
12808
12809   len = QT_UINT32 (node->data);
12810   if (len <= 14)
12811     goto short_read;
12812
12813   data = node->data;
12814   offset = 14;
12815
12816   /* TODO: language code skipped */
12817
12818   name = gst_tag_freeform_string_to_utf8 (data + offset, -1, env_vars);
12819
12820   if (!name) {
12821     /* do not alarm in trivial case, but bail out otherwise */
12822     if (*(data + offset) != 0) {
12823       GST_DEBUG_OBJECT (qtdemux, "failed to convert %s tag to UTF-8, "
12824           "giving up", tag);
12825     }
12826   } else {
12827     gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE,
12828         GST_TAG_GEO_LOCATION_NAME, name, NULL);
12829     offset += strlen (name);
12830     g_free (name);
12831   }
12832
12833   if (len < offset + 2 + 4 + 4 + 4)
12834     goto short_read;
12835
12836   /* +1 +1 = skip null-terminator and location role byte */
12837   offset += 1 + 1;
12838   /* table in spec says unsigned, semantics say negative has meaning ... */
12839   longitude = QT_SFP32 (data + offset);
12840
12841   offset += 4;
12842   latitude = QT_SFP32 (data + offset);
12843
12844   offset += 4;
12845   altitude = QT_SFP32 (data + offset);
12846
12847   /* one invalid means all are invalid */
12848   if (longitude >= -180.0 && longitude <= 180.0 &&
12849       latitude >= -90.0 && latitude <= 90.0) {
12850     gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE,
12851         GST_TAG_GEO_LOCATION_LATITUDE, latitude,
12852         GST_TAG_GEO_LOCATION_LONGITUDE, longitude,
12853         GST_TAG_GEO_LOCATION_ELEVATION, altitude, NULL);
12854   }
12855
12856   /* TODO: no GST_TAG_, so astronomical body and additional notes skipped */
12857
12858   return;
12859
12860   /* ERRORS */
12861 short_read:
12862   {
12863     GST_DEBUG_OBJECT (qtdemux, "short read parsing 3GP location");
12864     return;
12865   }
12866 }
12867
12868
12869 static void
12870 qtdemux_tag_add_year (GstQTDemux * qtdemux, GstTagList * taglist,
12871     const char *tag, const char *dummy, GNode * node)
12872 {
12873   guint16 y;
12874   GDate *date;
12875   gint len;
12876
12877   len = QT_UINT32 (node->data);
12878   if (len < 14)
12879     return;
12880
12881   y = QT_UINT16 ((guint8 *) node->data + 12);
12882   if (y == 0) {
12883     GST_DEBUG_OBJECT (qtdemux, "year: %u is not a valid year", y);
12884     return;
12885   }
12886   GST_DEBUG_OBJECT (qtdemux, "year: %u", y);
12887
12888   date = g_date_new_dmy (1, 1, y);
12889   gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag, date, NULL);
12890   g_date_free (date);
12891 }
12892
12893 static void
12894 qtdemux_tag_add_classification (GstQTDemux * qtdemux, GstTagList * taglist,
12895     const char *tag, const char *dummy, GNode * node)
12896 {
12897   int offset;
12898   char *tag_str = NULL;
12899   guint8 *entity;
12900   guint16 table;
12901   gint len;
12902
12903   len = QT_UINT32 (node->data);
12904   if (len <= 20)
12905     goto short_read;
12906
12907   offset = 12;
12908   entity = (guint8 *) node->data + offset;
12909   if (entity[0] == 0 || entity[1] == 0 || entity[2] == 0 || entity[3] == 0) {
12910     GST_DEBUG_OBJECT (qtdemux,
12911         "classification info: %c%c%c%c invalid classification entity",
12912         entity[0], entity[1], entity[2], entity[3]);
12913     return;
12914   }
12915
12916   offset += 4;
12917   table = QT_UINT16 ((guint8 *) node->data + offset);
12918
12919   /* Language code skipped */
12920
12921   offset += 4;
12922
12923   /* Tag format: "XXXX://Y[YYYY]/classification info string"
12924    * XXXX: classification entity, fixed length 4 chars.
12925    * Y[YYYY]: classification table, max 5 chars.
12926    */
12927   tag_str = g_strdup_printf ("----://%u/%s",
12928       table, (char *) node->data + offset);
12929
12930   /* memcpy To be sure we're preserving byte order */
12931   memcpy (tag_str, entity, 4);
12932   GST_DEBUG_OBJECT (qtdemux, "classification info: %s", tag_str);
12933
12934   gst_tag_list_add (taglist, GST_TAG_MERGE_APPEND, tag, tag_str, NULL);
12935
12936   g_free (tag_str);
12937
12938   return;
12939
12940   /* ERRORS */
12941 short_read:
12942   {
12943     GST_DEBUG_OBJECT (qtdemux, "short read parsing 3GP classification");
12944     return;
12945   }
12946 }
12947
12948 static gboolean
12949 qtdemux_tag_add_str_full (GstQTDemux * qtdemux, GstTagList * taglist,
12950     const char *tag, const char *dummy, GNode * node)
12951 {
12952   const gchar *env_vars[] = { "GST_QT_TAG_ENCODING", "GST_TAG_ENCODING", NULL };
12953   GNode *data;
12954   char *s;
12955   int len;
12956   guint32 type;
12957   int offset;
12958   gboolean ret = TRUE;
12959   const gchar *charset = NULL;
12960
12961   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
12962   if (data) {
12963     len = QT_UINT32 (data->data);
12964     type = QT_UINT32 ((guint8 *) data->data + 8);
12965     if (type == 0x00000001 && len > 16) {
12966       s = gst_tag_freeform_string_to_utf8 ((char *) data->data + 16, len - 16,
12967           env_vars);
12968       if (s) {
12969         GST_DEBUG_OBJECT (qtdemux, "adding tag %s", GST_STR_NULL (s));
12970         gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag, s, NULL);
12971         g_free (s);
12972       } else {
12973         GST_DEBUG_OBJECT (qtdemux, "failed to convert %s tag to UTF-8", tag);
12974       }
12975     }
12976   } else {
12977     len = QT_UINT32 (node->data);
12978     type = QT_UINT32 ((guint8 *) node->data + 4);
12979     if ((type >> 24) == 0xa9 && len > 8 + 4) {
12980       gint str_len;
12981       gint lang_code;
12982
12983       /* Type starts with the (C) symbol, so the next data is a list
12984        * of (string size(16), language code(16), string) */
12985
12986       str_len = QT_UINT16 ((guint8 *) node->data + 8);
12987       lang_code = QT_UINT16 ((guint8 *) node->data + 10);
12988
12989       /* the string + fourcc + size + 2 16bit fields,
12990        * means that there are more tags in this atom */
12991       if (len > str_len + 8 + 4) {
12992         /* TODO how to represent the same tag in different languages? */
12993         GST_WARNING_OBJECT (qtdemux, "Ignoring metadata entry with multiple "
12994             "text alternatives, reading only first one");
12995       }
12996
12997       offset = 12;
12998       len = MIN (len, str_len + 8 + 4); /* remove trailing strings that we don't use */
12999       GST_DEBUG_OBJECT (qtdemux, "found international text tag");
13000
13001       if (lang_code < 0x800) {  /* MAC encoded string */
13002         charset = "mac";
13003       }
13004     } else if (len > 14 && qtdemux_is_string_tag_3gp (qtdemux,
13005             QT_FOURCC ((guint8 *) node->data + 4))) {
13006       guint32 type = QT_UINT32 ((guint8 *) node->data + 8);
13007
13008       /* we go for 3GP style encoding if major brands claims so,
13009        * or if no hope for data be ok UTF-8, and compatible 3GP brand present */
13010       if (qtdemux_is_brand_3gp (qtdemux, TRUE) ||
13011           (qtdemux_is_brand_3gp (qtdemux, FALSE) &&
13012               ((type & 0x00FFFFFF) == 0x0) && (type >> 24 <= 0xF))) {
13013         offset = 14;
13014         /* 16-bit Language code is ignored here as well */
13015         GST_DEBUG_OBJECT (qtdemux, "found 3gpp text tag");
13016       } else {
13017         goto normal;
13018       }
13019     } else {
13020     normal:
13021       offset = 8;
13022       GST_DEBUG_OBJECT (qtdemux, "found normal text tag");
13023       ret = FALSE;              /* may have to fallback */
13024     }
13025     if (charset) {
13026       GError *err = NULL;
13027
13028       s = g_convert ((gchar *) node->data + offset, len - offset, "utf8",
13029           charset, NULL, NULL, &err);
13030       if (err) {
13031         GST_DEBUG_OBJECT (qtdemux, "Failed to convert string from charset %s:"
13032             " %s(%d): %s", charset, g_quark_to_string (err->domain), err->code,
13033             err->message);
13034         g_error_free (err);
13035       }
13036     } else {
13037       s = gst_tag_freeform_string_to_utf8 ((char *) node->data + offset,
13038           len - offset, env_vars);
13039     }
13040     if (s) {
13041       GST_DEBUG_OBJECT (qtdemux, "adding tag %s", GST_STR_NULL (s));
13042       gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag, s, NULL);
13043       g_free (s);
13044       ret = TRUE;
13045     } else {
13046       GST_DEBUG_OBJECT (qtdemux, "failed to convert %s tag to UTF-8", tag);
13047     }
13048   }
13049   return ret;
13050 }
13051
13052 static void
13053 qtdemux_tag_add_str (GstQTDemux * qtdemux, GstTagList * taglist,
13054     const char *tag, const char *dummy, GNode * node)
13055 {
13056   qtdemux_tag_add_str_full (qtdemux, taglist, tag, dummy, node);
13057 }
13058
13059 static void
13060 qtdemux_tag_add_keywords (GstQTDemux * qtdemux, GstTagList * taglist,
13061     const char *tag, const char *dummy, GNode * node)
13062 {
13063   const gchar *env_vars[] = { "GST_QT_TAG_ENCODING", "GST_TAG_ENCODING", NULL };
13064   guint8 *data;
13065   char *s, *t, *k = NULL;
13066   int len;
13067   int offset;
13068   int count;
13069
13070   /* first try normal string tag if major brand not 3GP */
13071   if (!qtdemux_is_brand_3gp (qtdemux, TRUE)) {
13072     if (!qtdemux_tag_add_str_full (qtdemux, taglist, tag, dummy, node)) {
13073       /* hm, that did not work, maybe 3gpp storage in non-3gpp major brand;
13074        * let's try it 3gpp way after minor safety check */
13075       data = node->data;
13076       if (QT_UINT32 (data) < 15 || !qtdemux_is_brand_3gp (qtdemux, FALSE))
13077         return;
13078     } else
13079       return;
13080   }
13081
13082   GST_DEBUG_OBJECT (qtdemux, "found 3gpp keyword tag");
13083
13084   data = node->data;
13085
13086   len = QT_UINT32 (data);
13087   if (len < 15)
13088     goto short_read;
13089
13090   count = QT_UINT8 (data + 14);
13091   offset = 15;
13092   for (; count; count--) {
13093     gint slen;
13094
13095     if (offset + 1 > len)
13096       goto short_read;
13097     slen = QT_UINT8 (data + offset);
13098     offset += 1;
13099     if (offset + slen > len)
13100       goto short_read;
13101     s = gst_tag_freeform_string_to_utf8 ((char *) node->data + offset,
13102         slen, env_vars);
13103     if (s) {
13104       GST_DEBUG_OBJECT (qtdemux, "adding keyword %s", GST_STR_NULL (s));
13105       if (k) {
13106         t = g_strjoin (",", k, s, NULL);
13107         g_free (s);
13108         g_free (k);
13109         k = t;
13110       } else {
13111         k = s;
13112       }
13113     } else {
13114       GST_DEBUG_OBJECT (qtdemux, "failed to convert keyword to UTF-8");
13115     }
13116     offset += slen;
13117   }
13118
13119 done:
13120   if (k) {
13121     GST_DEBUG_OBJECT (qtdemux, "adding tag %s", GST_STR_NULL (k));
13122     gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag, k, NULL);
13123   }
13124   g_free (k);
13125
13126   return;
13127
13128   /* ERRORS */
13129 short_read:
13130   {
13131     GST_DEBUG_OBJECT (qtdemux, "short read parsing 3GP keywords");
13132     goto done;
13133   }
13134 }
13135
13136 static void
13137 qtdemux_tag_add_num (GstQTDemux * qtdemux, GstTagList * taglist,
13138     const char *tag1, const char *tag2, GNode * node)
13139 {
13140   GNode *data;
13141   int len;
13142   int type;
13143   int n1, n2;
13144
13145   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
13146   if (data) {
13147     len = QT_UINT32 (data->data);
13148     type = QT_UINT32 ((guint8 *) data->data + 8);
13149     if (type == 0x00000000 && len >= 22) {
13150       n1 = QT_UINT16 ((guint8 *) data->data + 18);
13151       n2 = QT_UINT16 ((guint8 *) data->data + 20);
13152       if (n1 > 0) {
13153         GST_DEBUG_OBJECT (qtdemux, "adding tag %s=%d", tag1, n1);
13154         gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag1, n1, NULL);
13155       }
13156       if (n2 > 0) {
13157         GST_DEBUG_OBJECT (qtdemux, "adding tag %s=%d", tag2, n2);
13158         gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag2, n2, NULL);
13159       }
13160     }
13161   }
13162 }
13163
13164 static void
13165 qtdemux_tag_add_tmpo (GstQTDemux * qtdemux, GstTagList * taglist,
13166     const char *tag1, const char *dummy, GNode * node)
13167 {
13168   GNode *data;
13169   int len;
13170   int type;
13171   int n1;
13172
13173   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
13174   if (data) {
13175     len = QT_UINT32 (data->data);
13176     type = QT_UINT32 ((guint8 *) data->data + 8);
13177     GST_DEBUG_OBJECT (qtdemux, "have tempo tag, type=%d,len=%d", type, len);
13178     /* some files wrongly have a type 0x0f=15, but it should be 0x15 */
13179     if ((type == 0x00000015 || type == 0x0000000f) && len >= 18) {
13180       n1 = QT_UINT16 ((guint8 *) data->data + 16);
13181       if (n1) {
13182         /* do not add bpm=0 */
13183         GST_DEBUG_OBJECT (qtdemux, "adding tag %d", n1);
13184         gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag1, (gdouble) n1,
13185             NULL);
13186       }
13187     }
13188   }
13189 }
13190
13191 static void
13192 qtdemux_tag_add_uint32 (GstQTDemux * qtdemux, GstTagList * taglist,
13193     const char *tag1, const char *dummy, GNode * node)
13194 {
13195   GNode *data;
13196   int len;
13197   int type;
13198   guint32 num;
13199
13200   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
13201   if (data) {
13202     len = QT_UINT32 (data->data);
13203     type = QT_UINT32 ((guint8 *) data->data + 8);
13204     GST_DEBUG_OBJECT (qtdemux, "have %s tag, type=%d,len=%d", tag1, type, len);
13205     /* some files wrongly have a type 0x0f=15, but it should be 0x15 */
13206     if ((type == 0x00000015 || type == 0x0000000f) && len >= 20) {
13207       num = QT_UINT32 ((guint8 *) data->data + 16);
13208       if (num) {
13209         /* do not add num=0 */
13210         GST_DEBUG_OBJECT (qtdemux, "adding tag %d", num);
13211         gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag1, num, NULL);
13212       }
13213     }
13214   }
13215 }
13216
13217 static void
13218 qtdemux_tag_add_covr (GstQTDemux * qtdemux, GstTagList * taglist,
13219     const char *tag1, const char *dummy, GNode * node)
13220 {
13221   GNode *data;
13222   int len;
13223   int type;
13224   GstSample *sample;
13225
13226   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
13227   if (data) {
13228     len = QT_UINT32 (data->data);
13229     type = QT_UINT32 ((guint8 *) data->data + 8);
13230     GST_DEBUG_OBJECT (qtdemux, "have covr tag, type=%d,len=%d", type, len);
13231     if ((type == 0x0000000d || type == 0x0000000e) && len > 16) {
13232       GstTagImageType image_type;
13233
13234       if (gst_tag_list_get_tag_size (taglist, GST_TAG_IMAGE) == 0)
13235         image_type = GST_TAG_IMAGE_TYPE_FRONT_COVER;
13236       else
13237         image_type = GST_TAG_IMAGE_TYPE_NONE;
13238
13239       if ((sample =
13240               gst_tag_image_data_to_image_sample ((guint8 *) data->data + 16,
13241                   len - 16, image_type))) {
13242         GST_DEBUG_OBJECT (qtdemux, "adding tag size %d", len - 16);
13243         gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag1, sample, NULL);
13244         gst_sample_unref (sample);
13245       }
13246     }
13247   }
13248 }
13249
13250 static void
13251 qtdemux_tag_add_date (GstQTDemux * qtdemux, GstTagList * taglist,
13252     const char *tag, const char *dummy, GNode * node)
13253 {
13254   GNode *data;
13255   GstDateTime *datetime = NULL;
13256   char *s;
13257   int len;
13258   int type;
13259
13260   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
13261   if (data) {
13262     len = QT_UINT32 (data->data);
13263     type = QT_UINT32 ((guint8 *) data->data + 8);
13264     if (type == 0x00000001 && len > 16) {
13265       guint y, m = 1, d = 1;
13266       gint ret;
13267
13268       s = g_strndup ((char *) data->data + 16, len - 16);
13269       GST_DEBUG_OBJECT (qtdemux, "adding date '%s'", s);
13270       datetime = gst_date_time_new_from_iso8601_string (s);
13271       if (datetime != NULL) {
13272         gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, GST_TAG_DATE_TIME,
13273             datetime, NULL);
13274         gst_date_time_unref (datetime);
13275       }
13276
13277       ret = sscanf (s, "%u-%u-%u", &y, &m, &d);
13278       if (ret >= 1 && y > 1500 && y < 3000) {
13279         GDate *date;
13280
13281         date = g_date_new_dmy (d, m, y);
13282         gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag, date, NULL);
13283         g_date_free (date);
13284       } else {
13285         GST_DEBUG_OBJECT (qtdemux, "could not parse date string '%s'", s);
13286       }
13287       g_free (s);
13288     }
13289   }
13290 }
13291
13292 static void
13293 qtdemux_tag_add_gnre (GstQTDemux * qtdemux, GstTagList * taglist,
13294     const char *tag, const char *dummy, GNode * node)
13295 {
13296   GNode *data;
13297
13298   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
13299
13300   /* re-route to normal string tag if major brand says so
13301    * or no data atom and compatible brand suggests so */
13302   if (qtdemux_is_brand_3gp (qtdemux, TRUE) ||
13303       (qtdemux_is_brand_3gp (qtdemux, FALSE) && !data)) {
13304     qtdemux_tag_add_str (qtdemux, taglist, tag, dummy, node);
13305     return;
13306   }
13307
13308   if (data) {
13309     guint len, type, n;
13310
13311     len = QT_UINT32 (data->data);
13312     type = QT_UINT32 ((guint8 *) data->data + 8);
13313     if (type == 0x00000000 && len >= 18) {
13314       n = QT_UINT16 ((guint8 *) data->data + 16);
13315       if (n > 0) {
13316         const gchar *genre;
13317
13318         genre = gst_tag_id3_genre_get (n - 1);
13319         if (genre != NULL) {
13320           GST_DEBUG_OBJECT (qtdemux, "adding %d [%s]", n, genre);
13321           gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag, genre, NULL);
13322         }
13323       }
13324     }
13325   }
13326 }
13327
13328 static void
13329 qtdemux_add_double_tag_from_str (GstQTDemux * demux, GstTagList * taglist,
13330     const gchar * tag, guint8 * data, guint32 datasize)
13331 {
13332   gdouble value;
13333   gchar *datacopy;
13334
13335   /* make a copy to have \0 at the end */
13336   datacopy = g_strndup ((gchar *) data, datasize);
13337
13338   /* convert the str to double */
13339   if (sscanf (datacopy, "%lf", &value) == 1) {
13340     GST_DEBUG_OBJECT (demux, "adding tag: %s [%s]", tag, datacopy);
13341     gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag, value, NULL);
13342   } else {
13343     GST_WARNING_OBJECT (demux, "Failed to parse double from string: %s",
13344         datacopy);
13345   }
13346   g_free (datacopy);
13347 }
13348
13349
13350 static void
13351 qtdemux_tag_add_revdns (GstQTDemux * demux, GstTagList * taglist,
13352     const char *tag, const char *tag_bis, GNode * node)
13353 {
13354   GNode *mean;
13355   GNode *name;
13356   GNode *data;
13357   guint32 meansize;
13358   guint32 namesize;
13359   guint32 datatype;
13360   guint32 datasize;
13361   const gchar *meanstr;
13362   const gchar *namestr;
13363
13364   /* checking the whole ---- atom size for consistency */
13365   if (QT_UINT32 (node->data) <= 4 + 12 + 12 + 16) {
13366     GST_WARNING_OBJECT (demux, "Tag ---- atom is too small, ignoring");
13367     return;
13368   }
13369
13370   mean = qtdemux_tree_get_child_by_type (node, FOURCC_mean);
13371   if (!mean) {
13372     GST_WARNING_OBJECT (demux, "No 'mean' atom found");
13373     return;
13374   }
13375
13376   meansize = QT_UINT32 (mean->data);
13377   if (meansize <= 12) {
13378     GST_WARNING_OBJECT (demux, "Small mean atom, ignoring the whole tag");
13379     return;
13380   }
13381   meanstr = ((gchar *) mean->data) + 12;
13382   meansize -= 12;
13383
13384   name = qtdemux_tree_get_child_by_type (node, FOURCC_name);
13385   if (!name) {
13386     GST_WARNING_OBJECT (demux, "'name' atom not found, ignoring tag");
13387     return;
13388   }
13389
13390   namesize = QT_UINT32 (name->data);
13391   if (namesize <= 12) {
13392     GST_WARNING_OBJECT (demux, "'name' atom is too small, ignoring tag");
13393     return;
13394   }
13395   namestr = ((gchar *) name->data) + 12;
13396   namesize -= 12;
13397
13398   /*
13399    * Data atom is:
13400    * uint32 - size
13401    * uint32 - name
13402    * uint8  - version
13403    * uint24 - data type
13404    * uint32 - all 0
13405    * rest   - the data
13406    */
13407   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
13408   if (!data) {
13409     GST_WARNING_OBJECT (demux, "No data atom in this tag");
13410     return;
13411   }
13412   datasize = QT_UINT32 (data->data);
13413   if (datasize <= 16) {
13414     GST_WARNING_OBJECT (demux, "Data atom too small");
13415     return;
13416   }
13417   datatype = QT_UINT32 (((gchar *) data->data) + 8) & 0xFFFFFF;
13418
13419   if ((strncmp (meanstr, "com.apple.iTunes", meansize) == 0) ||
13420       (strncmp (meanstr, "org.hydrogenaudio.replaygain", meansize) == 0)) {
13421     static const struct
13422     {
13423       const gchar name[28];
13424       const gchar tag[28];
13425     } tags[] = {
13426       {
13427       "replaygain_track_gain", GST_TAG_TRACK_GAIN}, {
13428       "replaygain_track_peak", GST_TAG_TRACK_PEAK}, {
13429       "replaygain_album_gain", GST_TAG_ALBUM_GAIN}, {
13430       "replaygain_album_peak", GST_TAG_ALBUM_PEAK}, {
13431       "MusicBrainz Track Id", GST_TAG_MUSICBRAINZ_TRACKID}, {
13432       "MusicBrainz Artist Id", GST_TAG_MUSICBRAINZ_ARTISTID}, {
13433       "MusicBrainz Album Id", GST_TAG_MUSICBRAINZ_ALBUMID}, {
13434       "MusicBrainz Album Artist Id", GST_TAG_MUSICBRAINZ_ALBUMARTISTID}
13435     };
13436     int i;
13437
13438     for (i = 0; i < G_N_ELEMENTS (tags); ++i) {
13439       if (!g_ascii_strncasecmp (tags[i].name, namestr, namesize)) {
13440         switch (gst_tag_get_type (tags[i].tag)) {
13441           case G_TYPE_DOUBLE:
13442             qtdemux_add_double_tag_from_str (demux, taglist, tags[i].tag,
13443                 ((guint8 *) data->data) + 16, datasize - 16);
13444             break;
13445           case G_TYPE_STRING:
13446             qtdemux_tag_add_str (demux, taglist, tags[i].tag, NULL, node);
13447             break;
13448           default:
13449             /* not reached */
13450             break;
13451         }
13452         break;
13453       }
13454     }
13455     if (i == G_N_ELEMENTS (tags))
13456       goto unknown_tag;
13457   } else {
13458     goto unknown_tag;
13459   }
13460
13461   return;
13462
13463 /* errors */
13464 unknown_tag:
13465 #ifndef GST_DISABLE_GST_DEBUG
13466   {
13467     gchar *namestr_dbg;
13468     gchar *meanstr_dbg;
13469
13470     meanstr_dbg = g_strndup (meanstr, meansize);
13471     namestr_dbg = g_strndup (namestr, namesize);
13472
13473     GST_WARNING_OBJECT (demux, "This tag %s:%s type:%u is not mapped, "
13474         "file a bug at bugzilla.gnome.org", meanstr_dbg, namestr_dbg, datatype);
13475
13476     g_free (namestr_dbg);
13477     g_free (meanstr_dbg);
13478   }
13479 #endif
13480   return;
13481 }
13482
13483 static void
13484 qtdemux_tag_add_id32 (GstQTDemux * demux, GstTagList * taglist, const char *tag,
13485     const char *tag_bis, GNode * node)
13486 {
13487   guint8 *data;
13488   GstBuffer *buf;
13489   guint len;
13490   GstTagList *id32_taglist = NULL;
13491
13492   GST_LOG_OBJECT (demux, "parsing ID32");
13493
13494   data = node->data;
13495   len = GST_READ_UINT32_BE (data);
13496
13497   /* need at least full box and language tag */
13498   if (len < 12 + 2)
13499     return;
13500
13501   buf = gst_buffer_new_allocate (NULL, len - 14, NULL);
13502   gst_buffer_fill (buf, 0, data + 14, len - 14);
13503
13504   id32_taglist = gst_tag_list_from_id3v2_tag (buf);
13505   if (id32_taglist) {
13506     GST_LOG_OBJECT (demux, "parsing ok");
13507     gst_tag_list_insert (taglist, id32_taglist, GST_TAG_MERGE_KEEP);
13508     gst_tag_list_unref (id32_taglist);
13509   } else {
13510     GST_LOG_OBJECT (demux, "parsing failed");
13511   }
13512
13513   gst_buffer_unref (buf);
13514 }
13515
13516 typedef void (*GstQTDemuxAddTagFunc) (GstQTDemux * demux, GstTagList * taglist,
13517     const char *tag, const char *tag_bis, GNode * node);
13518
13519 /* unmapped tags
13520 FOURCC_pcst -> if media is a podcast -> bool
13521 FOURCC_cpil -> if media is part of a compilation -> bool
13522 FOURCC_pgap -> if media is part of a gapless context -> bool
13523 FOURCC_tven -> the tv episode id e.g. S01E23 -> str
13524 */
13525
13526 static const struct
13527 {
13528   guint32 fourcc;
13529   const gchar *gst_tag;
13530   const gchar *gst_tag_bis;
13531   const GstQTDemuxAddTagFunc func;
13532 } add_funcs[] = {
13533   {
13534   FOURCC__nam, GST_TAG_TITLE, NULL, qtdemux_tag_add_str}, {
13535   FOURCC_titl, GST_TAG_TITLE, NULL, qtdemux_tag_add_str}, {
13536   FOURCC__grp, GST_TAG_GROUPING, NULL, qtdemux_tag_add_str}, {
13537   FOURCC__wrt, GST_TAG_COMPOSER, NULL, qtdemux_tag_add_str}, {
13538   FOURCC__ART, GST_TAG_ARTIST, NULL, qtdemux_tag_add_str}, {
13539   FOURCC_aART, GST_TAG_ALBUM_ARTIST, NULL, qtdemux_tag_add_str}, {
13540   FOURCC_perf, GST_TAG_ARTIST, NULL, qtdemux_tag_add_str}, {
13541   FOURCC_auth, GST_TAG_COMPOSER, NULL, qtdemux_tag_add_str}, {
13542   FOURCC__alb, GST_TAG_ALBUM, NULL, qtdemux_tag_add_str}, {
13543   FOURCC_albm, GST_TAG_ALBUM, NULL, qtdemux_tag_add_str}, {
13544   FOURCC_cprt, GST_TAG_COPYRIGHT, NULL, qtdemux_tag_add_str}, {
13545   FOURCC__cpy, GST_TAG_COPYRIGHT, NULL, qtdemux_tag_add_str}, {
13546   FOURCC__cmt, GST_TAG_COMMENT, NULL, qtdemux_tag_add_str}, {
13547   FOURCC__des, GST_TAG_DESCRIPTION, NULL, qtdemux_tag_add_str}, {
13548   FOURCC_desc, GST_TAG_DESCRIPTION, NULL, qtdemux_tag_add_str}, {
13549   FOURCC_dscp, GST_TAG_DESCRIPTION, NULL, qtdemux_tag_add_str}, {
13550   FOURCC__lyr, GST_TAG_LYRICS, NULL, qtdemux_tag_add_str}, {
13551   FOURCC__day, GST_TAG_DATE, NULL, qtdemux_tag_add_date}, {
13552   FOURCC_yrrc, GST_TAG_DATE, NULL, qtdemux_tag_add_year}, {
13553   FOURCC__too, GST_TAG_ENCODER, NULL, qtdemux_tag_add_str}, {
13554   FOURCC__inf, GST_TAG_COMMENT, NULL, qtdemux_tag_add_str}, {
13555   FOURCC_trkn, GST_TAG_TRACK_NUMBER, GST_TAG_TRACK_COUNT, qtdemux_tag_add_num}, {
13556   FOURCC_disk, GST_TAG_ALBUM_VOLUME_NUMBER, GST_TAG_ALBUM_VOLUME_COUNT,
13557         qtdemux_tag_add_num}, {
13558   FOURCC_disc, GST_TAG_ALBUM_VOLUME_NUMBER, GST_TAG_ALBUM_VOLUME_COUNT,
13559         qtdemux_tag_add_num}, {
13560   FOURCC__gen, GST_TAG_GENRE, NULL, qtdemux_tag_add_str}, {
13561   FOURCC_gnre, GST_TAG_GENRE, NULL, qtdemux_tag_add_gnre}, {
13562   FOURCC_tmpo, GST_TAG_BEATS_PER_MINUTE, NULL, qtdemux_tag_add_tmpo}, {
13563   FOURCC_covr, GST_TAG_IMAGE, NULL, qtdemux_tag_add_covr}, {
13564   FOURCC_sonm, GST_TAG_TITLE_SORTNAME, NULL, qtdemux_tag_add_str}, {
13565   FOURCC_soal, GST_TAG_ALBUM_SORTNAME, NULL, qtdemux_tag_add_str}, {
13566   FOURCC_soar, GST_TAG_ARTIST_SORTNAME, NULL, qtdemux_tag_add_str}, {
13567   FOURCC_soaa, GST_TAG_ALBUM_ARTIST_SORTNAME, NULL, qtdemux_tag_add_str}, {
13568   FOURCC_soco, GST_TAG_COMPOSER_SORTNAME, NULL, qtdemux_tag_add_str}, {
13569   FOURCC_sosn, GST_TAG_SHOW_SORTNAME, NULL, qtdemux_tag_add_str}, {
13570   FOURCC_tvsh, GST_TAG_SHOW_NAME, NULL, qtdemux_tag_add_str}, {
13571   FOURCC_tvsn, GST_TAG_SHOW_SEASON_NUMBER, NULL, qtdemux_tag_add_uint32}, {
13572   FOURCC_tves, GST_TAG_SHOW_EPISODE_NUMBER, NULL, qtdemux_tag_add_uint32}, {
13573   FOURCC_kywd, GST_TAG_KEYWORDS, NULL, qtdemux_tag_add_keywords}, {
13574   FOURCC_keyw, GST_TAG_KEYWORDS, NULL, qtdemux_tag_add_str}, {
13575   FOURCC__enc, GST_TAG_ENCODER, NULL, qtdemux_tag_add_str}, {
13576   FOURCC_loci, GST_TAG_GEO_LOCATION_NAME, NULL, qtdemux_tag_add_location}, {
13577   FOURCC_clsf, GST_QT_DEMUX_CLASSIFICATION_TAG, NULL,
13578         qtdemux_tag_add_classification}, {
13579   FOURCC__mak, GST_TAG_DEVICE_MANUFACTURER, NULL, qtdemux_tag_add_str}, {
13580   FOURCC__mod, GST_TAG_DEVICE_MODEL, NULL, qtdemux_tag_add_str}, {
13581   FOURCC__swr, GST_TAG_APPLICATION_NAME, NULL, qtdemux_tag_add_str}, {
13582
13583     /* This is a special case, some tags are stored in this
13584      * 'reverse dns naming', according to:
13585      * http://atomicparsley.sourceforge.net/mpeg-4files.html and
13586      * bug #614471
13587      */
13588   FOURCC_____, "", NULL, qtdemux_tag_add_revdns}, {
13589     /* see http://www.mp4ra.org/specs.html for ID32 in meta box */
13590   FOURCC_ID32, "", NULL, qtdemux_tag_add_id32}
13591 };
13592
13593 struct _GstQtDemuxTagList
13594 {
13595   GstQTDemux *demux;
13596   GstTagList *taglist;
13597 };
13598 typedef struct _GstQtDemuxTagList GstQtDemuxTagList;
13599
13600 static void
13601 qtdemux_tag_add_blob (GNode * node, GstQtDemuxTagList * qtdemuxtaglist)
13602 {
13603   gint len;
13604   guint8 *data;
13605   GstBuffer *buf;
13606   gchar *media_type;
13607   const gchar *style;
13608   GstSample *sample;
13609   GstStructure *s;
13610   guint i;
13611   guint8 ndata[4];
13612   GstQTDemux *demux = qtdemuxtaglist->demux;
13613   GstTagList *taglist = qtdemuxtaglist->taglist;
13614
13615   data = node->data;
13616   len = QT_UINT32 (data);
13617   buf = gst_buffer_new_and_alloc (len);
13618   gst_buffer_fill (buf, 0, data, len);
13619
13620   /* heuristic to determine style of tag */
13621   if (QT_FOURCC (data + 4) == FOURCC_____ ||
13622       (len > 8 + 12 && QT_FOURCC (data + 12) == FOURCC_data))
13623     style = "itunes";
13624   else if (demux->major_brand == FOURCC_qt__)
13625     style = "quicktime";
13626   /* fall back to assuming iso/3gp tag style */
13627   else
13628     style = "iso";
13629
13630   /* santize the name for the caps. */
13631   for (i = 0; i < 4; i++) {
13632     guint8 d = data[4 + i];
13633     if (g_ascii_isalnum (d))
13634       ndata[i] = g_ascii_tolower (d);
13635     else
13636       ndata[i] = '_';
13637   }
13638
13639   media_type = g_strdup_printf ("application/x-gst-qt-%c%c%c%c-tag",
13640       ndata[0], ndata[1], ndata[2], ndata[3]);
13641   GST_DEBUG_OBJECT (demux, "media type %s", media_type);
13642
13643   s = gst_structure_new (media_type, "style", G_TYPE_STRING, style, NULL);
13644   sample = gst_sample_new (buf, NULL, NULL, s);
13645   gst_buffer_unref (buf);
13646   g_free (media_type);
13647
13648   GST_DEBUG_OBJECT (demux, "adding private tag; size %d, info %" GST_PTR_FORMAT,
13649       len, s);
13650
13651   gst_tag_list_add (taglist, GST_TAG_MERGE_APPEND,
13652       GST_QT_DEMUX_PRIVATE_TAG, sample, NULL);
13653
13654   gst_sample_unref (sample);
13655 }
13656
13657 static void
13658 qtdemux_parse_udta (GstQTDemux * qtdemux, GstTagList * taglist, GNode * udta)
13659 {
13660   GNode *meta;
13661   GNode *ilst;
13662   GNode *xmp_;
13663   GNode *node;
13664   gint i;
13665   GstQtDemuxTagList demuxtaglist;
13666
13667   demuxtaglist.demux = qtdemux;
13668   demuxtaglist.taglist = taglist;
13669
13670   meta = qtdemux_tree_get_child_by_type (udta, FOURCC_meta);
13671   if (meta != NULL) {
13672     ilst = qtdemux_tree_get_child_by_type (meta, FOURCC_ilst);
13673     if (ilst == NULL) {
13674       GST_LOG_OBJECT (qtdemux, "no ilst");
13675       return;
13676     }
13677   } else {
13678     ilst = udta;
13679     GST_LOG_OBJECT (qtdemux, "no meta so using udta itself");
13680   }
13681
13682   i = 0;
13683   while (i < G_N_ELEMENTS (add_funcs)) {
13684     node = qtdemux_tree_get_child_by_type (ilst, add_funcs[i].fourcc);
13685     if (node) {
13686       gint len;
13687
13688       len = QT_UINT32 (node->data);
13689       if (len < 12) {
13690         GST_DEBUG_OBJECT (qtdemux, "too small tag atom %" GST_FOURCC_FORMAT,
13691             GST_FOURCC_ARGS (add_funcs[i].fourcc));
13692       } else {
13693         add_funcs[i].func (qtdemux, taglist, add_funcs[i].gst_tag,
13694             add_funcs[i].gst_tag_bis, node);
13695       }
13696       g_node_destroy (node);
13697     } else {
13698       i++;
13699     }
13700   }
13701
13702   /* parsed nodes have been removed, pass along remainder as blob */
13703   g_node_children_foreach (ilst, G_TRAVERSE_ALL,
13704       (GNodeForeachFunc) qtdemux_tag_add_blob, &demuxtaglist);
13705
13706   /* parse up XMP_ node if existing */
13707   xmp_ = qtdemux_tree_get_child_by_type (udta, FOURCC_XMP_);
13708   if (xmp_ != NULL) {
13709     GstBuffer *buf;
13710     GstTagList *xmptaglist;
13711
13712     buf = _gst_buffer_new_wrapped (((guint8 *) xmp_->data) + 8,
13713         QT_UINT32 ((guint8 *) xmp_->data) - 8, NULL);
13714     xmptaglist = gst_tag_list_from_xmp_buffer (buf);
13715     gst_buffer_unref (buf);
13716
13717     qtdemux_handle_xmp_taglist (qtdemux, taglist, xmptaglist);
13718   } else {
13719     GST_DEBUG_OBJECT (qtdemux, "No XMP_ node found");
13720   }
13721 }
13722
13723 typedef struct
13724 {
13725   GstStructure *structure;      /* helper for sort function */
13726   gchar *location;
13727   guint min_req_bitrate;
13728   guint min_req_qt_version;
13729 } GstQtReference;
13730
13731 static gint
13732 qtdemux_redirects_sort_func (gconstpointer a, gconstpointer b)
13733 {
13734   GstQtReference *ref_a = (GstQtReference *) a;
13735   GstQtReference *ref_b = (GstQtReference *) b;
13736
13737   if (ref_b->min_req_qt_version != ref_a->min_req_qt_version)
13738     return ref_b->min_req_qt_version - ref_a->min_req_qt_version;
13739
13740   /* known bitrates go before unknown; higher bitrates go first */
13741   return ref_b->min_req_bitrate - ref_a->min_req_bitrate;
13742 }
13743
13744 /* sort the redirects and post a message for the application.
13745  */
13746 static void
13747 qtdemux_process_redirects (GstQTDemux * qtdemux, GList * references)
13748 {
13749   GstQtReference *best;
13750   GstStructure *s;
13751   GstMessage *msg;
13752   GValue list_val = { 0, };
13753   GList *l;
13754
13755   g_assert (references != NULL);
13756
13757   references = g_list_sort (references, qtdemux_redirects_sort_func);
13758
13759   best = (GstQtReference *) references->data;
13760
13761   g_value_init (&list_val, GST_TYPE_LIST);
13762
13763   for (l = references; l != NULL; l = l->next) {
13764     GstQtReference *ref = (GstQtReference *) l->data;
13765     GValue struct_val = { 0, };
13766
13767     ref->structure = gst_structure_new ("redirect",
13768         "new-location", G_TYPE_STRING, ref->location, NULL);
13769
13770     if (ref->min_req_bitrate > 0) {
13771       gst_structure_set (ref->structure, "minimum-bitrate", G_TYPE_INT,
13772           ref->min_req_bitrate, NULL);
13773     }
13774
13775     g_value_init (&struct_val, GST_TYPE_STRUCTURE);
13776     g_value_set_boxed (&struct_val, ref->structure);
13777     gst_value_list_append_value (&list_val, &struct_val);
13778     g_value_unset (&struct_val);
13779     /* don't free anything here yet, since we need best->structure below */
13780   }
13781
13782   g_assert (best != NULL);
13783   s = gst_structure_copy (best->structure);
13784
13785   if (g_list_length (references) > 1) {
13786     gst_structure_set_value (s, "locations", &list_val);
13787   }
13788
13789   g_value_unset (&list_val);
13790
13791   for (l = references; l != NULL; l = l->next) {
13792     GstQtReference *ref = (GstQtReference *) l->data;
13793
13794     gst_structure_free (ref->structure);
13795     g_free (ref->location);
13796     g_free (ref);
13797   }
13798   g_list_free (references);
13799
13800   GST_INFO_OBJECT (qtdemux, "posting redirect message: %" GST_PTR_FORMAT, s);
13801   msg = gst_message_new_element (GST_OBJECT_CAST (qtdemux), s);
13802   gst_element_post_message (GST_ELEMENT_CAST (qtdemux), msg);
13803   qtdemux->posted_redirect = TRUE;
13804 }
13805
13806 /* look for redirect nodes, collect all redirect information and
13807  * process it.
13808  */
13809 static gboolean
13810 qtdemux_parse_redirects (GstQTDemux * qtdemux)
13811 {
13812   GNode *rmra, *rmda, *rdrf;
13813
13814   rmra = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_rmra);
13815   if (rmra) {
13816     GList *redirects = NULL;
13817
13818     rmda = qtdemux_tree_get_child_by_type (rmra, FOURCC_rmda);
13819     while (rmda) {
13820       GstQtReference ref = { NULL, NULL, 0, 0 };
13821       GNode *rmdr, *rmvc;
13822
13823       if ((rmdr = qtdemux_tree_get_child_by_type (rmda, FOURCC_rmdr))) {
13824         ref.min_req_bitrate = QT_UINT32 ((guint8 *) rmdr->data + 12);
13825         GST_LOG_OBJECT (qtdemux, "data rate atom, required bitrate = %u",
13826             ref.min_req_bitrate);
13827       }
13828
13829       if ((rmvc = qtdemux_tree_get_child_by_type (rmda, FOURCC_rmvc))) {
13830         guint32 package = QT_FOURCC ((guint8 *) rmvc->data + 12);
13831         guint version = QT_UINT32 ((guint8 *) rmvc->data + 16);
13832
13833 #ifndef GST_DISABLE_GST_DEBUG
13834         guint bitmask = QT_UINT32 ((guint8 *) rmvc->data + 20);
13835 #endif
13836         guint check_type = QT_UINT16 ((guint8 *) rmvc->data + 24);
13837
13838         GST_LOG_OBJECT (qtdemux,
13839             "version check atom [%" GST_FOURCC_FORMAT "], version=0x%08x"
13840             ", mask=%08x, check_type=%u", GST_FOURCC_ARGS (package), version,
13841             bitmask, check_type);
13842         if (package == FOURCC_qtim && check_type == 0) {
13843           ref.min_req_qt_version = version;
13844         }
13845       }
13846
13847       rdrf = qtdemux_tree_get_child_by_type (rmda, FOURCC_rdrf);
13848       if (rdrf) {
13849         guint32 ref_type;
13850         guint8 *ref_data;
13851         guint ref_len;
13852
13853         ref_len = QT_UINT32 ((guint8 *) rdrf->data);
13854         if (ref_len > 20) {
13855           ref_type = QT_FOURCC ((guint8 *) rdrf->data + 12);
13856           ref_data = (guint8 *) rdrf->data + 20;
13857           if (ref_type == FOURCC_alis) {
13858             guint record_len, record_version, fn_len;
13859
13860             if (ref_len > 70) {
13861               /* MacOSX alias record, google for alias-layout.txt */
13862               record_len = QT_UINT16 (ref_data + 4);
13863               record_version = QT_UINT16 (ref_data + 4 + 2);
13864               fn_len = QT_UINT8 (ref_data + 50);
13865               if (record_len > 50 && record_version == 2 && fn_len > 0) {
13866                 ref.location = g_strndup ((gchar *) ref_data + 51, fn_len);
13867               }
13868             } else {
13869               GST_WARNING_OBJECT (qtdemux, "Invalid rdrf/alis size (%u < 70)",
13870                   ref_len);
13871             }
13872           } else if (ref_type == FOURCC_url_) {
13873             ref.location = g_strndup ((gchar *) ref_data, ref_len - 8);
13874           } else {
13875             GST_DEBUG_OBJECT (qtdemux,
13876                 "unknown rdrf reference type %" GST_FOURCC_FORMAT,
13877                 GST_FOURCC_ARGS (ref_type));
13878           }
13879           if (ref.location != NULL) {
13880             GST_INFO_OBJECT (qtdemux, "New location: %s", ref.location);
13881             redirects =
13882                 g_list_prepend (redirects, g_memdup (&ref, sizeof (ref)));
13883           } else {
13884             GST_WARNING_OBJECT (qtdemux,
13885                 "Failed to extract redirect location from rdrf atom");
13886           }
13887         } else {
13888           GST_WARNING_OBJECT (qtdemux, "Invalid rdrf size (%u < 20)", ref_len);
13889         }
13890       }
13891
13892       /* look for others */
13893       rmda = qtdemux_tree_get_sibling_by_type (rmda, FOURCC_rmda);
13894     }
13895
13896     if (redirects != NULL) {
13897       qtdemux_process_redirects (qtdemux, redirects);
13898     }
13899   }
13900   return TRUE;
13901 }
13902
13903 static GstTagList *
13904 qtdemux_add_container_format (GstQTDemux * qtdemux, GstTagList * tags)
13905 {
13906   const gchar *fmt;
13907
13908   if (tags == NULL) {
13909     tags = gst_tag_list_new_empty ();
13910     gst_tag_list_set_scope (tags, GST_TAG_SCOPE_GLOBAL);
13911   }
13912
13913   if (qtdemux->major_brand == FOURCC_mjp2)
13914     fmt = "Motion JPEG 2000";
13915   else if ((qtdemux->major_brand & 0xffff) == FOURCC_3g__)
13916     fmt = "3GP";
13917   else if (qtdemux->major_brand == FOURCC_qt__)
13918     fmt = "Quicktime";
13919   else if (qtdemux->fragmented)
13920     fmt = "ISO fMP4";
13921   else
13922     fmt = "ISO MP4/M4A";
13923
13924   GST_LOG_OBJECT (qtdemux, "mapped %" GST_FOURCC_FORMAT " to '%s'",
13925       GST_FOURCC_ARGS (qtdemux->major_brand), fmt);
13926
13927   gst_tag_list_add (tags, GST_TAG_MERGE_REPLACE, GST_TAG_CONTAINER_FORMAT,
13928       fmt, NULL);
13929
13930   return tags;
13931 }
13932
13933 /* we have read the complete moov node now.
13934  * This function parses all of the relevant info, creates the traks and
13935  * prepares all data structures for playback
13936  */
13937 static gboolean
13938 qtdemux_parse_tree (GstQTDemux * qtdemux)
13939 {
13940   GNode *mvhd;
13941   GNode *trak;
13942   GNode *udta;
13943   GNode *mvex;
13944   GNode *pssh;
13945   guint64 creation_time;
13946   GstDateTime *datetime = NULL;
13947   gint version;
13948
13949   /* make sure we have a usable taglist */
13950   qtdemux->tag_list = gst_tag_list_make_writable (qtdemux->tag_list);
13951
13952   mvhd = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_mvhd);
13953   if (mvhd == NULL) {
13954     GST_LOG_OBJECT (qtdemux, "No mvhd node found, looking for redirects.");
13955     return qtdemux_parse_redirects (qtdemux);
13956   }
13957
13958   version = QT_UINT8 ((guint8 *) mvhd->data + 8);
13959   if (version == 1) {
13960     creation_time = QT_UINT64 ((guint8 *) mvhd->data + 12);
13961     qtdemux->timescale = QT_UINT32 ((guint8 *) mvhd->data + 28);
13962     qtdemux->duration = QT_UINT64 ((guint8 *) mvhd->data + 32);
13963   } else if (version == 0) {
13964     creation_time = QT_UINT32 ((guint8 *) mvhd->data + 12);
13965     qtdemux->timescale = QT_UINT32 ((guint8 *) mvhd->data + 20);
13966     qtdemux->duration = QT_UINT32 ((guint8 *) mvhd->data + 24);
13967   } else {
13968     GST_WARNING_OBJECT (qtdemux, "Unhandled mvhd version %d", version);
13969     return FALSE;
13970   }
13971
13972   /* Moving qt creation time (secs since 1904) to unix time */
13973   if (creation_time != 0) {
13974     /* Try to use epoch first as it should be faster and more commonly found */
13975     if (creation_time >= QTDEMUX_SECONDS_FROM_1904_TO_1970) {
13976       GTimeVal now;
13977
13978       creation_time -= QTDEMUX_SECONDS_FROM_1904_TO_1970;
13979       /* some data cleansing sanity */
13980       g_get_current_time (&now);
13981       if (now.tv_sec + 24 * 3600 < creation_time) {
13982         GST_DEBUG_OBJECT (qtdemux, "discarding bogus future creation time");
13983       } else {
13984         datetime = gst_date_time_new_from_unix_epoch_utc (creation_time);
13985       }
13986     } else {
13987       GDateTime *base_dt = g_date_time_new_utc (1904, 1, 1, 0, 0, 0);
13988       GDateTime *dt, *dt_local;
13989
13990       dt = g_date_time_add_seconds (base_dt, creation_time);
13991       dt_local = g_date_time_to_local (dt);
13992       datetime = gst_date_time_new_from_g_date_time (dt_local);
13993
13994       g_date_time_unref (base_dt);
13995       g_date_time_unref (dt);
13996     }
13997   }
13998   if (datetime) {
13999     /* Use KEEP as explicit tags should have a higher priority than mvhd tag */
14000     gst_tag_list_add (qtdemux->tag_list, GST_TAG_MERGE_KEEP, GST_TAG_DATE_TIME,
14001         datetime, NULL);
14002     gst_date_time_unref (datetime);
14003   }
14004
14005   GST_INFO_OBJECT (qtdemux, "timescale: %u", qtdemux->timescale);
14006   GST_INFO_OBJECT (qtdemux, "duration: %" G_GUINT64_FORMAT, qtdemux->duration);
14007
14008   /* check for fragmented file and get some (default) data */
14009   mvex = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_mvex);
14010   if (mvex) {
14011     GNode *mehd;
14012     GstByteReader mehd_data;
14013
14014     /* let track parsing or anyone know weird stuff might happen ... */
14015     qtdemux->fragmented = TRUE;
14016
14017     /* compensate for total duration */
14018     mehd = qtdemux_tree_get_child_by_type_full (mvex, FOURCC_mehd, &mehd_data);
14019     if (mehd)
14020       qtdemux_parse_mehd (qtdemux, &mehd_data);
14021   }
14022
14023   /* Update the movie segment duration, unless it was directly given to us
14024    * by upstream. Otherwise let it as is, as we don't want to mangle the
14025    * duration provided by upstream that may come e.g. from a MPD file. */
14026   if (!qtdemux->upstream_format_is_time) {
14027     GstClockTime duration;
14028     /* set duration in the segment info */
14029     gst_qtdemux_get_duration (qtdemux, &duration);
14030     qtdemux->segment.duration = duration;
14031     /* also do not exceed duration; stop is set that way post seek anyway,
14032      * and segment activation falls back to duration,
14033      * whereas loop only checks stop, so let's align this here as well */
14034     qtdemux->segment.stop = duration;
14035   }
14036
14037   /* parse all traks */
14038   trak = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_trak);
14039   while (trak) {
14040     qtdemux_parse_trak (qtdemux, trak);
14041     /* iterate all siblings */
14042     trak = qtdemux_tree_get_sibling_by_type (trak, FOURCC_trak);
14043   }
14044
14045   qtdemux->tag_list = gst_tag_list_make_writable (qtdemux->tag_list);
14046
14047   /* find tags */
14048   udta = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_udta);
14049   if (udta) {
14050     qtdemux_parse_udta (qtdemux, qtdemux->tag_list, udta);
14051   } else {
14052     GST_LOG_OBJECT (qtdemux, "No udta node found.");
14053   }
14054
14055   /* maybe also some tags in meta box */
14056   udta = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_meta);
14057   if (udta) {
14058     GST_DEBUG_OBJECT (qtdemux, "Parsing meta box for tags.");
14059     qtdemux_parse_udta (qtdemux, qtdemux->tag_list, udta);
14060   } else {
14061     GST_LOG_OBJECT (qtdemux, "No meta node found.");
14062   }
14063
14064   /* parse any protection system info */
14065   pssh = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_pssh);
14066   while (pssh) {
14067     GST_LOG_OBJECT (qtdemux, "Parsing pssh box.");
14068     qtdemux_parse_pssh (qtdemux, pssh);
14069     pssh = qtdemux_tree_get_sibling_by_type (pssh, FOURCC_pssh);
14070   }
14071
14072   qtdemux->tag_list = qtdemux_add_container_format (qtdemux, qtdemux->tag_list);
14073
14074   return TRUE;
14075 }
14076
14077 /* taken from ffmpeg */
14078 static int
14079 read_descr_size (guint8 * ptr, guint8 * end, guint8 ** end_out)
14080 {
14081   int count = 4;
14082   int len = 0;
14083
14084   while (count--) {
14085     int c;
14086
14087     if (ptr >= end)
14088       return -1;
14089
14090     c = *ptr++;
14091     len = (len << 7) | (c & 0x7f);
14092     if (!(c & 0x80))
14093       break;
14094   }
14095   *end_out = ptr;
14096   return len;
14097 }
14098
14099 static GList *
14100 parse_xiph_stream_headers (GstQTDemux * qtdemux, gpointer codec_data,
14101     gsize codec_data_size)
14102 {
14103   GList *list = NULL;
14104   guint8 *p = codec_data;
14105   gint i, offset, num_packets;
14106   guint *length, last;
14107
14108   GST_MEMDUMP_OBJECT (qtdemux, "xiph codec data", codec_data, codec_data_size);
14109
14110   if (codec_data == NULL || codec_data_size == 0)
14111     goto error;
14112
14113   /* start of the stream and vorbis audio or theora video, need to
14114    * send the codec_priv data as first three packets */
14115   num_packets = p[0] + 1;
14116   GST_DEBUG_OBJECT (qtdemux,
14117       "%u stream headers, total length=%" G_GSIZE_FORMAT " bytes",
14118       (guint) num_packets, codec_data_size);
14119
14120   /* Let's put some limits, Don't think there even is a xiph codec
14121    * with more than 3-4 headers */
14122   if (G_UNLIKELY (num_packets > 16)) {
14123     GST_WARNING_OBJECT (qtdemux,
14124         "Unlikely number of xiph headers, most likely not valid");
14125     goto error;
14126   }
14127
14128   length = g_alloca (num_packets * sizeof (guint));
14129   last = 0;
14130   offset = 1;
14131
14132   /* first packets, read length values */
14133   for (i = 0; i < num_packets - 1; i++) {
14134     length[i] = 0;
14135     while (offset < codec_data_size) {
14136       length[i] += p[offset];
14137       if (p[offset++] != 0xff)
14138         break;
14139     }
14140     last += length[i];
14141   }
14142   if (offset + last > codec_data_size)
14143     goto error;
14144
14145   /* last packet is the remaining size */
14146   length[i] = codec_data_size - offset - last;
14147
14148   for (i = 0; i < num_packets; i++) {
14149     GstBuffer *hdr;
14150
14151     GST_DEBUG_OBJECT (qtdemux, "buffer %d: %u bytes", i, (guint) length[i]);
14152
14153     if (offset + length[i] > codec_data_size)
14154       goto error;
14155
14156     hdr = gst_buffer_new_wrapped (g_memdup (p + offset, length[i]), length[i]);
14157     list = g_list_append (list, hdr);
14158
14159     offset += length[i];
14160   }
14161
14162   return list;
14163
14164   /* ERRORS */
14165 error:
14166   {
14167     if (list != NULL)
14168       g_list_free_full (list, (GDestroyNotify) gst_buffer_unref);
14169     return NULL;
14170   }
14171
14172 }
14173
14174 /* this can change the codec originally present in @list */
14175 static void
14176 gst_qtdemux_handle_esds (GstQTDemux * qtdemux, QtDemuxStream * stream,
14177     QtDemuxStreamStsdEntry * entry, GNode * esds, GstTagList * list)
14178 {
14179   int len = QT_UINT32 (esds->data);
14180   guint8 *ptr = esds->data;
14181   guint8 *end = ptr + len;
14182   int tag;
14183   guint8 *data_ptr = NULL;
14184   int data_len = 0;
14185   guint8 object_type_id = 0;
14186   guint8 stream_type = 0;
14187   const char *codec_name = NULL;
14188   GstCaps *caps = NULL;
14189
14190   GST_MEMDUMP_OBJECT (qtdemux, "esds", ptr, len);
14191   ptr += 8;
14192   GST_DEBUG_OBJECT (qtdemux, "version/flags = %08x", QT_UINT32 (ptr));
14193   ptr += 4;
14194   while (ptr + 1 < end) {
14195     tag = QT_UINT8 (ptr);
14196     GST_DEBUG_OBJECT (qtdemux, "tag = %02x", tag);
14197     ptr++;
14198     len = read_descr_size (ptr, end, &ptr);
14199     GST_DEBUG_OBJECT (qtdemux, "len = %d", len);
14200
14201     /* Check the stated amount of data is available for reading */
14202     if (len < 0 || ptr + len > end)
14203       break;
14204
14205     switch (tag) {
14206       case ES_DESCRIPTOR_TAG:
14207         GST_DEBUG_OBJECT (qtdemux, "ID 0x%04x", QT_UINT16 (ptr));
14208         GST_DEBUG_OBJECT (qtdemux, "priority 0x%04x", QT_UINT8 (ptr + 2));
14209         ptr += 3;
14210         break;
14211       case DECODER_CONFIG_DESC_TAG:{
14212         guint max_bitrate, avg_bitrate;
14213
14214         object_type_id = QT_UINT8 (ptr);
14215         stream_type = QT_UINT8 (ptr + 1) >> 2;
14216         max_bitrate = QT_UINT32 (ptr + 5);
14217         avg_bitrate = QT_UINT32 (ptr + 9);
14218         GST_DEBUG_OBJECT (qtdemux, "object_type_id %02x", object_type_id);
14219         GST_DEBUG_OBJECT (qtdemux, "stream_type %02x", stream_type);
14220         GST_DEBUG_OBJECT (qtdemux, "buffer_size_db %02x", QT_UINT24 (ptr + 2));
14221         GST_DEBUG_OBJECT (qtdemux, "max bitrate %u", max_bitrate);
14222         GST_DEBUG_OBJECT (qtdemux, "avg bitrate %u", avg_bitrate);
14223         if (max_bitrate > 0 && max_bitrate < G_MAXUINT32) {
14224           gst_tag_list_add (list, GST_TAG_MERGE_REPLACE,
14225               GST_TAG_MAXIMUM_BITRATE, max_bitrate, NULL);
14226         }
14227         if (avg_bitrate > 0 && avg_bitrate < G_MAXUINT32) {
14228           gst_tag_list_add (list, GST_TAG_MERGE_REPLACE, GST_TAG_BITRATE,
14229               avg_bitrate, NULL);
14230         }
14231         ptr += 13;
14232         break;
14233       }
14234       case DECODER_SPECIFIC_INFO_TAG:
14235         GST_MEMDUMP_OBJECT (qtdemux, "data", ptr, len);
14236         if (object_type_id == 0xe0 && len == 0x40) {
14237           guint8 *data;
14238           GstStructure *s;
14239           guint32 clut[16];
14240           gint i;
14241
14242           GST_DEBUG_OBJECT (qtdemux,
14243               "Have VOBSUB palette. Creating palette event");
14244           /* move to decConfigDescr data and read palette */
14245           data = ptr;
14246           for (i = 0; i < 16; i++) {
14247             clut[i] = QT_UINT32 (data);
14248             data += 4;
14249           }
14250
14251           s = gst_structure_new ("application/x-gst-dvd", "event",
14252               G_TYPE_STRING, "dvd-spu-clut-change",
14253               "clut00", G_TYPE_INT, clut[0], "clut01", G_TYPE_INT, clut[1],
14254               "clut02", G_TYPE_INT, clut[2], "clut03", G_TYPE_INT, clut[3],
14255               "clut04", G_TYPE_INT, clut[4], "clut05", G_TYPE_INT, clut[5],
14256               "clut06", G_TYPE_INT, clut[6], "clut07", G_TYPE_INT, clut[7],
14257               "clut08", G_TYPE_INT, clut[8], "clut09", G_TYPE_INT, clut[9],
14258               "clut10", G_TYPE_INT, clut[10], "clut11", G_TYPE_INT, clut[11],
14259               "clut12", G_TYPE_INT, clut[12], "clut13", G_TYPE_INT, clut[13],
14260               "clut14", G_TYPE_INT, clut[14], "clut15", G_TYPE_INT, clut[15],
14261               NULL);
14262
14263           /* store event and trigger custom processing */
14264           stream->pending_event =
14265               gst_event_new_custom (GST_EVENT_CUSTOM_DOWNSTREAM, s);
14266         } else {
14267           /* Generic codec_data handler puts it on the caps */
14268           data_ptr = ptr;
14269           data_len = len;
14270         }
14271
14272         ptr += len;
14273         break;
14274       case SL_CONFIG_DESC_TAG:
14275         GST_DEBUG_OBJECT (qtdemux, "data %02x", QT_UINT8 (ptr));
14276         ptr += 1;
14277         break;
14278       default:
14279         GST_DEBUG_OBJECT (qtdemux, "Unknown/unhandled descriptor tag %02x",
14280             tag);
14281         GST_MEMDUMP_OBJECT (qtdemux, "descriptor data", ptr, len);
14282         ptr += len;
14283         break;
14284     }
14285   }
14286
14287   /* object_type_id in the esds atom in mp4a and mp4v tells us which codec is
14288    * in use, and should also be used to override some other parameters for some
14289    * codecs. */
14290   switch (object_type_id) {
14291     case 0x20:                 /* MPEG-4 */
14292       /* 4 bytes for the visual_object_sequence_start_code and 1 byte for the
14293        * profile_and_level_indication */
14294       if (data_ptr != NULL && data_len >= 5 &&
14295           GST_READ_UINT32_BE (data_ptr) == 0x000001b0) {
14296         gst_codec_utils_mpeg4video_caps_set_level_and_profile (entry->caps,
14297             data_ptr + 4, data_len - 4);
14298       }
14299       break;                    /* Nothing special needed here */
14300     case 0x21:                 /* H.264 */
14301       codec_name = "H.264 / AVC";
14302       caps = gst_caps_new_simple ("video/x-h264",
14303           "stream-format", G_TYPE_STRING, "avc",
14304           "alignment", G_TYPE_STRING, "au", NULL);
14305       break;
14306     case 0x40:                 /* AAC (any) */
14307     case 0x66:                 /* AAC Main */
14308     case 0x67:                 /* AAC LC */
14309     case 0x68:                 /* AAC SSR */
14310       /* Override channels and rate based on the codec_data, as it's often
14311        * wrong. */
14312       /* Only do so for basic setup without HE-AAC extension */
14313       if (data_ptr && data_len == 2) {
14314         guint channels, rate;
14315
14316         channels = gst_codec_utils_aac_get_channels (data_ptr, data_len);
14317         if (channels > 0)
14318           entry->n_channels = channels;
14319
14320         rate = gst_codec_utils_aac_get_sample_rate (data_ptr, data_len);
14321         if (rate > 0)
14322           entry->rate = rate;
14323       }
14324
14325       /* Set level and profile if possible */
14326       if (data_ptr != NULL && data_len >= 2) {
14327         gst_codec_utils_aac_caps_set_level_and_profile (entry->caps,
14328             data_ptr, data_len);
14329       } else {
14330         const gchar *profile_str = NULL;
14331         GstBuffer *buffer;
14332         GstMapInfo map;
14333         guint8 *codec_data;
14334         gint rate_idx, profile;
14335
14336         /* No codec_data, let's invent something.
14337          * FIXME: This is wrong for SBR! */
14338
14339         GST_WARNING_OBJECT (qtdemux, "No codec_data for AAC available");
14340
14341         buffer = gst_buffer_new_and_alloc (2);
14342         gst_buffer_map (buffer, &map, GST_MAP_WRITE);
14343         codec_data = map.data;
14344
14345         rate_idx =
14346             gst_codec_utils_aac_get_index_from_sample_rate (CUR_STREAM
14347             (stream)->rate);
14348
14349         switch (object_type_id) {
14350           case 0x66:
14351             profile_str = "main";
14352             profile = 0;
14353             break;
14354           case 0x67:
14355             profile_str = "lc";
14356             profile = 1;
14357             break;
14358           case 0x68:
14359             profile_str = "ssr";
14360             profile = 2;
14361             break;
14362           default:
14363             profile = 3;
14364             break;
14365         }
14366
14367         codec_data[0] = ((profile + 1) << 3) | ((rate_idx & 0xE) >> 1);
14368         codec_data[1] =
14369             ((rate_idx & 0x1) << 7) | (CUR_STREAM (stream)->n_channels << 3);
14370
14371         gst_buffer_unmap (buffer, &map);
14372         gst_caps_set_simple (CUR_STREAM (stream)->caps, "codec_data",
14373             GST_TYPE_BUFFER, buffer, NULL);
14374         gst_buffer_unref (buffer);
14375
14376         if (profile_str) {
14377           gst_caps_set_simple (CUR_STREAM (stream)->caps, "profile",
14378               G_TYPE_STRING, profile_str, NULL);
14379         }
14380       }
14381       break;
14382     case 0x60:                 /* MPEG-2, various profiles */
14383     case 0x61:
14384     case 0x62:
14385     case 0x63:
14386     case 0x64:
14387     case 0x65:
14388       codec_name = "MPEG-2 video";
14389       caps = gst_caps_new_simple ("video/mpeg",
14390           "mpegversion", G_TYPE_INT, 2,
14391           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
14392       break;
14393     case 0x69:                 /* MPEG-2 BC audio */
14394     case 0x6B:                 /* MPEG-1 audio */
14395       caps = gst_caps_new_simple ("audio/mpeg",
14396           "mpegversion", G_TYPE_INT, 1, NULL);
14397       codec_name = "MPEG-1 audio";
14398       break;
14399     case 0x6A:                 /* MPEG-1 */
14400       codec_name = "MPEG-1 video";
14401       caps = gst_caps_new_simple ("video/mpeg",
14402           "mpegversion", G_TYPE_INT, 1,
14403           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
14404       break;
14405     case 0x6C:                 /* MJPEG */
14406       caps =
14407           gst_caps_new_simple ("image/jpeg", "parsed", G_TYPE_BOOLEAN, TRUE,
14408           NULL);
14409       codec_name = "Motion-JPEG";
14410       break;
14411     case 0x6D:                 /* PNG */
14412       caps =
14413           gst_caps_new_simple ("image/png", "parsed", G_TYPE_BOOLEAN, TRUE,
14414           NULL);
14415       codec_name = "PNG still images";
14416       break;
14417     case 0x6E:                 /* JPEG2000 */
14418       codec_name = "JPEG-2000";
14419       caps = gst_caps_new_simple ("image/x-j2c", "fields", G_TYPE_INT, 1, NULL);
14420       break;
14421     case 0xA4:                 /* Dirac */
14422       codec_name = "Dirac";
14423       caps = gst_caps_new_empty_simple ("video/x-dirac");
14424       break;
14425     case 0xA5:                 /* AC3 */
14426       codec_name = "AC-3 audio";
14427       caps = gst_caps_new_simple ("audio/x-ac3",
14428           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
14429       break;
14430     case 0xA9:                 /* AC3 */
14431       codec_name = "DTS audio";
14432       caps = gst_caps_new_simple ("audio/x-dts",
14433           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
14434       break;
14435     case 0xDD:
14436       if (stream_type == 0x05 && data_ptr) {
14437         GList *headers =
14438             parse_xiph_stream_headers (qtdemux, data_ptr, data_len);
14439         if (headers) {
14440           GList *tmp;
14441           GValue arr_val = G_VALUE_INIT;
14442           GValue buf_val = G_VALUE_INIT;
14443           GstStructure *s;
14444
14445           /* Let's assume it's vorbis if it's an audio stream of type 0xdd and we have codec data that extracts properly */
14446           codec_name = "Vorbis";
14447           caps = gst_caps_new_empty_simple ("audio/x-vorbis");
14448           g_value_init (&arr_val, GST_TYPE_ARRAY);
14449           g_value_init (&buf_val, GST_TYPE_BUFFER);
14450           for (tmp = headers; tmp; tmp = tmp->next) {
14451             g_value_set_boxed (&buf_val, (GstBuffer *) tmp->data);
14452             gst_value_array_append_value (&arr_val, &buf_val);
14453           }
14454           s = gst_caps_get_structure (caps, 0);
14455           gst_structure_take_value (s, "streamheader", &arr_val);
14456           g_value_unset (&buf_val);
14457           g_list_free (headers);
14458
14459           data_ptr = NULL;
14460           data_len = 0;
14461         }
14462       }
14463       break;
14464     case 0xE1:                 /* QCELP */
14465       /* QCELP, the codec_data is a riff tag (little endian) with
14466        * 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). */
14467       caps = gst_caps_new_empty_simple ("audio/qcelp");
14468       codec_name = "QCELP";
14469       break;
14470     default:
14471       break;
14472   }
14473
14474   /* If we have a replacement caps, then change our caps for this stream */
14475   if (caps) {
14476     gst_caps_unref (entry->caps);
14477     entry->caps = caps;
14478   }
14479
14480   if (codec_name && list)
14481     gst_tag_list_add (list, GST_TAG_MERGE_REPLACE,
14482         GST_TAG_AUDIO_CODEC, codec_name, NULL);
14483
14484   /* Add the codec_data attribute to caps, if we have it */
14485   if (data_ptr) {
14486     GstBuffer *buffer;
14487
14488     buffer = gst_buffer_new_and_alloc (data_len);
14489     gst_buffer_fill (buffer, 0, data_ptr, data_len);
14490
14491     GST_DEBUG_OBJECT (qtdemux, "setting codec_data from esds");
14492     GST_MEMDUMP_OBJECT (qtdemux, "codec_data from esds", data_ptr, data_len);
14493
14494     gst_caps_set_simple (entry->caps, "codec_data", GST_TYPE_BUFFER,
14495         buffer, NULL);
14496     gst_buffer_unref (buffer);
14497   }
14498
14499 }
14500
14501 static inline GstCaps *
14502 _get_unknown_codec_name (const gchar * type, guint32 fourcc)
14503 {
14504   GstCaps *caps;
14505   guint i;
14506   char *s, fourstr[5];
14507
14508   g_snprintf (fourstr, 5, "%" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (fourcc));
14509   for (i = 0; i < 4; i++) {
14510     if (!g_ascii_isalnum (fourstr[i]))
14511       fourstr[i] = '_';
14512   }
14513   s = g_strdup_printf ("%s/x-gst-fourcc-%s", type, g_strstrip (fourstr));
14514   caps = gst_caps_new_empty_simple (s);
14515   g_free (s);
14516   return caps;
14517 }
14518
14519 #define _codec(name) \
14520   do { \
14521     if (codec_name) { \
14522       *codec_name = g_strdup (name); \
14523     } \
14524   } while (0)
14525
14526 static GstCaps *
14527 qtdemux_video_caps (GstQTDemux * qtdemux, QtDemuxStream * stream,
14528     QtDemuxStreamStsdEntry * entry, guint32 fourcc,
14529     const guint8 * stsd_entry_data, gchar ** codec_name)
14530 {
14531   GstCaps *caps = NULL;
14532   GstVideoFormat format = GST_VIDEO_FORMAT_UNKNOWN;
14533
14534   switch (fourcc) {
14535     case FOURCC_png:
14536       _codec ("PNG still images");
14537       caps = gst_caps_new_empty_simple ("image/png");
14538       break;
14539     case FOURCC_jpeg:
14540       _codec ("JPEG still images");
14541       caps =
14542           gst_caps_new_simple ("image/jpeg", "parsed", G_TYPE_BOOLEAN, TRUE,
14543           NULL);
14544       break;
14545     case GST_MAKE_FOURCC ('m', 'j', 'p', 'a'):
14546     case GST_MAKE_FOURCC ('A', 'V', 'D', 'J'):
14547     case GST_MAKE_FOURCC ('M', 'J', 'P', 'G'):
14548     case GST_MAKE_FOURCC ('d', 'm', 'b', '1'):
14549       _codec ("Motion-JPEG");
14550       caps =
14551           gst_caps_new_simple ("image/jpeg", "parsed", G_TYPE_BOOLEAN, TRUE,
14552           NULL);
14553       break;
14554     case GST_MAKE_FOURCC ('m', 'j', 'p', 'b'):
14555       _codec ("Motion-JPEG format B");
14556       caps = gst_caps_new_empty_simple ("video/x-mjpeg-b");
14557       break;
14558     case FOURCC_mjp2:
14559       _codec ("JPEG-2000");
14560       /* override to what it should be according to spec, avoid palette_data */
14561       entry->bits_per_sample = 24;
14562       caps = gst_caps_new_simple ("image/x-j2c", "fields", G_TYPE_INT, 1, NULL);
14563       break;
14564     case FOURCC_SVQ3:
14565       _codec ("Sorensen video v.3");
14566       caps = gst_caps_new_simple ("video/x-svq",
14567           "svqversion", G_TYPE_INT, 3, NULL);
14568       break;
14569     case GST_MAKE_FOURCC ('s', 'v', 'q', 'i'):
14570     case GST_MAKE_FOURCC ('S', 'V', 'Q', '1'):
14571       _codec ("Sorensen video v.1");
14572       caps = gst_caps_new_simple ("video/x-svq",
14573           "svqversion", G_TYPE_INT, 1, NULL);
14574       break;
14575     case GST_MAKE_FOURCC ('W', 'R', 'A', 'W'):
14576       caps = gst_caps_new_empty_simple ("video/x-raw");
14577       gst_caps_set_simple (caps, "format", G_TYPE_STRING, "RGB8P", NULL);
14578       _codec ("Windows Raw RGB");
14579       stream->alignment = 32;
14580       break;
14581     case FOURCC_raw_:
14582     {
14583       guint16 bps;
14584
14585       bps = QT_UINT16 (stsd_entry_data + 82);
14586       switch (bps) {
14587         case 15:
14588           format = GST_VIDEO_FORMAT_RGB15;
14589           break;
14590         case 16:
14591           format = GST_VIDEO_FORMAT_RGB16;
14592           break;
14593         case 24:
14594           format = GST_VIDEO_FORMAT_RGB;
14595           break;
14596         case 32:
14597           format = GST_VIDEO_FORMAT_ARGB;
14598           break;
14599         default:
14600           /* unknown */
14601           break;
14602       }
14603       break;
14604     }
14605     case GST_MAKE_FOURCC ('y', 'v', '1', '2'):
14606       format = GST_VIDEO_FORMAT_I420;
14607       break;
14608     case GST_MAKE_FOURCC ('y', 'u', 'v', '2'):
14609     case GST_MAKE_FOURCC ('Y', 'u', 'v', '2'):
14610       format = GST_VIDEO_FORMAT_I420;
14611       break;
14612     case FOURCC_2vuy:
14613     case GST_MAKE_FOURCC ('2', 'V', 'u', 'y'):
14614       format = GST_VIDEO_FORMAT_UYVY;
14615       break;
14616     case GST_MAKE_FOURCC ('v', '3', '0', '8'):
14617       format = GST_VIDEO_FORMAT_v308;
14618       break;
14619     case GST_MAKE_FOURCC ('v', '2', '1', '6'):
14620       format = GST_VIDEO_FORMAT_v216;
14621       break;
14622     case FOURCC_v210:
14623       format = GST_VIDEO_FORMAT_v210;
14624       break;
14625     case GST_MAKE_FOURCC ('r', '2', '1', '0'):
14626       format = GST_VIDEO_FORMAT_r210;
14627       break;
14628       /* Packed YUV 4:4:4 10 bit in 32 bits, complex
14629          case GST_MAKE_FOURCC ('v', '4', '1', '0'):
14630          format = GST_VIDEO_FORMAT_v410;
14631          break;
14632        */
14633       /* Packed YUV 4:4:4:4 8 bit in 32 bits
14634        * but different order than AYUV
14635        case GST_MAKE_FOURCC ('v', '4', '0', '8'):
14636        format = GST_VIDEO_FORMAT_v408;
14637        break;
14638        */
14639     case GST_MAKE_FOURCC ('m', 'p', 'e', 'g'):
14640     case GST_MAKE_FOURCC ('m', 'p', 'g', '1'):
14641       _codec ("MPEG-1 video");
14642       caps = gst_caps_new_simple ("video/mpeg", "mpegversion", G_TYPE_INT, 1,
14643           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
14644       break;
14645     case GST_MAKE_FOURCC ('h', 'd', 'v', '1'): /* HDV 720p30 */
14646     case GST_MAKE_FOURCC ('h', 'd', 'v', '2'): /* HDV 1080i60 */
14647     case GST_MAKE_FOURCC ('h', 'd', 'v', '3'): /* HDV 1080i50 */
14648     case GST_MAKE_FOURCC ('h', 'd', 'v', '4'): /* HDV 720p24 */
14649     case GST_MAKE_FOURCC ('h', 'd', 'v', '5'): /* HDV 720p25 */
14650     case GST_MAKE_FOURCC ('h', 'd', 'v', '6'): /* HDV 1080p24 */
14651     case GST_MAKE_FOURCC ('h', 'd', 'v', '7'): /* HDV 1080p25 */
14652     case GST_MAKE_FOURCC ('h', 'd', 'v', '8'): /* HDV 1080p30 */
14653     case GST_MAKE_FOURCC ('h', 'd', 'v', '9'): /* HDV 720p60 */
14654     case GST_MAKE_FOURCC ('h', 'd', 'v', 'a'): /* HDV 720p50 */
14655     case GST_MAKE_FOURCC ('m', 'x', '5', 'n'): /* MPEG2 IMX NTSC 525/60 50mb/s produced by FCP */
14656     case GST_MAKE_FOURCC ('m', 'x', '5', 'p'): /* MPEG2 IMX PAL 625/60 50mb/s produced by FCP */
14657     case GST_MAKE_FOURCC ('m', 'x', '4', 'n'): /* MPEG2 IMX NTSC 525/60 40mb/s produced by FCP */
14658     case GST_MAKE_FOURCC ('m', 'x', '4', 'p'): /* MPEG2 IMX PAL 625/60 40mb/s produced by FCP */
14659     case GST_MAKE_FOURCC ('m', 'x', '3', 'n'): /* MPEG2 IMX NTSC 525/60 30mb/s produced by FCP */
14660     case GST_MAKE_FOURCC ('m', 'x', '3', 'p'): /* MPEG2 IMX PAL 625/50 30mb/s produced by FCP */
14661     case GST_MAKE_FOURCC ('x', 'd', 'v', '1'): /* XDCAM HD 720p30 35Mb/s */
14662     case GST_MAKE_FOURCC ('x', 'd', 'v', '2'): /* XDCAM HD 1080i60 35Mb/s */
14663     case GST_MAKE_FOURCC ('x', 'd', 'v', '3'): /* XDCAM HD 1080i50 35Mb/s */
14664     case GST_MAKE_FOURCC ('x', 'd', 'v', '4'): /* XDCAM HD 720p24 35Mb/s */
14665     case GST_MAKE_FOURCC ('x', 'd', 'v', '5'): /* XDCAM HD 720p25 35Mb/s */
14666     case GST_MAKE_FOURCC ('x', 'd', 'v', '6'): /* XDCAM HD 1080p24 35Mb/s */
14667     case GST_MAKE_FOURCC ('x', 'd', 'v', '7'): /* XDCAM HD 1080p25 35Mb/s */
14668     case GST_MAKE_FOURCC ('x', 'd', 'v', '8'): /* XDCAM HD 1080p30 35Mb/s */
14669     case GST_MAKE_FOURCC ('x', 'd', 'v', '9'): /* XDCAM HD 720p60 35Mb/s */
14670     case GST_MAKE_FOURCC ('x', 'd', 'v', 'a'): /* XDCAM HD 720p50 35Mb/s */
14671     case GST_MAKE_FOURCC ('x', 'd', 'v', 'b'): /* XDCAM EX 1080i60 50Mb/s CBR */
14672     case GST_MAKE_FOURCC ('x', 'd', 'v', 'c'): /* XDCAM EX 1080i50 50Mb/s CBR */
14673     case GST_MAKE_FOURCC ('x', 'd', 'v', 'd'): /* XDCAM HD 1080p24 50Mb/s CBR */
14674     case GST_MAKE_FOURCC ('x', 'd', 'v', 'e'): /* XDCAM HD 1080p25 50Mb/s CBR */
14675     case GST_MAKE_FOURCC ('x', 'd', 'v', 'f'): /* XDCAM HD 1080p30 50Mb/s CBR */
14676     case GST_MAKE_FOURCC ('x', 'd', '5', '1'): /* XDCAM HD422 720p30 50Mb/s CBR */
14677     case GST_MAKE_FOURCC ('x', 'd', '5', '4'): /* XDCAM HD422 720p24 50Mb/s CBR */
14678     case GST_MAKE_FOURCC ('x', 'd', '5', '5'): /* XDCAM HD422 720p25 50Mb/s CBR */
14679     case GST_MAKE_FOURCC ('x', 'd', '5', '9'): /* XDCAM HD422 720p60 50Mb/s CBR */
14680     case GST_MAKE_FOURCC ('x', 'd', '5', 'a'): /* XDCAM HD422 720p50 50Mb/s CBR */
14681     case GST_MAKE_FOURCC ('x', 'd', '5', 'b'): /* XDCAM HD422 1080i50 50Mb/s CBR */
14682     case GST_MAKE_FOURCC ('x', 'd', '5', 'c'): /* XDCAM HD422 1080i50 50Mb/s CBR */
14683     case GST_MAKE_FOURCC ('x', 'd', '5', 'd'): /* XDCAM HD422 1080p24 50Mb/s CBR */
14684     case GST_MAKE_FOURCC ('x', 'd', '5', 'e'): /* XDCAM HD422 1080p25 50Mb/s CBR */
14685     case GST_MAKE_FOURCC ('x', 'd', '5', 'f'): /* XDCAM HD422 1080p30 50Mb/s CBR */
14686     case GST_MAKE_FOURCC ('x', 'd', 'h', 'd'): /* XDCAM HD 540p */
14687     case GST_MAKE_FOURCC ('x', 'd', 'h', '2'): /* XDCAM HD422 540p */
14688     case GST_MAKE_FOURCC ('A', 'V', 'm', 'p'): /* AVID IMX PAL */
14689     case GST_MAKE_FOURCC ('m', 'p', 'g', '2'): /* AVID IMX PAL */
14690     case GST_MAKE_FOURCC ('m', 'p', '2', 'v'): /* AVID IMX PAL */
14691     case GST_MAKE_FOURCC ('m', '2', 'v', '1'):
14692       _codec ("MPEG-2 video");
14693       caps = gst_caps_new_simple ("video/mpeg", "mpegversion", G_TYPE_INT, 2,
14694           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
14695       break;
14696     case GST_MAKE_FOURCC ('g', 'i', 'f', ' '):
14697       _codec ("GIF still images");
14698       caps = gst_caps_new_empty_simple ("image/gif");
14699       break;
14700     case FOURCC_h263:
14701     case GST_MAKE_FOURCC ('H', '2', '6', '3'):
14702     case FOURCC_s263:
14703     case GST_MAKE_FOURCC ('U', '2', '6', '3'):
14704       _codec ("H.263");
14705       /* ffmpeg uses the height/width props, don't know why */
14706       caps = gst_caps_new_simple ("video/x-h263",
14707           "variant", G_TYPE_STRING, "itu", NULL);
14708       break;
14709     case FOURCC_mp4v:
14710     case FOURCC_MP4V:
14711       _codec ("MPEG-4 video");
14712       caps = gst_caps_new_simple ("video/mpeg", "mpegversion", G_TYPE_INT, 4,
14713           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
14714       break;
14715     case GST_MAKE_FOURCC ('3', 'i', 'v', 'd'):
14716     case GST_MAKE_FOURCC ('3', 'I', 'V', 'D'):
14717       _codec ("Microsoft MPEG-4 4.3");  /* FIXME? */
14718       caps = gst_caps_new_simple ("video/x-msmpeg",
14719           "msmpegversion", G_TYPE_INT, 43, NULL);
14720       break;
14721     case GST_MAKE_FOURCC ('D', 'I', 'V', '3'):
14722       _codec ("DivX 3");
14723       caps = gst_caps_new_simple ("video/x-divx",
14724           "divxversion", G_TYPE_INT, 3, NULL);
14725       break;
14726     case GST_MAKE_FOURCC ('D', 'I', 'V', 'X'):
14727     case GST_MAKE_FOURCC ('d', 'i', 'v', 'x'):
14728       _codec ("DivX 4");
14729       caps = gst_caps_new_simple ("video/x-divx",
14730           "divxversion", G_TYPE_INT, 4, NULL);
14731       break;
14732     case GST_MAKE_FOURCC ('D', 'X', '5', '0'):
14733       _codec ("DivX 5");
14734       caps = gst_caps_new_simple ("video/x-divx",
14735           "divxversion", G_TYPE_INT, 5, NULL);
14736       break;
14737
14738     case GST_MAKE_FOURCC ('F', 'F', 'V', '1'):
14739       _codec ("FFV1");
14740       caps = gst_caps_new_simple ("video/x-ffv",
14741           "ffvversion", G_TYPE_INT, 1, NULL);
14742       break;
14743
14744     case GST_MAKE_FOURCC ('3', 'I', 'V', '1'):
14745     case GST_MAKE_FOURCC ('3', 'I', 'V', '2'):
14746     case FOURCC_XVID:
14747     case FOURCC_xvid:
14748     case FOURCC_FMP4:
14749     case FOURCC_fmp4:
14750     case GST_MAKE_FOURCC ('U', 'M', 'P', '4'):
14751       caps = gst_caps_new_simple ("video/mpeg", "mpegversion", G_TYPE_INT, 4,
14752           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
14753       _codec ("MPEG-4");
14754       break;
14755
14756     case GST_MAKE_FOURCC ('c', 'v', 'i', 'd'):
14757       _codec ("Cinepak");
14758       caps = gst_caps_new_empty_simple ("video/x-cinepak");
14759       break;
14760     case GST_MAKE_FOURCC ('q', 'd', 'r', 'w'):
14761       _codec ("Apple QuickDraw");
14762       caps = gst_caps_new_empty_simple ("video/x-qdrw");
14763       break;
14764     case GST_MAKE_FOURCC ('r', 'p', 'z', 'a'):
14765       _codec ("Apple video");
14766       caps = gst_caps_new_empty_simple ("video/x-apple-video");
14767       break;
14768     case FOURCC_H264:
14769     case FOURCC_avc1:
14770       _codec ("H.264 / AVC");
14771       caps = gst_caps_new_simple ("video/x-h264",
14772           "stream-format", G_TYPE_STRING, "avc",
14773           "alignment", G_TYPE_STRING, "au", NULL);
14774       break;
14775     case FOURCC_avc3:
14776       _codec ("H.264 / AVC");
14777       caps = gst_caps_new_simple ("video/x-h264",
14778           "stream-format", G_TYPE_STRING, "avc3",
14779           "alignment", G_TYPE_STRING, "au", NULL);
14780       break;
14781     case FOURCC_H265:
14782     case FOURCC_hvc1:
14783       _codec ("H.265 / HEVC");
14784       caps = gst_caps_new_simple ("video/x-h265",
14785           "stream-format", G_TYPE_STRING, "hvc1",
14786           "alignment", G_TYPE_STRING, "au", NULL);
14787       break;
14788     case FOURCC_hev1:
14789       _codec ("H.265 / HEVC");
14790       caps = gst_caps_new_simple ("video/x-h265",
14791           "stream-format", G_TYPE_STRING, "hev1",
14792           "alignment", G_TYPE_STRING, "au", NULL);
14793       break;
14794     case FOURCC_rle_:
14795       _codec ("Run-length encoding");
14796       caps = gst_caps_new_simple ("video/x-rle",
14797           "layout", G_TYPE_STRING, "quicktime", NULL);
14798       break;
14799     case FOURCC_WRLE:
14800       _codec ("Run-length encoding");
14801       caps = gst_caps_new_simple ("video/x-rle",
14802           "layout", G_TYPE_STRING, "microsoft", NULL);
14803       break;
14804     case GST_MAKE_FOURCC ('I', 'V', '3', '2'):
14805     case GST_MAKE_FOURCC ('i', 'v', '3', '2'):
14806       _codec ("Indeo Video 3");
14807       caps = gst_caps_new_simple ("video/x-indeo",
14808           "indeoversion", G_TYPE_INT, 3, NULL);
14809       break;
14810     case GST_MAKE_FOURCC ('I', 'V', '4', '1'):
14811     case GST_MAKE_FOURCC ('i', 'v', '4', '1'):
14812       _codec ("Intel Video 4");
14813       caps = gst_caps_new_simple ("video/x-indeo",
14814           "indeoversion", G_TYPE_INT, 4, NULL);
14815       break;
14816     case FOURCC_dvcp:
14817     case FOURCC_dvc_:
14818     case GST_MAKE_FOURCC ('d', 'v', 's', 'd'):
14819     case GST_MAKE_FOURCC ('D', 'V', 'S', 'D'):
14820     case GST_MAKE_FOURCC ('d', 'v', 'c', 's'):
14821     case GST_MAKE_FOURCC ('D', 'V', 'C', 'S'):
14822     case GST_MAKE_FOURCC ('d', 'v', '2', '5'):
14823     case GST_MAKE_FOURCC ('d', 'v', 'p', 'p'):
14824       _codec ("DV Video");
14825       caps = gst_caps_new_simple ("video/x-dv", "dvversion", G_TYPE_INT, 25,
14826           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
14827       break;
14828     case FOURCC_dv5n:          /* DVCPRO50 NTSC */
14829     case FOURCC_dv5p:          /* DVCPRO50 PAL */
14830       _codec ("DVCPro50 Video");
14831       caps = gst_caps_new_simple ("video/x-dv", "dvversion", G_TYPE_INT, 50,
14832           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
14833       break;
14834     case GST_MAKE_FOURCC ('d', 'v', 'h', '5'): /* DVCPRO HD 50i produced by FCP */
14835     case GST_MAKE_FOURCC ('d', 'v', 'h', '6'): /* DVCPRO HD 60i produced by FCP */
14836       _codec ("DVCProHD Video");
14837       caps = gst_caps_new_simple ("video/x-dv", "dvversion", G_TYPE_INT, 100,
14838           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
14839       break;
14840     case GST_MAKE_FOURCC ('s', 'm', 'c', ' '):
14841       _codec ("Apple Graphics (SMC)");
14842       caps = gst_caps_new_empty_simple ("video/x-smc");
14843       break;
14844     case GST_MAKE_FOURCC ('V', 'P', '3', '1'):
14845       _codec ("VP3");
14846       caps = gst_caps_new_empty_simple ("video/x-vp3");
14847       break;
14848     case GST_MAKE_FOURCC ('V', 'P', '6', 'F'):
14849       _codec ("VP6 Flash");
14850       caps = gst_caps_new_empty_simple ("video/x-vp6-flash");
14851       break;
14852     case FOURCC_XiTh:
14853       _codec ("Theora");
14854       caps = gst_caps_new_empty_simple ("video/x-theora");
14855       /* theora uses one byte of padding in the data stream because it does not
14856        * allow 0 sized packets while theora does */
14857       entry->padding = 1;
14858       break;
14859     case FOURCC_drac:
14860       _codec ("Dirac");
14861       caps = gst_caps_new_empty_simple ("video/x-dirac");
14862       break;
14863     case GST_MAKE_FOURCC ('t', 'i', 'f', 'f'):
14864       _codec ("TIFF still images");
14865       caps = gst_caps_new_empty_simple ("image/tiff");
14866       break;
14867     case GST_MAKE_FOURCC ('i', 'c', 'o', 'd'):
14868       _codec ("Apple Intermediate Codec");
14869       caps = gst_caps_from_string ("video/x-apple-intermediate-codec");
14870       break;
14871     case GST_MAKE_FOURCC ('A', 'V', 'd', 'n'):
14872       _codec ("AVID DNxHD");
14873       caps = gst_caps_from_string ("video/x-dnxhd");
14874       break;
14875     case FOURCC_VP80:
14876     case FOURCC_vp08:
14877       _codec ("On2 VP8");
14878       caps = gst_caps_from_string ("video/x-vp8");
14879       break;
14880     case FOURCC_vp09:
14881       _codec ("Google VP9");
14882       caps = gst_caps_from_string ("video/x-vp9");
14883       break;
14884     case FOURCC_apcs:
14885       _codec ("Apple ProRes LT");
14886       caps =
14887           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING, "lt",
14888           NULL);
14889       break;
14890     case FOURCC_apch:
14891       _codec ("Apple ProRes HQ");
14892       caps =
14893           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING, "hq",
14894           NULL);
14895       break;
14896     case FOURCC_apcn:
14897       _codec ("Apple ProRes");
14898       caps =
14899           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING,
14900           "standard", NULL);
14901       break;
14902     case FOURCC_apco:
14903       _codec ("Apple ProRes Proxy");
14904       caps =
14905           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING,
14906           "proxy", NULL);
14907       break;
14908     case FOURCC_ap4h:
14909       _codec ("Apple ProRes 4444");
14910       caps =
14911           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING,
14912           "4444", NULL);
14913       break;
14914     case FOURCC_ap4x:
14915       _codec ("Apple ProRes 4444 XQ");
14916       caps =
14917           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING,
14918           "4444xq", NULL);
14919       break;
14920     case FOURCC_cfhd:
14921       _codec ("GoPro CineForm");
14922       caps = gst_caps_from_string ("video/x-cineform");
14923       break;
14924     case FOURCC_vc_1:
14925     case FOURCC_ovc1:
14926       _codec ("VC-1");
14927       caps = gst_caps_new_simple ("video/x-wmv",
14928           "wmvversion", G_TYPE_INT, 3, "format", G_TYPE_STRING, "WVC1", NULL);
14929       break;
14930     case FOURCC_av01:
14931       _codec ("AV1");
14932       caps = gst_caps_new_empty_simple ("video/x-av1");
14933       break;
14934     case GST_MAKE_FOURCC ('k', 'p', 'c', 'd'):
14935     default:
14936     {
14937       caps = _get_unknown_codec_name ("video", fourcc);
14938       break;
14939     }
14940   }
14941
14942   if (format != GST_VIDEO_FORMAT_UNKNOWN) {
14943     GstVideoInfo info;
14944
14945     gst_video_info_init (&info);
14946     gst_video_info_set_format (&info, format, entry->width, entry->height);
14947
14948     caps = gst_video_info_to_caps (&info);
14949     *codec_name = gst_pb_utils_get_codec_description (caps);
14950
14951     /* enable clipping for raw video streams */
14952     stream->need_clip = TRUE;
14953     stream->alignment = 32;
14954   }
14955
14956   return caps;
14957 }
14958
14959 static guint
14960 round_up_pow2 (guint n)
14961 {
14962   n = n - 1;
14963   n = n | (n >> 1);
14964   n = n | (n >> 2);
14965   n = n | (n >> 4);
14966   n = n | (n >> 8);
14967   n = n | (n >> 16);
14968   return n + 1;
14969 }
14970
14971 static GstCaps *
14972 qtdemux_audio_caps (GstQTDemux * qtdemux, QtDemuxStream * stream,
14973     QtDemuxStreamStsdEntry * entry, guint32 fourcc, const guint8 * data,
14974     int len, gchar ** codec_name)
14975 {
14976   GstCaps *caps;
14977   const GstStructure *s;
14978   const gchar *name;
14979   gint endian = 0;
14980   GstAudioFormat format = 0;
14981   gint depth;
14982
14983   GST_DEBUG_OBJECT (qtdemux, "resolve fourcc 0x%08x", GUINT32_TO_BE (fourcc));
14984
14985   depth = entry->bytes_per_packet * 8;
14986
14987   switch (fourcc) {
14988     case GST_MAKE_FOURCC ('N', 'O', 'N', 'E'):
14989     case FOURCC_raw_:
14990       /* 8-bit audio is unsigned */
14991       if (depth == 8)
14992         format = GST_AUDIO_FORMAT_U8;
14993       /* otherwise it's signed and big-endian just like 'twos' */
14994     case FOURCC_twos:
14995       endian = G_BIG_ENDIAN;
14996       /* fall-through */
14997     case FOURCC_sowt:
14998     {
14999       gchar *str;
15000
15001       if (!endian)
15002         endian = G_LITTLE_ENDIAN;
15003
15004       if (!format)
15005         format = gst_audio_format_build_integer (TRUE, endian, depth, depth);
15006
15007       str = g_strdup_printf ("Raw %d-bit PCM audio", depth);
15008       _codec (str);
15009       g_free (str);
15010
15011       caps = gst_caps_new_simple ("audio/x-raw",
15012           "format", G_TYPE_STRING, gst_audio_format_to_string (format),
15013           "layout", G_TYPE_STRING, "interleaved", NULL);
15014       stream->alignment = GST_ROUND_UP_8 (depth);
15015       stream->alignment = round_up_pow2 (stream->alignment);
15016       break;
15017     }
15018     case GST_MAKE_FOURCC ('f', 'l', '6', '4'):
15019       _codec ("Raw 64-bit floating-point audio");
15020       caps = gst_caps_new_simple ("audio/x-raw",
15021           "format", G_TYPE_STRING, "F64BE",
15022           "layout", G_TYPE_STRING, "interleaved", NULL);
15023       stream->alignment = 8;
15024       break;
15025     case GST_MAKE_FOURCC ('f', 'l', '3', '2'):
15026       _codec ("Raw 32-bit floating-point audio");
15027       caps = gst_caps_new_simple ("audio/x-raw",
15028           "format", G_TYPE_STRING, "F32BE",
15029           "layout", G_TYPE_STRING, "interleaved", NULL);
15030       stream->alignment = 4;
15031       break;
15032     case FOURCC_in24:
15033       _codec ("Raw 24-bit PCM audio");
15034       /* we assume BIG ENDIAN, an enda box will tell us to change this to little
15035        * endian later */
15036       caps = gst_caps_new_simple ("audio/x-raw",
15037           "format", G_TYPE_STRING, "S24BE",
15038           "layout", G_TYPE_STRING, "interleaved", NULL);
15039       stream->alignment = 4;
15040       break;
15041     case GST_MAKE_FOURCC ('i', 'n', '3', '2'):
15042       _codec ("Raw 32-bit PCM audio");
15043       caps = gst_caps_new_simple ("audio/x-raw",
15044           "format", G_TYPE_STRING, "S32BE",
15045           "layout", G_TYPE_STRING, "interleaved", NULL);
15046       stream->alignment = 4;
15047       break;
15048     case GST_MAKE_FOURCC ('s', '1', '6', 'l'):
15049       _codec ("Raw 16-bit PCM audio");
15050       caps = gst_caps_new_simple ("audio/x-raw",
15051           "format", G_TYPE_STRING, "S16LE",
15052           "layout", G_TYPE_STRING, "interleaved", NULL);
15053       stream->alignment = 2;
15054       break;
15055     case FOURCC_ulaw:
15056       _codec ("Mu-law audio");
15057       caps = gst_caps_new_empty_simple ("audio/x-mulaw");
15058       break;
15059     case FOURCC_alaw:
15060       _codec ("A-law audio");
15061       caps = gst_caps_new_empty_simple ("audio/x-alaw");
15062       break;
15063     case 0x0200736d:
15064     case 0x6d730002:
15065       _codec ("Microsoft ADPCM");
15066       /* Microsoft ADPCM-ACM code 2 */
15067       caps = gst_caps_new_simple ("audio/x-adpcm",
15068           "layout", G_TYPE_STRING, "microsoft", NULL);
15069       break;
15070     case 0x1100736d:
15071     case 0x6d730011:
15072       _codec ("DVI/IMA ADPCM");
15073       caps = gst_caps_new_simple ("audio/x-adpcm",
15074           "layout", G_TYPE_STRING, "dvi", NULL);
15075       break;
15076     case 0x1700736d:
15077     case 0x6d730017:
15078       _codec ("DVI/Intel IMA ADPCM");
15079       /* FIXME DVI/Intel IMA ADPCM/ACM code 17 */
15080       caps = gst_caps_new_simple ("audio/x-adpcm",
15081           "layout", G_TYPE_STRING, "quicktime", NULL);
15082       break;
15083     case 0x5500736d:
15084     case 0x6d730055:
15085       /* MPEG layer 3, CBR only (pre QT4.1) */
15086     case FOURCC__mp3:
15087       _codec ("MPEG-1 layer 3");
15088       /* MPEG layer 3, CBR & VBR (QT4.1 and later) */
15089       caps = gst_caps_new_simple ("audio/mpeg", "layer", G_TYPE_INT, 3,
15090           "mpegversion", G_TYPE_INT, 1, NULL);
15091       break;
15092     case GST_MAKE_FOURCC ('.', 'm', 'p', '2'):
15093       _codec ("MPEG-1 layer 2");
15094       /* MPEG layer 2 */
15095       caps = gst_caps_new_simple ("audio/mpeg", "layer", G_TYPE_INT, 2,
15096           "mpegversion", G_TYPE_INT, 1, NULL);
15097       break;
15098     case 0x20736d:
15099     case GST_MAKE_FOURCC ('e', 'c', '-', '3'):
15100       _codec ("EAC-3 audio");
15101       caps = gst_caps_new_simple ("audio/x-eac3",
15102           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
15103       entry->sampled = TRUE;
15104       break;
15105     case GST_MAKE_FOURCC ('s', 'a', 'c', '3'): // Nero Recode
15106     case FOURCC_ac_3:
15107       _codec ("AC-3 audio");
15108       caps = gst_caps_new_simple ("audio/x-ac3",
15109           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
15110       entry->sampled = TRUE;
15111       break;
15112     case GST_MAKE_FOURCC ('d', 't', 's', 'c'):
15113     case GST_MAKE_FOURCC ('D', 'T', 'S', ' '):
15114       _codec ("DTS audio");
15115       caps = gst_caps_new_simple ("audio/x-dts",
15116           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
15117       entry->sampled = TRUE;
15118       break;
15119     case GST_MAKE_FOURCC ('d', 't', 's', 'h'): // DTS-HD
15120     case GST_MAKE_FOURCC ('d', 't', 's', 'l'): // DTS-HD Lossless
15121       _codec ("DTS-HD audio");
15122       caps = gst_caps_new_simple ("audio/x-dts",
15123           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
15124       entry->sampled = TRUE;
15125       break;
15126     case FOURCC_MAC3:
15127       _codec ("MACE-3");
15128       caps = gst_caps_new_simple ("audio/x-mace",
15129           "maceversion", G_TYPE_INT, 3, NULL);
15130       break;
15131     case FOURCC_MAC6:
15132       _codec ("MACE-6");
15133       caps = gst_caps_new_simple ("audio/x-mace",
15134           "maceversion", G_TYPE_INT, 6, NULL);
15135       break;
15136     case GST_MAKE_FOURCC ('O', 'g', 'g', 'V'):
15137       /* ogg/vorbis */
15138       caps = gst_caps_new_empty_simple ("application/ogg");
15139       break;
15140     case GST_MAKE_FOURCC ('d', 'v', 'c', 'a'):
15141       _codec ("DV audio");
15142       caps = gst_caps_new_empty_simple ("audio/x-dv");
15143       break;
15144     case FOURCC_mp4a:
15145       _codec ("MPEG-4 AAC audio");
15146       caps = gst_caps_new_simple ("audio/mpeg",
15147           "mpegversion", G_TYPE_INT, 4, "framed", G_TYPE_BOOLEAN, TRUE,
15148           "stream-format", G_TYPE_STRING, "raw", NULL);
15149       break;
15150     case GST_MAKE_FOURCC ('Q', 'D', 'M', 'C'):
15151       _codec ("QDesign Music");
15152       caps = gst_caps_new_empty_simple ("audio/x-qdm");
15153       break;
15154     case FOURCC_QDM2:
15155       _codec ("QDesign Music v.2");
15156       /* FIXME: QDesign music version 2 (no constant) */
15157       if (FALSE && data) {
15158         caps = gst_caps_new_simple ("audio/x-qdm2",
15159             "framesize", G_TYPE_INT, QT_UINT32 (data + 52),
15160             "bitrate", G_TYPE_INT, QT_UINT32 (data + 40),
15161             "blocksize", G_TYPE_INT, QT_UINT32 (data + 44), NULL);
15162       } else {
15163         caps = gst_caps_new_empty_simple ("audio/x-qdm2");
15164       }
15165       break;
15166     case FOURCC_agsm:
15167       _codec ("GSM audio");
15168       caps = gst_caps_new_empty_simple ("audio/x-gsm");
15169       break;
15170     case FOURCC_samr:
15171       _codec ("AMR audio");
15172       caps = gst_caps_new_empty_simple ("audio/AMR");
15173       break;
15174     case FOURCC_sawb:
15175       _codec ("AMR-WB audio");
15176       caps = gst_caps_new_empty_simple ("audio/AMR-WB");
15177       break;
15178     case FOURCC_ima4:
15179       _codec ("Quicktime IMA ADPCM");
15180       caps = gst_caps_new_simple ("audio/x-adpcm",
15181           "layout", G_TYPE_STRING, "quicktime", NULL);
15182       break;
15183     case FOURCC_alac:
15184       _codec ("Apple lossless audio");
15185       caps = gst_caps_new_empty_simple ("audio/x-alac");
15186       break;
15187     case FOURCC_fLaC:
15188       _codec ("Free Lossless Audio Codec");
15189       caps = gst_caps_new_simple ("audio/x-flac",
15190           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
15191       break;
15192     case GST_MAKE_FOURCC ('Q', 'c', 'l', 'p'):
15193       _codec ("QualComm PureVoice");
15194       caps = gst_caps_from_string ("audio/qcelp");
15195       break;
15196     case FOURCC_wma_:
15197     case FOURCC_owma:
15198       _codec ("WMA");
15199       caps = gst_caps_new_empty_simple ("audio/x-wma");
15200       break;
15201     case FOURCC_opus:
15202       _codec ("Opus");
15203       caps = gst_caps_new_empty_simple ("audio/x-opus");
15204       break;
15205     case FOURCC_lpcm:
15206     {
15207       guint32 flags = 0;
15208       guint32 depth = 0;
15209       guint32 width = 0;
15210       GstAudioFormat format;
15211       enum
15212       {
15213         FLAG_IS_FLOAT = 0x1,
15214         FLAG_IS_BIG_ENDIAN = 0x2,
15215         FLAG_IS_SIGNED = 0x4,
15216         FLAG_IS_PACKED = 0x8,
15217         FLAG_IS_ALIGNED_HIGH = 0x10,
15218         FLAG_IS_NON_INTERLEAVED = 0x20
15219       };
15220       _codec ("Raw LPCM audio");
15221
15222       if (data && len >= 36) {
15223         depth = QT_UINT32 (data + 24);
15224         flags = QT_UINT32 (data + 28);
15225         width = QT_UINT32 (data + 32) * 8 / entry->n_channels;
15226       }
15227       if ((flags & FLAG_IS_FLOAT) == 0) {
15228         if (depth == 0)
15229           depth = 16;
15230         if (width == 0)
15231           width = 16;
15232         if ((flags & FLAG_IS_ALIGNED_HIGH))
15233           depth = width;
15234
15235         format = gst_audio_format_build_integer ((flags & FLAG_IS_SIGNED) ?
15236             TRUE : FALSE, (flags & FLAG_IS_BIG_ENDIAN) ?
15237             G_BIG_ENDIAN : G_LITTLE_ENDIAN, width, depth);
15238         caps = gst_caps_new_simple ("audio/x-raw",
15239             "format", G_TYPE_STRING,
15240             format !=
15241             GST_AUDIO_FORMAT_UNKNOWN ? gst_audio_format_to_string (format) :
15242             "UNKNOWN", "layout", G_TYPE_STRING,
15243             (flags & FLAG_IS_NON_INTERLEAVED) ? "non-interleaved" :
15244             "interleaved", NULL);
15245         stream->alignment = GST_ROUND_UP_8 (depth);
15246         stream->alignment = round_up_pow2 (stream->alignment);
15247       } else {
15248         if (width == 0)
15249           width = 32;
15250         if (width == 64) {
15251           if (flags & FLAG_IS_BIG_ENDIAN)
15252             format = GST_AUDIO_FORMAT_F64BE;
15253           else
15254             format = GST_AUDIO_FORMAT_F64LE;
15255         } else {
15256           if (flags & FLAG_IS_BIG_ENDIAN)
15257             format = GST_AUDIO_FORMAT_F32BE;
15258           else
15259             format = GST_AUDIO_FORMAT_F32LE;
15260         }
15261         caps = gst_caps_new_simple ("audio/x-raw",
15262             "format", G_TYPE_STRING, gst_audio_format_to_string (format),
15263             "layout", G_TYPE_STRING, (flags & FLAG_IS_NON_INTERLEAVED) ?
15264             "non-interleaved" : "interleaved", NULL);
15265         stream->alignment = width / 8;
15266       }
15267       break;
15268     }
15269     case GST_MAKE_FOURCC ('q', 't', 'v', 'r'):
15270       /* ? */
15271     default:
15272     {
15273       caps = _get_unknown_codec_name ("audio", fourcc);
15274       break;
15275     }
15276   }
15277
15278   if (caps) {
15279     GstCaps *templ_caps =
15280         gst_static_pad_template_get_caps (&gst_qtdemux_audiosrc_template);
15281     GstCaps *intersection = gst_caps_intersect (caps, templ_caps);
15282     gst_caps_unref (caps);
15283     gst_caps_unref (templ_caps);
15284     caps = intersection;
15285   }
15286
15287   /* enable clipping for raw audio streams */
15288   s = gst_caps_get_structure (caps, 0);
15289   name = gst_structure_get_name (s);
15290   if (g_str_has_prefix (name, "audio/x-raw")) {
15291     stream->need_clip = TRUE;
15292     stream->max_buffer_size = 4096 * entry->bytes_per_frame;
15293     GST_DEBUG ("setting max buffer size to %d", stream->max_buffer_size);
15294   }
15295   return caps;
15296 }
15297
15298 static GstCaps *
15299 qtdemux_sub_caps (GstQTDemux * qtdemux, QtDemuxStream * stream,
15300     QtDemuxStreamStsdEntry * entry, guint32 fourcc,
15301     const guint8 * stsd_entry_data, gchar ** codec_name)
15302 {
15303   GstCaps *caps;
15304
15305   GST_DEBUG_OBJECT (qtdemux, "resolve fourcc 0x%08x", GUINT32_TO_BE (fourcc));
15306
15307   switch (fourcc) {
15308     case FOURCC_mp4s:
15309       _codec ("DVD subtitle");
15310       caps = gst_caps_new_empty_simple ("subpicture/x-dvd");
15311       stream->need_process = TRUE;
15312       break;
15313     case FOURCC_text:
15314       _codec ("Quicktime timed text");
15315       goto text;
15316     case FOURCC_tx3g:
15317       _codec ("3GPP timed text");
15318     text:
15319       caps = gst_caps_new_simple ("text/x-raw", "format", G_TYPE_STRING,
15320           "utf8", NULL);
15321       /* actual text piece needs to be extracted */
15322       stream->need_process = TRUE;
15323       break;
15324     case FOURCC_stpp:
15325       _codec ("XML subtitles");
15326       caps = gst_caps_new_empty_simple ("application/ttml+xml");
15327       break;
15328     case FOURCC_c608:
15329       _codec ("CEA 608 Closed Caption");
15330       caps =
15331           gst_caps_new_simple ("closedcaption/x-cea-608", "format",
15332           G_TYPE_STRING, "cc_data", NULL);
15333       stream->need_process = TRUE;
15334       break;
15335     case FOURCC_c708:
15336       _codec ("CEA 708 Closed Caption");
15337       caps =
15338           gst_caps_new_simple ("closedcaption/x-cea-708", "format",
15339           G_TYPE_STRING, "cdp", NULL);
15340       stream->need_process = TRUE;
15341       break;
15342
15343     default:
15344     {
15345       caps = _get_unknown_codec_name ("text", fourcc);
15346       break;
15347     }
15348   }
15349   return caps;
15350 }
15351
15352 static GstCaps *
15353 qtdemux_generic_caps (GstQTDemux * qtdemux, QtDemuxStream * stream,
15354     QtDemuxStreamStsdEntry * entry, guint32 fourcc,
15355     const guint8 * stsd_entry_data, gchar ** codec_name)
15356 {
15357   GstCaps *caps;
15358
15359   switch (fourcc) {
15360     case FOURCC_m1v:
15361       _codec ("MPEG 1 video");
15362       caps = gst_caps_new_simple ("video/mpeg", "mpegversion", G_TYPE_INT, 1,
15363           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
15364       break;
15365     default:
15366       caps = NULL;
15367       break;
15368   }
15369   return caps;
15370 }
15371
15372 static void
15373 gst_qtdemux_append_protection_system_id (GstQTDemux * qtdemux,
15374     const gchar * system_id)
15375 {
15376   gint i;
15377
15378   if (!qtdemux->protection_system_ids)
15379     qtdemux->protection_system_ids =
15380         g_ptr_array_new_with_free_func ((GDestroyNotify) g_free);
15381   /* Check whether we already have an entry for this system ID. */
15382   for (i = 0; i < qtdemux->protection_system_ids->len; ++i) {
15383     const gchar *id = g_ptr_array_index (qtdemux->protection_system_ids, i);
15384     if (g_ascii_strcasecmp (system_id, id) == 0) {
15385       return;
15386     }
15387   }
15388   GST_DEBUG_OBJECT (qtdemux, "Adding cenc protection system ID %s", system_id);
15389   g_ptr_array_add (qtdemux->protection_system_ids, g_ascii_strdown (system_id,
15390           -1));
15391 }