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 #ifdef GSTREAMER_LITE
  87 // relaxing the limitation since some long files has more than 50Mb sample index
  88 #define QTDEMUX_MAX_SAMPLE_INDEX_SIZE (500*1024*1024)
  89 #else
  90 #define QTDEMUX_MAX_SAMPLE_INDEX_SIZE (200*1024*1024)
  91 #endif // GSTREAMER_LITE
  92 
  93 /* For converting qt creation times to unix epoch times */
  94 #define QTDEMUX_SECONDS_PER_DAY (60 * 60 * 24)
  95 #define QTDEMUX_LEAP_YEARS_FROM_1904_TO_1970 17
  96 #define QTDEMUX_SECONDS_FROM_1904_TO_1970 (((1970 - 1904) * (guint64) 365 + \
  97     QTDEMUX_LEAP_YEARS_FROM_1904_TO_1970) * QTDEMUX_SECONDS_PER_DAY)
  98 
  99 #define QTDEMUX_TREE_NODE_FOURCC(n) (QT_FOURCC(((guint8 *) (n)->data) + 4))
 100 
 101 #define STREAM_IS_EOS(s) (s->time_position == GST_CLOCK_TIME_NONE)
 102 
 103 #define ABSDIFF(x, y) ( (x) > (y) ? ((x) - (y)) : ((y) - (x)) )
 104 
 105 GST_DEBUG_CATEGORY (qtdemux_debug);
 106 #define GST_CAT_DEFAULT qtdemux_debug
 107 
 108 typedef struct _QtDemuxSegment QtDemuxSegment;
 109 typedef struct _QtDemuxSample QtDemuxSample;
 110 
 111 typedef struct _QtDemuxCencSampleSetInfo QtDemuxCencSampleSetInfo;
 112 
 113 struct _QtDemuxSample
 114 {
 115   guint32 size;
 116   gint32 pts_offset;            /* Add this value to timestamp to get the pts */
 117   guint64 offset;
 118   guint64 timestamp;            /* DTS In mov time */
 119   guint32 duration;             /* In mov time */
 120   gboolean keyframe;            /* TRUE when this packet is a keyframe */
 121 };
 122 
 123 /* Macros for converting to/from timescale */
 124 #define QTSTREAMTIME_TO_GSTTIME(stream, value) (gst_util_uint64_scale((value), GST_SECOND, (stream)->timescale))
 125 #define GSTTIME_TO_QTSTREAMTIME(stream, value) (gst_util_uint64_scale((value), (stream)->timescale, GST_SECOND))
 126 
 127 #define QTTIME_TO_GSTTIME(qtdemux, value) (gst_util_uint64_scale((value), GST_SECOND, (qtdemux)->timescale))
 128 #define GSTTIME_TO_QTTIME(qtdemux, value) (gst_util_uint64_scale((value), (qtdemux)->timescale, GST_SECOND))
 129 
 130 /* timestamp is the DTS */
 131 #define QTSAMPLE_DTS(stream,sample) (QTSTREAMTIME_TO_GSTTIME((stream), (sample)->timestamp))
 132 /* timestamp + offset + cslg_shift is the outgoing PTS */
 133 #define QTSAMPLE_PTS(stream,sample) (QTSTREAMTIME_TO_GSTTIME((stream), (sample)->timestamp + (stream)->cslg_shift + (sample)->pts_offset))
 134 /* timestamp + offset is the PTS used for internal seek calcuations */
 135 #define QTSAMPLE_PTS_NO_CSLG(stream,sample) (QTSTREAMTIME_TO_GSTTIME((stream), (sample)->timestamp + (sample)->pts_offset))
 136 /* timestamp + duration - dts is the duration */
 137 #define QTSAMPLE_DUR_DTS(stream, sample, dts) (QTSTREAMTIME_TO_GSTTIME ((stream), (sample)->timestamp + (sample)->duration) - (dts))
 138 
 139 #define QTSAMPLE_KEYFRAME(stream,sample) ((stream)->all_keyframe || (sample)->keyframe)
 140 
 141 /*
 142  * Quicktime has tracks and segments. A track is a continuous piece of
 143  * multimedia content. The track is not always played from start to finish but
 144  * instead, pieces of the track are 'cut out' and played in sequence. This is
 145  * what the segments do.
 146  *
 147  * Inside the track we have keyframes (K) and delta frames. The track has its
 148  * own timing, which starts from 0 and extends to end. The position in the track
 149  * is called the media_time.
 150  *
 151  * The segments now describe the pieces that should be played from this track
 152  * and are basically tuples of media_time/duration/rate entries. We can have
 153  * multiple segments and they are all played after one another. An example:
 154  *
 155  * segment 1: media_time: 1 second, duration: 1 second, rate 1
 156  * segment 2: media_time: 3 second, duration: 2 second, rate 2
 157  *
 158  * To correctly play back this track, one must play: 1 second of media starting
 159  * from media_time 1 followed by 2 seconds of media starting from media_time 3
 160  * at a rate of 2.
 161  *
 162  * Each of the segments will be played at a specific time, the first segment at
 163  * time 0, the second one after the duration of the first one, etc.. Note that
 164  * the time in resulting playback is not identical to the media_time of the
 165  * track anymore.
 166  *
 167  * Visually, assuming the track has 4 second of media_time:
 168  *
 169  *                (a)                   (b)          (c)              (d)
 170  *         .-----------------------------------------------------------.
 171  * track:  | K.....K.........K........K.......K.......K...........K... |
 172  *         '-----------------------------------------------------------'
 173  *         0              1              2              3              4
 174  *           .------------^              ^   .----------^              ^
 175  *          /              .-------------'  /       .------------------'
 176  *         /              /          .-----'       /
 177  *         .--------------.         .--------------.
 178  *         | segment 1    |         | segment 2    |
 179  *         '--------------'         '--------------'
 180  *
 181  * The challenge here is to cut out the right pieces of the track for each of
 182  * the playback segments. This fortunately can easily be done with the SEGMENT
 183  * events of GStreamer.
 184  *
 185  * For playback of segment 1, we need to provide the decoder with the keyframe
 186  * (a), in the above figure, but we must instruct it only to output the decoded
 187  * data between second 1 and 2. We do this with a SEGMENT event for 1 to 2, time
 188  * position set to the time of the segment: 0.
 189  *
 190  * We then proceed to push data from keyframe (a) to frame (b). The decoder
 191  * decodes but clips all before media_time 1.
 192  *
 193  * After finishing a segment, we push out a new SEGMENT event with the clipping
 194  * boundaries of the new data.
 195  *
 196  * This is a good usecase for the GStreamer accumulated SEGMENT events.
 197  */
 198 
 199 struct _QtDemuxSegment
 200 {
 201   /* global time and duration, all gst time */
 202   GstClockTime time;
 203   GstClockTime stop_time;
 204   GstClockTime duration;
 205   /* media time of trak, all gst time */
 206   GstClockTime media_start;
 207   GstClockTime media_stop;
 208   gdouble rate;
 209   /* Media start time in trak timescale units */
 210   guint32 trak_media_start;
 211 };
 212 
 213 #define QTSEGMENT_IS_EMPTY(s) ((s)->media_start == GST_CLOCK_TIME_NONE)
 214 
 215 /* Used with fragmented MP4 files (mfra atom) */
 216 typedef struct
 217 {
 218   GstClockTime ts;
 219   guint64 moof_offset;
 220 } QtDemuxRandomAccessEntry;
 221 
 222 typedef struct _QtDemuxStreamStsdEntry
 223 {
 224   GstCaps *caps;
 225   guint32 fourcc;
 226   gboolean sparse;
 227 
 228   /* video info */
 229   gint width;
 230   gint height;
 231   gint par_w;
 232   gint par_h;
 233   /* Numerator/denominator framerate */
 234   gint fps_n;
 235   gint fps_d;
 236   GstVideoColorimetry colorimetry;
 237   guint16 bits_per_sample;
 238   guint16 color_table_id;
 239   GstMemory *rgb8_palette;
 240   guint interlace_mode;
 241   guint field_order;
 242 
 243   /* audio info */
 244   gdouble rate;
 245   gint n_channels;
 246   guint samples_per_packet;
 247   guint samples_per_frame;
 248   guint bytes_per_packet;
 249   guint bytes_per_sample;
 250   guint bytes_per_frame;
 251   guint compression;
 252 
 253   /* if we use chunks or samples */
 254   gboolean sampled;
 255   guint padding;
 256 
 257 } QtDemuxStreamStsdEntry;
 258 
 259 #define CUR_STREAM(s) (&((s)->stsd_entries[(s)->cur_stsd_entry_index]))
 260 
 261 struct _QtDemuxStream
 262 {
 263   GstPad *pad;
 264 
 265   QtDemuxStreamStsdEntry *stsd_entries;
 266   guint stsd_entries_length;
 267   guint cur_stsd_entry_index;
 268 
 269   /* stream type */
 270   guint32 subtype;
 271 
 272   gboolean new_caps;            /* If TRUE, caps need to be generated (by
 273                                  * calling _configure_stream()) This happens
 274                                  * for MSS and fragmented streams */
 275 
 276   gboolean new_stream;          /* signals that a stream_start is required */
 277   gboolean on_keyframe;         /* if this stream last pushed buffer was a
 278                                  * keyframe. This is important to identify
 279                                  * where to stop pushing buffers after a
 280                                  * segment stop time */
 281 
 282   /* if the stream has a redirect URI in its headers, we store it here */
 283   gchar *redirect_uri;
 284 
 285   /* track id */
 286   guint track_id;
 287 #ifdef GSTREAMER_LITE
 288   gboolean track_enabled;
 289 #endif // GSTREAMER_LITE
 290 
 291   /* duration/scale */
 292   guint64 duration;             /* in timescale units */
 293   guint32 timescale;
 294 
 295   /* language */
 296   gchar lang_id[4];             /* ISO 639-2T language code */
 297 
 298   /* our samples */
 299   guint32 n_samples;
 300   QtDemuxSample *samples;
 301   gboolean all_keyframe;        /* TRUE when all samples are keyframes (no stss) */
 302   guint32 first_duration;       /* duration in timescale of first sample, used for figuring out
 303                                    the framerate */
 304   guint32 n_samples_moof;       /* sample count in a moof */
 305   guint64 duration_moof;        /* duration in timescale of a moof, used for figure out
 306                                  * the framerate of fragmented format stream */
 307   guint64 duration_last_moof;
 308 
 309   guint32 offset_in_sample;     /* Offset in the current sample, used for
 310                                  * streams which have got exceedingly big
 311                                  * sample size (such as 24s of raw audio).
 312                                  * Only used when max_buffer_size is non-NULL */
 313   guint32 max_buffer_size;      /* Maximum allowed size for output buffers.
 314                                  * Currently only set for raw audio streams*/
 315 
 316   /* video info */
 317   /* aspect ratio */
 318   gint display_width;
 319   gint display_height;
 320 
 321   /* allocation */
 322   gboolean use_allocator;
 323   GstAllocator *allocator;
 324   GstAllocationParams params;
 325 
 326   gsize alignment;
 327 
 328   /* when a discontinuity is pending */
 329   gboolean discont;
 330 
 331   /* list of buffers to push first */
 332   GSList *buffers;
 333 
 334   /* if we need to clip this buffer. This is only needed for uncompressed
 335    * data */
 336   gboolean need_clip;
 337 
 338   /* buffer needs some custom processing, e.g. subtitles */
 339   gboolean need_process;
 340 
 341   /* current position */
 342   guint32 segment_index;
 343   guint32 sample_index;
 344   GstClockTime time_position;   /* in gst time */
 345   guint64 accumulated_base;
 346 
 347   /* the Gst segment we are processing out, used for clipping */
 348   GstSegment segment;
 349 
 350   /* quicktime segments */
 351   guint32 n_segments;
 352   QtDemuxSegment *segments;
 353   gboolean dummy_segment;
 354   guint32 from_sample;
 355   guint32 to_sample;
 356 
 357   gboolean sent_eos;
 358   GstTagList *stream_tags;
 359   gboolean send_global_tags;
 360 
 361   GstEvent *pending_event;
 362 
 363   GstByteReader stco;
 364   GstByteReader stsz;
 365   GstByteReader stsc;
 366   GstByteReader stts;
 367   GstByteReader stss;
 368   GstByteReader stps;
 369   GstByteReader ctts;
 370 
 371   gboolean chunks_are_samples;  /* TRUE means treat chunks as samples */
 372   gint64 stbl_index;
 373   /* stco */
 374   guint co_size;
 375   GstByteReader co_chunk;
 376   guint32 first_chunk;
 377   guint32 current_chunk;
 378   guint32 last_chunk;
 379   guint32 samples_per_chunk;
 380   guint32 stsd_sample_description_id;
 381   guint32 stco_sample_index;
 382   /* stsz */
 383   guint32 sample_size;          /* 0 means variable sizes are stored in stsz */
 384   /* stsc */
 385   guint32 stsc_index;
 386   guint32 n_samples_per_chunk;
 387   guint32 stsc_chunk_index;
 388   guint32 stsc_sample_index;
 389   guint64 chunk_offset;
 390   /* stts */
 391   guint32 stts_index;
 392   guint32 stts_samples;
 393   guint32 n_sample_times;
 394   guint32 stts_sample_index;
 395   guint64 stts_time;
 396   guint32 stts_duration;
 397   /* stss */
 398   gboolean stss_present;
 399   guint32 n_sample_syncs;
 400   guint32 stss_index;
 401   /* stps */
 402   gboolean stps_present;
 403   guint32 n_sample_partial_syncs;
 404   guint32 stps_index;
 405   QtDemuxRandomAccessEntry *ra_entries;
 406   guint n_ra_entries;
 407 
 408   const QtDemuxRandomAccessEntry *pending_seek;
 409 
 410   /* ctts */
 411   gboolean ctts_present;
 412   guint32 n_composition_times;
 413   guint32 ctts_index;
 414   guint32 ctts_sample_index;
 415   guint32 ctts_count;
 416   gint32 ctts_soffset;
 417 
 418   /* cslg */
 419   guint32 cslg_shift;
 420 
 421   /* fragmented */
 422   gboolean parsed_trex;
 423   guint32 def_sample_description_index; /* index is 1-based */
 424   guint32 def_sample_duration;
 425   guint32 def_sample_size;
 426   guint32 def_sample_flags;
 427 
 428   gboolean disabled;
 429 
 430   /* stereoscopic video streams */
 431   GstVideoMultiviewMode multiview_mode;
 432   GstVideoMultiviewFlags multiview_flags;
 433 
 434   /* protected streams */
 435   gboolean protected;
 436   guint32 protection_scheme_type;
 437   guint32 protection_scheme_version;
 438   gpointer protection_scheme_info;      /* specific to the protection scheme */
 439   GQueue protection_scheme_event_queue;
 440 };
 441 
 442 /* Contains properties and cryptographic info for a set of samples from a
 443  * track protected using Common Encryption (cenc) */
 444 struct _QtDemuxCencSampleSetInfo
 445 {
 446   GstStructure *default_properties;
 447 
 448   /* @crypto_info holds one GstStructure per sample */
 449   GPtrArray *crypto_info;
 450 };
 451 
 452 static const gchar *
 453 qt_demux_state_string (enum QtDemuxState state)
 454 {
 455   switch (state) {
 456     case QTDEMUX_STATE_INITIAL:
 457       return "<INITIAL>";
 458     case QTDEMUX_STATE_HEADER:
 459       return "<HEADER>";
 460     case QTDEMUX_STATE_MOVIE:
 461       return "<MOVIE>";
 462     case QTDEMUX_STATE_BUFFER_MDAT:
 463       return "<BUFFER_MDAT>";
 464     default:
 465       return "<UNKNOWN>";
 466   }
 467 }
 468 
 469 static GNode *qtdemux_tree_get_child_by_type (GNode * node, guint32 fourcc);
 470 static GNode *qtdemux_tree_get_child_by_type_full (GNode * node,
 471     guint32 fourcc, GstByteReader * parser);
 472 static GNode *qtdemux_tree_get_sibling_by_type (GNode * node, guint32 fourcc);
 473 static GNode *qtdemux_tree_get_sibling_by_type_full (GNode * node,
 474     guint32 fourcc, GstByteReader * parser);
 475 
 476 static GstFlowReturn qtdemux_add_fragmented_samples (GstQTDemux * qtdemux);
 477 
 478 static GstStaticPadTemplate gst_qtdemux_sink_template =
 479     GST_STATIC_PAD_TEMPLATE ("sink",
 480     GST_PAD_SINK,
 481     GST_PAD_ALWAYS,
 482     GST_STATIC_CAPS ("video/quicktime; video/mj2; audio/x-m4a; "
 483         "application/x-3gp")
 484     );
 485 
 486 static GstStaticPadTemplate gst_qtdemux_videosrc_template =
 487 GST_STATIC_PAD_TEMPLATE ("video_%u",
 488     GST_PAD_SRC,
 489     GST_PAD_SOMETIMES,
 490     GST_STATIC_CAPS_ANY);
 491 
 492 static GstStaticPadTemplate gst_qtdemux_audiosrc_template =
 493 GST_STATIC_PAD_TEMPLATE ("audio_%u",
 494     GST_PAD_SRC,
 495     GST_PAD_SOMETIMES,
 496     GST_STATIC_CAPS_ANY);
 497 
 498 static GstStaticPadTemplate gst_qtdemux_subsrc_template =
 499 GST_STATIC_PAD_TEMPLATE ("subtitle_%u",
 500     GST_PAD_SRC,
 501     GST_PAD_SOMETIMES,
 502     GST_STATIC_CAPS_ANY);
 503 
 504 #define gst_qtdemux_parent_class parent_class
 505 G_DEFINE_TYPE (GstQTDemux, gst_qtdemux, GST_TYPE_ELEMENT);
 506 
 507 static void gst_qtdemux_dispose (GObject * object);
 508 
 509 static guint32
 510 gst_qtdemux_find_index_linear (GstQTDemux * qtdemux, QtDemuxStream * str,
 511     GstClockTime media_time);
 512 static guint32
 513 gst_qtdemux_find_index_for_given_media_offset_linear (GstQTDemux * qtdemux,
 514     QtDemuxStream * str, gint64 media_offset);
 515 
 516 #if 0
 517 static void gst_qtdemux_set_index (GstElement * element, GstIndex * index);
 518 static GstIndex *gst_qtdemux_get_index (GstElement * element);
 519 #endif
 520 static GstStateChangeReturn gst_qtdemux_change_state (GstElement * element,
 521     GstStateChange transition);
 522 static gboolean qtdemux_sink_activate (GstPad * sinkpad, GstObject * parent);
 523 static gboolean qtdemux_sink_activate_mode (GstPad * sinkpad,
 524     GstObject * parent, GstPadMode mode, gboolean active);
 525 
 526 static void gst_qtdemux_loop (GstPad * pad);
 527 static GstFlowReturn gst_qtdemux_chain (GstPad * sinkpad, GstObject * parent,
 528     GstBuffer * inbuf);
 529 static gboolean gst_qtdemux_handle_sink_event (GstPad * pad, GstObject * parent,
 530     GstEvent * event);
 531 static gboolean gst_qtdemux_setcaps (GstQTDemux * qtdemux, GstCaps * caps);
 532 static gboolean gst_qtdemux_configure_stream (GstQTDemux * qtdemux,
 533     QtDemuxStream * stream);
 534 static void gst_qtdemux_stream_check_and_change_stsd_index (GstQTDemux * demux,
 535     QtDemuxStream * stream);
 536 static GstFlowReturn gst_qtdemux_process_adapter (GstQTDemux * demux,
 537     gboolean force);
 538 
 539 static gboolean qtdemux_parse_moov (GstQTDemux * qtdemux,
 540     const guint8 * buffer, guint length);
 541 static gboolean qtdemux_parse_node (GstQTDemux * qtdemux, GNode * node,
 542     const guint8 * buffer, guint length);
 543 static gboolean qtdemux_parse_tree (GstQTDemux * qtdemux);
 544 static void qtdemux_parse_udta (GstQTDemux * qtdemux, GstTagList * taglist,
 545     GNode * udta);
 546 
 547 #ifdef GSTREAMER_LITE
 548 static gboolean gst_qtdemux_handle_esds (GstQTDemux * qtdemux,
 549     QtDemuxStream * stream, QtDemuxStreamStsdEntry * entry, GNode * esds,
 550     GstTagList * list);
 551 #else
 552 static void gst_qtdemux_handle_esds (GstQTDemux * qtdemux,
 553     QtDemuxStream * stream, QtDemuxStreamStsdEntry * entry, GNode * esds,
 554     GstTagList * list);
 555 #endif // GSTREAMER_LITE
 556 static GstCaps *qtdemux_video_caps (GstQTDemux * qtdemux,
 557     QtDemuxStream * stream, QtDemuxStreamStsdEntry * entry, guint32 fourcc,
 558     const guint8 * stsd_entry_data, gchar ** codec_name);
 559 static GstCaps *qtdemux_audio_caps (GstQTDemux * qtdemux,
 560     QtDemuxStream * stream, QtDemuxStreamStsdEntry * entry, guint32 fourcc,
 561     const guint8 * data, int len, gchar ** codec_name);
 562 static GstCaps *qtdemux_sub_caps (GstQTDemux * qtdemux, QtDemuxStream * stream,
 563     QtDemuxStreamStsdEntry * entry, guint32 fourcc, const guint8 * data,
 564     gchar ** codec_name);
 565 static GstCaps *qtdemux_generic_caps (GstQTDemux * qtdemux,
 566     QtDemuxStream * stream, QtDemuxStreamStsdEntry * entry, guint32 fourcc,
 567     const guint8 * stsd_entry_data, gchar ** codec_name);
 568 
 569 static gboolean qtdemux_parse_samples (GstQTDemux * qtdemux,
 570     QtDemuxStream * stream, guint32 n);
 571 static GstFlowReturn qtdemux_expose_streams (GstQTDemux * qtdemux);
 572 static void gst_qtdemux_stream_free (GstQTDemux * qtdemux,
 573     QtDemuxStream * stream);
 574 static void gst_qtdemux_stream_clear (GstQTDemux * qtdemux,
 575     QtDemuxStream * stream);
 576 static void gst_qtdemux_remove_stream (GstQTDemux * qtdemux, int index);
 577 static GstFlowReturn qtdemux_prepare_streams (GstQTDemux * qtdemux);
 578 static void qtdemux_do_allocation (GstQTDemux * qtdemux,
 579     QtDemuxStream * stream);
 580 static gboolean gst_qtdemux_activate_segment (GstQTDemux * qtdemux,
 581     QtDemuxStream * stream, guint32 seg_idx, GstClockTime offset);
 582 static gboolean gst_qtdemux_stream_update_segment (GstQTDemux * qtdemux,
 583     QtDemuxStream * stream, gint seg_idx, GstClockTime offset,
 584     GstClockTime * _start, GstClockTime * _stop);
 585 static void gst_qtdemux_send_gap_for_segment (GstQTDemux * demux,
 586     QtDemuxStream * stream, gint segment_index, GstClockTime pos);
 587 
 588 static gboolean qtdemux_pull_mfro_mfra (GstQTDemux * qtdemux);
 589 static void check_update_duration (GstQTDemux * qtdemux, GstClockTime duration);
 590 
 591 static gchar *qtdemux_uuid_bytes_to_string (gconstpointer uuid_bytes);
 592 
 593 static GstStructure *qtdemux_get_cenc_sample_properties (GstQTDemux * qtdemux,
 594     QtDemuxStream * stream, guint sample_index);
 595 static void gst_qtdemux_append_protection_system_id (GstQTDemux * qtdemux,
 596     const gchar * id);
 597 static void qtdemux_gst_structure_free (GstStructure * gststructure);
 598 
 599 static void
 600 gst_qtdemux_class_init (GstQTDemuxClass * klass)
 601 {
 602   GObjectClass *gobject_class;
 603   GstElementClass *gstelement_class;
 604 
 605   gobject_class = (GObjectClass *) klass;
 606   gstelement_class = (GstElementClass *) klass;
 607 
 608   parent_class = g_type_class_peek_parent (klass);
 609 
 610   gobject_class->dispose = gst_qtdemux_dispose;
 611 
 612   gstelement_class->change_state = GST_DEBUG_FUNCPTR (gst_qtdemux_change_state);
 613 #if 0
 614   gstelement_class->set_index = GST_DEBUG_FUNCPTR (gst_qtdemux_set_index);
 615   gstelement_class->get_index = GST_DEBUG_FUNCPTR (gst_qtdemux_get_index);
 616 #endif
 617 
 618   gst_tag_register_musicbrainz_tags ();
 619 
 620   gst_element_class_add_static_pad_template (gstelement_class,
 621       &gst_qtdemux_sink_template);
 622   gst_element_class_add_static_pad_template (gstelement_class,
 623       &gst_qtdemux_videosrc_template);
 624   gst_element_class_add_static_pad_template (gstelement_class,
 625       &gst_qtdemux_audiosrc_template);
 626   gst_element_class_add_static_pad_template (gstelement_class,
 627       &gst_qtdemux_subsrc_template);
 628   gst_element_class_set_static_metadata (gstelement_class, "QuickTime demuxer",
 629       "Codec/Demuxer",
 630       "Demultiplex a QuickTime file into audio and video streams",
 631       "David Schleef <ds@schleef.org>, Wim Taymans <wim@fluendo.com>");
 632 
 633   GST_DEBUG_CATEGORY_INIT (qtdemux_debug, "qtdemux", 0, "qtdemux plugin");
 634   gst_riff_init ();
 635 }
 636 
 637 static void
 638 gst_qtdemux_init (GstQTDemux * qtdemux)
 639 {
 640   qtdemux->sinkpad =
 641       gst_pad_new_from_static_template (&gst_qtdemux_sink_template, "sink");
 642   gst_pad_set_activate_function (qtdemux->sinkpad, qtdemux_sink_activate);
 643   gst_pad_set_activatemode_function (qtdemux->sinkpad,
 644       qtdemux_sink_activate_mode);
 645   gst_pad_set_chain_function (qtdemux->sinkpad, gst_qtdemux_chain);
 646   gst_pad_set_event_function (qtdemux->sinkpad, gst_qtdemux_handle_sink_event);
 647   gst_element_add_pad (GST_ELEMENT_CAST (qtdemux), qtdemux->sinkpad);
 648 
 649   qtdemux->state = QTDEMUX_STATE_INITIAL;
 650   qtdemux->pullbased = FALSE;
 651   qtdemux->posted_redirect = FALSE;
 652   qtdemux->neededbytes = 16;
 653   qtdemux->todrop = 0;
 654   qtdemux->adapter = gst_adapter_new ();
 655   qtdemux->offset = 0;
 656   qtdemux->first_mdat = -1;
 657   qtdemux->got_moov = FALSE;
 658   qtdemux->mdatoffset = -1;
 659   qtdemux->mdatbuffer = NULL;
 660   qtdemux->restoredata_buffer = NULL;
 661   qtdemux->restoredata_offset = -1;
 662   qtdemux->fragment_start = -1;
 663   qtdemux->fragment_start_offset = -1;
 664   qtdemux->media_caps = NULL;
 665   qtdemux->exposed = FALSE;
 666   qtdemux->mss_mode = FALSE;
 667   qtdemux->pending_newsegment = NULL;
 668   qtdemux->upstream_format_is_time = FALSE;
 669   qtdemux->have_group_id = FALSE;
 670   qtdemux->group_id = G_MAXUINT;
 671   qtdemux->cenc_aux_info_offset = 0;
 672   qtdemux->cenc_aux_info_sizes = NULL;
 673   qtdemux->cenc_aux_sample_count = 0;
 674   qtdemux->protection_system_ids = NULL;
 675   g_queue_init (&qtdemux->protection_event_queue);
 676   gst_segment_init (&qtdemux->segment, GST_FORMAT_TIME);
 677   qtdemux->tag_list = gst_tag_list_new_empty ();
 678   gst_tag_list_set_scope (qtdemux->tag_list, GST_TAG_SCOPE_GLOBAL);
 679   qtdemux->flowcombiner = gst_flow_combiner_new ();
 680 
 681   GST_OBJECT_FLAG_SET (qtdemux, GST_ELEMENT_FLAG_INDEXABLE);
 682 }
 683 
 684 static void
 685 gst_qtdemux_dispose (GObject * object)
 686 {
 687   GstQTDemux *qtdemux = GST_QTDEMUX (object);
 688 
 689   if (qtdemux->adapter) {
 690     g_object_unref (G_OBJECT (qtdemux->adapter));
 691     qtdemux->adapter = NULL;
 692   }
 693   gst_tag_list_unref (qtdemux->tag_list);
 694   gst_flow_combiner_free (qtdemux->flowcombiner);
 695   g_queue_foreach (&qtdemux->protection_event_queue, (GFunc) gst_event_unref,
 696       NULL);
 697   g_queue_clear (&qtdemux->protection_event_queue);
 698 
 699   g_free (qtdemux->cenc_aux_info_sizes);
 700   qtdemux->cenc_aux_info_sizes = NULL;
 701 
 702   G_OBJECT_CLASS (parent_class)->dispose (object);
 703 }
 704 
 705 static void
 706 gst_qtdemux_post_no_playable_stream_error (GstQTDemux * qtdemux)
 707 {
 708   if (qtdemux->posted_redirect) {
 709     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
 710         (_("This file contains no playable streams.")),
 711         ("no known streams found, a redirect message has been posted"));
 712   } else {
 713     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
 714         (_("This file contains no playable streams.")),
 715         ("no known streams found"));
 716   }
 717 }
 718 
 719 static GstBuffer *
 720 _gst_buffer_new_wrapped (gpointer mem, gsize size, GFreeFunc free_func)
 721 {
 722   return gst_buffer_new_wrapped_full (free_func ? 0 : GST_MEMORY_FLAG_READONLY,
 723       mem, size, 0, size, mem, free_func);
 724 }
 725 
 726 static GstFlowReturn
 727 gst_qtdemux_pull_atom (GstQTDemux * qtdemux, guint64 offset, guint64 size,
 728     GstBuffer ** buf)
 729 {
 730   GstFlowReturn flow;
 731   GstMapInfo map;
 732   gsize bsize;
 733 
 734   if (G_UNLIKELY (size == 0)) {
 735     GstFlowReturn ret;
 736     GstBuffer *tmp = NULL;
 737 
 738     ret = gst_qtdemux_pull_atom (qtdemux, offset, sizeof (guint32), &tmp);
 739     if (ret != GST_FLOW_OK)
 740       return ret;
 741 
 742     gst_buffer_map (tmp, &map, GST_MAP_READ);
 743     size = QT_UINT32 (map.data);
 744     GST_DEBUG_OBJECT (qtdemux, "size 0x%08" G_GINT64_MODIFIER "x", size);
 745 
 746     gst_buffer_unmap (tmp, &map);
 747     gst_buffer_unref (tmp);
 748   }
 749 
 750   /* Sanity check: catch bogus sizes (fuzzed/broken files) */
 751   if (G_UNLIKELY (size > QTDEMUX_MAX_ATOM_SIZE)) {
 752     if (qtdemux->state != QTDEMUX_STATE_MOVIE && qtdemux->got_moov) {
 753       /* we're pulling header but already got most interesting bits,
 754        * so never mind the rest (e.g. tags) (that much) */
 755       GST_WARNING_OBJECT (qtdemux, "atom has bogus size %" G_GUINT64_FORMAT,
 756           size);
 757       return GST_FLOW_EOS;
 758     } else {
 759       GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
 760           (_("This file is invalid and cannot be played.")),
 761           ("atom has bogus size %" G_GUINT64_FORMAT, size));
 762       return GST_FLOW_ERROR;
 763     }
 764   }
 765 
 766   flow = gst_pad_pull_range (qtdemux->sinkpad, offset, size, buf);
 767 
 768   if (G_UNLIKELY (flow != GST_FLOW_OK))
 769     return flow;
 770 
 771   bsize = gst_buffer_get_size (*buf);
 772   /* Catch short reads - we don't want any partial atoms */
 773   if (G_UNLIKELY (bsize < size)) {
 774     GST_WARNING_OBJECT (qtdemux,
 775         "short read: %" G_GSIZE_FORMAT " < %" G_GUINT64_FORMAT, bsize, size);
 776     gst_buffer_unref (*buf);
 777     *buf = NULL;
 778     return GST_FLOW_EOS;
 779   }
 780 
 781   return flow;
 782 }
 783 
 784 #if 1
 785 static gboolean
 786 gst_qtdemux_src_convert (GstQTDemux * qtdemux, GstPad * pad,
 787     GstFormat src_format, gint64 src_value, GstFormat dest_format,
 788     gint64 * dest_value)
 789 {
 790   gboolean res = TRUE;
 791   QtDemuxStream *stream = gst_pad_get_element_private (pad);
 792   gint32 index;
 793 
 794   if (stream->subtype != FOURCC_vide) {
 795     res = FALSE;
 796     goto done;
 797   }
 798 
 799   switch (src_format) {
 800     case GST_FORMAT_TIME:
 801       switch (dest_format) {
 802         case GST_FORMAT_BYTES:{
 803           index = gst_qtdemux_find_index_linear (qtdemux, stream, src_value);
 804           if (-1 == index) {
 805             res = FALSE;
 806             goto done;
 807           }
 808 
 809           *dest_value = stream->samples[index].offset;
 810 
 811           GST_DEBUG_OBJECT (qtdemux, "Format Conversion Time->Offset :%"
 812               GST_TIME_FORMAT "->%" G_GUINT64_FORMAT,
 813               GST_TIME_ARGS (src_value), *dest_value);
 814           break;
 815         }
 816         default:
 817           res = FALSE;
 818           break;
 819       }
 820       break;
 821     case GST_FORMAT_BYTES:
 822       switch (dest_format) {
 823         case GST_FORMAT_TIME:{
 824           index =
 825               gst_qtdemux_find_index_for_given_media_offset_linear (qtdemux,
 826               stream, src_value);
 827 
 828           if (-1 == index) {
 829             res = FALSE;
 830             goto done;
 831           }
 832 
 833           *dest_value =
 834               QTSTREAMTIME_TO_GSTTIME (stream,
 835               stream->samples[index].timestamp);
 836           GST_DEBUG_OBJECT (qtdemux,
 837               "Format Conversion Offset->Time :%" G_GUINT64_FORMAT "->%"
 838               GST_TIME_FORMAT, src_value, GST_TIME_ARGS (*dest_value));
 839           break;
 840         }
 841         default:
 842           res = FALSE;
 843           break;
 844       }
 845       break;
 846     default:
 847       res = FALSE;
 848       break;
 849   }
 850 
 851 done:
 852   return res;
 853 }
 854 #endif
 855 
 856 static gboolean
 857 gst_qtdemux_get_duration (GstQTDemux * qtdemux, GstClockTime * duration)
 858 {
 859   gboolean res = FALSE;
 860 
 861   *duration = GST_CLOCK_TIME_NONE;
 862 
 863   if (qtdemux->duration != 0 &&
 864       qtdemux->duration != G_MAXINT64 && qtdemux->timescale != 0) {
 865     *duration = QTTIME_TO_GSTTIME (qtdemux, qtdemux->duration);
 866     res = TRUE;
 867   } else {
 868     *duration = GST_CLOCK_TIME_NONE;
 869     }
 870 
 871   return res;
 872 }
 873 
 874 static gboolean
 875 gst_qtdemux_handle_src_query (GstPad * pad, GstObject * parent,
 876     GstQuery * query)
 877 {
 878   gboolean res = FALSE;
 879   GstQTDemux *qtdemux = GST_QTDEMUX (parent);
 880 
 881   GST_LOG_OBJECT (pad, "%s query", GST_QUERY_TYPE_NAME (query));
 882 
 883   switch (GST_QUERY_TYPE (query)) {
 884     case GST_QUERY_POSITION:{
 885       GstFormat fmt;
 886 
 887       gst_query_parse_position (query, &fmt, NULL);
 888       if (fmt == GST_FORMAT_TIME
 889           && GST_CLOCK_TIME_IS_VALID (qtdemux->segment.position)) {
 890         gst_query_set_position (query, GST_FORMAT_TIME,
 891             qtdemux->segment.position);
 892         res = TRUE;
 893       }
 894     }
 895       break;
 896     case GST_QUERY_DURATION:{
 897       GstFormat fmt;
 898 
 899       gst_query_parse_duration (query, &fmt, NULL);
 900       if (fmt == GST_FORMAT_TIME) {
 901         /* First try to query upstream */
 902         res = gst_pad_query_default (pad, parent, query);
 903         if (!res) {
 904           GstClockTime duration;
 905           if (gst_qtdemux_get_duration (qtdemux, &duration) && duration > 0) {
 906           gst_query_set_duration (query, GST_FORMAT_TIME, duration);
 907           res = TRUE;
 908         }
 909       }
 910       }
 911       break;
 912     }
 913     case GST_QUERY_CONVERT:{
 914       GstFormat src_fmt, dest_fmt;
 915       gint64 src_value, dest_value = 0;
 916 
 917       gst_query_parse_convert (query, &src_fmt, &src_value, &dest_fmt, NULL);
 918 
 919       res = gst_qtdemux_src_convert (qtdemux, pad,
 920           src_fmt, src_value, dest_fmt, &dest_value);
 921       if (res)
 922         gst_query_set_convert (query, src_fmt, src_value, dest_fmt, dest_value);
 923 
 924       break;
 925     }
 926     case GST_QUERY_FORMATS:
 927       gst_query_set_formats (query, 2, GST_FORMAT_TIME, GST_FORMAT_BYTES);
 928       res = TRUE;
 929       break;
 930     case GST_QUERY_SEEKING:{
 931       GstFormat fmt;
 932       gboolean seekable;
 933 
 934       /* try upstream first */
 935       res = gst_pad_query_default (pad, parent, query);
 936 
 937       if (!res) {
 938       gst_query_parse_seeking (query, &fmt, NULL, NULL, NULL);
 939       if (fmt == GST_FORMAT_TIME) {
 940           GstClockTime duration;
 941 
 942         gst_qtdemux_get_duration (qtdemux, &duration);
 943         seekable = TRUE;
 944         if (!qtdemux->pullbased) {
 945           GstQuery *q;
 946 
 947           /* we might be able with help from upstream */
 948           seekable = FALSE;
 949           q = gst_query_new_seeking (GST_FORMAT_BYTES);
 950           if (gst_pad_peer_query (qtdemux->sinkpad, q)) {
 951             gst_query_parse_seeking (q, &fmt, &seekable, NULL, NULL);
 952             GST_LOG_OBJECT (qtdemux, "upstream BYTE seekable %d", seekable);
 953           }
 954           gst_query_unref (q);
 955         }
 956         gst_query_set_seeking (query, GST_FORMAT_TIME, seekable, 0, duration);
 957         res = TRUE;
 958       }
 959       }
 960       break;
 961     }
 962     case GST_QUERY_SEGMENT:
 963     {
 964       GstFormat format;
 965       gint64 start, stop;
 966 
 967       format = qtdemux->segment.format;
 968 
 969       start =
 970           gst_segment_to_stream_time (&qtdemux->segment, format,
 971           qtdemux->segment.start);
 972       if ((stop = qtdemux->segment.stop) == -1)
 973         stop = qtdemux->segment.duration;
 974       else
 975         stop = gst_segment_to_stream_time (&qtdemux->segment, format, stop);
 976 
 977       gst_query_set_segment (query, qtdemux->segment.rate, format, start, stop);
 978       res = TRUE;
 979       break;
 980     }
 981     default:
 982       res = gst_pad_query_default (pad, parent, query);
 983       break;
 984   }
 985 
 986 #ifdef GSTREAMER_LITE
 987   if (!res)
 988       res = gst_pad_query_default (pad, parent, query);
 989 #endif
 990 
 991   return res;
 992 }
 993 
 994 static void
 995 gst_qtdemux_push_tags (GstQTDemux * qtdemux, QtDemuxStream * stream)
 996 {
 997   if (G_LIKELY (stream->pad)) {
 998     GST_DEBUG_OBJECT (qtdemux, "Checking pad %s:%s for tags",
 999         GST_DEBUG_PAD_NAME (stream->pad));
1000 
1001     if (!gst_tag_list_is_empty (stream->stream_tags)) {
1002       GST_DEBUG_OBJECT (qtdemux, "Sending tags %" GST_PTR_FORMAT,
1003           stream->stream_tags);
1004       gst_pad_push_event (stream->pad,
1005           gst_event_new_tag (gst_tag_list_ref (stream->stream_tags)));
1006     }
1007 
1008     if (G_UNLIKELY (stream->send_global_tags)) {
1009       GST_DEBUG_OBJECT (qtdemux, "Sending global tags %" GST_PTR_FORMAT,
1010           qtdemux->tag_list);
1011       gst_pad_push_event (stream->pad,
1012           gst_event_new_tag (gst_tag_list_ref (qtdemux->tag_list)));
1013       stream->send_global_tags = FALSE;
1014     }
1015   }
1016 }
1017 
1018 /* push event on all source pads; takes ownership of the event */
1019 static void
1020 gst_qtdemux_push_event (GstQTDemux * qtdemux, GstEvent * event)
1021 {
1022   guint n;
1023   gboolean has_valid_stream = FALSE;
1024   GstEventType etype = GST_EVENT_TYPE (event);
1025 
1026   GST_DEBUG_OBJECT (qtdemux, "pushing %s event on all source pads",
1027       GST_EVENT_TYPE_NAME (event));
1028 
1029   for (n = 0; n < qtdemux->n_streams; n++) {
1030     GstPad *pad;
1031     QtDemuxStream *stream = qtdemux->streams[n];
1032     GST_DEBUG_OBJECT (qtdemux, "pushing on pad %i", n);
1033 
1034     if ((pad = stream->pad)) {
1035       has_valid_stream = TRUE;
1036 
1037       if (etype == GST_EVENT_EOS) {
1038         /* let's not send twice */
1039         if (stream->sent_eos)
1040           continue;
1041         stream->sent_eos = TRUE;
1042       }
1043 
1044       gst_pad_push_event (pad, gst_event_ref (event));
1045     }
1046   }
1047 
1048   gst_event_unref (event);
1049 
1050   /* if it is EOS and there are no pads, post an error */
1051   if (!has_valid_stream && etype == GST_EVENT_EOS) {
1052     gst_qtdemux_post_no_playable_stream_error (qtdemux);
1053   }
1054 }
1055 
1056 /* push a pending newsegment event, if any from the streaming thread */
1057 static void
1058 gst_qtdemux_push_pending_newsegment (GstQTDemux * qtdemux)
1059 {
1060   if (qtdemux->pending_newsegment) {
1061     gst_qtdemux_push_event (qtdemux, qtdemux->pending_newsegment);
1062     qtdemux->pending_newsegment = NULL;
1063   }
1064 }
1065 
1066 typedef struct
1067 {
1068   guint64 media_time;
1069 } FindData;
1070 
1071 static gint
1072 find_func (QtDemuxSample * s1, gint64 * media_time, gpointer user_data)
1073 {
1074   if ((gint64) s1->timestamp + s1->pts_offset > *media_time)
1075     return 1;
1076   if ((gint64) s1->timestamp + s1->pts_offset == *media_time)
1077     return 0;
1078 
1079   return -1;
1080 }
1081 
1082 /* find the index of the sample that includes the data for @media_time using a
1083  * binary search.  Only to be called in optimized cases of linear search below.
1084  *
1085  * Returns the index of the sample.
1086  */
1087 static guint32
1088 gst_qtdemux_find_index (GstQTDemux * qtdemux, QtDemuxStream * str,
1089     guint64 media_time)
1090 {
1091   QtDemuxSample *result;
1092   guint32 index;
1093 
1094   /* convert media_time to mov format */
1095   media_time =
1096       gst_util_uint64_scale_ceil (media_time, str->timescale, GST_SECOND);
1097 
1098   result = gst_util_array_binary_search (str->samples, str->stbl_index + 1,
1099       sizeof (QtDemuxSample), (GCompareDataFunc) find_func,
1100       GST_SEARCH_MODE_BEFORE, &media_time, NULL);
1101 
1102   if (G_LIKELY (result))
1103     index = result - str->samples;
1104   else
1105     index = 0;
1106 
1107   return index;
1108 }
1109 
1110 
1111 
1112 /* find the index of the sample that includes the data for @media_offset using a
1113  * linear search
1114  *
1115  * Returns the index of the sample.
1116  */
1117 static guint32
1118 gst_qtdemux_find_index_for_given_media_offset_linear (GstQTDemux * qtdemux,
1119     QtDemuxStream * str, gint64 media_offset)
1120 {
1121   QtDemuxSample *result = str->samples;
1122   guint32 index = 0;
1123 
1124   if (result == NULL || str->n_samples == 0)
1125     return -1;
1126 
1127   if (media_offset == result->offset)
1128     return index;
1129 
1130   result++;
1131   while (index < str->n_samples - 1) {
1132     if (!qtdemux_parse_samples (qtdemux, str, index + 1))
1133       goto parse_failed;
1134 
1135     if (media_offset < result->offset)
1136       break;
1137 
1138     index++;
1139     result++;
1140   }
1141   return index;
1142 
1143   /* ERRORS */
1144 parse_failed:
1145   {
1146     GST_LOG_OBJECT (qtdemux, "Parsing of index %u failed!", index + 1);
1147     return -1;
1148   }
1149 }
1150 
1151 /* find the index of the sample that includes the data for @media_time using a
1152  * linear search, and keeping in mind that not all samples may have been parsed
1153  * yet.  If possible, it will delegate to binary search.
1154  *
1155  * Returns the index of the sample.
1156  */
1157 static guint32
1158 gst_qtdemux_find_index_linear (GstQTDemux * qtdemux, QtDemuxStream * str,
1159     GstClockTime media_time)
1160 {
1161   guint32 index = 0;
1162   guint64 mov_time;
1163   QtDemuxSample *sample;
1164 
1165   /* convert media_time to mov format */
1166   mov_time =
1167       gst_util_uint64_scale_ceil (media_time, str->timescale, GST_SECOND);
1168 
1169   sample = str->samples;
1170   if (mov_time == sample->timestamp + sample->pts_offset)
1171     return index;
1172 
1173   /* use faster search if requested time in already parsed range */
1174   sample = str->samples + str->stbl_index;
1175   if (str->stbl_index >= 0 &&
1176       mov_time <= (sample->timestamp + sample->pts_offset))
1177     return gst_qtdemux_find_index (qtdemux, str, media_time);
1178 
1179   while (index < str->n_samples - 1) {
1180     if (!qtdemux_parse_samples (qtdemux, str, index + 1))
1181       goto parse_failed;
1182 
1183     sample = str->samples + index + 1;
1184     if (mov_time < (sample->timestamp + sample->pts_offset))
1185       break;
1186 
1187     index++;
1188   }
1189   return index;
1190 
1191   /* ERRORS */
1192 parse_failed:
1193   {
1194     GST_LOG_OBJECT (qtdemux, "Parsing of index %u failed!", index + 1);
1195     return -1;
1196   }
1197 }
1198 
1199 /* find the index of the keyframe needed to decode the sample at @index
1200  * of stream @str, or of a subsequent keyframe (depending on @next)
1201  *
1202  * Returns the index of the keyframe.
1203  */
1204 static guint32
1205 gst_qtdemux_find_keyframe (GstQTDemux * qtdemux, QtDemuxStream * str,
1206     guint32 index, gboolean next)
1207 {
1208   guint32 new_index = index;
1209 
1210   if (index >= str->n_samples) {
1211     new_index = str->n_samples;
1212     goto beach;
1213   }
1214 
1215   /* all keyframes, return index */
1216   if (str->all_keyframe) {
1217     new_index = index;
1218     goto beach;
1219   }
1220 
1221   /* else search until we have a keyframe */
1222   while (new_index < str->n_samples) {
1223     if (next && !qtdemux_parse_samples (qtdemux, str, new_index))
1224       goto parse_failed;
1225 
1226     if (str->samples[new_index].keyframe)
1227       break;
1228 
1229     if (new_index == 0)
1230       break;
1231 
1232     if (next)
1233       new_index++;
1234     else
1235     new_index--;
1236   }
1237 
1238   if (new_index == str->n_samples) {
1239     GST_DEBUG_OBJECT (qtdemux, "no next keyframe");
1240     new_index = -1;
1241   }
1242 
1243 beach:
1244   GST_DEBUG_OBJECT (qtdemux, "searching for keyframe index %s index %u "
1245       "gave %u", next ? "after" : "before", index, new_index);
1246 
1247   return new_index;
1248 
1249   /* ERRORS */
1250 parse_failed:
1251   {
1252     GST_LOG_OBJECT (qtdemux, "Parsing of index %u failed!", new_index);
1253     return -1;
1254 }
1255 }
1256 
1257 /* find the segment for @time_position for @stream
1258  *
1259  * Returns the index of the segment containing @time_position.
1260  * Returns the last segment and sets the @eos variable to TRUE
1261  * if the time is beyond the end. @eos may be NULL
1262  */
1263 static guint32
1264 gst_qtdemux_find_segment (GstQTDemux * qtdemux, QtDemuxStream * stream,
1265     GstClockTime time_position)
1266 {
1267   gint i;
1268   guint32 seg_idx;
1269 
1270   GST_LOG_OBJECT (stream->pad, "finding segment for %" GST_TIME_FORMAT,
1271       GST_TIME_ARGS (time_position));
1272 
1273   seg_idx = -1;
1274   for (i = 0; i < stream->n_segments; i++) {
1275     QtDemuxSegment *segment = &stream->segments[i];
1276 
1277     GST_LOG_OBJECT (stream->pad,
1278         "looking at segment %" GST_TIME_FORMAT "-%" GST_TIME_FORMAT,
1279         GST_TIME_ARGS (segment->time), GST_TIME_ARGS (segment->stop_time));
1280 
1281     /* For the last segment we include stop_time in the last segment */
1282     if (i < stream->n_segments - 1) {
1283       if (segment->time <= time_position && time_position < segment->stop_time) {
1284         GST_LOG_OBJECT (stream->pad, "segment %d matches", i);
1285         seg_idx = i;
1286         break;
1287       }
1288     } else {
1289       /* Last segment always matches */
1290         seg_idx = i;
1291         break;
1292       }
1293     }
1294   return seg_idx;
1295 }
1296 
1297 /* move the stream @str to the sample position @index.
1298  *
1299  * Updates @str->sample_index and marks discontinuity if needed.
1300  */
1301 static void
1302 gst_qtdemux_move_stream (GstQTDemux * qtdemux, QtDemuxStream * str,
1303     guint32 index)
1304 {
1305   /* no change needed */
1306   if (index == str->sample_index)
1307     return;
1308 
1309   GST_DEBUG_OBJECT (qtdemux, "moving to sample %u of %u", index,
1310       str->n_samples);
1311 
1312   /* position changed, we have a discont */
1313   str->sample_index = index;
1314   str->offset_in_sample = 0;
1315   /* Each time we move in the stream we store the position where we are
1316    * starting from */
1317   str->from_sample = index;
1318   str->discont = TRUE;
1319 }
1320 
1321 static void
1322 gst_qtdemux_adjust_seek (GstQTDemux * qtdemux, gint64 desired_time,
1323     gboolean use_sparse, gboolean next, gint64 * key_time, gint64 * key_offset)
1324 {
1325   guint64 min_offset;
1326   gint64 min_byte_offset = -1;
1327   gint n;
1328 
1329   min_offset = desired_time;
1330 
1331   /* for each stream, find the index of the sample in the segment
1332    * and move back to the previous keyframe. */
1333   for (n = 0; n < qtdemux->n_streams; n++) {
1334     QtDemuxStream *str;
1335     guint32 index, kindex;
1336     guint32 seg_idx;
1337     GstClockTime media_start;
1338     GstClockTime media_time;
1339     GstClockTime seg_time;
1340     QtDemuxSegment *seg;
1341     gboolean empty_segment = FALSE;
1342 
1343     str = qtdemux->streams[n];
1344 
1345     if (CUR_STREAM (str)->sparse && !use_sparse)
1346       continue;
1347 
1348     seg_idx = gst_qtdemux_find_segment (qtdemux, str, desired_time);
1349     GST_DEBUG_OBJECT (qtdemux, "align segment %d", seg_idx);
1350 
1351     /* get segment and time in the segment */
1352     seg = &str->segments[seg_idx];
1353     seg_time = (desired_time - seg->time) * seg->rate;
1354 
1355     while (QTSEGMENT_IS_EMPTY (seg)) {
1356       seg_time = 0;
1357       empty_segment = TRUE;
1358       GST_DEBUG_OBJECT (str->pad, "Segment %d is empty, moving to next one",
1359           seg_idx);
1360       seg_idx++;
1361       if (seg_idx == str->n_segments)
1362         break;
1363       seg = &str->segments[seg_idx];
1364     }
1365 
1366     if (seg_idx == str->n_segments) {
1367       /* FIXME track shouldn't have the last segment as empty, but if it
1368        * happens we better handle it */
1369       continue;
1370     }
1371 
1372     /* get the media time in the segment */
1373     media_start = seg->media_start + seg_time;
1374 
1375     /* get the index of the sample with media time */
1376     index = gst_qtdemux_find_index_linear (qtdemux, str, media_start);
1377     GST_DEBUG_OBJECT (qtdemux, "sample for %" GST_TIME_FORMAT " at %u"
1378         " at offset %" G_GUINT64_FORMAT " (empty segment: %d)",
1379         GST_TIME_ARGS (media_start), index, str->samples[index].offset,
1380         empty_segment);
1381 
1382     /* shift to next frame if we are looking for next keyframe */
1383     if (next && QTSAMPLE_PTS_NO_CSLG (str, &str->samples[index]) < media_start
1384         && index < str->stbl_index)
1385       index++;
1386 
1387     if (!empty_segment) {
1388     /* find previous keyframe */
1389       kindex = gst_qtdemux_find_keyframe (qtdemux, str, index, next);
1390 
1391       /* we will settle for one before if none found after */
1392       if (next && kindex == -1)
1393         kindex = gst_qtdemux_find_keyframe (qtdemux, str, index, FALSE);
1394 
1395     /* if the keyframe is at a different position, we need to update the
1396      * requested seek time */
1397     if (index != kindex) {
1398       index = kindex;
1399 
1400       /* get timestamp of keyframe */
1401         media_time = QTSAMPLE_PTS_NO_CSLG (str, &str->samples[kindex]);
1402         GST_DEBUG_OBJECT (qtdemux,
1403             "keyframe at %u with time %" GST_TIME_FORMAT " at offset %"
1404             G_GUINT64_FORMAT, kindex, GST_TIME_ARGS (media_time),
1405             str->samples[kindex].offset);
1406 
1407       /* keyframes in the segment get a chance to change the
1408        * desired_offset. keyframes out of the segment are
1409        * ignored. */
1410       if (media_time >= seg->media_start) {
1411           GstClockTime seg_time;
1412 
1413         /* this keyframe is inside the segment, convert back to
1414          * segment time */
1415         seg_time = (media_time - seg->media_start) + seg->time;
1416           if ((!next && (seg_time < min_offset)) ||
1417               (next && (seg_time > min_offset)))
1418           min_offset = seg_time;
1419       }
1420     }
1421     }
1422 
1423     if (min_byte_offset < 0 || str->samples[index].offset < min_byte_offset)
1424       min_byte_offset = str->samples[index].offset;
1425   }
1426 
1427   if (key_time)
1428     *key_time = min_offset;
1429   if (key_offset)
1430     *key_offset = min_byte_offset;
1431 }
1432 
1433 static gboolean
1434 gst_qtdemux_convert_seek (GstPad * pad, GstFormat * format,
1435     GstSeekType cur_type, gint64 * cur, GstSeekType stop_type, gint64 * stop)
1436 {
1437   gboolean res;
1438 
1439   g_return_val_if_fail (format != NULL, FALSE);
1440   g_return_val_if_fail (cur != NULL, FALSE);
1441   g_return_val_if_fail (stop != NULL, FALSE);
1442 
1443   if (*format == GST_FORMAT_TIME)
1444     return TRUE;
1445 
1446   res = TRUE;
1447   if (cur_type != GST_SEEK_TYPE_NONE)
1448     res = gst_pad_query_convert (pad, *format, *cur, GST_FORMAT_TIME, cur);
1449   if (res && stop_type != GST_SEEK_TYPE_NONE)
1450     res = gst_pad_query_convert (pad, *format, *stop, GST_FORMAT_TIME, stop);
1451 
1452   if (res)
1453     *format = GST_FORMAT_TIME;
1454 
1455   return res;
1456 }
1457 
1458 /* perform seek in push based mode:
1459    find BYTE position to move to based on time and delegate to upstream
1460 */
1461 static gboolean
1462 gst_qtdemux_do_push_seek (GstQTDemux * qtdemux, GstPad * pad, GstEvent * event)
1463 {
1464   gdouble rate;
1465   GstFormat format;
1466   GstSeekFlags flags;
1467   GstSeekType cur_type, stop_type;
1468   gint64 cur, stop, key_cur;
1469   gboolean res;
1470   gint64 byte_cur;
1471   gint64 original_stop;
1472   guint32 seqnum;
1473 #ifdef GSTREAMER_LITE
1474   GstEvent * new_event = NULL;
1475 #endif // GSTREAMER_LITE
1476 
1477   GST_DEBUG_OBJECT (qtdemux, "doing push-based seek");
1478 
1479   gst_event_parse_seek (event, &rate, &format, &flags,
1480       &cur_type, &cur, &stop_type, &stop);
1481   seqnum = gst_event_get_seqnum (event);
1482 
1483   /* only forward streaming and seeking is possible */
1484   if (rate <= 0)
1485     goto unsupported_seek;
1486 
1487   /* convert to TIME if needed and possible */
1488   if (!gst_qtdemux_convert_seek (pad, &format, cur_type, &cur,
1489           stop_type, &stop))
1490     goto no_format;
1491 
1492   /* Upstream seek in bytes will have undefined stop, but qtdemux stores
1493    * the original stop position to use when upstream pushes the new segment
1494    * for this seek */
1495   original_stop = stop;
1496   stop = -1;
1497 
1498   /* find reasonable corresponding BYTE position,
1499    * also try to mind about keyframes, since we can not go back a bit for them
1500    * later on */
1501   /* determining @next here based on SNAP_BEFORE/SNAP_AFTER should
1502    * mostly just work, but let's not yet boldly go there  ... */
1503   gst_qtdemux_adjust_seek (qtdemux, cur, FALSE, FALSE, &key_cur, &byte_cur);
1504 
1505   if (byte_cur == -1)
1506     goto abort_seek;
1507 
1508   GST_DEBUG_OBJECT (qtdemux, "Pushing BYTE seek rate %g, "
1509       "start %" G_GINT64_FORMAT ", stop %" G_GINT64_FORMAT, rate, byte_cur,
1510       stop);
1511 
1512     GST_OBJECT_LOCK (qtdemux);
1513     qtdemux->seek_offset = byte_cur;
1514   if (!(flags & GST_SEEK_FLAG_KEY_UNIT)) {
1515     qtdemux->push_seek_start = cur;
1516   } else {
1517     qtdemux->push_seek_start = key_cur;
1518   }
1519 
1520   if (stop_type == GST_SEEK_TYPE_NONE) {
1521     qtdemux->push_seek_stop = qtdemux->segment.stop;
1522   } else {
1523     qtdemux->push_seek_stop = original_stop;
1524   }
1525   GST_OBJECT_UNLOCK (qtdemux);
1526 
1527   /* BYTE seek event */
1528 #ifdef GSTREAMER_LITE
1529   new_event = gst_event_new_seek(rate, GST_FORMAT_BYTES, flags, cur_type, byte_cur,
1530       stop_type, stop);
1531   gst_event_set_seqnum(new_event, seqnum);
1532   res = gst_pad_push_event(qtdemux->sinkpad, new_event);
1533   if (res) {
1534     gst_event_unref(event);
1535   }
1536 #else // GSTREAMER_LITE
1537   event = gst_event_new_seek (rate, GST_FORMAT_BYTES, flags, cur_type, byte_cur,
1538       stop_type, stop);
1539   gst_event_set_seqnum (event, seqnum);
1540   res = gst_pad_push_event (qtdemux->sinkpad, event);
1541 #endif // GSTREAMER_LITE
1542 
1543   return res;
1544 
1545   /* ERRORS */
1546 abort_seek:
1547   {
1548     GST_DEBUG_OBJECT (qtdemux, "could not determine byte position to seek to, "
1549         "seek aborted.");
1550     return FALSE;
1551   }
1552 unsupported_seek:
1553   {
1554     GST_DEBUG_OBJECT (qtdemux, "unsupported seek, seek aborted.");
1555     return FALSE;
1556   }
1557 no_format:
1558   {
1559     GST_DEBUG_OBJECT (qtdemux, "unsupported format given, seek aborted.");
1560     return FALSE;
1561   }
1562 }
1563 
1564 /* perform the seek.
1565  *
1566  * We set all segment_indexes in the streams to unknown and
1567  * adjust the time_position to the desired position. this is enough
1568  * to trigger a segment switch in the streaming thread to start
1569  * streaming from the desired position.
1570  *
1571  * Keyframe seeking is a little more complicated when dealing with
1572  * segments. Ideally we want to move to the previous keyframe in
1573  * the segment but there might not be a keyframe in the segment. In
1574  * fact, none of the segments could contain a keyframe. We take a
1575  * practical approach: seek to the previous keyframe in the segment,
1576  * if there is none, seek to the beginning of the segment.
1577  *
1578  * Called with STREAM_LOCK
1579  */
1580 static gboolean
1581 gst_qtdemux_perform_seek (GstQTDemux * qtdemux, GstSegment * segment,
1582     guint32 seqnum, GstSeekFlags flags)
1583 {
1584   gint64 desired_offset;
1585   gint n;
1586 
1587   desired_offset = segment->position;
1588 
1589   GST_DEBUG_OBJECT (qtdemux, "seeking to %" GST_TIME_FORMAT,
1590       GST_TIME_ARGS (desired_offset));
1591 
1592   /* may not have enough fragmented info to do this adjustment,
1593    * and we can't scan (and probably should not) at this time with
1594    * possibly flushing upstream */
1595   if ((flags & GST_SEEK_FLAG_KEY_UNIT) && !qtdemux->fragmented) {
1596     gint64 min_offset;
1597     gboolean next, before, after;
1598 
1599     before = ! !(flags & GST_SEEK_FLAG_SNAP_BEFORE);
1600     after = ! !(flags & GST_SEEK_FLAG_SNAP_AFTER);
1601     next = after && !before;
1602     if (segment->rate < 0)
1603       next = !next;
1604 
1605     gst_qtdemux_adjust_seek (qtdemux, desired_offset, TRUE, next, &min_offset,
1606         NULL);
1607     GST_DEBUG_OBJECT (qtdemux, "keyframe seek, align to %"
1608         GST_TIME_FORMAT, GST_TIME_ARGS (min_offset));
1609     desired_offset = min_offset;
1610   }
1611 
1612   /* and set all streams to the final position */
1613   gst_flow_combiner_reset (qtdemux->flowcombiner);
1614   qtdemux->segment_seqnum = seqnum;
1615   for (n = 0; n < qtdemux->n_streams; n++) {
1616     QtDemuxStream *stream = qtdemux->streams[n];
1617 
1618     stream->time_position = desired_offset;
1619     stream->accumulated_base = 0;
1620     stream->sample_index = -1;
1621     stream->offset_in_sample = 0;
1622     stream->segment_index = -1;
1623     stream->sent_eos = FALSE;
1624 
1625     if (segment->flags & GST_SEEK_FLAG_FLUSH)
1626       gst_segment_init (&stream->segment, GST_FORMAT_TIME);
1627   }
1628   segment->position = desired_offset;
1629   segment->time = desired_offset;
1630   if (segment->rate >= 0) {
1631     segment->start = desired_offset;
1632 
1633   /* we stop at the end */
1634   if (segment->stop == -1)
1635     segment->stop = segment->duration;
1636   } else {
1637     segment->stop = desired_offset;
1638   }
1639 
1640   if (qtdemux->fragmented)
1641     qtdemux->fragmented_seek_pending = TRUE;
1642 
1643   return TRUE;
1644 }
1645 
1646 /* do a seek in pull based mode */
1647 static gboolean
1648 gst_qtdemux_do_seek (GstQTDemux * qtdemux, GstPad * pad, GstEvent * event)
1649 {
1650   gdouble rate;
1651   GstFormat format;
1652   GstSeekFlags flags;
1653   GstSeekType cur_type, stop_type;
1654   gint64 cur, stop;
1655   gboolean flush;
1656   gboolean update;
1657   GstSegment seeksegment;
1658   guint32 seqnum = GST_SEQNUM_INVALID;
1659   GstEvent *flush_event;
1660   gboolean ret;
1661 
1662   if (event) {
1663     GST_DEBUG_OBJECT (qtdemux, "doing seek with event");
1664 
1665     gst_event_parse_seek (event, &rate, &format, &flags,
1666         &cur_type, &cur, &stop_type, &stop);
1667     seqnum = gst_event_get_seqnum (event);
1668 
1669     /* we have to have a format as the segment format. Try to convert
1670      * if not. */
1671     if (!gst_qtdemux_convert_seek (pad, &format, cur_type, &cur,
1672             stop_type, &stop))
1673       goto no_format;
1674 
1675     GST_DEBUG_OBJECT (qtdemux, "seek format %s", gst_format_get_name (format));
1676   } else {
1677     GST_DEBUG_OBJECT (qtdemux, "doing seek without event");
1678     flags = 0;
1679   }
1680 
1681   flush = flags & GST_SEEK_FLAG_FLUSH;
1682 
1683   /* stop streaming, either by flushing or by pausing the task */
1684   if (flush) {
1685     flush_event = gst_event_new_flush_start ();
1686     if (seqnum != GST_SEQNUM_INVALID)
1687       gst_event_set_seqnum (flush_event, seqnum);
1688     /* unlock upstream pull_range */
1689     gst_pad_push_event (qtdemux->sinkpad, gst_event_ref (flush_event));
1690     /* make sure out loop function exits */
1691     gst_qtdemux_push_event (qtdemux, flush_event);
1692   } else {
1693     /* non flushing seek, pause the task */
1694     gst_pad_pause_task (qtdemux->sinkpad);
1695   }
1696 
1697   /* wait for streaming to finish */
1698   GST_PAD_STREAM_LOCK (qtdemux->sinkpad);
1699 
1700   /* copy segment, we need this because we still need the old
1701    * segment when we close the current segment. */
1702   memcpy (&seeksegment, &qtdemux->segment, sizeof (GstSegment));
1703 
1704   if (event) {
1705     /* configure the segment with the seek variables */
1706     GST_DEBUG_OBJECT (qtdemux, "configuring seek");
1707     if (!gst_segment_do_seek (&seeksegment, rate, format, flags,
1708             cur_type, cur, stop_type, stop, &update)) {
1709       ret = FALSE;
1710       GST_ERROR_OBJECT (qtdemux, "inconsistent seek values, doing nothing");
1711     } else {
1712       /* now do the seek */
1713       ret = gst_qtdemux_perform_seek (qtdemux, &seeksegment, seqnum, flags);
1714   }
1715   } else {
1716     /* now do the seek */
1717     ret = gst_qtdemux_perform_seek (qtdemux, &seeksegment, seqnum, flags);
1718   }
1719 
1720   /* prepare for streaming again */
1721   if (flush) {
1722     flush_event = gst_event_new_flush_stop (TRUE);
1723     if (seqnum != GST_SEQNUM_INVALID)
1724       gst_event_set_seqnum (flush_event, seqnum);
1725 
1726     gst_pad_push_event (qtdemux->sinkpad, gst_event_ref (flush_event));
1727     gst_qtdemux_push_event (qtdemux, flush_event);
1728     }
1729 
1730   /* commit the new segment */
1731   memcpy (&qtdemux->segment, &seeksegment, sizeof (GstSegment));
1732 
1733   if (qtdemux->segment.flags & GST_SEEK_FLAG_SEGMENT) {
1734     GstMessage *msg = gst_message_new_segment_start (GST_OBJECT_CAST (qtdemux),
1735         qtdemux->segment.format, qtdemux->segment.position);
1736     if (seqnum != GST_SEQNUM_INVALID)
1737       gst_message_set_seqnum (msg, seqnum);
1738     gst_element_post_message (GST_ELEMENT_CAST (qtdemux), msg);
1739   }
1740 
1741   /* restart streaming, NEWSEGMENT will be sent from the streaming thread. */
1742   gst_pad_start_task (qtdemux->sinkpad, (GstTaskFunction) gst_qtdemux_loop,
1743       qtdemux->sinkpad, NULL);
1744 
1745   GST_PAD_STREAM_UNLOCK (qtdemux->sinkpad);
1746 
1747   return ret;
1748 
1749   /* ERRORS */
1750 no_format:
1751   {
1752     GST_DEBUG_OBJECT (qtdemux, "unsupported format given, seek aborted.");
1753     return FALSE;
1754   }
1755 }
1756 
1757 static gboolean
1758 qtdemux_ensure_index (GstQTDemux * qtdemux)
1759 {
1760   guint i;
1761 
1762   GST_DEBUG_OBJECT (qtdemux, "collecting all metadata for all streams");
1763 
1764   /* Build complete index */
1765   for (i = 0; i < qtdemux->n_streams; i++) {
1766     QtDemuxStream *stream = qtdemux->streams[i];
1767 
1768     if (!qtdemux_parse_samples (qtdemux, stream, stream->n_samples - 1))
1769       goto parse_error;
1770   }
1771   return TRUE;
1772 
1773   /* ERRORS */
1774 parse_error:
1775   {
1776     GST_LOG_OBJECT (qtdemux,
1777         "Building complete index of stream %u for seeking failed!", i);
1778     return FALSE;
1779   }
1780 }
1781 
1782 static gboolean
1783 gst_qtdemux_handle_src_event (GstPad * pad, GstObject * parent,
1784     GstEvent * event)
1785 {
1786   gboolean res = TRUE;
1787   GstQTDemux *qtdemux = GST_QTDEMUX (parent);
1788 
1789   switch (GST_EVENT_TYPE (event)) {
1790     case GST_EVENT_SEEK:
1791     {
1792 #ifndef GST_DISABLE_GST_DEBUG
1793       GstClockTime ts = gst_util_get_timestamp ();
1794 #endif
1795       guint32 seqnum = gst_event_get_seqnum (event);
1796 
1797       if (seqnum == qtdemux->segment_seqnum) {
1798         GST_LOG_OBJECT (pad,
1799             "Drop duplicated SEEK event seqnum %" G_GUINT32_FORMAT, seqnum);
1800         gst_event_unref (event);
1801         return TRUE;
1802       }
1803 
1804       if (qtdemux->upstream_format_is_time && qtdemux->fragmented) {
1805         /* seek should be handled by upstream, we might need to re-download fragments */
1806         GST_DEBUG_OBJECT (qtdemux,
1807             "let upstream handle seek for fragmented playback");
1808         goto upstream;
1809       }
1810 
1811       /* Build complete index for seeking;
1812        * if not a fragmented file at least */
1813       if (!qtdemux->fragmented)
1814         if (!qtdemux_ensure_index (qtdemux))
1815           goto index_failed;
1816 #ifndef GST_DISABLE_GST_DEBUG
1817       ts = gst_util_get_timestamp () - ts;
1818       GST_INFO_OBJECT (qtdemux,
1819           "Time taken to parse index %" GST_TIME_FORMAT, GST_TIME_ARGS (ts));
1820 #endif
1821     }
1822       if (qtdemux->pullbased) {
1823         res = gst_qtdemux_do_seek (qtdemux, pad, event);
1824       } else if (gst_pad_push_event (qtdemux->sinkpad, gst_event_ref (event))) {
1825         GST_DEBUG_OBJECT (qtdemux, "Upstream successfully seeked");
1826         res = TRUE;
1827       } else if (qtdemux->state == QTDEMUX_STATE_MOVIE && qtdemux->n_streams
1828           && !qtdemux->fragmented) {
1829         res = gst_qtdemux_do_push_seek (qtdemux, pad, event);
1830       } else {
1831         GST_DEBUG_OBJECT (qtdemux,
1832             "ignoring seek in push mode in current state");
1833         res = FALSE;
1834       }
1835       gst_event_unref (event);
1836       break;
1837     default:
1838     upstream:
1839       res = gst_pad_event_default (pad, parent, event);
1840       break;
1841   }
1842 
1843 done:
1844   return res;
1845 
1846   /* ERRORS */
1847 index_failed:
1848   {
1849     GST_ERROR_OBJECT (qtdemux, "Index failed");
1850     gst_event_unref (event);
1851     res = FALSE;
1852     goto done;
1853   }
1854 }
1855 
1856 /* Find, for each track, the first sample in coding order that has a file offset >= @byte_pos.
1857  *
1858  * If @fw is false, the coding order is explored backwards.
1859  *
1860  * If @set is true, each stream will be moved to its matched sample, or EOS if no matching
1861  * sample is found for that track.
1862  *
1863  * The stream and sample index of the sample with the minimum offset in the direction explored
1864  * (see @fw) is returned in the output parameters @_stream and @_index respectively.
1865  *
1866  * @_time is set to the QTSAMPLE_PTS of the matched sample with the minimum QTSAMPLE_PTS in the
1867  * direction explored, which may not always match the QTSAMPLE_PTS of the sample returned in
1868  * @_stream and @_index. */
1869 static void
1870 gst_qtdemux_find_sample (GstQTDemux * qtdemux, gint64 byte_pos, gboolean fw,
1871     gboolean set, QtDemuxStream ** _stream, gint * _index, gint64 * _time)
1872 {
1873   gint i, n, index;
1874   gint64 time, min_time;
1875   QtDemuxStream *stream;
1876 
1877   min_time = -1;
1878   stream = NULL;
1879   index = -1;
1880 
1881   for (n = 0; n < qtdemux->n_streams; ++n) {
1882     QtDemuxStream *str;
1883     gint inc;
1884     gboolean set_sample;
1885 
1886     str = qtdemux->streams[n];
1887     set_sample = !set;
1888 
1889     if (fw) {
1890       i = 0;
1891       inc = 1;
1892     } else {
1893       i = str->n_samples - 1;
1894       inc = -1;
1895     }
1896 
1897     for (; (i >= 0) && (i < str->n_samples); i += inc) {
1898       if (str->samples[i].size == 0)
1899         continue;
1900 
1901       if (fw && (str->samples[i].offset < byte_pos))
1902         continue;
1903 
1904       if (!fw && (str->samples[i].offset + str->samples[i].size > byte_pos))
1905         continue;
1906 
1907         /* move stream to first available sample */
1908         if (set) {
1909           gst_qtdemux_move_stream (qtdemux, str, i);
1910           set_sample = TRUE;
1911         }
1912 
1913       /* avoid index from sparse streams since they might be far away */
1914       if (!CUR_STREAM (str)->sparse) {
1915         /* determine min/max time */
1916         time = QTSAMPLE_PTS (str, &str->samples[i]);
1917         if (min_time == -1 || (!fw && time > min_time) ||
1918             (fw && time < min_time)) {
1919           min_time = time;
1920         }
1921 
1922         /* determine stream with leading sample, to get its position */
1923         if (!stream ||
1924             (fw && (str->samples[i].offset < stream->samples[index].offset)) ||
1925             (!fw && (str->samples[i].offset > stream->samples[index].offset))) {
1926           stream = str;
1927           index = i;
1928         }
1929       }
1930         break;
1931       }
1932 
1933     /* no sample for this stream, mark eos */
1934     if (!set_sample)
1935       gst_qtdemux_move_stream (qtdemux, str, str->n_samples);
1936   }
1937 
1938   if (_time)
1939     *_time = min_time;
1940   if (_stream)
1941     *_stream = stream;
1942   if (_index)
1943     *_index = index;
1944 }
1945 
1946 static QtDemuxStream *
1947 _create_stream (void)
1948 {
1949   QtDemuxStream *stream;
1950 
1951   stream = g_new0 (QtDemuxStream, 1);
1952   /* new streams always need a discont */
1953   stream->discont = TRUE;
1954   /* we enable clipping for raw audio/video streams */
1955   stream->need_clip = FALSE;
1956   stream->need_process = FALSE;
1957   stream->segment_index = -1;
1958   stream->time_position = 0;
1959   stream->sample_index = -1;
1960   stream->offset_in_sample = 0;
1961   stream->new_stream = TRUE;
1962   stream->multiview_mode = GST_VIDEO_MULTIVIEW_MODE_NONE;
1963   stream->multiview_flags = GST_VIDEO_MULTIVIEW_FLAGS_NONE;
1964   stream->protected = FALSE;
1965   stream->protection_scheme_type = 0;
1966   stream->protection_scheme_version = 0;
1967   stream->protection_scheme_info = NULL;
1968   stream->n_samples_moof = 0;
1969   stream->duration_moof = 0;
1970   stream->duration_last_moof = 0;
1971   stream->alignment = 1;
1972   stream->stream_tags = gst_tag_list_new_empty ();
1973   gst_tag_list_set_scope (stream->stream_tags, GST_TAG_SCOPE_STREAM);
1974   g_queue_init (&stream->protection_scheme_event_queue);
1975   return stream;
1976 }
1977 
1978 static gboolean
1979 gst_qtdemux_setcaps (GstQTDemux * demux, GstCaps * caps)
1980 {
1981   GstStructure *structure;
1982   const gchar *variant;
1983   const GstCaps *mediacaps = NULL;
1984 
1985   GST_DEBUG_OBJECT (demux, "Sink set caps: %" GST_PTR_FORMAT, caps);
1986 
1987   structure = gst_caps_get_structure (caps, 0);
1988   variant = gst_structure_get_string (structure, "variant");
1989 
1990   if (variant && strcmp (variant, "mss-fragmented") == 0) {
1991     QtDemuxStream *stream;
1992     const GValue *value;
1993 
1994     demux->fragmented = TRUE;
1995     demux->mss_mode = TRUE;
1996 
1997     if (demux->n_streams > 1) {
1998       /* can't do this, we can only renegotiate for another mss format */
1999       return FALSE;
2000     }
2001 
2002     value = gst_structure_get_value (structure, "media-caps");
2003     /* create stream */
2004     if (value) {
2005       const GValue *timescale_v;
2006 
2007       /* TODO update when stream changes during playback */
2008 
2009       if (demux->n_streams == 0) {
2010         stream = _create_stream ();
2011         demux->streams[demux->n_streams] = stream;
2012         demux->n_streams = 1;
2013         /* mss has no stsd/stsd entry, use id 0 as default */
2014         stream->stsd_entries_length = 1;
2015         stream->stsd_sample_description_id = stream->cur_stsd_entry_index = 0;
2016         stream->stsd_entries = g_new0 (QtDemuxStreamStsdEntry, 1);
2017       } else {
2018         stream = demux->streams[0];
2019       }
2020 
2021       timescale_v = gst_structure_get_value (structure, "timescale");
2022       if (timescale_v) {
2023         stream->timescale = g_value_get_uint64 (timescale_v);
2024       } else {
2025         /* default mss timescale */
2026         stream->timescale = 10000000;
2027       }
2028       demux->timescale = stream->timescale;
2029 
2030       mediacaps = gst_value_get_caps (value);
2031       if (!CUR_STREAM (stream)->caps
2032           || !gst_caps_is_equal_fixed (mediacaps, CUR_STREAM (stream)->caps)) {
2033         GST_DEBUG_OBJECT (demux, "We have a new caps %" GST_PTR_FORMAT,
2034             mediacaps);
2035         stream->new_caps = TRUE;
2036       }
2037       gst_caps_replace (&CUR_STREAM (stream)->caps, (GstCaps *) mediacaps);
2038       structure = gst_caps_get_structure (mediacaps, 0);
2039       if (g_str_has_prefix (gst_structure_get_name (structure), "video")) {
2040         stream->subtype = FOURCC_vide;
2041 
2042         gst_structure_get_int (structure, "width", &CUR_STREAM (stream)->width);
2043         gst_structure_get_int (structure, "height",
2044             &CUR_STREAM (stream)->height);
2045         gst_structure_get_fraction (structure, "framerate",
2046             &CUR_STREAM (stream)->fps_n, &CUR_STREAM (stream)->fps_d);
2047       } else if (g_str_has_prefix (gst_structure_get_name (structure), "audio")) {
2048         gint rate = 0;
2049         stream->subtype = FOURCC_soun;
2050         gst_structure_get_int (structure, "channels",
2051             &CUR_STREAM (stream)->n_channels);
2052         gst_structure_get_int (structure, "rate", &rate);
2053         CUR_STREAM (stream)->rate = rate;
2054       }
2055     }
2056     gst_caps_replace (&demux->media_caps, (GstCaps *) mediacaps);
2057   } else {
2058     demux->mss_mode = FALSE;
2059   }
2060 
2061   return TRUE;
2062 }
2063 
2064 static void
2065 gst_qtdemux_reset (GstQTDemux * qtdemux, gboolean hard)
2066 {
2067   gint n;
2068 
2069   GST_DEBUG_OBJECT (qtdemux, "Resetting demux");
2070   gst_pad_stop_task (qtdemux->sinkpad);
2071 
2072   if (hard || qtdemux->upstream_format_is_time) {
2073     qtdemux->state = QTDEMUX_STATE_INITIAL;
2074     qtdemux->neededbytes = 16;
2075     qtdemux->todrop = 0;
2076     qtdemux->pullbased = FALSE;
2077     qtdemux->posted_redirect = FALSE;
2078     qtdemux->first_mdat = -1;
2079     qtdemux->header_size = 0;
2080     qtdemux->mdatoffset = -1;
2081     qtdemux->restoredata_offset = -1;
2082     if (qtdemux->mdatbuffer)
2083       gst_buffer_unref (qtdemux->mdatbuffer);
2084     if (qtdemux->restoredata_buffer)
2085       gst_buffer_unref (qtdemux->restoredata_buffer);
2086     qtdemux->mdatbuffer = NULL;
2087     qtdemux->restoredata_buffer = NULL;
2088     qtdemux->mdatleft = 0;
2089     qtdemux->mdatsize = 0;
2090     if (qtdemux->comp_brands)
2091       gst_buffer_unref (qtdemux->comp_brands);
2092     qtdemux->comp_brands = NULL;
2093     qtdemux->last_moov_offset = -1;
2094     if (qtdemux->moov_node_compressed) {
2095       g_node_destroy (qtdemux->moov_node_compressed);
2096     if (qtdemux->moov_node)
2097         g_free (qtdemux->moov_node->data);
2098     }
2099     qtdemux->moov_node_compressed = NULL;
2100     if (qtdemux->moov_node)
2101       g_node_destroy (qtdemux->moov_node);
2102     qtdemux->moov_node = NULL;
2103     if (qtdemux->tag_list)
2104       gst_mini_object_unref (GST_MINI_OBJECT_CAST (qtdemux->tag_list));
2105     qtdemux->tag_list = gst_tag_list_new_empty ();
2106     gst_tag_list_set_scope (qtdemux->tag_list, GST_TAG_SCOPE_GLOBAL);
2107 #if 0
2108     if (qtdemux->element_index)
2109       gst_object_unref (qtdemux->element_index);
2110     qtdemux->element_index = NULL;
2111 #endif
2112     qtdemux->major_brand = 0;
2113     if (qtdemux->pending_newsegment)
2114       gst_event_unref (qtdemux->pending_newsegment);
2115     qtdemux->pending_newsegment = NULL;
2116     qtdemux->upstream_format_is_time = FALSE;
2117     qtdemux->upstream_seekable = FALSE;
2118     qtdemux->upstream_size = 0;
2119 
2120     qtdemux->fragment_start = -1;
2121     qtdemux->fragment_start_offset = -1;
2122     qtdemux->duration = 0;
2123     qtdemux->moof_offset = 0;
2124     qtdemux->chapters_track_id = 0;
2125     qtdemux->have_group_id = FALSE;
2126     qtdemux->group_id = G_MAXUINT;
2127 
2128     g_queue_foreach (&qtdemux->protection_event_queue, (GFunc) gst_event_unref,
2129         NULL);
2130     g_queue_clear (&qtdemux->protection_event_queue);
2131   }
2132   qtdemux->offset = 0;
2133   gst_adapter_clear (qtdemux->adapter);
2134   gst_segment_init (&qtdemux->segment, GST_FORMAT_TIME);
2135   qtdemux->segment_seqnum = GST_SEQNUM_INVALID;
2136 
2137   if (hard) {
2138     for (n = 0; n < qtdemux->n_streams; n++) {
2139       gst_qtdemux_stream_free (qtdemux, qtdemux->streams[n]);
2140       qtdemux->streams[n] = NULL;
2141     }
2142     qtdemux->n_streams = 0;
2143     qtdemux->n_video_streams = 0;
2144     qtdemux->n_audio_streams = 0;
2145     qtdemux->n_sub_streams = 0;
2146     qtdemux->exposed = FALSE;
2147     qtdemux->fragmented = FALSE;
2148     qtdemux->mss_mode = FALSE;
2149     gst_caps_replace (&qtdemux->media_caps, NULL);
2150     qtdemux->timescale = 0;
2151     qtdemux->got_moov = FALSE;
2152     if (qtdemux->protection_system_ids) {
2153       g_ptr_array_free (qtdemux->protection_system_ids, TRUE);
2154       qtdemux->protection_system_ids = NULL;
2155     }
2156   } else if (qtdemux->mss_mode) {
2157     gst_flow_combiner_reset (qtdemux->flowcombiner);
2158     for (n = 0; n < qtdemux->n_streams; n++)
2159       gst_qtdemux_stream_clear (qtdemux, qtdemux->streams[n]);
2160   } else {
2161     gst_flow_combiner_reset (qtdemux->flowcombiner);
2162     for (n = 0; n < qtdemux->n_streams; n++) {
2163       qtdemux->streams[n]->sent_eos = FALSE;
2164       qtdemux->streams[n]->time_position = 0;
2165       qtdemux->streams[n]->accumulated_base = 0;
2166     }
2167     if (!qtdemux->pending_newsegment) {
2168       qtdemux->pending_newsegment = gst_event_new_segment (&qtdemux->segment);
2169       if (qtdemux->segment_seqnum != GST_SEQNUM_INVALID)
2170         gst_event_set_seqnum (qtdemux->pending_newsegment,
2171             qtdemux->segment_seqnum);
2172   }
2173 }
2174 }
2175 
2176 
2177 /* Maps the @segment to the qt edts internal segments and pushes
2178  * the correspnding segment event.
2179  *
2180  * If it ends up being at a empty segment, a gap will be pushed and the next
2181  * edts segment will be activated in sequence.
2182  *
2183  * To be used in push-mode only */
2184 static void
2185 gst_qtdemux_map_and_push_segments (GstQTDemux * qtdemux, GstSegment * segment)
2186 {
2187   gint n, i;
2188 
2189   for (n = 0; n < qtdemux->n_streams; n++) {
2190     QtDemuxStream *stream = qtdemux->streams[n];
2191 
2192     stream->time_position = segment->start;
2193 
2194     /* in push mode we should be guaranteed that we will have empty segments
2195      * at the beginning and then one segment after, other scenarios are not
2196      * supported and are discarded when parsing the edts */
2197     for (i = 0; i < stream->n_segments; i++) {
2198       if (stream->segments[i].stop_time > segment->start) {
2199         gst_qtdemux_activate_segment (qtdemux, stream, i,
2200             stream->time_position);
2201         if (QTSEGMENT_IS_EMPTY (&stream->segments[i])) {
2202           /* push the empty segment and move to the next one */
2203           gst_qtdemux_send_gap_for_segment (qtdemux, stream, i,
2204               stream->time_position);
2205           continue;
2206         }
2207 
2208         g_assert (i == stream->n_segments - 1);
2209       }
2210     }
2211   }
2212 }
2213 
2214 static gboolean
2215 gst_qtdemux_handle_sink_event (GstPad * sinkpad, GstObject * parent,
2216     GstEvent * event)
2217 {
2218   GstQTDemux *demux = GST_QTDEMUX (parent);
2219   gboolean res = TRUE;
2220 
2221   GST_LOG_OBJECT (demux, "handling %s event", GST_EVENT_TYPE_NAME (event));
2222 
2223   switch (GST_EVENT_TYPE (event)) {
2224     case GST_EVENT_SEGMENT:
2225     {
2226       gint64 offset = 0;
2227       QtDemuxStream *stream;
2228       gint idx;
2229       GstSegment segment;
2230 
2231       /* some debug output */
2232       gst_event_copy_segment (event, &segment);
2233       GST_DEBUG_OBJECT (demux, "received newsegment %" GST_SEGMENT_FORMAT,
2234           &segment);
2235 
2236       /* erase any previously set segment */
2237       gst_event_replace (&demux->pending_newsegment, NULL);
2238 
2239       if (segment.format == GST_FORMAT_TIME) {
2240         GST_DEBUG_OBJECT (demux, "new pending_newsegment");
2241         gst_event_replace (&demux->pending_newsegment, event);
2242         demux->upstream_format_is_time = TRUE;
2243       } else {
2244         GST_DEBUG_OBJECT (demux, "Not storing upstream newsegment, "
2245             "not in time format");
2246 
2247       /* chain will send initial newsegment after pads have been added */
2248       if (demux->state != QTDEMUX_STATE_MOVIE || !demux->n_streams) {
2249         GST_DEBUG_OBJECT (demux, "still starting, eating event");
2250         goto exit;
2251       }
2252       }
2253 
2254       /* check if this matches a time seek we received previously
2255        * FIXME for backwards compatibility reasons we use the
2256        * seek_offset here to compare. In the future we might want to
2257        * change this to use the seqnum as it uniquely should identify
2258        * the segment that corresponds to the seek. */
2259       GST_DEBUG_OBJECT (demux, "Stored seek offset: %" G_GINT64_FORMAT
2260           ", received segment offset %" G_GINT64_FORMAT,
2261           demux->seek_offset, segment.start);
2262       if (segment.format == GST_FORMAT_BYTES
2263           && demux->seek_offset == segment.start) {
2264         GST_OBJECT_LOCK (demux);
2265         offset = segment.start;
2266 
2267         segment.format = GST_FORMAT_TIME;
2268         segment.start = demux->push_seek_start;
2269         segment.stop = demux->push_seek_stop;
2270         GST_DEBUG_OBJECT (demux, "Replaced segment with stored seek "
2271             "segment %" GST_TIME_FORMAT " - %" GST_TIME_FORMAT,
2272             GST_TIME_ARGS (segment.start), GST_TIME_ARGS (segment.stop));
2273           GST_OBJECT_UNLOCK (demux);
2274       }
2275 
2276       /* we only expect a BYTE segment, e.g. following a seek */
2277       if (segment.format == GST_FORMAT_BYTES) {
2278         if (GST_CLOCK_TIME_IS_VALID (segment.start)) {
2279           offset = segment.start;
2280 
2281           gst_qtdemux_find_sample (demux, segment.start, TRUE, FALSE, NULL,
2282               NULL, (gint64 *) & segment.start);
2283           if ((gint64) segment.start < 0)
2284             segment.start = 0;
2285           }
2286         if (GST_CLOCK_TIME_IS_VALID (segment.stop)) {
2287           gst_qtdemux_find_sample (demux, segment.stop, FALSE, FALSE, NULL,
2288               NULL, (gint64 *) & segment.stop);
2289           /* keyframe seeking should already arrange for start >= stop,
2290            * but make sure in other rare cases */
2291           segment.stop = MAX (segment.stop, segment.start);
2292         }
2293       } else if (segment.format == GST_FORMAT_TIME) {
2294         /* push all data on the adapter before starting this
2295          * new segment */
2296         gst_qtdemux_process_adapter (demux, TRUE);
2297       } else {
2298         GST_DEBUG_OBJECT (demux, "unsupported segment format, ignoring");
2299         goto exit;
2300       }
2301 
2302       /* We shouldn't modify upstream driven TIME FORMAT segment */
2303       if (!demux->upstream_format_is_time) {
2304       /* accept upstream's notion of segment and distribute along */
2305       segment.format = GST_FORMAT_TIME;
2306       segment.position = segment.time = segment.start;
2307       segment.duration = demux->segment.duration;
2308       segment.base = gst_segment_to_running_time (&demux->segment,
2309           GST_FORMAT_TIME, demux->segment.position);
2310       }
2311 
2312       gst_segment_copy_into (&segment, &demux->segment);
2313       GST_DEBUG_OBJECT (demux, "Pushing newseg %" GST_SEGMENT_FORMAT, &segment);
2314 
2315       /* map segment to internal qt segments and push on each stream */
2316       if (demux->n_streams) {
2317         if (demux->fragmented) {
2318           GstEvent *segment_event = gst_event_new_segment (&segment);
2319 
2320           gst_event_replace (&demux->pending_newsegment, NULL);
2321           gst_event_set_seqnum (segment_event, demux->segment_seqnum);
2322       gst_qtdemux_push_event (demux, segment_event);
2323         } else {
2324           gst_event_replace (&demux->pending_newsegment, NULL);
2325           gst_qtdemux_map_and_push_segments (demux, &segment);
2326         }
2327       }
2328 
2329       /* clear leftover in current segment, if any */
2330       gst_adapter_clear (demux->adapter);
2331 
2332       /* set up streaming thread */
2333       demux->offset = offset;
2334       if (demux->upstream_format_is_time) {
2335         GST_DEBUG_OBJECT (demux, "Upstream is driving in time format, "
2336             "set values to restart reading from a new atom");
2337         demux->neededbytes = 16;
2338         demux->todrop = 0;
2339       } else {
2340         gst_qtdemux_find_sample (demux, offset, TRUE, TRUE, &stream, &idx,
2341             NULL);
2342       if (stream) {
2343         demux->todrop = stream->samples[idx].offset - offset;
2344         demux->neededbytes = demux->todrop + stream->samples[idx].size;
2345       } else {
2346         /* set up for EOS */
2347         demux->neededbytes = -1;
2348         demux->todrop = 0;
2349       }
2350       }
2351     exit:
2352       gst_event_unref (event);
2353       res = TRUE;
2354       goto drop;
2355     }
2356     case GST_EVENT_FLUSH_START:
2357     {
2358       if (gst_event_get_seqnum (event) == demux->offset_seek_seqnum) {
2359         gst_event_unref (event);
2360         goto drop;
2361       }
2362       break;
2363     }
2364     case GST_EVENT_FLUSH_STOP:
2365     {
2366       guint64 dur;
2367 
2368       dur = demux->segment.duration;
2369       gst_qtdemux_reset (demux, FALSE);
2370       demux->segment.duration = dur;
2371 
2372       if (gst_event_get_seqnum (event) == demux->offset_seek_seqnum) {
2373         gst_event_unref (event);
2374         goto drop;
2375       }
2376       break;
2377     }
2378     case GST_EVENT_EOS:
2379       /* If we are in push mode, and get an EOS before we've seen any streams,
2380        * then error out - we have nowhere to send the EOS */
2381       if (!demux->pullbased) {
2382         gint i;
2383         gboolean has_valid_stream = FALSE;
2384         for (i = 0; i < demux->n_streams; i++) {
2385           if (demux->streams[i]->pad != NULL) {
2386             has_valid_stream = TRUE;
2387             break;
2388           }
2389         }
2390         if (!has_valid_stream)
2391           gst_qtdemux_post_no_playable_stream_error (demux);
2392         else {
2393           GST_DEBUG_OBJECT (demux, "Data still available after EOS: %u",
2394               (guint) gst_adapter_available (demux->adapter));
2395           if (gst_qtdemux_process_adapter (demux, TRUE) != GST_FLOW_OK) {
2396             res = FALSE;
2397       }
2398         }
2399       }
2400       break;
2401     case GST_EVENT_CAPS:{
2402       GstCaps *caps = NULL;
2403 
2404       gst_event_parse_caps (event, &caps);
2405       gst_qtdemux_setcaps (demux, caps);
2406       res = TRUE;
2407       gst_event_unref (event);
2408       goto drop;
2409     }
2410     case GST_EVENT_PROTECTION:
2411     {
2412       const gchar *system_id = NULL;
2413 
2414       gst_event_parse_protection (event, &system_id, NULL, NULL);
2415       GST_DEBUG_OBJECT (demux, "Received protection event for system ID %s",
2416           system_id);
2417       gst_qtdemux_append_protection_system_id (demux, system_id);
2418       /* save the event for later, for source pads that have not been created */
2419       g_queue_push_tail (&demux->protection_event_queue, gst_event_ref (event));
2420       /* send it to all pads that already exist */
2421       gst_qtdemux_push_event (demux, event);
2422       res = TRUE;
2423       goto drop;
2424     }
2425     default:
2426       break;
2427   }
2428 
2429   res = gst_pad_event_default (demux->sinkpad, parent, event) & res;
2430 
2431 drop:
2432   return res;
2433 }
2434 
2435 #if 0
2436 static void
2437 gst_qtdemux_set_index (GstElement * element, GstIndex * index)
2438 {
2439   GstQTDemux *demux = GST_QTDEMUX (element);
2440 
2441   GST_OBJECT_LOCK (demux);
2442   if (demux->element_index)
2443     gst_object_unref (demux->element_index);
2444   if (index) {
2445     demux->element_index = gst_object_ref (index);
2446   } else {
2447     demux->element_index = NULL;
2448   }
2449   GST_OBJECT_UNLOCK (demux);
2450   /* object lock might be taken again */
2451   if (index)
2452     gst_index_get_writer_id (index, GST_OBJECT (element), &demux->index_id);
2453   GST_DEBUG_OBJECT (demux, "Set index %" GST_PTR_FORMAT "for writer id %d",
2454       demux->element_index, demux->index_id);
2455 }
2456 
2457 static GstIndex *
2458 gst_qtdemux_get_index (GstElement * element)
2459 {
2460   GstIndex *result = NULL;
2461   GstQTDemux *demux = GST_QTDEMUX (element);
2462 
2463   GST_OBJECT_LOCK (demux);
2464   if (demux->element_index)
2465     result = gst_object_ref (demux->element_index);
2466   GST_OBJECT_UNLOCK (demux);
2467 
2468   GST_DEBUG_OBJECT (demux, "Returning index %" GST_PTR_FORMAT, result);
2469 
2470   return result;
2471 }
2472 #endif
2473 
2474 static void
2475 gst_qtdemux_stbl_free (QtDemuxStream * stream)
2476 {
2477   g_free ((gpointer) stream->stco.data);
2478   stream->stco.data = NULL;
2479   g_free ((gpointer) stream->stsz.data);
2480   stream->stsz.data = NULL;
2481   g_free ((gpointer) stream->stsc.data);
2482   stream->stsc.data = NULL;
2483   g_free ((gpointer) stream->stts.data);
2484   stream->stts.data = NULL;
2485   g_free ((gpointer) stream->stss.data);
2486   stream->stss.data = NULL;
2487   g_free ((gpointer) stream->stps.data);
2488   stream->stps.data = NULL;
2489   g_free ((gpointer) stream->ctts.data);
2490   stream->ctts.data = NULL;
2491 }
2492 
2493 static void
2494 gst_qtdemux_stream_flush_segments_data (GstQTDemux * qtdemux,
2495     QtDemuxStream * stream)
2496 {
2497   g_free (stream->segments);
2498   stream->segments = NULL;
2499   stream->segment_index = -1;
2500   stream->accumulated_base = 0;
2501 }
2502 
2503 static void
2504 gst_qtdemux_stream_flush_samples_data (GstQTDemux * qtdemux,
2505     QtDemuxStream * stream)
2506 {
2507   g_free (stream->samples);
2508   stream->samples = NULL;
2509   gst_qtdemux_stbl_free (stream);
2510 
2511   /* fragments */
2512   g_free (stream->ra_entries);
2513   stream->ra_entries = NULL;
2514   stream->n_ra_entries = 0;
2515 
2516   stream->sample_index = -1;
2517   stream->stbl_index = -1;
2518   stream->n_samples = 0;
2519   stream->time_position = 0;
2520 
2521   stream->n_samples_moof = 0;
2522   stream->duration_moof = 0;
2523   stream->duration_last_moof = 0;
2524 }
2525 
2526 static void
2527 gst_qtdemux_stream_clear (GstQTDemux * qtdemux, QtDemuxStream * stream)
2528 {
2529   gint i;
2530   if (stream->allocator)
2531     gst_object_unref (stream->allocator);
2532   while (stream->buffers) {
2533     gst_buffer_unref (GST_BUFFER_CAST (stream->buffers->data));
2534     stream->buffers = g_slist_delete_link (stream->buffers, stream->buffers);
2535   }
2536   for (i = 0; i < stream->stsd_entries_length; i++) {
2537     QtDemuxStreamStsdEntry *entry = &stream->stsd_entries[i];
2538     if (entry->rgb8_palette) {
2539       gst_memory_unref (entry->rgb8_palette);
2540       entry->rgb8_palette = NULL;
2541   }
2542     entry->sparse = FALSE;
2543   }
2544 
2545   gst_tag_list_unref (stream->stream_tags);
2546   stream->stream_tags = gst_tag_list_new_empty ();
2547   gst_tag_list_set_scope (stream->stream_tags, GST_TAG_SCOPE_STREAM);
2548   g_free (stream->redirect_uri);
2549   stream->redirect_uri = NULL;
2550   stream->sent_eos = FALSE;
2551   stream->protected = FALSE;
2552   if (stream->protection_scheme_info) {
2553     if (stream->protection_scheme_type == FOURCC_cenc) {
2554       QtDemuxCencSampleSetInfo *info =
2555           (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
2556       if (info->default_properties)
2557         gst_structure_free (info->default_properties);
2558       if (info->crypto_info)
2559         g_ptr_array_free (info->crypto_info, TRUE);
2560 }
2561     g_free (stream->protection_scheme_info);
2562     stream->protection_scheme_info = NULL;
2563   }
2564   stream->protection_scheme_type = 0;
2565   stream->protection_scheme_version = 0;
2566   g_queue_foreach (&stream->protection_scheme_event_queue,
2567       (GFunc) gst_event_unref, NULL);
2568   g_queue_clear (&stream->protection_scheme_event_queue);
2569   gst_qtdemux_stream_flush_segments_data (qtdemux, stream);
2570   gst_qtdemux_stream_flush_samples_data (qtdemux, stream);
2571 }
2572 
2573 static void
2574 gst_qtdemux_stream_reset (GstQTDemux * qtdemux, QtDemuxStream * stream)
2575 {
2576   gint i;
2577   gst_qtdemux_stream_clear (qtdemux, stream);
2578   for (i = 0; i < stream->stsd_entries_length; i++) {
2579     QtDemuxStreamStsdEntry *entry = &stream->stsd_entries[i];
2580     if (entry->caps) {
2581       gst_caps_unref (entry->caps);
2582       entry->caps = NULL;
2583     }
2584   }
2585   g_free (stream->stsd_entries);
2586   stream->stsd_entries = NULL;
2587   stream->stsd_entries_length = 0;
2588 }
2589 
2590 
2591 static void
2592 gst_qtdemux_stream_free (GstQTDemux * qtdemux, QtDemuxStream * stream)
2593 {
2594   gst_qtdemux_stream_reset (qtdemux, stream);
2595   gst_tag_list_unref (stream->stream_tags);
2596   if (stream->pad) {
2597     gst_element_remove_pad (GST_ELEMENT_CAST (qtdemux), stream->pad);
2598     gst_flow_combiner_remove_pad (qtdemux->flowcombiner, stream->pad);
2599   }
2600   g_free (stream);
2601 }
2602 
2603 static void
2604 gst_qtdemux_remove_stream (GstQTDemux * qtdemux, int i)
2605 {
2606   g_assert (i >= 0 && i < qtdemux->n_streams && qtdemux->streams[i] != NULL);
2607 
2608   gst_qtdemux_stream_free (qtdemux, qtdemux->streams[i]);
2609   qtdemux->streams[i] = qtdemux->streams[qtdemux->n_streams - 1];
2610   qtdemux->streams[qtdemux->n_streams - 1] = NULL;
2611   qtdemux->n_streams--;
2612 }
2613 
2614 static GstStateChangeReturn
2615 gst_qtdemux_change_state (GstElement * element, GstStateChange transition)
2616 {
2617   GstQTDemux *qtdemux = GST_QTDEMUX (element);
2618   GstStateChangeReturn result = GST_STATE_CHANGE_FAILURE;
2619 
2620   switch (transition) {
2621     case GST_STATE_CHANGE_PAUSED_TO_READY:
2622       break;
2623     default:
2624       break;
2625   }
2626 
2627   result = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
2628 
2629   switch (transition) {
2630     case GST_STATE_CHANGE_PAUSED_TO_READY:{
2631       gst_qtdemux_reset (qtdemux, TRUE);
2632       break;
2633     }
2634     default:
2635       break;
2636   }
2637 
2638   return result;
2639 }
2640 
2641 static void
2642 qtdemux_parse_ftyp (GstQTDemux * qtdemux, const guint8 * buffer, gint length)
2643 {
2644   /* counts as header data */
2645   qtdemux->header_size += length;
2646 
2647   /* only consider at least a sufficiently complete ftyp atom */
2648   if (length >= 20) {
2649     GstBuffer *buf;
2650 
2651     qtdemux->major_brand = QT_FOURCC (buffer + 8);
2652     GST_DEBUG_OBJECT (qtdemux, "major brand: %" GST_FOURCC_FORMAT,
2653         GST_FOURCC_ARGS (qtdemux->major_brand));
2654     if (qtdemux->comp_brands)
2655       gst_buffer_unref (qtdemux->comp_brands);
2656     buf = qtdemux->comp_brands = gst_buffer_new_and_alloc (length - 16);
2657     gst_buffer_fill (buf, 0, buffer + 16, length - 16);
2658   }
2659 }
2660 
2661 static void
2662 qtdemux_handle_xmp_taglist (GstQTDemux * qtdemux, GstTagList * taglist,
2663     GstTagList * xmptaglist)
2664 {
2665   /* Strip out bogus fields */
2666   if (xmptaglist) {
2667     if (gst_tag_list_get_scope (taglist) == GST_TAG_SCOPE_GLOBAL) {
2668       gst_tag_list_remove_tag (xmptaglist, GST_TAG_VIDEO_CODEC);
2669       gst_tag_list_remove_tag (xmptaglist, GST_TAG_AUDIO_CODEC);
2670     } else {
2671       gst_tag_list_remove_tag (xmptaglist, GST_TAG_CONTAINER_FORMAT);
2672     }
2673 
2674     GST_DEBUG_OBJECT (qtdemux, "Found XMP tags %" GST_PTR_FORMAT, xmptaglist);
2675 
2676       /* prioritize native tags using _KEEP mode */
2677     gst_tag_list_insert (taglist, xmptaglist, GST_TAG_MERGE_KEEP);
2678     gst_tag_list_unref (xmptaglist);
2679   }
2680 }
2681 
2682 static void
2683 qtdemux_parse_piff (GstQTDemux * qtdemux, const guint8 * buffer, gint length,
2684     guint offset)
2685 {
2686   GstByteReader br;
2687   guint8 version;
2688   guint32 flags = 0;
2689   guint i;
2690   guint8 iv_size = 8;
2691   QtDemuxStream *stream;
2692   GstStructure *structure;
2693   QtDemuxCencSampleSetInfo *ss_info = NULL;
2694   const gchar *system_id;
2695   gboolean uses_sub_sample_encryption = FALSE;
2696   guint32 sample_count;
2697 
2698   if (qtdemux->n_streams == 0)
2699     return;
2700 
2701   stream = qtdemux->streams[0];
2702 
2703   structure = gst_caps_get_structure (CUR_STREAM (stream)->caps, 0);
2704   if (!gst_structure_has_name (structure, "application/x-cenc")) {
2705     GST_WARNING_OBJECT (qtdemux,
2706         "Attempting PIFF box parsing on an unencrypted stream.");
2707     return;
2708   }
2709 
2710   gst_structure_get (structure, GST_PROTECTION_SYSTEM_ID_CAPS_FIELD,
2711       G_TYPE_STRING, &system_id, NULL);
2712   gst_qtdemux_append_protection_system_id (qtdemux, system_id);
2713 
2714   stream->protected = TRUE;
2715   stream->protection_scheme_type = FOURCC_cenc;
2716 
2717   if (!stream->protection_scheme_info)
2718     stream->protection_scheme_info = g_new0 (QtDemuxCencSampleSetInfo, 1);
2719 
2720   ss_info = (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
2721 
2722   if (ss_info->default_properties)
2723     gst_structure_free (ss_info->default_properties);
2724 
2725   ss_info->default_properties =
2726       gst_structure_new ("application/x-cenc",
2727       "iv_size", G_TYPE_UINT, iv_size, "encrypted", G_TYPE_BOOLEAN, TRUE, NULL);
2728 
2729   if (ss_info->crypto_info) {
2730     GST_LOG_OBJECT (qtdemux, "unreffing existing crypto_info");
2731     g_ptr_array_free (ss_info->crypto_info, TRUE);
2732     ss_info->crypto_info = NULL;
2733   }
2734 
2735   /* skip UUID */
2736   gst_byte_reader_init (&br, buffer + offset + 16, length - offset - 16);
2737 
2738   if (!gst_byte_reader_get_uint8 (&br, &version)) {
2739     GST_ERROR_OBJECT (qtdemux, "Error getting box's version field");
2740     return;
2741   }
2742 
2743   if (!gst_byte_reader_get_uint24_be (&br, &flags)) {
2744     GST_ERROR_OBJECT (qtdemux, "Error getting box's flags field");
2745     return;
2746   }
2747 
2748   if ((flags & 0x000001)) {
2749     guint32 algorithm_id = 0;
2750     const guint8 *kid;
2751     GstBuffer *kid_buf;
2752     gboolean is_encrypted = TRUE;
2753 
2754     if (!gst_byte_reader_get_uint24_le (&br, &algorithm_id)) {
2755       GST_ERROR_OBJECT (qtdemux, "Error getting box's algorithm ID field");
2756       return;
2757     }
2758 
2759     algorithm_id >>= 8;
2760     if (algorithm_id == 0) {
2761       is_encrypted = FALSE;
2762     } else if (algorithm_id == 1) {
2763       /* FIXME: maybe store this in properties? */
2764       GST_DEBUG_OBJECT (qtdemux, "AES 128-bits CTR encrypted stream");
2765     } else if (algorithm_id == 2) {
2766       /* FIXME: maybe store this in properties? */
2767       GST_DEBUG_OBJECT (qtdemux, "AES 128-bits CBC encrypted stream");
2768     }
2769 
2770     if (!gst_byte_reader_get_uint8 (&br, &iv_size))
2771       return;
2772 
2773     if (!gst_byte_reader_get_data (&br, 16, &kid))
2774       return;
2775 
2776     kid_buf = gst_buffer_new_allocate (NULL, 16, NULL);
2777     gst_buffer_fill (kid_buf, 0, kid, 16);
2778     if (ss_info->default_properties)
2779       gst_structure_free (ss_info->default_properties);
2780     ss_info->default_properties =
2781         gst_structure_new ("application/x-cenc",
2782         "iv_size", G_TYPE_UINT, iv_size,
2783         "encrypted", G_TYPE_BOOLEAN, is_encrypted,
2784         "kid", GST_TYPE_BUFFER, kid_buf, NULL);
2785     GST_DEBUG_OBJECT (qtdemux, "default sample properties: "
2786         "is_encrypted=%u, iv_size=%u", is_encrypted, iv_size);
2787     gst_buffer_unref (kid_buf);
2788   } else if ((flags & 0x000002)) {
2789     uses_sub_sample_encryption = TRUE;
2790   }
2791 
2792   if (!gst_byte_reader_get_uint32_be (&br, &sample_count)) {
2793     GST_ERROR_OBJECT (qtdemux, "Error getting box's sample count field");
2794     return;
2795   }
2796 
2797   ss_info->crypto_info =
2798       g_ptr_array_new_full (sample_count,
2799       (GDestroyNotify) qtdemux_gst_structure_free);
2800 
2801   for (i = 0; i < sample_count; ++i) {
2802     GstStructure *properties;
2803     guint8 *data;
2804     GstBuffer *buf;
2805 
2806     properties = qtdemux_get_cenc_sample_properties (qtdemux, stream, i);
2807     if (properties == NULL) {
2808       GST_ERROR_OBJECT (qtdemux, "failed to get properties for sample %u", i);
2809       qtdemux->cenc_aux_sample_count = i;
2810       return;
2811     }
2812 
2813     if (!gst_byte_reader_dup_data (&br, iv_size, &data)) {
2814       GST_ERROR_OBJECT (qtdemux, "IV data not present for sample %u", i);
2815       gst_structure_free (properties);
2816       qtdemux->cenc_aux_sample_count = i;
2817       return;
2818     }
2819     buf = gst_buffer_new_wrapped (data, iv_size);
2820     gst_structure_set (properties, "iv", GST_TYPE_BUFFER, buf, NULL);
2821     gst_buffer_unref (buf);
2822 
2823     if (uses_sub_sample_encryption) {
2824       guint16 n_subsamples;
2825 
2826       if (!gst_byte_reader_get_uint16_be (&br, &n_subsamples)
2827           || n_subsamples == 0) {
2828         GST_ERROR_OBJECT (qtdemux,
2829             "failed to get subsample count for sample %u", i);
2830         gst_structure_free (properties);
2831         qtdemux->cenc_aux_sample_count = i;
2832         return;
2833       }
2834       GST_LOG_OBJECT (qtdemux, "subsample count: %u", n_subsamples);
2835       if (!gst_byte_reader_dup_data (&br, n_subsamples * 6, &data)) {
2836         GST_ERROR_OBJECT (qtdemux, "failed to get subsample data for sample %u",
2837             i);
2838         gst_structure_free (properties);
2839         qtdemux->cenc_aux_sample_count = i;
2840         return;
2841       }
2842       buf = gst_buffer_new_wrapped (data, n_subsamples * 6);
2843       gst_structure_set (properties,
2844           "subsample_count", G_TYPE_UINT, n_subsamples,
2845           "subsamples", GST_TYPE_BUFFER, buf, NULL);
2846       gst_buffer_unref (buf);
2847     } else {
2848       gst_structure_set (properties, "subsample_count", G_TYPE_UINT, 0, NULL);
2849     }
2850 
2851     g_ptr_array_add (ss_info->crypto_info, properties);
2852   }
2853 
2854   qtdemux->cenc_aux_sample_count = sample_count;
2855 }
2856 
2857 static void
2858 qtdemux_parse_uuid (GstQTDemux * qtdemux, const guint8 * buffer, gint length)
2859 {
2860   static const guint8 xmp_uuid[] = { 0xBE, 0x7A, 0xCF, 0xCB,
2861     0x97, 0xA9, 0x42, 0xE8,
2862     0x9C, 0x71, 0x99, 0x94,
2863     0x91, 0xE3, 0xAF, 0xAC
2864   };
2865   static const guint8 playready_uuid[] = {
2866     0xd0, 0x8a, 0x4f, 0x18, 0x10, 0xf3, 0x4a, 0x82,
2867     0xb6, 0xc8, 0x32, 0xd8, 0xab, 0xa1, 0x83, 0xd3
2868   };
2869 
2870   static const guint8 piff_sample_encryption_uuid[] = {
2871     0xa2, 0x39, 0x4f, 0x52, 0x5a, 0x9b, 0x4f, 0x14,
2872     0xa2, 0x44, 0x6c, 0x42, 0x7c, 0x64, 0x8d, 0xf4
2873   };
2874 
2875   guint offset;
2876 
2877   /* counts as header data */
2878   qtdemux->header_size += length;
2879 
2880   offset = (QT_UINT32 (buffer) == 0) ? 16 : 8;
2881 
2882   if (length <= offset + 16) {
2883     GST_DEBUG_OBJECT (qtdemux, "uuid atom is too short, skipping");
2884     return;
2885   }
2886 
2887 #ifndef GSTREAMER_LITE
2888   if (memcmp (buffer + offset, xmp_uuid, 16) == 0) {
2889     GstBuffer *buf;
2890     GstTagList *taglist;
2891 
2892     buf = _gst_buffer_new_wrapped ((guint8 *) buffer + offset + 16,
2893         length - offset - 16, NULL);
2894     taglist = gst_tag_list_from_xmp_buffer (buf);
2895     gst_buffer_unref (buf);
2896 
2897     /* make sure we have a usable taglist */
2898     qtdemux->tag_list = gst_tag_list_make_writable (qtdemux->tag_list);
2899 
2900     qtdemux_handle_xmp_taglist (qtdemux, qtdemux->tag_list, taglist);
2901 
2902   } else if (memcmp (buffer + offset, playready_uuid, 16) == 0) {
2903     int len;
2904     const gunichar2 *s_utf16;
2905     char *contents;
2906 
2907     len = GST_READ_UINT16_LE (buffer + offset + 0x30);
2908     s_utf16 = (const gunichar2 *) (buffer + offset + 0x32);
2909     contents = g_utf16_to_utf8 (s_utf16, len / 2, NULL, NULL, NULL);
2910     GST_ERROR_OBJECT (qtdemux, "contents: %s", contents);
2911 
2912     g_free (contents);
2913 
2914     GST_ELEMENT_ERROR (qtdemux, STREAM, DECRYPT,
2915         (_("Cannot play stream because it is encrypted with PlayReady DRM.")),
2916         (NULL));
2917   } else if (memcmp (buffer + offset, piff_sample_encryption_uuid, 16) == 0) {
2918     qtdemux_parse_piff (qtdemux, buffer, length, offset);
2919   } else {
2920     GST_DEBUG_OBJECT (qtdemux, "Ignoring unknown uuid: %08x-%08x-%08x-%08x",
2921         GST_READ_UINT32_LE (buffer + offset),
2922         GST_READ_UINT32_LE (buffer + offset + 4),
2923         GST_READ_UINT32_LE (buffer + offset + 8),
2924         GST_READ_UINT32_LE (buffer + offset + 12));
2925   }
2926 #endif // GSTREAMER_LITE
2927 }
2928 
2929 static void
2930 qtdemux_parse_sidx (GstQTDemux * qtdemux, const guint8 * buffer, gint length)
2931 {
2932   GstSidxParser sidx_parser;
2933   GstIsoffParserResult res;
2934   guint consumed;
2935 
2936   gst_isoff_qt_sidx_parser_init (&sidx_parser);
2937 
2938   res =
2939       gst_isoff_qt_sidx_parser_add_data (&sidx_parser, buffer, length,
2940       &consumed);
2941   GST_DEBUG_OBJECT (qtdemux, "sidx parse result: %d", res);
2942   if (res == GST_ISOFF_QT_PARSER_DONE) {
2943     check_update_duration (qtdemux, sidx_parser.cumulative_pts);
2944   }
2945   gst_isoff_qt_sidx_parser_clear (&sidx_parser);
2946 }
2947 
2948 /* caller verifies at least 8 bytes in buf */
2949 static void
2950 extract_initial_length_and_fourcc (const guint8 * data, guint size,
2951     guint64 * plength, guint32 * pfourcc)
2952 {
2953   guint64 length;
2954   guint32 fourcc;
2955 
2956   length = QT_UINT32 (data);
2957   GST_DEBUG ("length 0x%08" G_GINT64_MODIFIER "x", length);
2958   fourcc = QT_FOURCC (data + 4);
2959   GST_DEBUG ("atom type %" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (fourcc));
2960 
2961   if (length == 0) {
2962     length = G_MAXUINT64;
2963   } else if (length == 1 && size >= 16) {
2964     /* this means we have an extended size, which is the 64 bit value of
2965      * the next 8 bytes */
2966     length = QT_UINT64 (data + 8);
2967     GST_DEBUG ("length 0x%08" G_GINT64_MODIFIER "x", length);
2968   }
2969 
2970   if (plength)
2971     *plength = length;
2972   if (pfourcc)
2973     *pfourcc = fourcc;
2974 }
2975 
2976 static gboolean
2977 qtdemux_parse_mehd (GstQTDemux * qtdemux, GstByteReader * br)
2978 {
2979   guint32 version = 0;
2980   GstClockTime duration = 0;
2981 
2982   if (!gst_byte_reader_get_uint32_be (br, &version))
2983     goto failed;
2984 
2985   version >>= 24;
2986   if (version == 1) {
2987     if (!gst_byte_reader_get_uint64_be (br, &duration))
2988       goto failed;
2989   } else {
2990     guint32 dur = 0;
2991 
2992     if (!gst_byte_reader_get_uint32_be (br, &dur))
2993       goto failed;
2994     duration = dur;
2995   }
2996 
2997   GST_INFO_OBJECT (qtdemux, "mehd duration: %" G_GUINT64_FORMAT, duration);
2998   qtdemux->duration = duration;
2999 
3000   return TRUE;
3001 
3002 failed:
3003   {
3004     GST_DEBUG_OBJECT (qtdemux, "parsing mehd failed");
3005     return FALSE;
3006   }
3007 }
3008 
3009 static gboolean
3010 qtdemux_parse_trex (GstQTDemux * qtdemux, QtDemuxStream * stream,
3011     guint32 * ds_duration, guint32 * ds_size, guint32 * ds_flags)
3012 {
3013   if (!stream->parsed_trex && qtdemux->moov_node) {
3014     GNode *mvex, *trex;
3015     GstByteReader trex_data;
3016 
3017     mvex = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_mvex);
3018     if (mvex) {
3019       trex = qtdemux_tree_get_child_by_type_full (mvex, FOURCC_trex,
3020           &trex_data);
3021       while (trex) {
3022         guint32 id = 0, sdi = 0, dur = 0, size = 0, flags = 0;
3023 
3024         /* skip version/flags */
3025         if (!gst_byte_reader_skip (&trex_data, 4))
3026           goto next;
3027         if (!gst_byte_reader_get_uint32_be (&trex_data, &id))
3028           goto next;
3029         if (id != stream->track_id)
3030           goto next;
3031         if (!gst_byte_reader_get_uint32_be (&trex_data, &sdi))
3032           goto next;
3033         if (!gst_byte_reader_get_uint32_be (&trex_data, &dur))
3034           goto next;
3035         if (!gst_byte_reader_get_uint32_be (&trex_data, &size))
3036           goto next;
3037         if (!gst_byte_reader_get_uint32_be (&trex_data, &flags))
3038           goto next;
3039 
3040         GST_DEBUG_OBJECT (qtdemux, "fragment defaults for stream %d; "
3041             "duration %d,  size %d, flags 0x%x", stream->track_id,
3042             dur, size, flags);
3043 
3044         stream->parsed_trex = TRUE;
3045         stream->def_sample_description_index = sdi;
3046         stream->def_sample_duration = dur;
3047         stream->def_sample_size = size;
3048         stream->def_sample_flags = flags;
3049 
3050       next:
3051         /* iterate all siblings */
3052         trex = qtdemux_tree_get_sibling_by_type_full (trex, FOURCC_trex,
3053             &trex_data);
3054       }
3055     }
3056   }
3057 
3058   *ds_duration = stream->def_sample_duration;
3059   *ds_size = stream->def_sample_size;
3060   *ds_flags = stream->def_sample_flags;
3061 
3062   /* even then, above values are better than random ... */
3063   if (G_UNLIKELY (!stream->parsed_trex)) {
3064     GST_WARNING_OBJECT (qtdemux,
3065         "failed to find fragment defaults for stream %d", stream->track_id);
3066     return FALSE;
3067   }
3068 
3069   return TRUE;
3070 }
3071 
3072 /* This method should be called whenever a more accurate duration might
3073  * have been found. It will update all relevant variables if/where needed
3074  */
3075 static void
3076 check_update_duration (GstQTDemux * qtdemux, GstClockTime duration)
3077 {
3078   guint i;
3079   guint64 movdur;
3080   GstClockTime prevdur;
3081 
3082   movdur = GSTTIME_TO_QTTIME (qtdemux, duration);
3083 
3084   if (movdur > qtdemux->duration) {
3085     prevdur = QTTIME_TO_GSTTIME (qtdemux, qtdemux->duration);
3086     GST_DEBUG_OBJECT (qtdemux,
3087         "Updating total duration to %" GST_TIME_FORMAT " was %" GST_TIME_FORMAT,
3088         GST_TIME_ARGS (duration), GST_TIME_ARGS (prevdur));
3089     qtdemux->duration = movdur;
3090     GST_DEBUG_OBJECT (qtdemux,
3091         "qtdemux->segment.duration: %" GST_TIME_FORMAT " .stop: %"
3092         GST_TIME_FORMAT, GST_TIME_ARGS (qtdemux->segment.duration),
3093         GST_TIME_ARGS (qtdemux->segment.stop));
3094     if (qtdemux->segment.duration == prevdur) {
3095       /* If the current segment has duration/stop identical to previous duration
3096        * update them also (because they were set at that point in time with
3097        * the wrong duration */
3098       /* We convert the value *from* the timescale version to avoid rounding errors */
3099       GstClockTime fixeddur = QTTIME_TO_GSTTIME (qtdemux, movdur);
3100       GST_DEBUG_OBJECT (qtdemux, "Updated segment.duration and segment.stop");
3101       qtdemux->segment.duration = fixeddur;
3102       qtdemux->segment.stop = fixeddur;
3103     }
3104   }
3105   for (i = 0; i < qtdemux->n_streams; i++) {
3106     QtDemuxStream *stream = qtdemux->streams[i];
3107     if (stream) {
3108       movdur = GSTTIME_TO_QTSTREAMTIME (stream, duration);
3109       if (movdur > stream->duration) {
3110         GST_DEBUG_OBJECT (qtdemux,
3111             "Updating stream #%d duration to %" GST_TIME_FORMAT, i,
3112             GST_TIME_ARGS (duration));
3113         stream->duration = movdur;
3114         /* internal duration tracking state has been updated above, so */
3115         /* preserve an open-ended dummy segment rather than repeatedly updating
3116          * it and spamming downstream accordingly with segment events */
3117         if (stream->dummy_segment &&
3118             GST_CLOCK_TIME_IS_VALID (stream->segments[0].duration)) {
3119           /* Update all dummy values to new duration */
3120           stream->segments[0].stop_time = duration;
3121           stream->segments[0].duration = duration;
3122           stream->segments[0].media_stop = duration;
3123 
3124           /* let downstream know we possibly have a new stop time */
3125           if (stream->segment_index != -1) {
3126             GstClockTime pos;
3127 
3128             if (qtdemux->segment.rate >= 0) {
3129               pos = stream->segment.start;
3130             } else {
3131               pos = stream->segment.stop;
3132             }
3133 
3134             gst_qtdemux_stream_update_segment (qtdemux, stream,
3135                 stream->segment_index, pos, NULL, NULL);
3136           }
3137         }
3138       }
3139     }
3140   }
3141 }
3142 
3143 static gboolean
3144 qtdemux_parse_trun (GstQTDemux * qtdemux, GstByteReader * trun,
3145     QtDemuxStream * stream, guint32 d_sample_duration, guint32 d_sample_size,
3146     guint32 d_sample_flags, gint64 moof_offset, gint64 moof_length,
3147     gint64 * base_offset, gint64 * running_offset, gint64 decode_ts,
3148     gboolean has_tfdt)
3149 {
3150   GstClockTime gst_ts = GST_CLOCK_TIME_NONE;
3151   guint64 timestamp;
3152   gint32 data_offset = 0;
3153   guint32 flags = 0, first_flags = 0, samples_count = 0;
3154   gint i;
3155   guint8 *data;
3156   guint entry_size, dur_offset, size_offset, flags_offset = 0, ct_offset = 0;
3157   QtDemuxSample *sample;
3158   gboolean ismv = FALSE;
3159   gint64 initial_offset;
3160 
3161   GST_LOG_OBJECT (qtdemux, "parsing trun stream %d; "
3162       "default dur %d, size %d, flags 0x%x, base offset %" G_GINT64_FORMAT ", "
3163       "decode ts %" G_GINT64_FORMAT, stream->track_id, d_sample_duration,
3164       d_sample_size, d_sample_flags, *base_offset, decode_ts);
3165 
3166   if (stream->pending_seek && moof_offset < stream->pending_seek->moof_offset) {
3167     GST_INFO_OBJECT (stream->pad, "skipping trun before seek target fragment");
3168     return TRUE;
3169   }
3170 
3171   /* presence of stss or not can't really tell us much,
3172    * and flags and so on tend to be marginally reliable in these files */
3173   if (stream->subtype == FOURCC_soun) {
3174     GST_DEBUG_OBJECT (qtdemux,
3175         "sound track in fragmented file; marking all keyframes");
3176     stream->all_keyframe = TRUE;
3177   }
3178 
3179   if (!gst_byte_reader_skip (trun, 1) ||
3180       !gst_byte_reader_get_uint24_be (trun, &flags))
3181     goto fail;
3182 
3183   if (!gst_byte_reader_get_uint32_be (trun, &samples_count))
3184     goto fail;
3185 
3186   if (flags & TR_DATA_OFFSET) {
3187     /* note this is really signed */
3188     if (!gst_byte_reader_get_int32_be (trun, &data_offset))
3189       goto fail;
3190     GST_LOG_OBJECT (qtdemux, "trun data offset %d", data_offset);
3191     /* default base offset = first byte of moof */
3192     if (*base_offset == -1) {
3193       GST_LOG_OBJECT (qtdemux, "base_offset at moof");
3194       *base_offset = moof_offset;
3195     }
3196     *running_offset = *base_offset + data_offset;
3197   } else {
3198     /* if no offset at all, that would mean data starts at moof start,
3199      * which is a bit wrong and is ismv crappy way, so compensate
3200      * assuming data is in mdat following moof */
3201     if (*base_offset == -1) {
3202       *base_offset = moof_offset + moof_length + 8;
3203       GST_LOG_OBJECT (qtdemux, "base_offset assumed in mdat after moof");
3204       ismv = TRUE;
3205     }
3206     if (*running_offset == -1)
3207       *running_offset = *base_offset;
3208   }
3209 
3210   GST_LOG_OBJECT (qtdemux, "running offset now %" G_GINT64_FORMAT,
3211       *running_offset);
3212   GST_LOG_OBJECT (qtdemux, "trun offset %d, flags 0x%x, entries %d",
3213       data_offset, flags, samples_count);
3214 
3215   if (flags & TR_FIRST_SAMPLE_FLAGS) {
3216     if (G_UNLIKELY (flags & TR_SAMPLE_FLAGS)) {
3217       GST_DEBUG_OBJECT (qtdemux,
3218           "invalid flags; SAMPLE and FIRST_SAMPLE present, discarding latter");
3219       flags ^= TR_FIRST_SAMPLE_FLAGS;
3220     } else {
3221       if (!gst_byte_reader_get_uint32_be (trun, &first_flags))
3222         goto fail;
3223       GST_LOG_OBJECT (qtdemux, "first flags: 0x%x", first_flags);
3224     }
3225   }
3226 
3227   /* FIXME ? spec says other bits should also be checked to determine
3228    * entry size (and prefix size for that matter) */
3229   entry_size = 0;
3230   dur_offset = size_offset = 0;
3231   if (flags & TR_SAMPLE_DURATION) {
3232     GST_LOG_OBJECT (qtdemux, "entry duration present");
3233     dur_offset = entry_size;
3234     entry_size += 4;
3235   }
3236   if (flags & TR_SAMPLE_SIZE) {
3237     GST_LOG_OBJECT (qtdemux, "entry size present");
3238     size_offset = entry_size;
3239     entry_size += 4;
3240   }
3241   if (flags & TR_SAMPLE_FLAGS) {
3242     GST_LOG_OBJECT (qtdemux, "entry flags present");
3243     flags_offset = entry_size;
3244     entry_size += 4;
3245   }
3246   if (flags & TR_COMPOSITION_TIME_OFFSETS) {
3247     GST_LOG_OBJECT (qtdemux, "entry ct offset present");
3248     ct_offset = entry_size;
3249     entry_size += 4;
3250   }
3251 
3252   if (!qt_atom_parser_has_chunks (trun, samples_count, entry_size))
3253     goto fail;
3254   data = (guint8 *) gst_byte_reader_peek_data_unchecked (trun);
3255 
3256   if (stream->n_samples + samples_count >=
3257       QTDEMUX_MAX_SAMPLE_INDEX_SIZE / sizeof (QtDemuxSample))
3258     goto index_too_big;
3259 
3260   GST_DEBUG_OBJECT (qtdemux, "allocating n_samples %u * %u (%.2f MB)",
3261       stream->n_samples + samples_count, (guint) sizeof (QtDemuxSample),
3262       (stream->n_samples + samples_count) *
3263       sizeof (QtDemuxSample) / (1024.0 * 1024.0));
3264 
3265   /* create a new array of samples if it's the first sample parsed */
3266   if (stream->n_samples == 0) {
3267     g_assert (stream->samples == NULL);
3268     stream->samples = g_try_new0 (QtDemuxSample, samples_count);
3269   /* or try to reallocate it with space enough to insert the new samples */
3270   } else
3271     stream->samples = g_try_renew (QtDemuxSample, stream->samples,
3272         stream->n_samples + samples_count);
3273   if (stream->samples == NULL)
3274     goto out_of_memory;
3275 
3276   if (qtdemux->fragment_start != -1) {
3277     timestamp = GSTTIME_TO_QTSTREAMTIME (stream, qtdemux->fragment_start);
3278     qtdemux->fragment_start = -1;
3279   } else {
3280     if (stream->n_samples == 0) {
3281       if (decode_ts > 0) {
3282         timestamp = decode_ts;
3283       } else if (stream->pending_seek != NULL) {
3284         /* if we don't have a timestamp from a tfdt box, we'll use the one
3285          * from the mfra seek table */
3286         GST_INFO_OBJECT (stream->pad, "pending seek ts = %" GST_TIME_FORMAT,
3287             GST_TIME_ARGS (stream->pending_seek->ts));
3288 
3289         /* FIXME: this is not fully correct, the timestamp refers to the random
3290          * access sample refered to in the tfra entry, which may not necessarily
3291          * be the first sample in the tfrag/trun (but hopefully/usually is) */
3292         timestamp = GSTTIME_TO_QTSTREAMTIME (stream, stream->pending_seek->ts);
3293       } else {
3294     timestamp = 0;
3295       }
3296 
3297       gst_ts = QTSTREAMTIME_TO_GSTTIME (stream, timestamp);
3298       GST_INFO_OBJECT (stream->pad, "first sample ts %" GST_TIME_FORMAT,
3299           GST_TIME_ARGS (gst_ts));
3300   } else {
3301     /* subsequent fragments extend stream */
3302     timestamp =
3303         stream->samples[stream->n_samples - 1].timestamp +
3304         stream->samples[stream->n_samples - 1].duration;
3305 
3306       /* If this is a GST_FORMAT_BYTES stream and there's a significant
3307        * difference (1 sec.) between decode_ts and timestamp, prefer the
3308        * former */
3309       if (has_tfdt && !qtdemux->upstream_format_is_time
3310           && ABSDIFF (decode_ts, timestamp) >
3311           MAX (stream->duration_last_moof / 2,
3312               GSTTIME_TO_QTSTREAMTIME (stream, GST_SECOND))) {
3313         GST_INFO_OBJECT (qtdemux,
3314             "decode_ts (%" GST_TIME_FORMAT ") and timestamp (%" GST_TIME_FORMAT
3315             ") are significantly different (more than %" GST_TIME_FORMAT
3316             "), using decode_ts",
3317             GST_TIME_ARGS (QTSTREAMTIME_TO_GSTTIME (stream, decode_ts)),
3318             GST_TIME_ARGS (QTSTREAMTIME_TO_GSTTIME (stream, timestamp)),
3319             GST_TIME_ARGS (QTSTREAMTIME_TO_GSTTIME (stream,
3320                     MAX (stream->duration_last_moof / 2,
3321                         GSTTIME_TO_QTSTREAMTIME (stream, GST_SECOND)))));
3322         timestamp = decode_ts;
3323   }
3324 
3325       gst_ts = QTSTREAMTIME_TO_GSTTIME (stream, timestamp);
3326       GST_INFO_OBJECT (qtdemux, "first sample ts %" GST_TIME_FORMAT
3327           " (extends previous samples)", GST_TIME_ARGS (gst_ts));
3328   }
3329   }
3330 
3331   initial_offset = *running_offset;
3332 
3333   sample = stream->samples + stream->n_samples;
3334   for (i = 0; i < samples_count; i++) {
3335     guint32 dur, size, sflags, ct;
3336 
3337     /* first read sample data */
3338     if (flags & TR_SAMPLE_DURATION) {
3339       dur = QT_UINT32 (data + dur_offset);
3340     } else {
3341       dur = d_sample_duration;
3342     }
3343     if (flags & TR_SAMPLE_SIZE) {
3344       size = QT_UINT32 (data + size_offset);
3345     } else {
3346       size = d_sample_size;
3347     }
3348     if (flags & TR_FIRST_SAMPLE_FLAGS) {
3349       if (i == 0) {
3350         sflags = first_flags;
3351       } else {
3352         sflags = d_sample_flags;
3353       }
3354     } else if (flags & TR_SAMPLE_FLAGS) {
3355       sflags = QT_UINT32 (data + flags_offset);
3356     } else {
3357       sflags = d_sample_flags;
3358     }
3359     if (flags & TR_COMPOSITION_TIME_OFFSETS) {
3360       ct = QT_UINT32 (data + ct_offset);
3361     } else {
3362       ct = 0;
3363     }
3364     data += entry_size;
3365 
3366     /* fill the sample information */
3367     sample->offset = *running_offset;
3368     sample->pts_offset = ct;
3369     sample->size = size;
3370     sample->timestamp = timestamp;
3371     sample->duration = dur;
3372     /* sample-is-difference-sample */
3373     /* ismv seems to use 0x40 for keyframe, 0xc0 for non-keyframe,
3374      * now idea how it relates to bitfield other than massive LE/BE confusion */
3375     sample->keyframe = ismv ? ((sflags & 0xff) == 0x40) : !(sflags & 0x10000);
3376     *running_offset += size;
3377     timestamp += dur;
3378     stream->duration_moof += dur;
3379     sample++;
3380   }
3381 
3382   /* Update total duration if needed */
3383   check_update_duration (qtdemux, QTSTREAMTIME_TO_GSTTIME (stream, timestamp));
3384 
3385   /* Pre-emptively figure out size of mdat based on trun information.
3386    * If the [mdat] atom is effectivelly read, it will be replaced by the actual
3387    * size, else we will still be able to use this when dealing with gap'ed
3388    * input */
3389   qtdemux->mdatleft = *running_offset - initial_offset;
3390   qtdemux->mdatoffset = initial_offset;
3391   qtdemux->mdatsize = qtdemux->mdatleft;
3392 
3393   stream->n_samples += samples_count;
3394   stream->n_samples_moof += samples_count;
3395 
3396   if (stream->pending_seek != NULL)
3397     stream->pending_seek = NULL;
3398 
3399   return TRUE;
3400 
3401 fail:
3402   {
3403     GST_WARNING_OBJECT (qtdemux, "failed to parse trun");
3404     return FALSE;
3405   }
3406 out_of_memory:
3407   {
3408     GST_WARNING_OBJECT (qtdemux, "failed to allocate %d samples",
3409         stream->n_samples);
3410     return FALSE;
3411   }
3412 index_too_big:
3413   {
3414     GST_WARNING_OBJECT (qtdemux, "not allocating index of %d samples, would "
3415         "be larger than %uMB (broken file?)", stream->n_samples,
3416         QTDEMUX_MAX_SAMPLE_INDEX_SIZE >> 20);
3417     return FALSE;
3418   }
3419 }
3420 
3421 /* find stream with @id */
3422 static inline QtDemuxStream *
3423 qtdemux_find_stream (GstQTDemux * qtdemux, guint32 id)
3424 {
3425   QtDemuxStream *stream;
3426   gint i;
3427 
3428   /* check */
3429   if (G_UNLIKELY (!id)) {
3430     GST_DEBUG_OBJECT (qtdemux, "invalid track id 0");
3431     return NULL;
3432   }
3433 
3434   /* try to get it fast and simple */
3435   if (G_LIKELY (id <= qtdemux->n_streams)) {
3436     stream = qtdemux->streams[id - 1];
3437     if (G_LIKELY (stream->track_id == id))
3438       return stream;
3439   }
3440 
3441   /* linear search otherwise */
3442   for (i = 0; i < qtdemux->n_streams; i++) {
3443     stream = qtdemux->streams[i];
3444     if (stream->track_id == id)
3445       return stream;
3446   }
3447   if (qtdemux->mss_mode) {
3448     /* mss should have only 1 stream anyway */
3449     return qtdemux->streams[0];
3450   }
3451 
3452   return NULL;
3453 }
3454 
3455 static gboolean
3456 qtdemux_parse_mfhd (GstQTDemux * qtdemux, GstByteReader * mfhd,
3457     guint32 * fragment_number)
3458 {
3459   if (!gst_byte_reader_skip (mfhd, 4))
3460     goto fail;
3461   if (!gst_byte_reader_get_uint32_be (mfhd, fragment_number))
3462     goto fail;
3463   return TRUE;
3464 fail:
3465   {
3466     GST_WARNING_OBJECT (qtdemux, "Failed to parse mfhd atom");
3467     return FALSE;
3468   }
3469 }
3470 
3471 static gboolean
3472 qtdemux_parse_tfhd (GstQTDemux * qtdemux, GstByteReader * tfhd,
3473     QtDemuxStream ** stream, guint32 * default_sample_duration,
3474     guint32 * default_sample_size, guint32 * default_sample_flags,
3475     gint64 * base_offset)
3476 {
3477   guint32 flags = 0;
3478   guint32 track_id = 0;
3479 
3480   if (!gst_byte_reader_skip (tfhd, 1) ||
3481       !gst_byte_reader_get_uint24_be (tfhd, &flags))
3482     goto invalid_track;
3483 
3484   if (!gst_byte_reader_get_uint32_be (tfhd, &track_id))
3485     goto invalid_track;
3486 
3487   *stream = qtdemux_find_stream (qtdemux, track_id);
3488   if (G_UNLIKELY (!*stream))
3489     goto unknown_stream;
3490 
3491   if (flags & TF_DEFAULT_BASE_IS_MOOF)
3492     *base_offset = qtdemux->moof_offset;
3493 
3494   if (flags & TF_BASE_DATA_OFFSET)
3495     if (!gst_byte_reader_get_uint64_be (tfhd, (guint64 *) base_offset))
3496       goto invalid_track;
3497 
3498   /* obtain stream defaults */
3499   qtdemux_parse_trex (qtdemux, *stream,
3500       default_sample_duration, default_sample_size, default_sample_flags);
3501 
3502   (*stream)->stsd_sample_description_id =
3503       (*stream)->def_sample_description_index - 1;
3504 
3505   if (flags & TF_SAMPLE_DESCRIPTION_INDEX) {
3506     guint32 sample_description_index;
3507     if (!gst_byte_reader_get_uint32_be (tfhd, &sample_description_index))
3508       goto invalid_track;
3509     (*stream)->stsd_sample_description_id = sample_description_index - 1;
3510   }
3511 
3512   if (qtdemux->mss_mode) {
3513     /* mss has no stsd entry */
3514     (*stream)->stsd_sample_description_id = 0;
3515   }
3516 
3517   if (flags & TF_DEFAULT_SAMPLE_DURATION)
3518     if (!gst_byte_reader_get_uint32_be (tfhd, default_sample_duration))
3519       goto invalid_track;
3520 
3521   if (flags & TF_DEFAULT_SAMPLE_SIZE)
3522     if (!gst_byte_reader_get_uint32_be (tfhd, default_sample_size))
3523       goto invalid_track;
3524 
3525   if (flags & TF_DEFAULT_SAMPLE_FLAGS)
3526     if (!gst_byte_reader_get_uint32_be (tfhd, default_sample_flags))
3527       goto invalid_track;
3528 
3529   return TRUE;
3530 
3531 invalid_track:
3532   {
3533     GST_WARNING_OBJECT (qtdemux, "invalid track fragment header");
3534     return FALSE;
3535   }
3536 unknown_stream:
3537   {
3538     GST_DEBUG_OBJECT (qtdemux, "unknown stream in tfhd");
3539     return TRUE;
3540   }
3541 }
3542 
3543 static gboolean
3544 qtdemux_parse_tfdt (GstQTDemux * qtdemux, GstByteReader * br,
3545     guint64 * decode_time)
3546 {
3547   guint32 version = 0;
3548 
3549   if (!gst_byte_reader_get_uint32_be (br, &version))
3550     return FALSE;
3551 
3552   version >>= 24;
3553   if (version == 1) {
3554     if (!gst_byte_reader_get_uint64_be (br, decode_time))
3555       goto failed;
3556   } else {
3557     guint32 dec_time = 0;
3558     if (!gst_byte_reader_get_uint32_be (br, &dec_time))
3559       goto failed;
3560     *decode_time = dec_time;
3561   }
3562 
3563   GST_INFO_OBJECT (qtdemux, "Track fragment decode time: %" G_GUINT64_FORMAT,
3564       *decode_time);
3565 
3566   return TRUE;
3567 
3568 failed:
3569   {
3570     GST_DEBUG_OBJECT (qtdemux, "parsing tfdt failed");
3571     return FALSE;
3572   }
3573 }
3574 
3575 /* Returns a pointer to a GstStructure containing the properties of
3576  * the stream sample identified by @sample_index. The caller must unref
3577  * the returned object after use. Returns NULL if unsuccessful. */
3578 static GstStructure *
3579 qtdemux_get_cenc_sample_properties (GstQTDemux * qtdemux,
3580     QtDemuxStream * stream, guint sample_index)
3581 {
3582   QtDemuxCencSampleSetInfo *info = NULL;
3583 
3584   g_return_val_if_fail (stream != NULL, NULL);
3585   g_return_val_if_fail (stream->protected, NULL);
3586   g_return_val_if_fail (stream->protection_scheme_info != NULL, NULL);
3587 
3588   info = (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
3589 
3590   /* Currently, cenc properties for groups of samples are not supported, so
3591    * simply return a copy of the default sample properties */
3592   return gst_structure_copy (info->default_properties);
3593 }
3594 
3595 /* Parses the sizes of sample auxiliary information contained within a stream,
3596  * as given in a saiz box. Returns array of sample_count guint8 size values,
3597  * or NULL on failure */
3598 static guint8 *
3599 qtdemux_parse_saiz (GstQTDemux * qtdemux, QtDemuxStream * stream,
3600     GstByteReader * br, guint32 * sample_count)
3601 {
3602   guint32 flags = 0;
3603   guint8 *info_sizes;
3604   guint8 default_info_size;
3605 
3606   g_return_val_if_fail (qtdemux != NULL, NULL);
3607   g_return_val_if_fail (stream != NULL, NULL);
3608   g_return_val_if_fail (br != NULL, NULL);
3609   g_return_val_if_fail (sample_count != NULL, NULL);
3610 
3611   if (!gst_byte_reader_get_uint32_be (br, &flags))
3612     return NULL;
3613 
3614   if (flags & 0x1) {
3615     /* aux_info_type and aux_info_type_parameter are ignored */
3616     if (!gst_byte_reader_skip (br, 8))
3617       return NULL;
3618   }
3619 
3620   if (!gst_byte_reader_get_uint8 (br, &default_info_size))
3621     return NULL;
3622   GST_DEBUG_OBJECT (qtdemux, "default_info_size: %u", default_info_size);
3623 
3624   if (!gst_byte_reader_get_uint32_be (br, sample_count))
3625     return NULL;
3626   GST_DEBUG_OBJECT (qtdemux, "sample_count: %u", *sample_count);
3627 
3628 
3629   if (default_info_size == 0) {
3630     if (!gst_byte_reader_dup_data (br, *sample_count, &info_sizes)) {
3631       return NULL;
3632     }
3633   } else {
3634     info_sizes = g_new (guint8, *sample_count);
3635     memset (info_sizes, default_info_size, *sample_count);
3636   }
3637 
3638   return info_sizes;
3639 }
3640 
3641 /* Parses the offset of sample auxiliary information contained within a stream,
3642  * as given in a saio box. Returns TRUE if successful; FALSE otherwise. */
3643 static gboolean
3644 qtdemux_parse_saio (GstQTDemux * qtdemux, QtDemuxStream * stream,
3645     GstByteReader * br, guint32 * info_type, guint32 * info_type_parameter,
3646     guint64 * offset)
3647 {
3648   guint8 version = 0;
3649   guint32 flags = 0;
3650   guint32 aux_info_type = 0;
3651   guint32 aux_info_type_parameter = 0;
3652   guint32 entry_count;
3653   guint32 off_32;
3654   guint64 off_64;
3655   const guint8 *aux_info_type_data = NULL;
3656 
3657   g_return_val_if_fail (qtdemux != NULL, FALSE);
3658   g_return_val_if_fail (stream != NULL, FALSE);
3659   g_return_val_if_fail (br != NULL, FALSE);
3660   g_return_val_if_fail (offset != NULL, FALSE);
3661 
3662   if (!gst_byte_reader_get_uint8 (br, &version))
3663     return FALSE;
3664 
3665   if (!gst_byte_reader_get_uint24_be (br, &flags))
3666     return FALSE;
3667 
3668   if (flags & 0x1) {
3669 
3670     if (!gst_byte_reader_get_data (br, 4, &aux_info_type_data))
3671       return FALSE;
3672     aux_info_type = QT_FOURCC (aux_info_type_data);
3673 
3674     if (!gst_byte_reader_get_uint32_be (br, &aux_info_type_parameter))
3675       return FALSE;
3676   } else if (stream->protected) {
3677     aux_info_type = stream->protection_scheme_type;
3678   } else {
3679     aux_info_type = CUR_STREAM (stream)->fourcc;
3680   }
3681 
3682   if (info_type)
3683     *info_type = aux_info_type;
3684   if (info_type_parameter)
3685     *info_type_parameter = aux_info_type_parameter;
3686 
3687   GST_DEBUG_OBJECT (qtdemux, "aux_info_type: '%" GST_FOURCC_FORMAT "', "
3688       "aux_info_type_parameter:  %#06x",
3689       GST_FOURCC_ARGS (aux_info_type), aux_info_type_parameter);
3690 
3691   if (!gst_byte_reader_get_uint32_be (br, &entry_count))
3692     return FALSE;
3693 
3694   if (entry_count != 1) {
3695     GST_ERROR_OBJECT (qtdemux, "multiple offsets are not supported");
3696     return FALSE;
3697   }
3698 
3699   if (version == 0) {
3700     if (!gst_byte_reader_get_uint32_be (br, &off_32))
3701       return FALSE;
3702     *offset = (guint64) off_32;
3703   } else {
3704     if (!gst_byte_reader_get_uint64_be (br, &off_64))
3705       return FALSE;
3706     *offset = off_64;
3707   }
3708 
3709   GST_DEBUG_OBJECT (qtdemux, "offset: %" G_GUINT64_FORMAT, *offset);
3710   return TRUE;
3711 }
3712 
3713 static void
3714 qtdemux_gst_structure_free (GstStructure * gststructure)
3715 {
3716   if (gststructure) {
3717     gst_structure_free (gststructure);
3718   }
3719 }
3720 
3721 /* Parses auxiliary information relating to samples protected using Common
3722  * Encryption (cenc); the format of this information is defined in
3723  * ISO/IEC 23001-7. Returns TRUE if successful; FALSE otherwise. */
3724 static gboolean
3725 qtdemux_parse_cenc_aux_info (GstQTDemux * qtdemux, QtDemuxStream * stream,
3726     GstByteReader * br, guint8 * info_sizes, guint32 sample_count)
3727 {
3728   QtDemuxCencSampleSetInfo *ss_info = NULL;
3729   guint8 size;
3730   gint i;
3731   GPtrArray *old_crypto_info = NULL;
3732   guint old_entries = 0;
3733 
3734   g_return_val_if_fail (qtdemux != NULL, FALSE);
3735   g_return_val_if_fail (stream != NULL, FALSE);
3736   g_return_val_if_fail (br != NULL, FALSE);
3737   g_return_val_if_fail (stream->protected, FALSE);
3738   g_return_val_if_fail (stream->protection_scheme_info != NULL, FALSE);
3739 
3740   ss_info = (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
3741 
3742   if (ss_info->crypto_info) {
3743     old_crypto_info = ss_info->crypto_info;
3744     /* Count number of non-null entries remaining at the tail end */
3745     for (i = old_crypto_info->len - 1; i >= 0; i--) {
3746       if (g_ptr_array_index (old_crypto_info, i) == NULL)
3747         break;
3748       old_entries++;
3749     }
3750   }
3751 
3752   ss_info->crypto_info =
3753       g_ptr_array_new_full (sample_count + old_entries,
3754       (GDestroyNotify) qtdemux_gst_structure_free);
3755 
3756   /* We preserve old entries because we parse the next moof in advance
3757    * of consuming all samples from the previous moof, and otherwise
3758    * we'd discard the corresponding crypto info for the samples
3759    * from the previous fragment. */
3760   if (old_entries) {
3761     GST_DEBUG_OBJECT (qtdemux, "Preserving %d old crypto info entries",
3762         old_entries);
3763     for (i = old_crypto_info->len - old_entries; i < old_crypto_info->len; i++) {
3764       g_ptr_array_add (ss_info->crypto_info, g_ptr_array_index (old_crypto_info,
3765               i));
3766       g_ptr_array_index (old_crypto_info, i) = NULL;
3767     }
3768   }
3769 
3770   if (old_crypto_info) {
3771     /* Everything now belongs to the new array */
3772     g_ptr_array_free (old_crypto_info, TRUE);
3773   }
3774 
3775   for (i = 0; i < sample_count; ++i) {
3776     GstStructure *properties;
3777     guint16 n_subsamples = 0;
3778     guint8 *data;
3779     guint iv_size;
3780     GstBuffer *buf;
3781 
3782     properties = qtdemux_get_cenc_sample_properties (qtdemux, stream, i);
3783     if (properties == NULL) {
3784       GST_ERROR_OBJECT (qtdemux, "failed to get properties for sample %u", i);
3785       return FALSE;
3786     }
3787     if (!gst_structure_get_uint (properties, "iv_size", &iv_size)) {
3788       GST_ERROR_OBJECT (qtdemux, "failed to get iv_size for sample %u", i);
3789       gst_structure_free (properties);
3790       return FALSE;
3791     }
3792     if (!gst_byte_reader_dup_data (br, iv_size, &data)) {
3793       GST_ERROR_OBJECT (qtdemux, "failed to get IV for sample %u", i);
3794       gst_structure_free (properties);
3795       return FALSE;
3796     }
3797     buf = gst_buffer_new_wrapped (data, iv_size);
3798     gst_structure_set (properties, "iv", GST_TYPE_BUFFER, buf, NULL);
3799     gst_buffer_unref (buf);
3800     size = info_sizes[i];
3801     if (size > iv_size) {
3802       if (!gst_byte_reader_get_uint16_be (br, &n_subsamples)
3803           || !(n_subsamples > 0)) {
3804         gst_structure_free (properties);
3805         GST_ERROR_OBJECT (qtdemux,
3806             "failed to get subsample count for sample %u", i);
3807         return FALSE;
3808       }
3809       GST_LOG_OBJECT (qtdemux, "subsample count: %u", n_subsamples);
3810       if (!gst_byte_reader_dup_data (br, n_subsamples * 6, &data)) {
3811         GST_ERROR_OBJECT (qtdemux, "failed to get subsample data for sample %u",
3812             i);
3813         gst_structure_free (properties);
3814         return FALSE;
3815       }
3816       buf = gst_buffer_new_wrapped (data, n_subsamples * 6);
3817       if (!buf) {
3818         gst_structure_free (properties);
3819         return FALSE;
3820       }
3821       gst_structure_set (properties,
3822           "subsample_count", G_TYPE_UINT, n_subsamples,
3823           "subsamples", GST_TYPE_BUFFER, buf, NULL);
3824       gst_buffer_unref (buf);
3825     } else {
3826       gst_structure_set (properties, "subsample_count", G_TYPE_UINT, 0, NULL);
3827     }
3828     g_ptr_array_add (ss_info->crypto_info, properties);
3829   }
3830   return TRUE;
3831 }
3832 
3833 /* Converts a UUID in raw byte form to a string representation, as defined in
3834  * RFC 4122. The caller takes ownership of the returned string and is
3835  * responsible for freeing it after use. */
3836 static gchar *
3837 qtdemux_uuid_bytes_to_string (gconstpointer uuid_bytes)
3838 {
3839   const guint8 *uuid = (const guint8 *) uuid_bytes;
3840 
3841   return g_strdup_printf ("%02x%02x%02x%02x-%02x%02x-%02x%02x-"
3842       "%02x%02x-%02x%02x%02x%02x%02x%02x",
3843       uuid[0], uuid[1], uuid[2], uuid[3],
3844       uuid[4], uuid[5], uuid[6], uuid[7],
3845       uuid[8], uuid[9], uuid[10], uuid[11],
3846       uuid[12], uuid[13], uuid[14], uuid[15]);
3847 }
3848 
3849 /* Parses a Protection System Specific Header box (pssh), as defined in the
3850  * Common Encryption (cenc) standard (ISO/IEC 23001-7), which contains
3851  * information needed by a specific content protection system in order to
3852  * decrypt cenc-protected tracks. Returns TRUE if successful; FALSE
3853  * otherwise. */
3854 static gboolean
3855 qtdemux_parse_pssh (GstQTDemux * qtdemux, GNode * node)
3856 {
3857   gchar *sysid_string;
3858   guint32 pssh_size = QT_UINT32 (node->data);
3859   GstBuffer *pssh = NULL;
3860   GstEvent *event = NULL;
3861   guint32 parent_box_type;
3862   gint i;
3863 
3864   if (G_UNLIKELY (pssh_size < 32U)) {
3865     GST_ERROR_OBJECT (qtdemux, "invalid box size");
3866     return FALSE;
3867   }
3868 
3869   sysid_string =
3870       qtdemux_uuid_bytes_to_string ((const guint8 *) node->data + 12);
3871 
3872   gst_qtdemux_append_protection_system_id (qtdemux, sysid_string);
3873 
3874   pssh = gst_buffer_new_wrapped (g_memdup (node->data, pssh_size), pssh_size);
3875   GST_LOG_OBJECT (qtdemux, "cenc pssh size: %" G_GSIZE_FORMAT,
3876       gst_buffer_get_size (pssh));
3877 
3878   parent_box_type = QT_FOURCC ((const guint8 *) node->parent->data + 4);
3879 
3880   /* Push an event containing the pssh box onto the queues of all streams. */
3881   event = gst_event_new_protection (sysid_string, pssh,
3882       (parent_box_type == FOURCC_moov) ? "isobmff/moov" : "isobmff/moof");
3883   for (i = 0; i < qtdemux->n_streams; ++i) {
3884     g_queue_push_tail (&qtdemux->streams[i]->protection_scheme_event_queue,
3885         gst_event_ref (event));
3886   }
3887   g_free (sysid_string);
3888   gst_event_unref (event);
3889   gst_buffer_unref (pssh);
3890   return TRUE;
3891 }
3892 
3893 static gboolean
3894 qtdemux_parse_moof (GstQTDemux * qtdemux, const guint8 * buffer, guint length,
3895     guint64 moof_offset, QtDemuxStream * stream)
3896 {
3897   GNode *moof_node, *traf_node, *tfhd_node, *trun_node, *tfdt_node, *mfhd_node;
3898   GNode *uuid_node;
3899   GstByteReader mfhd_data, trun_data, tfhd_data, tfdt_data;
3900   GNode *saiz_node, *saio_node, *pssh_node;
3901   GstByteReader saiz_data, saio_data;
3902   guint32 ds_size = 0, ds_duration = 0, ds_flags = 0;
3903   gint64 base_offset, running_offset;
3904   guint32 frag_num;
3905 
3906   /* NOTE @stream ignored */
3907 
3908   moof_node = g_node_new ((guint8 *) buffer);
3909   qtdemux_parse_node (qtdemux, moof_node, buffer, length);
3910   qtdemux_node_dump (qtdemux, moof_node);
3911 
3912   /* Get fragment number from mfhd and check it's valid */
3913   mfhd_node =
3914       qtdemux_tree_get_child_by_type_full (moof_node, FOURCC_mfhd, &mfhd_data);
3915   if (mfhd_node == NULL)
3916     goto missing_mfhd;
3917   if (!qtdemux_parse_mfhd (qtdemux, &mfhd_data, &frag_num))
3918     goto fail;
3919   GST_DEBUG_OBJECT (qtdemux, "Fragment #%d", frag_num);
3920 
3921   /* unknown base_offset to start with */
3922   base_offset = running_offset = -1;
3923   traf_node = qtdemux_tree_get_child_by_type (moof_node, FOURCC_traf);
3924   while (traf_node) {
3925     guint64 decode_time = 0;
3926 
3927     /* Fragment Header node */
3928     tfhd_node =
3929         qtdemux_tree_get_child_by_type_full (traf_node, FOURCC_tfhd,
3930         &tfhd_data);
3931     if (!tfhd_node)
3932       goto missing_tfhd;
3933     if (!qtdemux_parse_tfhd (qtdemux, &tfhd_data, &stream, &ds_duration,
3934             &ds_size, &ds_flags, &base_offset))
3935       goto missing_tfhd;
3936 
3937     /* The following code assumes at most a single set of sample auxiliary
3938      * data in the fragment (consisting of a saiz box and a corresponding saio
3939      * box); in theory, however, there could be multiple sets of sample
3940      * auxiliary data in a fragment. */
3941     saiz_node =
3942         qtdemux_tree_get_child_by_type_full (traf_node, FOURCC_saiz,
3943         &saiz_data);
3944     if (saiz_node) {
3945       guint32 info_type = 0;
3946       guint64 offset = 0;
3947       guint32 info_type_parameter = 0;
3948 
3949       g_free (qtdemux->cenc_aux_info_sizes);
3950 
3951       qtdemux->cenc_aux_info_sizes =
3952           qtdemux_parse_saiz (qtdemux, stream, &saiz_data,
3953           &qtdemux->cenc_aux_sample_count);
3954       if (qtdemux->cenc_aux_info_sizes == NULL) {
3955         GST_ERROR_OBJECT (qtdemux, "failed to parse saiz box");
3956         goto fail;
3957       }
3958       saio_node =
3959           qtdemux_tree_get_child_by_type_full (traf_node, FOURCC_saio,
3960           &saio_data);
3961       if (!saio_node) {
3962         GST_ERROR_OBJECT (qtdemux, "saiz box without a corresponding saio box");
3963         g_free (qtdemux->cenc_aux_info_sizes);
3964         qtdemux->cenc_aux_info_sizes = NULL;
3965         goto fail;
3966       }
3967 
3968       if (G_UNLIKELY (!qtdemux_parse_saio (qtdemux, stream, &saio_data,
3969                   &info_type, &info_type_parameter, &offset))) {
3970         GST_ERROR_OBJECT (qtdemux, "failed to parse saio box");
3971         g_free (qtdemux->cenc_aux_info_sizes);
3972         qtdemux->cenc_aux_info_sizes = NULL;
3973         goto fail;
3974       }
3975       if (base_offset > -1 && base_offset > qtdemux->moof_offset)
3976         offset += (guint64) (base_offset - qtdemux->moof_offset);
3977       if (info_type == FOURCC_cenc && info_type_parameter == 0U) {
3978         GstByteReader br;
3979         if (offset > length) {
3980           GST_DEBUG_OBJECT (qtdemux, "cenc auxiliary info stored out of moof");
3981           qtdemux->cenc_aux_info_offset = offset;
3982         } else {
3983           gst_byte_reader_init (&br, buffer + offset, length - offset);
3984           if (!qtdemux_parse_cenc_aux_info (qtdemux, stream, &br,
3985                   qtdemux->cenc_aux_info_sizes,
3986                   qtdemux->cenc_aux_sample_count)) {
3987             GST_ERROR_OBJECT (qtdemux, "failed to parse cenc auxiliary info");
3988             g_free (qtdemux->cenc_aux_info_sizes);
3989             qtdemux->cenc_aux_info_sizes = NULL;
3990             goto fail;
3991           }
3992         }
3993       }
3994     }
3995 
3996     tfdt_node =
3997         qtdemux_tree_get_child_by_type_full (traf_node, FOURCC_tfdt,
3998         &tfdt_data);
3999     if (tfdt_node) {
4000       /* We'll use decode_time to interpolate timestamps
4001        * in case the input timestamps are missing */
4002       qtdemux_parse_tfdt (qtdemux, &tfdt_data, &decode_time);
4003 
4004       GST_DEBUG_OBJECT (qtdemux, "decode time %" G_GINT64_FORMAT
4005           " (%" GST_TIME_FORMAT ")", decode_time,
4006           GST_TIME_ARGS (stream ? QTSTREAMTIME_TO_GSTTIME (stream,
4007                   decode_time) : GST_CLOCK_TIME_NONE));
4008 
4009       /* Discard the fragment buffer timestamp info to avoid using it.
4010        * Rely on tfdt instead as it is more accurate than the timestamp
4011        * that is fetched from a manifest/playlist and is usually
4012        * less accurate. */
4013       qtdemux->fragment_start = -1;
4014     }
4015 
4016     if (G_UNLIKELY (!stream)) {
4017       /* we lost track of offset, we'll need to regain it,
4018        * but can delay complaining until later or avoid doing so altogether */
4019       base_offset = -2;
4020       goto next;
4021     }
4022     if (G_UNLIKELY (base_offset < -1))
4023       goto lost_offset;
4024 
4025     if (qtdemux->upstream_format_is_time)
4026       gst_qtdemux_stream_flush_samples_data (qtdemux, stream);
4027 
4028     /* initialise moof sample data */
4029     stream->n_samples_moof = 0;
4030     stream->duration_last_moof = stream->duration_moof;
4031     stream->duration_moof = 0;
4032 
4033     /* Track Run node */
4034     trun_node =
4035         qtdemux_tree_get_child_by_type_full (traf_node, FOURCC_trun,
4036         &trun_data);
4037     while (trun_node) {
4038       qtdemux_parse_trun (qtdemux, &trun_data, stream,
4039           ds_duration, ds_size, ds_flags, moof_offset, length, &base_offset,
4040           &running_offset, decode_time, (tfdt_node != NULL));
4041       /* iterate all siblings */
4042       trun_node = qtdemux_tree_get_sibling_by_type_full (trun_node, FOURCC_trun,
4043           &trun_data);
4044     }
4045 
4046     uuid_node = qtdemux_tree_get_child_by_type (traf_node, FOURCC_uuid);
4047     if (uuid_node) {
4048       guint8 *uuid_buffer = (guint8 *) uuid_node->data;
4049       guint32 box_length = QT_UINT32 (uuid_buffer);
4050 
4051       qtdemux_parse_uuid (qtdemux, uuid_buffer, box_length);
4052     }
4053 
4054     /* if no new base_offset provided for next traf,
4055      * base is end of current traf */
4056     base_offset = running_offset;
4057     running_offset = -1;
4058 
4059     if (stream->n_samples_moof && stream->duration_moof)
4060       stream->new_caps = TRUE;
4061 
4062   next:
4063     /* iterate all siblings */
4064     traf_node = qtdemux_tree_get_sibling_by_type (traf_node, FOURCC_traf);
4065   }
4066 
4067   /* parse any protection system info */
4068   pssh_node = qtdemux_tree_get_child_by_type (moof_node, FOURCC_pssh);
4069   while (pssh_node) {
4070     GST_LOG_OBJECT (qtdemux, "Parsing pssh box.");
4071     qtdemux_parse_pssh (qtdemux, pssh_node);
4072     pssh_node = qtdemux_tree_get_sibling_by_type (pssh_node, FOURCC_pssh);
4073   }
4074 
4075   g_node_destroy (moof_node);
4076   return TRUE;
4077 
4078 missing_tfhd:
4079   {
4080     GST_DEBUG_OBJECT (qtdemux, "missing tfhd box");
4081     goto fail;
4082   }
4083 missing_mfhd:
4084   {
4085     GST_DEBUG_OBJECT (qtdemux, "Missing mfhd box");
4086     goto fail;
4087   }
4088 lost_offset:
4089   {
4090     GST_DEBUG_OBJECT (qtdemux, "lost offset");
4091     goto fail;
4092   }
4093 fail:
4094   {
4095     g_node_destroy (moof_node);
4096     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
4097         (_("This file is corrupt and cannot be played.")), (NULL));
4098     return FALSE;
4099   }
4100 }
4101 
4102 #if 0
4103 /* might be used if some day we actually use mfra & co
4104  * for random access to fragments,
4105  * but that will require quite some modifications and much less relying
4106  * on a sample array */
4107 #endif
4108 
4109 static gboolean
4110 qtdemux_parse_tfra (GstQTDemux * qtdemux, GNode * tfra_node)
4111 {
4112   QtDemuxStream *stream;
4113   guint32 ver_flags, track_id, len, num_entries, i;
4114   guint value_size, traf_size, trun_size, sample_size;
4115   guint64 time = 0, moof_offset = 0;
4116 #if 0
4117   GstBuffer *buf = NULL;
4118   GstFlowReturn ret;
4119 #endif
4120   GstByteReader tfra;
4121 
4122   gst_byte_reader_init (&tfra, tfra_node->data, QT_UINT32 (tfra_node->data));
4123 
4124   if (!gst_byte_reader_skip (&tfra, 8))
4125     return FALSE;
4126 
4127   if (!gst_byte_reader_get_uint32_be (&tfra, &ver_flags))
4128     return FALSE;
4129 
4130   if (!gst_byte_reader_get_uint32_be (&tfra, &track_id)
4131       || !gst_byte_reader_get_uint32_be (&tfra, &len)
4132       || !gst_byte_reader_get_uint32_be (&tfra, &num_entries))
4133     return FALSE;
4134 
4135   GST_DEBUG_OBJECT (qtdemux, "parsing tfra box for track id %u", track_id);
4136 
4137   stream = qtdemux_find_stream (qtdemux, track_id);
4138   if (stream == NULL)
4139     goto unknown_trackid;
4140 
4141   value_size = ((ver_flags >> 24) == 1) ? sizeof (guint64) : sizeof (guint32);
4142   sample_size = (len & 3) + 1;
4143   trun_size = ((len & 12) >> 2) + 1;
4144   traf_size = ((len & 48) >> 4) + 1;
4145 
4146   GST_DEBUG_OBJECT (qtdemux, "%u entries, sizes: value %u, traf %u, trun %u, "
4147       "sample %u", num_entries, value_size, traf_size, trun_size, sample_size);
4148 
4149   if (num_entries == 0)
4150     goto no_samples;
4151 
4152   if (!qt_atom_parser_has_chunks (&tfra, num_entries,
4153           value_size + value_size + traf_size + trun_size + sample_size))
4154     goto corrupt_file;
4155 
4156   g_free (stream->ra_entries);
4157   stream->ra_entries = g_new (QtDemuxRandomAccessEntry, num_entries);
4158   stream->n_ra_entries = num_entries;
4159 
4160   for (i = 0; i < num_entries; i++) {
4161     qt_atom_parser_get_offset (&tfra, value_size, &time);
4162     qt_atom_parser_get_offset (&tfra, value_size, &moof_offset);
4163     qt_atom_parser_get_uint_with_size_unchecked (&tfra, traf_size);
4164     qt_atom_parser_get_uint_with_size_unchecked (&tfra, trun_size);
4165     qt_atom_parser_get_uint_with_size_unchecked (&tfra, sample_size);
4166 
4167     time = QTSTREAMTIME_TO_GSTTIME (stream, time);
4168 
4169     GST_LOG_OBJECT (qtdemux, "fragment time: %" GST_TIME_FORMAT ", "
4170         " moof_offset: %" G_GUINT64_FORMAT, GST_TIME_ARGS (time), moof_offset);
4171 
4172     stream->ra_entries[i].ts = time;
4173     stream->ra_entries[i].moof_offset = moof_offset;
4174 
4175     /* don't want to go through the entire file and read all moofs at startup */
4176 #if 0
4177     ret = gst_qtdemux_pull_atom (qtdemux, moof_offset, 0, &buf);
4178     if (ret != GST_FLOW_OK)
4179       goto corrupt_file;
4180     qtdemux_parse_moof (qtdemux, GST_BUFFER_DATA (buf), GST_BUFFER_SIZE (buf),
4181         moof_offset, stream);
4182     gst_buffer_unref (buf);
4183 #endif
4184   }
4185 
4186   check_update_duration (qtdemux, time);
4187 
4188   return TRUE;
4189 
4190 /* ERRORS */
4191 unknown_trackid:
4192   {
4193     GST_WARNING_OBJECT (qtdemux, "Couldn't find stream for track %u", track_id);
4194     return FALSE;
4195   }
4196 corrupt_file:
4197   {
4198     GST_WARNING_OBJECT (qtdemux, "broken traf box, ignoring");
4199     return FALSE;
4200   }
4201 no_samples:
4202   {
4203     GST_WARNING_OBJECT (qtdemux, "stream has no samples");
4204     return FALSE;
4205   }
4206 }
4207 
4208 static gboolean
4209 qtdemux_pull_mfro_mfra (GstQTDemux * qtdemux)
4210 {
4211   GstMapInfo mfro_map = GST_MAP_INFO_INIT;
4212   GstMapInfo mfra_map = GST_MAP_INFO_INIT;
4213   GstBuffer *mfro = NULL, *mfra = NULL;
4214   GstFlowReturn flow;
4215   gboolean ret = FALSE;
4216   GNode *mfra_node, *tfra_node;
4217   guint64 mfra_offset = 0;
4218   guint32 fourcc, mfra_size;
4219   gint64 len;
4220 
4221   /* query upstream size in bytes */
4222   if (!gst_pad_peer_query_duration (qtdemux->sinkpad, GST_FORMAT_BYTES, &len))
4223     goto size_query_failed;
4224 
4225   /* mfro box should be at the very end of the file */
4226   flow = gst_qtdemux_pull_atom (qtdemux, len - 16, 16, &mfro);
4227   if (flow != GST_FLOW_OK)
4228     goto exit;
4229 
4230   gst_buffer_map (mfro, &mfro_map, GST_MAP_READ);
4231 
4232   fourcc = QT_FOURCC (mfro_map.data + 4);
4233   if (fourcc != FOURCC_mfro)
4234     goto exit;
4235 
4236   GST_INFO_OBJECT (qtdemux, "Found mfro box");
4237   if (mfro_map.size < 16)
4238     goto invalid_mfro_size;
4239 
4240   mfra_size = QT_UINT32 (mfro_map.data + 12);
4241   if (mfra_size >= len)
4242     goto invalid_mfra_size;
4243 
4244   mfra_offset = len - mfra_size;
4245 
4246   GST_INFO_OBJECT (qtdemux, "mfra offset: %" G_GUINT64_FORMAT ", size %u",
4247       mfra_offset, mfra_size);
4248 
4249   /* now get and parse mfra box */
4250   flow = gst_qtdemux_pull_atom (qtdemux, mfra_offset, mfra_size, &mfra);
4251   if (flow != GST_FLOW_OK)
4252     goto broken_file;
4253 
4254   gst_buffer_map (mfra, &mfra_map, GST_MAP_READ);
4255 
4256   mfra_node = g_node_new ((guint8 *) mfra_map.data);
4257   qtdemux_parse_node (qtdemux, mfra_node, mfra_map.data, mfra_map.size);
4258 
4259   tfra_node = qtdemux_tree_get_child_by_type (mfra_node, FOURCC_tfra);
4260 
4261   while (tfra_node) {
4262     qtdemux_parse_tfra (qtdemux, tfra_node);
4263     /* iterate all siblings */
4264     tfra_node = qtdemux_tree_get_sibling_by_type (tfra_node, FOURCC_tfra);
4265   }
4266   g_node_destroy (mfra_node);
4267 
4268   GST_INFO_OBJECT (qtdemux, "parsed movie fragment random access box (mfra)");
4269   ret = TRUE;
4270 
4271 exit:
4272 
4273   if (mfro) {
4274     if (mfro_map.memory != NULL)
4275       gst_buffer_unmap (mfro, &mfro_map);
4276     gst_buffer_unref (mfro);
4277   }
4278   if (mfra) {
4279     if (mfra_map.memory != NULL)
4280       gst_buffer_unmap (mfra, &mfra_map);
4281     gst_buffer_unref (mfra);
4282 }
4283   return ret;
4284 
4285 /* ERRORS */
4286 size_query_failed:
4287 {
4288     GST_WARNING_OBJECT (qtdemux, "could not query upstream size");
4289     goto exit;
4290   }
4291 invalid_mfro_size:
4292   {
4293     GST_WARNING_OBJECT (qtdemux, "mfro size is too small");
4294     goto exit;
4295   }
4296 invalid_mfra_size:
4297   {
4298     GST_WARNING_OBJECT (qtdemux, "mfra_size in mfro box is invalid");
4299     goto exit;
4300   }
4301 broken_file:
4302   {
4303     GST_WARNING_OBJECT (qtdemux, "bogus mfra offset or size, broken file");
4304       goto exit;
4305     }
4306   }
4307 
4308 static guint64
4309 add_offset (guint64 offset, guint64 advance)
4310 {
4311   /* Avoid 64-bit overflow by clamping */
4312   if (offset > G_MAXUINT64 - advance)
4313     return G_MAXUINT64;
4314   return offset + advance;
4315   }
4316 
4317 static GstFlowReturn
4318 gst_qtdemux_loop_state_header (GstQTDemux * qtdemux)
4319 {
4320   guint64 length = 0;
4321   guint32 fourcc = 0;
4322   GstBuffer *buf = NULL;
4323   GstFlowReturn ret = GST_FLOW_OK;
4324   guint64 cur_offset = qtdemux->offset;
4325   GstMapInfo map;
4326 
4327   ret = gst_pad_pull_range (qtdemux->sinkpad, cur_offset, 16, &buf);
4328   if (G_UNLIKELY (ret != GST_FLOW_OK))
4329     goto beach;
4330   gst_buffer_map (buf, &map, GST_MAP_READ);
4331   if (G_LIKELY (map.size >= 8))
4332     extract_initial_length_and_fourcc (map.data, map.size, &length, &fourcc);
4333   gst_buffer_unmap (buf, &map);
4334   gst_buffer_unref (buf);
4335 
4336   /* maybe we already got most we needed, so only consider this eof */
4337   if (G_UNLIKELY (length == 0)) {
4338     GST_ELEMENT_WARNING (qtdemux, STREAM, DEMUX,
4339         (_("Invalid atom size.")),
4340         ("Header atom '%" GST_FOURCC_FORMAT "' has empty length",
4341             GST_FOURCC_ARGS (fourcc)));
4342     ret = GST_FLOW_EOS;
4343     goto beach;
4344   }
4345 
4346   switch (fourcc) {
4347     case FOURCC_moof:
4348       /* record for later parsing when needed */
4349       if (!qtdemux->moof_offset) {
4350         qtdemux->moof_offset = qtdemux->offset;
4351       }
4352       if (qtdemux_pull_mfro_mfra (qtdemux)) {
4353         /* FIXME */
4354       } else {
4355         qtdemux->offset += length;      /* skip moof and keep going */
4356       }
4357       if (qtdemux->got_moov) {
4358         GST_INFO_OBJECT (qtdemux, "moof header, got moov, done with headers");
4359         ret = GST_FLOW_EOS;
4360         goto beach;
4361       }
4362       break;
4363     case FOURCC_mdat:
4364     case FOURCC_free:
4365     case FOURCC_skip:
4366     case FOURCC_wide:
4367     case FOURCC_PICT:
4368     case FOURCC_pnot:
4369     {
4370       GST_LOG_OBJECT (qtdemux,
4371           "skipping atom '%" GST_FOURCC_FORMAT "' at %" G_GUINT64_FORMAT,
4372           GST_FOURCC_ARGS (fourcc), cur_offset);
4373       qtdemux->offset = add_offset (qtdemux->offset, length);
4374       break;
4375     }
4376     case FOURCC_moov:
4377     {
4378       GstBuffer *moov = NULL;
4379 
4380       if (qtdemux->got_moov) {
4381         GST_DEBUG_OBJECT (qtdemux, "Skipping moov atom as we have one already");
4382         qtdemux->offset = add_offset (qtdemux->offset, length);
4383         goto beach;
4384       }
4385 
4386       ret = gst_pad_pull_range (qtdemux->sinkpad, cur_offset, length, &moov);
4387       if (ret != GST_FLOW_OK)
4388         goto beach;
4389       gst_buffer_map (moov, &map, GST_MAP_READ);
4390 
4391       if (length != map.size) {
4392         /* Some files have a 'moov' atom at the end of the file which contains
4393          * a terminal 'free' atom where the body of the atom is missing.
4394          * Check for, and permit, this special case.
4395          */
4396         if (map.size >= 8) {
4397           guint8 *final_data = map.data + (map.size - 8);
4398           guint32 final_length = QT_UINT32 (final_data);
4399           guint32 final_fourcc = QT_FOURCC (final_data + 4);
4400 
4401           if (final_fourcc == FOURCC_free
4402               && map.size + final_length - 8 == length) {
4403             /* Ok, we've found that special case. Allocate a new buffer with
4404              * that free atom actually present. */
4405             GstBuffer *newmoov = gst_buffer_new_and_alloc (length);
4406             gst_buffer_fill (newmoov, 0, map.data, map.size);
4407             gst_buffer_memset (newmoov, map.size, 0, final_length - 8);
4408             gst_buffer_unmap (moov, &map);
4409             gst_buffer_unref (moov);
4410             moov = newmoov;
4411             gst_buffer_map (moov, &map, GST_MAP_READ);
4412           }
4413         }
4414       }
4415 
4416       if (length != map.size) {
4417         GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
4418             (_("This file is incomplete and cannot be played.")),
4419             ("We got less than expected (received %" G_GSIZE_FORMAT
4420                 ", wanted %u, offset %" G_GUINT64_FORMAT ")", map.size,
4421                 (guint) length, cur_offset));
4422         gst_buffer_unmap (moov, &map);
4423         gst_buffer_unref (moov);
4424         ret = GST_FLOW_ERROR;
4425         goto beach;
4426       }
4427       qtdemux->offset += length;
4428 
4429       qtdemux_parse_moov (qtdemux, map.data, length);
4430       qtdemux_node_dump (qtdemux, qtdemux->moov_node);
4431 
4432 #ifdef GSTREAMER_LITE
4433       if (!qtdemux_parse_tree (qtdemux)) {
4434         ret = GST_FLOW_ERROR;
4435         break;
4436       }
4437 #else
4438       qtdemux_parse_tree (qtdemux);
4439 #endif //GSTREAMER_LITE
4440 
4441       if (qtdemux->moov_node_compressed) {
4442         g_node_destroy (qtdemux->moov_node_compressed);
4443         g_free (qtdemux->moov_node->data);
4444       }
4445       qtdemux->moov_node_compressed = NULL;
4446       g_node_destroy (qtdemux->moov_node);
4447       qtdemux->moov_node = NULL;
4448       gst_buffer_unmap (moov, &map);
4449       gst_buffer_unref (moov);
4450       qtdemux->got_moov = TRUE;
4451 
4452       break;
4453     }
4454     case FOURCC_ftyp:
4455     {
4456       GstBuffer *ftyp = NULL;
4457 
4458       /* extract major brand; might come in handy for ISO vs QT issues */
4459       ret = gst_qtdemux_pull_atom (qtdemux, cur_offset, length, &ftyp);
4460       if (ret != GST_FLOW_OK)
4461         goto beach;
4462       qtdemux->offset += length;
4463       gst_buffer_map (ftyp, &map, GST_MAP_READ);
4464       qtdemux_parse_ftyp (qtdemux, map.data, map.size);
4465       gst_buffer_unmap (ftyp, &map);
4466       gst_buffer_unref (ftyp);
4467       break;
4468     }
4469     case FOURCC_uuid:
4470     {
4471       GstBuffer *uuid = NULL;
4472 
4473       /* uuid are extension atoms */
4474       ret = gst_qtdemux_pull_atom (qtdemux, cur_offset, length, &uuid);
4475       if (ret != GST_FLOW_OK)
4476         goto beach;
4477       qtdemux->offset += length;
4478       gst_buffer_map (uuid, &map, GST_MAP_READ);
4479       qtdemux_parse_uuid (qtdemux, map.data, map.size);
4480       gst_buffer_unmap (uuid, &map);
4481       gst_buffer_unref (uuid);
4482       break;
4483     }
4484     case FOURCC_sidx:
4485     {
4486       GstBuffer *sidx = NULL;
4487       ret = gst_qtdemux_pull_atom (qtdemux, cur_offset, length, &sidx);
4488       if (ret != GST_FLOW_OK)
4489         goto beach;
4490       qtdemux->offset += length;
4491       gst_buffer_map (sidx, &map, GST_MAP_READ);
4492       qtdemux_parse_sidx (qtdemux, map.data, map.size);
4493       gst_buffer_unmap (sidx, &map);
4494       gst_buffer_unref (sidx);
4495       break;
4496     }
4497     default:
4498     {
4499       GstBuffer *unknown = NULL;
4500 
4501       GST_LOG_OBJECT (qtdemux,
4502           "unknown %08x '%" GST_FOURCC_FORMAT "' of size %" G_GUINT64_FORMAT
4503           " at %" G_GUINT64_FORMAT, fourcc, GST_FOURCC_ARGS (fourcc), length,
4504           cur_offset);
4505       ret = gst_qtdemux_pull_atom (qtdemux, cur_offset, length, &unknown);
4506       if (ret != GST_FLOW_OK)
4507         goto beach;
4508       gst_buffer_map (unknown, &map, GST_MAP_READ);
4509       GST_MEMDUMP ("Unknown tag", map.data, map.size);
4510       gst_buffer_unmap (unknown, &map);
4511       gst_buffer_unref (unknown);
4512       qtdemux->offset += length;
4513       break;
4514     }
4515   }
4516 
4517 beach:
4518   if (ret == GST_FLOW_EOS && (qtdemux->got_moov || qtdemux->media_caps)) {
4519     /* digested all data, show what we have */
4520     qtdemux_prepare_streams (qtdemux);
4521     ret = qtdemux_expose_streams (qtdemux);
4522 
4523     qtdemux->state = QTDEMUX_STATE_MOVIE;
4524     GST_DEBUG_OBJECT (qtdemux, "switching state to STATE_MOVIE (%d)",
4525         qtdemux->state);
4526     return ret;
4527   }
4528   return ret;
4529 }
4530 
4531 /* Seeks to the previous keyframe of the indexed stream and
4532  * aligns other streams with respect to the keyframe timestamp
4533  * of indexed stream. Only called in case of Reverse Playback
4534  */
4535 static GstFlowReturn
4536 gst_qtdemux_seek_to_previous_keyframe (GstQTDemux * qtdemux)
4537 {
4538   guint8 n = 0;
4539   guint32 seg_idx = 0, k_index = 0;
4540   guint32 ref_seg_idx, ref_k_index;
4541   GstClockTime k_pos = 0, last_stop = 0;
4542   QtDemuxSegment *seg = NULL;
4543   QtDemuxStream *ref_str = NULL;
4544   guint64 seg_media_start_mov;  /* segment media start time in mov format */
4545   guint64 target_ts;
4546 
4547   /* Now we choose an arbitrary stream, get the previous keyframe timestamp
4548    * and finally align all the other streams on that timestamp with their
4549    * respective keyframes */
4550   for (n = 0; n < qtdemux->n_streams; n++) {
4551     QtDemuxStream *str = qtdemux->streams[n];
4552 
4553     /* No candidate yet, take the first stream */
4554     if (!ref_str) {
4555       ref_str = str;
4556       continue;
4557     }
4558 
4559     /* So that stream has a segment, we prefer video streams */
4560     if (str->subtype == FOURCC_vide) {
4561       ref_str = str;
4562       break;
4563     }
4564   }
4565 
4566   if (G_UNLIKELY (!ref_str)) {
4567     GST_DEBUG_OBJECT (qtdemux, "couldn't find any stream");
4568     goto eos;
4569   }
4570 
4571   if (G_UNLIKELY (!ref_str->from_sample)) {
4572     GST_DEBUG_OBJECT (qtdemux, "reached the beginning of the file");
4573     goto eos;
4574   }
4575 
4576   /* So that stream has been playing from from_sample to to_sample. We will
4577    * get the timestamp of the previous sample and search for a keyframe before
4578    * that. For audio streams we do an arbitrary jump in the past (10 samples) */
4579   if (ref_str->subtype == FOURCC_vide) {
4580     k_index = gst_qtdemux_find_keyframe (qtdemux, ref_str,
4581         ref_str->from_sample - 1, FALSE);
4582   } else {
4583     if (ref_str->from_sample >= 10)
4584       k_index = ref_str->from_sample - 10;
4585     else
4586       k_index = 0;
4587   }
4588 
4589   target_ts =
4590       ref_str->samples[k_index].timestamp +
4591       ref_str->samples[k_index].pts_offset;
4592 
4593   /* get current segment for that stream */
4594   seg = &ref_str->segments[ref_str->segment_index];
4595   /* Use segment start in original timescale for comparisons */
4596   seg_media_start_mov = seg->trak_media_start;
4597 
4598   GST_LOG_OBJECT (qtdemux, "keyframe index %u ts %" G_GUINT64_FORMAT
4599       " seg start %" G_GUINT64_FORMAT " %" GST_TIME_FORMAT "\n",
4600       k_index, target_ts, seg_media_start_mov,
4601       GST_TIME_ARGS (seg->media_start));
4602 
4603   /* Crawl back through segments to find the one containing this I frame */
4604   while (target_ts < seg_media_start_mov) {
4605     GST_DEBUG_OBJECT (qtdemux,
4606         "keyframe position (sample %u) is out of segment %u " " target %"
4607         G_GUINT64_FORMAT " seg start %" G_GUINT64_FORMAT, k_index,
4608         ref_str->segment_index, target_ts, seg_media_start_mov);
4609 
4610     if (G_UNLIKELY (!ref_str->segment_index)) {
4611       /* Reached first segment, let's consider it's EOS */
4612       goto eos;
4613     }
4614     ref_str->segment_index--;
4615     seg = &ref_str->segments[ref_str->segment_index];
4616     /* Use segment start in original timescale for comparisons */
4617     seg_media_start_mov = seg->trak_media_start;
4618   }
4619   /* Calculate time position of the keyframe and where we should stop */
4620   k_pos =
4621       QTSTREAMTIME_TO_GSTTIME (ref_str,
4622       target_ts - seg->trak_media_start) + seg->time;
4623   last_stop =
4624       QTSTREAMTIME_TO_GSTTIME (ref_str,
4625       ref_str->samples[ref_str->from_sample].timestamp -
4626       seg->trak_media_start) + seg->time;
4627 
4628   GST_DEBUG_OBJECT (qtdemux, "preferred stream played from sample %u, "
4629       "now going to sample %u (pts %" GST_TIME_FORMAT ")", ref_str->from_sample,
4630       k_index, GST_TIME_ARGS (k_pos));
4631 
4632   /* Set last_stop with the keyframe timestamp we pushed of that stream */
4633   qtdemux->segment.position = last_stop;
4634   GST_DEBUG_OBJECT (qtdemux, "last_stop now is %" GST_TIME_FORMAT,
4635       GST_TIME_ARGS (last_stop));
4636 
4637   if (G_UNLIKELY (last_stop < qtdemux->segment.start)) {
4638     GST_DEBUG_OBJECT (qtdemux, "reached the beginning of segment");
4639     goto eos;
4640   }
4641 
4642   ref_seg_idx = ref_str->segment_index;
4643   ref_k_index = k_index;
4644 
4645   /* Align them all on this */
4646   for (n = 0; n < qtdemux->n_streams; n++) {
4647     guint32 index = 0;
4648     GstClockTime seg_time = 0;
4649     QtDemuxStream *str = qtdemux->streams[n];
4650 
4651     /* aligning reference stream again might lead to backing up to yet another
4652      * keyframe (due to timestamp rounding issues),
4653      * potentially putting more load on downstream; so let's try to avoid */
4654     if (str == ref_str) {
4655       seg_idx = ref_seg_idx;
4656       seg = &str->segments[seg_idx];
4657       k_index = ref_k_index;
4658       GST_DEBUG_OBJECT (qtdemux, "reference stream %d segment %d, "
4659           "sample at index %d", n, ref_str->segment_index, k_index);
4660     } else {
4661       seg_idx = gst_qtdemux_find_segment (qtdemux, str, k_pos);
4662       GST_DEBUG_OBJECT (qtdemux,
4663           "stream %d align segment %d for keyframe pos %" GST_TIME_FORMAT, n,
4664           seg_idx, GST_TIME_ARGS (k_pos));
4665 
4666       /* get segment and time in the segment */
4667       seg = &str->segments[seg_idx];
4668       seg_time = k_pos - seg->time;
4669 
4670       /* get the media time in the segment.
4671        * No adjustment for empty "filler" segments */
4672       if (seg->media_start != GST_CLOCK_TIME_NONE)
4673         seg_time += seg->media_start;
4674 
4675       /* get the index of the sample with media time */
4676       index = gst_qtdemux_find_index_linear (qtdemux, str, seg_time);
4677       GST_DEBUG_OBJECT (qtdemux,
4678           "stream %d sample for %" GST_TIME_FORMAT " at %u", n,
4679           GST_TIME_ARGS (seg_time), index);
4680 
4681       /* find previous keyframe */
4682       k_index = gst_qtdemux_find_keyframe (qtdemux, str, index, FALSE);
4683     }
4684 
4685     /* Remember until where we want to go */
4686     str->to_sample = str->from_sample - 1;
4687     /* Define our time position */
4688     target_ts =
4689         str->samples[k_index].timestamp + str->samples[k_index].pts_offset;
4690     str->time_position = QTSTREAMTIME_TO_GSTTIME (str, target_ts) + seg->time;
4691     if (seg->media_start != GST_CLOCK_TIME_NONE)
4692       str->time_position -= seg->media_start;
4693 
4694     /* Now seek back in time */
4695     gst_qtdemux_move_stream (qtdemux, str, k_index);
4696     GST_DEBUG_OBJECT (qtdemux, "stream %d keyframe at %u, time position %"
4697         GST_TIME_FORMAT " playing from sample %u to %u", n, k_index,
4698         GST_TIME_ARGS (str->time_position), str->from_sample, str->to_sample);
4699   }
4700 
4701   return GST_FLOW_OK;
4702 
4703 eos:
4704   return GST_FLOW_EOS;
4705 }
4706 
4707 /*
4708  * Gets the current qt segment start, stop and position for the
4709  * given time offset. This is used in update_segment()
4710  */
4711 static void
4712 gst_qtdemux_stream_segment_get_boundaries (GstQTDemux * qtdemux,
4713     QtDemuxStream * stream, GstClockTime offset,
4714     GstClockTime * _start, GstClockTime * _stop, GstClockTime * _time)
4715 {
4716   GstClockTime seg_time;
4717   GstClockTime start, stop, time;
4718   QtDemuxSegment *segment;
4719 
4720   segment = &stream->segments[stream->segment_index];
4721 
4722   /* get time in this segment */
4723   seg_time = (offset - segment->time) * segment->rate;
4724 
4725   GST_LOG_OBJECT (stream->pad, "seg_time %" GST_TIME_FORMAT,
4726       GST_TIME_ARGS (seg_time));
4727 
4728   if (G_UNLIKELY (seg_time > segment->duration)) {
4729     GST_LOG_OBJECT (stream->pad,
4730         "seg_time > segment->duration %" GST_TIME_FORMAT,
4731         GST_TIME_ARGS (segment->duration));
4732     seg_time = segment->duration;
4733   }
4734 
4735   /* qtdemux->segment.stop is in outside-time-realm, whereas
4736    * segment->media_stop is in track-time-realm.
4737    *
4738    * In order to compare the two, we need to bring segment.stop
4739    * into the track-time-realm
4740    *
4741    * FIXME - does this comment still hold? Don't see any conversion here */
4742 
4743   stop = qtdemux->segment.stop;
4744   if (stop == GST_CLOCK_TIME_NONE)
4745     stop = qtdemux->segment.duration;
4746   if (stop == GST_CLOCK_TIME_NONE)
4747     stop = segment->media_stop;
4748   else
4749     stop =
4750         MIN (segment->media_stop, stop - segment->time + segment->media_start);
4751 
4752   if (G_UNLIKELY (QTSEGMENT_IS_EMPTY (segment))) {
4753     start = segment->time + seg_time;
4754     time = offset;
4755     stop = start - seg_time + segment->duration;
4756   } else if (qtdemux->segment.rate >= 0) {
4757     start = MIN (segment->media_start + seg_time, stop);
4758     time = offset;
4759   } else {
4760     if (segment->media_start >= qtdemux->segment.start) {
4761       time = segment->time;
4762     } else {
4763       time = segment->time + (qtdemux->segment.start - segment->media_start);
4764     }
4765 
4766     start = MAX (segment->media_start, qtdemux->segment.start);
4767     stop = MIN (segment->media_start + seg_time, stop);
4768   }
4769 
4770   *_start = start;
4771   *_stop = stop;
4772   *_time = time;
4773 }
4774 
4775 /*
4776  * Updates the qt segment used for the stream and pushes a new segment event
4777  * downstream on this stream's pad.
4778  */
4779 static gboolean
4780 gst_qtdemux_stream_update_segment (GstQTDemux * qtdemux, QtDemuxStream * stream,
4781     gint seg_idx, GstClockTime offset, GstClockTime * _start,
4782     GstClockTime * _stop)
4783 {
4784   QtDemuxSegment *segment;
4785   GstClockTime start = 0, stop = GST_CLOCK_TIME_NONE, time = 0;
4786   gdouble rate;
4787   GstEvent *event;
4788 
4789   /* update the current segment */
4790   stream->segment_index = seg_idx;
4791 
4792   /* get the segment */
4793   segment = &stream->segments[seg_idx];
4794 
4795   if (G_UNLIKELY (offset < segment->time)) {
4796     GST_WARNING_OBJECT (stream->pad, "offset < segment->time %" GST_TIME_FORMAT,
4797         GST_TIME_ARGS (segment->time));
4798     return FALSE;
4799   }
4800 
4801   /* segment lies beyond total indicated duration */
4802   if (G_UNLIKELY (qtdemux->segment.duration != GST_CLOCK_TIME_NONE &&
4803           segment->time > qtdemux->segment.duration)) {
4804     GST_WARNING_OBJECT (stream->pad, "file duration %" GST_TIME_FORMAT
4805         " < segment->time %" GST_TIME_FORMAT,
4806         GST_TIME_ARGS (qtdemux->segment.duration),
4807         GST_TIME_ARGS (segment->time));
4808     return FALSE;
4809   }
4810 
4811   gst_qtdemux_stream_segment_get_boundaries (qtdemux, stream, offset,
4812       &start, &stop, &time);
4813 
4814   GST_DEBUG_OBJECT (stream->pad, "new segment %d from %" GST_TIME_FORMAT
4815       " to %" GST_TIME_FORMAT ", time %" GST_TIME_FORMAT, seg_idx,
4816       GST_TIME_ARGS (start), GST_TIME_ARGS (stop), GST_TIME_ARGS (time));
4817 
4818   /* combine global rate with that of the segment */
4819   rate = segment->rate * qtdemux->segment.rate;
4820 
4821   /* Copy flags from main segment */
4822   stream->segment.flags = qtdemux->segment.flags;
4823 
4824   /* update the segment values used for clipping */
4825   stream->segment.offset = qtdemux->segment.offset;
4826   stream->segment.base = qtdemux->segment.base + stream->accumulated_base;
4827   stream->segment.applied_rate = qtdemux->segment.applied_rate;
4828   stream->segment.rate = rate;
4829   stream->segment.start = start + QTSTREAMTIME_TO_GSTTIME (stream,
4830       stream->cslg_shift);
4831   stream->segment.stop = stop + QTSTREAMTIME_TO_GSTTIME (stream,
4832       stream->cslg_shift);
4833   stream->segment.time = time;
4834   stream->segment.position = stream->segment.start;
4835 
4836   GST_DEBUG_OBJECT (stream->pad, "New segment: %" GST_SEGMENT_FORMAT,
4837       &stream->segment);
4838 
4839   /* now prepare and send the segment */
4840   if (stream->pad) {
4841     event = gst_event_new_segment (&stream->segment);
4842     if (qtdemux->segment_seqnum != GST_SEQNUM_INVALID) {
4843       gst_event_set_seqnum (event, qtdemux->segment_seqnum);
4844     }
4845     gst_pad_push_event (stream->pad, event);
4846     /* assume we can send more data now */
4847     GST_PAD_LAST_FLOW_RETURN (stream->pad) = GST_FLOW_OK;
4848     /* clear to send tags on this pad now */
4849     gst_qtdemux_push_tags (qtdemux, stream);
4850   }
4851 
4852   if (_start)
4853     *_start = start;
4854   if (_stop)
4855     *_stop = stop;
4856 
4857   return TRUE;
4858 }
4859 
4860 /* activate the given segment number @seg_idx of @stream at time @offset.
4861  * @offset is an absolute global position over all the segments.
4862  *
4863  * This will push out a NEWSEGMENT event with the right values and
4864  * position the stream index to the first decodable sample before
4865  * @offset.
4866  */
4867 static gboolean
4868 gst_qtdemux_activate_segment (GstQTDemux * qtdemux, QtDemuxStream * stream,
4869     guint32 seg_idx, GstClockTime offset)
4870 {
4871   QtDemuxSegment *segment;
4872   guint32 index, kf_index;
4873   GstClockTime start = 0, stop = GST_CLOCK_TIME_NONE;
4874 
4875   GST_LOG_OBJECT (stream->pad, "activate segment %d, offset %" GST_TIME_FORMAT,
4876       seg_idx, GST_TIME_ARGS (offset));
4877 
4878   if (!gst_qtdemux_stream_update_segment (qtdemux, stream, seg_idx, offset,
4879           &start, &stop))
4880     return FALSE;
4881 
4882   segment = &stream->segments[stream->segment_index];
4883 
4884   /* in the fragmented case, we pick a fragment that starts before our
4885    * desired position and rely on downstream to wait for a keyframe
4886    * (FIXME: doesn't seem to work so well with ismv and wmv, as no parser; the
4887    * tfra entries tells us which trun/sample the key unit is in, but we don't
4888    * make use of this additional information at the moment) */
4889   if (qtdemux->fragmented && !qtdemux->fragmented_seek_pending) {
4890     stream->to_sample = G_MAXUINT32;
4891     return TRUE;
4892   } else {
4893     /* well, it will be taken care of below */
4894     qtdemux->fragmented_seek_pending = FALSE;
4895     /* FIXME ideally the do_fragmented_seek can be done right here,
4896      * rather than at loop level
4897      * (which might even allow handling edit lists in a fragmented file) */
4898   }
4899 
4900   /* We don't need to look for a sample in push-based */
4901   if (!qtdemux->pullbased)
4902     return TRUE;
4903 
4904   /* and move to the keyframe before the indicated media time of the
4905    * segment */
4906   if (G_LIKELY (!QTSEGMENT_IS_EMPTY (segment))) {
4907   if (qtdemux->segment.rate >= 0) {
4908     index = gst_qtdemux_find_index_linear (qtdemux, stream, start);
4909     stream->to_sample = G_MAXUINT32;
4910       GST_DEBUG_OBJECT (stream->pad,
4911           "moving data pointer to %" GST_TIME_FORMAT ", index: %u, pts %"
4912           GST_TIME_FORMAT, GST_TIME_ARGS (start), index,
4913           GST_TIME_ARGS (QTSAMPLE_PTS (stream, &stream->samples[index])));
4914   } else {
4915     index = gst_qtdemux_find_index_linear (qtdemux, stream, stop);
4916     stream->to_sample = index;
4917       GST_DEBUG_OBJECT (stream->pad,
4918           "moving data pointer to %" GST_TIME_FORMAT ", index: %u, pts %"
4919           GST_TIME_FORMAT, GST_TIME_ARGS (stop), index,
4920           GST_TIME_ARGS (QTSAMPLE_PTS (stream, &stream->samples[index])));
4921   }
4922   } else {
4923     GST_DEBUG_OBJECT (stream->pad, "No need to look for keyframe, "
4924         "this is an empty segment");
4925     return TRUE;
4926   }
4927 
4928   /* gst_qtdemux_parse_sample () called from gst_qtdemux_find_index_linear ()
4929    * encountered an error and printed a message so we return appropriately */
4930   if (index == -1)
4931     return FALSE;
4932 
4933   /* we're at the right spot */
4934   if (index == stream->sample_index) {
4935     GST_DEBUG_OBJECT (stream->pad, "we are at the right index");
4936     return TRUE;
4937   }
4938 
4939   /* find keyframe of the target index */
4940   kf_index = gst_qtdemux_find_keyframe (qtdemux, stream, index, FALSE);
4941 
4942 /* *INDENT-OFF* */
4943 /* indent does stupid stuff with stream->samples[].timestamp */
4944 
4945   /* if we move forwards, we don't have to go back to the previous
4946    * keyframe since we already sent that. We can also just jump to
4947    * the keyframe right before the target index if there is one. */
4948   if (index > stream->sample_index) {
4949     /* moving forwards check if we move past a keyframe */
4950     if (kf_index > stream->sample_index) {
4951       GST_DEBUG_OBJECT (stream->pad,
4952            "moving forwards to keyframe at %u (pts %" GST_TIME_FORMAT " dts %"GST_TIME_FORMAT" )", kf_index,
4953            GST_TIME_ARGS (QTSAMPLE_PTS(stream, &stream->samples[kf_index])),
4954            GST_TIME_ARGS (QTSAMPLE_DTS(stream, &stream->samples[kf_index])));
4955       gst_qtdemux_move_stream (qtdemux, stream, kf_index);
4956     } else {
4957       GST_DEBUG_OBJECT (stream->pad,
4958           "moving forwards, keyframe at %u (pts %" GST_TIME_FORMAT " dts %"GST_TIME_FORMAT" ) already sent", kf_index,
4959           GST_TIME_ARGS (QTSAMPLE_PTS (stream, &stream->samples[kf_index])),
4960           GST_TIME_ARGS (QTSAMPLE_DTS (stream, &stream->samples[kf_index])));
4961     }
4962   } else {
4963     GST_DEBUG_OBJECT (stream->pad,
4964         "moving backwards to keyframe at %u (pts %" GST_TIME_FORMAT " dts %"GST_TIME_FORMAT" )", kf_index,
4965         GST_TIME_ARGS (QTSAMPLE_PTS(stream, &stream->samples[kf_index])),
4966         GST_TIME_ARGS (QTSAMPLE_DTS(stream, &stream->samples[kf_index])));
4967     gst_qtdemux_move_stream (qtdemux, stream, kf_index);
4968   }
4969 
4970 /* *INDENT-ON* */
4971 
4972   return TRUE;
4973 }
4974 
4975 /* prepare to get the current sample of @stream, getting essential values.
4976  *
4977  * This function will also prepare and send the segment when needed.
4978  *
4979  * Return FALSE if the stream is EOS.
4980  *
4981  * PULL-BASED
4982  */
4983 static gboolean
4984 gst_qtdemux_prepare_current_sample (GstQTDemux * qtdemux,
4985     QtDemuxStream * stream, gboolean * empty, guint64 * offset, guint * size,
4986     GstClockTime * dts, GstClockTime * pts, GstClockTime * duration,
4987     gboolean * keyframe)
4988 {
4989   QtDemuxSample *sample;
4990   GstClockTime time_position;
4991   guint32 seg_idx;
4992 
4993   g_return_val_if_fail (stream != NULL, FALSE);
4994 
4995   time_position = stream->time_position;
4996   if (G_UNLIKELY (time_position == GST_CLOCK_TIME_NONE))
4997     goto eos;
4998 
4999   seg_idx = stream->segment_index;
5000   if (G_UNLIKELY (seg_idx == -1)) {
5001     /* find segment corresponding to time_position if we are looking
5002      * for a segment. */
5003     seg_idx = gst_qtdemux_find_segment (qtdemux, stream, time_position);
5004   }
5005 
5006   /* different segment, activate it, sample_index will be set. */
5007   if (G_UNLIKELY (stream->segment_index != seg_idx))
5008     gst_qtdemux_activate_segment (qtdemux, stream, seg_idx, time_position);
5009 
5010   if (G_UNLIKELY (QTSEGMENT_IS_EMPTY (&stream->segments[stream->
5011                   segment_index]))) {
5012     QtDemuxSegment *seg = &stream->segments[stream->segment_index];
5013 
5014     GST_LOG_OBJECT (qtdemux, "Empty segment activated,"
5015         " prepare empty sample");
5016 
5017     *empty = TRUE;
5018     *pts = *dts = time_position;
5019     *duration = seg->duration - (time_position - seg->time);
5020 
5021     return TRUE;
5022   }
5023 
5024   *empty = FALSE;
5025 
5026   if (stream->sample_index == -1)
5027     stream->sample_index = 0;
5028 
5029   GST_LOG_OBJECT (qtdemux, "segment active, index = %u of %u",
5030       stream->sample_index, stream->n_samples);
5031 
5032   if (G_UNLIKELY (stream->sample_index >= stream->n_samples)) {
5033     if (!qtdemux->fragmented)
5034     goto eos;
5035 
5036     GST_INFO_OBJECT (qtdemux, "out of samples, trying to add more");
5037     do {
5038       GstFlowReturn flow;
5039 
5040       GST_OBJECT_LOCK (qtdemux);
5041       flow = qtdemux_add_fragmented_samples (qtdemux);
5042       GST_OBJECT_UNLOCK (qtdemux);
5043 
5044       if (flow != GST_FLOW_OK)
5045         goto eos;
5046     }
5047     while (stream->sample_index >= stream->n_samples);
5048   }
5049 
5050   if (!qtdemux_parse_samples (qtdemux, stream, stream->sample_index)) {
5051     GST_LOG_OBJECT (qtdemux, "Parsing of index %u failed!",
5052         stream->sample_index);
5053     return FALSE;
5054   }
5055 
5056   /* now get the info for the sample we're at */
5057   sample = &stream->samples[stream->sample_index];
5058 
5059   *dts = QTSAMPLE_DTS (stream, sample);
5060   *pts = QTSAMPLE_PTS (stream, sample);
5061   *offset = sample->offset;
5062   *size = sample->size;
5063   *duration = QTSAMPLE_DUR_DTS (stream, sample, *dts);
5064   *keyframe = QTSAMPLE_KEYFRAME (stream, sample);
5065 
5066   return TRUE;
5067 
5068   /* special cases */
5069 eos:
5070   {
5071     stream->time_position = GST_CLOCK_TIME_NONE;
5072     return FALSE;
5073   }
5074 }
5075 
5076 /* move to the next sample in @stream.
5077  *
5078  * Moves to the next segment when needed.
5079  */
5080 static void
5081 gst_qtdemux_advance_sample (GstQTDemux * qtdemux, QtDemuxStream * stream)
5082 {
5083   QtDemuxSample *sample;
5084   QtDemuxSegment *segment;
5085 
5086   /* get current segment */
5087   segment = &stream->segments[stream->segment_index];
5088 
5089   if (G_UNLIKELY (QTSEGMENT_IS_EMPTY (segment))) {
5090     GST_DEBUG_OBJECT (qtdemux, "Empty segment, no samples to advance");
5091     goto next_segment;
5092   }
5093 
5094   if (G_UNLIKELY (stream->sample_index >= stream->to_sample)) {
5095     /* Mark the stream as EOS */
5096     GST_DEBUG_OBJECT (qtdemux,
5097         "reached max allowed sample %u, mark EOS", stream->to_sample);
5098     stream->time_position = GST_CLOCK_TIME_NONE;
5099     return;
5100   }
5101 
5102   /* move to next sample */
5103   stream->sample_index++;
5104   stream->offset_in_sample = 0;
5105 
5106   /* reached the last sample, we need the next segment */
5107   if (G_UNLIKELY (stream->sample_index >= stream->n_samples))
5108     goto next_segment;
5109 
5110   if (!qtdemux_parse_samples (qtdemux, stream, stream->sample_index)) {
5111     GST_LOG_OBJECT (qtdemux, "Parsing of index %u failed!",
5112         stream->sample_index);
5113     return;
5114   }
5115 
5116   /* get next sample */
5117   sample = &stream->samples[stream->sample_index];
5118 
5119   /* see if we are past the segment */
5120   if (G_UNLIKELY (QTSAMPLE_DTS (stream, sample) >= segment->media_stop))
5121     goto next_segment;
5122 
5123   if (QTSAMPLE_DTS (stream, sample) >= segment->media_start) {
5124     /* inside the segment, update time_position, looks very familiar to
5125      * GStreamer segments, doesn't it? */
5126     stream->time_position =
5127         QTSAMPLE_DTS (stream, sample) - segment->media_start + segment->time;
5128   } else {
5129     /* not yet in segment, time does not yet increment. This means
5130      * that we are still prerolling keyframes to the decoder so it can
5131      * decode the first sample of the segment. */
5132     stream->time_position = segment->time;
5133   }
5134   return;
5135 
5136   /* move to the next segment */
5137 next_segment:
5138   {
5139     GST_DEBUG_OBJECT (qtdemux, "segment %d ended ", stream->segment_index);
5140 
5141     if (stream->segment_index == stream->n_segments - 1) {
5142       /* are we at the end of the last segment, we're EOS */
5143       stream->time_position = GST_CLOCK_TIME_NONE;
5144     } else {
5145       /* else we're only at the end of the current segment */
5146       stream->time_position = segment->stop_time;
5147     }
5148     /* make sure we select a new segment */
5149 
5150     /* accumulate previous segments */
5151     if (GST_CLOCK_TIME_IS_VALID (stream->segment.stop))
5152       stream->accumulated_base +=
5153           (stream->segment.stop -
5154           stream->segment.start) / ABS (stream->segment.rate);
5155 
5156     stream->segment_index = -1;
5157   }
5158 }
5159 
5160 static void
5161 gst_qtdemux_sync_streams (GstQTDemux * demux)
5162 {
5163   gint i;
5164 
5165   if (demux->n_streams <= 1)
5166     return;
5167 
5168   for (i = 0; i < demux->n_streams; i++) {
5169     QtDemuxStream *stream;
5170     GstClockTime end_time;
5171 
5172     stream = demux->streams[i];
5173 
5174     if (!stream->pad)
5175       continue;
5176 
5177     /* TODO advance time on subtitle streams here, if any some day */
5178 
5179     /* some clips/trailers may have unbalanced streams at the end,
5180      * so send EOS on shorter stream to prevent stalling others */
5181 
5182     /* do not mess with EOS if SEGMENT seeking */
5183     if (demux->segment.flags & GST_SEEK_FLAG_SEGMENT)
5184       continue;
5185 
5186     if (demux->pullbased) {
5187       /* loop mode is sample time based */
5188       if (!STREAM_IS_EOS (stream))
5189         continue;
5190     } else {
5191       /* push mode is byte position based */
5192       if (stream->n_samples &&
5193           stream->samples[stream->n_samples - 1].offset >= demux->offset)
5194         continue;
5195     }
5196 
5197     if (stream->sent_eos)
5198       continue;
5199 
5200     /* only act if some gap */
5201     end_time = stream->segments[stream->n_segments - 1].stop_time;
5202     GST_LOG_OBJECT (demux, "current position: %" GST_TIME_FORMAT
5203         ", stream end: %" GST_TIME_FORMAT,
5204         GST_TIME_ARGS (demux->segment.position), GST_TIME_ARGS (end_time));
5205     if (GST_CLOCK_TIME_IS_VALID (end_time)
5206         && (end_time + 2 * GST_SECOND < demux->segment.position)) {
5207       GstEvent *event;
5208 
5209       GST_DEBUG_OBJECT (demux, "sending EOS for stream %s",
5210           GST_PAD_NAME (stream->pad));
5211       stream->sent_eos = TRUE;
5212       event = gst_event_new_eos ();
5213       if (demux->segment_seqnum != GST_SEQNUM_INVALID)
5214         gst_event_set_seqnum (event, demux->segment_seqnum);
5215       gst_pad_push_event (stream->pad, event);
5216     }
5217   }
5218 }
5219 
5220 /* EOS and NOT_LINKED need to be combined. This means that we return:
5221  *
5222  *  GST_FLOW_NOT_LINKED: when all pads NOT_LINKED.
5223  *  GST_FLOW_EOS: when all pads EOS or NOT_LINKED.
5224  */
5225 static GstFlowReturn
5226 gst_qtdemux_combine_flows (GstQTDemux * demux, QtDemuxStream * stream,
5227     GstFlowReturn ret)
5228 {
5229   GST_LOG_OBJECT (demux, "flow return: %s", gst_flow_get_name (ret));
5230 
5231   if (stream->pad)
5232     ret = gst_flow_combiner_update_pad_flow (demux->flowcombiner, stream->pad,
5233         ret);
5234   else
5235   ret = gst_flow_combiner_update_flow (demux->flowcombiner, ret);
5236 
5237   GST_LOG_OBJECT (demux, "combined flow return: %s", gst_flow_get_name (ret));
5238   return ret;
5239 }
5240 
5241 /* the input buffer metadata must be writable. Returns NULL when the buffer is
5242  * completely clipped
5243  *
5244  * Should be used only with raw buffers */
5245 static GstBuffer *
5246 gst_qtdemux_clip_buffer (GstQTDemux * qtdemux, QtDemuxStream * stream,
5247     GstBuffer * buf)
5248 {
5249   guint64 start, stop, cstart, cstop, diff;
5250   GstClockTime pts, duration;
5251   gsize size, osize;
5252   gint num_rate, denom_rate;
5253   gint frame_size;
5254   gboolean clip_data;
5255   guint offset;
5256 
5257   osize = size = gst_buffer_get_size (buf);
5258   offset = 0;
5259 
5260   /* depending on the type, setup the clip parameters */
5261   if (stream->subtype == FOURCC_soun) {
5262     frame_size = CUR_STREAM (stream)->bytes_per_frame;
5263     num_rate = GST_SECOND;
5264     denom_rate = (gint) CUR_STREAM (stream)->rate;
5265     clip_data = TRUE;
5266   } else if (stream->subtype == FOURCC_vide) {
5267     frame_size = size;
5268     num_rate = CUR_STREAM (stream)->fps_n;
5269     denom_rate = CUR_STREAM (stream)->fps_d;
5270     clip_data = FALSE;
5271   } else
5272     goto wrong_type;
5273 
5274   if (frame_size <= 0)
5275     goto bad_frame_size;
5276 
5277   /* we can only clip if we have a valid pts */
5278   pts = GST_BUFFER_PTS (buf);
5279   if (G_UNLIKELY (!GST_CLOCK_TIME_IS_VALID (pts)))
5280     goto no_pts;
5281 
5282     duration = GST_BUFFER_DURATION (buf);
5283 
5284   if (G_UNLIKELY (!GST_CLOCK_TIME_IS_VALID (duration))) {
5285     duration =
5286         gst_util_uint64_scale_int (size / frame_size, num_rate, denom_rate);
5287   }
5288 
5289   start = pts;
5290   stop = start + duration;
5291 
5292   if (G_UNLIKELY (!gst_segment_clip (&stream->segment,
5293               GST_FORMAT_TIME, start, stop, &cstart, &cstop)))
5294     goto clipped;
5295 
5296   /* see if some clipping happened */
5297   diff = cstart - start;
5298   if (diff > 0) {
5299     pts += diff;
5300     duration -= diff;
5301 
5302     if (clip_data) {
5303       /* bring clipped time to samples and to bytes */
5304       diff = gst_util_uint64_scale_int (diff, denom_rate, num_rate);
5305       diff *= frame_size;
5306 
5307       GST_DEBUG_OBJECT (qtdemux,
5308           "clipping start to %" GST_TIME_FORMAT " %"
5309           G_GUINT64_FORMAT " bytes", GST_TIME_ARGS (cstart), diff);
5310 
5311       offset = diff;
5312       size -= diff;
5313     }
5314   }
5315   diff = stop - cstop;
5316   if (diff > 0) {
5317     duration -= diff;
5318 
5319     if (clip_data) {
5320       /* bring clipped time to samples and then to bytes */
5321       diff = gst_util_uint64_scale_int (diff, denom_rate, num_rate);
5322       diff *= frame_size;
5323       GST_DEBUG_OBJECT (qtdemux,
5324           "clipping stop to %" GST_TIME_FORMAT " %" G_GUINT64_FORMAT
5325           " bytes", GST_TIME_ARGS (cstop), diff);
5326       size -= diff;
5327     }
5328   }
5329 
5330   if (offset != 0 || size != osize)
5331     gst_buffer_resize (buf, offset, size);
5332 
5333   GST_BUFFER_DTS (buf) = GST_CLOCK_TIME_NONE;
5334   GST_BUFFER_PTS (buf) = pts;
5335   GST_BUFFER_DURATION (buf) = duration;
5336 
5337   return buf;
5338 
5339   /* dropped buffer */
5340 wrong_type:
5341   {
5342     GST_DEBUG_OBJECT (qtdemux, "unknown stream type");
5343     return buf;
5344   }
5345 bad_frame_size:
5346   {
5347     GST_DEBUG_OBJECT (qtdemux, "bad frame size");
5348     return buf;
5349   }
5350 no_pts:
5351   {
5352     GST_DEBUG_OBJECT (qtdemux, "no pts on buffer");
5353     return buf;
5354   }
5355 clipped:
5356   {
5357     GST_DEBUG_OBJECT (qtdemux, "clipped buffer");
5358     gst_buffer_unref (buf);
5359     return NULL;
5360   }
5361 }
5362 
5363 static GstBuffer *
5364 gst_qtdemux_align_buffer (GstQTDemux * demux,
5365     GstBuffer * buffer, gsize alignment)
5366 {
5367   GstMapInfo map;
5368 
5369   gst_buffer_map (buffer, &map, GST_MAP_READ);
5370 
5371   if (map.size < sizeof (guintptr)) {
5372     gst_buffer_unmap (buffer, &map);
5373     return buffer;
5374   }
5375 
5376   if (((guintptr) map.data) & (alignment - 1)) {
5377     GstBuffer *new_buffer;
5378     GstAllocationParams params = { 0, alignment - 1, 0, 0, };
5379 
5380     new_buffer = gst_buffer_new_allocate (NULL,
5381         gst_buffer_get_size (buffer), &params);
5382 
5383     /* Copy data "by hand", so ensure alignment is kept: */
5384     gst_buffer_fill (new_buffer, 0, map.data, map.size);
5385 
5386     gst_buffer_copy_into (new_buffer, buffer, GST_BUFFER_COPY_METADATA, 0, -1);
5387     GST_DEBUG_OBJECT (demux,
5388         "We want output aligned on %" G_GSIZE_FORMAT ", reallocated",
5389         alignment);
5390 
5391     gst_buffer_unmap (buffer, &map);
5392     gst_buffer_unref (buffer);
5393 
5394     return new_buffer;
5395   }
5396 
5397   gst_buffer_unmap (buffer, &map);
5398   return buffer;
5399 }
5400 
5401 /* the input buffer metadata must be writable,
5402  * but time/duration etc not yet set and need not be preserved */
5403 static GstBuffer *
5404 gst_qtdemux_process_buffer (GstQTDemux * qtdemux, QtDemuxStream * stream,
5405     GstBuffer * buf)
5406 {
5407   GstMapInfo map;
5408   guint nsize = 0;
5409   gchar *str;
5410 
5411   /* not many cases for now */
5412   if (G_UNLIKELY (CUR_STREAM (stream)->fourcc == FOURCC_mp4s)) {
5413     /* send a one time dvd clut event */
5414     if (stream->pending_event && stream->pad)
5415       gst_pad_push_event (stream->pad, stream->pending_event);
5416     stream->pending_event = NULL;
5417   }
5418 
5419   if (G_UNLIKELY (stream->subtype != FOURCC_text
5420           && stream->subtype != FOURCC_sbtl &&
5421           stream->subtype != FOURCC_subp)) {
5422     return buf;
5423   }
5424 
5425   gst_buffer_map (buf, &map, GST_MAP_READ);
5426 
5427   /* empty buffer is sent to terminate previous subtitle */
5428   if (map.size <= 2) {
5429     gst_buffer_unmap (buf, &map);
5430     gst_buffer_unref (buf);
5431     return NULL;
5432   }
5433   if (stream->subtype == FOURCC_subp) {
5434     /* That's all the processing needed for subpictures */
5435     gst_buffer_unmap (buf, &map);
5436     return buf;
5437   }
5438 
5439   nsize = GST_READ_UINT16_BE (map.data);
5440   nsize = MIN (nsize, map.size - 2);
5441 
5442   GST_LOG_OBJECT (qtdemux, "3GPP timed text subtitle: %d/%" G_GSIZE_FORMAT "",
5443       nsize, map.size);
5444 
5445   /* takes care of UTF-8 validation or UTF-16 recognition,
5446    * no other encoding expected */
5447   str = gst_tag_freeform_string_to_utf8 ((gchar *) map.data + 2, nsize, NULL);
5448   gst_buffer_unmap (buf, &map);
5449   if (str) {
5450     gst_buffer_unref (buf);
5451     buf = _gst_buffer_new_wrapped (str, strlen (str), g_free);
5452   } else {
5453     /* this should not really happen unless the subtitle is corrupted */
5454     gst_buffer_unref (buf);
5455     buf = NULL;
5456   }
5457 
5458   /* FIXME ? convert optional subsequent style info to markup */
5459 
5460   return buf;
5461 }
5462 
5463 /* Sets a buffer's attributes properly and pushes it downstream.
5464  * Also checks for additional actions and custom processing that may
5465  * need to be done first.
5466  */
5467 static GstFlowReturn
5468 gst_qtdemux_decorate_and_push_buffer (GstQTDemux * qtdemux,
5469     QtDemuxStream * stream, GstBuffer * buf,
5470     GstClockTime dts, GstClockTime pts, GstClockTime duration,
5471     gboolean keyframe, GstClockTime position, guint64 byte_position)
5472 {
5473   GstFlowReturn ret = GST_FLOW_OK;
5474 
5475   /* offset the timestamps according to the edit list */
5476 
5477   if (G_UNLIKELY (CUR_STREAM (stream)->fourcc == FOURCC_rtsp)) {
5478     gchar *url;
5479     GstMapInfo map;
5480 
5481     gst_buffer_map (buf, &map, GST_MAP_READ);
5482     url = g_strndup ((gchar *) map.data, map.size);
5483     gst_buffer_unmap (buf, &map);
5484     if (url != NULL && strlen (url) != 0) {
5485       /* we have RTSP redirect now */
5486       gst_element_post_message (GST_ELEMENT_CAST (qtdemux),
5487           gst_message_new_element (GST_OBJECT_CAST (qtdemux),
5488               gst_structure_new ("redirect",
5489                   "new-location", G_TYPE_STRING, url, NULL)));
5490       qtdemux->posted_redirect = TRUE;
5491     } else {
5492       GST_WARNING_OBJECT (qtdemux, "Redirect URI of stream is empty, not "
5493           "posting");
5494     }
5495     g_free (url);
5496   }
5497 
5498   /* position reporting */
5499   if (qtdemux->segment.rate >= 0) {
5500     qtdemux->segment.position = position;
5501     gst_qtdemux_sync_streams (qtdemux);
5502   }
5503 
5504   if (G_UNLIKELY (!stream->pad)) {
5505     GST_DEBUG_OBJECT (qtdemux, "No output pad for stream, ignoring");
5506     gst_buffer_unref (buf);
5507     goto exit;
5508   }
5509 
5510   /* send out pending buffers */
5511   while (stream->buffers) {
5512     GstBuffer *buffer = (GstBuffer *) stream->buffers->data;
5513 
5514     if (G_UNLIKELY (stream->discont)) {
5515       GST_LOG_OBJECT (qtdemux, "marking discont buffer");
5516       GST_BUFFER_FLAG_SET (buffer, GST_BUFFER_FLAG_DISCONT);
5517       stream->discont = FALSE;
5518     } else {
5519       GST_BUFFER_FLAG_UNSET (buf, GST_BUFFER_FLAG_DISCONT);
5520     }
5521 
5522     if (stream->alignment > 1)
5523       buffer = gst_qtdemux_align_buffer (qtdemux, buffer, stream->alignment);
5524     gst_pad_push (stream->pad, buffer);
5525 
5526     stream->buffers = g_slist_delete_link (stream->buffers, stream->buffers);
5527   }
5528 
5529   /* we're going to modify the metadata */
5530   buf = gst_buffer_make_writable (buf);
5531 
5532   if (G_UNLIKELY (stream->need_process))
5533     buf = gst_qtdemux_process_buffer (qtdemux, stream, buf);
5534 
5535   if (!buf) {
5536     goto exit;
5537   }
5538 
5539   GST_BUFFER_DTS (buf) = dts;
5540   GST_BUFFER_PTS (buf) = pts;
5541   GST_BUFFER_DURATION (buf) = duration;
5542   GST_BUFFER_OFFSET (buf) = -1;
5543   GST_BUFFER_OFFSET_END (buf) = -1;
5544 
5545   if (G_UNLIKELY (CUR_STREAM (stream)->rgb8_palette))
5546     gst_buffer_append_memory (buf,
5547         gst_memory_ref (CUR_STREAM (stream)->rgb8_palette));
5548 
5549   if (G_UNLIKELY (CUR_STREAM (stream)->padding)) {
5550     gst_buffer_resize (buf, CUR_STREAM (stream)->padding, -1);
5551   }
5552 #if 0
5553   if (G_UNLIKELY (qtdemux->element_index)) {
5554     GstClockTime stream_time;
5555 
5556     stream_time =
5557         gst_segment_to_stream_time (&stream->segment, GST_FORMAT_TIME,
5558         timestamp);
5559     if (GST_CLOCK_TIME_IS_VALID (stream_time)) {
5560       GST_LOG_OBJECT (qtdemux,
5561           "adding association %" GST_TIME_FORMAT "-> %"
5562           G_GUINT64_FORMAT, GST_TIME_ARGS (stream_time), byte_position);
5563       gst_index_add_association (qtdemux->element_index,
5564           qtdemux->index_id,
5565           keyframe ? GST_ASSOCIATION_FLAG_KEY_UNIT :
5566           GST_ASSOCIATION_FLAG_DELTA_UNIT, GST_FORMAT_TIME, stream_time,
5567           GST_FORMAT_BYTES, byte_position, NULL);
5568     }
5569   }
5570 #endif
5571 
5572   if (stream->need_clip)
5573     buf = gst_qtdemux_clip_buffer (qtdemux, stream, buf);
5574 
5575   if (G_UNLIKELY (buf == NULL))
5576     goto exit;
5577 
5578   if (G_UNLIKELY (stream->discont)) {
5579     GST_LOG_OBJECT (qtdemux, "marking discont buffer");
5580     GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_DISCONT);
5581     stream->discont = FALSE;
5582   } else {
5583     GST_BUFFER_FLAG_UNSET (buf, GST_BUFFER_FLAG_DISCONT);
5584   }
5585 
5586   if (!keyframe) {
5587     GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_DELTA_UNIT);
5588     stream->on_keyframe = FALSE;
5589   } else {
5590     stream->on_keyframe = TRUE;
5591   }
5592 
5593 
5594   GST_LOG_OBJECT (qtdemux,
5595       "Pushing buffer with dts %" GST_TIME_FORMAT ", pts %" GST_TIME_FORMAT
5596       ", duration %" GST_TIME_FORMAT " on pad %s", GST_TIME_ARGS (dts),
5597       GST_TIME_ARGS (pts), GST_TIME_ARGS (duration),
5598       GST_PAD_NAME (stream->pad));
5599 
5600   if (stream->protected && stream->protection_scheme_type == FOURCC_cenc) {
5601     GstStructure *crypto_info;
5602     QtDemuxCencSampleSetInfo *info =
5603         (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
5604     gint index;
5605     GstEvent *event;
5606 
5607     while ((event = g_queue_pop_head (&stream->protection_scheme_event_queue))) {
5608       gst_pad_push_event (stream->pad, event);
5609     }
5610 
5611     if (info->crypto_info == NULL) {
5612       GST_DEBUG_OBJECT (qtdemux, "cenc metadata hasn't been parsed yet");
5613       gst_buffer_unref (buf);
5614       goto exit;
5615     }
5616 
5617     /* The end of the crypto_info array matches our n_samples position,
5618      * so count backward from there */
5619     index = stream->sample_index - stream->n_samples + info->crypto_info->len;
5620     if (G_LIKELY (index >= 0 && index < info->crypto_info->len)) {
5621       /* steal structure from array */
5622       crypto_info = g_ptr_array_index (info->crypto_info, index);
5623       g_ptr_array_index (info->crypto_info, index) = NULL;
5624       GST_LOG_OBJECT (qtdemux, "attaching cenc metadata [%u/%u]", index,
5625           info->crypto_info->len);
5626       if (!crypto_info || !gst_buffer_add_protection_meta (buf, crypto_info))
5627         GST_ERROR_OBJECT (qtdemux, "failed to attach cenc metadata to buffer");
5628     } else {
5629       GST_INFO_OBJECT (qtdemux, "No crypto info with index %d and sample %d",
5630           index, stream->sample_index);
5631     }
5632   }
5633 
5634   if (stream->alignment > 1)
5635     buf = gst_qtdemux_align_buffer (qtdemux, buf, stream->alignment);
5636 
5637   ret = gst_pad_push (stream->pad, buf);
5638 
5639   if (GST_CLOCK_TIME_IS_VALID (pts) && GST_CLOCK_TIME_IS_VALID (duration)) {
5640     /* mark position in stream, we'll need this to know when to send GAP event */
5641     stream->segment.position = pts + duration;
5642   }
5643 
5644 exit:
5645   return ret;
5646 }
5647 
5648 static const QtDemuxRandomAccessEntry *
5649 gst_qtdemux_stream_seek_fragment (GstQTDemux * qtdemux, QtDemuxStream * stream,
5650     GstClockTime pos, gboolean after)
5651 {
5652   QtDemuxRandomAccessEntry *entries = stream->ra_entries;
5653   guint n_entries = stream->n_ra_entries;
5654   guint i;
5655 
5656   /* we assume the table is sorted */
5657   for (i = 0; i < n_entries; ++i) {
5658     if (entries[i].ts > pos)
5659       break;
5660   }
5661 
5662   /* FIXME: maybe save first moof_offset somewhere instead, but for now it's
5663    * probably okay to assume that the index lists the very first fragment */
5664   if (i == 0)
5665     return &entries[0];
5666 
5667   if (after)
5668     return &entries[i];
5669   else
5670     return &entries[i - 1];
5671 }
5672 
5673 static gboolean
5674 gst_qtdemux_do_fragmented_seek (GstQTDemux * qtdemux)
5675 {
5676   const QtDemuxRandomAccessEntry *best_entry = NULL;
5677   guint i;
5678 
5679   GST_OBJECT_LOCK (qtdemux);
5680 
5681   g_assert (qtdemux->n_streams > 0);
5682 
5683   /* first see if we can determine where to go to using mfra,
5684    * before we start clearing things */
5685   for (i = 0; i < qtdemux->n_streams; i++) {
5686     const QtDemuxRandomAccessEntry *entry;
5687     QtDemuxStream *stream;
5688     gboolean is_audio_or_video;
5689 
5690     stream = qtdemux->streams[i];
5691 
5692     if (stream->ra_entries == NULL)
5693       continue;
5694 
5695     if (stream->subtype == FOURCC_vide || stream->subtype == FOURCC_soun)
5696       is_audio_or_video = TRUE;
5697     else
5698       is_audio_or_video = FALSE;
5699 
5700     entry =
5701         gst_qtdemux_stream_seek_fragment (qtdemux, stream,
5702         stream->time_position, !is_audio_or_video);
5703 
5704     GST_INFO_OBJECT (stream->pad, "%" GST_TIME_FORMAT " at offset "
5705         "%" G_GUINT64_FORMAT, GST_TIME_ARGS (entry->ts), entry->moof_offset);
5706 
5707     stream->pending_seek = entry;
5708 
5709     /* decide position to jump to just based on audio/video tracks, not subs */
5710     if (!is_audio_or_video)
5711       continue;
5712 
5713     if (best_entry == NULL || entry->moof_offset < best_entry->moof_offset)
5714       best_entry = entry;
5715   }
5716 
5717   /* no luck, will handle seek otherwise */
5718   if (best_entry == NULL) {
5719     GST_OBJECT_UNLOCK (qtdemux);
5720     return FALSE;
5721   }
5722 
5723   /* ok, now we can prepare for processing as of located moof */
5724   for (i = 0; i < qtdemux->n_streams; i++) {
5725     QtDemuxStream *stream;
5726 
5727     stream = qtdemux->streams[i];
5728 
5729     g_free (stream->samples);
5730     stream->samples = NULL;
5731     stream->n_samples = 0;
5732     stream->stbl_index = -1;    /* no samples have yet been parsed */
5733     stream->sample_index = -1;
5734 
5735     if (stream->protection_scheme_info) {
5736       /* Clear out any old cenc crypto info entries as we'll move to a new moof */
5737       if (stream->protection_scheme_type == FOURCC_cenc) {
5738         QtDemuxCencSampleSetInfo *info =
5739             (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
5740         if (info->crypto_info) {
5741           g_ptr_array_free (info->crypto_info, TRUE);
5742           info->crypto_info = NULL;
5743         }
5744       }
5745     }
5746   }
5747 
5748   GST_INFO_OBJECT (qtdemux, "seek to %" GST_TIME_FORMAT ", best fragment "
5749       "moof offset: %" G_GUINT64_FORMAT ", ts %" GST_TIME_FORMAT,
5750       GST_TIME_ARGS (qtdemux->streams[0]->time_position),
5751       best_entry->moof_offset, GST_TIME_ARGS (best_entry->ts));
5752 
5753   qtdemux->moof_offset = best_entry->moof_offset;
5754 
5755   qtdemux_add_fragmented_samples (qtdemux);
5756 
5757   GST_OBJECT_UNLOCK (qtdemux);
5758   return TRUE;
5759 }
5760 
5761 static GstFlowReturn
5762 gst_qtdemux_loop_state_movie (GstQTDemux * qtdemux)
5763 {
5764   GstFlowReturn ret = GST_FLOW_OK;
5765   GstBuffer *buf = NULL;
5766   QtDemuxStream *stream;
5767   GstClockTime min_time;
5768   guint64 offset = 0;
5769   GstClockTime dts = GST_CLOCK_TIME_NONE;
5770   GstClockTime pts = GST_CLOCK_TIME_NONE;
5771   GstClockTime duration = 0;
5772   gboolean keyframe = FALSE;
5773   guint sample_size = 0;
5774   gboolean empty = 0;
5775   guint size;
5776   gint index;
5777   gint i;
5778 
5779   gst_qtdemux_push_pending_newsegment (qtdemux);
5780 
5781   if (qtdemux->fragmented_seek_pending) {
5782     GST_INFO_OBJECT (qtdemux, "pending fragmented seek");
5783     if (gst_qtdemux_do_fragmented_seek (qtdemux)) {
5784       GST_INFO_OBJECT (qtdemux, "fragmented seek done!");
5785       qtdemux->fragmented_seek_pending = FALSE;
5786     } else {
5787       GST_INFO_OBJECT (qtdemux, "fragmented seek still pending");
5788     }
5789   }
5790 
5791   /* Figure out the next stream sample to output, min_time is expressed in
5792    * global time and runs over the edit list segments. */
5793   min_time = G_MAXUINT64;
5794   index = -1;
5795   for (i = 0; i < qtdemux->n_streams; i++) {
5796     GstClockTime position;
5797 
5798     stream = qtdemux->streams[i];
5799     position = stream->time_position;
5800 
5801     /* position of -1 is EOS */
5802     if (position != GST_CLOCK_TIME_NONE && position < min_time) {
5803       min_time = position;
5804       index = i;
5805     }
5806   }
5807   /* all are EOS */
5808   if (G_UNLIKELY (index == -1)) {
5809     GST_DEBUG_OBJECT (qtdemux, "all streams are EOS");
5810     goto eos;
5811   }
5812 
5813   /* check for segment end */
5814   if (G_UNLIKELY (qtdemux->segment.stop != -1
5815           && ((qtdemux->segment.rate >= 0 && qtdemux->segment.stop <= min_time)
5816               || (qtdemux->segment.rate < 0
5817                   && qtdemux->segment.start > min_time))
5818           && qtdemux->streams[index]->on_keyframe)) {
5819     GST_DEBUG_OBJECT (qtdemux, "we reached the end of our segment.");
5820     qtdemux->streams[index]->time_position = GST_CLOCK_TIME_NONE;
5821     goto eos_stream;
5822   }
5823 
5824   /* gap events for subtitle streams */
5825   for (i = 0; i < qtdemux->n_streams; i++) {
5826     stream = qtdemux->streams[i];
5827     if (stream->pad && (stream->subtype == FOURCC_subp
5828             || stream->subtype == FOURCC_text
5829             || stream->subtype == FOURCC_sbtl)) {
5830       /* send one second gap events until the stream catches up */
5831       /* gaps can only be sent after segment is activated (segment.stop is no longer -1) */
5832       while (GST_CLOCK_TIME_IS_VALID (stream->segment.stop) &&
5833           GST_CLOCK_TIME_IS_VALID (stream->segment.position) &&
5834           stream->segment.position + GST_SECOND < min_time) {
5835         GstEvent *gap =
5836             gst_event_new_gap (stream->segment.position, GST_SECOND);
5837         gst_pad_push_event (stream->pad, gap);
5838         stream->segment.position += GST_SECOND;
5839       }
5840     }
5841   }
5842 
5843   stream = qtdemux->streams[index];
5844   /* fetch info for the current sample of this stream */
5845   if (G_UNLIKELY (!gst_qtdemux_prepare_current_sample (qtdemux, stream, &empty,
5846               &offset, &sample_size, &dts, &pts, &duration, &keyframe)))
5847     goto eos_stream;
5848 
5849   gst_qtdemux_stream_check_and_change_stsd_index (qtdemux, stream);
5850   if (stream->new_caps) {
5851     gst_qtdemux_configure_stream (qtdemux, stream);
5852     qtdemux_do_allocation (qtdemux, stream);
5853   }
5854 
5855   /* If we're doing a keyframe-only trickmode, only push keyframes on video streams */
5856   if (G_UNLIKELY (qtdemux->
5857           segment.flags & GST_SEGMENT_FLAG_TRICKMODE_KEY_UNITS)) {
5858     if (stream->subtype == FOURCC_vide && !keyframe) {
5859       GST_LOG_OBJECT (qtdemux, "Skipping non-keyframe on stream %d", index);
5860       goto next;
5861     }
5862   }
5863 
5864   GST_DEBUG_OBJECT (qtdemux,
5865       "pushing from stream %d, empty %d offset %" G_GUINT64_FORMAT
5866       ", size %d, dts=%" GST_TIME_FORMAT ", pts=%" GST_TIME_FORMAT
5867       ", duration %" GST_TIME_FORMAT, index, empty, offset, sample_size,
5868       GST_TIME_ARGS (dts), GST_TIME_ARGS (pts), GST_TIME_ARGS (duration));
5869 
5870   if (G_UNLIKELY (empty)) {
5871     /* empty segment, push a gap if there's a second or more
5872      * difference and move to the next one */
5873     if ((pts + duration - stream->segment.position) >= GST_SECOND)
5874     gst_pad_push_event (stream->pad, gst_event_new_gap (pts, duration));
5875     stream->segment.position = pts + duration;
5876     goto next;
5877   }
5878 
5879   /* hmm, empty sample, skip and move to next sample */
5880   if (G_UNLIKELY (sample_size <= 0))
5881     goto next;
5882 
5883   /* last pushed sample was out of boundary, goto next sample */
5884   if (G_UNLIKELY (GST_PAD_LAST_FLOW_RETURN (stream->pad) == GST_FLOW_EOS))
5885     goto next;
5886 
5887   if (stream->max_buffer_size == 0 || sample_size <= stream->max_buffer_size) {
5888     size = sample_size;
5889   } else {
5890     GST_DEBUG_OBJECT (qtdemux,
5891         "size %d larger than stream max_buffer_size %d, trimming",
5892         sample_size, stream->max_buffer_size);
5893     size =
5894         MIN (sample_size - stream->offset_in_sample, stream->max_buffer_size);
5895   }
5896 
5897   if (qtdemux->cenc_aux_info_offset > 0) {
5898     GstMapInfo map;
5899     GstByteReader br;
5900     GstBuffer *aux_info = NULL;
5901 
5902     /* pull the data stored before the sample */
5903     ret =
5904         gst_qtdemux_pull_atom (qtdemux, qtdemux->offset,
5905         offset + stream->offset_in_sample - qtdemux->offset, &aux_info);
5906     if (G_UNLIKELY (ret != GST_FLOW_OK))
5907       goto beach;
5908     gst_buffer_map (aux_info, &map, GST_MAP_READ);
5909     GST_DEBUG_OBJECT (qtdemux, "parsing cenc auxiliary info");
5910     gst_byte_reader_init (&br, map.data + 8, map.size);
5911     if (!qtdemux_parse_cenc_aux_info (qtdemux, stream, &br,
5912             qtdemux->cenc_aux_info_sizes, qtdemux->cenc_aux_sample_count)) {
5913       GST_ERROR_OBJECT (qtdemux, "failed to parse cenc auxiliary info");
5914       gst_buffer_unmap (aux_info, &map);
5915       gst_buffer_unref (aux_info);
5916       ret = GST_FLOW_ERROR;
5917       goto beach;
5918     }
5919     gst_buffer_unmap (aux_info, &map);
5920     gst_buffer_unref (aux_info);
5921   }
5922 
5923   GST_LOG_OBJECT (qtdemux, "reading %d bytes @ %" G_GUINT64_FORMAT, size,
5924       offset);
5925 
5926   if (stream->use_allocator) {
5927     /* if we have a per-stream allocator, use it */
5928     buf = gst_buffer_new_allocate (stream->allocator, size, &stream->params);
5929   }
5930 
5931   ret = gst_qtdemux_pull_atom (qtdemux, offset + stream->offset_in_sample,
5932       size, &buf);
5933   if (G_UNLIKELY (ret != GST_FLOW_OK))
5934     goto beach;
5935 
5936   if (size != sample_size) {
5937     pts += gst_util_uint64_scale_int (GST_SECOND,
5938         stream->offset_in_sample / CUR_STREAM (stream)->bytes_per_frame,
5939         stream->timescale);
5940     dts +=
5941         gst_util_uint64_scale_int (GST_SECOND,
5942         stream->offset_in_sample / CUR_STREAM (stream)->bytes_per_frame,
5943         stream->timescale);
5944     duration =
5945         gst_util_uint64_scale_int (GST_SECOND,
5946         size / CUR_STREAM (stream)->bytes_per_frame, stream->timescale);
5947   }
5948 
5949   ret = gst_qtdemux_decorate_and_push_buffer (qtdemux, stream, buf,
5950       dts, pts, duration, keyframe, min_time, offset);
5951 
5952   if (size != sample_size) {
5953     QtDemuxSample *sample = &stream->samples[stream->sample_index];
5954     QtDemuxSegment *segment = &stream->segments[stream->segment_index];
5955 
5956     GstClockTime time_position = QTSTREAMTIME_TO_GSTTIME (stream,
5957         sample->timestamp +
5958         stream->offset_in_sample / CUR_STREAM (stream)->bytes_per_frame);
5959     if (time_position >= segment->media_start) {
5960       /* inside the segment, update time_position, looks very familiar to
5961        * GStreamer segments, doesn't it? */
5962       stream->time_position = (time_position - segment->media_start) +
5963           segment->time;
5964     } else {
5965       /* not yet in segment, time does not yet increment. This means
5966        * that we are still prerolling keyframes to the decoder so it can
5967        * decode the first sample of the segment. */
5968       stream->time_position = segment->time;
5969     }
5970   }
5971 
5972   /* combine flows */
5973   ret = gst_qtdemux_combine_flows (qtdemux, stream, ret);
5974   /* ignore unlinked, we will not push on the pad anymore and we will EOS when
5975    * we have no more data for the pad to push */
5976   if (ret == GST_FLOW_EOS)
5977     ret = GST_FLOW_OK;
5978 
5979   stream->offset_in_sample += size;
5980   if (stream->offset_in_sample >= sample_size) {
5981     gst_qtdemux_advance_sample (qtdemux, stream);
5982   }
5983   goto beach;
5984 
5985 next:
5986   gst_qtdemux_advance_sample (qtdemux, stream);
5987 
5988 beach:
5989   return ret;
5990 
5991   /* special cases */
5992 eos:
5993   {
5994     GST_DEBUG_OBJECT (qtdemux, "No samples left for any streams - EOS");
5995     ret = GST_FLOW_EOS;
5996     goto beach;
5997   }
5998 eos_stream:
5999   {
6000     GST_DEBUG_OBJECT (qtdemux, "No samples left for stream");
6001     /* EOS will be raised if all are EOS */
6002     ret = GST_FLOW_OK;
6003     goto beach;
6004   }
6005 }
6006 
6007 static void
6008 gst_qtdemux_loop (GstPad * pad)
6009 {
6010   GstQTDemux *qtdemux;
6011   guint64 cur_offset;
6012   GstFlowReturn ret;
6013 
6014   qtdemux = GST_QTDEMUX (gst_pad_get_parent (pad));
6015 
6016   cur_offset = qtdemux->offset;
6017   GST_LOG_OBJECT (qtdemux, "loop at position %" G_GUINT64_FORMAT ", state %s",
6018       cur_offset, qt_demux_state_string (qtdemux->state));
6019 
6020   switch (qtdemux->state) {
6021     case QTDEMUX_STATE_INITIAL:
6022     case QTDEMUX_STATE_HEADER:
6023       ret = gst_qtdemux_loop_state_header (qtdemux);
6024       break;
6025     case QTDEMUX_STATE_MOVIE:
6026       ret = gst_qtdemux_loop_state_movie (qtdemux);
6027       if (qtdemux->segment.rate < 0 && ret == GST_FLOW_EOS) {
6028         ret = gst_qtdemux_seek_to_previous_keyframe (qtdemux);
6029       }
6030       break;
6031     default:
6032       /* ouch */
6033       goto invalid_state;
6034   }
6035 
6036   /* if something went wrong, pause */
6037   if (ret != GST_FLOW_OK)
6038     goto pause;
6039 
6040 done:
6041   gst_object_unref (qtdemux);
6042   return;
6043 
6044   /* ERRORS */
6045 invalid_state:
6046   {
6047     GST_ELEMENT_ERROR (qtdemux, STREAM, FAILED,
6048         (NULL), ("streaming stopped, invalid state"));
6049     gst_pad_pause_task (pad);
6050     gst_qtdemux_push_event (qtdemux, gst_event_new_eos ());
6051     goto done;
6052   }
6053 pause:
6054   {
6055     const gchar *reason = gst_flow_get_name (ret);
6056 
6057     GST_LOG_OBJECT (qtdemux, "pausing task, reason %s", reason);
6058 
6059     gst_pad_pause_task (pad);
6060 
6061     /* fatal errors need special actions */
6062     /* check EOS */
6063     if (ret == GST_FLOW_EOS) {
6064       if (qtdemux->n_streams == 0) {
6065         /* we have no streams, post an error */
6066         gst_qtdemux_post_no_playable_stream_error (qtdemux);
6067       }
6068       if (qtdemux->segment.flags & GST_SEEK_FLAG_SEGMENT) {
6069         gint64 stop;
6070 
6071         if ((stop = qtdemux->segment.stop) == -1)
6072           stop = qtdemux->segment.duration;
6073 
6074         if (qtdemux->segment.rate >= 0) {
6075           GstMessage *message;
6076           GstEvent *event;
6077 
6078           GST_LOG_OBJECT (qtdemux, "Sending segment done, at end of segment");
6079           message = gst_message_new_segment_done (GST_OBJECT_CAST (qtdemux),
6080               GST_FORMAT_TIME, stop);
6081           event = gst_event_new_segment_done (GST_FORMAT_TIME, stop);
6082           if (qtdemux->segment_seqnum != GST_SEQNUM_INVALID) {
6083             gst_message_set_seqnum (message, qtdemux->segment_seqnum);
6084             gst_event_set_seqnum (event, qtdemux->segment_seqnum);
6085           }
6086           gst_element_post_message (GST_ELEMENT_CAST (qtdemux), message);
6087           gst_qtdemux_push_event (qtdemux, event);
6088         } else {
6089           GstMessage *message;
6090           GstEvent *event;
6091 
6092           /*  For Reverse Playback */
6093           GST_LOG_OBJECT (qtdemux, "Sending segment done, at start of segment");
6094           message = gst_message_new_segment_done (GST_OBJECT_CAST (qtdemux),
6095               GST_FORMAT_TIME, qtdemux->segment.start);
6096           event = gst_event_new_segment_done (GST_FORMAT_TIME,
6097               qtdemux->segment.start);
6098           if (qtdemux->segment_seqnum != GST_SEQNUM_INVALID) {
6099             gst_message_set_seqnum (message, qtdemux->segment_seqnum);
6100             gst_event_set_seqnum (event, qtdemux->segment_seqnum);
6101         }
6102           gst_element_post_message (GST_ELEMENT_CAST (qtdemux), message);
6103           gst_qtdemux_push_event (qtdemux, event);
6104         }
6105       } else {
6106         GstEvent *event;
6107 
6108         GST_LOG_OBJECT (qtdemux, "Sending EOS at end of segment");
6109         event = gst_event_new_eos ();
6110         if (qtdemux->segment_seqnum != GST_SEQNUM_INVALID)
6111           gst_event_set_seqnum (event, qtdemux->segment_seqnum);
6112         gst_qtdemux_push_event (qtdemux, event);
6113       }
6114     } else if (ret == GST_FLOW_NOT_LINKED || ret < GST_FLOW_EOS) {
6115       GST_ELEMENT_FLOW_ERROR (qtdemux, ret);
6116       gst_qtdemux_push_event (qtdemux, gst_event_new_eos ());
6117     }
6118     goto done;
6119   }
6120 }
6121 
6122 /*
6123  * has_next_entry
6124  *
6125  * Returns if there are samples to be played.
6126  */
6127 static gboolean
6128 has_next_entry (GstQTDemux * demux)
6129 {
6130   QtDemuxStream *stream;
6131   int i;
6132 
6133   GST_DEBUG_OBJECT (demux, "Checking if there are samples not played yet");
6134 
6135   for (i = 0; i < demux->n_streams; i++) {
6136     stream = demux->streams[i];
6137 
6138     if (stream->sample_index == -1) {
6139       stream->sample_index = 0;
6140       stream->offset_in_sample = 0;
6141     }
6142 
6143     if (stream->sample_index >= stream->n_samples) {
6144       GST_LOG_OBJECT (demux, "stream %d samples exhausted", i);
6145       continue;
6146     }
6147     GST_DEBUG_OBJECT (demux, "Found a sample");
6148     return TRUE;
6149   }
6150 
6151   GST_DEBUG_OBJECT (demux, "There wasn't any next sample");
6152   return FALSE;
6153 }
6154 
6155 /*
6156  * next_entry_size
6157  *
6158  * Returns the size of the first entry at the current offset.
6159  * If -1, there are none (which means EOS or empty file).
6160  */
6161 static guint64
6162 next_entry_size (GstQTDemux * demux)
6163 {
6164   QtDemuxStream *stream;
6165   int i;
6166   int smallidx = -1;
6167   guint64 smalloffs = (guint64) - 1;
6168   QtDemuxSample *sample;
6169 
6170   GST_LOG_OBJECT (demux, "Finding entry at offset %" G_GUINT64_FORMAT,
6171       demux->offset);
6172 
6173   for (i = 0; i < demux->n_streams; i++) {
6174     stream = demux->streams[i];
6175 
6176     if (stream->sample_index == -1) {
6177       stream->sample_index = 0;
6178       stream->offset_in_sample = 0;
6179     }
6180 
6181     if (stream->sample_index >= stream->n_samples) {
6182       GST_LOG_OBJECT (demux, "stream %d samples exhausted", i);
6183       continue;
6184     }
6185 
6186     if (!qtdemux_parse_samples (demux, stream, stream->sample_index)) {
6187       GST_LOG_OBJECT (demux, "Parsing of index %u from stbl atom failed!",
6188           stream->sample_index);
6189       return -1;
6190     }
6191 
6192     sample = &stream->samples[stream->sample_index];
6193 
6194     GST_LOG_OBJECT (demux,
6195         "Checking Stream %d (sample_index:%d / offset:%" G_GUINT64_FORMAT
6196         " / size:%" G_GUINT32_FORMAT ")", i, stream->sample_index,
6197         sample->offset, sample->size);
6198 
6199     if (((smalloffs == -1)
6200             || (sample->offset < smalloffs)) && (sample->size)) {
6201       smallidx = i;
6202       smalloffs = sample->offset;
6203     }
6204   }
6205 
6206   GST_LOG_OBJECT (demux,
6207       "stream %d offset %" G_GUINT64_FORMAT " demux->offset :%"
6208       G_GUINT64_FORMAT, smallidx, smalloffs, demux->offset);
6209 
6210   if (smallidx == -1)
6211     return -1;
6212 
6213   stream = demux->streams[smallidx];
6214   sample = &stream->samples[stream->sample_index];
6215 
6216   if (sample->offset >= demux->offset) {
6217     demux->todrop = sample->offset - demux->offset;
6218     return sample->size + demux->todrop;
6219   }
6220 
6221   GST_DEBUG_OBJECT (demux,
6222       "There wasn't any entry at offset %" G_GUINT64_FORMAT, demux->offset);
6223   return -1;
6224 }
6225 
6226 static void
6227 gst_qtdemux_post_progress (GstQTDemux * demux, gint num, gint denom)
6228 {
6229   gint perc = (gint) ((gdouble) num * 100.0 / (gdouble) denom);
6230 
6231   gst_element_post_message (GST_ELEMENT_CAST (demux),
6232       gst_message_new_element (GST_OBJECT_CAST (demux),
6233           gst_structure_new ("progress", "percent", G_TYPE_INT, perc, NULL)));
6234 }
6235 
6236 static gboolean
6237 qtdemux_seek_offset (GstQTDemux * demux, guint64 offset)
6238 {
6239   GstEvent *event;
6240   gboolean res = 0;
6241 
6242   GST_DEBUG_OBJECT (demux, "Seeking to %" G_GUINT64_FORMAT, offset);
6243 
6244   event =
6245       gst_event_new_seek (1.0, GST_FORMAT_BYTES,
6246       GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_ACCURATE, GST_SEEK_TYPE_SET, offset,
6247       GST_SEEK_TYPE_NONE, -1);
6248 
6249   /* store seqnum to drop flush events, they don't need to reach downstream */
6250   demux->offset_seek_seqnum = gst_event_get_seqnum (event);
6251   res = gst_pad_push_event (demux->sinkpad, event);
6252   demux->offset_seek_seqnum = GST_SEQNUM_INVALID;
6253 
6254   return res;
6255 }
6256 
6257 /* check for seekable upstream, above and beyond a mere query */
6258 static void
6259 gst_qtdemux_check_seekability (GstQTDemux * demux)
6260 {
6261   GstQuery *query;
6262   gboolean seekable = FALSE;
6263   gint64 start = -1, stop = -1;
6264 
6265   if (demux->upstream_size)
6266     return;
6267 
6268   if (demux->upstream_format_is_time)
6269     return;
6270 
6271   query = gst_query_new_seeking (GST_FORMAT_BYTES);
6272   if (!gst_pad_peer_query (demux->sinkpad, query)) {
6273     GST_DEBUG_OBJECT (demux, "seeking query failed");
6274     goto done;
6275   }
6276 
6277   gst_query_parse_seeking (query, NULL, &seekable, &start, &stop);
6278 
6279   /* try harder to query upstream size if we didn't get it the first time */
6280   if (seekable && stop == -1) {
6281     GST_DEBUG_OBJECT (demux, "doing duration query to fix up unset stop");
6282     gst_pad_peer_query_duration (demux->sinkpad, GST_FORMAT_BYTES, &stop);
6283   }
6284 
6285   /* if upstream doesn't know the size, it's likely that it's not seekable in
6286    * practice even if it technically may be seekable */
6287   if (seekable && (start != 0 || stop <= start)) {
6288     GST_DEBUG_OBJECT (demux, "seekable but unknown start/stop -> disable");
6289     seekable = FALSE;
6290   }
6291 
6292 done:
6293   gst_query_unref (query);
6294 
6295   GST_DEBUG_OBJECT (demux, "seekable: %d (%" G_GUINT64_FORMAT " - %"
6296       G_GUINT64_FORMAT ")", seekable, start, stop);
6297   demux->upstream_seekable = seekable;
6298   demux->upstream_size = seekable ? stop : -1;
6299 }
6300 
6301 static void
6302 gst_qtdemux_drop_data (GstQTDemux * demux, gint bytes)
6303 {
6304   g_return_if_fail (bytes <= demux->todrop);
6305 
6306   GST_LOG_OBJECT (demux, "Dropping %d bytes", bytes);
6307   gst_adapter_flush (demux->adapter, bytes);
6308   demux->neededbytes -= bytes;
6309   demux->offset += bytes;
6310   demux->todrop -= bytes;
6311 }
6312 
6313 static void
6314 gst_qtdemux_check_send_pending_segment (GstQTDemux * demux)
6315 {
6316   if (G_UNLIKELY (demux->pending_newsegment)) {
6317     gint i;
6318 
6319     gst_qtdemux_push_pending_newsegment (demux);
6320     /* clear to send tags on all streams */
6321     for (i = 0; i < demux->n_streams; i++) {
6322       QtDemuxStream *stream;
6323       stream = demux->streams[i];
6324       gst_qtdemux_push_tags (demux, stream);
6325       if (CUR_STREAM (stream)->sparse) {
6326         GST_INFO_OBJECT (demux, "Sending gap event on stream %d", i);
6327         gst_pad_push_event (stream->pad,
6328             gst_event_new_gap (stream->segment.position, GST_CLOCK_TIME_NONE));
6329       }
6330     }
6331   }
6332 }
6333 
6334 static void
6335 gst_qtdemux_send_gap_for_segment (GstQTDemux * demux,
6336     QtDemuxStream * stream, gint segment_index, GstClockTime pos)
6337 {
6338   GstClockTime ts, dur;
6339   GstEvent *gap;
6340 
6341   ts = pos;
6342   dur =
6343       stream->segments[segment_index].duration - (pos -
6344       stream->segments[segment_index].time);
6345   gap = gst_event_new_gap (ts, dur);
6346   stream->time_position += dur;
6347 
6348   GST_DEBUG_OBJECT (stream->pad, "Pushing gap for empty "
6349       "segment: %" GST_PTR_FORMAT, gap);
6350   gst_pad_push_event (stream->pad, gap);
6351 }
6352 
6353 static void
6354 gst_qtdemux_stream_send_initial_gap_segments (GstQTDemux * demux,
6355     QtDemuxStream * stream)
6356 {
6357   gint i;
6358 
6359   /* Push any initial gap segments before proceeding to the
6360    * 'real' data */
6361   for (i = 0; i < stream->n_segments; i++) {
6362     gst_qtdemux_activate_segment (demux, stream, i, stream->time_position);
6363 
6364     if (QTSEGMENT_IS_EMPTY (&stream->segments[i])) {
6365       gst_qtdemux_send_gap_for_segment (demux, stream, i,
6366           stream->time_position);
6367     } else {
6368       /* Only support empty segment at the beginning followed by
6369        * one non-empty segment, this was checked when parsing the
6370        * edts atom, arriving here is unexpected */
6371       g_assert (i + 1 == stream->n_segments);
6372       break;
6373     }
6374   }
6375 }
6376 
6377 static GstFlowReturn
6378 gst_qtdemux_chain (GstPad * sinkpad, GstObject * parent, GstBuffer * inbuf)
6379 {
6380   GstQTDemux *demux;
6381 
6382   demux = GST_QTDEMUX (parent);
6383 
6384   GST_DEBUG_OBJECT (demux,
6385       "Received buffer pts:%" GST_TIME_FORMAT " dts:%" GST_TIME_FORMAT
6386       " offset:%" G_GUINT64_FORMAT " size:%" G_GSIZE_FORMAT " demux offset:%"
6387       G_GUINT64_FORMAT, GST_TIME_ARGS (GST_BUFFER_PTS (inbuf)),
6388       GST_TIME_ARGS (GST_BUFFER_DTS (inbuf)), GST_BUFFER_OFFSET (inbuf),
6389       gst_buffer_get_size (inbuf), demux->offset);
6390 
6391   if (GST_BUFFER_FLAG_IS_SET (inbuf, GST_BUFFER_FLAG_DISCONT)) {
6392     gboolean is_gap_input = FALSE;
6393     gint i;
6394 
6395     GST_DEBUG_OBJECT (demux, "Got DISCONT, marking all streams as DISCONT");
6396 
6397     for (i = 0; i < demux->n_streams; i++) {
6398       demux->streams[i]->discont = TRUE;
6399     }
6400 
6401     /* Check if we can land back on our feet in the case where upstream is
6402      * handling the seeking/pushing of samples with gaps in between (like
6403      * in the case of trick-mode DASH for example) */
6404     if (demux->upstream_format_is_time
6405         && GST_BUFFER_OFFSET (inbuf) != GST_BUFFER_OFFSET_NONE) {
6406       gint i;
6407       for (i = 0; i < demux->n_streams; i++) {
6408         guint32 res;
6409         GST_LOG_OBJECT (demux,
6410             "Stream #%d , checking if offset %" G_GUINT64_FORMAT
6411             " is a sample start", i, GST_BUFFER_OFFSET (inbuf));
6412         res =
6413             gst_qtdemux_find_index_for_given_media_offset_linear (demux,
6414             demux->streams[i], GST_BUFFER_OFFSET (inbuf));
6415         if (res != -1) {
6416           QtDemuxSample *sample = &demux->streams[i]->samples[res];
6417           GST_LOG_OBJECT (demux,
6418               "Checking if sample %d from stream %d is valid (offset:%"
6419               G_GUINT64_FORMAT " size:%" G_GUINT32_FORMAT ")", res, i,
6420               sample->offset, sample->size);
6421           if (sample->offset == GST_BUFFER_OFFSET (inbuf)) {
6422             GST_LOG_OBJECT (demux,
6423                 "new buffer corresponds to a valid sample : %" G_GUINT32_FORMAT,
6424                 res);
6425             is_gap_input = TRUE;
6426             /* We can go back to standard playback mode */
6427             demux->state = QTDEMUX_STATE_MOVIE;
6428             /* Remember which sample this stream is at */
6429             demux->streams[i]->sample_index = res;
6430             /* Finally update all push-based values to the expected values */
6431             demux->neededbytes = demux->streams[i]->samples[res].size;
6432             demux->offset = GST_BUFFER_OFFSET (inbuf);
6433             demux->mdatleft =
6434                 demux->mdatsize - demux->offset + demux->mdatoffset;
6435             demux->todrop = 0;
6436           }
6437         }
6438       }
6439       if (!is_gap_input) {
6440         GST_DEBUG_OBJECT (demux, "Resetting, actual DISCONT");
6441         /* Reset state if it's a real discont */
6442         demux->neededbytes = 16;
6443         demux->state = QTDEMUX_STATE_INITIAL;
6444         demux->offset = GST_BUFFER_OFFSET (inbuf);
6445         gst_adapter_clear (demux->adapter);
6446       }
6447     }
6448     /* Reverse fragmented playback, need to flush all we have before
6449      * consuming a new fragment.
6450      * The samples array have the timestamps calculated by accumulating the
6451      * durations but this won't work for reverse playback of fragments as
6452      * the timestamps of a subsequent fragment should be smaller than the
6453      * previously received one. */
6454     if (!is_gap_input && demux->fragmented && demux->segment.rate < 0) {
6455       gst_qtdemux_process_adapter (demux, TRUE);
6456       for (i = 0; i < demux->n_streams; i++)
6457         gst_qtdemux_stream_flush_samples_data (demux, demux->streams[i]);
6458     }
6459   }
6460 
6461   gst_adapter_push (demux->adapter, inbuf);
6462 
6463   GST_DEBUG_OBJECT (demux,
6464       "pushing in inbuf %p, neededbytes:%u, available:%" G_GSIZE_FORMAT, inbuf,
6465       demux->neededbytes, gst_adapter_available (demux->adapter));
6466 
6467   return gst_qtdemux_process_adapter (demux, FALSE);
6468 }
6469 
6470 static GstFlowReturn
6471 gst_qtdemux_process_adapter (GstQTDemux * demux, gboolean force)
6472 {
6473   GstFlowReturn ret = GST_FLOW_OK;
6474 
6475   /* we never really mean to buffer that much */
6476   if (demux->neededbytes == -1) {
6477     goto eos;
6478   }
6479 
6480   while (((gst_adapter_available (demux->adapter)) >= demux->neededbytes) &&
6481       (ret == GST_FLOW_OK || (ret == GST_FLOW_NOT_LINKED && force))) {
6482 
6483 #ifndef GST_DISABLE_GST_DEBUG
6484     {
6485       guint64 discont_offset, distance_from_discont;
6486 
6487       discont_offset = gst_adapter_offset_at_discont (demux->adapter);
6488       distance_from_discont =
6489           gst_adapter_distance_from_discont (demux->adapter);
6490 
6491     GST_DEBUG_OBJECT (demux,
6492           "state:%s , demux->neededbytes:%d, demux->offset:%" G_GUINT64_FORMAT
6493           " adapter offset :%" G_GUINT64_FORMAT " (+ %" G_GUINT64_FORMAT
6494           " bytes)", qt_demux_state_string (demux->state), demux->neededbytes,
6495           demux->offset, discont_offset, distance_from_discont);
6496     }
6497 #endif
6498 
6499     switch (demux->state) {
6500       case QTDEMUX_STATE_INITIAL:{
6501         const guint8 *data;
6502         guint32 fourcc;
6503         guint64 size;
6504 
6505         gst_qtdemux_check_seekability (demux);
6506 
6507         data = gst_adapter_map (demux->adapter, demux->neededbytes);
6508 
6509         /* get fourcc/length, set neededbytes */
6510         extract_initial_length_and_fourcc ((guint8 *) data, demux->neededbytes,
6511             &size, &fourcc);
6512         gst_adapter_unmap (demux->adapter);
6513         data = NULL;
6514         GST_DEBUG_OBJECT (demux, "Peeking found [%" GST_FOURCC_FORMAT "] "
6515             "size: %" G_GUINT64_FORMAT, GST_FOURCC_ARGS (fourcc), size);
6516         if (size == 0) {
6517           GST_ELEMENT_ERROR (demux, STREAM, DEMUX,
6518               (_("This file is invalid and cannot be played.")),
6519               ("initial atom '%" GST_FOURCC_FORMAT "' has empty length",
6520                   GST_FOURCC_ARGS (fourcc)));
6521           ret = GST_FLOW_ERROR;
6522           break;
6523         }
6524         if (fourcc == FOURCC_mdat) {
6525           gint next_entry = next_entry_size (demux);
6526           if (demux->n_streams > 0 && (next_entry != -1 || !demux->fragmented)) {
6527             /* we have the headers, start playback */
6528             demux->state = QTDEMUX_STATE_MOVIE;
6529             demux->neededbytes = next_entry;
6530             demux->mdatleft = size;
6531             demux->mdatsize = demux->mdatleft;
6532           } else {
6533             /* no headers yet, try to get them */
6534             guint bs;
6535             gboolean res;
6536             guint64 old, target;
6537 
6538           buffer_data:
6539             old = demux->offset;
6540             target = old + size;
6541 
6542             /* try to jump over the atom with a seek */
6543             /* only bother if it seems worth doing so,
6544              * and avoids possible upstream/server problems */
6545             if (demux->upstream_seekable &&
6546                 demux->upstream_size > 4 * (1 << 20)) {
6547             res = qtdemux_seek_offset (demux, target);
6548             } else {
6549               GST_DEBUG_OBJECT (demux, "skipping seek");
6550               res = FALSE;
6551             }
6552 
6553             if (res) {
6554               GST_DEBUG_OBJECT (demux, "seek success");
6555               /* remember the offset fo the first mdat so we can seek back to it
6556                * after we have the headers */
6557               if (fourcc == FOURCC_mdat && demux->first_mdat == -1) {
6558                 demux->first_mdat = old;
6559                 GST_DEBUG_OBJECT (demux, "first mdat at %" G_GUINT64_FORMAT,
6560                     demux->first_mdat);
6561               }
6562               /* seek worked, continue reading */
6563               demux->offset = target;
6564               demux->neededbytes = 16;
6565               demux->state = QTDEMUX_STATE_INITIAL;
6566             } else {
6567               /* seek failed, need to buffer */
6568               demux->offset = old;
6569               GST_DEBUG_OBJECT (demux, "seek failed/skipped");
6570               /* there may be multiple mdat (or alike) buffers */
6571               /* sanity check */
6572               if (demux->mdatbuffer)
6573                 bs = gst_buffer_get_size (demux->mdatbuffer);
6574               else
6575                 bs = 0;
6576               if (size + bs > 10 * (1 << 20))
6577                 goto no_moov;
6578               demux->state = QTDEMUX_STATE_BUFFER_MDAT;
6579               demux->neededbytes = size;
6580               if (!demux->mdatbuffer)
6581                 demux->mdatoffset = demux->offset;
6582             }
6583           }
6584         } else if (G_UNLIKELY (size > QTDEMUX_MAX_ATOM_SIZE)) {
6585           GST_ELEMENT_ERROR (demux, STREAM, DEMUX,
6586               (_("This file is invalid and cannot be played.")),
6587               ("atom %" GST_FOURCC_FORMAT " has bogus size %" G_GUINT64_FORMAT,
6588                   GST_FOURCC_ARGS (fourcc), size));
6589           ret = GST_FLOW_ERROR;
6590           break;
6591         } else {
6592           /* this means we already started buffering and still no moov header,
6593            * let's continue buffering everything till we get moov */
6594           if (demux->mdatbuffer && !(fourcc == FOURCC_moov
6595                   || fourcc == FOURCC_moof))
6596             goto buffer_data;
6597           demux->neededbytes = size;
6598           demux->state = QTDEMUX_STATE_HEADER;
6599         }
6600         break;
6601       }
6602       case QTDEMUX_STATE_HEADER:{
6603         const guint8 *data;
6604         guint32 fourcc;
6605 
6606         GST_DEBUG_OBJECT (demux, "In header");
6607 
6608         data = gst_adapter_map (demux->adapter, demux->neededbytes);
6609 
6610         /* parse the header */
6611         extract_initial_length_and_fourcc (data, demux->neededbytes, NULL,
6612             &fourcc);
6613         if (fourcc == FOURCC_moov) {
6614           gint n;
6615 
6616           /* in usual fragmented setup we could try to scan for more
6617            * and end up at the the moov (after mdat) again */
6618           if (demux->got_moov && demux->n_streams > 0 &&
6619               (!demux->fragmented
6620                   || demux->last_moov_offset == demux->offset)) {
6621             GST_DEBUG_OBJECT (demux,
6622                 "Skipping moov atom as we have (this) one already");
6623           } else {
6624           GST_DEBUG_OBJECT (demux, "Parsing [moov]");
6625 
6626             if (demux->got_moov && demux->fragmented) {
6627               GST_DEBUG_OBJECT (demux,
6628                   "Got a second moov, clean up data from old one");
6629               if (demux->moov_node_compressed) {
6630                 g_node_destroy (demux->moov_node_compressed);
6631               if (demux->moov_node)
6632                   g_free (demux->moov_node->data);
6633               }
6634               demux->moov_node_compressed = NULL;
6635               if (demux->moov_node)
6636                 g_node_destroy (demux->moov_node);
6637               demux->moov_node = NULL;
6638             } else {
6639           /* prepare newsegment to send when streaming actually starts */
6640               if (!demux->pending_newsegment) {
6641             demux->pending_newsegment =
6642                     gst_event_new_segment (&demux->segment);
6643                 if (demux->segment_seqnum != GST_SEQNUM_INVALID)
6644                   gst_event_set_seqnum (demux->pending_newsegment,
6645                       demux->segment_seqnum);
6646           }
6647             }
6648 
6649             demux->last_moov_offset = demux->offset;
6650 
6651           qtdemux_parse_moov (demux, data, demux->neededbytes);
6652           qtdemux_node_dump (demux, demux->moov_node);
6653 #ifdef GSTREAMER_LITE
6654           if (!qtdemux_parse_tree (demux))
6655           {
6656               g_node_destroy (demux->moov_node);
6657               demux->moov_node = NULL;
6658               ret = GST_FLOW_ERROR;
6659               goto done;
6660           }
6661 #else
6662           qtdemux_parse_tree (demux);
6663 #endif //GSTREAMER_LITE
6664           qtdemux_prepare_streams (demux);
6665           if (!demux->got_moov)
6666             qtdemux_expose_streams (demux);
6667             else {
6668 
6669               for (n = 0; n < demux->n_streams; n++) {
6670                 QtDemuxStream *stream = demux->streams[n];
6671 
6672                 gst_qtdemux_configure_stream (demux, stream);
6673               }
6674             }
6675 
6676             demux->got_moov = TRUE;
6677             gst_qtdemux_check_send_pending_segment (demux);
6678 
6679             /* fragmented streams headers shouldn't contain edts atoms */
6680             if (!demux->fragmented) {
6681               for (n = 0; n < demux->n_streams; n++) {
6682                 gst_qtdemux_stream_send_initial_gap_segments (demux,
6683                     demux->streams[n]);
6684               }
6685             }
6686 
6687             if (demux->moov_node_compressed) {
6688               g_node_destroy (demux->moov_node_compressed);
6689               g_free (demux->moov_node->data);
6690             }
6691             demux->moov_node_compressed = NULL;
6692           g_node_destroy (demux->moov_node);
6693           demux->moov_node = NULL;
6694           GST_DEBUG_OBJECT (demux, "Finished parsing the header");
6695           }
6696         } else if (fourcc == FOURCC_moof) {
6697           if ((demux->got_moov || demux->media_caps) && demux->fragmented) {
6698             guint64 dist = 0;
6699             GstClockTime prev_pts;
6700             guint64 prev_offset;
6701             guint64 adapter_discont_offset, adapter_discont_dist;
6702 
6703             GST_DEBUG_OBJECT (demux, "Parsing [moof]");
6704 
6705             /*
6706              * The timestamp of the moof buffer is relevant as some scenarios
6707              * won't have the initial timestamp in the atoms. Whenever a new
6708              * buffer has started, we get that buffer's PTS and use it as a base
6709              * timestamp for the trun entries.
6710              *
6711              * To keep track of the current buffer timestamp and starting point
6712              * we use gst_adapter_prev_pts that gives us the PTS and the distance
6713              * from the beggining of the buffer, with the distance and demux->offset
6714              * we know if it is still the same buffer or not.
6715              */
6716             prev_pts = gst_adapter_prev_pts (demux->adapter, &dist);
6717             prev_offset = demux->offset - dist;
6718             if (demux->fragment_start_offset == -1
6719                 || prev_offset > demux->fragment_start_offset) {
6720               demux->fragment_start_offset = prev_offset;
6721               demux->fragment_start = prev_pts;
6722               GST_DEBUG_OBJECT (demux,
6723                   "New fragment start found at: %" G_GUINT64_FORMAT " : %"
6724                   GST_TIME_FORMAT, demux->fragment_start_offset,
6725                   GST_TIME_ARGS (demux->fragment_start));
6726             }
6727 
6728             /* We can't use prev_offset() here because this would require
6729              * upstream to set consistent and correct offsets on all buffers
6730              * since the discont. Nothing ever did that in the past and we
6731              * would break backwards compatibility here then.
6732              * Instead take the offset we had at the last discont and count
6733              * the bytes from there. This works with old code as there would
6734              * be no discont between moov and moof, and also works with
6735              * adaptivedemux which correctly sets offset and will set the
6736              * DISCONT flag accordingly when needed.
6737              *
6738              * We also only do this for upstream TIME segments as otherwise
6739              * there are potential backwards compatibility problems with
6740              * seeking in PUSH mode and upstream providing inconsistent
6741              * timestamps. */
6742             adapter_discont_offset =
6743                 gst_adapter_offset_at_discont (demux->adapter);
6744             adapter_discont_dist =
6745                 gst_adapter_distance_from_discont (demux->adapter);
6746 
6747             GST_DEBUG_OBJECT (demux,
6748                 "demux offset %" G_GUINT64_FORMAT " adapter offset %"
6749                 G_GUINT64_FORMAT " (+ %" G_GUINT64_FORMAT " bytes)",
6750                 demux->offset, adapter_discont_offset, adapter_discont_dist);
6751 
6752             if (demux->upstream_format_is_time) {
6753               demux->moof_offset = adapter_discont_offset;
6754               if (demux->moof_offset != GST_BUFFER_OFFSET_NONE)
6755                 demux->moof_offset += adapter_discont_dist;
6756               if (demux->moof_offset == GST_BUFFER_OFFSET_NONE)
6757                 demux->moof_offset = demux->offset;
6758             } else {
6759               demux->moof_offset = demux->offset;
6760             }
6761 
6762             if (!qtdemux_parse_moof (demux, data, demux->neededbytes,
6763                     demux->moof_offset, NULL)) {
6764               gst_adapter_unmap (demux->adapter);
6765               ret = GST_FLOW_ERROR;
6766               goto done;
6767             }
6768             /* in MSS we need to expose the pads after the first moof as we won't get a moov */
6769             if (demux->mss_mode && !demux->exposed) {
6770               if (!demux->pending_newsegment) {
6771                 GST_DEBUG_OBJECT (demux, "new pending_newsegment");
6772                 demux->pending_newsegment =
6773                     gst_event_new_segment (&demux->segment);
6774                 if (demux->segment_seqnum != GST_SEQNUM_INVALID)
6775                   gst_event_set_seqnum (demux->pending_newsegment,
6776                       demux->segment_seqnum);
6777               }
6778               qtdemux_expose_streams (demux);
6779             }
6780           } else {
6781             GST_DEBUG_OBJECT (demux, "Discarding [moof]");
6782           }
6783         } else if (fourcc == FOURCC_ftyp) {
6784           GST_DEBUG_OBJECT (demux, "Parsing [ftyp]");
6785           qtdemux_parse_ftyp (demux, data, demux->neededbytes);
6786         } else if (fourcc == FOURCC_uuid) {
6787           GST_DEBUG_OBJECT (demux, "Parsing [uuid]");
6788           qtdemux_parse_uuid (demux, data, demux->neededbytes);
6789         } else if (fourcc == FOURCC_sidx) {
6790           GST_DEBUG_OBJECT (demux, "Parsing [sidx]");
6791           qtdemux_parse_sidx (demux, data, demux->neededbytes);
6792         } else {
6793           switch (fourcc) {
6794             case FOURCC_styp:
6795               /* [styp] is like a [ftyp], but in fragment header. We ignore it for now
6796                * FALLTHROUGH */
6797             case FOURCC_skip:
6798             case FOURCC_free:
6799               /* [free] and [skip] are padding atoms */
6800               GST_DEBUG_OBJECT (demux,
6801                   "Skipping fourcc while parsing header : %" GST_FOURCC_FORMAT,
6802                   GST_FOURCC_ARGS (fourcc));
6803               break;
6804             default:
6805           GST_WARNING_OBJECT (demux,
6806               "Unknown fourcc while parsing header : %" GST_FOURCC_FORMAT,
6807               GST_FOURCC_ARGS (fourcc));
6808           /* Let's jump that one and go back to initial state */
6809               break;
6810         }
6811         }
6812         gst_adapter_unmap (demux->adapter);
6813         data = NULL;
6814 
6815         if (demux->mdatbuffer && demux->n_streams) {
6816           gsize remaining_data_size = 0;
6817 
6818           /* the mdat was before the header */
6819           GST_DEBUG_OBJECT (demux, "We have n_streams:%d and mdatbuffer:%p",
6820               demux->n_streams, demux->mdatbuffer);
6821           /* restore our adapter/offset view of things with upstream;
6822            * put preceding buffered data ahead of current moov data.
6823            * This should also handle evil mdat, moov, mdat cases and alike */
6824           gst_adapter_flush (demux->adapter, demux->neededbytes);
6825 
6826           /* Store any remaining data after the mdat for later usage */
6827           remaining_data_size = gst_adapter_available (demux->adapter);
6828           if (remaining_data_size > 0) {
6829             g_assert (demux->restoredata_buffer == NULL);
6830             demux->restoredata_buffer =
6831                 gst_adapter_take_buffer (demux->adapter, remaining_data_size);
6832             demux->restoredata_offset = demux->offset + demux->neededbytes;
6833             GST_DEBUG_OBJECT (demux,
6834                 "Stored %" G_GSIZE_FORMAT " post mdat bytes at offset %"
6835                 G_GUINT64_FORMAT, remaining_data_size,
6836                 demux->restoredata_offset);
6837           }
6838 
6839           gst_adapter_push (demux->adapter, demux->mdatbuffer);
6840           demux->mdatbuffer = NULL;
6841           demux->offset = demux->mdatoffset;
6842           demux->neededbytes = next_entry_size (demux);
6843           demux->state = QTDEMUX_STATE_MOVIE;
6844           demux->mdatleft = gst_adapter_available (demux->adapter);
6845           demux->mdatsize = demux->mdatleft;
6846         } else {
6847           GST_DEBUG_OBJECT (demux, "Carrying on normally");
6848           gst_adapter_flush (demux->adapter, demux->neededbytes);
6849 
6850           /* only go back to the mdat if there are samples to play */
6851           if (demux->got_moov && demux->first_mdat != -1
6852               && has_next_entry (demux)) {
6853             gboolean res;
6854 
6855             /* we need to seek back */
6856             res = qtdemux_seek_offset (demux, demux->first_mdat);
6857             if (res) {
6858               demux->offset = demux->first_mdat;
6859             } else {
6860               GST_DEBUG_OBJECT (demux, "Seek back failed");
6861             }
6862           } else {
6863             demux->offset += demux->neededbytes;
6864           }
6865           demux->neededbytes = 16;
6866           demux->state = QTDEMUX_STATE_INITIAL;
6867         }
6868 
6869         break;
6870       }
6871       case QTDEMUX_STATE_BUFFER_MDAT:{
6872         GstBuffer *buf;
6873         guint8 fourcc[4];
6874 
6875         GST_DEBUG_OBJECT (demux, "Got our buffer at offset %" G_GUINT64_FORMAT,
6876             demux->offset);
6877         buf = gst_adapter_take_buffer (demux->adapter, demux->neededbytes);
6878         gst_buffer_extract (buf, 0, fourcc, 4);
6879         GST_DEBUG_OBJECT (demux, "mdatbuffer starts with %" GST_FOURCC_FORMAT,
6880             GST_FOURCC_ARGS (QT_FOURCC (fourcc)));
6881         if (demux->mdatbuffer)
6882           demux->mdatbuffer = gst_buffer_append (demux->mdatbuffer, buf);
6883         else
6884           demux->mdatbuffer = buf;
6885         demux->offset += demux->neededbytes;
6886         demux->neededbytes = 16;
6887         demux->state = QTDEMUX_STATE_INITIAL;
6888         gst_qtdemux_post_progress (demux, 1, 1);
6889 
6890         break;
6891       }
6892       case QTDEMUX_STATE_MOVIE:{
6893         QtDemuxStream *stream = NULL;
6894         QtDemuxSample *sample;
6895         int i = -1;
6896         GstClockTime dts, pts, duration;
6897         gboolean keyframe;
6898 
6899         GST_DEBUG_OBJECT (demux,
6900             "BEGIN // in MOVIE for offset %" G_GUINT64_FORMAT, demux->offset);
6901 
6902         if (demux->fragmented) {
6903           GST_DEBUG_OBJECT (demux, "mdat remaining %" G_GUINT64_FORMAT,
6904               demux->mdatleft);
6905           if (G_LIKELY (demux->todrop < demux->mdatleft)) {
6906             /* if needed data starts within this atom,
6907              * then it should not exceed this atom */
6908             if (G_UNLIKELY (demux->neededbytes > demux->mdatleft)) {
6909               GST_ELEMENT_ERROR (demux, STREAM, DEMUX,
6910                   (_("This file is invalid and cannot be played.")),
6911                   ("sample data crosses atom boundary"));
6912               ret = GST_FLOW_ERROR;
6913               break;
6914             }
6915             demux->mdatleft -= demux->neededbytes;
6916           } else {
6917             GST_DEBUG_OBJECT (demux, "data atom emptied; resuming atom scan");
6918             /* so we are dropping more than left in this atom */
6919             gst_qtdemux_drop_data (demux, demux->mdatleft);
6920             demux->mdatleft = 0;
6921 
6922             /* need to resume atom parsing so we do not miss any other pieces */
6923             demux->state = QTDEMUX_STATE_INITIAL;
6924             demux->neededbytes = 16;
6925 
6926             /* check if there was any stored post mdat data from previous buffers */
6927             if (demux->restoredata_buffer) {
6928               g_assert (gst_adapter_available (demux->adapter) == 0);
6929 
6930               gst_adapter_push (demux->adapter, demux->restoredata_buffer);
6931               demux->restoredata_buffer = NULL;
6932               demux->offset = demux->restoredata_offset;
6933             }
6934 
6935             break;
6936           }
6937         }
6938 
6939         if (demux->todrop) {
6940           if (demux->cenc_aux_info_offset > 0) {
6941             GstByteReader br;
6942             const guint8 *data;
6943 
6944             GST_DEBUG_OBJECT (demux, "parsing cenc auxiliary info");
6945             data = gst_adapter_map (demux->adapter, demux->todrop);
6946             gst_byte_reader_init (&br, data + 8, demux->todrop);
6947             if (!qtdemux_parse_cenc_aux_info (demux, demux->streams[0], &br,
6948                     demux->cenc_aux_info_sizes, demux->cenc_aux_sample_count)) {
6949               GST_ERROR_OBJECT (demux, "failed to parse cenc auxiliary info");
6950               ret = GST_FLOW_ERROR;
6951               gst_adapter_unmap (demux->adapter);
6952               g_free (demux->cenc_aux_info_sizes);
6953               demux->cenc_aux_info_sizes = NULL;
6954               goto done;
6955         }
6956             demux->cenc_aux_info_offset = 0;
6957             g_free (demux->cenc_aux_info_sizes);
6958             demux->cenc_aux_info_sizes = NULL;
6959             gst_adapter_unmap (demux->adapter);
6960           }
6961           gst_qtdemux_drop_data (demux, demux->todrop);
6962         }
6963 
6964         /* first buffer? */
6965         /* initial newsegment sent here after having added pads,
6966          * possible others in sink_event */
6967         gst_qtdemux_check_send_pending_segment (demux);
6968 
6969         /* Figure out which stream this packet belongs to */
6970         for (i = 0; i < demux->n_streams; i++) {
6971           stream = demux->streams[i];
6972           if (stream->sample_index >= stream->n_samples)
6973             continue;
6974           GST_LOG_OBJECT (demux,
6975               "Checking stream %d (sample_index:%d / offset:%" G_GUINT64_FORMAT
6976               " / size:%d)", i, stream->sample_index,
6977               stream->samples[stream->sample_index].offset,
6978               stream->samples[stream->sample_index].size);
6979 
6980           if (stream->samples[stream->sample_index].offset == demux->offset)
6981             break;
6982         }
6983 
6984         if (G_UNLIKELY (stream == NULL || i == demux->n_streams))
6985           goto unknown_stream;
6986 
6987         gst_qtdemux_stream_check_and_change_stsd_index (demux, stream);
6988 
6989         if (stream->new_caps) {
6990           gst_qtdemux_configure_stream (demux, stream);
6991         }
6992 
6993         /* Put data in a buffer, set timestamps, caps, ... */
6994         sample = &stream->samples[stream->sample_index];
6995 
6996         if (G_LIKELY (!(STREAM_IS_EOS (stream)))) {
6997         GST_DEBUG_OBJECT (demux, "stream : %" GST_FOURCC_FORMAT,
6998               GST_FOURCC_ARGS (CUR_STREAM (stream)->fourcc));
6999 
7000           dts = QTSAMPLE_DTS (stream, sample);
7001           pts = QTSAMPLE_PTS (stream, sample);
7002           duration = QTSAMPLE_DUR_DTS (stream, sample, dts);
7003         keyframe = QTSAMPLE_KEYFRAME (stream, sample);
7004 
7005           /* check for segment end */
7006           if (G_UNLIKELY (demux->segment.stop != -1
7007                   && demux->segment.stop <= pts && stream->on_keyframe)) {
7008             GST_DEBUG_OBJECT (demux, "we reached the end of our segment.");
7009             stream->time_position = GST_CLOCK_TIME_NONE;        /* this means EOS */
7010 
7011             /* skip this data, stream is EOS */
7012             gst_adapter_flush (demux->adapter, demux->neededbytes);
7013             demux->offset += demux->neededbytes;
7014 
7015             /* check if all streams are eos */
7016             ret = GST_FLOW_EOS;
7017             for (i = 0; i < demux->n_streams; i++) {
7018               if (!STREAM_IS_EOS (demux->streams[i])) {
7019                 ret = GST_FLOW_OK;
7020                 break;
7021               }
7022             }
7023           } else {
7024             GstBuffer *outbuf;
7025 
7026             outbuf =
7027                 gst_adapter_take_buffer (demux->adapter, demux->neededbytes);
7028 
7029             /* FIXME: should either be an assert or a plain check */
7030             g_return_val_if_fail (outbuf != NULL, GST_FLOW_ERROR);
7031 
7032         ret = gst_qtdemux_decorate_and_push_buffer (demux, stream, outbuf,
7033                 dts, pts, duration, keyframe, dts, demux->offset);
7034           }
7035 
7036         /* combine flows */
7037           ret = gst_qtdemux_combine_flows (demux, stream, ret);
7038         } else {
7039           /* skip this data, stream is EOS */
7040           gst_adapter_flush (demux->adapter, demux->neededbytes);
7041         }
7042 
7043         stream->sample_index++;
7044         stream->offset_in_sample = 0;
7045 
7046         /* update current offset and figure out size of next buffer */
7047         GST_LOG_OBJECT (demux, "increasing offset %" G_GUINT64_FORMAT " by %u",
7048             demux->offset, demux->neededbytes);
7049         demux->offset += demux->neededbytes;
7050         GST_LOG_OBJECT (demux, "offset is now %" G_GUINT64_FORMAT,
7051             demux->offset);
7052 
7053 
7054         if (ret == GST_FLOW_EOS) {
7055           GST_DEBUG_OBJECT (demux, "All streams are EOS, signal upstream");
7056           demux->neededbytes = -1;
7057           goto eos;
7058         }
7059 
7060         if ((demux->neededbytes = next_entry_size (demux)) == -1) {
7061           if (demux->fragmented) {
7062             GST_DEBUG_OBJECT (demux, "(temporarily) out of fragmented samples");
7063             /* there may be more to follow, only finish this atom */
7064             demux->todrop = demux->mdatleft;
7065             demux->neededbytes = demux->todrop;
7066             break;
7067           }
7068           goto eos;
7069         }
7070         if (ret != GST_FLOW_OK && ret != GST_FLOW_NOT_LINKED) {
7071           goto non_ok_unlinked_flow;
7072         }
7073         break;
7074       }
7075       default:
7076         goto invalid_state;
7077     }
7078   }
7079 
7080   /* when buffering movie data, at least show user something is happening */
7081   if (ret == GST_FLOW_OK && demux->state == QTDEMUX_STATE_BUFFER_MDAT &&
7082       gst_adapter_available (demux->adapter) <= demux->neededbytes) {
7083     gst_qtdemux_post_progress (demux, gst_adapter_available (demux->adapter),
7084         demux->neededbytes);
7085   }
7086 done:
7087 
7088   return ret;
7089 
7090   /* ERRORS */
7091 non_ok_unlinked_flow:
7092   {
7093     GST_DEBUG_OBJECT (demux, "Stopping, combined return flow %s",
7094         gst_flow_get_name (ret));
7095     return ret;
7096   }
7097 unknown_stream:
7098   {
7099     GST_ELEMENT_ERROR (demux, STREAM, FAILED, (NULL), ("unknown stream found"));
7100     ret = GST_FLOW_ERROR;
7101     goto done;
7102   }
7103 eos:
7104   {
7105     GST_DEBUG_OBJECT (demux, "no next entry, EOS");
7106     ret = GST_FLOW_EOS;
7107     goto done;
7108   }
7109 invalid_state:
7110   {
7111     GST_ELEMENT_ERROR (demux, STREAM, FAILED,
7112         (NULL), ("qtdemuxer invalid state %d", demux->state));
7113     ret = GST_FLOW_ERROR;
7114     goto done;
7115   }
7116 no_moov:
7117   {
7118     GST_ELEMENT_ERROR (demux, STREAM, FAILED,
7119         (NULL), ("no 'moov' atom within the first 10 MB"));
7120     ret = GST_FLOW_ERROR;
7121     goto done;
7122   }
7123 }
7124 
7125 static gboolean
7126 qtdemux_sink_activate (GstPad * sinkpad, GstObject * parent)
7127 {
7128   GstQuery *query;
7129   gboolean pull_mode;
7130 
7131   query = gst_query_new_scheduling ();
7132 
7133   if (!gst_pad_peer_query (sinkpad, query)) {
7134     gst_query_unref (query);
7135     goto activate_push;
7136   }
7137 
7138   pull_mode = gst_query_has_scheduling_mode_with_flags (query,
7139       GST_PAD_MODE_PULL, GST_SCHEDULING_FLAG_SEEKABLE);
7140   gst_query_unref (query);
7141 
7142   if (!pull_mode)
7143     goto activate_push;
7144 
7145   GST_DEBUG_OBJECT (sinkpad, "activating pull");
7146   return gst_pad_activate_mode (sinkpad, GST_PAD_MODE_PULL, TRUE);
7147 
7148 activate_push:
7149   {
7150     GST_DEBUG_OBJECT (sinkpad, "activating push");
7151     return gst_pad_activate_mode (sinkpad, GST_PAD_MODE_PUSH, TRUE);
7152   }
7153 }
7154 
7155 static gboolean
7156 qtdemux_sink_activate_mode (GstPad * sinkpad, GstObject * parent,
7157     GstPadMode mode, gboolean active)
7158 {
7159   gboolean res;
7160   GstQTDemux *demux = GST_QTDEMUX (parent);
7161 
7162   switch (mode) {
7163     case GST_PAD_MODE_PUSH:
7164   demux->pullbased = FALSE;
7165       res = TRUE;
7166       break;
7167     case GST_PAD_MODE_PULL:
7168       if (active) {
7169         demux->pullbased = TRUE;
7170         res = gst_pad_start_task (sinkpad, (GstTaskFunction) gst_qtdemux_loop,
7171             sinkpad, NULL);
7172       } else {
7173         res = gst_pad_stop_task (sinkpad);
7174       }
7175       break;
7176     default:
7177       res = FALSE;
7178       break;
7179   }
7180   return res;
7181 }
7182 
7183 #ifdef HAVE_ZLIB
7184 static void *
7185 qtdemux_inflate (void *z_buffer, guint z_length, guint * length)
7186 {
7187   guint8 *buffer;
7188   z_stream z;
7189   int ret;
7190 
7191   memset (&z, 0, sizeof (z));
7192   z.zalloc = NULL;
7193   z.zfree = NULL;
7194   z.opaque = NULL;
7195 
7196   if ((ret = inflateInit (&z)) != Z_OK) {
7197     GST_ERROR ("inflateInit() returned %d", ret);
7198     return NULL;
7199   }
7200 
7201   z.next_in = z_buffer;
7202   z.avail_in = z_length;
7203 
7204   buffer = (guint8 *) g_malloc (*length);
7205   z.avail_out = *length;
7206   z.next_out = (Bytef *) buffer;
7207   do {
7208     ret = inflate (&z, Z_NO_FLUSH);
7209     if (ret == Z_STREAM_END) {
7210       break;
7211     } else if (ret != Z_OK) {
7212       GST_WARNING ("inflate() returned %d", ret);
7213       break;
7214   }
7215 
7216     *length += 4096;
7217     buffer = (guint8 *) g_realloc (buffer, *length);
7218     z.next_out = (Bytef *) (buffer + z.total_out);
7219     z.avail_out += 4096;
7220   } while (z.avail_in > 0);
7221 
7222   if (ret != Z_STREAM_END) {
7223     g_free (buffer);
7224     buffer = NULL;
7225     *length = 0;
7226   } else {
7227     *length = z.total_out;
7228   }
7229 
7230   inflateEnd (&z);
7231 
7232   return buffer;
7233 }
7234 #endif /* HAVE_ZLIB */
7235 
7236 static gboolean
7237 qtdemux_parse_moov (GstQTDemux * qtdemux, const guint8 * buffer, guint length)
7238 {
7239   GNode *cmov;
7240 
7241   qtdemux->moov_node = g_node_new ((guint8 *) buffer);
7242 
7243   /* counts as header data */
7244   qtdemux->header_size += length;
7245 
7246   GST_DEBUG_OBJECT (qtdemux, "parsing 'moov' atom");
7247   qtdemux_parse_node (qtdemux, qtdemux->moov_node, buffer, length);
7248 
7249   cmov = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_cmov);
7250   if (cmov) {
7251     guint32 method;
7252     GNode *dcom;
7253     GNode *cmvd;
7254     guint32 dcom_len;
7255 
7256     dcom = qtdemux_tree_get_child_by_type (cmov, FOURCC_dcom);
7257     cmvd = qtdemux_tree_get_child_by_type (cmov, FOURCC_cmvd);
7258     if (dcom == NULL || cmvd == NULL)
7259       goto invalid_compression;
7260 
7261     dcom_len = QT_UINT32 (dcom->data);
7262     if (dcom_len < 12)
7263       goto invalid_compression;
7264 
7265     method = QT_FOURCC ((guint8 *) dcom->data + 8);
7266     switch (method) {
7267 #ifdef HAVE_ZLIB
7268       case FOURCC_zlib:{
7269         guint uncompressed_length;
7270         guint compressed_length;
7271         guint8 *buf;
7272         guint32 cmvd_len;
7273 
7274         cmvd_len = QT_UINT32 ((guint8 *) cmvd->data);
7275         if (cmvd_len < 12)
7276           goto invalid_compression;
7277 
7278         uncompressed_length = QT_UINT32 ((guint8 *) cmvd->data + 8);
7279         compressed_length = cmvd_len - 12;
7280         GST_LOG ("length = %u", uncompressed_length);
7281 
7282         buf =
7283             (guint8 *) qtdemux_inflate ((guint8 *) cmvd->data + 12,
7284             compressed_length, &uncompressed_length);
7285 
7286         if (buf) {
7287         qtdemux->moov_node_compressed = qtdemux->moov_node;
7288         qtdemux->moov_node = g_node_new (buf);
7289 
7290         qtdemux_parse_node (qtdemux, qtdemux->moov_node, buf,
7291             uncompressed_length);
7292         }
7293         break;
7294       }
7295 #endif /* HAVE_ZLIB */
7296       default:
7297         GST_WARNING_OBJECT (qtdemux, "unknown or unhandled header compression "
7298             "type %" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (method));
7299         break;
7300     }
7301   }
7302   return TRUE;
7303 
7304   /* ERRORS */
7305 invalid_compression:
7306   {
7307     GST_ERROR_OBJECT (qtdemux, "invalid compressed header");
7308     return FALSE;
7309   }
7310 }
7311 
7312 static gboolean
7313 qtdemux_parse_container (GstQTDemux * qtdemux, GNode * node, const guint8 * buf,
7314     const guint8 * end)
7315 {
7316   while (G_UNLIKELY (buf < end)) {
7317     GNode *child;
7318     guint32 len;
7319 
7320     if (G_UNLIKELY (buf + 4 > end)) {
7321       GST_LOG_OBJECT (qtdemux, "buffer overrun");
7322       break;
7323     }
7324     len = QT_UINT32 (buf);
7325     if (G_UNLIKELY (len == 0)) {
7326       GST_LOG_OBJECT (qtdemux, "empty container");
7327       break;
7328     }
7329     if (G_UNLIKELY (len < 8)) {
7330       GST_WARNING_OBJECT (qtdemux, "length too short (%d < 8)", len);
7331       break;
7332     }
7333     if (G_UNLIKELY (len > (end - buf))) {
7334       GST_WARNING_OBJECT (qtdemux, "length too long (%d > %d)", len,
7335           (gint) (end - buf));
7336       break;
7337     }
7338 
7339     child = g_node_new ((guint8 *) buf);
7340     g_node_append (node, child);
7341     GST_LOG_OBJECT (qtdemux, "adding new node of len %d", len);
7342     qtdemux_parse_node (qtdemux, child, buf, len);
7343 
7344     buf += len;
7345   }
7346   return TRUE;
7347 }
7348 
7349 static gboolean
7350 qtdemux_parse_theora_extension (GstQTDemux * qtdemux, QtDemuxStream * stream,
7351     GNode * xdxt)
7352 {
7353   int len = QT_UINT32 (xdxt->data);
7354   guint8 *buf = xdxt->data;
7355   guint8 *end = buf + len;
7356   GstBuffer *buffer;
7357 
7358   /* skip size and type */
7359   buf += 8;
7360   end -= 8;
7361 
7362   while (buf < end) {
7363     gint size;
7364     guint32 type;
7365 
7366     size = QT_UINT32 (buf);
7367     type = QT_FOURCC (buf + 4);
7368 
7369     GST_LOG_OBJECT (qtdemux, "%p %p", buf, end);
7370 
7371     if (buf + size > end || size <= 0)
7372       break;
7373 
7374     buf += 8;
7375     size -= 8;
7376 
7377     GST_WARNING_OBJECT (qtdemux, "have cookie %" GST_FOURCC_FORMAT,
7378         GST_FOURCC_ARGS (type));
7379 
7380     switch (type) {
7381       case FOURCC_tCtH:
7382         buffer = gst_buffer_new_and_alloc (size);
7383         gst_buffer_fill (buffer, 0, buf, size);
7384         stream->buffers = g_slist_append (stream->buffers, buffer);
7385         GST_LOG_OBJECT (qtdemux, "parsing theora header");
7386         break;
7387       case FOURCC_tCt_:
7388         buffer = gst_buffer_new_and_alloc (size);
7389         gst_buffer_fill (buffer, 0, buf, size);
7390         stream->buffers = g_slist_append (stream->buffers, buffer);
7391         GST_LOG_OBJECT (qtdemux, "parsing theora comment");
7392         break;
7393       case FOURCC_tCtC:
7394         buffer = gst_buffer_new_and_alloc (size);
7395         gst_buffer_fill (buffer, 0, buf, size);
7396         stream->buffers = g_slist_append (stream->buffers, buffer);
7397         GST_LOG_OBJECT (qtdemux, "parsing theora codebook");
7398         break;
7399       default:
7400         GST_WARNING_OBJECT (qtdemux,
7401             "unknown theora cookie %" GST_FOURCC_FORMAT,
7402             GST_FOURCC_ARGS (type));
7403         break;
7404     }
7405     buf += size;
7406   }
7407   return TRUE;
7408 }
7409 
7410 static gboolean
7411 qtdemux_parse_node (GstQTDemux * qtdemux, GNode * node, const guint8 * buffer,
7412     guint length)
7413 {
7414   guint32 fourcc = 0;
7415   guint32 node_length = 0;
7416   const QtNodeType *type;
7417   const guint8 *end;
7418 
7419   GST_LOG_OBJECT (qtdemux, "qtdemux_parse buffer %p length %u", buffer, length);
7420 
7421   if (G_UNLIKELY (length < 8))
7422     goto not_enough_data;
7423 
7424   node_length = QT_UINT32 (buffer);
7425   fourcc = QT_FOURCC (buffer + 4);
7426 
7427   /* ignore empty nodes */
7428   if (G_UNLIKELY (fourcc == 0 || node_length == 8))
7429     return TRUE;
7430 
7431   type = qtdemux_type_get (fourcc);
7432 
7433   end = buffer + length;
7434 
7435   GST_LOG_OBJECT (qtdemux,
7436       "parsing '%" GST_FOURCC_FORMAT "', length=%u, name '%s'",
7437       GST_FOURCC_ARGS (fourcc), node_length, type->name);
7438 
7439   if (node_length > length)
7440     goto broken_atom_size;
7441 
7442   if (type->flags & QT_FLAG_CONTAINER) {
7443     qtdemux_parse_container (qtdemux, node, buffer + 8, end);
7444   } else {
7445     switch (fourcc) {
7446       case FOURCC_stsd:
7447       {
7448         if (node_length < 20) {
7449           GST_LOG_OBJECT (qtdemux, "skipping small stsd box");
7450           break;
7451         }
7452         GST_DEBUG_OBJECT (qtdemux,
7453             "parsing stsd (sample table, sample description) atom");
7454         /* Skip over 8 byte atom hdr + 1 byte version, 3 bytes flags, 4 byte num_entries */
7455         qtdemux_parse_container (qtdemux, node, buffer + 16, end);
7456         break;
7457       }
7458       case FOURCC_mp4a:
7459       case FOURCC_alac:
7460       case FOURCC_fLaC:
7461       {
7462         guint32 version;
7463         guint32 offset;
7464         guint min_size;
7465 
7466         /* also read alac (or whatever) in stead of mp4a in the following,
7467          * since a similar layout is used in other cases as well */
7468         if (fourcc == FOURCC_mp4a)
7469           min_size = 20;
7470         else if (fourcc == FOURCC_fLaC)
7471           min_size = 86;
7472         else
7473           min_size = 40;
7474 
7475         /* There are two things we might encounter here: a true mp4a atom, and
7476            an mp4a entry in an stsd atom. The latter is what we're interested
7477            in, and it looks like an atom, but isn't really one. The true mp4a
7478            atom is short, so we detect it based on length here. */
7479         if (length < min_size) {
7480           GST_LOG_OBJECT (qtdemux, "skipping small %" GST_FOURCC_FORMAT " box",
7481               GST_FOURCC_ARGS (fourcc));
7482           break;
7483         }
7484 
7485         /* 'version' here is the sound sample description version. Types 0 and
7486            1 are documented in the QTFF reference, but type 2 is not: it's
7487            described in Apple header files instead (struct SoundDescriptionV2
7488            in Movies.h) */
7489         version = QT_UINT16 (buffer + 16);
7490 
7491         GST_DEBUG_OBJECT (qtdemux, "%" GST_FOURCC_FORMAT " version 0x%08x",
7492             GST_FOURCC_ARGS (fourcc), version);
7493 
7494         /* parse any esds descriptors */
7495         switch (version) {
7496           case 0:
7497             offset = 0x24;
7498             break;
7499           case 1:
7500             offset = 0x34;
7501             break;
7502           case 2:
7503             offset = 0x48;
7504             break;
7505           default:
7506             GST_WARNING_OBJECT (qtdemux,
7507                 "unhandled %" GST_FOURCC_FORMAT " version 0x%08x",
7508                 GST_FOURCC_ARGS (fourcc), version);
7509             offset = 0;
7510             break;
7511         }
7512         if (offset)
7513           qtdemux_parse_container (qtdemux, node, buffer + offset, end);
7514         break;
7515       }
7516       case FOURCC_mp4v:
7517       case FOURCC_MP4V:
7518       case FOURCC_fmp4:
7519       case FOURCC_FMP4:
7520       case FOURCC_apcs:
7521       case FOURCC_apch:
7522       case FOURCC_apcn:
7523       case FOURCC_apco:
7524       case FOURCC_ap4h:
7525       case FOURCC_xvid:
7526       case FOURCC_XVID:
7527       case FOURCC_H264:
7528       case FOURCC_avc1:
7529       case FOURCC_avc3:
7530       case FOURCC_H265:
7531       case FOURCC_hvc1:
7532       case FOURCC_hev1:
7533       case FOURCC_mjp2:
7534       case FOURCC_encv:
7535       {
7536         guint32 version;
7537         guint32 str_len;
7538 
7539         /* codec_data is contained inside these atoms, which all have
7540          * the same format. */
7541         /* video sample description size is 86 bytes without extension.
7542          * node_length have to be bigger than 86 bytes because video sample
7543          * description can include extenstions such as esds, fiel, glbl, etc. */
7544         if (node_length < 86) {
7545           GST_WARNING_OBJECT (qtdemux, "%" GST_FOURCC_FORMAT
7546               " sample description length too short (%u < 86)",
7547               GST_FOURCC_ARGS (fourcc), node_length);
7548           break;
7549         }
7550 
7551         GST_DEBUG_OBJECT (qtdemux, "parsing in %" GST_FOURCC_FORMAT,
7552             GST_FOURCC_ARGS (fourcc));
7553 
7554         /* version (2 bytes) : this is set to 0, unless a compressor has changed
7555          *              its data format.
7556          * revision level (2 bytes) : must be set to 0. */
7557         version = QT_UINT32 (buffer + 16);
7558         GST_DEBUG_OBJECT (qtdemux, "version %08x", version);
7559 
7560         /* compressor name : PASCAL string and informative purposes
7561          * first byte : the number of bytes to be displayed.
7562          *              it has to be less than 32 because it is reserved
7563          *              space of 32 bytes total including itself. */
7564         str_len = QT_UINT8 (buffer + 50);
7565         if (str_len < 32)
7566           GST_DEBUG_OBJECT (qtdemux, "compressorname = %.*s", str_len,
7567               (char *) buffer + 51);
7568         else
7569           GST_WARNING_OBJECT (qtdemux,
7570               "compressorname length too big (%u > 31)", str_len);
7571 
7572         GST_MEMDUMP_OBJECT (qtdemux, "video sample description", buffer,
7573             end - buffer);
7574         qtdemux_parse_container (qtdemux, node, buffer + 86, end);
7575         break;
7576       }
7577       case FOURCC_meta:
7578       {
7579         GST_DEBUG_OBJECT (qtdemux, "parsing meta atom");
7580 
7581         /* You are reading this correctly. QTFF specifies that the
7582          * metadata atom is a short atom, whereas ISO BMFF specifies
7583          * it's a full atom. But since so many people are doing things
7584          * differently, we actually peek into the atom to see which
7585          * variant it is */
7586         if (length < 16) {
7587           GST_LOG_OBJECT (qtdemux, "skipping small %" GST_FOURCC_FORMAT " box",
7588               GST_FOURCC_ARGS (fourcc));
7589           break;
7590         }
7591         if (QT_FOURCC (buffer + 12) == FOURCC_hdlr) {
7592           /* Variant 1: What QTFF specifies. 'meta' is a short header which
7593            * starts with a 'hdlr' atom */
7594           qtdemux_parse_container (qtdemux, node, buffer + 8, end);
7595         } else if (QT_UINT32 (buffer + 8) == 0x00000000) {
7596           /* Variant 2: What ISO BMFF specifies. 'meta' is a _full_ atom
7597            * with version/flags both set to zero */
7598         qtdemux_parse_container (qtdemux, node, buffer + 12, end);
7599         } else
7600           GST_WARNING_OBJECT (qtdemux, "Unknown 'meta' atom format");
7601         break;
7602       }
7603       case FOURCC_mp4s:
7604       {
7605         GST_MEMDUMP_OBJECT (qtdemux, "mp4s", buffer, end - buffer);
7606         /* Skip 8 byte header, plus 8 byte version + flags + entry_count */
7607         qtdemux_parse_container (qtdemux, node, buffer + 16, end);
7608         break;
7609       }
7610       case FOURCC_XiTh:
7611       {
7612         guint32 version;
7613         guint32 offset;
7614 
7615         if (length < 16) {
7616           GST_LOG_OBJECT (qtdemux, "skipping small %" GST_FOURCC_FORMAT " box",
7617               GST_FOURCC_ARGS (fourcc));
7618           break;
7619         }
7620 
7621         version = QT_UINT32 (buffer + 12);
7622         GST_DEBUG_OBJECT (qtdemux, "parsing XiTh atom version 0x%08x", version);
7623 
7624         switch (version) {
7625           case 0x00000001:
7626             offset = 0x62;
7627             break;
7628           default:
7629             GST_DEBUG_OBJECT (qtdemux, "unknown version 0x%08x", version);
7630             offset = 0;
7631             break;
7632         }
7633         if (offset) {
7634           if (length < offset) {
7635             GST_WARNING_OBJECT (qtdemux,
7636                 "skipping too small %" GST_FOURCC_FORMAT " box",
7637                 GST_FOURCC_ARGS (fourcc));
7638             break;
7639           }
7640           qtdemux_parse_container (qtdemux, node, buffer + offset, end);
7641         }
7642         break;
7643       }
7644       case FOURCC_in24:
7645       {
7646         qtdemux_parse_container (qtdemux, node, buffer + 0x34, end);
7647         break;
7648       }
7649       case FOURCC_uuid:
7650       {
7651         qtdemux_parse_uuid (qtdemux, buffer, end - buffer);
7652         break;
7653       }
7654       case FOURCC_enca:
7655       {
7656         qtdemux_parse_container (qtdemux, node, buffer + 36, end);
7657         break;
7658       }
7659       default:
7660         if (!strcmp (type->name, "unknown"))
7661           GST_MEMDUMP ("Unknown tag", buffer + 4, end - buffer - 4);
7662         break;
7663     }
7664   }
7665   GST_LOG_OBJECT (qtdemux, "parsed '%" GST_FOURCC_FORMAT "'",
7666       GST_FOURCC_ARGS (fourcc));
7667   return TRUE;
7668 
7669 /* ERRORS */
7670 not_enough_data:
7671   {
7672     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
7673         (_("This file is corrupt and cannot be played.")),
7674         ("Not enough data for an atom header, got only %u bytes", length));
7675     return FALSE;
7676   }
7677 broken_atom_size:
7678   {
7679     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
7680         (_("This file is corrupt and cannot be played.")),
7681         ("Atom '%" GST_FOURCC_FORMAT "' has size of %u bytes, but we have only "
7682             "%u bytes available.", GST_FOURCC_ARGS (fourcc), node_length,
7683             length));
7684     return FALSE;
7685   }
7686 }
7687 
7688 static GNode *
7689 qtdemux_tree_get_child_by_type (GNode * node, guint32 fourcc)
7690 {
7691   GNode *child;
7692   guint8 *buffer;
7693   guint32 child_fourcc;
7694 
7695   for (child = g_node_first_child (node); child;
7696       child = g_node_next_sibling (child)) {
7697     buffer = (guint8 *) child->data;
7698 
7699     child_fourcc = QT_FOURCC (buffer + 4);
7700 
7701     if (G_UNLIKELY (child_fourcc == fourcc)) {
7702       return child;
7703     }
7704   }
7705   return NULL;
7706 }
7707 
7708 static GNode *
7709 qtdemux_tree_get_child_by_type_full (GNode * node, guint32 fourcc,
7710     GstByteReader * parser)
7711 {
7712   GNode *child;
7713   guint8 *buffer;
7714   guint32 child_fourcc, child_len;
7715 
7716   for (child = g_node_first_child (node); child;
7717       child = g_node_next_sibling (child)) {
7718     buffer = (guint8 *) child->data;
7719 
7720     child_len = QT_UINT32 (buffer);
7721     child_fourcc = QT_FOURCC (buffer + 4);
7722 
7723     if (G_UNLIKELY (child_fourcc == fourcc)) {
7724       if (G_UNLIKELY (child_len < (4 + 4)))
7725         return NULL;
7726       /* FIXME: must verify if atom length < parent atom length */
7727       gst_byte_reader_init (parser, buffer + (4 + 4), child_len - (4 + 4));
7728       return child;
7729     }
7730   }
7731   return NULL;
7732 }
7733 
7734 static GNode *
7735 qtdemux_tree_get_child_by_index (GNode * node, guint index)
7736 {
7737   return g_node_nth_child (node, index);
7738 }
7739 
7740 static GNode *
7741 qtdemux_tree_get_sibling_by_type_full (GNode * node, guint32 fourcc,
7742     GstByteReader * parser)
7743 {
7744   GNode *child;
7745   guint8 *buffer;
7746   guint32 child_fourcc, child_len;
7747 
7748   for (child = g_node_next_sibling (node); child;
7749       child = g_node_next_sibling (child)) {
7750     buffer = (guint8 *) child->data;
7751 
7752     child_fourcc = QT_FOURCC (buffer + 4);
7753 
7754     if (child_fourcc == fourcc) {
7755       if (parser) {
7756         child_len = QT_UINT32 (buffer);
7757         if (G_UNLIKELY (child_len < (4 + 4)))
7758           return NULL;
7759         /* FIXME: must verify if atom length < parent atom length */
7760         gst_byte_reader_init (parser, buffer + (4 + 4), child_len - (4 + 4));
7761       }
7762       return child;
7763     }
7764   }
7765   return NULL;
7766 }
7767 
7768 static GNode *
7769 qtdemux_tree_get_sibling_by_type (GNode * node, guint32 fourcc)
7770 {
7771   return qtdemux_tree_get_sibling_by_type_full (node, fourcc, NULL);
7772 }
7773 
7774 static void
7775 qtdemux_do_allocation (GstQTDemux * qtdemux, QtDemuxStream * stream)
7776 {
7777 /* FIXME: This can only reliably work if demuxers have a
7778  * separate streaming thread per srcpad. This should be
7779  * done in a demuxer base class, which integrates parts
7780  * of multiqueue
7781  *
7782  * https://bugzilla.gnome.org/show_bug.cgi?id=701856
7783  */
7784 #if 0
7785   GstQuery *query;
7786 
7787   query = gst_query_new_allocation (stream->caps, FALSE);
7788 
7789   if (!gst_pad_peer_query (stream->pad, query)) {
7790     /* not a problem, just debug a little */
7791     GST_DEBUG_OBJECT (qtdemux, "peer ALLOCATION query failed");
7792   }
7793 
7794   if (stream->allocator)
7795     gst_object_unref (stream->allocator);
7796 
7797   if (gst_query_get_n_allocation_params (query) > 0) {
7798     /* try the allocator */
7799     gst_query_parse_nth_allocation_param (query, 0, &stream->allocator,
7800         &stream->params);
7801     stream->use_allocator = TRUE;
7802   } else {
7803     stream->allocator = NULL;
7804     gst_allocation_params_init (&stream->params);
7805     stream->use_allocator = FALSE;
7806   }
7807   gst_query_unref (query);
7808 #endif
7809 }
7810 
7811 static gboolean
7812 gst_qtdemux_configure_protected_caps (GstQTDemux * qtdemux,
7813     QtDemuxStream * stream)
7814 {
7815   GstStructure *s;
7816   const gchar *selected_system;
7817 
7818   g_return_val_if_fail (qtdemux != NULL, FALSE);
7819   g_return_val_if_fail (stream != NULL, FALSE);
7820   g_return_val_if_fail (gst_caps_get_size (CUR_STREAM (stream)->caps) == 1,
7821       FALSE);
7822 
7823   if (stream->protection_scheme_type != FOURCC_cenc) {
7824     GST_ERROR_OBJECT (qtdemux, "unsupported protection scheme");
7825     return FALSE;
7826   }
7827   if (qtdemux->protection_system_ids == NULL) {
7828     GST_ERROR_OBJECT (qtdemux, "stream is protected using cenc, but no "
7829         "cenc protection system information has been found");
7830     return FALSE;
7831   }
7832   g_ptr_array_add (qtdemux->protection_system_ids, NULL);
7833   selected_system = gst_protection_select_system ((const gchar **)
7834       qtdemux->protection_system_ids->pdata);
7835   g_ptr_array_remove_index (qtdemux->protection_system_ids,
7836       qtdemux->protection_system_ids->len - 1);
7837   if (!selected_system) {
7838     GST_ERROR_OBJECT (qtdemux, "stream is protected, but no "
7839         "suitable decryptor element has been found");
7840     return FALSE;
7841   }
7842 
7843   s = gst_caps_get_structure (CUR_STREAM (stream)->caps, 0);
7844   if (!gst_structure_has_name (s, "application/x-cenc")) {
7845     gst_structure_set (s,
7846         "original-media-type", G_TYPE_STRING, gst_structure_get_name (s),
7847         GST_PROTECTION_SYSTEM_ID_CAPS_FIELD, G_TYPE_STRING, selected_system,
7848         NULL);
7849     gst_structure_set_name (s, "application/x-cenc");
7850   }
7851   return TRUE;
7852 }
7853 
7854 static gboolean
7855 gst_qtdemux_configure_stream (GstQTDemux * qtdemux, QtDemuxStream * stream)
7856 {
7857   if (stream->subtype == FOURCC_vide) {
7858     /* fps is calculated base on the duration of the average framerate since
7859      * qt does not have a fixed framerate. */
7860     gboolean fps_available = TRUE;
7861 
7862     if ((stream->n_samples == 1 && stream->first_duration == 0)
7863         || (qtdemux->fragmented && stream->n_samples_moof == 1)) {
7864       /* still frame */
7865       CUR_STREAM (stream)->fps_n = 0;
7866       CUR_STREAM (stream)->fps_d = 1;
7867     } else {
7868       if (stream->duration == 0 || stream->n_samples < 2) {
7869         CUR_STREAM (stream)->fps_n = stream->timescale;
7870         CUR_STREAM (stream)->fps_d = 1;
7871         fps_available = FALSE;
7872       } else {
7873         GstClockTime avg_duration;
7874         guint64 duration;
7875         guint32 n_samples;
7876 
7877         /* duration and n_samples can be updated for fragmented format
7878          * so, framerate of fragmented format is calculated using data in a moof */
7879         if (qtdemux->fragmented && stream->n_samples_moof > 0
7880             && stream->duration_moof > 0) {
7881           n_samples = stream->n_samples_moof;
7882           duration = stream->duration_moof;
7883         } else {
7884           n_samples = stream->n_samples;
7885           duration = stream->duration;
7886         }
7887 
7888         /* Calculate a framerate, ignoring the first sample which is sometimes truncated */
7889         /* stream->duration is guint64, timescale, n_samples are guint32 */
7890         avg_duration =
7891             gst_util_uint64_scale_round (duration -
7892             stream->first_duration, GST_SECOND,
7893             (guint64) (stream->timescale) * (n_samples - 1));
7894 
7895         GST_LOG_OBJECT (qtdemux,
7896             "Calculating avg sample duration based on stream (or moof) duration %"
7897             G_GUINT64_FORMAT
7898             " minus first sample %u, leaving %d samples gives %"
7899             GST_TIME_FORMAT, duration, stream->first_duration,
7900             n_samples - 1, GST_TIME_ARGS (avg_duration));
7901 
7902         gst_video_guess_framerate (avg_duration, &CUR_STREAM (stream)->fps_n,
7903             &CUR_STREAM (stream)->fps_d);
7904 
7905         GST_DEBUG_OBJECT (qtdemux,
7906             "Calculating framerate, timescale %u gave fps_n %d fps_d %d",
7907             stream->timescale, CUR_STREAM (stream)->fps_n,
7908             CUR_STREAM (stream)->fps_d);
7909     }
7910     }
7911 
7912     if (CUR_STREAM (stream)->caps) {
7913       CUR_STREAM (stream)->caps =
7914           gst_caps_make_writable (CUR_STREAM (stream)->caps);
7915 
7916       gst_caps_set_simple (CUR_STREAM (stream)->caps,
7917           "width", G_TYPE_INT, CUR_STREAM (stream)->width,
7918           "height", G_TYPE_INT, CUR_STREAM (stream)->height, NULL);
7919 
7920       /* set framerate if calculated framerate is reliable */
7921       if (fps_available) {
7922         gst_caps_set_simple (CUR_STREAM (stream)->caps,
7923             "framerate", GST_TYPE_FRACTION, CUR_STREAM (stream)->fps_n,
7924             CUR_STREAM (stream)->fps_d, NULL);
7925       }
7926 
7927       /* calculate pixel-aspect-ratio using display width and height */
7928       GST_DEBUG_OBJECT (qtdemux,
7929           "video size %dx%d, target display size %dx%d",
7930           CUR_STREAM (stream)->width, CUR_STREAM (stream)->height,
7931           stream->display_width, stream->display_height);
7932       /* qt file might have pasp atom */
7933       if (CUR_STREAM (stream)->par_w > 0 && CUR_STREAM (stream)->par_h > 0) {
7934         GST_DEBUG_OBJECT (qtdemux, "par %d:%d", CUR_STREAM (stream)->par_w,
7935             CUR_STREAM (stream)->par_h);
7936         gst_caps_set_simple (CUR_STREAM (stream)->caps, "pixel-aspect-ratio",
7937             GST_TYPE_FRACTION, CUR_STREAM (stream)->par_w,
7938             CUR_STREAM (stream)->par_h, NULL);
7939       } else if (stream->display_width > 0 && stream->display_height > 0
7940           && CUR_STREAM (stream)->width > 0
7941           && CUR_STREAM (stream)->height > 0) {
7942         gint n, d;
7943 
7944         /* calculate the pixel aspect ratio using the display and pixel w/h */
7945         n = stream->display_width * CUR_STREAM (stream)->height;
7946         d = stream->display_height * CUR_STREAM (stream)->width;
7947         if (n == d)
7948           n = d = 1;
7949         GST_DEBUG_OBJECT (qtdemux, "setting PAR to %d/%d", n, d);
7950         CUR_STREAM (stream)->par_w = n;
7951         CUR_STREAM (stream)->par_h = d;
7952         gst_caps_set_simple (CUR_STREAM (stream)->caps, "pixel-aspect-ratio",
7953             GST_TYPE_FRACTION, CUR_STREAM (stream)->par_w,
7954             CUR_STREAM (stream)->par_h, NULL);
7955       }
7956 
7957       if (CUR_STREAM (stream)->interlace_mode > 0) {
7958         if (CUR_STREAM (stream)->interlace_mode == 1) {
7959           gst_caps_set_simple (CUR_STREAM (stream)->caps, "interlace-mode",
7960               G_TYPE_STRING, "progressive", NULL);
7961         } else if (CUR_STREAM (stream)->interlace_mode == 2) {
7962           gst_caps_set_simple (CUR_STREAM (stream)->caps, "interlace-mode",
7963               G_TYPE_STRING, "interleaved", NULL);
7964           if (CUR_STREAM (stream)->field_order == 9) {
7965             gst_caps_set_simple (CUR_STREAM (stream)->caps, "field-order",
7966                 G_TYPE_STRING, "top-field-first", NULL);
7967           } else if (CUR_STREAM (stream)->field_order == 14) {
7968             gst_caps_set_simple (CUR_STREAM (stream)->caps, "field-order",
7969                 G_TYPE_STRING, "bottom-field-first", NULL);
7970       }
7971     }
7972       }
7973 
7974       /* Create incomplete colorimetry here if needed */
7975       if (CUR_STREAM (stream)->colorimetry.range ||
7976           CUR_STREAM (stream)->colorimetry.matrix ||
7977           CUR_STREAM (stream)->colorimetry.transfer
7978           || CUR_STREAM (stream)->colorimetry.primaries) {
7979         gchar *colorimetry =
7980             gst_video_colorimetry_to_string (&CUR_STREAM (stream)->colorimetry);
7981         gst_caps_set_simple (CUR_STREAM (stream)->caps, "colorimetry",
7982             G_TYPE_STRING, colorimetry, NULL);
7983         g_free (colorimetry);
7984       }
7985 
7986       if (stream->multiview_mode != GST_VIDEO_MULTIVIEW_MODE_NONE) {
7987         guint par_w = 1, par_h = 1;
7988 
7989         if (CUR_STREAM (stream)->par_w > 0 && CUR_STREAM (stream)->par_h > 0) {
7990           par_w = CUR_STREAM (stream)->par_w;
7991           par_h = CUR_STREAM (stream)->par_h;
7992         }
7993 
7994         if (gst_video_multiview_guess_half_aspect (stream->multiview_mode,
7995                 CUR_STREAM (stream)->width, CUR_STREAM (stream)->height, par_w,
7996                 par_h)) {
7997           stream->multiview_flags |= GST_VIDEO_MULTIVIEW_FLAGS_HALF_ASPECT;
7998         }
7999 
8000         gst_caps_set_simple (CUR_STREAM (stream)->caps,
8001             "multiview-mode", G_TYPE_STRING,
8002             gst_video_multiview_mode_to_caps_string (stream->multiview_mode),
8003             "multiview-flags", GST_TYPE_VIDEO_MULTIVIEW_FLAGSET,
8004             stream->multiview_flags, GST_FLAG_SET_MASK_EXACT, NULL);
8005       }
8006     }
8007   }
8008 
8009   else if (stream->subtype == FOURCC_soun) {
8010     if (CUR_STREAM (stream)->caps) {
8011       CUR_STREAM (stream)->caps =
8012           gst_caps_make_writable (CUR_STREAM (stream)->caps);
8013       if (CUR_STREAM (stream)->rate > 0)
8014         gst_caps_set_simple (CUR_STREAM (stream)->caps,
8015             "rate", G_TYPE_INT, (int) CUR_STREAM (stream)->rate, NULL);
8016       if (CUR_STREAM (stream)->n_channels > 0)
8017         gst_caps_set_simple (CUR_STREAM (stream)->caps,
8018             "channels", G_TYPE_INT, CUR_STREAM (stream)->n_channels, NULL);
8019       if (CUR_STREAM (stream)->n_channels > 2) {
8020         /* FIXME: Need to parse the 'chan' atom to get channel layouts
8021          * correctly; this is just the minimum we can do - assume
8022          * we don't actually have any channel positions. */
8023         gst_caps_set_simple (CUR_STREAM (stream)->caps,
8024             "channel-mask", GST_TYPE_BITMASK, G_GUINT64_CONSTANT (0), NULL);
8025       }
8026     }
8027   }
8028 
8029   if (stream->pad) {
8030     GstCaps *prev_caps = NULL;
8031 
8032     GST_PAD_ELEMENT_PRIVATE (stream->pad) = stream;
8033     gst_pad_set_event_function (stream->pad, gst_qtdemux_handle_src_event);
8034     gst_pad_set_query_function (stream->pad, gst_qtdemux_handle_src_query);
8035     gst_pad_set_active (stream->pad, TRUE);
8036 
8037     gst_pad_use_fixed_caps (stream->pad);
8038 
8039     if (stream->protected) {
8040       if (!gst_qtdemux_configure_protected_caps (qtdemux, stream)) {
8041         GST_ERROR_OBJECT (qtdemux,
8042             "Failed to configure protected stream caps.");
8043         return FALSE;
8044       }
8045     }
8046 
8047     GST_DEBUG_OBJECT (qtdemux, "setting caps %" GST_PTR_FORMAT,
8048         CUR_STREAM (stream)->caps);
8049     if (stream->new_stream) {
8050       gchar *stream_id;
8051       GstEvent *event;
8052       GstStreamFlags stream_flags = GST_STREAM_FLAG_NONE;
8053 
8054       event =
8055           gst_pad_get_sticky_event (qtdemux->sinkpad, GST_EVENT_STREAM_START,
8056           0);
8057       if (event) {
8058         gst_event_parse_stream_flags (event, &stream_flags);
8059         if (gst_event_parse_group_id (event, &qtdemux->group_id))
8060           qtdemux->have_group_id = TRUE;
8061           else
8062           qtdemux->have_group_id = FALSE;
8063         gst_event_unref (event);
8064       } else if (!qtdemux->have_group_id) {
8065         qtdemux->have_group_id = TRUE;
8066         qtdemux->group_id = gst_util_group_id_next ();
8067       }
8068 
8069       stream->new_stream = FALSE;
8070       stream_id =
8071           gst_pad_create_stream_id_printf (stream->pad,
8072           GST_ELEMENT_CAST (qtdemux), "%03u", stream->track_id);
8073       event = gst_event_new_stream_start (stream_id);
8074       if (qtdemux->have_group_id)
8075         gst_event_set_group_id (event, qtdemux->group_id);
8076       if (stream->disabled)
8077         stream_flags |= GST_STREAM_FLAG_UNSELECT;
8078       if (CUR_STREAM (stream)->sparse) {
8079         stream_flags |= GST_STREAM_FLAG_SPARSE;
8080       } else {
8081         stream_flags &= ~GST_STREAM_FLAG_SPARSE;
8082       }
8083       gst_event_set_stream_flags (event, stream_flags);
8084       gst_pad_push_event (stream->pad, event);
8085       g_free (stream_id);
8086     }
8087 
8088     prev_caps = gst_pad_get_current_caps (stream->pad);
8089 
8090     if (CUR_STREAM (stream)->caps) {
8091       if (!prev_caps
8092           || !gst_caps_is_equal_fixed (prev_caps, CUR_STREAM (stream)->caps)) {
8093         GST_DEBUG_OBJECT (qtdemux, "setting caps %" GST_PTR_FORMAT,
8094             CUR_STREAM (stream)->caps);
8095         gst_pad_set_caps (stream->pad, CUR_STREAM (stream)->caps);
8096       } else {
8097         GST_DEBUG_OBJECT (qtdemux, "ignore duplicated caps");
8098       }
8099     } else {
8100       GST_WARNING_OBJECT (qtdemux, "stream without caps");
8101     }
8102 
8103     if (prev_caps)
8104       gst_caps_unref (prev_caps);
8105     stream->new_caps = FALSE;
8106   }
8107   return TRUE;
8108 }
8109 
8110 static void
8111 gst_qtdemux_stream_check_and_change_stsd_index (GstQTDemux * demux,
8112     QtDemuxStream * stream)
8113 {
8114   if (stream->cur_stsd_entry_index == stream->stsd_sample_description_id)
8115     return;
8116 
8117   GST_DEBUG_OBJECT (stream->pad, "Changing stsd index from '%u' to '%u'",
8118       stream->cur_stsd_entry_index, stream->stsd_sample_description_id);
8119   if (G_UNLIKELY (stream->stsd_sample_description_id >=
8120           stream->stsd_entries_length)) {
8121     GST_ELEMENT_ERROR (demux, STREAM, DEMUX,
8122         (_("This file is invalid and cannot be played.")),
8123         ("New sample description id is out of bounds (%d >= %d)",
8124             stream->stsd_sample_description_id, stream->stsd_entries_length));
8125   } else {
8126     stream->cur_stsd_entry_index = stream->stsd_sample_description_id;
8127     stream->new_caps = TRUE;
8128   }
8129 }
8130 
8131 static gboolean
8132 gst_qtdemux_add_stream (GstQTDemux * qtdemux,
8133     QtDemuxStream * stream, GstTagList * list)
8134 {
8135   gboolean ret = TRUE;
8136   /* consistent default for push based mode */
8137   gst_segment_init (&stream->segment, GST_FORMAT_TIME);
8138 
8139   if (stream->subtype == FOURCC_vide) {
8140     gchar *name = g_strdup_printf ("video_%u", qtdemux->n_video_streams);
8141 
8142     stream->pad =
8143         gst_pad_new_from_static_template (&gst_qtdemux_videosrc_template, name);
8144     g_free (name);
8145 
8146     if (!gst_qtdemux_configure_stream (qtdemux, stream)) {
8147       gst_object_unref (stream->pad);
8148       stream->pad = NULL;
8149       ret = FALSE;
8150       goto done;
8151     }
8152 
8153     qtdemux->n_video_streams++;
8154   } else if (stream->subtype == FOURCC_soun) {
8155     gchar *name = g_strdup_printf ("audio_%u", qtdemux->n_audio_streams);
8156 
8157     stream->pad =
8158         gst_pad_new_from_static_template (&gst_qtdemux_audiosrc_template, name);
8159     g_free (name);
8160     if (!gst_qtdemux_configure_stream (qtdemux, stream)) {
8161       gst_object_unref (stream->pad);
8162       stream->pad = NULL;
8163       ret = FALSE;
8164       goto done;
8165     }
8166     qtdemux->n_audio_streams++;
8167   } else if (stream->subtype == FOURCC_strm) {
8168     GST_DEBUG_OBJECT (qtdemux, "stream type, not creating pad");
8169   } else if (stream->subtype == FOURCC_subp || stream->subtype == FOURCC_text
8170       || stream->subtype == FOURCC_sbtl || stream->subtype == FOURCC_subt) {
8171     gchar *name = g_strdup_printf ("subtitle_%u", qtdemux->n_sub_streams);
8172 
8173     stream->pad =
8174         gst_pad_new_from_static_template (&gst_qtdemux_subsrc_template, name);
8175     g_free (name);
8176     if (!gst_qtdemux_configure_stream (qtdemux, stream)) {
8177       gst_object_unref (stream->pad);
8178       stream->pad = NULL;
8179       ret = FALSE;
8180       goto done;
8181     }
8182     qtdemux->n_sub_streams++;
8183   } else if (CUR_STREAM (stream)->caps) {
8184     gchar *name = g_strdup_printf ("video_%u", qtdemux->n_video_streams);
8185 
8186     stream->pad =
8187         gst_pad_new_from_static_template (&gst_qtdemux_videosrc_template, name);
8188     g_free (name);
8189     if (!gst_qtdemux_configure_stream (qtdemux, stream)) {
8190       gst_object_unref (stream->pad);
8191       stream->pad = NULL;
8192       ret = FALSE;
8193       goto done;
8194     }
8195     qtdemux->n_video_streams++;
8196   } else {
8197     GST_DEBUG_OBJECT (qtdemux, "unknown stream type");
8198     goto done;
8199   }
8200 
8201   if (stream->pad) {
8202     GList *l;
8203 #ifdef GSTREAMER_LITE
8204     // Add track_id and track_enabled so we can find this pad later on by track ID
8205     if (CUR_STREAM (stream)->caps) {
8206       gst_caps_set_simple(CUR_STREAM (stream)->caps,
8207           "track_id", G_TYPE_INT, stream->track_id,
8208           "track_enabled", G_TYPE_BOOLEAN, stream->track_enabled,
8209           NULL);
8210       GST_DEBUG_OBJECT (qtdemux, "setting caps %" GST_PTR_FORMAT, stream->caps);
8211     }
8212 #endif // GSTREAMER_LITE
8213 
8214     GST_DEBUG_OBJECT (qtdemux, "adding pad %s %p to qtdemux %p",
8215         GST_OBJECT_NAME (stream->pad), stream->pad, qtdemux);
8216     gst_element_add_pad (GST_ELEMENT_CAST (qtdemux), stream->pad);
8217     gst_flow_combiner_add_pad (qtdemux->flowcombiner, stream->pad);
8218 
8219     if (stream->stream_tags)
8220       gst_tag_list_unref (stream->stream_tags);
8221     stream->stream_tags = list;
8222     list = NULL;
8223     /* global tags go on each pad anyway */
8224     stream->send_global_tags = TRUE;
8225     /* send upstream GST_EVENT_PROTECTION events that were received before
8226        this source pad was created */
8227     for (l = qtdemux->protection_event_queue.head; l != NULL; l = l->next)
8228       gst_pad_push_event (stream->pad, gst_event_ref (l->data));
8229   }
8230 done:
8231   if (list)
8232     gst_tag_list_unref (list);
8233   return ret;
8234 }
8235 
8236 /* find next atom with @fourcc starting at @offset */
8237 static GstFlowReturn
8238 qtdemux_find_atom (GstQTDemux * qtdemux, guint64 * offset,
8239     guint64 * length, guint32 fourcc)
8240 {
8241   GstFlowReturn ret;
8242   guint32 lfourcc;
8243   GstBuffer *buf;
8244 
8245   GST_LOG_OBJECT (qtdemux, "finding fourcc %" GST_FOURCC_FORMAT " at offset %"
8246       G_GUINT64_FORMAT, GST_FOURCC_ARGS (fourcc), *offset);
8247 
8248   while (TRUE) {
8249     GstMapInfo map;
8250 
8251     buf = NULL;
8252     ret = gst_pad_pull_range (qtdemux->sinkpad, *offset, 16, &buf);
8253     if (G_UNLIKELY (ret != GST_FLOW_OK))
8254       goto locate_failed;
8255     if (G_UNLIKELY (gst_buffer_get_size (buf) != 16)) {
8256       /* likely EOF */
8257       ret = GST_FLOW_EOS;
8258       gst_buffer_unref (buf);
8259       goto locate_failed;
8260     }
8261     gst_buffer_map (buf, &map, GST_MAP_READ);
8262     extract_initial_length_and_fourcc (map.data, 16, length, &lfourcc);
8263     gst_buffer_unmap (buf, &map);
8264     gst_buffer_unref (buf);
8265 
8266     if (G_UNLIKELY (*length == 0)) {
8267       GST_DEBUG_OBJECT (qtdemux, "invalid length 0");
8268       ret = GST_FLOW_ERROR;
8269       goto locate_failed;
8270     }
8271 
8272     if (lfourcc == fourcc) {
8273       GST_DEBUG_OBJECT (qtdemux, "found fourcc at offset %" G_GUINT64_FORMAT,
8274           *offset);
8275       break;
8276     } else {
8277       GST_LOG_OBJECT (qtdemux,
8278           "skipping atom '%" GST_FOURCC_FORMAT "' at %" G_GUINT64_FORMAT,
8279           GST_FOURCC_ARGS (fourcc), *offset);
8280       *offset += *length;
8281     }
8282   }
8283 
8284   return GST_FLOW_OK;
8285 
8286 locate_failed:
8287   {
8288     /* might simply have had last one */
8289     GST_DEBUG_OBJECT (qtdemux, "fourcc not found");
8290     return ret;
8291   }
8292 }
8293 
8294 /* should only do something in pull mode */
8295 /* call with OBJECT lock */
8296 static GstFlowReturn
8297 qtdemux_add_fragmented_samples (GstQTDemux * qtdemux)
8298 {
8299   guint64 length, offset;
8300   GstBuffer *buf = NULL;
8301   GstFlowReturn ret = GST_FLOW_OK;
8302   GstFlowReturn res = GST_FLOW_OK;
8303   GstMapInfo map;
8304 
8305   offset = qtdemux->moof_offset;
8306   GST_DEBUG_OBJECT (qtdemux, "next moof at offset %" G_GUINT64_FORMAT, offset);
8307 
8308   if (!offset) {
8309     GST_DEBUG_OBJECT (qtdemux, "no next moof");
8310     return GST_FLOW_EOS;
8311   }
8312 
8313   /* best not do pull etc with lock held */
8314   GST_OBJECT_UNLOCK (qtdemux);
8315 
8316   ret = qtdemux_find_atom (qtdemux, &offset, &length, FOURCC_moof);
8317   if (ret != GST_FLOW_OK)
8318     goto flow_failed;
8319 
8320   ret = gst_qtdemux_pull_atom (qtdemux, offset, length, &buf);
8321   if (G_UNLIKELY (ret != GST_FLOW_OK))
8322     goto flow_failed;
8323   gst_buffer_map (buf, &map, GST_MAP_READ);
8324   if (!qtdemux_parse_moof (qtdemux, map.data, map.size, offset, NULL)) {
8325     gst_buffer_unmap (buf, &map);
8326     gst_buffer_unref (buf);
8327     buf = NULL;
8328     goto parse_failed;
8329   }
8330 
8331   gst_buffer_unmap (buf, &map);
8332   gst_buffer_unref (buf);
8333   buf = NULL;
8334 
8335   offset += length;
8336   /* look for next moof */
8337   ret = qtdemux_find_atom (qtdemux, &offset, &length, FOURCC_moof);
8338   if (G_UNLIKELY (ret != GST_FLOW_OK))
8339     goto flow_failed;
8340 
8341 exit:
8342   GST_OBJECT_LOCK (qtdemux);
8343 
8344   qtdemux->moof_offset = offset;
8345 
8346   return res;
8347 
8348 parse_failed:
8349   {
8350     GST_DEBUG_OBJECT (qtdemux, "failed to parse moof");
8351     offset = 0;
8352     res = GST_FLOW_ERROR;
8353     goto exit;
8354   }
8355 flow_failed:
8356   {
8357     /* maybe upstream temporarily flushing */
8358     if (ret != GST_FLOW_FLUSHING) {
8359       GST_DEBUG_OBJECT (qtdemux, "no next moof");
8360       offset = 0;
8361     } else {
8362       GST_DEBUG_OBJECT (qtdemux, "upstream WRONG_STATE");
8363       /* resume at current position next time */
8364     }
8365     res = ret;
8366     goto exit;
8367   }
8368 }
8369 
8370 /* initialise bytereaders for stbl sub-atoms */
8371 static gboolean
8372 qtdemux_stbl_init (GstQTDemux * qtdemux, QtDemuxStream * stream, GNode * stbl)
8373 {
8374   stream->stbl_index = -1;      /* no samples have yet been parsed */
8375   stream->sample_index = -1;
8376 
8377   /* time-to-sample atom */
8378   if (!qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stts, &stream->stts))
8379     goto corrupt_file;
8380 
8381   /* copy atom data into a new buffer for later use */
8382   stream->stts.data = g_memdup (stream->stts.data, stream->stts.size);
8383 
8384   /* skip version + flags */
8385   if (!gst_byte_reader_skip (&stream->stts, 1 + 3) ||
8386       !gst_byte_reader_get_uint32_be (&stream->stts, &stream->n_sample_times))
8387     goto corrupt_file;
8388   GST_LOG_OBJECT (qtdemux, "%u timestamp blocks", stream->n_sample_times);
8389 
8390   /* make sure there's enough data */
8391   if (!qt_atom_parser_has_chunks (&stream->stts, stream->n_sample_times, 8)) {
8392     stream->n_sample_times = gst_byte_reader_get_remaining (&stream->stts) / 8;
8393     GST_LOG_OBJECT (qtdemux, "overriding to %u timestamp blocks",
8394         stream->n_sample_times);
8395     if (!stream->n_sample_times)
8396     goto corrupt_file;
8397   }
8398 
8399   /* sync sample atom */
8400   stream->stps_present = FALSE;
8401   if ((stream->stss_present =
8402           ! !qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stss,
8403               &stream->stss) ? TRUE : FALSE) == TRUE) {
8404     /* copy atom data into a new buffer for later use */
8405     stream->stss.data = g_memdup (stream->stss.data, stream->stss.size);
8406 
8407     /* skip version + flags */
8408     if (!gst_byte_reader_skip (&stream->stss, 1 + 3) ||
8409         !gst_byte_reader_get_uint32_be (&stream->stss, &stream->n_sample_syncs))
8410       goto corrupt_file;
8411 
8412     if (stream->n_sample_syncs) {
8413       /* make sure there's enough data */
8414       if (!qt_atom_parser_has_chunks (&stream->stss, stream->n_sample_syncs, 4))
8415         goto corrupt_file;
8416     }
8417 
8418     /* partial sync sample atom */
8419     if ((stream->stps_present =
8420             ! !qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stps,
8421                 &stream->stps) ? TRUE : FALSE) == TRUE) {
8422       /* copy atom data into a new buffer for later use */
8423       stream->stps.data = g_memdup (stream->stps.data, stream->stps.size);
8424 
8425       /* skip version + flags */
8426       if (!gst_byte_reader_skip (&stream->stps, 1 + 3) ||
8427           !gst_byte_reader_get_uint32_be (&stream->stps,
8428               &stream->n_sample_partial_syncs))
8429         goto corrupt_file;
8430 
8431       /* if there are no entries, the stss table contains the real
8432        * sync samples */
8433       if (stream->n_sample_partial_syncs) {
8434         /* make sure there's enough data */
8435         if (!qt_atom_parser_has_chunks (&stream->stps,
8436                 stream->n_sample_partial_syncs, 4))
8437           goto corrupt_file;
8438       }
8439     }
8440   }
8441 
8442   /* sample size */
8443   if (!qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stsz, &stream->stsz))
8444     goto no_samples;
8445 
8446   /* copy atom data into a new buffer for later use */
8447   stream->stsz.data = g_memdup (stream->stsz.data, stream->stsz.size);
8448 
8449   /* skip version + flags */
8450   if (!gst_byte_reader_skip (&stream->stsz, 1 + 3) ||
8451       !gst_byte_reader_get_uint32_be (&stream->stsz, &stream->sample_size))
8452     goto corrupt_file;
8453 
8454   if (!gst_byte_reader_get_uint32_be (&stream->stsz, &stream->n_samples))
8455     goto corrupt_file;
8456 
8457   if (!stream->n_samples)
8458     goto no_samples;
8459 
8460   /* sample-to-chunk atom */
8461   if (!qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stsc, &stream->stsc))
8462     goto corrupt_file;
8463 
8464   /* copy atom data into a new buffer for later use */
8465   stream->stsc.data = g_memdup (stream->stsc.data, stream->stsc.size);
8466 
8467   /* skip version + flags */
8468   if (!gst_byte_reader_skip (&stream->stsc, 1 + 3) ||
8469       !gst_byte_reader_get_uint32_be (&stream->stsc,
8470           &stream->n_samples_per_chunk))
8471     goto corrupt_file;
8472 
8473   GST_DEBUG_OBJECT (qtdemux, "n_samples_per_chunk %u",
8474       stream->n_samples_per_chunk);
8475 
8476   /* make sure there's enough data */
8477   if (!qt_atom_parser_has_chunks (&stream->stsc, stream->n_samples_per_chunk,
8478           12))
8479     goto corrupt_file;
8480 
8481 
8482   /* chunk offset */
8483   if (qtdemux_tree_get_child_by_type_full (stbl, FOURCC_stco, &stream->stco))
8484     stream->co_size = sizeof (guint32);
8485   else if (qtdemux_tree_get_child_by_type_full (stbl, FOURCC_co64,
8486           &stream->stco))
8487     stream->co_size = sizeof (guint64);
8488   else
8489     goto corrupt_file;
8490 
8491   /* copy atom data into a new buffer for later use */
8492   stream->stco.data = g_memdup (stream->stco.data, stream->stco.size);
8493 
8494   /* skip version + flags */
8495   if (!gst_byte_reader_skip (&stream->stco, 1 + 3))
8496     goto corrupt_file;
8497 
8498   /* chunks_are_samples == TRUE means treat chunks as samples */
8499   stream->chunks_are_samples = stream->sample_size
8500       && !CUR_STREAM (stream)->sampled;
8501   if (stream->chunks_are_samples) {
8502     /* treat chunks as samples */
8503     if (!gst_byte_reader_get_uint32_be (&stream->stco, &stream->n_samples))
8504       goto corrupt_file;
8505   } else {
8506     /* skip number of entries */
8507     if (!gst_byte_reader_skip (&stream->stco, 4))
8508       goto corrupt_file;
8509 
8510     /* make sure there are enough data in the stsz atom */
8511     if (!stream->sample_size) {
8512       /* different sizes for each sample */
8513       if (!qt_atom_parser_has_chunks (&stream->stsz, stream->n_samples, 4))
8514         goto corrupt_file;
8515     }
8516   }
8517 
8518   GST_DEBUG_OBJECT (qtdemux, "allocating n_samples %u * %u (%.2f MB)",
8519       stream->n_samples, (guint) sizeof (QtDemuxSample),
8520       stream->n_samples * sizeof (QtDemuxSample) / (1024.0 * 1024.0));
8521 
8522   if (stream->n_samples >=
8523       QTDEMUX_MAX_SAMPLE_INDEX_SIZE / sizeof (QtDemuxSample)) {
8524     GST_WARNING_OBJECT (qtdemux, "not allocating index of %d samples, would "
8525         "be larger than %uMB (broken file?)", stream->n_samples,
8526         QTDEMUX_MAX_SAMPLE_INDEX_SIZE >> 20);
8527     return FALSE;
8528   }
8529 
8530   g_assert (stream->samples == NULL);
8531   stream->samples = g_try_new0 (QtDemuxSample, stream->n_samples);
8532   if (!stream->samples) {
8533     GST_WARNING_OBJECT (qtdemux, "failed to allocate %d samples",
8534         stream->n_samples);
8535     return FALSE;
8536   }
8537 
8538   /* composition time-to-sample */
8539   if ((stream->ctts_present =
8540           ! !qtdemux_tree_get_child_by_type_full (stbl, FOURCC_ctts,
8541               &stream->ctts) ? TRUE : FALSE) == TRUE) {
8542     GstByteReader cslg = GST_BYTE_READER_INIT (NULL, 0);
8543 
8544     /* copy atom data into a new buffer for later use */
8545     stream->ctts.data = g_memdup (stream->ctts.data, stream->ctts.size);
8546 
8547     /* skip version + flags */
8548     if (!gst_byte_reader_skip (&stream->ctts, 1 + 3)
8549         || !gst_byte_reader_get_uint32_be (&stream->ctts,
8550             &stream->n_composition_times))
8551       goto corrupt_file;
8552 
8553     /* make sure there's enough data */
8554     if (!qt_atom_parser_has_chunks (&stream->ctts, stream->n_composition_times,
8555             4 + 4))
8556       goto corrupt_file;
8557 
8558     /* This is optional, if missing we iterate the ctts */
8559     if (qtdemux_tree_get_child_by_type_full (stbl, FOURCC_cslg, &cslg)) {
8560       if (!gst_byte_reader_skip (&cslg, 1 + 3)
8561           || !gst_byte_reader_get_uint32_be (&cslg, &stream->cslg_shift)) {
8562         g_free ((gpointer) cslg.data);
8563         goto corrupt_file;
8564   }
8565     } else {
8566       gint32 cslg_least = 0;
8567       guint num_entries, pos;
8568       gint i;
8569 
8570       pos = gst_byte_reader_get_pos (&stream->ctts);
8571       num_entries = stream->n_composition_times;
8572 
8573       stream->cslg_shift = 0;
8574 
8575       for (i = 0; i < num_entries; i++) {
8576         gint32 offset;
8577 
8578         gst_byte_reader_skip_unchecked (&stream->ctts, 4);
8579         offset = gst_byte_reader_get_int32_be_unchecked (&stream->ctts);
8580 
8581         if (offset < cslg_least)
8582           cslg_least = offset;
8583       }
8584 
8585       if (cslg_least < 0)
8586         stream->cslg_shift = ABS (cslg_least);
8587       else
8588         stream->cslg_shift = 0;
8589 
8590       /* reset the reader so we can generate sample table */
8591       gst_byte_reader_set_pos (&stream->ctts, pos);
8592     }
8593   } else {
8594     /* Ensure the cslg_shift value is consistent so we can use it
8595      * unconditionnally to produce TS and Segment */
8596     stream->cslg_shift = 0;
8597   }
8598 
8599   return TRUE;
8600 
8601 corrupt_file:
8602   {
8603     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
8604         (_("This file is corrupt and cannot be played.")), (NULL));
8605     return FALSE;
8606   }
8607 no_samples:
8608   {
8609     gst_qtdemux_stbl_free (stream);
8610     if (!qtdemux->fragmented) {
8611       /* not quite good */
8612       GST_WARNING_OBJECT (qtdemux, "stream has no samples");
8613       return FALSE;
8614     } else {
8615       /* may pick up samples elsewhere */
8616       return TRUE;
8617     }
8618   }
8619 }
8620 
8621 /* collect samples from the next sample to be parsed up to sample @n for @stream
8622  * by reading the info from @stbl
8623  *
8624  * This code can be executed from both the streaming thread and the seeking
8625  * thread so it takes the object lock to protect itself
8626  */
8627 static gboolean
8628 qtdemux_parse_samples (GstQTDemux * qtdemux, QtDemuxStream * stream, guint32 n)
8629 {
8630   gint i, j, k;
8631   QtDemuxSample *samples, *first, *cur, *last;
8632   guint32 n_samples_per_chunk;
8633   guint32 n_samples;
8634 
8635   GST_LOG_OBJECT (qtdemux, "parsing samples for stream fourcc %"
8636       GST_FOURCC_FORMAT ", pad %s",
8637       GST_FOURCC_ARGS (CUR_STREAM (stream)->fourcc),
8638       stream->pad ? GST_PAD_NAME (stream->pad) : "(NULL)");
8639 
8640   n_samples = stream->n_samples;
8641 
8642   if (n >= n_samples)
8643     goto out_of_samples;
8644 
8645   GST_OBJECT_LOCK (qtdemux);
8646   if (n <= stream->stbl_index)
8647     goto already_parsed;
8648 
8649   GST_DEBUG_OBJECT (qtdemux, "parsing up to sample %u", n);
8650 
8651   if (!stream->stsz.data) {
8652     /* so we already parsed and passed all the moov samples;
8653      * onto fragmented ones */
8654     g_assert (qtdemux->fragmented);
8655     goto done;
8656   }
8657 
8658   /* pointer to the sample table */
8659   samples = stream->samples;
8660 
8661   /* starts from -1, moves to the next sample index to parse */
8662   stream->stbl_index++;
8663 
8664   /* keep track of the first and last sample to fill */
8665   first = &samples[stream->stbl_index];
8666   last = &samples[n];
8667 
8668   if (!stream->chunks_are_samples) {
8669     /* set the sample sizes */
8670     if (stream->sample_size == 0) {
8671       /* different sizes for each sample */
8672       for (cur = first; cur <= last; cur++) {
8673         cur->size = gst_byte_reader_get_uint32_be_unchecked (&stream->stsz);
8674         GST_LOG_OBJECT (qtdemux, "sample %d has size %u",
8675             (guint) (cur - samples), cur->size);
8676       }
8677     } else {
8678       /* samples have the same size */
8679       GST_LOG_OBJECT (qtdemux, "all samples have size %u", stream->sample_size);
8680       for (cur = first; cur <= last; cur++)
8681         cur->size = stream->sample_size;
8682     }
8683   }
8684 
8685   n_samples_per_chunk = stream->n_samples_per_chunk;
8686   cur = first;
8687 
8688   for (i = stream->stsc_index; i < n_samples_per_chunk; i++) {
8689     guint32 last_chunk;
8690 
8691     if (stream->stsc_chunk_index >= stream->last_chunk
8692         || stream->stsc_chunk_index < stream->first_chunk) {
8693       stream->first_chunk =
8694           gst_byte_reader_get_uint32_be_unchecked (&stream->stsc);
8695       stream->samples_per_chunk =
8696           gst_byte_reader_get_uint32_be_unchecked (&stream->stsc);
8697       /* starts from 1 */
8698       stream->stsd_sample_description_id =
8699           gst_byte_reader_get_uint32_be_unchecked (&stream->stsc) - 1;
8700 
8701       /* chunk numbers are counted from 1 it seems */
8702       if (G_UNLIKELY (stream->first_chunk == 0))
8703         goto corrupt_file;
8704 
8705       --stream->first_chunk;
8706 
8707       /* the last chunk of each entry is calculated by taking the first chunk
8708        * of the next entry; except if there is no next, where we fake it with
8709        * INT_MAX */
8710       if (G_UNLIKELY (i == (stream->n_samples_per_chunk - 1))) {
8711         stream->last_chunk = G_MAXUINT32;
8712       } else {
8713         stream->last_chunk =
8714             gst_byte_reader_peek_uint32_be_unchecked (&stream->stsc);
8715         if (G_UNLIKELY (stream->last_chunk == 0))
8716           goto corrupt_file;
8717 
8718         --stream->last_chunk;
8719       }
8720 
8721       GST_LOG_OBJECT (qtdemux,
8722           "entry %d has first_chunk %d, last_chunk %d, samples_per_chunk %d"
8723           "sample desc ID: %d", i, stream->first_chunk, stream->last_chunk,
8724           stream->samples_per_chunk, stream->stsd_sample_description_id);
8725 
8726       if (G_UNLIKELY (stream->last_chunk < stream->first_chunk))
8727         goto corrupt_file;
8728 
8729       if (stream->last_chunk != G_MAXUINT32) {
8730         if (!qt_atom_parser_peek_sub (&stream->stco,
8731                 stream->first_chunk * stream->co_size,
8732                 (stream->last_chunk - stream->first_chunk) * stream->co_size,
8733                 &stream->co_chunk))
8734           goto corrupt_file;
8735 
8736       } else {
8737         stream->co_chunk = stream->stco;
8738         if (!gst_byte_reader_skip (&stream->co_chunk,
8739                 stream->first_chunk * stream->co_size))
8740           goto corrupt_file;
8741       }
8742 
8743       stream->stsc_chunk_index = stream->first_chunk;
8744     }
8745 
8746     last_chunk = stream->last_chunk;
8747 
8748     if (stream->chunks_are_samples) {
8749       cur = &samples[stream->stsc_chunk_index];
8750 
8751       for (j = stream->stsc_chunk_index; j < last_chunk; j++) {
8752         if (j > n) {
8753           /* save state */
8754           stream->stsc_chunk_index = j;
8755           goto done;
8756         }
8757 
8758         cur->offset =
8759             qt_atom_parser_get_offset_unchecked (&stream->co_chunk,
8760             stream->co_size);
8761 
8762         GST_LOG_OBJECT (qtdemux, "Created entry %d with offset "
8763             "%" G_GUINT64_FORMAT, j, cur->offset);
8764 
8765         if (CUR_STREAM (stream)->samples_per_frame > 0 &&
8766             CUR_STREAM (stream)->bytes_per_frame > 0) {
8767           cur->size =
8768               (stream->samples_per_chunk * CUR_STREAM (stream)->n_channels) /
8769               CUR_STREAM (stream)->samples_per_frame *
8770               CUR_STREAM (stream)->bytes_per_frame;
8771         } else {
8772           cur->size = stream->samples_per_chunk;
8773         }
8774 
8775         GST_DEBUG_OBJECT (qtdemux,
8776             "keyframe sample %d: timestamp %" GST_TIME_FORMAT ", size %u",
8777             j, GST_TIME_ARGS (QTSTREAMTIME_TO_GSTTIME (stream,
8778                     stream->stco_sample_index)), cur->size);
8779 
8780         cur->timestamp = stream->stco_sample_index;
8781         cur->duration = stream->samples_per_chunk;
8782         cur->keyframe = TRUE;
8783         cur++;
8784 
8785         stream->stco_sample_index += stream->samples_per_chunk;
8786       }
8787       stream->stsc_chunk_index = j;
8788     } else {
8789       for (j = stream->stsc_chunk_index; j < last_chunk; j++) {
8790         guint32 samples_per_chunk;
8791         guint64 chunk_offset;
8792 
8793         if (!stream->stsc_sample_index
8794             && !qt_atom_parser_get_offset (&stream->co_chunk, stream->co_size,
8795                 &stream->chunk_offset))
8796           goto corrupt_file;
8797 
8798         samples_per_chunk = stream->samples_per_chunk;
8799         chunk_offset = stream->chunk_offset;
8800 
8801         for (k = stream->stsc_sample_index; k < samples_per_chunk; k++) {
8802           GST_LOG_OBJECT (qtdemux, "creating entry %d with offset %"
8803               G_GUINT64_FORMAT " and size %d",
8804               (guint) (cur - samples), chunk_offset, cur->size);
8805 
8806           cur->offset = chunk_offset;
8807           chunk_offset += cur->size;
8808           cur++;
8809 
8810           if (G_UNLIKELY (cur > last)) {
8811             /* save state */
8812             stream->stsc_sample_index = k + 1;
8813             stream->chunk_offset = chunk_offset;
8814             stream->stsc_chunk_index = j;
8815             goto done2;
8816     }
8817         }
8818         stream->stsc_sample_index = 0;
8819       }
8820       stream->stsc_chunk_index = j;
8821     }
8822     stream->stsc_index++;
8823   }
8824 
8825   if (stream->chunks_are_samples)
8826     goto ctts;
8827 done2:
8828   {
8829     guint32 n_sample_times;
8830 
8831     n_sample_times = stream->n_sample_times;
8832     cur = first;
8833 
8834     for (i = stream->stts_index; i < n_sample_times; i++) {
8835       guint32 stts_samples;
8836       gint32 stts_duration;
8837       gint64 stts_time;
8838 
8839       if (stream->stts_sample_index >= stream->stts_samples
8840           || !stream->stts_sample_index) {
8841 
8842         stream->stts_samples =
8843             gst_byte_reader_get_uint32_be_unchecked (&stream->stts);
8844         stream->stts_duration =
8845             gst_byte_reader_get_uint32_be_unchecked (&stream->stts);
8846 
8847         GST_LOG_OBJECT (qtdemux, "block %d, %u timestamps, duration %u",
8848             i, stream->stts_samples, stream->stts_duration);
8849 
8850         stream->stts_sample_index = 0;
8851       }
8852 
8853       stts_samples = stream->stts_samples;
8854       stts_duration = stream->stts_duration;
8855       stts_time = stream->stts_time;
8856 
8857       for (j = stream->stts_sample_index; j < stts_samples; j++) {
8858         GST_DEBUG_OBJECT (qtdemux,
8859             "sample %d: index %d, timestamp %" GST_TIME_FORMAT,
8860             (guint) (cur - samples), j,
8861             GST_TIME_ARGS (QTSTREAMTIME_TO_GSTTIME (stream, stts_time)));
8862 
8863         cur->timestamp = stts_time;
8864         cur->duration = stts_duration;
8865 
8866         /* avoid 32-bit wrap-around,
8867          * but still mind possible 'negative' duration */
8868         stts_time += (gint64) stts_duration;
8869         cur++;
8870 
8871         if (G_UNLIKELY (cur > last)) {
8872           /* save values */
8873           stream->stts_time = stts_time;
8874           stream->stts_sample_index = j + 1;
8875           if (stream->stts_sample_index >= stream->stts_samples)
8876             stream->stts_index++;
8877           goto done3;
8878         }
8879       }
8880       stream->stts_sample_index = 0;
8881       stream->stts_time = stts_time;
8882       stream->stts_index++;
8883     }
8884     /* fill up empty timestamps with the last timestamp, this can happen when
8885      * the last samples do not decode and so we don't have timestamps for them.
8886      * We however look at the last timestamp to estimate the track length so we
8887      * need something in here. */
8888     for (; cur < last; cur++) {
8889       GST_DEBUG_OBJECT (qtdemux,
8890           "fill sample %d: timestamp %" GST_TIME_FORMAT,
8891           (guint) (cur - samples),
8892           GST_TIME_ARGS (QTSTREAMTIME_TO_GSTTIME (stream, stream->stts_time)));
8893       cur->timestamp = stream->stts_time;
8894       cur->duration = -1;
8895     }
8896   }
8897 done3:
8898   {
8899     /* sample sync, can be NULL */
8900     if (stream->stss_present == TRUE) {
8901       guint32 n_sample_syncs;
8902 
8903       n_sample_syncs = stream->n_sample_syncs;
8904 
8905       if (!n_sample_syncs) {
8906         GST_DEBUG_OBJECT (qtdemux, "all samples are keyframes");
8907         stream->all_keyframe = TRUE;
8908       } else {
8909         for (i = stream->stss_index; i < n_sample_syncs; i++) {
8910           /* note that the first sample is index 1, not 0 */
8911           guint32 index;
8912 
8913           index = gst_byte_reader_get_uint32_be_unchecked (&stream->stss);
8914 
8915           if (G_LIKELY (index > 0 && index <= n_samples)) {
8916             index -= 1;
8917             samples[index].keyframe = TRUE;
8918             GST_DEBUG_OBJECT (qtdemux, "samples at %u is keyframe", index);
8919             /* and exit if we have enough samples */
8920             if (G_UNLIKELY (index >= n)) {
8921               i++;
8922               break;
8923             }
8924           }
8925         }
8926         /* save state */
8927         stream->stss_index = i;
8928       }
8929 
8930       /* stps marks partial sync frames like open GOP I-Frames */
8931       if (stream->stps_present == TRUE) {
8932         guint32 n_sample_partial_syncs;
8933 
8934         n_sample_partial_syncs = stream->n_sample_partial_syncs;
8935 
8936         /* if there are no entries, the stss table contains the real
8937          * sync samples */
8938         if (n_sample_partial_syncs) {
8939           for (i = stream->stps_index; i < n_sample_partial_syncs; i++) {
8940             /* note that the first sample is index 1, not 0 */
8941             guint32 index;
8942 
8943             index = gst_byte_reader_get_uint32_be_unchecked (&stream->stps);
8944 
8945             if (G_LIKELY (index > 0 && index <= n_samples)) {
8946               index -= 1;
8947               samples[index].keyframe = TRUE;
8948               GST_DEBUG_OBJECT (qtdemux, "samples at %u is keyframe", index);
8949               /* and exit if we have enough samples */
8950               if (G_UNLIKELY (index >= n)) {
8951                 i++;
8952                 break;
8953               }
8954             }
8955           }
8956           /* save state */
8957           stream->stps_index = i;
8958         }
8959       }
8960     } else {
8961       /* no stss, all samples are keyframes */
8962       stream->all_keyframe = TRUE;
8963       GST_DEBUG_OBJECT (qtdemux, "setting all keyframes");
8964     }
8965   }
8966 
8967 ctts:
8968   /* composition time to sample */
8969   if (stream->ctts_present == TRUE) {
8970     guint32 n_composition_times;
8971     guint32 ctts_count;
8972     gint32 ctts_soffset;
8973 
8974     /* Fill in the pts_offsets */
8975     cur = first;
8976     n_composition_times = stream->n_composition_times;
8977 
8978     for (i = stream->ctts_index; i < n_composition_times; i++) {
8979       if (stream->ctts_sample_index >= stream->ctts_count
8980           || !stream->ctts_sample_index) {
8981         stream->ctts_count =
8982             gst_byte_reader_get_uint32_be_unchecked (&stream->ctts);
8983         stream->ctts_soffset =
8984             gst_byte_reader_get_int32_be_unchecked (&stream->ctts);
8985         stream->ctts_sample_index = 0;
8986       }
8987 
8988       ctts_count = stream->ctts_count;
8989       ctts_soffset = stream->ctts_soffset;
8990 
8991       for (j = stream->ctts_sample_index; j < ctts_count; j++) {
8992         cur->pts_offset = ctts_soffset;
8993         cur++;
8994 
8995         if (G_UNLIKELY (cur > last)) {
8996           /* save state */
8997           stream->ctts_sample_index = j + 1;
8998           goto done;
8999         }
9000       }
9001       stream->ctts_sample_index = 0;
9002       stream->ctts_index++;
9003     }
9004   }
9005 done:
9006   stream->stbl_index = n;
9007   /* if index has been completely parsed, free data that is no-longer needed */
9008   if (n + 1 == stream->n_samples) {
9009     gst_qtdemux_stbl_free (stream);
9010     GST_DEBUG_OBJECT (qtdemux, "parsed all available samples;");
9011     if (qtdemux->pullbased) {
9012       GST_DEBUG_OBJECT (qtdemux, "checking for more samples");
9013     while (n + 1 == stream->n_samples)
9014       if (qtdemux_add_fragmented_samples (qtdemux) != GST_FLOW_OK)
9015         break;
9016   }
9017   }
9018   GST_OBJECT_UNLOCK (qtdemux);
9019 
9020   return TRUE;
9021 
9022   /* SUCCESS */
9023 already_parsed:
9024   {
9025     GST_LOG_OBJECT (qtdemux,
9026         "Tried to parse up to sample %u but this sample has already been parsed",
9027         n);
9028     /* if fragmented, there may be more */
9029     if (qtdemux->fragmented && n == stream->stbl_index)
9030       goto done;
9031     GST_OBJECT_UNLOCK (qtdemux);
9032     return TRUE;
9033   }
9034   /* ERRORS */
9035 out_of_samples:
9036   {
9037     GST_LOG_OBJECT (qtdemux,
9038         "Tried to parse up to sample %u but there are only %u samples", n + 1,
9039         stream->n_samples);
9040     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
9041         (_("This file is corrupt and cannot be played.")), (NULL));
9042     return FALSE;
9043   }
9044 corrupt_file:
9045   {
9046     GST_OBJECT_UNLOCK (qtdemux);
9047     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
9048         (_("This file is corrupt and cannot be played.")), (NULL));
9049     return FALSE;
9050   }
9051 }
9052 
9053 /* collect all segment info for @stream.
9054  */
9055 static gboolean
9056 qtdemux_parse_segments (GstQTDemux * qtdemux, QtDemuxStream * stream,
9057     GNode * trak)
9058 {
9059   GNode *edts;
9060   /* accept edts if they contain gaps at start and there is only
9061    * one media segment */
9062   gboolean allow_pushbased_edts = TRUE;
9063   gint media_segments_count = 0;
9064 
9065   /* parse and prepare segment info from the edit list */
9066   GST_DEBUG_OBJECT (qtdemux, "looking for edit list container");
9067   stream->n_segments = 0;
9068   stream->segments = NULL;
9069   if ((edts = qtdemux_tree_get_child_by_type (trak, FOURCC_edts))) {
9070     GNode *elst;
9071     gint n_segments;
9072     gint i, count, entry_size;
9073     guint64 time;
9074     GstClockTime stime;
9075     const guint8 *buffer;
9076     guint8 version;
9077     guint32 size;
9078 
9079     GST_DEBUG_OBJECT (qtdemux, "looking for edit list");
9080     if (!(elst = qtdemux_tree_get_child_by_type (edts, FOURCC_elst)))
9081       goto done;
9082 
9083     buffer = elst->data;
9084 
9085     size = QT_UINT32 (buffer);
9086     /* version, flags, n_segments */
9087     if (size < 16) {
9088       GST_WARNING_OBJECT (qtdemux, "Invalid edit list");
9089       goto done;
9090     }
9091     version = QT_UINT8 (buffer + 8);
9092     entry_size = (version == 1) ? 20 : 12;
9093 
9094     n_segments = QT_UINT32 (buffer + 12);
9095 
9096     if (n_segments > 100000 || size < 16 + n_segments * entry_size) {
9097       GST_WARNING_OBJECT (qtdemux, "Invalid edit list");
9098       goto done;
9099     }
9100 
9101     /* we might allocate a bit too much, at least allocate 1 segment */
9102     stream->segments = g_new (QtDemuxSegment, MAX (n_segments, 1));
9103 
9104     /* segments always start from 0 */
9105     time = 0;
9106     stime = 0;
9107     count = 0;
9108     buffer += 16;
9109     for (i = 0; i < n_segments; i++) {
9110       guint64 duration;
9111       guint64 media_time;
9112       gboolean time_valid = TRUE;
9113       QtDemuxSegment *segment;
9114       guint32 rate_int;
9115       GstClockTime media_start = GST_CLOCK_TIME_NONE;
9116 
9117      if (version == 1) {
9118         media_time = QT_UINT64 (buffer + 8);
9119         duration = QT_UINT64 (buffer);
9120         if (media_time == G_MAXUINT64)
9121           time_valid = FALSE;
9122       } else {
9123         media_time = QT_UINT32 (buffer + 4);
9124         duration = QT_UINT32 (buffer);
9125         if (media_time == G_MAXUINT32)
9126           time_valid = FALSE;
9127       }
9128 
9129       if (time_valid)
9130         media_start = QTSTREAMTIME_TO_GSTTIME (stream, media_time);
9131 
9132       segment = &stream->segments[count++];
9133 
9134       /* time and duration expressed in global timescale */
9135       segment->time = stime;
9136       /* add non scaled values so we don't cause roundoff errors */
9137       if (duration || media_start == GST_CLOCK_TIME_NONE) {
9138       time += duration;
9139         stime = QTTIME_TO_GSTTIME (qtdemux, time);
9140         segment->duration = stime - segment->time;
9141       } else {
9142         /* zero duration does not imply media_start == media_stop
9143          * but, only specify media_start.*/
9144         stime = QTTIME_TO_GSTTIME (qtdemux, qtdemux->duration);
9145         if (GST_CLOCK_TIME_IS_VALID (stime) && time_valid
9146             && stime >= media_start) {
9147           segment->duration = stime - media_start;
9148         } else {
9149           segment->duration = GST_CLOCK_TIME_NONE;
9150         }
9151       }
9152       segment->stop_time = stime;
9153 
9154       segment->trak_media_start = media_time;
9155       /* media_time expressed in stream timescale */
9156       if (time_valid) {
9157         segment->media_start = media_start;
9158         segment->media_stop = segment->media_start + segment->duration;
9159         media_segments_count++;
9160       } else {
9161         segment->media_start = GST_CLOCK_TIME_NONE;
9162         segment->media_stop = GST_CLOCK_TIME_NONE;
9163       }
9164       rate_int = QT_UINT32 (buffer + ((version == 1) ? 16 : 8));
9165 
9166       if (rate_int <= 1) {
9167         /* 0 is not allowed, some programs write 1 instead of the floating point
9168          * value */
9169         GST_WARNING_OBJECT (qtdemux, "found suspicious rate %" G_GUINT32_FORMAT,
9170             rate_int);
9171         segment->rate = 1;
9172       } else {
9173         segment->rate = rate_int / 65536.0;
9174       }
9175 
9176       GST_DEBUG_OBJECT (qtdemux, "created segment %d time %" GST_TIME_FORMAT
9177           ", duration %" GST_TIME_FORMAT ", media_start %" GST_TIME_FORMAT
9178           " (%" G_GUINT64_FORMAT ") , media_stop %" GST_TIME_FORMAT
9179           " stop_time %" GST_TIME_FORMAT " rate %g, (%d) timescale %u",
9180           i, GST_TIME_ARGS (segment->time),
9181           GST_TIME_ARGS (segment->duration),
9182           GST_TIME_ARGS (segment->media_start), media_time,
9183           GST_TIME_ARGS (segment->media_stop),
9184           GST_TIME_ARGS (segment->stop_time), segment->rate, rate_int,
9185           stream->timescale);
9186       if (segment->stop_time > qtdemux->segment.stop) {
9187         GST_WARNING_OBJECT (qtdemux, "Segment %d "
9188             " extends to %" GST_TIME_FORMAT
9189             " past the end of the file duration %" GST_TIME_FORMAT
9190             " it will be truncated", i, GST_TIME_ARGS (segment->stop_time),
9191             GST_TIME_ARGS (qtdemux->segment.stop));
9192         qtdemux->segment.stop = segment->stop_time;
9193     }
9194 
9195       buffer += entry_size;
9196     }
9197     GST_DEBUG_OBJECT (qtdemux, "found %d segments", count);
9198     stream->n_segments = count;
9199     if (media_segments_count != 1)
9200       allow_pushbased_edts = FALSE;
9201   }
9202 done:
9203 
9204   /* push based does not handle segments, so act accordingly here,
9205    * and warn if applicable */
9206   if (!qtdemux->pullbased && !allow_pushbased_edts) {
9207     GST_WARNING_OBJECT (qtdemux, "streaming; discarding edit list segments");
9208     /* remove and use default one below, we stream like it anyway */
9209     g_free (stream->segments);
9210     stream->segments = NULL;
9211     stream->n_segments = 0;
9212   }
9213 
9214   /* no segments, create one to play the complete trak */
9215   if (stream->n_segments == 0) {
9216     GstClockTime stream_duration =
9217         QTSTREAMTIME_TO_GSTTIME (stream, stream->duration);
9218 
9219     if (stream->segments == NULL)
9220       stream->segments = g_new (QtDemuxSegment, 1);
9221 
9222     /* represent unknown our way */
9223     if (stream_duration == 0)
9224       stream_duration = GST_CLOCK_TIME_NONE;
9225 
9226     stream->segments[0].time = 0;
9227     stream->segments[0].stop_time = stream_duration;
9228     stream->segments[0].duration = stream_duration;
9229     stream->segments[0].media_start = 0;
9230     stream->segments[0].media_stop = stream_duration;
9231     stream->segments[0].rate = 1.0;
9232     stream->segments[0].trak_media_start = 0;
9233 
9234     GST_DEBUG_OBJECT (qtdemux, "created dummy segment %" GST_TIME_FORMAT,
9235         GST_TIME_ARGS (stream_duration));
9236     stream->n_segments = 1;
9237     stream->dummy_segment = TRUE;
9238   }
9239   GST_DEBUG_OBJECT (qtdemux, "using %d segments", stream->n_segments);
9240 
9241   return TRUE;
9242 }
9243 
9244 /*
9245  * Parses the stsd atom of a svq3 trak looking for
9246  * the SMI and gama atoms.
9247  */
9248 static void
9249 qtdemux_parse_svq3_stsd_data (GstQTDemux * qtdemux,
9250     const guint8 * stsd_entry_data, const guint8 ** gamma, GstBuffer ** seqh)
9251 {
9252   const guint8 *_gamma = NULL;
9253   GstBuffer *_seqh = NULL;
9254   const guint8 *stsd_data = stsd_entry_data;
9255   guint32 length = QT_UINT32 (stsd_data);
9256   guint16 version;
9257 
9258   if (length < 32) {
9259     GST_WARNING_OBJECT (qtdemux, "stsd too short");
9260     goto end;
9261   }
9262 
9263   stsd_data += 16;
9264   length -= 16;
9265   version = QT_UINT16 (stsd_data);
9266   if (version == 3) {
9267     if (length >= 70) {
9268       length -= 70;
9269       stsd_data += 70;
9270       while (length > 8) {
9271         guint32 fourcc, size;
9272         const guint8 *data;
9273         size = QT_UINT32 (stsd_data);
9274         fourcc = QT_FOURCC (stsd_data + 4);
9275         data = stsd_data + 8;
9276 
9277         if (size == 0) {
9278           GST_WARNING_OBJECT (qtdemux, "Atom of size 0 found, aborting "
9279               "svq3 atom parsing");
9280           goto end;
9281         }
9282 
9283         switch (fourcc) {
9284           case FOURCC_gama:{
9285             if (size == 12) {
9286               _gamma = data;
9287             } else {
9288               GST_WARNING_OBJECT (qtdemux, "Unexpected size %" G_GUINT32_FORMAT
9289                   " for gama atom, expected 12", size);
9290             }
9291             break;
9292           }
9293           case FOURCC_SMI_:{
9294             if (size > 16 && QT_FOURCC (data) == FOURCC_SEQH) {
9295               guint32 seqh_size;
9296               if (_seqh != NULL) {
9297                 GST_WARNING_OBJECT (qtdemux, "Unexpected second SEQH SMI atom "
9298                     " found, ignoring");
9299               } else {
9300                 seqh_size = QT_UINT32 (data + 4);
9301                 if (seqh_size > 0) {
9302                   _seqh = gst_buffer_new_and_alloc (seqh_size);
9303                   gst_buffer_fill (_seqh, 0, data + 8, seqh_size);
9304                 }
9305               }
9306             }
9307             break;
9308           }
9309           default:{
9310             GST_WARNING_OBJECT (qtdemux, "Unhandled atom %" GST_FOURCC_FORMAT
9311                 " in SVQ3 entry in stsd atom", GST_FOURCC_ARGS (fourcc));
9312           }
9313         }
9314 
9315         if (size <= length) {
9316           length -= size;
9317           stsd_data += size;
9318         }
9319       }
9320     } else {
9321       GST_WARNING_OBJECT (qtdemux, "SVQ3 entry too short in stsd atom");
9322     }
9323   } else {
9324     GST_WARNING_OBJECT (qtdemux, "Unexpected version for SVQ3 entry %"
9325         G_GUINT16_FORMAT, version);
9326     goto end;
9327   }
9328 
9329 end:
9330   if (gamma) {
9331     *gamma = _gamma;
9332   }
9333   if (seqh) {
9334     *seqh = _seqh;
9335   } else if (_seqh) {
9336     gst_buffer_unref (_seqh);
9337   }
9338 }
9339 
9340 static gchar *
9341 qtdemux_get_rtsp_uri_from_hndl (GstQTDemux * qtdemux, GNode * minf)
9342 {
9343   GNode *dinf;
9344   GstByteReader dref;
9345   gchar *uri = NULL;
9346 
9347   /*
9348    * Get 'dinf', to get its child 'dref', that might contain a 'hndl'
9349    * atom that might contain a 'data' atom with the rtsp uri.
9350    * This case was reported in bug #597497, some info about
9351    * the hndl atom can be found in TN1195
9352    */
9353   dinf = qtdemux_tree_get_child_by_type (minf, FOURCC_dinf);
9354   GST_DEBUG_OBJECT (qtdemux, "Trying to obtain rtsp URI for stream trak");
9355 
9356   if (dinf) {
9357     guint32 dref_num_entries = 0;
9358     if (qtdemux_tree_get_child_by_type_full (dinf, FOURCC_dref, &dref) &&
9359         gst_byte_reader_skip (&dref, 4) &&
9360         gst_byte_reader_get_uint32_be (&dref, &dref_num_entries)) {
9361       gint i;
9362 
9363       /* search dref entries for hndl atom */
9364       for (i = 0; i < dref_num_entries; i++) {
9365         guint32 size = 0, type;
9366         guint8 string_len = 0;
9367         if (gst_byte_reader_get_uint32_be (&dref, &size) &&
9368             qt_atom_parser_get_fourcc (&dref, &type)) {
9369           if (type == FOURCC_hndl) {
9370             GST_DEBUG_OBJECT (qtdemux, "Found hndl atom");
9371 
9372             /* skip data reference handle bytes and the
9373              * following pascal string and some extra 4
9374              * bytes I have no idea what are */
9375             if (!gst_byte_reader_skip (&dref, 4) ||
9376                 !gst_byte_reader_get_uint8 (&dref, &string_len) ||
9377                 !gst_byte_reader_skip (&dref, string_len + 4)) {
9378               GST_WARNING_OBJECT (qtdemux, "Failed to parse hndl atom");
9379               break;
9380             }
9381 
9382             /* iterate over the atoms to find the data atom */
9383             while (gst_byte_reader_get_remaining (&dref) >= 8) {
9384               guint32 atom_size;
9385               guint32 atom_type;
9386 
9387               if (gst_byte_reader_get_uint32_be (&dref, &atom_size) &&
9388                   qt_atom_parser_get_fourcc (&dref, &atom_type)) {
9389                 if (atom_type == FOURCC_data) {
9390                   const guint8 *uri_aux = NULL;
9391 
9392                   /* found the data atom that might contain the rtsp uri */
9393                   GST_DEBUG_OBJECT (qtdemux, "Found data atom inside "
9394                       "hndl atom, interpreting it as an URI");
9395                   if (gst_byte_reader_peek_data (&dref, atom_size - 8,
9396                           &uri_aux)) {
9397                     if (g_strstr_len ((gchar *) uri_aux, 7, "rtsp://") != NULL)
9398                       uri = g_strndup ((gchar *) uri_aux, atom_size - 8);
9399                     else
9400                       GST_WARNING_OBJECT (qtdemux, "Data atom in hndl atom "
9401                           "didn't contain a rtsp address");
9402                   } else {
9403                     GST_WARNING_OBJECT (qtdemux, "Failed to get the data "
9404                         "atom contents");
9405                   }
9406                   break;
9407                 }
9408                 /* skipping to the next entry */
9409                 if (!gst_byte_reader_skip (&dref, atom_size - 8))
9410                   break;
9411               } else {
9412                 GST_WARNING_OBJECT (qtdemux, "Failed to parse hndl child "
9413                     "atom header");
9414                 break;
9415               }
9416             }
9417             break;
9418           }
9419           /* skip to the next entry */
9420           if (!gst_byte_reader_skip (&dref, size - 8))
9421             break;
9422         } else {
9423           GST_WARNING_OBJECT (qtdemux, "Error parsing dref atom");
9424         }
9425       }
9426       GST_DEBUG_OBJECT (qtdemux, "Finished parsing dref atom");
9427     }
9428   }
9429   return uri;
9430 }
9431 
9432 #define AMR_NB_ALL_MODES        0x81ff
9433 #define AMR_WB_ALL_MODES        0x83ff
9434 static guint
9435 qtdemux_parse_amr_bitrate (GstBuffer * buf, gboolean wb)
9436 {
9437   /* The 'damr' atom is of the form:
9438    *
9439    * | vendor | decoder_ver | mode_set | mode_change_period | frames/sample |
9440    *    32 b       8 b          16 b           8 b                 8 b
9441    *
9442    * The highest set bit of the first 7 (AMR-NB) or 8 (AMR-WB) bits of mode_set
9443    * represents the highest mode used in the stream (and thus the maximum
9444    * bitrate), with a couple of special cases as seen below.
9445    */
9446 
9447   /* Map of frame type ID -> bitrate */
9448   static const guint nb_bitrates[] = {
9449     4750, 5150, 5900, 6700, 7400, 7950, 10200, 12200
9450   };
9451   static const guint wb_bitrates[] = {
9452     6600, 8850, 12650, 14250, 15850, 18250, 19850, 23050, 23850
9453   };
9454   GstMapInfo map;
9455   gsize max_mode;
9456   guint16 mode_set;
9457 
9458   gst_buffer_map (buf, &map, GST_MAP_READ);
9459 
9460   if (map.size != 0x11) {
9461     GST_DEBUG ("Atom should have size 0x11, not %" G_GSIZE_FORMAT, map.size);
9462     goto bad_data;
9463   }
9464 
9465   if (QT_FOURCC (map.data + 4) != FOURCC_damr) {
9466     GST_DEBUG ("Unknown atom in %" GST_FOURCC_FORMAT,
9467         GST_FOURCC_ARGS (QT_UINT32 (map.data + 4)));
9468     goto bad_data;
9469   }
9470 
9471   mode_set = QT_UINT16 (map.data + 13);
9472 
9473   if (mode_set == (wb ? AMR_WB_ALL_MODES : AMR_NB_ALL_MODES))
9474     max_mode = 7 + (wb ? 1 : 0);
9475   else
9476     /* AMR-NB modes fo from 0-7, and AMR-WB modes go from 0-8 */
9477     max_mode = g_bit_nth_msf ((gulong) mode_set & (wb ? 0x1ff : 0xff), -1);
9478 
9479   if (max_mode == -1) {
9480     GST_DEBUG ("No mode indication was found (mode set) = %x",
9481         (guint) mode_set);
9482     goto bad_data;
9483   }
9484 
9485   gst_buffer_unmap (buf, &map);
9486   return wb ? wb_bitrates[max_mode] : nb_bitrates[max_mode];
9487 
9488 bad_data:
9489   gst_buffer_unmap (buf, &map);
9490   return 0;
9491 }
9492 
9493 static gboolean
9494 qtdemux_parse_transformation_matrix (GstQTDemux * qtdemux,
9495     GstByteReader * reader, guint32 * matrix, const gchar * atom)
9496 {
9497   /*
9498    * 9 values of 32 bits (fixed point 16.16, except 2 5 and 8 that are 2.30)
9499    * [0 1 2]
9500    * [3 4 5]
9501    * [6 7 8]
9502    */
9503 
9504   if (gst_byte_reader_get_remaining (reader) < 36)
9505     return FALSE;
9506 
9507   matrix[0] = gst_byte_reader_get_uint32_be_unchecked (reader);
9508   matrix[1] = gst_byte_reader_get_uint32_be_unchecked (reader);
9509   matrix[2] = gst_byte_reader_get_uint32_be_unchecked (reader);
9510   matrix[3] = gst_byte_reader_get_uint32_be_unchecked (reader);
9511   matrix[4] = gst_byte_reader_get_uint32_be_unchecked (reader);
9512   matrix[5] = gst_byte_reader_get_uint32_be_unchecked (reader);
9513   matrix[6] = gst_byte_reader_get_uint32_be_unchecked (reader);
9514   matrix[7] = gst_byte_reader_get_uint32_be_unchecked (reader);
9515   matrix[8] = gst_byte_reader_get_uint32_be_unchecked (reader);
9516 
9517   GST_DEBUG_OBJECT (qtdemux, "Transformation matrix from atom %s", atom);
9518   GST_DEBUG_OBJECT (qtdemux, "%u.%u %u.%u %u.%u", matrix[0] >> 16,
9519       matrix[0] & 0xFFFF, matrix[1] >> 16, matrix[1] & 0xFF, matrix[2] >> 16,
9520       matrix[2] & 0xFF);
9521   GST_DEBUG_OBJECT (qtdemux, "%u.%u %u.%u %u.%u", matrix[3] >> 16,
9522       matrix[3] & 0xFFFF, matrix[4] >> 16, matrix[4] & 0xFF, matrix[5] >> 16,
9523       matrix[5] & 0xFF);
9524   GST_DEBUG_OBJECT (qtdemux, "%u.%u %u.%u %u.%u", matrix[6] >> 16,
9525       matrix[6] & 0xFFFF, matrix[7] >> 16, matrix[7] & 0xFF, matrix[8] >> 16,
9526       matrix[8] & 0xFF);
9527 
9528   return TRUE;
9529 }
9530 
9531 static void
9532 qtdemux_inspect_transformation_matrix (GstQTDemux * qtdemux,
9533     QtDemuxStream * stream, guint32 * matrix, GstTagList ** taglist)
9534 {
9535 
9536 /* [a b c]
9537  * [d e f]
9538  * [g h i]
9539  *
9540  * This macro will only compare value abdegh, it expects cfi to have already
9541  * been checked
9542  */
9543 #define QTCHECK_MATRIX(m,a,b,d,e) ((m)[0] == (a << 16) && (m)[1] == (b << 16) && \
9544                                    (m)[3] == (d << 16) && (m)[4] == (e << 16))
9545 
9546   /* only handle the cases where the last column has standard values */
9547   if (matrix[2] == 0 && matrix[5] == 0 && matrix[8] == 1 << 30) {
9548     const gchar *rotation_tag = NULL;
9549 
9550     /* no rotation needed */
9551     if (QTCHECK_MATRIX (matrix, 1, 0, 0, 1)) {
9552       /* NOP */
9553     } else if (QTCHECK_MATRIX (matrix, 0, 1, G_MAXUINT16, 0)) {
9554       rotation_tag = "rotate-90";
9555     } else if (QTCHECK_MATRIX (matrix, G_MAXUINT16, 0, 0, G_MAXUINT16)) {
9556       rotation_tag = "rotate-180";
9557     } else if (QTCHECK_MATRIX (matrix, 0, G_MAXUINT16, 1, 0)) {
9558       rotation_tag = "rotate-270";
9559     } else {
9560       GST_FIXME_OBJECT (qtdemux, "Unhandled transformation matrix values");
9561     }
9562 
9563     GST_DEBUG_OBJECT (qtdemux, "Transformation matrix rotation %s",
9564         rotation_tag);
9565     if (rotation_tag != NULL) {
9566       if (*taglist == NULL)
9567         *taglist = gst_tag_list_new_empty ();
9568       gst_tag_list_add (*taglist, GST_TAG_MERGE_REPLACE,
9569           GST_TAG_IMAGE_ORIENTATION, rotation_tag, NULL);
9570     }
9571   } else {
9572     GST_FIXME_OBJECT (qtdemux, "Unhandled transformation matrix values");
9573   }
9574 }
9575 
9576 /* Parses the boxes defined in ISO/IEC 14496-12 that enable support for
9577  * protected streams (sinf, frma, schm and schi); if the protection scheme is
9578  * Common Encryption (cenc), the function will also parse the tenc box (defined
9579  * in ISO/IEC 23001-7). @container points to the node that contains these boxes
9580  * (typically an enc[v|a|t|s] sample entry); the function will set
9581  * @original_fmt to the fourcc of the original unencrypted stream format.
9582  * Returns TRUE if successful; FALSE otherwise. */
9583 static gboolean
9584 qtdemux_parse_protection_scheme_info (GstQTDemux * qtdemux,
9585     QtDemuxStream * stream, GNode * container, guint32 * original_fmt)
9586 {
9587   GNode *sinf;
9588   GNode *frma;
9589   GNode *schm;
9590   GNode *schi;
9591 
9592   g_return_val_if_fail (qtdemux != NULL, FALSE);
9593   g_return_val_if_fail (stream != NULL, FALSE);
9594   g_return_val_if_fail (container != NULL, FALSE);
9595   g_return_val_if_fail (original_fmt != NULL, FALSE);
9596 
9597   sinf = qtdemux_tree_get_child_by_type (container, FOURCC_sinf);
9598   if (G_UNLIKELY (!sinf)) {
9599     if (stream->protection_scheme_type == FOURCC_cenc) {
9600       GST_ERROR_OBJECT (qtdemux, "sinf box does not contain schi box, which is "
9601           "mandatory for Common Encryption");
9602       return FALSE;
9603     }
9604     return TRUE;
9605   }
9606 
9607   frma = qtdemux_tree_get_child_by_type (sinf, FOURCC_frma);
9608   if (G_UNLIKELY (!frma)) {
9609     GST_ERROR_OBJECT (qtdemux, "sinf box does not contain mandatory frma box");
9610     return FALSE;
9611   }
9612 
9613   *original_fmt = QT_FOURCC ((const guint8 *) frma->data + 8);
9614   GST_DEBUG_OBJECT (qtdemux, "original stream format: '%" GST_FOURCC_FORMAT "'",
9615       GST_FOURCC_ARGS (*original_fmt));
9616 
9617   schm = qtdemux_tree_get_child_by_type (sinf, FOURCC_schm);
9618   if (!schm) {
9619     GST_DEBUG_OBJECT (qtdemux, "sinf box does not contain schm box");
9620     return FALSE;
9621   }
9622   stream->protection_scheme_type = QT_FOURCC ((const guint8 *) schm->data + 12);
9623   stream->protection_scheme_version =
9624       QT_UINT32 ((const guint8 *) schm->data + 16);
9625 
9626   GST_DEBUG_OBJECT (qtdemux,
9627       "protection_scheme_type: %" GST_FOURCC_FORMAT ", "
9628       "protection_scheme_version: %#010x",
9629       GST_FOURCC_ARGS (stream->protection_scheme_type),
9630       stream->protection_scheme_version);
9631 
9632   schi = qtdemux_tree_get_child_by_type (sinf, FOURCC_schi);
9633   if (!schi) {
9634     GST_DEBUG_OBJECT (qtdemux, "sinf box does not contain schi box");
9635     return FALSE;
9636   }
9637   if (stream->protection_scheme_type == FOURCC_cenc) {
9638     QtDemuxCencSampleSetInfo *info;
9639     GNode *tenc;
9640     const guint8 *tenc_data;
9641     guint32 isEncrypted;
9642     guint8 iv_size;
9643     const guint8 *default_kid;
9644     GstBuffer *kid_buf;
9645 
9646     if (G_UNLIKELY (!stream->protection_scheme_info))
9647       stream->protection_scheme_info =
9648           g_malloc0 (sizeof (QtDemuxCencSampleSetInfo));
9649 
9650     info = (QtDemuxCencSampleSetInfo *) stream->protection_scheme_info;
9651 
9652     tenc = qtdemux_tree_get_child_by_type (schi, FOURCC_tenc);
9653     if (!tenc) {
9654       GST_ERROR_OBJECT (qtdemux, "schi box does not contain tenc box, "
9655           "which is mandatory for Common Encryption");
9656       return FALSE;
9657     }
9658     tenc_data = (const guint8 *) tenc->data + 12;
9659     isEncrypted = QT_UINT24 (tenc_data);
9660     iv_size = QT_UINT8 (tenc_data + 3);
9661     default_kid = (tenc_data + 4);
9662     kid_buf = gst_buffer_new_allocate (NULL, 16, NULL);
9663     gst_buffer_fill (kid_buf, 0, default_kid, 16);
9664     if (info->default_properties)
9665       gst_structure_free (info->default_properties);
9666     info->default_properties =
9667         gst_structure_new ("application/x-cenc",
9668         "iv_size", G_TYPE_UINT, iv_size,
9669         "encrypted", G_TYPE_BOOLEAN, (isEncrypted == 1),
9670         "kid", GST_TYPE_BUFFER, kid_buf, NULL);
9671     GST_DEBUG_OBJECT (qtdemux, "default sample properties: "
9672         "is_encrypted=%u, iv_size=%u", isEncrypted, iv_size);
9673     gst_buffer_unref (kid_buf);
9674   }
9675   return TRUE;
9676 }
9677 
9678 /* parse the traks.
9679  * With each track we associate a new QtDemuxStream that contains all the info
9680  * about the trak.
9681  * traks that do not decode to something (like strm traks) will not have a pad.
9682  */
9683 static gboolean
9684 qtdemux_parse_trak (GstQTDemux * qtdemux, GNode * trak)
9685 {
9686   GstByteReader tkhd;
9687   int offset;
9688   GNode *mdia;
9689   GNode *mdhd;
9690   GNode *hdlr;
9691   GNode *minf;
9692   GNode *stbl;
9693   GNode *stsd;
9694   GNode *mp4a;
9695   GNode *mp4v;
9696   GNode *esds;
9697   GNode *tref;
9698   GNode *udta;
9699   GNode *svmi;
9700 
9701   QtDemuxStream *stream = NULL;
9702   gboolean new_stream = FALSE;
9703   const guint8 *stsd_data;
9704   const guint8 *stsd_entry_data;
9705   guint remaining_stsd_len;
9706   guint stsd_entry_count;
9707   guint stsd_index;
9708   guint16 lang_code;            /* quicktime lang code or packed iso code */
9709   guint32 version;
9710   guint32 tkhd_flags = 0;
9711   guint8 tkhd_version = 0;
9712   guint32 w = 0, h = 0;
9713   guint value_size, stsd_len, len;
9714   guint32 track_id;
9715   guint32 dummy;
9716 
9717   GST_DEBUG_OBJECT (qtdemux, "parse_trak");
9718 
9719   if (!qtdemux_tree_get_child_by_type_full (trak, FOURCC_tkhd, &tkhd)
9720       || !gst_byte_reader_get_uint8 (&tkhd, &tkhd_version)
9721       || !gst_byte_reader_get_uint24_be (&tkhd, &tkhd_flags))
9722     goto corrupt_file;
9723 
9724   /* pick between 64 or 32 bits */
9725   value_size = tkhd_version == 1 ? 8 : 4;
9726   if (!gst_byte_reader_skip (&tkhd, value_size * 2) ||
9727       !gst_byte_reader_get_uint32_be (&tkhd, &track_id))
9728     goto corrupt_file;
9729 
9730   if (!qtdemux->got_moov) {
9731     if (qtdemux_find_stream (qtdemux, track_id))
9732       goto existing_stream;
9733     stream = _create_stream ();
9734     stream->track_id = track_id;
9735     new_stream = TRUE;
9736   } else {
9737     stream = qtdemux_find_stream (qtdemux, track_id);
9738     if (!stream) {
9739       GST_WARNING_OBJECT (qtdemux, "Stream not found, going to ignore it");
9740       goto skip_track;
9741     }
9742 
9743     /* reset reused stream */
9744     gst_qtdemux_stream_reset (qtdemux, stream);
9745   }
9746   /* need defaults for fragments */
9747   qtdemux_parse_trex (qtdemux, stream, &dummy, &dummy, &dummy);
9748 
9749   if ((tkhd_flags & 1) == 0)
9750     stream->disabled = TRUE;
9751 
9752 #ifdef GSTREAMER_LITE
9753   // set track_enabled based on bit 0 of flags
9754   stream->track_enabled = (gboolean)(tkhd_flags & 0x000001);
9755 #endif // GSTREAMER_LITE
9756 
9757   GST_LOG_OBJECT (qtdemux, "track[tkhd] version/flags/id: 0x%02x/%06x/%u",
9758       tkhd_version, tkhd_flags, stream->track_id);
9759 
9760   if (!(mdia = qtdemux_tree_get_child_by_type (trak, FOURCC_mdia)))
9761     goto corrupt_file;
9762 
9763   if (!(mdhd = qtdemux_tree_get_child_by_type (mdia, FOURCC_mdhd))) {
9764     /* be nice for some crooked mjp2 files that use mhdr for mdhd */
9765     if (qtdemux->major_brand != FOURCC_mjp2 ||
9766         !(mdhd = qtdemux_tree_get_child_by_type (mdia, FOURCC_mhdr)))
9767       goto corrupt_file;
9768   }
9769 
9770   len = QT_UINT32 ((guint8 *) mdhd->data);
9771   version = QT_UINT32 ((guint8 *) mdhd->data + 8);
9772   GST_LOG_OBJECT (qtdemux, "track version/flags: %08x", version);
9773   if (version == 0x01000000) {
9774     if (len < 38)
9775       goto corrupt_file;
9776     stream->timescale = QT_UINT32 ((guint8 *) mdhd->data + 28);
9777     stream->duration = QT_UINT64 ((guint8 *) mdhd->data + 32);
9778     lang_code = QT_UINT16 ((guint8 *) mdhd->data + 36);
9779   } else {
9780     if (len < 30)
9781       goto corrupt_file;
9782     stream->timescale = QT_UINT32 ((guint8 *) mdhd->data + 20);
9783     stream->duration = QT_UINT32 ((guint8 *) mdhd->data + 24);
9784     lang_code = QT_UINT16 ((guint8 *) mdhd->data + 28);
9785   }
9786 
9787   if (lang_code < 0x400) {
9788     qtdemux_lang_map_qt_code_to_iso (stream->lang_id, lang_code);
9789   } else if (lang_code == 0x7fff) {
9790     stream->lang_id[0] = 0;     /* unspecified */
9791   } else {
9792     stream->lang_id[0] = 0x60 + ((lang_code >> 10) & 0x1F);
9793     stream->lang_id[1] = 0x60 + ((lang_code >> 5) & 0x1F);
9794     stream->lang_id[2] = 0x60 + (lang_code & 0x1F);
9795     stream->lang_id[3] = 0;
9796   }
9797 
9798   GST_LOG_OBJECT (qtdemux, "track timescale: %" G_GUINT32_FORMAT,
9799       stream->timescale);
9800   GST_LOG_OBJECT (qtdemux, "track duration: %" G_GUINT64_FORMAT,
9801       stream->duration);
9802   GST_LOG_OBJECT (qtdemux, "track language code/id: 0x%04x/%s",
9803       lang_code, stream->lang_id);
9804 
9805   if (G_UNLIKELY (stream->timescale == 0 || qtdemux->timescale == 0))
9806     goto corrupt_file;
9807 
9808   if ((tref = qtdemux_tree_get_child_by_type (trak, FOURCC_tref))) {
9809     /* chapters track reference */
9810     GNode *chap = qtdemux_tree_get_child_by_type (tref, FOURCC_chap);
9811     if (chap) {
9812       gsize length = GST_READ_UINT32_BE (chap->data);
9813       if (qtdemux->chapters_track_id)
9814         GST_FIXME_OBJECT (qtdemux, "Multiple CHAP tracks");
9815 
9816       if (length >= 12) {
9817         qtdemux->chapters_track_id =
9818             GST_READ_UINT32_BE ((gint8 *) chap->data + 8);
9819       }
9820     }
9821   }
9822 
9823   /* fragmented files may have bogus duration in moov */
9824   if (!qtdemux->fragmented &&
9825       qtdemux->duration != G_MAXINT64 && stream->duration != G_MAXINT32) {
9826     guint64 tdur1, tdur2;
9827 
9828     /* don't overflow */
9829     tdur1 = stream->timescale * (guint64) qtdemux->duration;
9830     tdur2 = qtdemux->timescale * (guint64) stream->duration;
9831 
9832     /* HACK:
9833      * some of those trailers, nowadays, have prologue images that are
9834      * themselves video tracks as well. I haven't really found a way to
9835      * identify those yet, except for just looking at their duration. */
9836     if (tdur1 != 0 && (tdur2 * 10 / tdur1) < 2) {
9837       GST_WARNING_OBJECT (qtdemux,
9838           "Track shorter than 20%% (%" G_GUINT64_FORMAT "/%" G_GUINT32_FORMAT
9839           " vs. %" G_GUINT64_FORMAT "/%" G_GUINT32_FORMAT ") of the stream "
9840           "found, assuming preview image or something; skipping track",
9841           stream->duration, stream->timescale, qtdemux->duration,
9842           qtdemux->timescale);
9843       if (new_stream)
9844         gst_qtdemux_stream_free (qtdemux, stream);
9845       return TRUE;
9846     }
9847   }
9848 
9849   if (!(hdlr = qtdemux_tree_get_child_by_type (mdia, FOURCC_hdlr)))
9850     goto corrupt_file;
9851 
9852   GST_LOG_OBJECT (qtdemux, "track type: %" GST_FOURCC_FORMAT,
9853       GST_FOURCC_ARGS (QT_FOURCC ((guint8 *) hdlr->data + 12)));
9854 
9855   len = QT_UINT32 ((guint8 *) hdlr->data);
9856   if (len >= 20)
9857     stream->subtype = QT_FOURCC ((guint8 *) hdlr->data + 16);
9858   GST_LOG_OBJECT (qtdemux, "track subtype: %" GST_FOURCC_FORMAT,
9859       GST_FOURCC_ARGS (stream->subtype));
9860 
9861   if (!(minf = qtdemux_tree_get_child_by_type (mdia, FOURCC_minf)))
9862     goto corrupt_file;
9863 
9864   if (!(stbl = qtdemux_tree_get_child_by_type (minf, FOURCC_stbl)))
9865     goto corrupt_file;
9866 
9867   /*parse svmi header if existing */
9868   svmi = qtdemux_tree_get_child_by_type (stbl, FOURCC_svmi);
9869   if (svmi) {
9870     len = QT_UINT32 ((guint8 *) svmi->data);
9871     version = QT_UINT32 ((guint8 *) svmi->data + 8);
9872     if (!version) {
9873       GstVideoMultiviewMode mode = GST_VIDEO_MULTIVIEW_MODE_NONE;
9874       GstVideoMultiviewFlags flags = GST_VIDEO_MULTIVIEW_FLAGS_NONE;
9875       guint8 frame_type, frame_layout;
9876 
9877       /* MPEG-A stereo video */
9878       if (qtdemux->major_brand == FOURCC_ss02)
9879         flags |= GST_VIDEO_MULTIVIEW_FLAGS_MIXED_MONO;
9880 
9881       frame_type = QT_UINT8 ((guint8 *) svmi->data + 12);
9882       frame_layout = QT_UINT8 ((guint8 *) svmi->data + 13) & 0x01;
9883       switch (frame_type) {
9884         case 0:
9885           mode = GST_VIDEO_MULTIVIEW_MODE_SIDE_BY_SIDE;
9886           break;
9887         case 1:
9888           mode = GST_VIDEO_MULTIVIEW_MODE_ROW_INTERLEAVED;
9889           break;
9890         case 2:
9891           mode = GST_VIDEO_MULTIVIEW_MODE_FRAME_BY_FRAME;
9892           break;
9893         case 3:
9894           /* mode 3 is primary/secondary view sequence, ie
9895            * left/right views in separate tracks. See section 7.2
9896            * of ISO/IEC 23000-11:2009 */
9897           GST_FIXME_OBJECT (qtdemux,
9898               "Implement stereo video in separate streams");
9899       }
9900 
9901       if ((frame_layout & 0x1) == 0)
9902         flags |= GST_VIDEO_MULTIVIEW_FLAGS_RIGHT_VIEW_FIRST;
9903 
9904       GST_LOG_OBJECT (qtdemux,
9905           "StereoVideo: composition type: %u, is_left_first: %u",
9906           frame_type, frame_layout);
9907       stream->multiview_mode = mode;
9908       stream->multiview_flags = flags;
9909     }
9910   }
9911 
9912   /* parse rest of tkhd */
9913   if (stream->subtype == FOURCC_vide) {
9914     guint32 matrix[9];
9915 
9916     /* version 1 uses some 64-bit ints */
9917     if (!gst_byte_reader_skip (&tkhd, 20 + value_size))
9918       goto corrupt_file;
9919 
9920     if (!qtdemux_parse_transformation_matrix (qtdemux, &tkhd, matrix, "tkhd"))
9921       goto corrupt_file;
9922 
9923     if (!gst_byte_reader_get_uint32_be (&tkhd, &w)
9924         || !gst_byte_reader_get_uint32_be (&tkhd, &h))
9925       goto corrupt_file;
9926 
9927     qtdemux_inspect_transformation_matrix (qtdemux, stream, matrix,
9928         &stream->stream_tags);
9929   }
9930 
9931   /* parse stsd */
9932   if (!(stsd = qtdemux_tree_get_child_by_type (stbl, FOURCC_stsd)))
9933     goto corrupt_file;
9934   stsd_data = (const guint8 *) stsd->data;
9935 
9936   /* stsd should at least have one entry */
9937   stsd_len = QT_UINT32 (stsd_data);
9938   if (stsd_len < 24) {
9939     /* .. but skip stream with empty stsd produced by some Vivotek cameras */
9940     if (stream->subtype == FOURCC_vivo) {
9941       if (new_stream)
9942         gst_qtdemux_stream_free (qtdemux, stream);
9943       return TRUE;
9944     } else {
9945     goto corrupt_file;
9946     }
9947   }
9948 
9949   stream->stsd_entries_length = stsd_entry_count = QT_UINT32 (stsd_data + 12);
9950   stream->stsd_entries = g_new0 (QtDemuxStreamStsdEntry, stsd_entry_count);
9951 #ifdef GSTREAMER_LITE
9952   // Even if we check stsd header length (stsd_len) to make sure we have at least
9953   // one entry, we still might have actual entry count set to 0. g_new0() will
9954   // return NULL if fail or count is 0.
9955   if (stream->stsd_entries == NULL) {
9956     goto corrupt_file;
9957   }
9958 #endif // GSTREAMER_LITE
9959   GST_LOG_OBJECT (qtdemux, "stsd len:           %d", stsd_len);
9960   GST_LOG_OBJECT (qtdemux, "stsd entry count:   %u", stsd_entry_count);
9961 
9962   stsd_entry_data = stsd_data + 16;
9963   remaining_stsd_len = stsd_len - 16;
9964   for (stsd_index = 0; stsd_index < stsd_entry_count; stsd_index++) {
9965     guint32 fourcc;
9966     gchar *codec = NULL;
9967     QtDemuxStreamStsdEntry *entry = &stream->stsd_entries[stsd_index];
9968 
9969   /* and that entry should fit within stsd */
9970     len = QT_UINT32 (stsd_entry_data);
9971     if (len > remaining_stsd_len)
9972     goto corrupt_file;
9973 
9974     entry->fourcc = fourcc = QT_FOURCC (stsd_entry_data + 4);
9975   GST_LOG_OBJECT (qtdemux, "stsd type:          %" GST_FOURCC_FORMAT,
9976         GST_FOURCC_ARGS (entry->fourcc));
9977   GST_LOG_OBJECT (qtdemux, "stsd type len:      %d", len);
9978 
9979     if ((fourcc == FOURCC_drms) || (fourcc == FOURCC_drmi))
9980     goto error_encrypted;
9981 
9982     if (fourcc == FOURCC_encv || fourcc == FOURCC_enca) {
9983       /* FIXME this looks wrong, there might be multiple children
9984        * with the same type */
9985       GNode *enc = qtdemux_tree_get_child_by_type (stsd, fourcc);
9986       stream->protected = TRUE;
9987       if (!qtdemux_parse_protection_scheme_info (qtdemux, stream, enc, &fourcc))
9988         GST_ERROR_OBJECT (qtdemux, "Failed to parse protection scheme info");
9989     }
9990 
9991   if (stream->subtype == FOURCC_vide) {
9992       GNode *colr;
9993       GNode *fiel;
9994       GNode *pasp;
9995     gboolean gray;
9996     gint depth, palette_size, palette_count;
9997     guint32 *palette_data = NULL;
9998 
9999       entry->sampled = TRUE;
10000 
10001     stream->display_width = w >> 16;
10002     stream->display_height = h >> 16;
10003 
10004     offset = 16;
10005       if (len < 86)             /* TODO verify */
10006       goto corrupt_file;
10007 
10008       entry->width = QT_UINT16 (stsd_entry_data + offset + 16);
10009       entry->height = QT_UINT16 (stsd_entry_data + offset + 18);
10010       entry->fps_n = 0;         /* this is filled in later */
10011       entry->fps_d = 0;         /* this is filled in later */
10012       entry->bits_per_sample = QT_UINT16 (stsd_entry_data + offset + 66);
10013       entry->color_table_id = QT_UINT16 (stsd_entry_data + offset + 68);
10014 
10015       /* if color_table_id is 0, ctab atom must follow; however some files
10016        * produced by TMPEGEnc have color_table_id = 0 and no ctab atom, so
10017        * if color table is not present we'll correct the value */
10018       if (entry->color_table_id == 0 &&
10019           (len < 90
10020               || QT_FOURCC (stsd_entry_data + offset + 70) != FOURCC_ctab)) {
10021         entry->color_table_id = -1;
10022       }
10023 
10024     GST_LOG_OBJECT (qtdemux, "width %d, height %d, bps %d, color table id %d",
10025           entry->width, entry->height, entry->bits_per_sample,
10026           entry->color_table_id);
10027 
10028       depth = entry->bits_per_sample;
10029 
10030     /* more than 32 bits means grayscale */
10031     gray = (depth > 32);
10032     /* low 32 bits specify the depth  */
10033     depth &= 0x1F;
10034 
10035     /* different number of palette entries is determined by depth. */
10036     palette_count = 0;
10037     if ((depth == 1) || (depth == 2) || (depth == 4) || (depth == 8))
10038       palette_count = (1 << depth);
10039     palette_size = palette_count * 4;
10040 
10041       if (entry->color_table_id) {
10042       switch (palette_count) {
10043         case 0:
10044           break;
10045         case 2:
10046           palette_data = g_memdup (ff_qt_default_palette_2, palette_size);
10047           break;
10048         case 4:
10049           palette_data = g_memdup (ff_qt_default_palette_4, palette_size);
10050           break;
10051         case 16:
10052           if (gray)
10053               palette_data =
10054                   g_memdup (ff_qt_grayscale_palette_16, palette_size);
10055           else
10056             palette_data = g_memdup (ff_qt_default_palette_16, palette_size);
10057           break;
10058         case 256:
10059           if (gray)
10060               palette_data =
10061                   g_memdup (ff_qt_grayscale_palette_256, palette_size);
10062           else
10063             palette_data = g_memdup (ff_qt_default_palette_256, palette_size);
10064           break;
10065         default:
10066           GST_ELEMENT_WARNING (qtdemux, STREAM, DEMUX,
10067               (_("The video in this file might not play correctly.")),
10068               ("unsupported palette depth %d", depth));
10069           break;
10070       }
10071     } else {
10072       gint i, j, start, end;
10073 
10074       if (len < 94)
10075         goto corrupt_file;
10076 
10077       /* read table */
10078         start = QT_UINT32 (stsd_entry_data + offset + 70);
10079         palette_count = QT_UINT16 (stsd_entry_data + offset + 74);
10080         end = QT_UINT16 (stsd_entry_data + offset + 76);
10081 
10082       GST_LOG_OBJECT (qtdemux, "start %d, end %d, palette_count %d",
10083           start, end, palette_count);
10084 
10085       if (end > 255)
10086         end = 255;
10087       if (start > end)
10088         start = end;
10089 
10090       if (len < 94 + (end - start) * 8)
10091         goto corrupt_file;
10092 
10093       /* palette is always the same size */
10094       palette_data = g_malloc0 (256 * 4);
10095       palette_size = 256 * 4;
10096 
10097       for (j = 0, i = start; i <= end; j++, i++) {
10098         guint32 a, r, g, b;
10099 
10100           a = QT_UINT16 (stsd_entry_data + offset + 78 + (j * 8));
10101           r = QT_UINT16 (stsd_entry_data + offset + 80 + (j * 8));
10102           g = QT_UINT16 (stsd_entry_data + offset + 82 + (j * 8));
10103           b = QT_UINT16 (stsd_entry_data + offset + 84 + (j * 8));
10104 
10105         palette_data[i] = ((a & 0xff00) << 16) | ((r & 0xff00) << 8) |
10106             (g & 0xff00) | (b >> 8);
10107       }
10108     }
10109 
10110       if (entry->caps)
10111         gst_caps_unref (entry->caps);
10112 
10113       entry->caps =
10114           qtdemux_video_caps (qtdemux, stream, entry, fourcc, stsd_entry_data,
10115           &codec);
10116       if (G_UNLIKELY (!entry->caps)) {
10117       g_free (palette_data);
10118       goto unknown_stream;
10119     }
10120 
10121     if (codec) {
10122         gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
10123           GST_TAG_VIDEO_CODEC, codec, NULL);
10124       g_free (codec);
10125       codec = NULL;
10126     }
10127 
10128     if (palette_data) {
10129       GstStructure *s;
10130 
10131         if (entry->rgb8_palette)
10132           gst_memory_unref (entry->rgb8_palette);
10133         entry->rgb8_palette = gst_memory_new_wrapped (GST_MEMORY_FLAG_READONLY,
10134           palette_data, palette_size, 0, palette_size, palette_data, g_free);
10135 
10136         s = gst_caps_get_structure (entry->caps, 0);
10137 
10138       /* non-raw video has a palette_data property. raw video has the palette as
10139        * an extra plane that we append to the output buffers before we push
10140        * them*/
10141       if (!gst_structure_has_name (s, "video/x-raw")) {
10142         GstBuffer *palette;
10143 
10144         palette = gst_buffer_new ();
10145           gst_buffer_append_memory (palette, entry->rgb8_palette);
10146           entry->rgb8_palette = NULL;
10147 
10148           gst_caps_set_simple (entry->caps, "palette_data",
10149             GST_TYPE_BUFFER, palette, NULL);
10150         gst_buffer_unref (palette);
10151       }
10152     } else if (palette_count != 0) {
10153       GST_ELEMENT_WARNING (qtdemux, STREAM, NOT_IMPLEMENTED,
10154           (NULL), ("Unsupported palette depth %d", depth));
10155     }
10156 
10157     GST_LOG_OBJECT (qtdemux, "frame count:   %u",
10158           QT_UINT16 (stsd_entry_data + offset + 32));
10159 
10160     esds = NULL;
10161     pasp = NULL;
10162       colr = NULL;
10163       fiel = NULL;
10164     /* pick 'the' stsd child */
10165       mp4v = qtdemux_tree_get_child_by_index (stsd, stsd_index);
10166       if (!stream->protected) {
10167         if (QTDEMUX_TREE_NODE_FOURCC (mp4v) != fourcc) {
10168           mp4v = NULL;
10169         }
10170       } else {
10171         if (QTDEMUX_TREE_NODE_FOURCC (mp4v) != FOURCC_encv) {
10172           mp4v = NULL;
10173         }
10174       }
10175 
10176     if (mp4v) {
10177       esds = qtdemux_tree_get_child_by_type (mp4v, FOURCC_esds);
10178       pasp = qtdemux_tree_get_child_by_type (mp4v, FOURCC_pasp);
10179         colr = qtdemux_tree_get_child_by_type (mp4v, FOURCC_colr);
10180         fiel = qtdemux_tree_get_child_by_type (mp4v, FOURCC_fiel);
10181     }
10182 
10183     if (pasp) {
10184       const guint8 *pasp_data = (const guint8 *) pasp->data;
10185         gint len = QT_UINT32 (pasp_data);
10186 
10187         if (len == 16) {
10188           CUR_STREAM (stream)->par_w = QT_UINT32 (pasp_data + 8);
10189           CUR_STREAM (stream)->par_h = QT_UINT32 (pasp_data + 12);
10190     } else {
10191           CUR_STREAM (stream)->par_w = 0;
10192           CUR_STREAM (stream)->par_h = 0;
10193     }
10194       } else {
10195         CUR_STREAM (stream)->par_w = 0;
10196         CUR_STREAM (stream)->par_h = 0;
10197       }
10198 
10199       if (fiel) {
10200         const guint8 *fiel_data = (const guint8 *) fiel->data;
10201         gint len = QT_UINT32 (fiel_data);
10202 
10203         if (len == 10) {
10204           CUR_STREAM (stream)->interlace_mode = GST_READ_UINT8 (fiel_data + 8);
10205           CUR_STREAM (stream)->field_order = GST_READ_UINT8 (fiel_data + 9);
10206         }
10207       }
10208 
10209       if (colr) {
10210         const guint8 *colr_data = (const guint8 *) colr->data;
10211         gint len = QT_UINT32 (colr_data);
10212 
10213         if (len == 19 || len == 18) {
10214           guint32 color_type = GST_READ_UINT32_LE (colr_data + 8);
10215 
10216           if (color_type == FOURCC_nclx || color_type == FOURCC_nclc) {
10217             guint16 primaries = GST_READ_UINT16_BE (colr_data + 12);
10218             guint16 transfer_function = GST_READ_UINT16_BE (colr_data + 14);
10219             guint16 matrix = GST_READ_UINT16_BE (colr_data + 16);
10220             gboolean full_range = len == 19 ? colr_data[17] >> 7 : FALSE;
10221 
10222             switch (primaries) {
10223               case 1:
10224                 CUR_STREAM (stream)->colorimetry.primaries =
10225                     GST_VIDEO_COLOR_PRIMARIES_BT709;
10226                 break;
10227               case 5:
10228                 CUR_STREAM (stream)->colorimetry.primaries =
10229                     GST_VIDEO_COLOR_PRIMARIES_BT470BG;
10230                 break;
10231               case 6:
10232                 CUR_STREAM (stream)->colorimetry.primaries =
10233                     GST_VIDEO_COLOR_PRIMARIES_SMPTE170M;
10234                 break;
10235               case 9:
10236                 CUR_STREAM (stream)->colorimetry.primaries =
10237                     GST_VIDEO_COLOR_PRIMARIES_BT2020;
10238                 break;
10239               default:
10240                 break;
10241             }
10242 
10243             switch (transfer_function) {
10244               case 1:
10245                 CUR_STREAM (stream)->colorimetry.transfer =
10246                     GST_VIDEO_TRANSFER_BT709;
10247                 break;
10248               case 7:
10249                 CUR_STREAM (stream)->colorimetry.transfer =
10250                     GST_VIDEO_TRANSFER_SMPTE240M;
10251                 break;
10252               default:
10253                 break;
10254             }
10255 
10256             switch (matrix) {
10257               case 1:
10258                 CUR_STREAM (stream)->colorimetry.matrix =
10259                     GST_VIDEO_COLOR_MATRIX_BT709;
10260                 break;
10261               case 6:
10262                 CUR_STREAM (stream)->colorimetry.matrix =
10263                     GST_VIDEO_COLOR_MATRIX_BT601;
10264                 break;
10265               case 7:
10266                 CUR_STREAM (stream)->colorimetry.matrix =
10267                     GST_VIDEO_COLOR_MATRIX_SMPTE240M;
10268                 break;
10269               case 9:
10270                 CUR_STREAM (stream)->colorimetry.matrix =
10271                     GST_VIDEO_COLOR_MATRIX_BT2020;
10272                 break;
10273               default:
10274                 break;
10275             }
10276 
10277             CUR_STREAM (stream)->colorimetry.range =
10278                 full_range ? GST_VIDEO_COLOR_RANGE_0_255 :
10279                 GST_VIDEO_COLOR_RANGE_16_235;
10280           } else {
10281             GST_DEBUG_OBJECT (qtdemux, "Unsupported color type");
10282           }
10283         } else {
10284           GST_WARNING_OBJECT (qtdemux, "Invalid colr atom size");
10285         }
10286       }
10287 
10288     if (esds) {
10289 #ifdef GSTREAMER_LITE
10290         if (!gst_qtdemux_handle_esds (qtdemux, stream, entry, esds,
10291                                       stream->stream_tags))
10292             goto corrupt_file;
10293 #else
10294         gst_qtdemux_handle_esds (qtdemux, stream, entry, esds,
10295             stream->stream_tags);
10296 #endif // GSTREAMER_LITE
10297     } else {
10298       switch (fourcc) {
10299         case FOURCC_H264:
10300         case FOURCC_avc1:
10301         case FOURCC_avc3:
10302         {
10303             gint len = QT_UINT32 (stsd_entry_data) - 0x56;
10304             const guint8 *avc_data = stsd_entry_data + 0x56;
10305 
10306           /* find avcC */
10307           while (len >= 0x8) {
10308             gint size;
10309 
10310             if (QT_UINT32 (avc_data) <= len)
10311               size = QT_UINT32 (avc_data) - 0x8;
10312             else
10313               size = len - 0x8;
10314 
10315             if (size < 1)
10316               /* No real data, so break out */
10317               break;
10318 
10319             switch (QT_FOURCC (avc_data + 0x4)) {
10320               case FOURCC_avcC:
10321               {
10322                 /* parse, if found */
10323                 GstBuffer *buf;
10324 
10325                 GST_DEBUG_OBJECT (qtdemux, "found avcC codec_data in stsd");
10326 
10327                 /* First 4 bytes are the length of the atom, the next 4 bytes
10328                  * are the fourcc, the next 1 byte is the version, and the
10329                  * subsequent bytes are profile_tier_level structure like data. */
10330                   gst_codec_utils_h264_caps_set_level_and_profile (entry->caps,
10331                     avc_data + 8 + 1, size - 1);
10332                 buf = gst_buffer_new_and_alloc (size);
10333                 gst_buffer_fill (buf, 0, avc_data + 0x8, size);
10334                   gst_caps_set_simple (entry->caps,
10335                     "codec_data", GST_TYPE_BUFFER, buf, NULL);
10336                 gst_buffer_unref (buf);
10337 
10338                 break;
10339               }
10340               case FOURCC_strf:
10341               {
10342                 GstBuffer *buf;
10343 
10344                 GST_DEBUG_OBJECT (qtdemux, "found strf codec_data in stsd");
10345 
10346                 /* First 4 bytes are the length of the atom, the next 4 bytes
10347                  * are the fourcc, next 40 bytes are BITMAPINFOHEADER,
10348                  * next 1 byte is the version, and the
10349                  * subsequent bytes are sequence parameter set like data. */
10350 
10351                   size -= 40;   /* we'll be skipping BITMAPINFOHEADER */
10352                 if (size > 1) {
10353                     gst_codec_utils_h264_caps_set_level_and_profile
10354                         (entry->caps, avc_data + 8 + 40 + 1, size - 1);
10355 
10356                   buf = gst_buffer_new_and_alloc (size);
10357                   gst_buffer_fill (buf, 0, avc_data + 8 + 40, size);
10358                     gst_caps_set_simple (entry->caps,
10359                       "codec_data", GST_TYPE_BUFFER, buf, NULL);
10360                   gst_buffer_unref (buf);
10361                 }
10362                 break;
10363               }
10364               case FOURCC_btrt:
10365               {
10366                 guint avg_bitrate, max_bitrate;
10367 
10368                 /* bufferSizeDB, maxBitrate and avgBitrate - 4 bytes each */
10369                 if (size < 12)
10370                   break;
10371 
10372                 max_bitrate = QT_UINT32 (avc_data + 0xc);
10373                 avg_bitrate = QT_UINT32 (avc_data + 0x10);
10374 
10375                 if (!max_bitrate && !avg_bitrate)
10376                   break;
10377 
10378                 /* Some muxers seem to swap the average and maximum bitrates
10379                  * (I'm looking at you, YouTube), so we swap for sanity. */
10380                 if (max_bitrate > 0 && max_bitrate < avg_bitrate) {
10381                   guint temp = avg_bitrate;
10382 
10383                   avg_bitrate = max_bitrate;
10384                   max_bitrate = temp;
10385                 }
10386 
10387                 if (max_bitrate > 0 && max_bitrate < G_MAXUINT32) {
10388                     gst_tag_list_add (stream->stream_tags,
10389                         GST_TAG_MERGE_REPLACE, GST_TAG_MAXIMUM_BITRATE,
10390                         max_bitrate, NULL);
10391                 }
10392                 if (avg_bitrate > 0 && avg_bitrate < G_MAXUINT32) {
10393                     gst_tag_list_add (stream->stream_tags,
10394                         GST_TAG_MERGE_REPLACE, GST_TAG_BITRATE, avg_bitrate,
10395                         NULL);
10396                 }
10397 
10398                 break;
10399               }
10400 
10401               default:
10402                 break;
10403             }
10404 
10405             len -= size + 8;
10406             avc_data += size + 8;
10407           }
10408 
10409           break;
10410         }
10411         case FOURCC_H265:
10412         case FOURCC_hvc1:
10413         case FOURCC_hev1:
10414         {
10415             gint len = QT_UINT32 (stsd_entry_data) - 0x56;
10416             const guint8 *hevc_data = stsd_entry_data + 0x56;
10417 
10418           /* find hevc */
10419           while (len >= 0x8) {
10420             gint size;
10421 
10422             if (QT_UINT32 (hevc_data) <= len)
10423               size = QT_UINT32 (hevc_data) - 0x8;
10424             else
10425               size = len - 0x8;
10426 
10427             if (size < 1)
10428               /* No real data, so break out */
10429               break;
10430 
10431             switch (QT_FOURCC (hevc_data + 0x4)) {
10432               case FOURCC_hvcC:
10433               {
10434                 /* parse, if found */
10435                 GstBuffer *buf;
10436 
10437                   GST_DEBUG_OBJECT (qtdemux, "found hvcC codec_data in stsd");
10438 
10439                 /* First 4 bytes are the length of the atom, the next 4 bytes
10440                  * are the fourcc, the next 1 byte is the version, and the
10441                  * subsequent bytes are sequence parameter set like data. */
10442                 gst_codec_utils_h265_caps_set_level_tier_and_profile
10443                       (entry->caps, hevc_data + 8 + 1, size - 1);
10444 
10445                 buf = gst_buffer_new_and_alloc (size);
10446                 gst_buffer_fill (buf, 0, hevc_data + 0x8, size);
10447                   gst_caps_set_simple (entry->caps,
10448                     "codec_data", GST_TYPE_BUFFER, buf, NULL);
10449                 gst_buffer_unref (buf);
10450                 break;
10451               }
10452               default:
10453                 break;
10454             }
10455             len -= size + 8;
10456             hevc_data += size + 8;
10457           }
10458           break;
10459         }
10460         case FOURCC_mp4v:
10461         case FOURCC_MP4V:
10462         case FOURCC_fmp4:
10463         case FOURCC_FMP4:
10464           case FOURCC_xvid:
10465           case FOURCC_XVID:
10466         {
10467           GNode *glbl;
10468 
10469           GST_DEBUG_OBJECT (qtdemux, "found %" GST_FOURCC_FORMAT,
10470               GST_FOURCC_ARGS (fourcc));
10471 
10472           /* codec data might be in glbl extension atom */
10473           glbl = mp4v ?
10474               qtdemux_tree_get_child_by_type (mp4v, FOURCC_glbl) : NULL;
10475           if (glbl) {
10476             guint8 *data;
10477             GstBuffer *buf;
10478             gint len;
10479 
10480             GST_DEBUG_OBJECT (qtdemux, "found glbl data in stsd");
10481             data = glbl->data;
10482             len = QT_UINT32 (data);
10483             if (len > 0x8) {
10484               len -= 0x8;
10485               buf = gst_buffer_new_and_alloc (len);
10486               gst_buffer_fill (buf, 0, data + 8, len);
10487                 gst_caps_set_simple (entry->caps,
10488                   "codec_data", GST_TYPE_BUFFER, buf, NULL);
10489               gst_buffer_unref (buf);
10490             }
10491           }
10492           break;
10493         }
10494         case FOURCC_mjp2:
10495         {
10496           /* see annex I of the jpeg2000 spec */
10497           GNode *jp2h, *ihdr, *colr, *mjp2, *field, *prefix, *cmap, *cdef;
10498           const guint8 *data;
10499           const gchar *colorspace = NULL;
10500           gint ncomp = 0;
10501           guint32 ncomp_map = 0;
10502           gint32 *comp_map = NULL;
10503           guint32 nchan_def = 0;
10504           gint32 *chan_def = NULL;
10505 
10506           GST_DEBUG_OBJECT (qtdemux, "found mjp2");
10507           /* some required atoms */
10508             mjp2 = qtdemux_tree_get_child_by_index (stsd, stsd_index);
10509           if (!mjp2)
10510             break;
10511           jp2h = qtdemux_tree_get_child_by_type (mjp2, FOURCC_jp2h);
10512           if (!jp2h)
10513             break;
10514 
10515           /* number of components; redundant with info in codestream, but useful
10516              to a muxer */
10517           ihdr = qtdemux_tree_get_child_by_type (jp2h, FOURCC_ihdr);
10518           if (!ihdr || QT_UINT32 (ihdr->data) != 22)
10519             break;
10520           ncomp = QT_UINT16 (((guint8 *) ihdr->data) + 16);
10521 
10522           colr = qtdemux_tree_get_child_by_type (jp2h, FOURCC_colr);
10523           if (!colr)
10524             break;
10525           GST_DEBUG_OBJECT (qtdemux, "found colr");
10526           /* extract colour space info */
10527           if (QT_UINT8 ((guint8 *) colr->data + 8) == 1) {
10528             switch (QT_UINT32 ((guint8 *) colr->data + 11)) {
10529               case 16:
10530                 colorspace = "sRGB";
10531                 break;
10532               case 17:
10533                 colorspace = "GRAY";
10534                 break;
10535               case 18:
10536                 colorspace = "sYUV";
10537                 break;
10538               default:
10539                 colorspace = NULL;
10540                 break;
10541             }
10542           }
10543           if (!colorspace)
10544             /* colr is required, and only values 16, 17, and 18 are specified,
10545                so error if we have no colorspace */
10546             break;
10547 
10548           /* extract component mapping */
10549           cmap = qtdemux_tree_get_child_by_type (jp2h, FOURCC_cmap);
10550           if (cmap) {
10551             guint32 cmap_len = 0;
10552             int i;
10553             cmap_len = QT_UINT32 (cmap->data);
10554             if (cmap_len >= 8) {
10555               /* normal box, subtract off header */
10556               cmap_len -= 8;
10557               /* cmap: { u16 cmp; u8 mtyp; u8 pcol; }* */
10558               if (cmap_len % 4 == 0) {
10559                 ncomp_map = (cmap_len / 4);
10560                 comp_map = g_new0 (gint32, ncomp_map);
10561                 for (i = 0; i < ncomp_map; i++) {
10562                   guint16 cmp;
10563                   guint8 mtyp, pcol;
10564                   cmp = QT_UINT16 (((guint8 *) cmap->data) + 8 + i * 4);
10565                   mtyp = QT_UINT8 (((guint8 *) cmap->data) + 8 + i * 4 + 2);
10566                   pcol = QT_UINT8 (((guint8 *) cmap->data) + 8 + i * 4 + 3);
10567                   comp_map[i] = (mtyp << 24) | (pcol << 16) | cmp;
10568                 }
10569               }
10570             }
10571           }
10572           /* extract channel definitions */
10573           cdef = qtdemux_tree_get_child_by_type (jp2h, FOURCC_cdef);
10574           if (cdef) {
10575             guint32 cdef_len = 0;
10576             int i;
10577             cdef_len = QT_UINT32 (cdef->data);
10578             if (cdef_len >= 10) {
10579               /* normal box, subtract off header and len */
10580               cdef_len -= 10;
10581               /* cdef: u16 n; { u16 cn; u16 typ; u16 asoc; }* */
10582               if (cdef_len % 6 == 0) {
10583                 nchan_def = (cdef_len / 6);
10584                 chan_def = g_new0 (gint32, nchan_def);
10585                 for (i = 0; i < nchan_def; i++)
10586                   chan_def[i] = -1;
10587                 for (i = 0; i < nchan_def; i++) {
10588                   guint16 cn, typ, asoc;
10589                   cn = QT_UINT16 (((guint8 *) cdef->data) + 10 + i * 6);
10590                   typ = QT_UINT16 (((guint8 *) cdef->data) + 10 + i * 6 + 2);
10591                   asoc = QT_UINT16 (((guint8 *) cdef->data) + 10 + i * 6 + 4);
10592                   if (cn < nchan_def) {
10593                     switch (typ) {
10594                       case 0:
10595                         chan_def[cn] = asoc;
10596                         break;
10597                       case 1:
10598                           chan_def[cn] = 0;     /* alpha */
10599                         break;
10600                       default:
10601                         chan_def[cn] = -typ;
10602                     }
10603                   }
10604                 }
10605               }
10606             }
10607           }
10608 
10609             gst_caps_set_simple (entry->caps,
10610               "num-components", G_TYPE_INT, ncomp, NULL);
10611             gst_caps_set_simple (entry->caps,
10612               "colorspace", G_TYPE_STRING, colorspace, NULL);
10613 
10614           if (comp_map) {
10615             GValue arr = { 0, };
10616             GValue elt = { 0, };
10617             int i;
10618             g_value_init (&arr, GST_TYPE_ARRAY);
10619             g_value_init (&elt, G_TYPE_INT);
10620             for (i = 0; i < ncomp_map; i++) {
10621               g_value_set_int (&elt, comp_map[i]);
10622               gst_value_array_append_value (&arr, &elt);
10623             }
10624               gst_structure_set_value (gst_caps_get_structure (entry->caps, 0),
10625                 "component-map", &arr);
10626             g_value_unset (&elt);
10627             g_value_unset (&arr);
10628             g_free (comp_map);
10629           }
10630 
10631           if (chan_def) {
10632             GValue arr = { 0, };
10633             GValue elt = { 0, };
10634             int i;
10635             g_value_init (&arr, GST_TYPE_ARRAY);
10636             g_value_init (&elt, G_TYPE_INT);
10637             for (i = 0; i < nchan_def; i++) {
10638               g_value_set_int (&elt, chan_def[i]);
10639               gst_value_array_append_value (&arr, &elt);
10640             }
10641               gst_structure_set_value (gst_caps_get_structure (entry->caps, 0),
10642                 "channel-definitions", &arr);
10643             g_value_unset (&elt);
10644             g_value_unset (&arr);
10645             g_free (chan_def);
10646           }
10647 
10648           /* some optional atoms */
10649           field = qtdemux_tree_get_child_by_type (mjp2, FOURCC_fiel);
10650           prefix = qtdemux_tree_get_child_by_type (mjp2, FOURCC_jp2x);
10651 
10652           /* indicate possible fields in caps */
10653           if (field) {
10654             data = (guint8 *) field->data + 8;
10655             if (*data != 1)
10656                 gst_caps_set_simple (entry->caps, "fields", G_TYPE_INT,
10657                   (gint) * data, NULL);
10658           }
10659           /* add codec_data if provided */
10660           if (prefix) {
10661             GstBuffer *buf;
10662             gint len;
10663 
10664             GST_DEBUG_OBJECT (qtdemux, "found prefix data in stsd");
10665             data = prefix->data;
10666             len = QT_UINT32 (data);
10667             if (len > 0x8) {
10668               len -= 0x8;
10669               buf = gst_buffer_new_and_alloc (len);
10670               gst_buffer_fill (buf, 0, data + 8, len);
10671                 gst_caps_set_simple (entry->caps,
10672                   "codec_data", GST_TYPE_BUFFER, buf, NULL);
10673               gst_buffer_unref (buf);
10674             }
10675           }
10676           break;
10677         }
10678         case FOURCC_SVQ3:
10679         case FOURCC_VP31:
10680         {
10681           GstBuffer *buf;
10682           GstBuffer *seqh = NULL;
10683             const guint8 *gamma_data = NULL;
10684             gint len = QT_UINT32 (stsd_data);   /* FIXME review - why put the whole stsd in codec data? */
10685 
10686             qtdemux_parse_svq3_stsd_data (qtdemux, stsd_entry_data, &gamma_data,
10687                 &seqh);
10688           if (gamma_data) {
10689               gst_caps_set_simple (entry->caps, "applied-gamma", G_TYPE_DOUBLE,
10690                 QT_FP32 (gamma_data), NULL);
10691           }
10692           if (seqh) {
10693             /* sorry for the bad name, but we don't know what this is, other
10694              * than its own fourcc */
10695               gst_caps_set_simple (entry->caps, "seqh", GST_TYPE_BUFFER, seqh,
10696                 NULL);
10697               gst_buffer_unref (seqh);
10698           }
10699 
10700           GST_DEBUG_OBJECT (qtdemux, "found codec_data in stsd");
10701           buf = gst_buffer_new_and_alloc (len);
10702           gst_buffer_fill (buf, 0, stsd_data, len);
10703             gst_caps_set_simple (entry->caps,
10704               "codec_data", GST_TYPE_BUFFER, buf, NULL);
10705           gst_buffer_unref (buf);
10706           break;
10707         }
10708           case FOURCC_jpeg:
10709           {
10710             /* https://developer.apple.com/standards/qtff-2001.pdf,
10711              * page 92, "Video Sample Description", under table 3.1 */
10712             GstByteReader br;
10713 
10714             const gint compressor_offset =
10715                 16 + 4 + 4 * 3 + 2 * 2 + 2 * 4 + 4 + 2;
10716             const gint min_size = compressor_offset + 32 + 2 + 2;
10717             GNode *jpeg;
10718             guint32 len;
10719             guint16 color_table_id = 0;
10720             gboolean ok;
10721 
10722             GST_DEBUG_OBJECT (qtdemux, "found jpeg");
10723 
10724             /* recover information on interlaced/progressive */
10725             jpeg = qtdemux_tree_get_child_by_type (stsd, FOURCC_jpeg);
10726             if (!jpeg)
10727               break;
10728 
10729             len = QT_UINT32 (jpeg->data);
10730             GST_DEBUG_OBJECT (qtdemux, "Found jpeg: len %u, need %d", len,
10731                 min_size);
10732             if (len >= min_size) {
10733               gst_byte_reader_init (&br, jpeg->data, len);
10734 
10735               gst_byte_reader_skip (&br, compressor_offset + 32 + 2);
10736               gst_byte_reader_get_uint16_le (&br, &color_table_id);
10737               if (color_table_id != 0) {
10738                 /* the spec says there can be concatenated chunks in the data, and we want
10739                  * to find one called field. Walk through them. */
10740                 gint offset = min_size;
10741                 while (offset + 8 < len) {
10742                   guint32 size = 0, tag;
10743                   ok = gst_byte_reader_get_uint32_le (&br, &size);
10744                   ok &= gst_byte_reader_get_uint32_le (&br, &tag);
10745                   if (!ok || size < 8) {
10746                     GST_WARNING_OBJECT (qtdemux,
10747                         "Failed to walk optional chunk list");
10748                     break;
10749                   }
10750                   GST_DEBUG_OBJECT (qtdemux,
10751                       "Found optional %4.4s chunk, size %u",
10752                       (const char *) &tag, size);
10753                   if (tag == FOURCC_fiel) {
10754                     guint8 n_fields = 0, ordering = 0;
10755                     gst_byte_reader_get_uint8 (&br, &n_fields);
10756                     gst_byte_reader_get_uint8 (&br, &ordering);
10757                     if (n_fields == 1 || n_fields == 2) {
10758                       GST_DEBUG_OBJECT (qtdemux,
10759                           "Found fiel tag with %u fields, ordering %u",
10760                           n_fields, ordering);
10761                       if (n_fields == 2)
10762                         gst_caps_set_simple (CUR_STREAM (stream)->caps,
10763                             "interlace-mode", G_TYPE_STRING, "interleaved",
10764                             NULL);
10765                     } else {
10766                       GST_WARNING_OBJECT (qtdemux,
10767                           "Found fiel tag with invalid fields (%u)", n_fields);
10768                     }
10769                   }
10770                   offset += size;
10771                 }
10772               } else {
10773                 GST_DEBUG_OBJECT (qtdemux,
10774                     "Color table ID is 0, not trying to get interlacedness");
10775               }
10776             } else {
10777               GST_WARNING_OBJECT (qtdemux,
10778                   "Length of jpeg chunk is too small, not trying to get interlacedness");
10779             }
10780 
10781             break;
10782           }
10783         case FOURCC_rle_:
10784         case FOURCC_WRLE:
10785         {
10786             gst_caps_set_simple (entry->caps,
10787                 "depth", G_TYPE_INT, QT_UINT16 (stsd_entry_data + offset + 66),
10788                 NULL);
10789           break;
10790         }
10791         case FOURCC_XiTh:
10792         {
10793           GNode *xith, *xdxt;
10794 
10795           GST_DEBUG_OBJECT (qtdemux, "found XiTh");
10796             xith = qtdemux_tree_get_child_by_index (stsd, stsd_index);
10797           if (!xith)
10798             break;
10799 
10800           xdxt = qtdemux_tree_get_child_by_type (xith, FOURCC_XdxT);
10801           if (!xdxt)
10802             break;
10803 
10804           GST_DEBUG_OBJECT (qtdemux, "found XdxT node");
10805           /* collect the headers and store them in a stream list so that we can
10806            * send them out first */
10807           qtdemux_parse_theora_extension (qtdemux, stream, xdxt);
10808           break;
10809         }
10810         case FOURCC_ovc1:
10811         {
10812           GNode *ovc1;
10813           guint8 *ovc1_data;
10814           guint ovc1_len;
10815           GstBuffer *buf;
10816 
10817           GST_DEBUG_OBJECT (qtdemux, "parse ovc1 header");
10818             ovc1 = qtdemux_tree_get_child_by_index (stsd, stsd_index);
10819           if (!ovc1)
10820             break;
10821           ovc1_data = ovc1->data;
10822           ovc1_len = QT_UINT32 (ovc1_data);
10823           if (ovc1_len <= 198) {
10824             GST_WARNING_OBJECT (qtdemux, "Too small ovc1 header, skipping");
10825             break;
10826           }
10827           buf = gst_buffer_new_and_alloc (ovc1_len - 198);
10828           gst_buffer_fill (buf, 0, ovc1_data + 198, ovc1_len - 198);
10829             gst_caps_set_simple (entry->caps,
10830               "codec_data", GST_TYPE_BUFFER, buf, NULL);
10831           gst_buffer_unref (buf);
10832           break;
10833         }
10834           case FOURCC_vc_1:
10835           {
10836             gint len = QT_UINT32 (stsd_entry_data) - 0x56;
10837             const guint8 *vc1_data = stsd_entry_data + 0x56;
10838 
10839             /* find dvc1 */
10840             while (len >= 8) {
10841               gint size;
10842 
10843               if (QT_UINT32 (vc1_data) <= len)
10844                 size = QT_UINT32 (vc1_data) - 8;
10845               else
10846                 size = len - 8;
10847 
10848               if (size < 1)
10849                 /* No real data, so break out */
10850                 break;
10851 
10852               switch (QT_FOURCC (vc1_data + 0x4)) {
10853                 case GST_MAKE_FOURCC ('d', 'v', 'c', '1'):
10854                 {
10855                   GstBuffer *buf;
10856 
10857                   GST_DEBUG_OBJECT (qtdemux, "found dvc1 codec_data in stsd");
10858                   buf = gst_buffer_new_and_alloc (size);
10859                   gst_buffer_fill (buf, 0, vc1_data + 8, size);
10860                   gst_caps_set_simple (entry->caps,
10861                       "codec_data", GST_TYPE_BUFFER, buf, NULL);
10862                   gst_buffer_unref (buf);
10863                   break;
10864                 }
10865         default:
10866           break;
10867       }
10868               len -= size + 8;
10869               vc1_data += size + 8;
10870     }
10871             break;
10872           }
10873           default:
10874             break;
10875         }
10876       }
10877 
10878     GST_INFO_OBJECT (qtdemux,
10879         "type %" GST_FOURCC_FORMAT " caps %" GST_PTR_FORMAT,
10880           GST_FOURCC_ARGS (fourcc), entry->caps);
10881 
10882   } else if (stream->subtype == FOURCC_soun) {
10883       GNode *wave;
10884     int version, samplesize;
10885     guint16 compression_id;
10886     gboolean amrwb = FALSE;
10887 
10888       offset = 16;
10889     /* sample description entry (16) + sound sample description v0 (20) */
10890     if (len < 36)
10891       goto corrupt_file;
10892 
10893       version = QT_UINT32 (stsd_entry_data + offset);
10894       entry->n_channels = QT_UINT16 (stsd_entry_data + offset + 8);
10895       samplesize = QT_UINT16 (stsd_entry_data + offset + 10);
10896       compression_id = QT_UINT16 (stsd_entry_data + offset + 12);
10897       entry->rate = QT_FP32 (stsd_entry_data + offset + 16);
10898 
10899     GST_LOG_OBJECT (qtdemux, "version/rev:      %08x", version);
10900     GST_LOG_OBJECT (qtdemux, "vendor:           %08x",
10901           QT_UINT32 (stsd_entry_data + offset + 4));
10902       GST_LOG_OBJECT (qtdemux, "n_channels:       %d", entry->n_channels);
10903     GST_LOG_OBJECT (qtdemux, "sample_size:      %d", samplesize);
10904     GST_LOG_OBJECT (qtdemux, "compression_id:   %d", compression_id);
10905     GST_LOG_OBJECT (qtdemux, "packet size:      %d",
10906           QT_UINT16 (stsd_entry_data + offset + 14));
10907       GST_LOG_OBJECT (qtdemux, "sample rate:      %g", entry->rate);
10908 
10909     if (compression_id == 0xfffe)
10910         entry->sampled = TRUE;
10911 
10912     /* first assume uncompressed audio */
10913       entry->bytes_per_sample = samplesize / 8;
10914       entry->samples_per_frame = entry->n_channels;
10915       entry->bytes_per_frame = entry->n_channels * entry->bytes_per_sample;
10916       entry->samples_per_packet = entry->samples_per_frame;
10917       entry->bytes_per_packet = entry->bytes_per_sample;
10918 
10919       offset = 36;
10920     switch (fourcc) {
10921         /* Yes, these have to be hard-coded */
10922       case FOURCC_MAC6:
10923       {
10924           entry->samples_per_packet = 6;
10925           entry->bytes_per_packet = 1;
10926           entry->bytes_per_frame = 1 * entry->n_channels;
10927           entry->bytes_per_sample = 1;
10928           entry->samples_per_frame = 6 * entry->n_channels;
10929         break;
10930       }
10931       case FOURCC_MAC3:
10932       {
10933           entry->samples_per_packet = 3;
10934           entry->bytes_per_packet = 1;
10935           entry->bytes_per_frame = 1 * entry->n_channels;
10936           entry->bytes_per_sample = 1;
10937           entry->samples_per_frame = 3 * entry->n_channels;
10938         break;
10939       }
10940       case FOURCC_ima4:
10941       {
10942           entry->samples_per_packet = 64;
10943           entry->bytes_per_packet = 34;
10944           entry->bytes_per_frame = 34 * entry->n_channels;
10945           entry->bytes_per_sample = 2;
10946           entry->samples_per_frame = 64 * entry->n_channels;
10947         break;
10948       }
10949       case FOURCC_ulaw:
10950       case FOURCC_alaw:
10951       {
10952           entry->samples_per_packet = 1;
10953           entry->bytes_per_packet = 1;
10954           entry->bytes_per_frame = 1 * entry->n_channels;
10955           entry->bytes_per_sample = 1;
10956           entry->samples_per_frame = 1 * entry->n_channels;
10957         break;
10958       }
10959       case FOURCC_agsm:
10960       {
10961           entry->samples_per_packet = 160;
10962           entry->bytes_per_packet = 33;
10963           entry->bytes_per_frame = 33 * entry->n_channels;
10964           entry->bytes_per_sample = 2;
10965           entry->samples_per_frame = 160 * entry->n_channels;
10966         break;
10967       }
10968       default:
10969         break;
10970     }
10971 
10972     if (version == 0x00010000) {
10973       /* sample description entry (16) + sound sample description v1 (20+16) */
10974       if (len < 52)
10975         goto corrupt_file;
10976 
10977       switch (fourcc) {
10978         case FOURCC_twos:
10979         case FOURCC_sowt:
10980         case FOURCC_raw_:
10981           case FOURCC_lpcm:
10982           break;
10983         default:
10984         {
10985           /* only parse extra decoding config for non-pcm audio */
10986             entry->samples_per_packet = QT_UINT32 (stsd_entry_data + offset);
10987             entry->bytes_per_packet = QT_UINT32 (stsd_entry_data + offset + 4);
10988             entry->bytes_per_frame = QT_UINT32 (stsd_entry_data + offset + 8);
10989             entry->bytes_per_sample = QT_UINT32 (stsd_entry_data + offset + 12);
10990 
10991           GST_LOG_OBJECT (qtdemux, "samples/packet:   %d",
10992                 entry->samples_per_packet);
10993           GST_LOG_OBJECT (qtdemux, "bytes/packet:     %d",
10994                 entry->bytes_per_packet);
10995           GST_LOG_OBJECT (qtdemux, "bytes/frame:      %d",
10996                 entry->bytes_per_frame);
10997           GST_LOG_OBJECT (qtdemux, "bytes/sample:     %d",
10998                 entry->bytes_per_sample);
10999 
11000             if (!entry->sampled && entry->bytes_per_packet) {
11001               entry->samples_per_frame = (entry->bytes_per_frame /
11002                   entry->bytes_per_packet) * entry->samples_per_packet;
11003             GST_LOG_OBJECT (qtdemux, "samples/frame:    %d",
11004                   entry->samples_per_frame);
11005           }
11006           break;
11007         }
11008       }
11009     } else if (version == 0x00020000) {
11010       union
11011       {
11012         gdouble fp;
11013         guint64 val;
11014       } qtfp;
11015 
11016       /* sample description entry (16) + sound sample description v2 (56) */
11017       if (len < 72)
11018         goto corrupt_file;
11019 
11020         qtfp.val = QT_UINT64 (stsd_entry_data + offset + 4);
11021         entry->rate = qtfp.fp;
11022         entry->n_channels = QT_UINT32 (stsd_entry_data + offset + 12);
11023 
11024       GST_LOG_OBJECT (qtdemux, "Sound sample description Version 2");
11025         GST_LOG_OBJECT (qtdemux, "sample rate:        %g", entry->rate);
11026         GST_LOG_OBJECT (qtdemux, "n_channels:         %d", entry->n_channels);
11027       GST_LOG_OBJECT (qtdemux, "bits/channel:       %d",
11028             QT_UINT32 (stsd_entry_data + offset + 20));
11029       GST_LOG_OBJECT (qtdemux, "format flags:       %X",
11030             QT_UINT32 (stsd_entry_data + offset + 24));
11031       GST_LOG_OBJECT (qtdemux, "bytes/packet:       %d",
11032             QT_UINT32 (stsd_entry_data + offset + 28));
11033       GST_LOG_OBJECT (qtdemux, "LPCM frames/packet: %d",
11034             QT_UINT32 (stsd_entry_data + offset + 32));
11035     } else if (version != 0x00000) {
11036         GST_WARNING_OBJECT (qtdemux, "unknown audio STSD version %08x",
11037             version);
11038     }
11039 
11040       if (entry->caps)
11041         gst_caps_unref (entry->caps);
11042 
11043       entry->caps = qtdemux_audio_caps (qtdemux, stream, entry, fourcc,
11044           stsd_entry_data + 32, len - 16, &codec);
11045 
11046     switch (fourcc) {
11047       case FOURCC_in24:
11048       {
11049         GNode *enda;
11050         GNode *in24;
11051 
11052         in24 = qtdemux_tree_get_child_by_type (stsd, FOURCC_in24);
11053 
11054         enda = qtdemux_tree_get_child_by_type (in24, FOURCC_enda);
11055         if (!enda) {
11056           wave = qtdemux_tree_get_child_by_type (in24, FOURCC_wave);
11057           if (wave)
11058             enda = qtdemux_tree_get_child_by_type (wave, FOURCC_enda);
11059         }
11060         if (enda) {
11061           int enda_value = QT_UINT16 ((guint8 *) enda->data + 8);
11062             gst_caps_set_simple (entry->caps,
11063                 "format", G_TYPE_STRING, (enda_value) ? "S24LE" : "S24BE",
11064                 NULL);
11065         }
11066         break;
11067       }
11068       case FOURCC_owma:
11069       {
11070         const guint8 *owma_data;
11071         const gchar *codec_name = NULL;
11072         guint owma_len;
11073         GstBuffer *buf;
11074         gint version = 1;
11075         /* from http://msdn.microsoft.com/en-us/library/dd757720(VS.85).aspx */
11076         /* FIXME this should also be gst_riff_strf_auds,
11077          * but the latter one is actually missing bits-per-sample :( */
11078         typedef struct
11079         {
11080           gint16 wFormatTag;
11081           gint16 nChannels;
11082           gint32 nSamplesPerSec;
11083           gint32 nAvgBytesPerSec;
11084           gint16 nBlockAlign;
11085           gint16 wBitsPerSample;
11086           gint16 cbSize;
11087         } WAVEFORMATEX;
11088         WAVEFORMATEX *wfex;
11089 
11090         GST_DEBUG_OBJECT (qtdemux, "parse owma");
11091           owma_data = stsd_entry_data;
11092         owma_len = QT_UINT32 (owma_data);
11093         if (owma_len <= 54) {
11094           GST_WARNING_OBJECT (qtdemux, "Too small owma header, skipping");
11095           break;
11096         }
11097         wfex = (WAVEFORMATEX *) (owma_data + 36);
11098         buf = gst_buffer_new_and_alloc (owma_len - 54);
11099         gst_buffer_fill (buf, 0, owma_data + 54, owma_len - 54);
11100         if (wfex->wFormatTag == 0x0161) {
11101           codec_name = "Windows Media Audio";
11102           version = 2;
11103         } else if (wfex->wFormatTag == 0x0162) {
11104           codec_name = "Windows Media Audio 9 Pro";
11105           version = 3;
11106         } else if (wfex->wFormatTag == 0x0163) {
11107           codec_name = "Windows Media Audio 9 Lossless";
11108           /* is that correct? gstffmpegcodecmap.c is missing it, but
11109            * fluendo codec seems to support it */
11110           version = 4;
11111         }
11112 
11113           gst_caps_set_simple (entry->caps,
11114             "codec_data", GST_TYPE_BUFFER, buf,
11115             "wmaversion", G_TYPE_INT, version,
11116               "block_align", G_TYPE_INT,
11117               GST_READ_UINT16_LE (&wfex->nBlockAlign), "bitrate", G_TYPE_INT,
11118               GST_READ_UINT32_LE (&wfex->nAvgBytesPerSec), "width", G_TYPE_INT,
11119               GST_READ_UINT16_LE (&wfex->wBitsPerSample), "depth", G_TYPE_INT,
11120               GST_READ_UINT16_LE (&wfex->wBitsPerSample), NULL);
11121         gst_buffer_unref (buf);
11122 
11123         if (codec_name) {
11124           g_free (codec);
11125           codec = g_strdup (codec_name);
11126         }
11127         break;
11128       }
11129         case FOURCC_wma_:
11130         {
11131           gint len = QT_UINT32 (stsd_entry_data) - offset;
11132           const guint8 *wfex_data = stsd_entry_data + offset;
11133           const gchar *codec_name = NULL;
11134           gint version = 1;
11135           /* from http://msdn.microsoft.com/en-us/library/dd757720(VS.85).aspx */
11136           /* FIXME this should also be gst_riff_strf_auds,
11137            * but the latter one is actually missing bits-per-sample :( */
11138           typedef struct
11139           {
11140             gint16 wFormatTag;
11141             gint16 nChannels;
11142             gint32 nSamplesPerSec;
11143             gint32 nAvgBytesPerSec;
11144             gint16 nBlockAlign;
11145             gint16 wBitsPerSample;
11146             gint16 cbSize;
11147           } WAVEFORMATEX;
11148           WAVEFORMATEX wfex;
11149 
11150           /* FIXME: unify with similar wavformatex parsing code above */
11151           GST_DEBUG_OBJECT (qtdemux, "parse wma, looking for wfex");
11152 
11153           /* find wfex */
11154           while (len >= 8) {
11155             gint size;
11156 
11157             if (QT_UINT32 (wfex_data) <= len)
11158               size = QT_UINT32 (wfex_data) - 8;
11159             else
11160               size = len - 8;
11161 
11162             if (size < 1)
11163               /* No real data, so break out */
11164               break;
11165 
11166             switch (QT_FOURCC (wfex_data + 4)) {
11167               case GST_MAKE_FOURCC ('w', 'f', 'e', 'x'):
11168               {
11169                 GST_DEBUG_OBJECT (qtdemux, "found wfex in stsd");
11170 
11171                 if (size < 8 + 18)
11172                   break;
11173 
11174                 wfex.wFormatTag = GST_READ_UINT16_LE (wfex_data + 8 + 0);
11175                 wfex.nChannels = GST_READ_UINT16_LE (wfex_data + 8 + 2);
11176                 wfex.nSamplesPerSec = GST_READ_UINT32_LE (wfex_data + 8 + 4);
11177                 wfex.nAvgBytesPerSec = GST_READ_UINT32_LE (wfex_data + 8 + 8);
11178                 wfex.nBlockAlign = GST_READ_UINT16_LE (wfex_data + 8 + 12);
11179                 wfex.wBitsPerSample = GST_READ_UINT16_LE (wfex_data + 8 + 14);
11180                 wfex.cbSize = GST_READ_UINT16_LE (wfex_data + 8 + 16);
11181 
11182                 GST_LOG_OBJECT (qtdemux, "Found wfex box in stsd:");
11183                 GST_LOG_OBJECT (qtdemux, "FormatTag = 0x%04x, Channels = %u, "
11184                     "SamplesPerSec = %u, AvgBytesPerSec = %u, BlockAlign = %u, "
11185                     "BitsPerSample = %u, Size = %u", wfex.wFormatTag,
11186                     wfex.nChannels, wfex.nSamplesPerSec, wfex.nAvgBytesPerSec,
11187                     wfex.nBlockAlign, wfex.wBitsPerSample, wfex.cbSize);
11188 
11189                 if (wfex.wFormatTag == 0x0161) {
11190                   codec_name = "Windows Media Audio";
11191                   version = 2;
11192                 } else if (wfex.wFormatTag == 0x0162) {
11193                   codec_name = "Windows Media Audio 9 Pro";
11194                   version = 3;
11195                 } else if (wfex.wFormatTag == 0x0163) {
11196                   codec_name = "Windows Media Audio 9 Lossless";
11197                   /* is that correct? gstffmpegcodecmap.c is missing it, but
11198                    * fluendo codec seems to support it */
11199                   version = 4;
11200                 }
11201 
11202                 gst_caps_set_simple (entry->caps,
11203                     "wmaversion", G_TYPE_INT, version,
11204                     "block_align", G_TYPE_INT, wfex.nBlockAlign,
11205                     "bitrate", G_TYPE_INT, wfex.nAvgBytesPerSec,
11206                     "width", G_TYPE_INT, wfex.wBitsPerSample,
11207                     "depth", G_TYPE_INT, wfex.wBitsPerSample, NULL);
11208 
11209                 if (size > wfex.cbSize) {
11210                   GstBuffer *buf;
11211 
11212                   buf = gst_buffer_new_and_alloc (size - wfex.cbSize);
11213                   gst_buffer_fill (buf, 0, wfex_data + 8 + wfex.cbSize,
11214                       size - wfex.cbSize);
11215                   gst_caps_set_simple (entry->caps,
11216                       "codec_data", GST_TYPE_BUFFER, buf, NULL);
11217                   gst_buffer_unref (buf);
11218                 } else {
11219                   GST_WARNING_OBJECT (qtdemux, "no codec data");
11220                 }
11221 
11222                 if (codec_name) {
11223                   g_free (codec);
11224                   codec = g_strdup (codec_name);
11225                 }
11226                 break;
11227               }
11228       default:
11229         break;
11230     }
11231             len -= size + 8;
11232             wfex_data += size + 8;
11233           }
11234           break;
11235         }
11236 #ifndef GSTREAMER_LITE
11237         case FOURCC_opus:
11238         {
11239           const guint8 *opus_data;
11240           guint8 *channel_mapping = NULL;
11241           guint32 rate;
11242           guint8 channels;
11243           guint8 channel_mapping_family;
11244           guint8 stream_count;
11245           guint8 coupled_count;
11246           guint8 i;
11247 
11248           opus_data = stsd_entry_data;
11249 
11250           channels = GST_READ_UINT8 (opus_data + 45);
11251           rate = GST_READ_UINT32_LE (opus_data + 48);
11252           channel_mapping_family = GST_READ_UINT8 (opus_data + 54);
11253           stream_count = GST_READ_UINT8 (opus_data + 55);
11254           coupled_count = GST_READ_UINT8 (opus_data + 56);
11255 
11256           if (channels > 0) {
11257             channel_mapping = g_malloc (channels * sizeof (guint8));
11258             for (i = 0; i < channels; i++)
11259               channel_mapping[i] = GST_READ_UINT8 (opus_data + i + 57);
11260           }
11261 
11262           entry->caps = gst_codec_utils_opus_create_caps (rate, channels,
11263               channel_mapping_family, stream_count, coupled_count,
11264               channel_mapping);
11265           break;
11266         }
11267 #endif // GSTREAMER_LITE
11268         default:
11269           break;
11270       }
11271 
11272     if (codec) {
11273       GstStructure *s;
11274       gint bitrate = 0;
11275 
11276         gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
11277           GST_TAG_AUDIO_CODEC, codec, NULL);
11278       g_free (codec);
11279       codec = NULL;
11280 
11281       /* some bitrate info may have ended up in caps */
11282         s = gst_caps_get_structure (entry->caps, 0);
11283       gst_structure_get_int (s, "bitrate", &bitrate);
11284       if (bitrate > 0)
11285           gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
11286               GST_TAG_BITRATE, bitrate, NULL);
11287     }
11288 
11289       mp4a = qtdemux_tree_get_child_by_index (stsd, stsd_index);
11290       if (!stream->protected) {
11291       } else {
11292         if (QTDEMUX_TREE_NODE_FOURCC (mp4v) != FOURCC_encv) {
11293           mp4v = NULL;
11294         }
11295       }
11296       if (stream->protected && fourcc == FOURCC_mp4a) {
11297         if (QTDEMUX_TREE_NODE_FOURCC (mp4a) != FOURCC_enca) {
11298           mp4a = NULL;
11299         }
11300       } else {
11301         if (QTDEMUX_TREE_NODE_FOURCC (mp4a) != FOURCC_mp4a) {
11302           mp4a = NULL;
11303         }
11304       }
11305 
11306     wave = NULL;
11307     esds = NULL;
11308     if (mp4a) {
11309       wave = qtdemux_tree_get_child_by_type (mp4a, FOURCC_wave);
11310       if (wave)
11311         esds = qtdemux_tree_get_child_by_type (wave, FOURCC_esds);
11312       if (!esds)
11313         esds = qtdemux_tree_get_child_by_type (mp4a, FOURCC_esds);
11314     }
11315 
11316 
11317     /* If the fourcc's bottom 16 bits gives 'sm', then the top
11318        16 bits is a byte-swapped wave-style codec identifier,
11319        and we can find a WAVE header internally to a 'wave' atom here.
11320        This can more clearly be thought of as 'ms' as the top 16 bits, and a
11321        codec id as the bottom 16 bits - but byte-swapped to store in QT (which
11322        is big-endian).
11323      */
11324     if ((fourcc & 0xffff) == (('s' << 8) | 'm')) {
11325       if (len < offset + 20) {
11326         GST_WARNING_OBJECT (qtdemux, "No wave atom in MS-style audio");
11327       } else {
11328           guint32 datalen = QT_UINT32 (stsd_entry_data + offset + 16);
11329           const guint8 *data = stsd_entry_data + offset + 16;
11330         GNode *wavenode;
11331         GNode *waveheadernode;
11332 
11333         wavenode = g_node_new ((guint8 *) data);
11334         if (qtdemux_parse_node (qtdemux, wavenode, data, datalen)) {
11335           const guint8 *waveheader;
11336           guint32 headerlen;
11337 
11338           waveheadernode = qtdemux_tree_get_child_by_type (wavenode, fourcc);
11339           if (waveheadernode) {
11340             waveheader = (const guint8 *) waveheadernode->data;
11341             headerlen = QT_UINT32 (waveheader);
11342 
11343             if (headerlen > 8) {
11344               gst_riff_strf_auds *header = NULL;
11345               GstBuffer *headerbuf;
11346               GstBuffer *extra;
11347 
11348               waveheader += 8;
11349               headerlen -= 8;
11350 
11351               headerbuf = gst_buffer_new_and_alloc (headerlen);
11352               gst_buffer_fill (headerbuf, 0, waveheader, headerlen);
11353 
11354               if (gst_riff_parse_strf_auds (GST_ELEMENT_CAST (qtdemux),
11355                       headerbuf, &header, &extra)) {
11356                   gst_caps_unref (entry->caps);
11357                 /* FIXME: Need to do something with the channel reorder map */
11358                   entry->caps =
11359                       gst_riff_create_audio_caps (header->format, NULL, header,
11360                       extra, NULL, NULL, NULL);
11361 
11362                 if (extra)
11363                   gst_buffer_unref (extra);
11364                 g_free (header);
11365               }
11366             }
11367           } else
11368             GST_DEBUG ("Didn't find waveheadernode for this codec");
11369         }
11370         g_node_destroy (wavenode);
11371       }
11372     } else if (esds) {
11373 #ifdef GSTREAMER_LITE
11374         if (!gst_qtdemux_handle_esds (qtdemux, stream, entry, esds,
11375                                       stream->stream_tags))
11376             goto corrupt_file;
11377 #else
11378         gst_qtdemux_handle_esds (qtdemux, stream, entry, esds,
11379             stream->stream_tags);
11380 #endif // GSTREAMER_LITE
11381     } else {
11382       switch (fourcc) {
11383 #if 0
11384           /* FIXME: what is in the chunk? */
11385         case FOURCC_QDMC:
11386         {
11387           gint len = QT_UINT32 (stsd_data);
11388 
11389           /* seems to be always = 116 = 0x74 */
11390           break;
11391         }
11392 #endif
11393         case FOURCC_QDM2:
11394         {
11395             gint len = QT_UINT32 (stsd_entry_data);
11396 
11397             if (len > 0x3C) {
11398               GstBuffer *buf = gst_buffer_new_and_alloc (len - 0x3C);
11399 
11400               gst_buffer_fill (buf, 0, stsd_entry_data + 0x3C, len - 0x3C);
11401               gst_caps_set_simple (entry->caps,
11402                 "codec_data", GST_TYPE_BUFFER, buf, NULL);
11403             gst_buffer_unref (buf);
11404           }
11405             gst_caps_set_simple (entry->caps,
11406               "samplesize", G_TYPE_INT, samplesize, NULL);
11407           break;
11408         }
11409         case FOURCC_alac:
11410         {
11411           GNode *alac, *wave = NULL;
11412 
11413           /* apparently, m4a has this atom appended directly in the stsd entry,
11414            * while mov has it in a wave atom */
11415           alac = qtdemux_tree_get_child_by_type (stsd, FOURCC_alac);
11416           if (alac) {
11417             /* alac now refers to stsd entry atom */
11418             wave = qtdemux_tree_get_child_by_type (alac, FOURCC_wave);
11419             if (wave)
11420               alac = qtdemux_tree_get_child_by_type (wave, FOURCC_alac);
11421             else
11422               alac = qtdemux_tree_get_child_by_type (alac, FOURCC_alac);
11423           }
11424           if (alac) {
11425             const guint8 *alac_data = alac->data;
11426             gint len = QT_UINT32 (alac->data);
11427             GstBuffer *buf;
11428 
11429             if (len < 36) {
11430               GST_DEBUG_OBJECT (qtdemux,
11431                   "discarding alac atom with unexpected len %d", len);
11432             } else {
11433               /* codec-data contains alac atom size and prefix,
11434                * ffmpeg likes it that way, not quite gst-ish though ...*/
11435               buf = gst_buffer_new_and_alloc (len);
11436               gst_buffer_fill (buf, 0, alac->data, len);
11437                 gst_caps_set_simple (entry->caps,
11438                   "codec_data", GST_TYPE_BUFFER, buf, NULL);
11439               gst_buffer_unref (buf);
11440 
11441                 entry->bytes_per_frame = QT_UINT32 (alac_data + 12);
11442                 entry->n_channels = QT_UINT8 (alac_data + 21);
11443                 entry->rate = QT_UINT32 (alac_data + 32);
11444             }
11445           }
11446             gst_caps_set_simple (entry->caps,
11447               "samplesize", G_TYPE_INT, samplesize, NULL);
11448           break;
11449         }
11450           case FOURCC_fLaC:
11451           {
11452             /* The codingname of the sample entry is 'fLaC' */
11453             GNode *flac = qtdemux_tree_get_child_by_type (stsd, FOURCC_fLaC);
11454 
11455             if (flac) {
11456               /* The 'dfLa' box is added to the sample entry to convey
11457                  initializing information for the decoder. */
11458               const GNode *dfla =
11459                   qtdemux_tree_get_child_by_type (flac, FOURCC_dfLa);
11460 
11461               if (dfla) {
11462                 const guint32 len = QT_UINT32 (dfla->data);
11463 
11464                 /* Must contain at least dfLa box header (12),
11465                  * METADATA_BLOCK_HEADER (4), METADATA_BLOCK_STREAMINFO (34) */
11466                 if (len < 50) {
11467                   GST_DEBUG_OBJECT (qtdemux,
11468                       "discarding dfla atom with unexpected len %d", len);
11469                 } else {
11470                   /* skip dfLa header to get the METADATA_BLOCKs */
11471                   const guint8 *metadata_blocks = (guint8 *) dfla->data + 12;
11472                   const guint32 metadata_blocks_len = len - 12;
11473 
11474                   gchar *stream_marker = g_strdup ("fLaC");
11475                   GstBuffer *block = gst_buffer_new_wrapped (stream_marker,
11476                       strlen (stream_marker));
11477 
11478                   guint32 index = 0;
11479                   guint32 remainder = 0;
11480                   guint32 block_size = 0;
11481                   gboolean is_last = FALSE;
11482 
11483                   GValue array = G_VALUE_INIT;
11484                   GValue value = G_VALUE_INIT;
11485 
11486                   g_value_init (&array, GST_TYPE_ARRAY);
11487                   g_value_init (&value, GST_TYPE_BUFFER);
11488 
11489                   gst_value_set_buffer (&value, block);
11490                   gst_value_array_append_value (&array, &value);
11491                   g_value_reset (&value);
11492 
11493                   gst_buffer_unref (block);
11494 
11495                   /* check there's at least one METADATA_BLOCK_HEADER's worth
11496                    * of data, and we haven't already finished parsing */
11497                   while (!is_last && ((index + 3) < metadata_blocks_len)) {
11498                     remainder = metadata_blocks_len - index;
11499 
11500                     /* add the METADATA_BLOCK_HEADER size to the signalled size */
11501                     block_size = 4 +
11502                         (metadata_blocks[index + 1] << 16) +
11503                         (metadata_blocks[index + 2] << 8) +
11504                         metadata_blocks[index + 3];
11505 
11506                     /* be careful not to read off end of box */
11507                     if (block_size > remainder) {
11508                       break;
11509                     }
11510 
11511                     is_last = metadata_blocks[index] >> 7;
11512 
11513                     block = gst_buffer_new_and_alloc (block_size);
11514 
11515                     gst_buffer_fill (block, 0, &metadata_blocks[index],
11516                         block_size);
11517 
11518                     gst_value_set_buffer (&value, block);
11519                     gst_value_array_append_value (&array, &value);
11520                     g_value_reset (&value);
11521 
11522                     gst_buffer_unref (block);
11523 
11524                     index += block_size;
11525                   }
11526 
11527                   /* only append the metadata if we successfully read all of it */
11528                   if (is_last) {
11529                     gst_structure_set_value (gst_caps_get_structure (CUR_STREAM
11530                             (stream)->caps, 0), "streamheader", &array);
11531                   } else {
11532                     GST_WARNING_OBJECT (qtdemux,
11533                         "discarding all METADATA_BLOCKs due to invalid "
11534                         "block_size %d at idx %d, rem %d", block_size, index,
11535                         remainder);
11536                   }
11537 
11538                   g_value_unset (&value);
11539                   g_value_unset (&array);
11540 
11541                   /* The sample rate obtained from the stsd may not be accurate
11542                    * since it cannot represent rates greater than 65535Hz, so
11543                    * override that value with the sample rate from the
11544                    * METADATA_BLOCK_STREAMINFO block */
11545                   CUR_STREAM (stream)->rate =
11546                       (QT_UINT32 (metadata_blocks + 14) >> 12) & 0xFFFFF;
11547                 }
11548               }
11549             }
11550             break;
11551           }
11552         case FOURCC_sawb:
11553           /* Fallthrough! */
11554           amrwb = TRUE;
11555         case FOURCC_samr:
11556         {
11557             gint len = QT_UINT32 (stsd_entry_data);
11558 
11559             if (len > 0x24) {
11560               GstBuffer *buf = gst_buffer_new_and_alloc (len - 0x24);
11561             guint bitrate;
11562 
11563               gst_buffer_fill (buf, 0, stsd_entry_data + 0x24, len - 0x24);
11564 
11565             /* If we have enough data, let's try to get the 'damr' atom. See
11566              * the 3GPP container spec (26.244) for more details. */
11567             if ((len - 0x34) > 8 &&
11568                 (bitrate = qtdemux_parse_amr_bitrate (buf, amrwb))) {
11569                 gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
11570                   GST_TAG_MAXIMUM_BITRATE, bitrate, NULL);
11571             }
11572 
11573               gst_caps_set_simple (entry->caps,
11574                 "codec_data", GST_TYPE_BUFFER, buf, NULL);
11575             gst_buffer_unref (buf);
11576           }
11577           break;
11578         }
11579           case FOURCC_mp4a:
11580           {
11581             /* mp4a atom withtout ESDS; Attempt to build codec data from atom */
11582             gint len = QT_UINT32 (stsd_entry_data);
11583 
11584             if (len >= 34) {
11585               guint16 sound_version = QT_UINT16 (stsd_entry_data + 16);
11586 
11587               if (sound_version == 1) {
11588                 guint16 channels = QT_UINT16 (stsd_entry_data + 24);
11589                 guint32 time_scale = QT_UINT32 (stsd_entry_data + 30);
11590                 guint8 codec_data[2];
11591                 GstBuffer *buf;
11592                 gint profile = 2;       /* FIXME: Can this be determined somehow? There doesn't seem to be anything in mp4a atom that specifis compression */
11593 
11594                 gint sample_rate_index =
11595                     gst_codec_utils_aac_get_index_from_sample_rate (time_scale);
11596 
11597                 /* build AAC codec data */
11598                 codec_data[0] = profile << 3;
11599                 codec_data[0] |= ((sample_rate_index >> 1) & 0x7);
11600                 codec_data[1] = (sample_rate_index & 0x01) << 7;
11601                 codec_data[1] |= (channels & 0xF) << 3;
11602 
11603                 buf = gst_buffer_new_and_alloc (2);
11604                 gst_buffer_fill (buf, 0, codec_data, 2);
11605                 gst_caps_set_simple (entry->caps,
11606                     "codec_data", GST_TYPE_BUFFER, buf, NULL);
11607                 gst_buffer_unref (buf);
11608               }
11609             }
11610             break;
11611           }
11612           case FOURCC_lpcm:
11613             /* Fully handled elsewhere */
11614             break;
11615         default:
11616           GST_INFO_OBJECT (qtdemux,
11617               "unhandled type %" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (fourcc));
11618           break;
11619       }
11620     }
11621     GST_INFO_OBJECT (qtdemux,
11622         "type %" GST_FOURCC_FORMAT " caps %" GST_PTR_FORMAT,
11623           GST_FOURCC_ARGS (fourcc), entry->caps);
11624 
11625   } else if (stream->subtype == FOURCC_strm) {
11626     if (fourcc == FOURCC_rtsp) {
11627       stream->redirect_uri = qtdemux_get_rtsp_uri_from_hndl (qtdemux, minf);
11628     } else {
11629       GST_INFO_OBJECT (qtdemux, "unhandled stream type %" GST_FOURCC_FORMAT,
11630           GST_FOURCC_ARGS (fourcc));
11631       goto unknown_stream;
11632     }
11633       entry->sampled = TRUE;
11634   } else if (stream->subtype == FOURCC_subp || stream->subtype == FOURCC_text
11635         || stream->subtype == FOURCC_sbtl || stream->subtype == FOURCC_subt) {
11636 
11637       entry->sampled = TRUE;
11638       entry->sparse = TRUE;
11639 
11640       entry->caps =
11641           qtdemux_sub_caps (qtdemux, stream, entry, fourcc, stsd_entry_data,
11642           &codec);
11643     if (codec) {
11644         gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
11645           GST_TAG_SUBTITLE_CODEC, codec, NULL);
11646       g_free (codec);
11647       codec = NULL;
11648     }
11649 
11650     /* hunt for sort-of codec data */
11651     switch (fourcc) {
11652       case FOURCC_mp4s:
11653       {
11654         GNode *mp4s = NULL;
11655         GNode *esds = NULL;
11656 
11657         /* look for palette in a stsd->mp4s->esds sub-atom */
11658         mp4s = qtdemux_tree_get_child_by_type (stsd, FOURCC_mp4s);
11659         if (mp4s)
11660           esds = qtdemux_tree_get_child_by_type (mp4s, FOURCC_esds);
11661         if (esds == NULL) {
11662           /* Invalid STSD */
11663           GST_LOG_OBJECT (qtdemux, "Skipping invalid stsd: no esds child");
11664           break;
11665           }
11666 
11667           gst_qtdemux_handle_esds (qtdemux, stream, entry, esds,
11668               stream->stream_tags);
11669         break;
11670       }
11671       default:
11672         GST_INFO_OBJECT (qtdemux,
11673             "unhandled type %" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (fourcc));
11674         break;
11675     }
11676     GST_INFO_OBJECT (qtdemux,
11677         "type %" GST_FOURCC_FORMAT " caps %" GST_PTR_FORMAT,
11678           GST_FOURCC_ARGS (fourcc), entry->caps);
11679   } else {
11680     /* everything in 1 sample */
11681       entry->sampled = TRUE;
11682 
11683       entry->caps =
11684           qtdemux_generic_caps (qtdemux, stream, entry, fourcc, stsd_entry_data,
11685           &codec);
11686 
11687       if (entry->caps == NULL)
11688     goto unknown_stream;
11689 
11690     if (codec) {
11691         gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
11692           GST_TAG_SUBTITLE_CODEC, codec, NULL);
11693       g_free (codec);
11694       codec = NULL;
11695   }
11696   }
11697 
11698   /* promote to sampled format */
11699     if (entry->fourcc == FOURCC_samr) {
11700     /* force mono 8000 Hz for AMR */
11701       entry->sampled = TRUE;
11702       entry->n_channels = 1;
11703       entry->rate = 8000;
11704     } else if (entry->fourcc == FOURCC_sawb) {
11705     /* force mono 16000 Hz for AMR-WB */
11706       entry->sampled = TRUE;
11707       entry->n_channels = 1;
11708       entry->rate = 16000;
11709     } else if (entry->fourcc == FOURCC_mp4a) {
11710       entry->sampled = TRUE;
11711   }
11712 
11713 
11714     stsd_entry_data += len;
11715     remaining_stsd_len -= len;
11716 
11717   }
11718 
11719   /* collect sample information */
11720   if (!qtdemux_stbl_init (qtdemux, stream, stbl))
11721     goto samples_failed;
11722 
11723   if (qtdemux->fragmented) {
11724     guint64 offset;
11725 
11726     /* need all moov samples as basis; probably not many if any at all */
11727     /* prevent moof parsing taking of at this time */
11728     offset = qtdemux->moof_offset;
11729     qtdemux->moof_offset = 0;
11730     if (stream->n_samples &&
11731         !qtdemux_parse_samples (qtdemux, stream, stream->n_samples - 1)) {
11732       qtdemux->moof_offset = offset;
11733       goto samples_failed;
11734     }
11735     qtdemux->moof_offset = 0;
11736     /* movie duration more reliable in this case (e.g. mehd) */
11737     if (qtdemux->segment.duration &&
11738         GST_CLOCK_TIME_IS_VALID (qtdemux->segment.duration))
11739       stream->duration =
11740           GSTTIME_TO_QTSTREAMTIME (stream, qtdemux->segment.duration);
11741   }
11742 
11743   /* configure segments */
11744   if (!qtdemux_parse_segments (qtdemux, stream, trak))
11745     goto segments_failed;
11746 
11747   /* add some language tag, if useful */
11748   if (stream->lang_id[0] != '\0' && strcmp (stream->lang_id, "unk") &&
11749       strcmp (stream->lang_id, "und")) {
11750     const gchar *lang_code;
11751 
11752     /* convert ISO 639-2 code to ISO 639-1 */
11753     lang_code = gst_tag_get_language_code (stream->lang_id);
11754     gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
11755         GST_TAG_LANGUAGE_CODE, (lang_code) ? lang_code : stream->lang_id, NULL);
11756   }
11757 
11758   /* Check for UDTA tags */
11759   if ((udta = qtdemux_tree_get_child_by_type (trak, FOURCC_udta))) {
11760     qtdemux_parse_udta (qtdemux, stream->stream_tags, udta);
11761   }
11762 
11763   /* now we are ready to add the stream */
11764   if (qtdemux->n_streams >= GST_QTDEMUX_MAX_STREAMS)
11765     goto too_many_streams;
11766 
11767   if (!qtdemux->got_moov) {
11768     qtdemux->streams[qtdemux->n_streams] = stream;
11769     qtdemux->n_streams++;
11770     GST_DEBUG_OBJECT (qtdemux, "n_streams is now %d", qtdemux->n_streams);
11771   }
11772 
11773   return TRUE;
11774 
11775 /* ERRORS */
11776 skip_track:
11777   {
11778     GST_INFO_OBJECT (qtdemux, "skip disabled track");
11779     if (new_stream)
11780       gst_qtdemux_stream_free (qtdemux, stream);
11781     return TRUE;
11782   }
11783 corrupt_file:
11784   {
11785     GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
11786         (_("This file is corrupt and cannot be played.")), (NULL));
11787     if (new_stream)
11788       gst_qtdemux_stream_free (qtdemux, stream);
11789     return FALSE;
11790   }
11791 error_encrypted:
11792   {
11793     GST_ELEMENT_ERROR (qtdemux, STREAM, DECRYPT, (NULL), (NULL));
11794     if (new_stream)
11795       gst_qtdemux_stream_free (qtdemux, stream);
11796     return FALSE;
11797   }
11798 samples_failed:
11799 segments_failed:
11800   {
11801     /* we posted an error already */
11802     /* free stbl sub-atoms */
11803     gst_qtdemux_stbl_free (stream);
11804     if (new_stream)
11805       gst_qtdemux_stream_free (qtdemux, stream);
11806     return FALSE;
11807   }
11808 existing_stream:
11809   {
11810     GST_INFO_OBJECT (qtdemux, "stream with track id %i already exists",
11811         track_id);
11812     if (new_stream)
11813       gst_qtdemux_stream_free (qtdemux, stream);
11814     return TRUE;
11815   }
11816 unknown_stream:
11817   {
11818     GST_INFO_OBJECT (qtdemux, "unknown subtype %" GST_FOURCC_FORMAT,
11819         GST_FOURCC_ARGS (stream->subtype));
11820     if (new_stream)
11821       gst_qtdemux_stream_free (qtdemux, stream);
11822     return TRUE;
11823   }
11824 too_many_streams:
11825   {
11826     GST_ELEMENT_WARNING (qtdemux, STREAM, DEMUX,
11827         (_("This file contains too many streams. Only playing first %d"),
11828             GST_QTDEMUX_MAX_STREAMS), (NULL));
11829     return TRUE;
11830   }
11831 }
11832 
11833 /* If we can estimate the overall bitrate, and don't have information about the
11834  * stream bitrate for exactly one stream, this guesses the stream bitrate as
11835  * the overall bitrate minus the sum of the bitrates of all other streams. This
11836  * should be useful for the common case where we have one audio and one video
11837  * stream and can estimate the bitrate of one, but not the other. */
11838 static void
11839 gst_qtdemux_guess_bitrate (GstQTDemux * qtdemux)
11840 {
11841   QtDemuxStream *stream = NULL;
11842   gint64 size, sys_bitrate, sum_bitrate = 0;
11843   GstClockTime duration;
11844   gint i;
11845   guint bitrate;
11846 
11847   if (qtdemux->fragmented)
11848     return;
11849 
11850   GST_DEBUG_OBJECT (qtdemux, "Looking for streams with unknown bitrate");
11851 
11852   if (!gst_pad_peer_query_duration (qtdemux->sinkpad, GST_FORMAT_BYTES, &size)
11853       || size <= 0) {
11854     GST_DEBUG_OBJECT (qtdemux,
11855         "Size in bytes of the stream not known - bailing");
11856     return;
11857   }
11858 
11859   /* Subtract the header size */
11860   GST_DEBUG_OBJECT (qtdemux, "Total size %" G_GINT64_FORMAT ", header size %u",
11861       size, qtdemux->header_size);
11862 
11863   if (size < qtdemux->header_size)
11864     return;
11865 
11866   size = size - qtdemux->header_size;
11867 
11868   if (!gst_qtdemux_get_duration (qtdemux, &duration)) {
11869     GST_DEBUG_OBJECT (qtdemux, "Stream duration not known - bailing");
11870     return;
11871   }
11872 
11873   for (i = 0; i < qtdemux->n_streams; i++) {
11874     switch (qtdemux->streams[i]->subtype) {
11875       case FOURCC_soun:
11876       case FOURCC_vide:
11877         GST_DEBUG_OBJECT (qtdemux, "checking bitrate for %" GST_PTR_FORMAT,
11878             CUR_STREAM (qtdemux->streams[i])->caps);
11879         /* retrieve bitrate, prefer avg then max */
11880         bitrate = 0;
11881         if (qtdemux->streams[i]->stream_tags) {
11882           if (gst_tag_list_get_uint (qtdemux->streams[i]->stream_tags,
11883                   GST_TAG_MAXIMUM_BITRATE, &bitrate))
11884           GST_DEBUG_OBJECT (qtdemux, "max-bitrate: %u", bitrate);
11885           if (gst_tag_list_get_uint (qtdemux->streams[i]->stream_tags,
11886                   GST_TAG_NOMINAL_BITRATE, &bitrate))
11887           GST_DEBUG_OBJECT (qtdemux, "nominal-bitrate: %u", bitrate);
11888           if (gst_tag_list_get_uint (qtdemux->streams[i]->stream_tags,
11889                   GST_TAG_BITRATE, &bitrate))
11890           GST_DEBUG_OBJECT (qtdemux, "bitrate: %u", bitrate);
11891         }
11892         if (bitrate)
11893           sum_bitrate += bitrate;
11894         else {
11895           if (stream) {
11896             GST_DEBUG_OBJECT (qtdemux,
11897                 ">1 stream with unknown bitrate - bailing");
11898             return;
11899           } else
11900             stream = qtdemux->streams[i];
11901         }
11902 
11903       default:
11904         /* For other subtypes, we assume no significant impact on bitrate */
11905         break;
11906     }
11907   }
11908 
11909   if (!stream) {
11910     GST_DEBUG_OBJECT (qtdemux, "All stream bitrates are known");
11911     return;
11912   }
11913 
11914   sys_bitrate = gst_util_uint64_scale (size, GST_SECOND * 8, duration);
11915 
11916   if (sys_bitrate < sum_bitrate) {
11917     /* This can happen, since sum_bitrate might be derived from maximum
11918      * bitrates and not average bitrates */
11919     GST_DEBUG_OBJECT (qtdemux,
11920         "System bitrate less than sum bitrate - bailing");
11921     return;
11922   }
11923 
11924   bitrate = sys_bitrate - sum_bitrate;
11925   GST_DEBUG_OBJECT (qtdemux, "System bitrate = %" G_GINT64_FORMAT
11926       ", Stream bitrate = %u", sys_bitrate, bitrate);
11927 
11928   if (!stream->stream_tags)
11929     stream->stream_tags = gst_tag_list_new_empty ();
11930   else
11931     stream->stream_tags = gst_tag_list_make_writable (stream->stream_tags);
11932 
11933   gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
11934       GST_TAG_BITRATE, bitrate, NULL);
11935 }
11936 
11937 static GstFlowReturn
11938 qtdemux_prepare_streams (GstQTDemux * qtdemux)
11939 {
11940   gint i;
11941   GstFlowReturn ret = GST_FLOW_OK;
11942 
11943   GST_DEBUG_OBJECT (qtdemux, "prepare streams");
11944 
11945   for (i = 0; ret == GST_FLOW_OK && i < qtdemux->n_streams; i++) {
11946     QtDemuxStream *stream = qtdemux->streams[i];
11947     guint32 sample_num = 0;
11948 
11949     GST_DEBUG_OBJECT (qtdemux, "stream %d, id %d, fourcc %" GST_FOURCC_FORMAT,
11950         i, stream->track_id, GST_FOURCC_ARGS (CUR_STREAM (stream)->fourcc));
11951 
11952     if (qtdemux->fragmented) {
11953       /* need all moov samples first */
11954       GST_OBJECT_LOCK (qtdemux);
11955       while (stream->n_samples == 0)
11956         if ((ret = qtdemux_add_fragmented_samples (qtdemux)) != GST_FLOW_OK)
11957           break;
11958       GST_OBJECT_UNLOCK (qtdemux);
11959     } else {
11960       /* discard any stray moof */
11961       qtdemux->moof_offset = 0;
11962     }
11963 
11964     /* prepare braking */
11965     if (ret != GST_FLOW_ERROR)
11966       ret = GST_FLOW_OK;
11967 
11968     /* in pull mode, we should have parsed some sample info by now;
11969      * and quite some code will not handle no samples.
11970      * in push mode, we'll just have to deal with it */
11971     if (G_UNLIKELY (qtdemux->pullbased && !stream->n_samples)) {
11972       GST_DEBUG_OBJECT (qtdemux, "no samples for stream; discarding");
11973       gst_qtdemux_remove_stream (qtdemux, i);
11974       i--;
11975       continue;
11976     }
11977 
11978     /* parse the initial sample for use in setting the frame rate cap */
11979     while (sample_num == 0 && sample_num < stream->n_samples) {
11980       if (!qtdemux_parse_samples (qtdemux, stream, sample_num))
11981         break;
11982       ++sample_num;
11983     }
11984     if (stream->n_samples > 0 && stream->stbl_index >= 0) {
11985       stream->first_duration = stream->samples[0].duration;
11986       GST_LOG_OBJECT (qtdemux, "stream %d first duration %u",
11987           stream->track_id, stream->first_duration);
11988       }
11989     }
11990 
11991   return ret;
11992 }
11993 
11994 static GstFlowReturn
11995 qtdemux_expose_streams (GstQTDemux * qtdemux)
11996 {
11997   gint i;
11998   GSList *oldpads = NULL;
11999   GSList *iter;
12000 
12001   GST_DEBUG_OBJECT (qtdemux, "exposing streams");
12002 
12003   for (i = 0; i < qtdemux->n_streams; i++) {
12004     QtDemuxStream *stream = qtdemux->streams[i];
12005     GstPad *oldpad = stream->pad;
12006     GstTagList *list;
12007 
12008     GST_DEBUG_OBJECT (qtdemux, "stream %d, id %d, fourcc %" GST_FOURCC_FORMAT,
12009         i, stream->track_id, GST_FOURCC_ARGS (CUR_STREAM (stream)->fourcc));
12010 
12011     if ((stream->subtype == FOURCC_text || stream->subtype == FOURCC_sbtl) &&
12012         stream->track_id == qtdemux->chapters_track_id) {
12013       /* TODO - parse chapters track and expose it as GstToc; For now just ignore it
12014          so that it doesn't look like a subtitle track */
12015       gst_qtdemux_remove_stream (qtdemux, i);
12016       i--;
12017       continue;
12018     }
12019 
12020     /* now we have all info and can expose */
12021     list = stream->stream_tags;
12022     stream->stream_tags = NULL;
12023     if (oldpad)
12024       oldpads = g_slist_prepend (oldpads, oldpad);
12025     if (!gst_qtdemux_add_stream (qtdemux, stream, list))
12026       return GST_FLOW_ERROR;
12027   }
12028 
12029   gst_qtdemux_guess_bitrate (qtdemux);
12030 
12031   gst_element_no_more_pads (GST_ELEMENT_CAST (qtdemux));
12032 
12033   for (iter = oldpads; iter; iter = g_slist_next (iter)) {
12034     GstPad *oldpad = iter->data;
12035     GstEvent *event;
12036 
12037     event = gst_event_new_eos ();
12038     if (qtdemux->segment_seqnum != GST_SEQNUM_INVALID)
12039       gst_event_set_seqnum (event, qtdemux->segment_seqnum);
12040 
12041     gst_pad_push_event (oldpad, event);
12042     gst_pad_set_active (oldpad, FALSE);
12043     gst_element_remove_pad (GST_ELEMENT (qtdemux), oldpad);
12044     gst_flow_combiner_remove_pad (qtdemux->flowcombiner, oldpad);
12045     gst_object_unref (oldpad);
12046   }
12047 
12048   /* check if we should post a redirect in case there is a single trak
12049    * and it is a redirecting trak */
12050   if (qtdemux->n_streams == 1 && qtdemux->streams[0]->redirect_uri != NULL) {
12051     GstMessage *m;
12052 
12053     GST_INFO_OBJECT (qtdemux, "Issuing a redirect due to a single track with "
12054         "an external content");
12055     m = gst_message_new_element (GST_OBJECT_CAST (qtdemux),
12056         gst_structure_new ("redirect",
12057             "new-location", G_TYPE_STRING, qtdemux->streams[0]->redirect_uri,
12058             NULL));
12059     gst_element_post_message (GST_ELEMENT_CAST (qtdemux), m);
12060     qtdemux->posted_redirect = TRUE;
12061   }
12062 
12063   for (i = 0; i < qtdemux->n_streams; i++) {
12064     QtDemuxStream *stream = qtdemux->streams[i];
12065 
12066     qtdemux_do_allocation (qtdemux, stream);
12067   }
12068 
12069   qtdemux->exposed = TRUE;
12070   return GST_FLOW_OK;
12071 }
12072 
12073 /* check if major or compatible brand is 3GP */
12074 static inline gboolean
12075 qtdemux_is_brand_3gp (GstQTDemux * qtdemux, gboolean major)
12076 {
12077   if (major) {
12078     return ((qtdemux->major_brand & GST_MAKE_FOURCC (255, 255, 0, 0)) ==
12079         FOURCC_3g__);
12080   } else if (qtdemux->comp_brands != NULL) {
12081     GstMapInfo map;
12082     guint8 *data;
12083     gsize size;
12084     gboolean res = FALSE;
12085 
12086     gst_buffer_map (qtdemux->comp_brands, &map, GST_MAP_READ);
12087     data = map.data;
12088     size = map.size;
12089     while (size >= 4) {
12090       res = res || ((QT_FOURCC (data) & GST_MAKE_FOURCC (255, 255, 0, 0)) ==
12091           FOURCC_3g__);
12092       data += 4;
12093       size -= 4;
12094     }
12095     gst_buffer_unmap (qtdemux->comp_brands, &map);
12096     return res;
12097   } else {
12098     return FALSE;
12099   }
12100 }
12101 
12102 /* check if tag is a spec'ed 3GP tag keyword storing a string */
12103 static inline gboolean
12104 qtdemux_is_string_tag_3gp (GstQTDemux * qtdemux, guint32 fourcc)
12105 {
12106   return fourcc == FOURCC_cprt || fourcc == FOURCC_gnre || fourcc == FOURCC_titl
12107       || fourcc == FOURCC_dscp || fourcc == FOURCC_perf || fourcc == FOURCC_auth
12108       || fourcc == FOURCC_albm;
12109 }
12110 
12111 static void
12112 qtdemux_tag_add_location (GstQTDemux * qtdemux, GstTagList * taglist,
12113     const char *tag, const char *dummy, GNode * node)
12114 {
12115   const gchar *env_vars[] = { "GST_QT_TAG_ENCODING", "GST_TAG_ENCODING", NULL };
12116   int offset;
12117   char *name;
12118   gchar *data;
12119   gdouble longitude, latitude, altitude;
12120   gint len;
12121 
12122   len = QT_UINT32 (node->data);
12123   if (len <= 14)
12124     goto short_read;
12125 
12126   data = node->data;
12127   offset = 14;
12128 
12129   /* TODO: language code skipped */
12130 
12131   name = gst_tag_freeform_string_to_utf8 (data + offset, -1, env_vars);
12132 
12133   if (!name) {
12134     /* do not alarm in trivial case, but bail out otherwise */
12135     if (*(data + offset) != 0) {
12136       GST_DEBUG_OBJECT (qtdemux, "failed to convert %s tag to UTF-8, "
12137           "giving up", tag);
12138     }
12139   } else {
12140     gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE,
12141         GST_TAG_GEO_LOCATION_NAME, name, NULL);
12142     offset += strlen (name);
12143     g_free (name);
12144   }
12145 
12146   if (len < offset + 2 + 4 + 4 + 4)
12147     goto short_read;
12148 
12149   /* +1 +1 = skip null-terminator and location role byte */
12150   offset += 1 + 1;
12151   /* table in spec says unsigned, semantics say negative has meaning ... */
12152   longitude = QT_SFP32 (data + offset);
12153 
12154   offset += 4;
12155   latitude = QT_SFP32 (data + offset);
12156 
12157   offset += 4;
12158   altitude = QT_SFP32 (data + offset);
12159 
12160   /* one invalid means all are invalid */
12161   if (longitude >= -180.0 && longitude <= 180.0 &&
12162       latitude >= -90.0 && latitude <= 90.0) {
12163     gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE,
12164         GST_TAG_GEO_LOCATION_LATITUDE, latitude,
12165         GST_TAG_GEO_LOCATION_LONGITUDE, longitude,
12166         GST_TAG_GEO_LOCATION_ELEVATION, altitude, NULL);
12167   }
12168 
12169   /* TODO: no GST_TAG_, so astronomical body and additional notes skipped */
12170 
12171   return;
12172 
12173   /* ERRORS */
12174 short_read:
12175   {
12176     GST_DEBUG_OBJECT (qtdemux, "short read parsing 3GP location");
12177     return;
12178   }
12179 }
12180 
12181 
12182 static void
12183 qtdemux_tag_add_year (GstQTDemux * qtdemux, GstTagList * taglist,
12184     const char *tag, const char *dummy, GNode * node)
12185 {
12186   guint16 y;
12187   GDate *date;
12188   gint len;
12189 
12190   len = QT_UINT32 (node->data);
12191   if (len < 14)
12192     return;
12193 
12194   y = QT_UINT16 ((guint8 *) node->data + 12);
12195   if (y == 0) {
12196     GST_DEBUG_OBJECT (qtdemux, "year: %u is not a valid year", y);
12197     return;
12198   }
12199   GST_DEBUG_OBJECT (qtdemux, "year: %u", y);
12200 
12201   date = g_date_new_dmy (1, 1, y);
12202   gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag, date, NULL);
12203   g_date_free (date);
12204 }
12205 
12206 static void
12207 qtdemux_tag_add_classification (GstQTDemux * qtdemux, GstTagList * taglist,
12208     const char *tag, const char *dummy, GNode * node)
12209 {
12210   int offset;
12211   char *tag_str = NULL;
12212   guint8 *entity;
12213   guint16 table;
12214   gint len;
12215 
12216   len = QT_UINT32 (node->data);
12217   if (len <= 20)
12218     goto short_read;
12219 
12220   offset = 12;
12221   entity = (guint8 *) node->data + offset;
12222   if (entity[0] == 0 || entity[1] == 0 || entity[2] == 0 || entity[3] == 0) {
12223     GST_DEBUG_OBJECT (qtdemux,
12224         "classification info: %c%c%c%c invalid classification entity",
12225         entity[0], entity[1], entity[2], entity[3]);
12226     return;
12227   }
12228 
12229   offset += 4;
12230   table = QT_UINT16 ((guint8 *) node->data + offset);
12231 
12232   /* Language code skipped */
12233 
12234   offset += 4;
12235 
12236   /* Tag format: "XXXX://Y[YYYY]/classification info string"
12237    * XXXX: classification entity, fixed length 4 chars.
12238    * Y[YYYY]: classification table, max 5 chars.
12239    */
12240   tag_str = g_strdup_printf ("----://%u/%s",
12241       table, (char *) node->data + offset);
12242 
12243   /* memcpy To be sure we're preserving byte order */
12244   memcpy (tag_str, entity, 4);
12245   GST_DEBUG_OBJECT (qtdemux, "classification info: %s", tag_str);
12246 
12247   gst_tag_list_add (taglist, GST_TAG_MERGE_APPEND, tag, tag_str, NULL);
12248 
12249   g_free (tag_str);
12250 
12251   return;
12252 
12253   /* ERRORS */
12254 short_read:
12255   {
12256     GST_DEBUG_OBJECT (qtdemux, "short read parsing 3GP classification");
12257     return;
12258   }
12259 }
12260 
12261 static gboolean
12262 qtdemux_tag_add_str_full (GstQTDemux * qtdemux, GstTagList * taglist,
12263     const char *tag, const char *dummy, GNode * node)
12264 {
12265   const gchar *env_vars[] = { "GST_QT_TAG_ENCODING", "GST_TAG_ENCODING", NULL };
12266   GNode *data;
12267   char *s;
12268   int len;
12269   guint32 type;
12270   int offset;
12271   gboolean ret = TRUE;
12272   const gchar *charset = NULL;
12273 
12274   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
12275   if (data) {
12276     len = QT_UINT32 (data->data);
12277     type = QT_UINT32 ((guint8 *) data->data + 8);
12278     if (type == 0x00000001 && len > 16) {
12279       s = gst_tag_freeform_string_to_utf8 ((char *) data->data + 16, len - 16,
12280           env_vars);
12281       if (s) {
12282         GST_DEBUG_OBJECT (qtdemux, "adding tag %s", GST_STR_NULL (s));
12283         gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag, s, NULL);
12284         g_free (s);
12285       } else {
12286         GST_DEBUG_OBJECT (qtdemux, "failed to convert %s tag to UTF-8", tag);
12287       }
12288     }
12289   } else {
12290     len = QT_UINT32 (node->data);
12291     type = QT_UINT32 ((guint8 *) node->data + 4);
12292     if ((type >> 24) == 0xa9 && len > 8 + 4) {
12293       gint str_len;
12294       gint lang_code;
12295 
12296       /* Type starts with the (C) symbol, so the next data is a list
12297        * of (string size(16), language code(16), string) */
12298 
12299       str_len = QT_UINT16 ((guint8 *) node->data + 8);
12300       lang_code = QT_UINT16 ((guint8 *) node->data + 10);
12301 
12302       /* the string + fourcc + size + 2 16bit fields,
12303        * means that there are more tags in this atom */
12304       if (len > str_len + 8 + 4) {
12305         /* TODO how to represent the same tag in different languages? */
12306         GST_WARNING_OBJECT (qtdemux, "Ignoring metadata entry with multiple "
12307             "text alternatives, reading only first one");
12308       }
12309 
12310       offset = 12;
12311       len = MIN (len, str_len + 8 + 4); /* remove trailing strings that we don't use */
12312       GST_DEBUG_OBJECT (qtdemux, "found international text tag");
12313 
12314       if (lang_code < 0x800) {  /* MAC encoded string */
12315         charset = "mac";
12316       }
12317     } else if (len > 14 && qtdemux_is_string_tag_3gp (qtdemux,
12318             QT_FOURCC ((guint8 *) node->data + 4))) {
12319       guint32 type = QT_UINT32 ((guint8 *) node->data + 8);
12320 
12321       /* we go for 3GP style encoding if major brands claims so,
12322        * or if no hope for data be ok UTF-8, and compatible 3GP brand present */
12323       if (qtdemux_is_brand_3gp (qtdemux, TRUE) ||
12324           (qtdemux_is_brand_3gp (qtdemux, FALSE) &&
12325               ((type & 0x00FFFFFF) == 0x0) && (type >> 24 <= 0xF))) {
12326         offset = 14;
12327         /* 16-bit Language code is ignored here as well */
12328         GST_DEBUG_OBJECT (qtdemux, "found 3gpp text tag");
12329       } else {
12330         goto normal;
12331       }
12332     } else {
12333     normal:
12334       offset = 8;
12335       GST_DEBUG_OBJECT (qtdemux, "found normal text tag");
12336       ret = FALSE;              /* may have to fallback */
12337     }
12338     if (charset) {
12339       GError *err = NULL;
12340 
12341       s = g_convert ((gchar *) node->data + offset, len - offset, "utf8",
12342           charset, NULL, NULL, &err);
12343       if (err) {
12344         GST_DEBUG_OBJECT (qtdemux, "Failed to convert string from charset %s:"
12345             " %s(%d): %s", charset, g_quark_to_string (err->domain), err->code,
12346             err->message);
12347         g_error_free (err);
12348       }
12349     } else {
12350     s = gst_tag_freeform_string_to_utf8 ((char *) node->data + offset,
12351         len - offset, env_vars);
12352     }
12353     if (s) {
12354       GST_DEBUG_OBJECT (qtdemux, "adding tag %s", GST_STR_NULL (s));
12355       gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag, s, NULL);
12356       g_free (s);
12357       ret = TRUE;
12358     } else {
12359       GST_DEBUG_OBJECT (qtdemux, "failed to convert %s tag to UTF-8", tag);
12360     }
12361   }
12362   return ret;
12363 }
12364 
12365 static void
12366 qtdemux_tag_add_str (GstQTDemux * qtdemux, GstTagList * taglist,
12367     const char *tag, const char *dummy, GNode * node)
12368 {
12369   qtdemux_tag_add_str_full (qtdemux, taglist, tag, dummy, node);
12370 }
12371 
12372 static void
12373 qtdemux_tag_add_keywords (GstQTDemux * qtdemux, GstTagList * taglist,
12374     const char *tag, const char *dummy, GNode * node)
12375 {
12376   const gchar *env_vars[] = { "GST_QT_TAG_ENCODING", "GST_TAG_ENCODING", NULL };
12377   guint8 *data;
12378   char *s, *t, *k = NULL;
12379   int len;
12380   int offset;
12381   int count;
12382 
12383   /* first try normal string tag if major brand not 3GP */
12384   if (!qtdemux_is_brand_3gp (qtdemux, TRUE)) {
12385     if (!qtdemux_tag_add_str_full (qtdemux, taglist, tag, dummy, node)) {
12386       /* hm, that did not work, maybe 3gpp storage in non-3gpp major brand;
12387        * let's try it 3gpp way after minor safety check */
12388       data = node->data;
12389       if (QT_UINT32 (data) < 15 || !qtdemux_is_brand_3gp (qtdemux, FALSE))
12390         return;
12391     } else
12392       return;
12393   }
12394 
12395   GST_DEBUG_OBJECT (qtdemux, "found 3gpp keyword tag");
12396 
12397   data = node->data;
12398 
12399   len = QT_UINT32 (data);
12400   if (len < 15)
12401     goto short_read;
12402 
12403   count = QT_UINT8 (data + 14);
12404   offset = 15;
12405   for (; count; count--) {
12406     gint slen;
12407 
12408     if (offset + 1 > len)
12409       goto short_read;
12410     slen = QT_UINT8 (data + offset);
12411     offset += 1;
12412     if (offset + slen > len)
12413       goto short_read;
12414     s = gst_tag_freeform_string_to_utf8 ((char *) node->data + offset,
12415         slen, env_vars);
12416     if (s) {
12417       GST_DEBUG_OBJECT (qtdemux, "adding keyword %s", GST_STR_NULL (s));
12418       if (k) {
12419         t = g_strjoin (",", k, s, NULL);
12420         g_free (s);
12421         g_free (k);
12422         k = t;
12423       } else {
12424         k = s;
12425       }
12426     } else {
12427       GST_DEBUG_OBJECT (qtdemux, "failed to convert keyword to UTF-8");
12428     }
12429     offset += slen;
12430   }
12431 
12432 done:
12433   if (k) {
12434     GST_DEBUG_OBJECT (qtdemux, "adding tag %s", GST_STR_NULL (k));
12435     gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag, k, NULL);
12436   }
12437   g_free (k);
12438 
12439   return;
12440 
12441   /* ERRORS */
12442 short_read:
12443   {
12444     GST_DEBUG_OBJECT (qtdemux, "short read parsing 3GP keywords");
12445     goto done;
12446   }
12447 }
12448 
12449 static void
12450 qtdemux_tag_add_num (GstQTDemux * qtdemux, GstTagList * taglist,
12451     const char *tag1, const char *tag2, GNode * node)
12452 {
12453   GNode *data;
12454   int len;
12455   int type;
12456   int n1, n2;
12457 
12458   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
12459   if (data) {
12460     len = QT_UINT32 (data->data);
12461     type = QT_UINT32 ((guint8 *) data->data + 8);
12462     if (type == 0x00000000 && len >= 22) {
12463       n1 = QT_UINT16 ((guint8 *) data->data + 18);
12464       n2 = QT_UINT16 ((guint8 *) data->data + 20);
12465       if (n1 > 0) {
12466         GST_DEBUG_OBJECT (qtdemux, "adding tag %s=%d", tag1, n1);
12467         gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag1, n1, NULL);
12468       }
12469       if (n2 > 0) {
12470         GST_DEBUG_OBJECT (qtdemux, "adding tag %s=%d", tag2, n2);
12471         gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag2, n2, NULL);
12472       }
12473     }
12474   }
12475 }
12476 
12477 static void
12478 qtdemux_tag_add_tmpo (GstQTDemux * qtdemux, GstTagList * taglist,
12479     const char *tag1, const char *dummy, GNode * node)
12480 {
12481   GNode *data;
12482   int len;
12483   int type;
12484   int n1;
12485 
12486   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
12487   if (data) {
12488     len = QT_UINT32 (data->data);
12489     type = QT_UINT32 ((guint8 *) data->data + 8);
12490     GST_DEBUG_OBJECT (qtdemux, "have tempo tag, type=%d,len=%d", type, len);
12491     /* some files wrongly have a type 0x0f=15, but it should be 0x15 */
12492     if ((type == 0x00000015 || type == 0x0000000f) && len >= 18) {
12493       n1 = QT_UINT16 ((guint8 *) data->data + 16);
12494       if (n1) {
12495         /* do not add bpm=0 */
12496         GST_DEBUG_OBJECT (qtdemux, "adding tag %d", n1);
12497         gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag1, (gdouble) n1,
12498             NULL);
12499       }
12500     }
12501   }
12502 }
12503 
12504 static void
12505 qtdemux_tag_add_uint32 (GstQTDemux * qtdemux, GstTagList * taglist,
12506     const char *tag1, const char *dummy, GNode * node)
12507 {
12508   GNode *data;
12509   int len;
12510   int type;
12511   guint32 num;
12512 
12513   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
12514   if (data) {
12515     len = QT_UINT32 (data->data);
12516     type = QT_UINT32 ((guint8 *) data->data + 8);
12517     GST_DEBUG_OBJECT (qtdemux, "have %s tag, type=%d,len=%d", tag1, type, len);
12518     /* some files wrongly have a type 0x0f=15, but it should be 0x15 */
12519     if ((type == 0x00000015 || type == 0x0000000f) && len >= 20) {
12520       num = QT_UINT32 ((guint8 *) data->data + 16);
12521       if (num) {
12522         /* do not add num=0 */
12523         GST_DEBUG_OBJECT (qtdemux, "adding tag %d", num);
12524         gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag1, num, NULL);
12525       }
12526     }
12527   }
12528 }
12529 
12530 static void
12531 qtdemux_tag_add_covr (GstQTDemux * qtdemux, GstTagList * taglist,
12532     const char *tag1, const char *dummy, GNode * node)
12533 {
12534   GNode *data;
12535   int len;
12536   int type;
12537   GstSample *sample;
12538 
12539   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
12540   if (data) {
12541     len = QT_UINT32 (data->data);
12542     type = QT_UINT32 ((guint8 *) data->data + 8);
12543     GST_DEBUG_OBJECT (qtdemux, "have covr tag, type=%d,len=%d", type, len);
12544     if ((type == 0x0000000d || type == 0x0000000e) && len > 16) {
12545       GstTagImageType image_type;
12546 
12547       if (gst_tag_list_get_tag_size (taglist, GST_TAG_IMAGE) == 0)
12548         image_type = GST_TAG_IMAGE_TYPE_FRONT_COVER;
12549       else
12550         image_type = GST_TAG_IMAGE_TYPE_NONE;
12551 
12552       if ((sample =
12553               gst_tag_image_data_to_image_sample ((guint8 *) data->data + 16,
12554                   len - 16, image_type))) {
12555         GST_DEBUG_OBJECT (qtdemux, "adding tag size %d", len - 16);
12556         gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag1, sample, NULL);
12557         gst_sample_unref (sample);
12558       }
12559     }
12560   }
12561 }
12562 
12563 static void
12564 qtdemux_tag_add_date (GstQTDemux * qtdemux, GstTagList * taglist,
12565     const char *tag, const char *dummy, GNode * node)
12566 {
12567   GNode *data;
12568   char *s;
12569   int len;
12570   int type;
12571 
12572   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
12573   if (data) {
12574     len = QT_UINT32 (data->data);
12575     type = QT_UINT32 ((guint8 *) data->data + 8);
12576     if (type == 0x00000001 && len > 16) {
12577       guint y, m = 1, d = 1;
12578       gint ret;
12579 
12580       s = g_strndup ((char *) data->data + 16, len - 16);
12581       GST_DEBUG_OBJECT (qtdemux, "adding date '%s'", s);
12582       ret = sscanf (s, "%u-%u-%u", &y, &m, &d);
12583       if (ret >= 1 && y > 1500 && y < 3000) {
12584         GDate *date;
12585 
12586         date = g_date_new_dmy (d, m, y);
12587         gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag, date, NULL);
12588         g_date_free (date);
12589       } else {
12590         GST_DEBUG_OBJECT (qtdemux, "could not parse date string '%s'", s);
12591       }
12592       g_free (s);
12593     }
12594   }
12595 }
12596 
12597 static void
12598 qtdemux_tag_add_gnre (GstQTDemux * qtdemux, GstTagList * taglist,
12599     const char *tag, const char *dummy, GNode * node)
12600 {
12601   GNode *data;
12602 
12603   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
12604 
12605   /* re-route to normal string tag if major brand says so
12606    * or no data atom and compatible brand suggests so */
12607   if (qtdemux_is_brand_3gp (qtdemux, TRUE) ||
12608       (qtdemux_is_brand_3gp (qtdemux, FALSE) && !data)) {
12609     qtdemux_tag_add_str (qtdemux, taglist, tag, dummy, node);
12610     return;
12611   }
12612 
12613   if (data) {
12614     guint len, type, n;
12615 
12616     len = QT_UINT32 (data->data);
12617     type = QT_UINT32 ((guint8 *) data->data + 8);
12618     if (type == 0x00000000 && len >= 18) {
12619       n = QT_UINT16 ((guint8 *) data->data + 16);
12620       if (n > 0) {
12621         const gchar *genre;
12622 
12623         genre = gst_tag_id3_genre_get (n - 1);
12624         if (genre != NULL) {
12625           GST_DEBUG_OBJECT (qtdemux, "adding %d [%s]", n, genre);
12626           gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag, genre, NULL);
12627         }
12628       }
12629     }
12630   }
12631 }
12632 
12633 static void
12634 qtdemux_add_double_tag_from_str (GstQTDemux * demux, GstTagList * taglist,
12635     const gchar * tag, guint8 * data, guint32 datasize)
12636 {
12637   gdouble value;
12638   gchar *datacopy;
12639 
12640   /* make a copy to have \0 at the end */
12641   datacopy = g_strndup ((gchar *) data, datasize);
12642 
12643   /* convert the str to double */
12644   if (sscanf (datacopy, "%lf", &value) == 1) {
12645     GST_DEBUG_OBJECT (demux, "adding tag: %s [%s]", tag, datacopy);
12646     gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag, value, NULL);
12647   } else {
12648     GST_WARNING_OBJECT (demux, "Failed to parse double from string: %s",
12649         datacopy);
12650   }
12651   g_free (datacopy);
12652 }
12653 
12654 
12655 static void
12656 qtdemux_tag_add_revdns (GstQTDemux * demux, GstTagList * taglist,
12657     const char *tag, const char *tag_bis, GNode * node)
12658 {
12659   GNode *mean;
12660   GNode *name;
12661   GNode *data;
12662   guint32 meansize;
12663   guint32 namesize;
12664   guint32 datatype;
12665   guint32 datasize;
12666   const gchar *meanstr;
12667   const gchar *namestr;
12668 
12669   /* checking the whole ---- atom size for consistency */
12670   if (QT_UINT32 (node->data) <= 4 + 12 + 12 + 16) {
12671     GST_WARNING_OBJECT (demux, "Tag ---- atom is too small, ignoring");
12672     return;
12673   }
12674 
12675   mean = qtdemux_tree_get_child_by_type (node, FOURCC_mean);
12676   if (!mean) {
12677     GST_WARNING_OBJECT (demux, "No 'mean' atom found");
12678     return;
12679   }
12680 
12681   meansize = QT_UINT32 (mean->data);
12682   if (meansize <= 12) {
12683     GST_WARNING_OBJECT (demux, "Small mean atom, ignoring the whole tag");
12684     return;
12685   }
12686   meanstr = ((gchar *) mean->data) + 12;
12687   meansize -= 12;
12688 
12689   name = qtdemux_tree_get_child_by_type (node, FOURCC_name);
12690   if (!name) {
12691     GST_WARNING_OBJECT (demux, "'name' atom not found, ignoring tag");
12692     return;
12693   }
12694 
12695   namesize = QT_UINT32 (name->data);
12696   if (namesize <= 12) {
12697     GST_WARNING_OBJECT (demux, "'name' atom is too small, ignoring tag");
12698     return;
12699   }
12700   namestr = ((gchar *) name->data) + 12;
12701   namesize -= 12;
12702 
12703   /*
12704    * Data atom is:
12705    * uint32 - size
12706    * uint32 - name
12707    * uint8  - version
12708    * uint24 - data type
12709    * uint32 - all 0
12710    * rest   - the data
12711    */
12712   data = qtdemux_tree_get_child_by_type (node, FOURCC_data);
12713   if (!data) {
12714     GST_WARNING_OBJECT (demux, "No data atom in this tag");
12715     return;
12716   }
12717   datasize = QT_UINT32 (data->data);
12718   if (datasize <= 16) {
12719     GST_WARNING_OBJECT (demux, "Data atom too small");
12720     return;
12721   }
12722   datatype = QT_UINT32 (((gchar *) data->data) + 8) & 0xFFFFFF;
12723 
12724   if ((strncmp (meanstr, "com.apple.iTunes", meansize) == 0) ||
12725       (strncmp (meanstr, "org.hydrogenaudio.replaygain", meansize) == 0)) {
12726     static const struct
12727     {
12728       const gchar name[28];
12729       const gchar tag[28];
12730     } tags[] = {
12731       {
12732       "replaygain_track_gain", GST_TAG_TRACK_GAIN}, {
12733       "replaygain_track_peak", GST_TAG_TRACK_PEAK}, {
12734       "replaygain_album_gain", GST_TAG_ALBUM_GAIN}, {
12735       "replaygain_album_peak", GST_TAG_ALBUM_PEAK}, {
12736       "MusicBrainz Track Id", GST_TAG_MUSICBRAINZ_TRACKID}, {
12737       "MusicBrainz Artist Id", GST_TAG_MUSICBRAINZ_ARTISTID}, {
12738       "MusicBrainz Album Id", GST_TAG_MUSICBRAINZ_ALBUMID}, {
12739       "MusicBrainz Album Artist Id", GST_TAG_MUSICBRAINZ_ALBUMARTISTID}
12740     };
12741     int i;
12742 
12743     for (i = 0; i < G_N_ELEMENTS (tags); ++i) {
12744       if (!g_ascii_strncasecmp (tags[i].name, namestr, namesize)) {
12745         switch (gst_tag_get_type (tags[i].tag)) {
12746           case G_TYPE_DOUBLE:
12747             qtdemux_add_double_tag_from_str (demux, taglist, tags[i].tag,
12748                 ((guint8 *) data->data) + 16, datasize - 16);
12749             break;
12750           case G_TYPE_STRING:
12751             qtdemux_tag_add_str (demux, taglist, tags[i].tag, NULL, node);
12752             break;
12753           default:
12754             /* not reached */
12755             break;
12756         }
12757         break;
12758       }
12759     }
12760     if (i == G_N_ELEMENTS (tags))
12761       goto unknown_tag;
12762   } else {
12763     goto unknown_tag;
12764   }
12765 
12766   return;
12767 
12768 /* errors */
12769 unknown_tag:
12770 #ifndef GST_DISABLE_GST_DEBUG
12771   {
12772     gchar *namestr_dbg;
12773     gchar *meanstr_dbg;
12774 
12775     meanstr_dbg = g_strndup (meanstr, meansize);
12776     namestr_dbg = g_strndup (namestr, namesize);
12777 
12778     GST_WARNING_OBJECT (demux, "This tag %s:%s type:%u is not mapped, "
12779         "file a bug at bugzilla.gnome.org", meanstr_dbg, namestr_dbg, datatype);
12780 
12781     g_free (namestr_dbg);
12782     g_free (meanstr_dbg);
12783   }
12784 #endif
12785     return;
12786 }
12787 
12788 static void
12789 qtdemux_tag_add_id32 (GstQTDemux * demux, GstTagList * taglist, const char *tag,
12790     const char *tag_bis, GNode * node)
12791 {
12792   guint8 *data;
12793   GstBuffer *buf;
12794   guint len;
12795   GstTagList *id32_taglist = NULL;
12796 
12797   GST_LOG_OBJECT (demux, "parsing ID32");
12798 
12799   data = node->data;
12800   len = GST_READ_UINT32_BE (data);
12801 
12802   /* need at least full box and language tag */
12803   if (len < 12 + 2)
12804     return;
12805 
12806   buf = gst_buffer_new_allocate (NULL, len - 14, NULL);
12807   gst_buffer_fill (buf, 0, data + 14, len - 14);
12808 
12809   id32_taglist = gst_tag_list_from_id3v2_tag (buf);
12810   if (id32_taglist) {
12811     GST_LOG_OBJECT (demux, "parsing ok");
12812     gst_tag_list_insert (taglist, id32_taglist, GST_TAG_MERGE_KEEP);
12813     gst_tag_list_unref (id32_taglist);
12814   } else {
12815     GST_LOG_OBJECT (demux, "parsing failed");
12816   }
12817 
12818   gst_buffer_unref (buf);
12819 }
12820 
12821 typedef void (*GstQTDemuxAddTagFunc) (GstQTDemux * demux, GstTagList * taglist,
12822     const char *tag, const char *tag_bis, GNode * node);
12823 
12824 /* unmapped tags
12825 FOURCC_pcst -> if media is a podcast -> bool
12826 FOURCC_cpil -> if media is part of a compilation -> bool
12827 FOURCC_pgap -> if media is part of a gapless context -> bool
12828 FOURCC_tven -> the tv episode id e.g. S01E23 -> str
12829 */
12830 
12831 static const struct
12832 {
12833   guint32 fourcc;
12834   const gchar *gst_tag;
12835   const gchar *gst_tag_bis;
12836   const GstQTDemuxAddTagFunc func;
12837 } add_funcs[] = {
12838   {
12839   FOURCC__nam, GST_TAG_TITLE, NULL, qtdemux_tag_add_str}, {
12840   FOURCC_titl, GST_TAG_TITLE, NULL, qtdemux_tag_add_str}, {
12841   FOURCC__grp, GST_TAG_GROUPING, NULL, qtdemux_tag_add_str}, {
12842   FOURCC__wrt, GST_TAG_COMPOSER, NULL, qtdemux_tag_add_str}, {
12843   FOURCC__ART, GST_TAG_ARTIST, NULL, qtdemux_tag_add_str}, {
12844   FOURCC_aART, GST_TAG_ALBUM_ARTIST, NULL, qtdemux_tag_add_str}, {
12845   FOURCC_perf, GST_TAG_ARTIST, NULL, qtdemux_tag_add_str}, {
12846   FOURCC_auth, GST_TAG_COMPOSER, NULL, qtdemux_tag_add_str}, {
12847   FOURCC__alb, GST_TAG_ALBUM, NULL, qtdemux_tag_add_str}, {
12848   FOURCC_albm, GST_TAG_ALBUM, NULL, qtdemux_tag_add_str}, {
12849   FOURCC_cprt, GST_TAG_COPYRIGHT, NULL, qtdemux_tag_add_str}, {
12850   FOURCC__cpy, GST_TAG_COPYRIGHT, NULL, qtdemux_tag_add_str}, {
12851   FOURCC__cmt, GST_TAG_COMMENT, NULL, qtdemux_tag_add_str}, {
12852   FOURCC__des, GST_TAG_DESCRIPTION, NULL, qtdemux_tag_add_str}, {
12853   FOURCC_desc, GST_TAG_DESCRIPTION, NULL, qtdemux_tag_add_str}, {
12854   FOURCC_dscp, GST_TAG_DESCRIPTION, NULL, qtdemux_tag_add_str}, {
12855   FOURCC__lyr, GST_TAG_LYRICS, NULL, qtdemux_tag_add_str}, {
12856   FOURCC__day, GST_TAG_DATE, NULL, qtdemux_tag_add_date}, {
12857   FOURCC_yrrc, GST_TAG_DATE, NULL, qtdemux_tag_add_year}, {
12858   FOURCC__too, GST_TAG_ENCODER, NULL, qtdemux_tag_add_str}, {
12859   FOURCC__inf, GST_TAG_COMMENT, NULL, qtdemux_tag_add_str}, {
12860   FOURCC_trkn, GST_TAG_TRACK_NUMBER, GST_TAG_TRACK_COUNT, qtdemux_tag_add_num}, {
12861   FOURCC_disk, GST_TAG_ALBUM_VOLUME_NUMBER, GST_TAG_ALBUM_VOLUME_COUNT,
12862         qtdemux_tag_add_num}, {
12863   FOURCC_disc, GST_TAG_ALBUM_VOLUME_NUMBER, GST_TAG_ALBUM_VOLUME_COUNT,
12864         qtdemux_tag_add_num}, {
12865   FOURCC__gen, GST_TAG_GENRE, NULL, qtdemux_tag_add_str}, {
12866   FOURCC_gnre, GST_TAG_GENRE, NULL, qtdemux_tag_add_gnre}, {
12867   FOURCC_tmpo, GST_TAG_BEATS_PER_MINUTE, NULL, qtdemux_tag_add_tmpo}, {
12868   FOURCC_covr, GST_TAG_IMAGE, NULL, qtdemux_tag_add_covr}, {
12869   FOURCC_sonm, GST_TAG_TITLE_SORTNAME, NULL, qtdemux_tag_add_str}, {
12870   FOURCC_soal, GST_TAG_ALBUM_SORTNAME, NULL, qtdemux_tag_add_str}, {
12871   FOURCC_soar, GST_TAG_ARTIST_SORTNAME, NULL, qtdemux_tag_add_str}, {
12872   FOURCC_soaa, GST_TAG_ALBUM_ARTIST_SORTNAME, NULL, qtdemux_tag_add_str}, {
12873   FOURCC_soco, GST_TAG_COMPOSER_SORTNAME, NULL, qtdemux_tag_add_str}, {
12874   FOURCC_sosn, GST_TAG_SHOW_SORTNAME, NULL, qtdemux_tag_add_str}, {
12875   FOURCC_tvsh, GST_TAG_SHOW_NAME, NULL, qtdemux_tag_add_str}, {
12876   FOURCC_tvsn, GST_TAG_SHOW_SEASON_NUMBER, NULL, qtdemux_tag_add_uint32}, {
12877   FOURCC_tves, GST_TAG_SHOW_EPISODE_NUMBER, NULL, qtdemux_tag_add_uint32}, {
12878   FOURCC_kywd, GST_TAG_KEYWORDS, NULL, qtdemux_tag_add_keywords}, {
12879   FOURCC_keyw, GST_TAG_KEYWORDS, NULL, qtdemux_tag_add_str}, {
12880   FOURCC__enc, GST_TAG_ENCODER, NULL, qtdemux_tag_add_str}, {
12881   FOURCC_loci, GST_TAG_GEO_LOCATION_NAME, NULL, qtdemux_tag_add_location}, {
12882   FOURCC_clsf, GST_QT_DEMUX_CLASSIFICATION_TAG, NULL,
12883         qtdemux_tag_add_classification}, {
12884   FOURCC__mak, GST_TAG_DEVICE_MANUFACTURER, NULL, qtdemux_tag_add_str}, {
12885   FOURCC__mod, GST_TAG_DEVICE_MODEL, NULL, qtdemux_tag_add_str}, {
12886   FOURCC__swr, GST_TAG_APPLICATION_NAME, NULL, qtdemux_tag_add_str}, {
12887 
12888     /* This is a special case, some tags are stored in this
12889      * 'reverse dns naming', according to:
12890      * http://atomicparsley.sourceforge.net/mpeg-4files.html and
12891      * bug #614471
12892      */
12893   FOURCC_____, "", NULL, qtdemux_tag_add_revdns}, {
12894     /* see http://www.mp4ra.org/specs.html for ID32 in meta box */
12895   FOURCC_ID32, "", NULL, qtdemux_tag_add_id32}
12896 };
12897 
12898 struct _GstQtDemuxTagList
12899 {
12900   GstQTDemux *demux;
12901   GstTagList *taglist;
12902 };
12903 typedef struct _GstQtDemuxTagList GstQtDemuxTagList;
12904 
12905 static void
12906 qtdemux_tag_add_blob (GNode * node, GstQtDemuxTagList * qtdemuxtaglist)
12907 {
12908   gint len;
12909   guint8 *data;
12910   GstBuffer *buf;
12911   gchar *media_type;
12912   const gchar *style;
12913   GstSample *sample;
12914   GstStructure *s;
12915   guint i;
12916   guint8 ndata[4];
12917   GstQTDemux *demux = qtdemuxtaglist->demux;
12918   GstTagList *taglist = qtdemuxtaglist->taglist;
12919 
12920   data = node->data;
12921   len = QT_UINT32 (data);
12922   buf = gst_buffer_new_and_alloc (len);
12923   gst_buffer_fill (buf, 0, data, len);
12924 
12925   /* heuristic to determine style of tag */
12926   if (QT_FOURCC (data + 4) == FOURCC_____ ||
12927       (len > 8 + 12 && QT_FOURCC (data + 12) == FOURCC_data))
12928     style = "itunes";
12929   else if (demux->major_brand == FOURCC_qt__)
12930     style = "quicktime";
12931   /* fall back to assuming iso/3gp tag style */
12932   else
12933     style = "iso";
12934 
12935   /* santize the name for the caps. */
12936   for (i = 0; i < 4; i++) {
12937     guint8 d = data[4 + i];
12938     if (g_ascii_isalnum (d))
12939       ndata[i] = g_ascii_tolower (d);
12940     else
12941       ndata[i] = '_';
12942   }
12943 
12944   media_type = g_strdup_printf ("application/x-gst-qt-%c%c%c%c-tag",
12945       ndata[0], ndata[1], ndata[2], ndata[3]);
12946   GST_DEBUG_OBJECT (demux, "media type %s", media_type);
12947 
12948   s = gst_structure_new (media_type, "style", G_TYPE_STRING, style, NULL);
12949   sample = gst_sample_new (buf, NULL, NULL, s);
12950   gst_buffer_unref (buf);
12951   g_free (media_type);
12952 
12953   GST_DEBUG_OBJECT (demux, "adding private tag; size %d, info %" GST_PTR_FORMAT,
12954       len, s);
12955 
12956   gst_tag_list_add (taglist, GST_TAG_MERGE_APPEND,
12957       GST_QT_DEMUX_PRIVATE_TAG, sample, NULL);
12958 
12959   gst_sample_unref (sample);
12960 }
12961 
12962 static void
12963 qtdemux_parse_udta (GstQTDemux * qtdemux, GstTagList * taglist, GNode * udta)
12964 {
12965   GNode *meta;
12966   GNode *ilst;
12967   GNode *xmp_;
12968   GNode *node;
12969   gint i;
12970   GstQtDemuxTagList demuxtaglist;
12971 
12972   demuxtaglist.demux = qtdemux;
12973   demuxtaglist.taglist = taglist;
12974 
12975   meta = qtdemux_tree_get_child_by_type (udta, FOURCC_meta);
12976   if (meta != NULL) {
12977     ilst = qtdemux_tree_get_child_by_type (meta, FOURCC_ilst);
12978     if (ilst == NULL) {
12979       GST_LOG_OBJECT (qtdemux, "no ilst");
12980       return;
12981     }
12982   } else {
12983     ilst = udta;
12984     GST_LOG_OBJECT (qtdemux, "no meta so using udta itself");
12985   }
12986 
12987   i = 0;
12988   while (i < G_N_ELEMENTS (add_funcs)) {
12989     node = qtdemux_tree_get_child_by_type (ilst, add_funcs[i].fourcc);
12990     if (node) {
12991       gint len;
12992 
12993       len = QT_UINT32 (node->data);
12994       if (len < 12) {
12995         GST_DEBUG_OBJECT (qtdemux, "too small tag atom %" GST_FOURCC_FORMAT,
12996             GST_FOURCC_ARGS (add_funcs[i].fourcc));
12997       } else {
12998         add_funcs[i].func (qtdemux, taglist, add_funcs[i].gst_tag,
12999             add_funcs[i].gst_tag_bis, node);
13000       }
13001       g_node_destroy (node);
13002     } else {
13003       i++;
13004     }
13005   }
13006 
13007   /* parsed nodes have been removed, pass along remainder as blob */
13008   g_node_children_foreach (ilst, G_TRAVERSE_ALL,
13009       (GNodeForeachFunc) qtdemux_tag_add_blob, &demuxtaglist);
13010 
13011 #ifndef GSTREAMER_LITE
13012   /* parse up XMP_ node if existing */
13013   xmp_ = qtdemux_tree_get_child_by_type (udta, FOURCC_XMP_);
13014   if (xmp_ != NULL) {
13015     GstBuffer *buf;
13016     GstTagList *xmptaglist;
13017 
13018     buf = _gst_buffer_new_wrapped (((guint8 *) xmp_->data) + 8,
13019         QT_UINT32 ((guint8 *) xmp_->data) - 8, NULL);
13020     xmptaglist = gst_tag_list_from_xmp_buffer (buf);
13021     gst_buffer_unref (buf);
13022 
13023     qtdemux_handle_xmp_taglist (qtdemux, taglist, xmptaglist);
13024   } else {
13025     GST_DEBUG_OBJECT (qtdemux, "No XMP_ node found");
13026   }
13027 #endif // GSTREAMER_LITE
13028 }
13029 
13030 typedef struct
13031 {
13032   GstStructure *structure;      /* helper for sort function */
13033   gchar *location;
13034   guint min_req_bitrate;
13035   guint min_req_qt_version;
13036 } GstQtReference;
13037 
13038 static gint
13039 qtdemux_redirects_sort_func (gconstpointer a, gconstpointer b)
13040 {
13041   GstQtReference *ref_a = (GstQtReference *) a;
13042   GstQtReference *ref_b = (GstQtReference *) b;
13043 
13044   if (ref_b->min_req_qt_version != ref_a->min_req_qt_version)
13045     return ref_b->min_req_qt_version - ref_a->min_req_qt_version;
13046 
13047   /* known bitrates go before unknown; higher bitrates go first */
13048   return ref_b->min_req_bitrate - ref_a->min_req_bitrate;
13049 }
13050 
13051 /* sort the redirects and post a message for the application.
13052  */
13053 static void
13054 qtdemux_process_redirects (GstQTDemux * qtdemux, GList * references)
13055 {
13056   GstQtReference *best;
13057   GstStructure *s;
13058   GstMessage *msg;
13059   GValue list_val = { 0, };
13060   GList *l;
13061 
13062   g_assert (references != NULL);
13063 
13064   references = g_list_sort (references, qtdemux_redirects_sort_func);
13065 
13066   best = (GstQtReference *) references->data;
13067 
13068   g_value_init (&list_val, GST_TYPE_LIST);
13069 
13070   for (l = references; l != NULL; l = l->next) {
13071     GstQtReference *ref = (GstQtReference *) l->data;
13072     GValue struct_val = { 0, };
13073 
13074     ref->structure = gst_structure_new ("redirect",
13075         "new-location", G_TYPE_STRING, ref->location, NULL);
13076 
13077     if (ref->min_req_bitrate > 0) {
13078       gst_structure_set (ref->structure, "minimum-bitrate", G_TYPE_INT,
13079           ref->min_req_bitrate, NULL);
13080     }
13081 
13082     g_value_init (&struct_val, GST_TYPE_STRUCTURE);
13083     g_value_set_boxed (&struct_val, ref->structure);
13084     gst_value_list_append_value (&list_val, &struct_val);
13085     g_value_unset (&struct_val);
13086     /* don't free anything here yet, since we need best->structure below */
13087   }
13088 
13089   g_assert (best != NULL);
13090   s = gst_structure_copy (best->structure);
13091 
13092   if (g_list_length (references) > 1) {
13093     gst_structure_set_value (s, "locations", &list_val);
13094   }
13095 
13096   g_value_unset (&list_val);
13097 
13098   for (l = references; l != NULL; l = l->next) {
13099     GstQtReference *ref = (GstQtReference *) l->data;
13100 
13101     gst_structure_free (ref->structure);
13102     g_free (ref->location);
13103     g_free (ref);
13104   }
13105   g_list_free (references);
13106 
13107   GST_INFO_OBJECT (qtdemux, "posting redirect message: %" GST_PTR_FORMAT, s);
13108   msg = gst_message_new_element (GST_OBJECT_CAST (qtdemux), s);
13109   gst_element_post_message (GST_ELEMENT_CAST (qtdemux), msg);
13110   qtdemux->posted_redirect = TRUE;
13111 }
13112 
13113 /* look for redirect nodes, collect all redirect information and
13114  * process it.
13115  */
13116 static gboolean
13117 qtdemux_parse_redirects (GstQTDemux * qtdemux)
13118 {
13119   GNode *rmra, *rmda, *rdrf;
13120 
13121   rmra = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_rmra);
13122   if (rmra) {
13123     GList *redirects = NULL;
13124 
13125     rmda = qtdemux_tree_get_child_by_type (rmra, FOURCC_rmda);
13126     while (rmda) {
13127       GstQtReference ref = { NULL, NULL, 0, 0 };
13128       GNode *rmdr, *rmvc;
13129 
13130       if ((rmdr = qtdemux_tree_get_child_by_type (rmda, FOURCC_rmdr))) {
13131         ref.min_req_bitrate = QT_UINT32 ((guint8 *) rmdr->data + 12);
13132         GST_LOG_OBJECT (qtdemux, "data rate atom, required bitrate = %u",
13133             ref.min_req_bitrate);
13134       }
13135 
13136       if ((rmvc = qtdemux_tree_get_child_by_type (rmda, FOURCC_rmvc))) {
13137         guint32 package = QT_FOURCC ((guint8 *) rmvc->data + 12);
13138         guint version = QT_UINT32 ((guint8 *) rmvc->data + 16);
13139 
13140 #ifndef GST_DISABLE_GST_DEBUG
13141         guint bitmask = QT_UINT32 ((guint8 *) rmvc->data + 20);
13142 #endif
13143         guint check_type = QT_UINT16 ((guint8 *) rmvc->data + 24);
13144 
13145         GST_LOG_OBJECT (qtdemux,
13146             "version check atom [%" GST_FOURCC_FORMAT "], version=0x%08x"
13147             ", mask=%08x, check_type=%u", GST_FOURCC_ARGS (package), version,
13148             bitmask, check_type);
13149         if (package == FOURCC_qtim && check_type == 0) {
13150           ref.min_req_qt_version = version;
13151         }
13152       }
13153 
13154       rdrf = qtdemux_tree_get_child_by_type (rmda, FOURCC_rdrf);
13155       if (rdrf) {
13156         guint32 ref_type;
13157         guint8 *ref_data;
13158         guint ref_len;
13159 
13160         ref_len = QT_UINT32 ((guint8 *) rdrf->data);
13161         if (ref_len > 20) {
13162         ref_type = QT_FOURCC ((guint8 *) rdrf->data + 12);
13163         ref_data = (guint8 *) rdrf->data + 20;
13164         if (ref_type == FOURCC_alis) {
13165           guint record_len, record_version, fn_len;
13166 
13167             if (ref_len > 70) {
13168           /* MacOSX alias record, google for alias-layout.txt */
13169           record_len = QT_UINT16 (ref_data + 4);
13170           record_version = QT_UINT16 (ref_data + 4 + 2);
13171           fn_len = QT_UINT8 (ref_data + 50);
13172           if (record_len > 50 && record_version == 2 && fn_len > 0) {
13173             ref.location = g_strndup ((gchar *) ref_data + 51, fn_len);
13174           }
13175             } else {
13176               GST_WARNING_OBJECT (qtdemux, "Invalid rdrf/alis size (%u < 70)",
13177                   ref_len);
13178             }
13179         } else if (ref_type == FOURCC_url_) {
13180             ref.location = g_strndup ((gchar *) ref_data, ref_len - 8);
13181         } else {
13182           GST_DEBUG_OBJECT (qtdemux,
13183               "unknown rdrf reference type %" GST_FOURCC_FORMAT,
13184               GST_FOURCC_ARGS (ref_type));
13185         }
13186         if (ref.location != NULL) {
13187           GST_INFO_OBJECT (qtdemux, "New location: %s", ref.location);
13188             redirects =
13189                 g_list_prepend (redirects, g_memdup (&ref, sizeof (ref)));
13190         } else {
13191           GST_WARNING_OBJECT (qtdemux,
13192               "Failed to extract redirect location from rdrf atom");
13193         }
13194         } else {
13195           GST_WARNING_OBJECT (qtdemux, "Invalid rdrf size (%u < 20)", ref_len);
13196       }
13197       }
13198 
13199       /* look for others */
13200       rmda = qtdemux_tree_get_sibling_by_type (rmda, FOURCC_rmda);
13201     }
13202 
13203     if (redirects != NULL) {
13204       qtdemux_process_redirects (qtdemux, redirects);
13205     }
13206   }
13207   return TRUE;
13208 }
13209 
13210 static GstTagList *
13211 qtdemux_add_container_format (GstQTDemux * qtdemux, GstTagList * tags)
13212 {
13213   const gchar *fmt;
13214 
13215   if (tags == NULL) {
13216     tags = gst_tag_list_new_empty ();
13217     gst_tag_list_set_scope (tags, GST_TAG_SCOPE_GLOBAL);
13218   }
13219 
13220   if (qtdemux->major_brand == FOURCC_mjp2)
13221     fmt = "Motion JPEG 2000";
13222   else if ((qtdemux->major_brand & 0xffff) == FOURCC_3g__)
13223     fmt = "3GP";
13224   else if (qtdemux->major_brand == FOURCC_qt__)
13225     fmt = "Quicktime";
13226   else if (qtdemux->fragmented)
13227     fmt = "ISO fMP4";
13228   else
13229     fmt = "ISO MP4/M4A";
13230 
13231   GST_LOG_OBJECT (qtdemux, "mapped %" GST_FOURCC_FORMAT " to '%s'",
13232       GST_FOURCC_ARGS (qtdemux->major_brand), fmt);
13233 
13234   gst_tag_list_add (tags, GST_TAG_MERGE_REPLACE, GST_TAG_CONTAINER_FORMAT,
13235       fmt, NULL);
13236 
13237   return tags;
13238 }
13239 
13240 /* we have read the complete moov node now.
13241  * This function parses all of the relevant info, creates the traks and
13242  * prepares all data structures for playback
13243  */
13244 static gboolean
13245 qtdemux_parse_tree (GstQTDemux * qtdemux)
13246 {
13247   GNode *mvhd;
13248   GNode *trak;
13249   GNode *udta;
13250   GNode *mvex;
13251   GstClockTime duration;
13252   GNode *pssh;
13253   guint64 creation_time;
13254   GstDateTime *datetime = NULL;
13255   gint version;
13256 
13257   /* make sure we have a usable taglist */
13258     qtdemux->tag_list = gst_tag_list_make_writable (qtdemux->tag_list);
13259 
13260   mvhd = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_mvhd);
13261   if (mvhd == NULL) {
13262     GST_LOG_OBJECT (qtdemux, "No mvhd node found, looking for redirects.");
13263     return qtdemux_parse_redirects (qtdemux);
13264   }
13265 
13266   version = QT_UINT8 ((guint8 *) mvhd->data + 8);
13267   if (version == 1) {
13268     creation_time = QT_UINT64 ((guint8 *) mvhd->data + 12);
13269     qtdemux->timescale = QT_UINT32 ((guint8 *) mvhd->data + 28);
13270     qtdemux->duration = QT_UINT64 ((guint8 *) mvhd->data + 32);
13271   } else if (version == 0) {
13272     creation_time = QT_UINT32 ((guint8 *) mvhd->data + 12);
13273     qtdemux->timescale = QT_UINT32 ((guint8 *) mvhd->data + 20);
13274     qtdemux->duration = QT_UINT32 ((guint8 *) mvhd->data + 24);
13275   } else {
13276     GST_WARNING_OBJECT (qtdemux, "Unhandled mvhd version %d", version);
13277     return FALSE;
13278   }
13279 
13280   /* Moving qt creation time (secs since 1904) to unix time */
13281   if (creation_time != 0) {
13282     /* Try to use epoch first as it should be faster and more commonly found */
13283     if (creation_time >= QTDEMUX_SECONDS_FROM_1904_TO_1970) {
13284       GTimeVal now;
13285 
13286       creation_time -= QTDEMUX_SECONDS_FROM_1904_TO_1970;
13287       /* some data cleansing sanity */
13288       g_get_current_time (&now);
13289       if (now.tv_sec + 24 * 3600 < creation_time) {
13290         GST_DEBUG_OBJECT (qtdemux, "discarding bogus future creation time");
13291     } else {
13292         datetime = gst_date_time_new_from_unix_epoch_utc (creation_time);
13293     }
13294     } else {
13295       GDateTime *base_dt = g_date_time_new_utc (1904, 1, 1, 0, 0, 0);
13296       GDateTime *dt, *dt_local;
13297 
13298       dt = g_date_time_add_seconds (base_dt, creation_time);
13299       dt_local = g_date_time_to_local (dt);
13300       datetime = gst_date_time_new_from_g_date_time (dt_local);
13301 
13302       g_date_time_unref (base_dt);
13303       g_date_time_unref (dt);
13304   }
13305   }
13306   if (datetime) {
13307     /* Use KEEP as explicit tags should have a higher priority than mvhd tag */
13308     gst_tag_list_add (qtdemux->tag_list, GST_TAG_MERGE_KEEP, GST_TAG_DATE_TIME,
13309         datetime, NULL);
13310     gst_date_time_unref (datetime);
13311   }
13312 
13313   GST_INFO_OBJECT (qtdemux, "timescale: %u", qtdemux->timescale);
13314   GST_INFO_OBJECT (qtdemux, "duration: %" G_GUINT64_FORMAT, qtdemux->duration);
13315 
13316   /* check for fragmented file and get some (default) data */
13317   mvex = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_mvex);
13318   if (mvex) {
13319     GNode *mehd;
13320     GstByteReader mehd_data;
13321 
13322     /* let track parsing or anyone know weird stuff might happen ... */
13323     qtdemux->fragmented = TRUE;
13324 
13325     /* compensate for total duration */
13326     mehd = qtdemux_tree_get_child_by_type_full (mvex, FOURCC_mehd, &mehd_data);
13327     if (mehd)
13328       qtdemux_parse_mehd (qtdemux, &mehd_data);
13329   }
13330 
13331   /* set duration in the segment info */
13332   gst_qtdemux_get_duration (qtdemux, &duration);
13333   if (duration) {
13334     qtdemux->segment.duration = duration;
13335     /* also do not exceed duration; stop is set that way post seek anyway,
13336      * and segment activation falls back to duration,
13337      * whereas loop only checks stop, so let's align this here as well */
13338     qtdemux->segment.stop = duration;
13339   }
13340 
13341   /* parse all traks */
13342   trak = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_trak);
13343   while (trak) {
13344 #ifdef GSTREAMER_LITE
13345       if (!qtdemux_parse_trak (qtdemux, trak))
13346         return FALSE;
13347 #else
13348     qtdemux_parse_trak (qtdemux, trak);
13349 #endif // GSTREAMER_LITE
13350     /* iterate all siblings */
13351     trak = qtdemux_tree_get_sibling_by_type (trak, FOURCC_trak);
13352   }
13353 
13354   qtdemux->tag_list = gst_tag_list_make_writable (qtdemux->tag_list);
13355 
13356   /* find tags */
13357   udta = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_udta);
13358   if (udta) {
13359     qtdemux_parse_udta (qtdemux, qtdemux->tag_list, udta);
13360   } else {
13361     GST_LOG_OBJECT (qtdemux, "No udta node found.");
13362   }
13363 
13364   /* maybe also some tags in meta box */
13365   udta = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_meta);
13366   if (udta) {
13367     GST_DEBUG_OBJECT (qtdemux, "Parsing meta box for tags.");
13368     qtdemux_parse_udta (qtdemux, qtdemux->tag_list, udta);
13369   } else {
13370     GST_LOG_OBJECT (qtdemux, "No meta node found.");
13371   }
13372 
13373   /* parse any protection system info */
13374   pssh = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_pssh);
13375   while (pssh) {
13376     GST_LOG_OBJECT (qtdemux, "Parsing pssh box.");
13377     qtdemux_parse_pssh (qtdemux, pssh);
13378     pssh = qtdemux_tree_get_sibling_by_type (pssh, FOURCC_pssh);
13379   }
13380 
13381   qtdemux->tag_list = qtdemux_add_container_format (qtdemux, qtdemux->tag_list);
13382 
13383   return TRUE;
13384 }
13385 
13386 /* taken from ffmpeg */
13387 static int
13388 read_descr_size (guint8 * ptr, guint8 * end, guint8 ** end_out)
13389 {
13390   int count = 4;
13391   int len = 0;
13392 
13393   while (count--) {
13394     int c;
13395 
13396     if (ptr >= end)
13397       return -1;
13398 
13399     c = *ptr++;
13400     len = (len << 7) | (c & 0x7f);
13401     if (!(c & 0x80))
13402       break;
13403   }
13404   *end_out = ptr;
13405   return len;
13406 }
13407 
13408 /* this can change the codec originally present in @list */
13409 #ifdef GSTREAMER_LITE
13410 static gboolean
13411 #else
13412 static void
13413 #endif // GSTREAMER_LITE
13414 gst_qtdemux_handle_esds (GstQTDemux * qtdemux, QtDemuxStream * stream,
13415     QtDemuxStreamStsdEntry * entry, GNode * esds, GstTagList * list)
13416 {
13417   int len = QT_UINT32 (esds->data);
13418   guint8 *ptr = esds->data;
13419   guint8 *end = ptr + len;
13420   int tag;
13421   guint8 *data_ptr = NULL;
13422   int data_len = 0;
13423   guint8 object_type_id = 0;
13424   const char *codec_name = NULL;
13425   GstCaps *caps = NULL;
13426 
13427   GST_MEMDUMP_OBJECT (qtdemux, "esds", ptr, len);
13428   ptr += 8;
13429   GST_DEBUG_OBJECT (qtdemux, "version/flags = %08x", QT_UINT32 (ptr));
13430   ptr += 4;
13431   while (ptr + 1 < end) {
13432     tag = QT_UINT8 (ptr);
13433     GST_DEBUG_OBJECT (qtdemux, "tag = %02x", tag);
13434     ptr++;
13435     len = read_descr_size (ptr, end, &ptr);
13436     GST_DEBUG_OBJECT (qtdemux, "len = %d", len);
13437 
13438     /* Check the stated amount of data is available for reading */
13439     if (len < 0 || ptr + len > end)
13440       break;
13441 
13442     switch (tag) {
13443       case ES_DESCRIPTOR_TAG:
13444         GST_DEBUG_OBJECT (qtdemux, "ID %04x", QT_UINT16 (ptr));
13445         GST_DEBUG_OBJECT (qtdemux, "priority %04x", QT_UINT8 (ptr + 2));
13446         ptr += 3;
13447         break;
13448       case DECODER_CONFIG_DESC_TAG:{
13449         guint max_bitrate, avg_bitrate;
13450 
13451         object_type_id = QT_UINT8 (ptr);
13452         max_bitrate = QT_UINT32 (ptr + 5);
13453         avg_bitrate = QT_UINT32 (ptr + 9);
13454         GST_DEBUG_OBJECT (qtdemux, "object_type_id %02x", object_type_id);
13455         GST_DEBUG_OBJECT (qtdemux, "stream_type %02x", QT_UINT8 (ptr + 1));
13456         GST_DEBUG_OBJECT (qtdemux, "buffer_size_db %02x", QT_UINT24 (ptr + 2));
13457         GST_DEBUG_OBJECT (qtdemux, "max bitrate %u", max_bitrate);
13458         GST_DEBUG_OBJECT (qtdemux, "avg bitrate %u", avg_bitrate);
13459         if (max_bitrate > 0 && max_bitrate < G_MAXUINT32) {
13460           gst_tag_list_add (list, GST_TAG_MERGE_REPLACE,
13461               GST_TAG_MAXIMUM_BITRATE, max_bitrate, NULL);
13462         }
13463         if (avg_bitrate > 0 && avg_bitrate < G_MAXUINT32) {
13464           gst_tag_list_add (list, GST_TAG_MERGE_REPLACE, GST_TAG_BITRATE,
13465               avg_bitrate, NULL);
13466         }
13467         ptr += 13;
13468         break;
13469       }
13470       case DECODER_SPECIFIC_INFO_TAG:
13471         GST_MEMDUMP_OBJECT (qtdemux, "data", ptr, len);
13472 #ifdef GSTREAMER_LITE
13473         if (end - len < ptr)
13474             return FALSE;
13475 #endif // GSTREAMER_LITE
13476         if (object_type_id == 0xe0 && len == 0x40) {
13477           guint8 *data;
13478           GstStructure *s;
13479           guint32 clut[16];
13480           gint i;
13481 
13482           GST_DEBUG_OBJECT (qtdemux,
13483               "Have VOBSUB palette. Creating palette event");
13484           /* move to decConfigDescr data and read palette */
13485           data = ptr;
13486           for (i = 0; i < 16; i++) {
13487             clut[i] = QT_UINT32 (data);
13488             data += 4;
13489           }
13490 
13491           s = gst_structure_new ("application/x-gst-dvd", "event",
13492               G_TYPE_STRING, "dvd-spu-clut-change",
13493               "clut00", G_TYPE_INT, clut[0], "clut01", G_TYPE_INT, clut[1],
13494               "clut02", G_TYPE_INT, clut[2], "clut03", G_TYPE_INT, clut[3],
13495               "clut04", G_TYPE_INT, clut[4], "clut05", G_TYPE_INT, clut[5],
13496               "clut06", G_TYPE_INT, clut[6], "clut07", G_TYPE_INT, clut[7],
13497               "clut08", G_TYPE_INT, clut[8], "clut09", G_TYPE_INT, clut[9],
13498               "clut10", G_TYPE_INT, clut[10], "clut11", G_TYPE_INT, clut[11],
13499               "clut12", G_TYPE_INT, clut[12], "clut13", G_TYPE_INT, clut[13],
13500               "clut14", G_TYPE_INT, clut[14], "clut15", G_TYPE_INT, clut[15],
13501               NULL);
13502 
13503           /* store event and trigger custom processing */
13504           stream->pending_event =
13505               gst_event_new_custom (GST_EVENT_CUSTOM_DOWNSTREAM, s);
13506         } else {
13507           /* Generic codec_data handler puts it on the caps */
13508           data_ptr = ptr;
13509           data_len = len;
13510         }
13511 
13512         ptr += len;
13513         break;
13514       case SL_CONFIG_DESC_TAG:
13515         GST_DEBUG_OBJECT (qtdemux, "data %02x", QT_UINT8 (ptr));
13516         ptr += 1;
13517         break;
13518       default:
13519         GST_DEBUG_OBJECT (qtdemux, "Unknown/unhandled descriptor tag %02x",
13520             tag);
13521         GST_MEMDUMP_OBJECT (qtdemux, "descriptor data", ptr, len);
13522         ptr += len;
13523         break;
13524     }
13525   }
13526 
13527   /* object_type_id in the esds atom in mp4a and mp4v tells us which codec is
13528    * in use, and should also be used to override some other parameters for some
13529    * codecs. */
13530   switch (object_type_id) {
13531     case 0x20:                 /* MPEG-4 */
13532       /* 4 bytes for the visual_object_sequence_start_code and 1 byte for the
13533        * profile_and_level_indication */
13534       if (data_ptr != NULL && data_len >= 5 &&
13535           GST_READ_UINT32_BE (data_ptr) == 0x000001b0) {
13536         gst_codec_utils_mpeg4video_caps_set_level_and_profile (entry->caps,
13537             data_ptr + 4, data_len - 4);
13538       }
13539       break;                    /* Nothing special needed here */
13540     case 0x21:                 /* H.264 */
13541       codec_name = "H.264 / AVC";
13542       caps = gst_caps_new_simple ("video/x-h264",
13543           "stream-format", G_TYPE_STRING, "avc",
13544           "alignment", G_TYPE_STRING, "au", NULL);
13545       break;
13546     case 0x40:                 /* AAC (any) */
13547     case 0x66:                 /* AAC Main */
13548     case 0x67:                 /* AAC LC */
13549     case 0x68:                 /* AAC SSR */
13550       /* Override channels and rate based on the codec_data, as it's often
13551        * wrong. */
13552       /* Only do so for basic setup without HE-AAC extension */
13553       if (data_ptr && data_len == 2) {
13554         guint channels, rate;
13555 
13556         channels = gst_codec_utils_aac_get_channels (data_ptr, data_len);
13557         if (channels > 0)
13558           entry->n_channels = channels;
13559 
13560         rate = gst_codec_utils_aac_get_sample_rate (data_ptr, data_len);
13561         if (rate > 0)
13562           entry->rate = rate;
13563       }
13564 
13565       /* Set level and profile if possible */
13566       if (data_ptr != NULL && data_len >= 2) {
13567         gst_codec_utils_aac_caps_set_level_and_profile (entry->caps,
13568             data_ptr, data_len);
13569       } else {
13570         const gchar *profile_str = NULL;
13571         GstBuffer *buffer;
13572         GstMapInfo map;
13573         guint8 *codec_data;
13574         gint rate_idx, profile;
13575 
13576         /* No codec_data, let's invent something.
13577          * FIXME: This is wrong for SBR! */
13578 
13579         GST_WARNING_OBJECT (qtdemux, "No codec_data for AAC available");
13580 
13581         buffer = gst_buffer_new_and_alloc (2);
13582         gst_buffer_map (buffer, &map, GST_MAP_WRITE);
13583         codec_data = map.data;
13584 
13585         rate_idx =
13586             gst_codec_utils_aac_get_index_from_sample_rate (CUR_STREAM
13587             (stream)->rate);
13588 
13589         switch (object_type_id) {
13590           case 0x66:
13591             profile_str = "main";
13592             profile = 0;
13593             break;
13594           case 0x67:
13595             profile_str = "lc";
13596             profile = 1;
13597             break;
13598           case 0x68:
13599             profile_str = "ssr";
13600             profile = 2;
13601             break;
13602           default:
13603             profile = 3;
13604             break;
13605       }
13606 
13607         codec_data[0] = ((profile + 1) << 3) | ((rate_idx & 0xE) >> 1);
13608         codec_data[1] =
13609             ((rate_idx & 0x1) << 7) | (CUR_STREAM (stream)->n_channels << 3);
13610 
13611         gst_buffer_unmap (buffer, &map);
13612         gst_caps_set_simple (CUR_STREAM (stream)->caps, "codec_data",
13613             GST_TYPE_BUFFER, buffer, NULL);
13614         gst_buffer_unref (buffer);
13615 
13616         if (profile_str) {
13617           gst_caps_set_simple (CUR_STREAM (stream)->caps, "profile",
13618               G_TYPE_STRING, profile_str, NULL);
13619         }
13620       }
13621       break;
13622     case 0x60:                 /* MPEG-2, various profiles */
13623     case 0x61:
13624     case 0x62:
13625     case 0x63:
13626     case 0x64:
13627     case 0x65:
13628       codec_name = "MPEG-2 video";
13629       caps = gst_caps_new_simple ("video/mpeg",
13630           "mpegversion", G_TYPE_INT, 2,
13631           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
13632       break;
13633     case 0x69:                 /* MPEG-2 BC audio */
13634     case 0x6B:                 /* MPEG-1 audio */
13635       caps = gst_caps_new_simple ("audio/mpeg",
13636           "mpegversion", G_TYPE_INT, 1, NULL);
13637       codec_name = "MPEG-1 audio";
13638       break;
13639     case 0x6A:                 /* MPEG-1 */
13640       codec_name = "MPEG-1 video";
13641       caps = gst_caps_new_simple ("video/mpeg",
13642           "mpegversion", G_TYPE_INT, 1,
13643           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
13644       break;
13645     case 0x6C:                 /* MJPEG */
13646       caps =
13647           gst_caps_new_simple ("image/jpeg", "parsed", G_TYPE_BOOLEAN, TRUE,
13648           NULL);
13649       codec_name = "Motion-JPEG";
13650       break;
13651     case 0x6D:                 /* PNG */
13652       caps =
13653           gst_caps_new_simple ("image/png", "parsed", G_TYPE_BOOLEAN, TRUE,
13654           NULL);
13655       codec_name = "PNG still images";
13656       break;
13657     case 0x6E:                 /* JPEG2000 */
13658       codec_name = "JPEG-2000";
13659       caps = gst_caps_new_simple ("image/x-j2c", "fields", G_TYPE_INT, 1, NULL);
13660       break;
13661     case 0xA4:                 /* Dirac */
13662       codec_name = "Dirac";
13663       caps = gst_caps_new_empty_simple ("video/x-dirac");
13664       break;
13665     case 0xA5:                 /* AC3 */
13666       codec_name = "AC-3 audio";
13667       caps = gst_caps_new_simple ("audio/x-ac3",
13668           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
13669       break;
13670     case 0xA9:                 /* AC3 */
13671       codec_name = "DTS audio";
13672       caps = gst_caps_new_simple ("audio/x-dts",
13673           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
13674       break;
13675     case 0xE1:                 /* QCELP */
13676       /* QCELP, the codec_data is a riff tag (little endian) with
13677        * 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). */
13678       caps = gst_caps_new_empty_simple ("audio/qcelp");
13679       codec_name = "QCELP";
13680       break;
13681     default:
13682       break;
13683   }
13684 
13685   /* If we have a replacement caps, then change our caps for this stream */
13686   if (caps) {
13687     gst_caps_unref (entry->caps);
13688     entry->caps = caps;
13689   }
13690 
13691   if (codec_name && list)
13692     gst_tag_list_add (list, GST_TAG_MERGE_REPLACE,
13693         GST_TAG_AUDIO_CODEC, codec_name, NULL);
13694 
13695   /* Add the codec_data attribute to caps, if we have it */
13696   if (data_ptr) {
13697     GstBuffer *buffer;
13698 
13699     buffer = gst_buffer_new_and_alloc (data_len);
13700     gst_buffer_fill (buffer, 0, data_ptr, data_len);
13701 
13702     GST_DEBUG_OBJECT (qtdemux, "setting codec_data from esds");
13703     GST_MEMDUMP_OBJECT (qtdemux, "codec_data from esds", data_ptr, data_len);
13704 
13705     gst_caps_set_simple (entry->caps, "codec_data", GST_TYPE_BUFFER,
13706         buffer, NULL);
13707     gst_buffer_unref (buffer);
13708 
13709 #if defined(GSTREAMER_LITE) && defined(OSX)
13710       switch (object_type_id) {
13711           case 0x40:                 /* AAC (any) */
13712           case 0x66:                 /* AAC Main */
13713           case 0x67:                 /* AAC LC */
13714           case 0x68:                 /* AAC SSR */
13715           {
13716               GstMapInfo info;
13717               int esds_len = QT_UINT32 (esds->data);
13718               GstBuffer* esds_buffer = gst_buffer_new_allocate (NULL, esds_len, NULL);
13719               if (esds_buffer)
13720               {
13721                   if (gst_buffer_map(esds_buffer, &info, GST_MAP_WRITE))
13722                   {
13723                       memcpy (info.data, esds->data, esds_len);
13724                       gst_buffer_unmap(esds_buffer, &info);
13725 
13726                       GST_DEBUG_OBJECT (qtdemux, "setting esds_data from esds");
13727                       GST_MEMDUMP_OBJECT (qtdemux, "esds_data from esds", esds->data, esds_len);
13728 
13729                       gst_caps_set_simple (entry->caps, "esds_data", GST_TYPE_BUFFER,
13730                                    esds_buffer, NULL);
13731                   }
13732 
13733                   gst_buffer_unref (esds_buffer);
13734               }
13735           }
13736               break;
13737           default:
13738               break;
13739       }
13740 #endif
13741 
13742   }
13743 
13744 #ifdef GSTREAMER_LITE
13745     return TRUE;
13746 #endif
13747 }
13748 
13749 static inline GstCaps *
13750 _get_unknown_codec_name (const gchar * type, guint32 fourcc)
13751 {
13752   GstCaps *caps;
13753   guint i;
13754   char *s, fourstr[5];
13755 
13756   g_snprintf (fourstr, 5, "%" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (fourcc));
13757   for (i = 0; i < 4; i++) {
13758     if (!g_ascii_isalnum (fourstr[i]))
13759       fourstr[i] = '_';
13760   }
13761   s = g_strdup_printf ("%s/x-gst-fourcc-%s", type, g_strstrip (fourstr));
13762   caps = gst_caps_new_empty_simple (s);
13763   g_free (s);
13764   return caps;
13765 }
13766 
13767 #define _codec(name) \
13768   do { \
13769     if (codec_name) { \
13770       *codec_name = g_strdup (name); \
13771     } \
13772   } while (0)
13773 
13774 static GstCaps *
13775 qtdemux_video_caps (GstQTDemux * qtdemux, QtDemuxStream * stream,
13776     QtDemuxStreamStsdEntry * entry, guint32 fourcc,
13777     const guint8 * stsd_entry_data, gchar ** codec_name)
13778 {
13779   GstCaps *caps = NULL;
13780   GstVideoFormat format = GST_VIDEO_FORMAT_UNKNOWN;
13781 
13782   switch (fourcc) {
13783     case FOURCC_png:
13784       _codec ("PNG still images");
13785       caps = gst_caps_new_empty_simple ("image/png");
13786       break;
13787     case FOURCC_jpeg:
13788       _codec ("JPEG still images");
13789       caps =
13790           gst_caps_new_simple ("image/jpeg", "parsed", G_TYPE_BOOLEAN, TRUE,
13791           NULL);
13792       break;
13793     case GST_MAKE_FOURCC ('m', 'j', 'p', 'a'):
13794     case GST_MAKE_FOURCC ('A', 'V', 'D', 'J'):
13795     case GST_MAKE_FOURCC ('M', 'J', 'P', 'G'):
13796     case GST_MAKE_FOURCC ('d', 'm', 'b', '1'):
13797       _codec ("Motion-JPEG");
13798       caps =
13799           gst_caps_new_simple ("image/jpeg", "parsed", G_TYPE_BOOLEAN, TRUE,
13800           NULL);
13801       break;
13802     case GST_MAKE_FOURCC ('m', 'j', 'p', 'b'):
13803       _codec ("Motion-JPEG format B");
13804       caps = gst_caps_new_empty_simple ("video/x-mjpeg-b");
13805       break;
13806     case FOURCC_mjp2:
13807       _codec ("JPEG-2000");
13808       /* override to what it should be according to spec, avoid palette_data */
13809       entry->bits_per_sample = 24;
13810       caps = gst_caps_new_simple ("image/x-j2c", "fields", G_TYPE_INT, 1, NULL);
13811       break;
13812     case FOURCC_SVQ3:
13813       _codec ("Sorensen video v.3");
13814       caps = gst_caps_new_simple ("video/x-svq",
13815           "svqversion", G_TYPE_INT, 3, NULL);
13816       break;
13817     case GST_MAKE_FOURCC ('s', 'v', 'q', 'i'):
13818     case GST_MAKE_FOURCC ('S', 'V', 'Q', '1'):
13819       _codec ("Sorensen video v.1");
13820       caps = gst_caps_new_simple ("video/x-svq",
13821           "svqversion", G_TYPE_INT, 1, NULL);
13822       break;
13823     case GST_MAKE_FOURCC ('W', 'R', 'A', 'W'):
13824       caps = gst_caps_new_empty_simple ("video/x-raw");
13825       gst_caps_set_simple (caps, "format", G_TYPE_STRING, "RGB8P", NULL);
13826       _codec ("Windows Raw RGB");
13827       stream->alignment = 32;
13828       break;
13829     case FOURCC_raw_:
13830     {
13831       guint16 bps;
13832 
13833       bps = QT_UINT16 (stsd_entry_data + 82);
13834       switch (bps) {
13835         case 15:
13836           format = GST_VIDEO_FORMAT_RGB15;
13837           break;
13838         case 16:
13839           format = GST_VIDEO_FORMAT_RGB16;
13840           break;
13841         case 24:
13842           format = GST_VIDEO_FORMAT_RGB;
13843           break;
13844         case 32:
13845           format = GST_VIDEO_FORMAT_ARGB;
13846           break;
13847         default:
13848           /* unknown */
13849           break;
13850       }
13851       break;
13852     }
13853     case GST_MAKE_FOURCC ('y', 'v', '1', '2'):
13854       format = GST_VIDEO_FORMAT_I420;
13855       break;
13856     case GST_MAKE_FOURCC ('y', 'u', 'v', '2'):
13857     case GST_MAKE_FOURCC ('Y', 'u', 'v', '2'):
13858       format = GST_VIDEO_FORMAT_I420;
13859       break;
13860     case FOURCC_2vuy:
13861     case GST_MAKE_FOURCC ('2', 'V', 'u', 'y'):
13862       format = GST_VIDEO_FORMAT_UYVY;
13863       break;
13864     case GST_MAKE_FOURCC ('v', '3', '0', '8'):
13865       format = GST_VIDEO_FORMAT_v308;
13866       break;
13867     case GST_MAKE_FOURCC ('v', '2', '1', '6'):
13868       format = GST_VIDEO_FORMAT_v216;
13869       break;
13870     case FOURCC_v210:
13871       format = GST_VIDEO_FORMAT_v210;
13872       break;
13873     case GST_MAKE_FOURCC ('r', '2', '1', '0'):
13874       format = GST_VIDEO_FORMAT_r210;
13875       break;
13876       /* Packed YUV 4:4:4 10 bit in 32 bits, complex
13877          case GST_MAKE_FOURCC ('v', '4', '1', '0'):
13878          format = GST_VIDEO_FORMAT_v410;
13879          break;
13880        */
13881       /* Packed YUV 4:4:4:4 8 bit in 32 bits
13882        * but different order than AYUV
13883        case GST_MAKE_FOURCC ('v', '4', '0', '8'):
13884        format = GST_VIDEO_FORMAT_v408;
13885        break;
13886        */
13887     case GST_MAKE_FOURCC ('m', 'p', 'e', 'g'):
13888     case GST_MAKE_FOURCC ('m', 'p', 'g', '1'):
13889       _codec ("MPEG-1 video");
13890       caps = gst_caps_new_simple ("video/mpeg", "mpegversion", G_TYPE_INT, 1,
13891           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
13892       break;
13893     case GST_MAKE_FOURCC ('h', 'd', 'v', '1'): /* HDV 720p30 */
13894     case GST_MAKE_FOURCC ('h', 'd', 'v', '2'): /* HDV 1080i60 */
13895     case GST_MAKE_FOURCC ('h', 'd', 'v', '3'): /* HDV 1080i50 */
13896     case GST_MAKE_FOURCC ('h', 'd', 'v', '4'): /* HDV 720p24 */
13897     case GST_MAKE_FOURCC ('h', 'd', 'v', '5'): /* HDV 720p25 */
13898     case GST_MAKE_FOURCC ('h', 'd', 'v', '6'): /* HDV 1080p24 */
13899     case GST_MAKE_FOURCC ('h', 'd', 'v', '7'): /* HDV 1080p25 */
13900     case GST_MAKE_FOURCC ('h', 'd', 'v', '8'): /* HDV 1080p30 */
13901     case GST_MAKE_FOURCC ('h', 'd', 'v', '9'): /* HDV 720p60 */
13902     case GST_MAKE_FOURCC ('h', 'd', 'v', 'a'): /* HDV 720p50 */
13903     case GST_MAKE_FOURCC ('m', 'x', '5', 'n'): /* MPEG2 IMX NTSC 525/60 50mb/s produced by FCP */
13904     case GST_MAKE_FOURCC ('m', 'x', '5', 'p'): /* MPEG2 IMX PAL 625/60 50mb/s produced by FCP */
13905     case GST_MAKE_FOURCC ('m', 'x', '4', 'n'): /* MPEG2 IMX NTSC 525/60 40mb/s produced by FCP */
13906     case GST_MAKE_FOURCC ('m', 'x', '4', 'p'): /* MPEG2 IMX PAL 625/60 40mb/s produced by FCP */
13907     case GST_MAKE_FOURCC ('m', 'x', '3', 'n'): /* MPEG2 IMX NTSC 525/60 30mb/s produced by FCP */
13908     case GST_MAKE_FOURCC ('m', 'x', '3', 'p'): /* MPEG2 IMX PAL 625/50 30mb/s produced by FCP */
13909     case GST_MAKE_FOURCC ('x', 'd', 'v', '1'): /* XDCAM HD 720p30 35Mb/s */
13910     case GST_MAKE_FOURCC ('x', 'd', 'v', '2'): /* XDCAM HD 1080i60 35Mb/s */
13911     case GST_MAKE_FOURCC ('x', 'd', 'v', '3'): /* XDCAM HD 1080i50 35Mb/s */
13912     case GST_MAKE_FOURCC ('x', 'd', 'v', '4'): /* XDCAM HD 720p24 35Mb/s */
13913     case GST_MAKE_FOURCC ('x', 'd', 'v', '5'): /* XDCAM HD 720p25 35Mb/s */
13914     case GST_MAKE_FOURCC ('x', 'd', 'v', '6'): /* XDCAM HD 1080p24 35Mb/s */
13915     case GST_MAKE_FOURCC ('x', 'd', 'v', '7'): /* XDCAM HD 1080p25 35Mb/s */
13916     case GST_MAKE_FOURCC ('x', 'd', 'v', '8'): /* XDCAM HD 1080p30 35Mb/s */
13917     case GST_MAKE_FOURCC ('x', 'd', 'v', '9'): /* XDCAM HD 720p60 35Mb/s */
13918     case GST_MAKE_FOURCC ('x', 'd', 'v', 'a'): /* XDCAM HD 720p50 35Mb/s */
13919     case GST_MAKE_FOURCC ('x', 'd', 'v', 'b'): /* XDCAM EX 1080i60 50Mb/s CBR */
13920     case GST_MAKE_FOURCC ('x', 'd', 'v', 'c'): /* XDCAM EX 1080i50 50Mb/s CBR */
13921     case GST_MAKE_FOURCC ('x', 'd', 'v', 'd'): /* XDCAM HD 1080p24 50Mb/s CBR */
13922     case GST_MAKE_FOURCC ('x', 'd', 'v', 'e'): /* XDCAM HD 1080p25 50Mb/s CBR */
13923     case GST_MAKE_FOURCC ('x', 'd', 'v', 'f'): /* XDCAM HD 1080p30 50Mb/s CBR */
13924     case GST_MAKE_FOURCC ('x', 'd', '5', '1'): /* XDCAM HD422 720p30 50Mb/s CBR */
13925     case GST_MAKE_FOURCC ('x', 'd', '5', '4'): /* XDCAM HD422 720p24 50Mb/s CBR */
13926     case GST_MAKE_FOURCC ('x', 'd', '5', '5'): /* XDCAM HD422 720p25 50Mb/s CBR */
13927     case GST_MAKE_FOURCC ('x', 'd', '5', '9'): /* XDCAM HD422 720p60 50Mb/s CBR */
13928     case GST_MAKE_FOURCC ('x', 'd', '5', 'a'): /* XDCAM HD422 720p50 50Mb/s CBR */
13929     case GST_MAKE_FOURCC ('x', 'd', '5', 'b'): /* XDCAM HD422 1080i50 50Mb/s CBR */
13930     case GST_MAKE_FOURCC ('x', 'd', '5', 'c'): /* XDCAM HD422 1080i50 50Mb/s CBR */
13931     case GST_MAKE_FOURCC ('x', 'd', '5', 'd'): /* XDCAM HD422 1080p24 50Mb/s CBR */
13932     case GST_MAKE_FOURCC ('x', 'd', '5', 'e'): /* XDCAM HD422 1080p25 50Mb/s CBR */
13933     case GST_MAKE_FOURCC ('x', 'd', '5', 'f'): /* XDCAM HD422 1080p30 50Mb/s CBR */
13934     case GST_MAKE_FOURCC ('x', 'd', 'h', 'd'): /* XDCAM HD 540p */
13935     case GST_MAKE_FOURCC ('x', 'd', 'h', '2'): /* XDCAM HD422 540p */
13936     case GST_MAKE_FOURCC ('A', 'V', 'm', 'p'): /* AVID IMX PAL */
13937     case GST_MAKE_FOURCC ('m', 'p', 'g', '2'): /* AVID IMX PAL */
13938     case GST_MAKE_FOURCC ('m', 'p', '2', 'v'): /* AVID IMX PAL */
13939     case GST_MAKE_FOURCC ('m', '2', 'v', '1'):
13940       _codec ("MPEG-2 video");
13941       caps = gst_caps_new_simple ("video/mpeg", "mpegversion", G_TYPE_INT, 2,
13942           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
13943       break;
13944     case GST_MAKE_FOURCC ('g', 'i', 'f', ' '):
13945       _codec ("GIF still images");
13946       caps = gst_caps_new_empty_simple ("image/gif");
13947       break;
13948     case FOURCC_h263:
13949     case GST_MAKE_FOURCC ('H', '2', '6', '3'):
13950     case FOURCC_s263:
13951     case GST_MAKE_FOURCC ('U', '2', '6', '3'):
13952       _codec ("H.263");
13953       /* ffmpeg uses the height/width props, don't know why */
13954       caps = gst_caps_new_simple ("video/x-h263",
13955           "variant", G_TYPE_STRING, "itu", NULL);
13956       break;
13957     case FOURCC_mp4v:
13958     case FOURCC_MP4V:
13959       _codec ("MPEG-4 video");
13960       caps = gst_caps_new_simple ("video/mpeg", "mpegversion", G_TYPE_INT, 4,
13961           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
13962       break;
13963     case GST_MAKE_FOURCC ('3', 'i', 'v', 'd'):
13964     case GST_MAKE_FOURCC ('3', 'I', 'V', 'D'):
13965       _codec ("Microsoft MPEG-4 4.3");  /* FIXME? */
13966       caps = gst_caps_new_simple ("video/x-msmpeg",
13967           "msmpegversion", G_TYPE_INT, 43, NULL);
13968       break;
13969     case GST_MAKE_FOURCC ('D', 'I', 'V', '3'):
13970       _codec ("DivX 3");
13971       caps = gst_caps_new_simple ("video/x-divx",
13972           "divxversion", G_TYPE_INT, 3, NULL);
13973       break;
13974     case GST_MAKE_FOURCC ('D', 'I', 'V', 'X'):
13975     case GST_MAKE_FOURCC ('d', 'i', 'v', 'x'):
13976       _codec ("DivX 4");
13977       caps = gst_caps_new_simple ("video/x-divx",
13978           "divxversion", G_TYPE_INT, 4, NULL);
13979       break;
13980     case GST_MAKE_FOURCC ('D', 'X', '5', '0'):
13981       _codec ("DivX 5");
13982       caps = gst_caps_new_simple ("video/x-divx",
13983           "divxversion", G_TYPE_INT, 5, NULL);
13984       break;
13985 
13986     case GST_MAKE_FOURCC ('F', 'F', 'V', '1'):
13987       _codec ("FFV1");
13988       caps = gst_caps_new_simple ("video/x-ffv",
13989           "ffvversion", G_TYPE_INT, 1, NULL);
13990       break;
13991 
13992     case GST_MAKE_FOURCC ('3', 'I', 'V', '1'):
13993     case GST_MAKE_FOURCC ('3', 'I', 'V', '2'):
13994     case FOURCC_XVID:
13995     case FOURCC_xvid:
13996     case FOURCC_FMP4:
13997     case FOURCC_fmp4:
13998     case GST_MAKE_FOURCC ('U', 'M', 'P', '4'):
13999       caps = gst_caps_new_simple ("video/mpeg", "mpegversion", G_TYPE_INT, 4,
14000           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
14001       _codec ("MPEG-4");
14002       break;
14003 
14004     case GST_MAKE_FOURCC ('c', 'v', 'i', 'd'):
14005       _codec ("Cinepak");
14006       caps = gst_caps_new_empty_simple ("video/x-cinepak");
14007       break;
14008     case GST_MAKE_FOURCC ('q', 'd', 'r', 'w'):
14009       _codec ("Apple QuickDraw");
14010       caps = gst_caps_new_empty_simple ("video/x-qdrw");
14011       break;
14012     case GST_MAKE_FOURCC ('r', 'p', 'z', 'a'):
14013       _codec ("Apple video");
14014       caps = gst_caps_new_empty_simple ("video/x-apple-video");
14015       break;
14016     case FOURCC_H264:
14017     case FOURCC_avc1:
14018       _codec ("H.264 / AVC");
14019       caps = gst_caps_new_simple ("video/x-h264",
14020           "stream-format", G_TYPE_STRING, "avc",
14021           "alignment", G_TYPE_STRING, "au", NULL);
14022       break;
14023     case FOURCC_avc3:
14024       _codec ("H.264 / AVC");
14025       caps = gst_caps_new_simple ("video/x-h264",
14026           "stream-format", G_TYPE_STRING, "avc3",
14027           "alignment", G_TYPE_STRING, "au", NULL);
14028       break;
14029     case FOURCC_H265:
14030     case FOURCC_hvc1:
14031       _codec ("H.265 / HEVC");
14032       caps = gst_caps_new_simple ("video/x-h265",
14033           "stream-format", G_TYPE_STRING, "hvc1",
14034           "alignment", G_TYPE_STRING, "au", NULL);
14035       break;
14036     case FOURCC_hev1:
14037       _codec ("H.265 / HEVC");
14038       caps = gst_caps_new_simple ("video/x-h265",
14039           "stream-format", G_TYPE_STRING, "hev1",
14040           "alignment", G_TYPE_STRING, "au", NULL);
14041       break;
14042     case FOURCC_rle_:
14043       _codec ("Run-length encoding");
14044       caps = gst_caps_new_simple ("video/x-rle",
14045           "layout", G_TYPE_STRING, "quicktime", NULL);
14046       break;
14047     case FOURCC_WRLE:
14048       _codec ("Run-length encoding");
14049       caps = gst_caps_new_simple ("video/x-rle",
14050           "layout", G_TYPE_STRING, "microsoft", NULL);
14051       break;
14052     case GST_MAKE_FOURCC ('I', 'V', '3', '2'):
14053     case GST_MAKE_FOURCC ('i', 'v', '3', '2'):
14054       _codec ("Indeo Video 3");
14055       caps = gst_caps_new_simple ("video/x-indeo",
14056           "indeoversion", G_TYPE_INT, 3, NULL);
14057       break;
14058     case GST_MAKE_FOURCC ('I', 'V', '4', '1'):
14059     case GST_MAKE_FOURCC ('i', 'v', '4', '1'):
14060       _codec ("Intel Video 4");
14061       caps = gst_caps_new_simple ("video/x-indeo",
14062           "indeoversion", G_TYPE_INT, 4, NULL);
14063       break;
14064     case FOURCC_dvcp:
14065     case FOURCC_dvc_:
14066     case GST_MAKE_FOURCC ('d', 'v', 's', 'd'):
14067     case GST_MAKE_FOURCC ('D', 'V', 'S', 'D'):
14068     case GST_MAKE_FOURCC ('d', 'v', 'c', 's'):
14069     case GST_MAKE_FOURCC ('D', 'V', 'C', 'S'):
14070     case GST_MAKE_FOURCC ('d', 'v', '2', '5'):
14071     case GST_MAKE_FOURCC ('d', 'v', 'p', 'p'):
14072       _codec ("DV Video");
14073       caps = gst_caps_new_simple ("video/x-dv", "dvversion", G_TYPE_INT, 25,
14074           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
14075       break;
14076     case FOURCC_dv5n:          /* DVCPRO50 NTSC */
14077     case FOURCC_dv5p:          /* DVCPRO50 PAL */
14078       _codec ("DVCPro50 Video");
14079       caps = gst_caps_new_simple ("video/x-dv", "dvversion", G_TYPE_INT, 50,
14080           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
14081       break;
14082     case GST_MAKE_FOURCC ('d', 'v', 'h', '5'): /* DVCPRO HD 50i produced by FCP */
14083     case GST_MAKE_FOURCC ('d', 'v', 'h', '6'): /* DVCPRO HD 60i produced by FCP */
14084       _codec ("DVCProHD Video");
14085       caps = gst_caps_new_simple ("video/x-dv", "dvversion", G_TYPE_INT, 100,
14086           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
14087       break;
14088     case GST_MAKE_FOURCC ('s', 'm', 'c', ' '):
14089       _codec ("Apple Graphics (SMC)");
14090       caps = gst_caps_new_empty_simple ("video/x-smc");
14091       break;
14092     case GST_MAKE_FOURCC ('V', 'P', '3', '1'):
14093       _codec ("VP3");
14094       caps = gst_caps_new_empty_simple ("video/x-vp3");
14095       break;
14096     case GST_MAKE_FOURCC ('V', 'P', '6', 'F'):
14097       _codec ("VP6 Flash");
14098       caps = gst_caps_new_empty_simple ("video/x-vp6-flash");
14099       break;
14100     case FOURCC_XiTh:
14101       _codec ("Theora");
14102       caps = gst_caps_new_empty_simple ("video/x-theora");
14103       /* theora uses one byte of padding in the data stream because it does not
14104        * allow 0 sized packets while theora does */
14105       entry->padding = 1;
14106       break;
14107     case FOURCC_drac:
14108       _codec ("Dirac");
14109       caps = gst_caps_new_empty_simple ("video/x-dirac");
14110       break;
14111     case GST_MAKE_FOURCC ('t', 'i', 'f', 'f'):
14112       _codec ("TIFF still images");
14113       caps = gst_caps_new_empty_simple ("image/tiff");
14114       break;
14115     case GST_MAKE_FOURCC ('i', 'c', 'o', 'd'):
14116       _codec ("Apple Intermediate Codec");
14117       caps = gst_caps_from_string ("video/x-apple-intermediate-codec");
14118       break;
14119     case GST_MAKE_FOURCC ('A', 'V', 'd', 'n'):
14120       _codec ("AVID DNxHD");
14121       caps = gst_caps_from_string ("video/x-dnxhd");
14122       break;
14123     case FOURCC_VP80:
14124     case FOURCC_vp08:
14125       _codec ("On2 VP8");
14126       caps = gst_caps_from_string ("video/x-vp8");
14127       break;
14128     case FOURCC_vp09:
14129       _codec ("Google VP9");
14130       caps = gst_caps_from_string ("video/x-vp9");
14131       break;
14132     case FOURCC_apcs:
14133       _codec ("Apple ProRes LT");
14134       caps =
14135           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING, "lt",
14136           NULL);
14137       break;
14138     case FOURCC_apch:
14139       _codec ("Apple ProRes HQ");
14140       caps =
14141           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING, "hq",
14142           NULL);
14143       break;
14144     case FOURCC_apcn:
14145       _codec ("Apple ProRes");
14146       caps =
14147           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING,
14148           "standard", NULL);
14149       break;
14150     case FOURCC_apco:
14151       _codec ("Apple ProRes Proxy");
14152       caps =
14153           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING,
14154           "proxy", NULL);
14155       break;
14156     case FOURCC_ap4h:
14157       _codec ("Apple ProRes 4444");
14158       caps =
14159           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING,
14160           "4444", NULL);
14161       break;
14162     case FOURCC_ap4x:
14163       _codec ("Apple ProRes 4444 XQ");
14164       caps =
14165           gst_caps_new_simple ("video/x-prores", "variant", G_TYPE_STRING,
14166           "4444xq", NULL);
14167       break;
14168     case FOURCC_cfhd:
14169       _codec ("GoPro CineForm");
14170       caps = gst_caps_from_string ("video/x-cineform");
14171       break;
14172     case FOURCC_vc_1:
14173     case FOURCC_ovc1:
14174       _codec ("VC-1");
14175       caps = gst_caps_new_simple ("video/x-wmv",
14176           "wmvversion", G_TYPE_INT, 3, "format", G_TYPE_STRING, "WVC1", NULL);
14177       break;
14178     case GST_MAKE_FOURCC ('k', 'p', 'c', 'd'):
14179     default:
14180     {
14181       caps = _get_unknown_codec_name ("video", fourcc);
14182       break;
14183     }
14184   }
14185 
14186   if (format != GST_VIDEO_FORMAT_UNKNOWN) {
14187     GstVideoInfo info;
14188 
14189     gst_video_info_init (&info);
14190     gst_video_info_set_format (&info, format, entry->width, entry->height);
14191 
14192     caps = gst_video_info_to_caps (&info);
14193     *codec_name = gst_pb_utils_get_codec_description (caps);
14194 
14195   /* enable clipping for raw video streams */
14196     stream->need_clip = TRUE;
14197     stream->alignment = 32;
14198   }
14199 
14200   return caps;
14201 }
14202 
14203 static guint
14204 round_up_pow2 (guint n)
14205 {
14206   n = n - 1;
14207   n = n | (n >> 1);
14208   n = n | (n >> 2);
14209   n = n | (n >> 4);
14210   n = n | (n >> 8);
14211   n = n | (n >> 16);
14212   return n + 1;
14213 }
14214 
14215 static GstCaps *
14216 qtdemux_audio_caps (GstQTDemux * qtdemux, QtDemuxStream * stream,
14217     QtDemuxStreamStsdEntry * entry, guint32 fourcc, const guint8 * data,
14218     int len, gchar ** codec_name)
14219 {
14220   GstCaps *caps;
14221   const GstStructure *s;
14222   const gchar *name;
14223   gint endian = 0;
14224   GstAudioFormat format = 0;
14225   gint depth;
14226 
14227   GST_DEBUG_OBJECT (qtdemux, "resolve fourcc 0x%08x", GUINT32_TO_BE (fourcc));
14228 
14229   depth = entry->bytes_per_packet * 8;
14230 
14231   switch (fourcc) {
14232     case GST_MAKE_FOURCC ('N', 'O', 'N', 'E'):
14233     case FOURCC_raw_:
14234       /* 8-bit audio is unsigned */
14235       if (depth == 8)
14236         format = GST_AUDIO_FORMAT_U8;
14237       /* otherwise it's signed and big-endian just like 'twos' */
14238     case FOURCC_twos:
14239       endian = G_BIG_ENDIAN;
14240       /* fall-through */
14241     case FOURCC_sowt:
14242     {
14243       gchar *str;
14244 
14245       if (!endian)
14246         endian = G_LITTLE_ENDIAN;
14247 
14248       if (!format)
14249       format = gst_audio_format_build_integer (TRUE, endian, depth, depth);
14250 
14251       str = g_strdup_printf ("Raw %d-bit PCM audio", depth);
14252       _codec (str);
14253       g_free (str);
14254 
14255       caps = gst_caps_new_simple ("audio/x-raw",
14256           "format", G_TYPE_STRING, gst_audio_format_to_string (format),
14257           "layout", G_TYPE_STRING, "interleaved", NULL);
14258       stream->alignment = GST_ROUND_UP_8 (depth);
14259       stream->alignment = round_up_pow2 (stream->alignment);
14260       break;
14261     }
14262     case GST_MAKE_FOURCC ('f', 'l', '6', '4'):
14263       _codec ("Raw 64-bit floating-point audio");
14264       caps = gst_caps_new_simple ("audio/x-raw",
14265           "format", G_TYPE_STRING, "F64BE",
14266           "layout", G_TYPE_STRING, "interleaved", NULL);
14267       stream->alignment = 8;
14268       break;
14269     case GST_MAKE_FOURCC ('f', 'l', '3', '2'):
14270       _codec ("Raw 32-bit floating-point audio");
14271       caps = gst_caps_new_simple ("audio/x-raw",
14272           "format", G_TYPE_STRING, "F32BE",
14273           "layout", G_TYPE_STRING, "interleaved", NULL);
14274       stream->alignment = 4;
14275       break;
14276     case FOURCC_in24:
14277       _codec ("Raw 24-bit PCM audio");
14278       /* we assume BIG ENDIAN, an enda box will tell us to change this to little
14279        * endian later */
14280       caps = gst_caps_new_simple ("audio/x-raw",
14281           "format", G_TYPE_STRING, "S24BE",
14282           "layout", G_TYPE_STRING, "interleaved", NULL);
14283       stream->alignment = 4;
14284       break;
14285     case GST_MAKE_FOURCC ('i', 'n', '3', '2'):
14286       _codec ("Raw 32-bit PCM audio");
14287       caps = gst_caps_new_simple ("audio/x-raw",
14288           "format", G_TYPE_STRING, "S32BE",
14289           "layout", G_TYPE_STRING, "interleaved", NULL);
14290       stream->alignment = 4;
14291       break;
14292     case GST_MAKE_FOURCC ('s', '1', '6', 'l'):
14293       _codec ("Raw 16-bit PCM audio");
14294       caps = gst_caps_new_simple ("audio/x-raw",
14295           "format", G_TYPE_STRING, "S16LE",
14296           "layout", G_TYPE_STRING, "interleaved", NULL);
14297       stream->alignment = 2;
14298       break;
14299     case FOURCC_ulaw:
14300       _codec ("Mu-law audio");
14301       caps = gst_caps_new_empty_simple ("audio/x-mulaw");
14302       break;
14303     case FOURCC_alaw:
14304       _codec ("A-law audio");
14305       caps = gst_caps_new_empty_simple ("audio/x-alaw");
14306       break;
14307     case 0x0200736d:
14308     case 0x6d730002:
14309       _codec ("Microsoft ADPCM");
14310       /* Microsoft ADPCM-ACM code 2 */
14311       caps = gst_caps_new_simple ("audio/x-adpcm",
14312           "layout", G_TYPE_STRING, "microsoft", NULL);
14313       break;
14314     case 0x1100736d:
14315     case 0x6d730011:
14316       _codec ("DVI/IMA ADPCM");
14317       caps = gst_caps_new_simple ("audio/x-adpcm",
14318           "layout", G_TYPE_STRING, "dvi", NULL);
14319       break;
14320     case 0x1700736d:
14321     case 0x6d730017:
14322       _codec ("DVI/Intel IMA ADPCM");
14323       /* FIXME DVI/Intel IMA ADPCM/ACM code 17 */
14324       caps = gst_caps_new_simple ("audio/x-adpcm",
14325           "layout", G_TYPE_STRING, "quicktime", NULL);
14326       break;
14327     case 0x5500736d:
14328     case 0x6d730055:
14329       /* MPEG layer 3, CBR only (pre QT4.1) */
14330     case FOURCC__mp3:
14331       _codec ("MPEG-1 layer 3");
14332       /* MPEG layer 3, CBR & VBR (QT4.1 and later) */
14333       caps = gst_caps_new_simple ("audio/mpeg", "layer", G_TYPE_INT, 3,
14334           "mpegversion", G_TYPE_INT, 1, NULL);
14335       break;
14336     case GST_MAKE_FOURCC ('.', 'm', 'p', '2'):
14337       _codec ("MPEG-1 layer 2");
14338       /* MPEG layer 2 */
14339       caps = gst_caps_new_simple ("audio/mpeg", "layer", G_TYPE_INT, 2,
14340           "mpegversion", G_TYPE_INT, 1, NULL);
14341       break;
14342     case 0x20736d:
14343     case GST_MAKE_FOURCC ('e', 'c', '-', '3'):
14344       _codec ("EAC-3 audio");
14345       caps = gst_caps_new_simple ("audio/x-eac3",
14346           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
14347       entry->sampled = TRUE;
14348       break;
14349     case GST_MAKE_FOURCC ('s', 'a', 'c', '3'): // Nero Recode
14350     case FOURCC_ac_3:
14351       _codec ("AC-3 audio");
14352       caps = gst_caps_new_simple ("audio/x-ac3",
14353           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
14354       entry->sampled = TRUE;
14355       break;
14356     case GST_MAKE_FOURCC ('d', 't', 's', 'c'):
14357     case GST_MAKE_FOURCC ('D', 'T', 'S', ' '):
14358       _codec ("DTS audio");
14359       caps = gst_caps_new_simple ("audio/x-dts",
14360           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
14361       entry->sampled = TRUE;
14362       break;
14363     case GST_MAKE_FOURCC ('d', 't', 's', 'h'): // DTS-HD
14364     case GST_MAKE_FOURCC ('d', 't', 's', 'l'): // DTS-HD Lossless
14365       _codec ("DTS-HD audio");
14366       caps = gst_caps_new_simple ("audio/x-dts",
14367           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
14368       entry->sampled = TRUE;
14369       break;
14370     case FOURCC_MAC3:
14371       _codec ("MACE-3");
14372       caps = gst_caps_new_simple ("audio/x-mace",
14373           "maceversion", G_TYPE_INT, 3, NULL);
14374       break;
14375     case FOURCC_MAC6:
14376       _codec ("MACE-6");
14377       caps = gst_caps_new_simple ("audio/x-mace",
14378           "maceversion", G_TYPE_INT, 6, NULL);
14379       break;
14380     case GST_MAKE_FOURCC ('O', 'g', 'g', 'V'):
14381       /* ogg/vorbis */
14382       caps = gst_caps_new_empty_simple ("application/ogg");
14383       break;
14384     case GST_MAKE_FOURCC ('d', 'v', 'c', 'a'):
14385       _codec ("DV audio");
14386       caps = gst_caps_new_empty_simple ("audio/x-dv");
14387       break;
14388     case FOURCC_mp4a:
14389       _codec ("MPEG-4 AAC audio");
14390       caps = gst_caps_new_simple ("audio/mpeg",
14391           "mpegversion", G_TYPE_INT, 4, "framed", G_TYPE_BOOLEAN, TRUE,
14392           "stream-format", G_TYPE_STRING, "raw", NULL);
14393       break;
14394     case GST_MAKE_FOURCC ('Q', 'D', 'M', 'C'):
14395       _codec ("QDesign Music");
14396       caps = gst_caps_new_empty_simple ("audio/x-qdm");
14397       break;
14398     case FOURCC_QDM2:
14399       _codec ("QDesign Music v.2");
14400       /* FIXME: QDesign music version 2 (no constant) */
14401       if (FALSE && data) {
14402         caps = gst_caps_new_simple ("audio/x-qdm2",
14403             "framesize", G_TYPE_INT, QT_UINT32 (data + 52),
14404             "bitrate", G_TYPE_INT, QT_UINT32 (data + 40),
14405             "blocksize", G_TYPE_INT, QT_UINT32 (data + 44), NULL);
14406       } else {
14407         caps = gst_caps_new_empty_simple ("audio/x-qdm2");
14408       }
14409       break;
14410     case FOURCC_agsm:
14411       _codec ("GSM audio");
14412       caps = gst_caps_new_empty_simple ("audio/x-gsm");
14413       break;
14414     case FOURCC_samr:
14415       _codec ("AMR audio");
14416       caps = gst_caps_new_empty_simple ("audio/AMR");
14417       break;
14418     case FOURCC_sawb:
14419       _codec ("AMR-WB audio");
14420       caps = gst_caps_new_empty_simple ("audio/AMR-WB");
14421       break;
14422     case FOURCC_ima4:
14423       _codec ("Quicktime IMA ADPCM");
14424       caps = gst_caps_new_simple ("audio/x-adpcm",
14425           "layout", G_TYPE_STRING, "quicktime", NULL);
14426       break;
14427     case FOURCC_alac:
14428       _codec ("Apple lossless audio");
14429       caps = gst_caps_new_empty_simple ("audio/x-alac");
14430       break;
14431     case FOURCC_fLaC:
14432       _codec ("Free Lossless Audio Codec");
14433       caps = gst_caps_new_simple ("audio/x-flac",
14434           "framed", G_TYPE_BOOLEAN, TRUE, NULL);
14435       break;
14436     case GST_MAKE_FOURCC ('Q', 'c', 'l', 'p'):
14437       _codec ("QualComm PureVoice");
14438       caps = gst_caps_from_string ("audio/qcelp");
14439       break;
14440     case FOURCC_wma_:
14441     case FOURCC_owma:
14442       _codec ("WMA");
14443       caps = gst_caps_new_empty_simple ("audio/x-wma");
14444       break;
14445     case FOURCC_opus:
14446       _codec ("Opus");
14447       caps = gst_caps_new_empty_simple ("audio/x-opus");
14448       break;
14449     case FOURCC_lpcm:
14450     {
14451       guint32 flags = 0;
14452       guint32 depth = 0;
14453       guint32 width = 0;
14454       GstAudioFormat format;
14455       enum
14456       {
14457         FLAG_IS_FLOAT = 0x1,
14458         FLAG_IS_BIG_ENDIAN = 0x2,
14459         FLAG_IS_SIGNED = 0x4,
14460         FLAG_IS_PACKED = 0x8,
14461         FLAG_IS_ALIGNED_HIGH = 0x10,
14462         FLAG_IS_NON_INTERLEAVED = 0x20
14463       };
14464       _codec ("Raw LPCM audio");
14465 
14466       if (data && len >= 36) {
14467         depth = QT_UINT32 (data + 24);
14468         flags = QT_UINT32 (data + 28);
14469         width = QT_UINT32 (data + 32) * 8 / entry->n_channels;
14470       }
14471       if ((flags & FLAG_IS_FLOAT) == 0) {
14472         if (depth == 0)
14473           depth = 16;
14474         if (width == 0)
14475           width = 16;
14476         if ((flags & FLAG_IS_ALIGNED_HIGH))
14477           depth = width;
14478 
14479         format = gst_audio_format_build_integer ((flags & FLAG_IS_SIGNED) ?
14480             TRUE : FALSE, (flags & FLAG_IS_BIG_ENDIAN) ?
14481             G_BIG_ENDIAN : G_LITTLE_ENDIAN, width, depth);
14482         caps = gst_caps_new_simple ("audio/x-raw",
14483             "format", G_TYPE_STRING,
14484             format !=
14485             GST_AUDIO_FORMAT_UNKNOWN ? gst_audio_format_to_string (format) :
14486             "UNKNOWN", "layout", G_TYPE_STRING,
14487             (flags & FLAG_IS_NON_INTERLEAVED) ? "non-interleaved" :
14488             "interleaved", NULL);
14489         stream->alignment = GST_ROUND_UP_8 (depth);
14490         stream->alignment = round_up_pow2 (stream->alignment);
14491       } else {
14492         if (width == 0)
14493           width = 32;
14494         if (width == 64) {
14495           if (flags & FLAG_IS_BIG_ENDIAN)
14496             format = GST_AUDIO_FORMAT_F64BE;
14497           else
14498             format = GST_AUDIO_FORMAT_F64LE;
14499         } else {
14500           if (flags & FLAG_IS_BIG_ENDIAN)
14501             format = GST_AUDIO_FORMAT_F32BE;
14502           else
14503             format = GST_AUDIO_FORMAT_F32LE;
14504         }
14505         caps = gst_caps_new_simple ("audio/x-raw",
14506             "format", G_TYPE_STRING, gst_audio_format_to_string (format),
14507             "layout", G_TYPE_STRING, (flags & FLAG_IS_NON_INTERLEAVED) ?
14508             "non-interleaved" : "interleaved", NULL);
14509         stream->alignment = width / 8;
14510       }
14511       break;
14512     }
14513     case GST_MAKE_FOURCC ('q', 't', 'v', 'r'):
14514       /* ? */
14515     default:
14516     {
14517       caps = _get_unknown_codec_name ("audio", fourcc);
14518       break;
14519     }
14520   }
14521 
14522   if (caps) {
14523     GstCaps *templ_caps =
14524         gst_static_pad_template_get_caps (&gst_qtdemux_audiosrc_template);
14525     GstCaps *intersection = gst_caps_intersect (caps, templ_caps);
14526     gst_caps_unref (caps);
14527     gst_caps_unref (templ_caps);
14528     caps = intersection;
14529   }
14530 
14531   /* enable clipping for raw audio streams */
14532   s = gst_caps_get_structure (caps, 0);
14533   name = gst_structure_get_name (s);
14534   if (g_str_has_prefix (name, "audio/x-raw")) {
14535     stream->need_clip = TRUE;
14536     stream->max_buffer_size = 4096 * entry->bytes_per_frame;
14537     GST_DEBUG ("setting max buffer size to %d", stream->max_buffer_size);
14538   }
14539   return caps;
14540 }
14541 
14542 static GstCaps *
14543 qtdemux_sub_caps (GstQTDemux * qtdemux, QtDemuxStream * stream,
14544     QtDemuxStreamStsdEntry * entry, guint32 fourcc,
14545     const guint8 * stsd_entry_data, gchar ** codec_name)
14546 {
14547   GstCaps *caps;
14548 
14549   GST_DEBUG_OBJECT (qtdemux, "resolve fourcc 0x%08x", GUINT32_TO_BE (fourcc));
14550 
14551   switch (fourcc) {
14552     case FOURCC_mp4s:
14553       _codec ("DVD subtitle");
14554       caps = gst_caps_new_empty_simple ("subpicture/x-dvd");
14555       stream->need_process = TRUE;
14556       break;
14557     case FOURCC_text:
14558       _codec ("Quicktime timed text");
14559       goto text;
14560     case FOURCC_tx3g:
14561       _codec ("3GPP timed text");
14562     text:
14563       caps = gst_caps_new_simple ("text/x-raw", "format", G_TYPE_STRING,
14564           "utf8", NULL);
14565       /* actual text piece needs to be extracted */
14566       stream->need_process = TRUE;
14567       break;
14568     case FOURCC_stpp:
14569       _codec ("XML subtitles");
14570       caps = gst_caps_new_empty_simple ("application/ttml+xml");
14571       break;
14572     default:
14573     {
14574       caps = _get_unknown_codec_name ("text", fourcc);
14575       break;
14576     }
14577   }
14578   return caps;
14579 }
14580 
14581 static GstCaps *
14582 qtdemux_generic_caps (GstQTDemux * qtdemux, QtDemuxStream * stream,
14583     QtDemuxStreamStsdEntry * entry, guint32 fourcc,
14584     const guint8 * stsd_entry_data, gchar ** codec_name)
14585 {
14586   GstCaps *caps;
14587 
14588   switch (fourcc) {
14589     case FOURCC_m1v:
14590       _codec ("MPEG 1 video");
14591       caps = gst_caps_new_simple ("video/mpeg", "mpegversion", G_TYPE_INT, 1,
14592           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
14593       break;
14594     default:
14595       caps = NULL;
14596       break;
14597   }
14598   return caps;
14599 }
14600 
14601 static void
14602 gst_qtdemux_append_protection_system_id (GstQTDemux * qtdemux,
14603     const gchar * system_id)
14604 {
14605   gint i;
14606 
14607   if (!qtdemux->protection_system_ids)
14608     qtdemux->protection_system_ids =
14609         g_ptr_array_new_with_free_func ((GDestroyNotify) g_free);
14610   /* Check whether we already have an entry for this system ID. */
14611   for (i = 0; i < qtdemux->protection_system_ids->len; ++i) {
14612     const gchar *id = g_ptr_array_index (qtdemux->protection_system_ids, i);
14613     if (g_ascii_strcasecmp (system_id, id) == 0) {
14614       return;
14615     }
14616   }
14617   GST_DEBUG_OBJECT (qtdemux, "Adding cenc protection system ID %s", system_id);
14618   g_ptr_array_add (qtdemux->protection_system_ids, g_ascii_strdown (system_id,
14619           -1));
14620 }