1 /* -*- Mode: C; tab-width: 2; indent-tabs-mode: t; c-basic-offset: 2 -*- */
   2 /* GStreamer AIFF parser
   3  * Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu>
   4  *               <2006> Nokia Corporation, Stefan Kost <stefan.kost@nokia.com>.
   5  *               <2008> Pioneers of the Inevitable <songbird@songbirdnest.com>
   6  *
   7  *
   8  * This library is free software; you can redistribute it and/or
   9  * modify it under the terms of the GNU Library General Public
  10  * License as published by the Free Software Foundation; either
  11  * version 2 of the License, or (at your option) any later version.
  12  *
  13  * This library is distributed in the hope that it will be useful,
  14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  16  * Library General Public License for more details.
  17  *
  18  * You should have received a copy of the GNU Library General Public
  19  * License along with this library; if not, write to the
  20  * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
  21  * Boston, MA 02110-1301, USA.
  22  */
  23 
  24 /**
  25  * SECTION:element-aiffparse
  26  * @title: aiffparse
  27  *
  28  * Parse a .aiff file into raw or compressed audio.
  29  *
  30  * The aiffparse element supports both push and pull mode operations, making it
  31  * possible to stream from a network source.
  32  *
  33  * ## Example launch line
  34  *
  35  * |[
  36  * gst-launch-1.0 filesrc location=sine.aiff ! aiffparse ! audioconvert ! alsasink
  37  * ]|
  38  * Read a aiff file and output to the soundcard using the ALSA element. The
  39  * aiff file is assumed to contain raw uncompressed samples.
  40  *
  41  * |[
  42  * gst-launch-1.0 souphttpsrc location=http://www.example.org/sine.aiff ! queue ! aiffparse ! audioconvert ! alsasink
  43  * ]|
  44  * Stream data from a network url.
  45  *
  46  */
  47 
  48 #ifdef HAVE_CONFIG_H
  49 #include "config.h"
  50 #endif
  51 
  52 #include <string.h>
  53 #include <math.h>
  54 
  55 #include "aiffparse.h"
  56 #include <gst/audio/audio.h>
  57 #include <gst/tag/tag.h>
  58 #include <gst/pbutils/descriptions.h>
  59 #include <gst/gst-i18n-plugin.h>
  60 
  61 GST_DEBUG_CATEGORY (aiffparse_debug);
  62 #define GST_CAT_DEFAULT (aiffparse_debug)
  63 
  64 static void gst_aiff_parse_dispose (GObject * object);
  65 
  66 static gboolean gst_aiff_parse_sink_activate (GstPad * sinkpad,
  67     GstObject * parent);
  68 static gboolean gst_aiff_parse_sink_activate_mode (GstPad * sinkpad,
  69     GstObject * parent, GstPadMode mode, gboolean active);
  70 static gboolean gst_aiff_parse_sink_event (GstPad * pad, GstObject * parent,
  71     GstEvent * buf);
  72 static gboolean gst_aiff_parse_send_event (GstElement * element,
  73     GstEvent * event);
  74 static GstStateChangeReturn gst_aiff_parse_change_state (GstElement * element,
  75     GstStateChange transition);
  76 
  77 static gboolean gst_aiff_parse_pad_query (GstPad * pad, GstObject * parent,
  78     GstQuery * query);
  79 static gboolean gst_aiff_parse_pad_convert (GstPad * pad,
  80     GstFormat src_format,
  81     gint64 src_value, GstFormat * dest_format, gint64 * dest_value);
  82 
  83 static GstFlowReturn gst_aiff_parse_chain (GstPad * pad, GstObject * parent,
  84     GstBuffer * buf);
  85 static void gst_aiff_parse_loop (GstPad * pad);
  86 static gboolean gst_aiff_parse_srcpad_event (GstPad * pad, GstObject * parent,
  87     GstEvent * event);
  88 
  89 static GstStaticPadTemplate sink_template_factory =
  90 GST_STATIC_PAD_TEMPLATE ("sink",
  91     GST_PAD_SINK,
  92     GST_PAD_ALWAYS,
  93     GST_STATIC_CAPS ("audio/x-aiff")
  94     );
  95 
  96 static GstStaticPadTemplate src_template_factory =
  97 GST_STATIC_PAD_TEMPLATE ("src",
  98     GST_PAD_SRC,
  99     GST_PAD_ALWAYS,
 100     GST_STATIC_CAPS (GST_AUDIO_CAPS_MAKE ("{ S8, S16BE, S16LE, S24BE, S24LE, "
 101             "S32LE, S32BE, F32BE, F64BE }"))
 102     );
 103 
 104 #define MAX_BUFFER_SIZE 4096
 105 
 106 #define gst_aiff_parse_parent_class parent_class
 107 G_DEFINE_TYPE (GstAiffParse, gst_aiff_parse, GST_TYPE_ELEMENT);
 108 
 109 static void
 110 gst_aiff_parse_class_init (GstAiffParseClass * klass)
 111 {
 112   GstElementClass *gstelement_class;
 113   GObjectClass *object_class;
 114 
 115   gstelement_class = (GstElementClass *) klass;
 116   object_class = (GObjectClass *) klass;
 117 
 118   object_class->dispose = gst_aiff_parse_dispose;
 119 
 120   gst_element_class_add_static_pad_template (gstelement_class,
 121       &sink_template_factory);
 122   gst_element_class_add_static_pad_template (gstelement_class,
 123       &src_template_factory);
 124 
 125   gst_element_class_set_static_metadata (gstelement_class,
 126       "AIFF audio demuxer", "Codec/Demuxer/Audio",
 127       "Parse a .aiff file into raw audio",
 128       "Pioneers of the Inevitable <songbird@songbirdnest.com>");
 129 
 130   gstelement_class->change_state =
 131       GST_DEBUG_FUNCPTR (gst_aiff_parse_change_state);
 132   gstelement_class->send_event = GST_DEBUG_FUNCPTR (gst_aiff_parse_send_event);
 133 }
 134 
 135 static void
 136 gst_aiff_parse_reset (GstAiffParse * aiff)
 137 {
 138   aiff->state = AIFF_PARSE_START;
 139 
 140   /* These will all be set correctly in the fmt chunk */
 141   aiff->rate = 0;
 142   aiff->width = 0;
 143   aiff->depth = 0;
 144   aiff->channels = 0;
 145   aiff->bps = 0;
 146   aiff->offset = 0;
 147   aiff->end_offset = 0;
 148   aiff->dataleft = 0;
 149   aiff->datasize = 0;
 150   aiff->datastart = 0;
 151   aiff->duration = 0;
 152   aiff->got_comm = FALSE;
 153 
 154   if (aiff->seek_event)
 155     gst_event_unref (aiff->seek_event);
 156   aiff->seek_event = NULL;
 157   if (aiff->adapter) {
 158     gst_adapter_clear (aiff->adapter);
 159     aiff->adapter = NULL;
 160   }
 161 
 162   if (aiff->tags != NULL) {
 163     gst_tag_list_unref (aiff->tags);
 164     aiff->tags = NULL;
 165   }
 166 }
 167 
 168 static void
 169 gst_aiff_parse_dispose (GObject * object)
 170 {
 171   GstAiffParse *aiff = GST_AIFF_PARSE (object);
 172 
 173   GST_DEBUG_OBJECT (aiff, "AIFF: Dispose");
 174   gst_aiff_parse_reset (aiff);
 175 
 176   G_OBJECT_CLASS (parent_class)->dispose (object);
 177 }
 178 
 179 static void
 180 gst_aiff_parse_init (GstAiffParse * aiffparse)
 181 {
 182   gst_aiff_parse_reset (aiffparse);
 183 
 184   /* sink */
 185   aiffparse->sinkpad =
 186       gst_pad_new_from_static_template (&sink_template_factory, "sink");
 187   gst_pad_set_activate_function (aiffparse->sinkpad,
 188       GST_DEBUG_FUNCPTR (gst_aiff_parse_sink_activate));
 189   gst_pad_set_activatemode_function (aiffparse->sinkpad,
 190       GST_DEBUG_FUNCPTR (gst_aiff_parse_sink_activate_mode));
 191   gst_pad_set_event_function (aiffparse->sinkpad,
 192       GST_DEBUG_FUNCPTR (gst_aiff_parse_sink_event));
 193   gst_pad_set_chain_function (aiffparse->sinkpad,
 194       GST_DEBUG_FUNCPTR (gst_aiff_parse_chain));
 195   gst_element_add_pad (GST_ELEMENT_CAST (aiffparse), aiffparse->sinkpad);
 196 
 197   /* source */
 198   aiffparse->srcpad =
 199       gst_pad_new_from_static_template (&src_template_factory, "src");
 200   gst_pad_use_fixed_caps (aiffparse->srcpad);
 201   gst_pad_set_query_function (aiffparse->srcpad,
 202       GST_DEBUG_FUNCPTR (gst_aiff_parse_pad_query));
 203   gst_pad_set_event_function (aiffparse->srcpad,
 204       GST_DEBUG_FUNCPTR (gst_aiff_parse_srcpad_event));
 205   gst_element_add_pad (GST_ELEMENT_CAST (aiffparse), aiffparse->srcpad);
 206 }
 207 
 208 static gboolean
 209 gst_aiff_parse_parse_file_header (GstAiffParse * aiff, GstBuffer * buf)
 210 {
 211   guint32 header, type = 0;
 212   GstMapInfo info;
 213 
 214   if (!gst_buffer_map (buf, &info, GST_MAP_READ)) {
 215     GST_WARNING_OBJECT (aiff, "Could not map buffer");
 216     goto not_aiff;
 217   }
 218 
 219   if (info.size < 12) {
 220     GST_WARNING_OBJECT (aiff, "Buffer too short");
 221     gst_buffer_unmap (buf, &info);
 222     goto not_aiff;
 223   }
 224 
 225   header = GST_READ_UINT32_LE (info.data);
 226   type = GST_READ_UINT32_LE (info.data + 8);
 227   gst_buffer_unmap (buf, &info);
 228 
 229   if (header != GST_MAKE_FOURCC ('F', 'O', 'R', 'M'))
 230     goto not_aiff;
 231 
 232   if (type == GST_MAKE_FOURCC ('A', 'I', 'F', 'F'))
 233     aiff->is_aifc = FALSE;
 234   else if (type == GST_MAKE_FOURCC ('A', 'I', 'F', 'C'))
 235     aiff->is_aifc = TRUE;
 236   else
 237     goto not_aiff;
 238 
 239   gst_buffer_unref (buf);
 240   return TRUE;
 241 
 242   /* ERRORS */
 243 not_aiff:
 244   {
 245     GST_ELEMENT_ERROR (aiff, STREAM, WRONG_TYPE, (NULL),
 246         ("File is not an AIFF file: 0x%" G_GINT32_MODIFIER "x", type));
 247     gst_buffer_unref (buf);
 248     return FALSE;
 249   }
 250 }
 251 
 252 static GstFlowReturn
 253 gst_aiff_parse_stream_init (GstAiffParse * aiff)
 254 {
 255   GstFlowReturn res;
 256   GstBuffer *buf = NULL;
 257 
 258   if ((res = gst_pad_pull_range (aiff->sinkpad,
 259               aiff->offset, 12, &buf)) != GST_FLOW_OK)
 260     return res;
 261   else if (!gst_aiff_parse_parse_file_header (aiff, buf))
 262     return GST_FLOW_ERROR;
 263 
 264   aiff->offset += 12;
 265 
 266   return GST_FLOW_OK;
 267 }
 268 
 269 static gboolean
 270 gst_aiff_parse_time_to_bytepos (GstAiffParse * aiff, gint64 ts,
 271     gint64 * bytepos)
 272 {
 273   /* -1 always maps to -1 */
 274   if (ts == -1) {
 275     *bytepos = -1;
 276     return TRUE;
 277   }
 278 
 279   /* 0 always maps to 0 */
 280   if (ts == 0) {
 281     *bytepos = 0;
 282     return TRUE;
 283   }
 284 
 285   if (aiff->bps > 0) {
 286     *bytepos = gst_util_uint64_scale_ceil (ts, (guint64) aiff->bps, GST_SECOND);
 287     return TRUE;
 288   }
 289 
 290   GST_WARNING_OBJECT (aiff, "No valid bps to convert position");
 291 
 292   return FALSE;
 293 }
 294 
 295 /* This function is used to perform seeks on the element in
 296  * pull mode.
 297  *
 298  * It also works when event is NULL, in which case it will just
 299  * start from the last configured segment. This technique is
 300  * used when activating the element and to perform the seek in
 301  * READY.
 302  */
 303 static gboolean
 304 gst_aiff_parse_perform_seek (GstAiffParse * aiff, GstEvent * event,
 305     gboolean starting)
 306 {
 307   gboolean res;
 308   gdouble rate;
 309   GstFormat format;
 310   GstSeekFlags flags;
 311   GstSeekType start_type = GST_SEEK_TYPE_NONE, stop_type;
 312   gint64 start, stop, upstream_size;
 313   gboolean flush;
 314   gboolean update;
 315   GstSegment seeksegment = { 0, };
 316   gint64 position;
 317 
 318   if (event) {
 319     GST_DEBUG_OBJECT (aiff, "doing seek with event");
 320 
 321     gst_event_parse_seek (event, &rate, &format, &flags,
 322         &start_type, &start, &stop_type, &stop);
 323 
 324     /* no negative rates yet */
 325     if (rate < 0.0)
 326       goto negative_rate;
 327 
 328     if (format != aiff->segment.format) {
 329       GST_INFO_OBJECT (aiff, "converting seek-event from %s to %s",
 330           gst_format_get_name (format),
 331           gst_format_get_name (aiff->segment.format));
 332       res = TRUE;
 333       if (start_type != GST_SEEK_TYPE_NONE)
 334         res =
 335             gst_pad_query_convert (aiff->srcpad, format, start,
 336             aiff->segment.format, &start);
 337       if (res && stop_type != GST_SEEK_TYPE_NONE)
 338         res =
 339             gst_pad_query_convert (aiff->srcpad, format, stop,
 340             aiff->segment.format, &stop);
 341       if (!res)
 342         goto no_format;
 343 
 344       format = aiff->segment.format;
 345     }
 346   } else {
 347     GST_DEBUG_OBJECT (aiff, "doing seek without event");
 348     flags = 0;
 349     rate = 1.0;
 350     start = 0;
 351     start_type = GST_SEEK_TYPE_SET;
 352     stop = -1;
 353     stop_type = GST_SEEK_TYPE_SET;
 354   }
 355 
 356   /* get flush flag */
 357   flush = flags & GST_SEEK_FLAG_FLUSH;
 358 
 359   if (aiff->streaming && !starting) {
 360     GstEvent *new_event;
 361 
 362     /* streaming seek */
 363     if ((start_type != GST_SEEK_TYPE_NONE)) {
 364       /* bring offset to bytes, if the bps is 0, we have the segment in BYTES and
 365        * we can just copy the position. If not, we use the bps to convert TIME to
 366        * bytes. */
 367       if (aiff->bps > 0)
 368         start =
 369             gst_util_uint64_scale_ceil (start, (guint64) aiff->bps, GST_SECOND);
 370       start -= (start % aiff->bytes_per_sample);
 371       start += aiff->datastart;
 372     }
 373 
 374     if (stop_type != GST_SEEK_TYPE_NONE) {
 375       if (aiff->bps > 0)
 376         stop =
 377             gst_util_uint64_scale_ceil (stop, (guint64) aiff->bps, GST_SECOND);
 378       stop -= (stop % aiff->bytes_per_sample);
 379       stop += aiff->datastart;
 380     }
 381 
 382     /* make sure filesize is not exceeded due to rounding errors or so,
 383      * same precaution as in _stream_headers */
 384     if (gst_pad_peer_query_duration (aiff->sinkpad, GST_FORMAT_BYTES,
 385             &upstream_size))
 386       stop = MIN (stop, upstream_size);
 387 
 388     if (stop >= 0 && stop <= start)
 389       stop = start;
 390 
 391     new_event = gst_event_new_seek (rate, GST_FORMAT_BYTES, flags,
 392         start_type, start, stop_type, stop);
 393 
 394     res = gst_pad_push_event (aiff->sinkpad, new_event);
 395   } else {
 396     /* now we need to make sure the streaming thread is stopped. We do this by
 397      * either sending a FLUSH_START event downstream which will cause the
 398      * streaming thread to stop with a FLUSHING.
 399      * For a non-flushing seek we simply pause the task, which will happen as soon
 400      * as it completes one iteration (and thus might block when the sink is
 401      * blocking in preroll). */
 402     if (flush) {
 403       GST_DEBUG_OBJECT (aiff, "sending flush start");
 404       gst_pad_push_event (aiff->srcpad, gst_event_new_flush_start ());
 405     } else {
 406       gst_pad_pause_task (aiff->sinkpad);
 407     }
 408 
 409     /* we should now be able to grab the streaming thread because we stopped it
 410      * with the above flush/pause code */
 411     GST_PAD_STREAM_LOCK (aiff->sinkpad);
 412 
 413     /* save current position */
 414     position = aiff->segment.position;
 415 
 416     GST_DEBUG_OBJECT (aiff, "stopped streaming at %" G_GINT64_FORMAT, position);
 417 
 418     /* copy segment, we need this because we still need the old
 419      * segment when we close the current segment. */
 420     memcpy (&seeksegment, &aiff->segment, sizeof (GstSegment));
 421 
 422     /* configure the seek parameters in the seeksegment. We will then have the
 423      * right values in the segment to perform the seek */
 424     if (event) {
 425       GST_DEBUG_OBJECT (aiff, "configuring seek");
 426       gst_segment_do_seek (&seeksegment, rate, format, flags,
 427           start_type, start, stop_type, stop, &update);
 428     }
 429 
 430     /* figure out the last position we need to play. If it's configured (stop !=
 431      * -1), use that, else we play until the total duration of the file */
 432     if ((stop = seeksegment.stop) == -1)
 433       stop = seeksegment.duration;
 434 
 435     GST_DEBUG_OBJECT (aiff, "start_type =%d", start_type);
 436     if ((start_type != GST_SEEK_TYPE_NONE)) {
 437       /* bring offset to bytes, if the bps is 0, we have the segment in BYTES and
 438        * we can just copy the position. If not, we use the bps to convert TIME to
 439        * bytes. */
 440       if (aiff->bps > 0)
 441         aiff->offset =
 442             gst_util_uint64_scale_ceil (seeksegment.position,
 443             (guint64) aiff->bps, GST_SECOND);
 444       else
 445         aiff->offset = seeksegment.position;
 446       GST_LOG_OBJECT (aiff, "offset=%" G_GUINT64_FORMAT, aiff->offset);
 447       aiff->offset -= (aiff->offset % aiff->bytes_per_sample);
 448       GST_LOG_OBJECT (aiff, "offset=%" G_GUINT64_FORMAT, aiff->offset);
 449       aiff->offset += aiff->datastart;
 450       GST_LOG_OBJECT (aiff, "offset=%" G_GUINT64_FORMAT, aiff->offset);
 451     } else {
 452       GST_LOG_OBJECT (aiff, "continue from offset=%" G_GUINT64_FORMAT,
 453           aiff->offset);
 454     }
 455 
 456     if (stop_type != GST_SEEK_TYPE_NONE) {
 457       if (aiff->bps > 0)
 458         aiff->end_offset =
 459             gst_util_uint64_scale_ceil (stop, (guint64) aiff->bps, GST_SECOND);
 460       else
 461         aiff->end_offset = stop;
 462       GST_LOG_OBJECT (aiff, "end_offset=%" G_GUINT64_FORMAT, aiff->end_offset);
 463       aiff->end_offset -= (aiff->end_offset % aiff->bytes_per_sample);
 464       GST_LOG_OBJECT (aiff, "end_offset=%" G_GUINT64_FORMAT, aiff->end_offset);
 465       aiff->end_offset += aiff->datastart;
 466       GST_LOG_OBJECT (aiff, "end_offset=%" G_GUINT64_FORMAT, aiff->end_offset);
 467     } else {
 468       GST_LOG_OBJECT (aiff, "continue to end_offset=%" G_GUINT64_FORMAT,
 469           aiff->end_offset);
 470     }
 471 
 472     /* make sure filesize is not exceeded due to rounding errors or so,
 473      * same precaution as in _stream_headers */
 474     if (gst_pad_peer_query_duration (aiff->sinkpad, GST_FORMAT_BYTES,
 475             &upstream_size))
 476       aiff->end_offset = MIN (aiff->end_offset, upstream_size);
 477 
 478     /* this is the range of bytes we will use for playback */
 479     aiff->offset = MIN (aiff->offset, aiff->end_offset);
 480     aiff->dataleft = aiff->end_offset - aiff->offset;
 481 
 482     GST_DEBUG_OBJECT (aiff,
 483         "seek: rate %lf, offset %" G_GUINT64_FORMAT ", end %" G_GUINT64_FORMAT
 484         ", segment %" GST_TIME_FORMAT " -- %" GST_TIME_FORMAT, rate,
 485         aiff->offset, aiff->end_offset, GST_TIME_ARGS (seeksegment.start),
 486         GST_TIME_ARGS (stop));
 487 
 488     /* prepare for streaming again */
 489     if (flush) {
 490       /* if we sent a FLUSH_START, we now send a FLUSH_STOP */
 491       GST_DEBUG_OBJECT (aiff, "sending flush stop");
 492       gst_pad_push_event (aiff->srcpad, gst_event_new_flush_stop (TRUE));
 493     }
 494 
 495     /* now we did the seek and can activate the new segment values */
 496     memcpy (&aiff->segment, &seeksegment, sizeof (GstSegment));
 497 
 498     /* if we're doing a segment seek, post a SEGMENT_START message */
 499     if (aiff->segment.flags & GST_SEEK_FLAG_SEGMENT) {
 500       gst_element_post_message (GST_ELEMENT_CAST (aiff),
 501           gst_message_new_segment_start (GST_OBJECT_CAST (aiff),
 502               aiff->segment.format, aiff->segment.position));
 503     }
 504 
 505     /* now create the segment */
 506     GST_DEBUG_OBJECT (aiff, "Creating segment from %" G_GINT64_FORMAT
 507         " to %" G_GINT64_FORMAT, aiff->segment.position, stop);
 508 
 509     /* store the segment event so it can be sent from the streaming thread. */
 510     if (aiff->start_segment)
 511       gst_event_unref (aiff->start_segment);
 512     aiff->start_segment = gst_event_new_segment (&aiff->segment);
 513 
 514     /* mark discont if we are going to stream from another position. */
 515     if (position != aiff->segment.position) {
 516       GST_DEBUG_OBJECT (aiff,
 517           "mark DISCONT, we did a seek to another position");
 518       aiff->discont = TRUE;
 519     }
 520 
 521     /* and start the streaming task again */
 522     aiff->segment_running = TRUE;
 523     if (!aiff->streaming) {
 524       gst_pad_start_task (aiff->sinkpad, (GstTaskFunction) gst_aiff_parse_loop,
 525           aiff->sinkpad, NULL);
 526     }
 527 
 528     GST_PAD_STREAM_UNLOCK (aiff->sinkpad);
 529 
 530     res = TRUE;
 531   }
 532 
 533   return res;
 534 
 535   /* ERRORS */
 536 negative_rate:
 537   {
 538     GST_DEBUG_OBJECT (aiff, "negative playback rates are not supported yet.");
 539     return FALSE;
 540   }
 541 no_format:
 542   {
 543     GST_DEBUG_OBJECT (aiff, "unsupported format given, seek aborted.");
 544     return FALSE;
 545   }
 546 }
 547 
 548 /*
 549  * gst_aiff_parse_peek_chunk_info:
 550  * @aiff AIFFparse object
 551  * @tag holder for tag
 552  * @size holder for tag size
 553  *
 554  * Peek next chunk info (tag and size)
 555  *
 556  * Returns: %TRUE when the chunk info (header) is available
 557  */
 558 static gboolean
 559 gst_aiff_parse_peek_chunk_info (GstAiffParse * aiff, guint32 * tag,
 560     guint32 * size)
 561 {
 562   const guint8 *data = NULL;
 563 
 564   if (gst_adapter_available (aiff->adapter) < 8)
 565     return FALSE;
 566 
 567   data = gst_adapter_map (aiff->adapter, 8);
 568   *tag = GST_READ_UINT32_LE (data);
 569   *size = GST_READ_UINT32_BE (data + 4);
 570   gst_adapter_unmap (aiff->adapter);
 571 
 572   GST_DEBUG_OBJECT (aiff,
 573       "Next chunk size is %d bytes, type %" GST_FOURCC_FORMAT, *size,
 574       GST_FOURCC_ARGS (*tag));
 575 
 576   return TRUE;
 577 }
 578 
 579 /*
 580  * gst_aiff_parse_peek_chunk:
 581  * @aiff AIFFparse object
 582  * @tag holder for tag
 583  * @size holder for tag size
 584  *
 585  * Peek enough data for one full chunk
 586  *
 587  * Returns: %TRUE when the full chunk is available
 588  */
 589 static gboolean
 590 gst_aiff_parse_peek_chunk (GstAiffParse * aiff, guint32 * tag, guint32 * size)
 591 {
 592   guint32 peek_size = 0;
 593   guint available;
 594 
 595   if (!gst_aiff_parse_peek_chunk_info (aiff, tag, size))
 596     return FALSE;
 597 
 598   GST_DEBUG_OBJECT (aiff, "Need to peek chunk of %d bytes", *size);
 599   peek_size = (*size + 1) & ~1;
 600 
 601   available = gst_adapter_available (aiff->adapter);
 602   if (available >= (8 + peek_size)) {
 603     return TRUE;
 604   } else {
 605     GST_LOG_OBJECT (aiff, "but only %u bytes available now", available);
 606     return FALSE;
 607   }
 608 }
 609 
 610 static gboolean
 611 gst_aiff_parse_peek_data (GstAiffParse * aiff, guint32 size,
 612     const guint8 ** data)
 613 {
 614   if (gst_adapter_available (aiff->adapter) < size)
 615     return FALSE;
 616 
 617   *data = gst_adapter_map (aiff->adapter, size);
 618   return TRUE;
 619 }
 620 
 621 /*
 622  * gst_aiff_parse_calculate_duration:
 623  * @aiff: aiffparse object
 624  *
 625  * Calculate duration on demand and store in @aiff.
 626  *
 627  * Returns: %TRUE if duration is available.
 628  */
 629 static gboolean
 630 gst_aiff_parse_calculate_duration (GstAiffParse * aiff)
 631 {
 632   if (aiff->duration > 0)
 633     return TRUE;
 634 
 635   if (aiff->datasize > 0 && aiff->bps > 0) {
 636     aiff->duration =
 637         gst_util_uint64_scale_ceil (aiff->datasize, GST_SECOND,
 638         (guint64) aiff->bps);
 639     GST_INFO_OBJECT (aiff, "Got duration %" GST_TIME_FORMAT,
 640         GST_TIME_ARGS (aiff->duration));
 641     return TRUE;
 642   }
 643   return FALSE;
 644 }
 645 
 646 #ifdef GSTREAMER_LITE
 647 static gboolean
 648 #else
 649 static void
 650 #endif
 651 gst_aiff_parse_ignore_chunk (GstAiffParse * aiff, guint32 tag, guint32 size)
 652 {
 653 #ifdef GSTREAMER_LITE
 654     guint64 flush;
 655 #else
 656     guint flush;
 657 #endif
 658 
 659   if (aiff->streaming) {
 660     if (!gst_aiff_parse_peek_chunk (aiff, &tag, &size))
 661 #ifdef GSTREAMER_LITE
 662       return FALSE;
 663 #else
 664       return;
 665 #endif
 666   }
 667   GST_WARNING_OBJECT (aiff, "Ignoring tag %" GST_FOURCC_FORMAT,
 668       GST_FOURCC_ARGS (tag));
 669 #ifdef GSTREAMER_LITE
 670   flush = 8 + (((guint64)size + 1) & ~1);
 671 #else
 672   flush = 8 + ((size + 1) & ~1);
 673 #endif
 674   aiff->offset += flush;
 675   if (aiff->streaming) {
 676     gst_adapter_flush (aiff->adapter, flush);
 677   }
 678 
 679 #ifdef GSTREAMER_LITE
 680   return TRUE;
 681 #endif
 682 }
 683 
 684 static double
 685 gst_aiff_parse_read_IEEE80 (guint8 * buf)
 686 {
 687   int s = buf[0] & 0xff;
 688   int e = ((buf[0] & 0x7f) << 8) | (buf[1] & 0xff);
 689   double f = ((unsigned long) (buf[2] & 0xff) << 24) |
 690       ((buf[3] & 0xff) << 16) | ((buf[4] & 0xff) << 8) | (buf[5] & 0xff);
 691 
 692   if (e == 32767) {
 693     if (buf[2] & 0x80)
 694       return HUGE_VAL;          /* Really NaN, but this won't happen in reality */
 695     else {
 696       if (s)
 697         return -HUGE_VAL;
 698       else
 699         return HUGE_VAL;
 700     }
 701   }
 702 
 703   f = ldexp (f, 32);
 704   f += ((buf[6] & 0xff) << 24) |
 705       ((buf[7] & 0xff) << 16) | ((buf[8] & 0xff) << 8) | (buf[9] & 0xff);
 706 
 707   return ldexp (f, e - 16446);
 708 }
 709 
 710 static gboolean
 711 gst_aiff_parse_parse_comm (GstAiffParse * aiff, GstBuffer * buf)
 712 {
 713   int size;
 714   GstMapInfo info;
 715   guint32 fourcc;
 716 
 717   if (!gst_buffer_map (buf, &info, GST_MAP_READ)) {
 718     GST_WARNING_OBJECT (aiff, "Can't map buffer");
 719     gst_buffer_unref (buf);
 720     return FALSE;
 721   }
 722 
 723   if (aiff->is_aifc)
 724     size = 22;
 725   else
 726     size = 18;
 727 
 728   if (info.size < size)
 729     goto too_small;
 730 
 731   aiff->channels = GST_READ_UINT16_BE (info.data);
 732   aiff->total_frames = GST_READ_UINT32_BE (info.data + 2);
 733   aiff->depth = GST_READ_UINT16_BE (info.data + 6);
 734   aiff->width = GST_ROUND_UP_8 (aiff->depth);
 735   aiff->rate = (int) gst_aiff_parse_read_IEEE80 (info.data + 8);
 736 
 737   aiff->floating_point = FALSE;
 738 
 739   if (aiff->is_aifc) {
 740     fourcc = GST_READ_UINT32_LE (info.data + 18);
 741 
 742     /* We only support the 'trivial' uncompressed AIFC, but it can be
 743      * either big or little endian */
 744     switch (fourcc) {
 745       case GST_MAKE_FOURCC ('N', 'O', 'N', 'E'):
 746         aiff->endianness = G_BIG_ENDIAN;
 747         break;
 748       case GST_MAKE_FOURCC ('s', 'o', 'w', 't'):
 749         aiff->endianness = G_LITTLE_ENDIAN;
 750         break;
 751       case GST_MAKE_FOURCC ('F', 'L', '3', '2'):
 752       case GST_MAKE_FOURCC ('f', 'l', '3', '2'):
 753         aiff->floating_point = TRUE;
 754         aiff->width = aiff->depth = 32;
 755         aiff->endianness = G_BIG_ENDIAN;
 756         break;
 757       case GST_MAKE_FOURCC ('f', 'l', '6', '4'):
 758         aiff->floating_point = TRUE;
 759         aiff->width = aiff->depth = 64;
 760         aiff->endianness = G_BIG_ENDIAN;
 761         break;
 762       default:
 763         goto unknown_compression;
 764     }
 765   } else
 766     aiff->endianness = G_BIG_ENDIAN;
 767 
 768   gst_buffer_unmap (buf, &info);
 769   gst_buffer_unref (buf);
 770 
 771   return TRUE;
 772 
 773   /* ERRORS */
 774 too_small:
 775   {
 776     GST_WARNING_OBJECT (aiff, "COMM chunk too short, cannot parse header");
 777     gst_buffer_unmap (buf, &info);
 778     gst_buffer_unref (buf);
 779     return FALSE;
 780   }
 781 unknown_compression:
 782   {
 783     GST_WARNING_OBJECT (aiff, "Unsupported compression in AIFC "
 784         "file: %" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (fourcc));
 785     gst_buffer_unmap (buf, &info);
 786     gst_buffer_unref (buf);
 787     return FALSE;
 788   }
 789 }
 790 
 791 static GstFlowReturn
 792 gst_aiff_parse_read_chunk (GstAiffParse * aiff, guint64 * offset, guint32 * tag,
 793     GstBuffer ** data)
 794 {
 795   guint size;
 796   GstFlowReturn res;
 797   GstBuffer *buf = NULL;
 798   GstMapInfo info;
 799 
 800   if ((res =
 801           gst_pad_pull_range (aiff->sinkpad, *offset, 8, &buf)) != GST_FLOW_OK)
 802     return res;
 803 
 804   gst_buffer_map (buf, &info, GST_MAP_READ);
 805   *tag = GST_READ_UINT32_LE (info.data);
 806   size = GST_READ_UINT32_BE (info.data + 4);
 807   gst_buffer_unmap (buf, &info);
 808   gst_buffer_unref (buf);
 809   buf = NULL;
 810 
 811   if ((res =
 812           gst_pad_pull_range (aiff->sinkpad, (*offset) + 8, size,
 813               &buf)) != GST_FLOW_OK)
 814     return res;
 815   else if (gst_buffer_get_size (buf) < size)
 816     goto too_small;
 817 
 818   *data = buf;
 819   *offset += 8 + GST_ROUND_UP_2 (size);
 820 
 821   return GST_FLOW_OK;
 822 
 823   /* ERRORS */
 824 too_small:
 825   {
 826     /* short read, we return EOS to mark the EOS case */
 827     GST_DEBUG_OBJECT (aiff,
 828         "not enough data (available=%" G_GSIZE_FORMAT ", needed=%u)",
 829         gst_buffer_get_size (buf), size);
 830     gst_buffer_unref (buf);
 831     return GST_FLOW_EOS;
 832   }
 833 
 834 }
 835 
 836 #define _P(pos) (G_GUINT64_CONSTANT (1) << GST_AUDIO_CHANNEL_POSITION_ ##pos)
 837 
 838 static GstCaps *
 839 gst_aiff_parse_create_caps (GstAiffParse * aiff)
 840 {
 841   GstCaps *caps = NULL;
 842   const gchar *format = NULL;
 843   guint64 channel_mask;
 844 
 845   if (aiff->floating_point) {
 846     if (aiff->endianness == G_BIG_ENDIAN) {
 847       if (aiff->width == 32)
 848         format = "F32BE";
 849       else if (aiff->width == 64)
 850         format = "F64BE";
 851     }
 852   } else {
 853     if (aiff->endianness == G_BIG_ENDIAN) {
 854       if (aiff->width == 8)
 855         format = "S8";
 856       else if (aiff->width == 16)
 857         format = "S16BE";
 858       else if (aiff->width == 24)
 859         format = "S24BE";
 860       else if (aiff->width == 32)
 861         format = "S32BE";
 862     } else {
 863       if (aiff->width == 8)
 864         format = "S8";
 865       else if (aiff->width == 16)
 866         format = "S16LE";
 867       else if (aiff->width == 24)
 868         format = "S24LE";
 869       else if (aiff->width == 32)
 870         format = "S32LE";
 871     }
 872   }
 873   if (format) {
 874     caps = gst_caps_new_simple ("audio/x-raw",
 875         "format", G_TYPE_STRING, format,
 876         "channels", G_TYPE_INT, aiff->channels,
 877         "layout", G_TYPE_STRING, "interleaved",
 878         "rate", G_TYPE_INT, aiff->rate, NULL);
 879   }
 880 
 881   if (aiff->channels > 2) {
 882     GST_FIXME_OBJECT (aiff, "using fallback channel layout for %d channels",
 883         aiff->channels);
 884 
 885     /* based on AIFF-1.3.pdf */
 886     switch (aiff->channels) {
 887       case 1:
 888         channel_mask = 0;
 889         break;
 890       case 2:
 891         channel_mask = _P (FRONT_LEFT) | _P (FRONT_RIGHT);
 892         break;
 893       case 3:
 894         channel_mask = _P (FRONT_LEFT) | _P (FRONT_RIGHT) | _P (FRONT_CENTER);
 895         break;
 896       case 4:
 897         /* lists both this and 'quad' but doesn't say how to distinguish the two */
 898         channel_mask =
 899             _P (FRONT_LEFT) | _P (FRONT_RIGHT) | _P (REAR_LEFT) |
 900             _P (REAR_RIGHT);
 901         break;
 902       case 6:
 903         channel_mask =
 904             _P (FRONT_LEFT) | _P (FRONT_LEFT_OF_CENTER) | _P (FRONT_CENTER) |
 905             _P (FRONT_RIGHT) | _P (FRONT_RIGHT_OF_CENTER) | _P (LFE1);
 906         break;
 907       default:
 908         channel_mask = gst_audio_channel_get_fallback_mask (aiff->channels);
 909         break;
 910     }
 911 
 912 
 913     if (channel_mask != 0) {
 914       gst_caps_set_simple (caps, "channel-mask", GST_TYPE_BITMASK, channel_mask,
 915           NULL);
 916     }
 917   }
 918 
 919   GST_DEBUG_OBJECT (aiff, "Created caps: %" GST_PTR_FORMAT, caps);
 920 
 921   return caps;
 922 }
 923 
 924 static GstFlowReturn
 925 gst_aiff_parse_stream_headers (GstAiffParse * aiff)
 926 {
 927   GstFlowReturn res;
 928   GstBuffer *buf = NULL;
 929   guint32 tag, size;
 930   gboolean gotdata = FALSE;
 931   gboolean done = FALSE;
 932   GstEvent **event_p;
 933   gint64 upstream_size = 0;
 934 
 935   gst_pad_peer_query_duration (aiff->sinkpad, GST_FORMAT_BYTES, &upstream_size);
 936   GST_DEBUG_OBJECT (aiff, "upstream size %" G_GUINT64_FORMAT, upstream_size);
 937 
 938   /* loop headers until we get data */
 939   while (!done) {
 940     if (aiff->streaming) {
 941       if (!gst_aiff_parse_peek_chunk_info (aiff, &tag, &size))
 942         return GST_FLOW_OK;
 943     } else {
 944       GstMapInfo info;
 945 
 946       if ((res =
 947               gst_pad_pull_range (aiff->sinkpad, aiff->offset, 8,
 948                   &buf)) != GST_FLOW_OK)
 949         goto header_read_error;
 950 
 951       gst_buffer_map (buf, &info, GST_MAP_READ);
 952       tag = GST_READ_UINT32_LE (info.data);
 953       size = GST_READ_UINT32_BE (info.data + 4);
 954       gst_buffer_unmap (buf, &info);
 955       gst_buffer_unref (buf);
 956       buf = NULL;
 957     }
 958 
 959     GST_INFO_OBJECT (aiff,
 960         "Got TAG: %" GST_FOURCC_FORMAT ", offset %" G_GUINT64_FORMAT,
 961         GST_FOURCC_ARGS (tag), aiff->offset);
 962 
 963     /* We just keep reading chunks until we find the one we're interested in.
 964      */
 965     switch (tag) {
 966       case GST_MAKE_FOURCC ('C', 'O', 'M', 'M'):{
 967         GstCaps *caps;
 968         GstEvent *event;
 969         gchar *stream_id;
 970 
 971         if (aiff->streaming) {
 972           if (!gst_aiff_parse_peek_chunk (aiff, &tag, &size))
 973             return GST_FLOW_OK;
 974 
 975           gst_adapter_flush (aiff->adapter, 8);
 976           aiff->offset += 8;
 977 
 978           buf = gst_adapter_take_buffer (aiff->adapter, size);
 979           aiff->offset += size;
 980         } else {
 981           if ((res = gst_aiff_parse_read_chunk (aiff,
 982                       &aiff->offset, &tag, &buf)) != GST_FLOW_OK)
 983             return res;
 984         }
 985 
 986         if (!gst_aiff_parse_parse_comm (aiff, buf))
 987           goto parse_header_error;
 988 
 989         /* do sanity checks of header fields */
 990         if (aiff->channels == 0)
 991           goto no_channels;
 992         if (aiff->rate == 0)
 993           goto no_rate;
 994 
 995         stream_id =
 996             gst_pad_create_stream_id (aiff->srcpad, GST_ELEMENT_CAST (aiff),
 997             NULL);
 998         event = gst_event_new_stream_start (stream_id);
 999         gst_event_set_group_id (event, gst_util_group_id_next ());
1000         gst_pad_push_event (aiff->srcpad, event);
1001         g_free (stream_id);
1002 
1003         GST_DEBUG_OBJECT (aiff, "creating the caps");
1004 
1005         caps = gst_aiff_parse_create_caps (aiff);
1006         if (caps == NULL)
1007           goto unknown_format;
1008 
1009         gst_pad_push_event (aiff->srcpad, gst_event_new_caps (caps));
1010         gst_caps_unref (caps);
1011 
1012         aiff->bytes_per_sample = aiff->channels * aiff->width / 8;
1013         aiff->bps = aiff->bytes_per_sample * aiff->rate;
1014 
1015         if (!aiff->tags)
1016           aiff->tags = gst_tag_list_new_empty ();
1017 
1018         {
1019           GstCaps *templ_caps = gst_pad_get_pad_template_caps (aiff->sinkpad);
1020           gst_pb_utils_add_codec_description_to_tag_list (aiff->tags,
1021               GST_TAG_CONTAINER_FORMAT, templ_caps);
1022           gst_caps_unref (templ_caps);
1023         }
1024 
1025         if (aiff->bps) {
1026           guint bitrate = aiff->bps * 8;
1027 
1028           GST_DEBUG_OBJECT (aiff, "adding bitrate of %u bps to tag list",
1029               bitrate);
1030 
1031           /* At the moment, aiffparse only supports uncompressed PCM data.
1032            * Therefore, nominal, actual, minimum, maximum bitrate are the same.
1033            * XXX: If AIFF-C support is extended to include compression,
1034            * make sure that aiff->bps is set properly. */
1035           gst_tag_list_add (aiff->tags, GST_TAG_MERGE_REPLACE,
1036               GST_TAG_BITRATE, bitrate, GST_TAG_NOMINAL_BITRATE, bitrate,
1037               GST_TAG_MINIMUM_BITRATE, bitrate, GST_TAG_MAXIMUM_BITRATE,
1038               bitrate, NULL);
1039         }
1040 
1041         if (aiff->bytes_per_sample <= 0)
1042           goto no_bytes_per_sample;
1043 
1044         aiff->got_comm = TRUE;
1045         break;
1046       }
1047       case GST_MAKE_FOURCC ('S', 'S', 'N', 'D'):{
1048         guint32 datasize;
1049 
1050         GST_DEBUG_OBJECT (aiff, "Got 'SSND' TAG, size : %d", size);
1051 
1052         /* Now, read the 8-byte header in the SSND chunk */
1053         if (aiff->streaming) {
1054           const guint8 *ssnddata = NULL;
1055 
1056           if (!gst_aiff_parse_peek_data (aiff, 16, &ssnddata))
1057             return GST_FLOW_OK;
1058 
1059           aiff->ssnd_offset = GST_READ_UINT32_BE (ssnddata + 8);
1060           aiff->ssnd_blocksize = GST_READ_UINT32_BE (ssnddata + 12);
1061           gst_adapter_unmap (aiff->adapter);
1062           gst_adapter_flush (aiff->adapter, 16);
1063         } else {
1064           GstBuffer *ssndbuf = NULL;
1065           GstMapInfo info;
1066 
1067           if ((res =
1068                   gst_pad_pull_range (aiff->sinkpad, aiff->offset, 16,
1069                       &ssndbuf)) != GST_FLOW_OK)
1070             goto header_read_error;
1071 
1072           gst_buffer_map (ssndbuf, &info, GST_MAP_READ);
1073           aiff->ssnd_offset = GST_READ_UINT32_BE (info.data + 8);
1074           aiff->ssnd_blocksize = GST_READ_UINT32_BE (info.data + 12);
1075           gst_buffer_unmap (ssndbuf, &info);
1076           gst_buffer_unref (ssndbuf);
1077         }
1078 
1079         gotdata = TRUE;
1080 
1081         /* 8 byte chunk header, 8 byte SSND header */
1082         aiff->offset += 16;
1083         datasize = size - 8;
1084 
1085         aiff->datastart = aiff->offset + aiff->ssnd_offset;
1086         /* file might be truncated */
1087         if (upstream_size) {
1088           size = MIN (datasize, (upstream_size - aiff->datastart));
1089         }
1090         aiff->datasize = (guint64) datasize;
1091         aiff->dataleft = (guint64) datasize;
1092         aiff->end_offset = datasize + aiff->datastart;
1093         if (!aiff->streaming) {
1094           /* We will continue looking at chunks until the end - to read tags,
1095            * etc. */
1096           aiff->offset += datasize;
1097         }
1098         GST_DEBUG_OBJECT (aiff, "datasize = %d", datasize);
1099         if (aiff->streaming) {
1100           done = TRUE;
1101         }
1102         break;
1103       }
1104       case GST_MAKE_FOURCC ('I', 'D', '3', ' '):{
1105         GstTagList *tags;
1106 
1107         if (aiff->streaming) {
1108           if (!gst_aiff_parse_peek_chunk (aiff, &tag, &size))
1109             return GST_FLOW_OK;
1110 
1111           gst_adapter_flush (aiff->adapter, 8);
1112           aiff->offset += 8;
1113 
1114           buf = gst_adapter_take_buffer (aiff->adapter, size);
1115         } else {
1116           if ((res = gst_aiff_parse_read_chunk (aiff,
1117                       &aiff->offset, &tag, &buf)) != GST_FLOW_OK)
1118             return res;
1119         }
1120 
1121         GST_LOG_OBJECT (aiff, "ID3 chunk of size %" G_GSIZE_FORMAT,
1122             gst_buffer_get_size (buf));
1123 
1124         tags = gst_tag_list_from_id3v2_tag (buf);
1125         gst_buffer_unref (buf);
1126 
1127         GST_INFO_OBJECT (aiff, "ID3 tags: %" GST_PTR_FORMAT, tags);
1128 
1129         if (aiff->tags == NULL) {
1130           aiff->tags = tags;
1131         } else {
1132           gst_tag_list_insert (aiff->tags, tags, GST_TAG_MERGE_APPEND);
1133           gst_tag_list_unref (tags);
1134         }
1135         break;
1136       }
1137       case GST_MAKE_FOURCC ('C', 'H', 'A', 'N'):{
1138         GST_FIXME_OBJECT (aiff, "Handle CHAN chunk with channel layouts");
1139 #ifdef GSTREAMER_LITE
1140         if (!gst_aiff_parse_ignore_chunk (aiff, tag, size)) {
1141           return GST_FLOW_OK;
1142         }
1143 #else
1144         gst_aiff_parse_ignore_chunk (aiff, tag, size);
1145 #endif
1146         break;
1147       }
1148       default:
1149 #ifdef GSTREAMER_LITE
1150         if (!gst_aiff_parse_ignore_chunk (aiff, tag, size)) {
1151           return GST_FLOW_OK;
1152         }
1153 #else
1154         gst_aiff_parse_ignore_chunk (aiff, tag, size);
1155 #endif
1156     }
1157 
1158     buf = NULL;
1159 
1160     if (upstream_size && (aiff->offset >= upstream_size)) {
1161       /* Now we have gone through the whole file */
1162       done = TRUE;
1163     }
1164   }
1165 
1166   /* We read all the chunks (in pull mode) or reached the SSND chunk
1167    * (in push mode). We must have both COMM and SSND now; error out
1168    * otherwise.
1169    */
1170   if (!aiff->got_comm) {
1171     GST_WARNING_OBJECT (aiff, "Failed to find COMM chunk");
1172     goto no_header;
1173   }
1174   if (!gotdata) {
1175     GST_WARNING_OBJECT (aiff, "Failed to find SSND chunk");
1176     goto no_data;
1177   }
1178 
1179   GST_DEBUG_OBJECT (aiff, "Finished parsing headers");
1180 
1181   if (gst_aiff_parse_calculate_duration (aiff)) {
1182     gst_segment_init (&aiff->segment, GST_FORMAT_TIME);
1183     aiff->segment.duration = aiff->duration;
1184   } else {
1185     /* no bitrate, let downstream peer do the math, we'll feed it bytes. */
1186     gst_segment_init (&aiff->segment, GST_FORMAT_BYTES);
1187     aiff->segment.duration = aiff->datasize;
1188   }
1189 
1190   /* now we have all the info to perform a pending seek if any, if no
1191    * event, this will still do the right thing and it will also send
1192    * the right segment event downstream. */
1193   gst_aiff_parse_perform_seek (aiff, aiff->seek_event, TRUE);
1194   /* remove pending event */
1195   event_p = &aiff->seek_event;
1196   gst_event_replace (event_p, NULL);
1197 
1198   /* we just started, we are discont */
1199   aiff->discont = TRUE;
1200 
1201   aiff->state = AIFF_PARSE_DATA;
1202 
1203   /* determine reasonable max buffer size,
1204    * that is, buffers not too small either size or time wise
1205    * so we do not end up with too many of them */
1206   /* var abuse */
1207   upstream_size = 0;
1208   gst_aiff_parse_time_to_bytepos (aiff, 40 * GST_MSECOND, &upstream_size);
1209   aiff->max_buf_size = upstream_size;
1210   aiff->max_buf_size = MAX (aiff->max_buf_size, MAX_BUFFER_SIZE);
1211   if (aiff->bytes_per_sample > 0)
1212     aiff->max_buf_size -= (aiff->max_buf_size % aiff->bytes_per_sample);
1213 
1214   GST_DEBUG_OBJECT (aiff, "max buffer size %u", aiff->max_buf_size);
1215 
1216   return GST_FLOW_OK;
1217 
1218   /* ERROR */
1219 no_header:
1220   {
1221     GST_ELEMENT_ERROR (aiff, STREAM, TYPE_NOT_FOUND, (NULL),
1222         ("Invalid AIFF header (no COMM found)"));
1223     return GST_FLOW_ERROR;
1224   }
1225 no_data:
1226   {
1227     GST_ELEMENT_ERROR (aiff, STREAM, TYPE_NOT_FOUND, (NULL),
1228         ("Invalid AIFF: no SSND found"));
1229     return GST_FLOW_ERROR;
1230   }
1231 parse_header_error:
1232   {
1233     GST_ELEMENT_ERROR (aiff, STREAM, DEMUX, (NULL),
1234         ("Couldn't parse audio header"));
1235     return GST_FLOW_ERROR;
1236   }
1237 no_channels:
1238   {
1239     GST_ELEMENT_ERROR (aiff, STREAM, FAILED, (NULL),
1240         ("Stream claims to contain no channels - invalid data"));
1241     return GST_FLOW_ERROR;
1242   }
1243 no_rate:
1244   {
1245     GST_ELEMENT_ERROR (aiff, STREAM, FAILED, (NULL),
1246         ("Stream with sample_rate == 0 - invalid data"));
1247     return GST_FLOW_ERROR;
1248   }
1249 no_bytes_per_sample:
1250   {
1251     GST_ELEMENT_ERROR (aiff, STREAM, FAILED, (NULL),
1252         ("Could not calculate bytes per sample - invalid data"));
1253     return GST_FLOW_ERROR;
1254   }
1255 unknown_format:
1256   {
1257     GST_ELEMENT_ERROR (aiff, STREAM, TYPE_NOT_FOUND, (NULL),
1258         ("No caps found for format 0x%x, %d channels, %d Hz",
1259             aiff->format, aiff->channels, aiff->rate));
1260     return GST_FLOW_ERROR;
1261   }
1262 header_read_error:
1263   {
1264     GST_ELEMENT_ERROR (aiff, STREAM, DEMUX, (NULL),
1265         ("Couldn't read in header"));
1266     return GST_FLOW_ERROR;
1267   }
1268 }
1269 
1270 /*
1271  * Read AIFF file tag when streaming
1272  */
1273 static GstFlowReturn
1274 gst_aiff_parse_parse_stream_init (GstAiffParse * aiff)
1275 {
1276   if (gst_adapter_available (aiff->adapter) >= 12) {
1277     GstBuffer *tmp;
1278 
1279     /* _take flushes the data */
1280     tmp = gst_adapter_take_buffer (aiff->adapter, 12);
1281 
1282     GST_DEBUG_OBJECT (aiff, "Parsing aiff header");
1283     if (!gst_aiff_parse_parse_file_header (aiff, tmp))
1284       return GST_FLOW_ERROR;
1285 
1286     aiff->offset += 12;
1287     /* Go to next state */
1288     aiff->state = AIFF_PARSE_HEADER;
1289   }
1290   return GST_FLOW_OK;
1291 }
1292 
1293 /* handle an event sent directly to the element.
1294  *
1295  * This event can be sent either in the READY state or the
1296  * >READY state. The only event of interest really is the seek
1297  * event.
1298  *
1299  * In the READY state we can only store the event and try to
1300  * respect it when going to PAUSED. We assume we are in the
1301  * READY state when our parsing state != AIFF_PARSE_DATA.
1302  *
1303  * When we are steaming, we can simply perform the seek right
1304  * away.
1305  */
1306 static gboolean
1307 gst_aiff_parse_send_event (GstElement * element, GstEvent * event)
1308 {
1309   GstAiffParse *aiff = GST_AIFF_PARSE (element);
1310   gboolean res = FALSE;
1311   GstEvent **event_p;
1312 
1313   GST_DEBUG_OBJECT (aiff, "received event %s", GST_EVENT_TYPE_NAME (event));
1314 
1315   switch (GST_EVENT_TYPE (event)) {
1316     case GST_EVENT_SEEK:
1317       if (aiff->state == AIFF_PARSE_DATA) {
1318         /* we can handle the seek directly when streaming data */
1319         res = gst_aiff_parse_perform_seek (aiff, event, FALSE);
1320       } else {
1321         GST_DEBUG_OBJECT (aiff, "queuing seek for later");
1322 
1323         event_p = &aiff->seek_event;
1324         gst_event_replace (event_p, event);
1325 
1326         /* we always return true */
1327         res = TRUE;
1328       }
1329       break;
1330     default:
1331       break;
1332   }
1333   gst_event_unref (event);
1334   return res;
1335 }
1336 
1337 static GstFlowReturn
1338 gst_aiff_parse_stream_data (GstAiffParse * aiff)
1339 {
1340   GstBuffer *buf = NULL;
1341   GstFlowReturn res = GST_FLOW_OK;
1342   guint64 desired, obtained;
1343   GstClockTime timestamp, next_timestamp, duration;
1344   guint64 pos, nextpos;
1345 
1346   if (aiff->bytes_per_sample <= 0) {
1347     GST_ELEMENT_ERROR (aiff, STREAM, WRONG_TYPE, (NULL),
1348         ("File is not a valid AIFF file (invalid bytes per sample)"));
1349     return GST_FLOW_ERROR;
1350   }
1351 
1352 iterate_adapter:
1353   GST_LOG_OBJECT (aiff,
1354       "offset: %" G_GINT64_FORMAT " , end: %" G_GINT64_FORMAT " , dataleft: %"
1355       G_GINT64_FORMAT, aiff->offset, aiff->end_offset, aiff->dataleft);
1356 
1357   /* Get the next n bytes and output them */
1358   if (aiff->dataleft == 0 || aiff->dataleft < aiff->bytes_per_sample)
1359     goto found_eos;
1360 
1361   /* scale the amount of data by the segment rate so we get equal
1362    * amounts of data regardless of the playback rate */
1363   desired =
1364       MIN (gst_guint64_to_gdouble (aiff->dataleft),
1365       aiff->max_buf_size * ABS (aiff->segment.rate));
1366 
1367   if (desired >= aiff->bytes_per_sample)
1368     desired -= (desired % aiff->bytes_per_sample);
1369 
1370 #ifdef GSTREAMER_LITE
1371   if (desired == 0) {
1372     GST_ELEMENT_ERROR (aiff, STREAM, DEMUX, (NULL),
1373               ("Invalid stream"));
1374     return GST_FLOW_ERROR;
1375   }
1376 #endif // GSTREAMER_LITE
1377 
1378   GST_LOG_OBJECT (aiff, "Fetching %" G_GINT64_FORMAT " bytes of data "
1379       "from the sinkpad", desired);
1380 
1381   if (aiff->streaming) {
1382     guint avail = gst_adapter_available (aiff->adapter);
1383 
1384     if (avail < desired) {
1385       GST_LOG_OBJECT (aiff, "Got only %d bytes of data from the sinkpad",
1386           avail);
1387       return GST_FLOW_OK;
1388     }
1389 
1390     buf = gst_adapter_take_buffer (aiff->adapter, desired);
1391   } else {
1392     if ((res = gst_pad_pull_range (aiff->sinkpad, aiff->offset,
1393                 desired, &buf)) != GST_FLOW_OK)
1394       goto pull_error;
1395   }
1396 
1397   /* If we have a pending close/start segment, send it now. */
1398   if (G_UNLIKELY (aiff->close_segment != NULL)) {
1399     gst_pad_push_event (aiff->srcpad, aiff->close_segment);
1400     aiff->close_segment = NULL;
1401   }
1402   if (G_UNLIKELY (aiff->start_segment != NULL)) {
1403     gst_pad_push_event (aiff->srcpad, aiff->start_segment);
1404     aiff->start_segment = NULL;
1405   }
1406   if (G_UNLIKELY (aiff->tags != NULL)) {
1407     gst_pad_push_event (aiff->srcpad, gst_event_new_tag (aiff->tags));
1408     aiff->tags = NULL;
1409   }
1410 
1411   obtained = gst_buffer_get_size (buf);
1412 
1413   /* our positions in bytes */
1414   pos = aiff->offset - aiff->datastart;
1415   nextpos = pos + obtained;
1416 
1417   /* update offsets, does not overflow. */
1418   GST_BUFFER_OFFSET (buf) = pos / aiff->bytes_per_sample;
1419   GST_BUFFER_OFFSET_END (buf) = nextpos / aiff->bytes_per_sample;
1420 
1421   if (aiff->bps > 0) {
1422     /* and timestamps if we have a bitrate, be careful for overflows */
1423     timestamp =
1424         gst_util_uint64_scale_ceil (pos, GST_SECOND, (guint64) aiff->bps);
1425     next_timestamp =
1426         gst_util_uint64_scale_ceil (nextpos, GST_SECOND, (guint64) aiff->bps);
1427     duration = next_timestamp - timestamp;
1428 
1429     /* update current running segment position */
1430     aiff->segment.position = next_timestamp;
1431   } else {
1432     /* no bitrate, all we know is that the first sample has timestamp 0, all
1433      * other positions and durations have unknown timestamp. */
1434     if (pos == 0)
1435       timestamp = 0;
1436     else
1437       timestamp = GST_CLOCK_TIME_NONE;
1438     duration = GST_CLOCK_TIME_NONE;
1439     /* update current running segment position with byte offset */
1440     aiff->segment.position = nextpos;
1441   }
1442   if (aiff->discont) {
1443     GST_DEBUG_OBJECT (aiff, "marking DISCONT");
1444     GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_DISCONT);
1445     aiff->discont = FALSE;
1446   }
1447 
1448   GST_BUFFER_TIMESTAMP (buf) = timestamp;
1449   GST_BUFFER_DURATION (buf) = duration;
1450 
1451   GST_LOG_OBJECT (aiff,
1452       "Got buffer. timestamp:%" GST_TIME_FORMAT " , duration:%" GST_TIME_FORMAT
1453       ", size:%" G_GUINT64_FORMAT, GST_TIME_ARGS (timestamp),
1454       GST_TIME_ARGS (duration), obtained);
1455 
1456   if ((res = gst_pad_push (aiff->srcpad, buf)) != GST_FLOW_OK)
1457     goto push_error;
1458 
1459   if (obtained < aiff->dataleft) {
1460     aiff->offset += obtained;
1461     aiff->dataleft -= obtained;
1462   } else {
1463     aiff->offset += aiff->dataleft;
1464     aiff->dataleft = 0;
1465   }
1466 
1467   /* Iterate until need more data, so adapter size won't grow */
1468   if (aiff->streaming) {
1469     GST_LOG_OBJECT (aiff,
1470         "offset: %" G_GINT64_FORMAT " , end: %" G_GINT64_FORMAT, aiff->offset,
1471         aiff->end_offset);
1472     goto iterate_adapter;
1473   }
1474   return res;
1475 
1476   /* ERROR */
1477 found_eos:
1478   {
1479     GST_DEBUG_OBJECT (aiff, "found EOS");
1480     return GST_FLOW_EOS;
1481   }
1482 pull_error:
1483   {
1484     /* check if we got EOS */
1485     if (res == GST_FLOW_EOS)
1486       goto found_eos;
1487 
1488     GST_WARNING_OBJECT (aiff,
1489         "Error getting %" G_GINT64_FORMAT " bytes from the "
1490         "sinkpad (dataleft = %" G_GINT64_FORMAT ")", desired, aiff->dataleft);
1491     return res;
1492   }
1493 push_error:
1494   {
1495     GST_INFO_OBJECT (aiff,
1496         "Error pushing on srcpad %s:%s, reason %s, is linked? = %d",
1497         GST_DEBUG_PAD_NAME (aiff->srcpad), gst_flow_get_name (res),
1498         gst_pad_is_linked (aiff->srcpad));
1499     return res;
1500   }
1501 }
1502 
1503 static void
1504 gst_aiff_parse_loop (GstPad * pad)
1505 {
1506   GstFlowReturn ret;
1507   GstAiffParse *aiff = GST_AIFF_PARSE (GST_PAD_PARENT (pad));
1508 
1509   GST_LOG_OBJECT (aiff, "process data");
1510 
1511   switch (aiff->state) {
1512     case AIFF_PARSE_START:
1513       GST_INFO_OBJECT (aiff, "AIFF_PARSE_START");
1514       if ((ret = gst_aiff_parse_stream_init (aiff)) != GST_FLOW_OK)
1515         goto pause;
1516 
1517       aiff->state = AIFF_PARSE_HEADER;
1518       /* fall-through */
1519 
1520     case AIFF_PARSE_HEADER:
1521       GST_INFO_OBJECT (aiff, "AIFF_PARSE_HEADER");
1522       if ((ret = gst_aiff_parse_stream_headers (aiff)) != GST_FLOW_OK)
1523         goto pause;
1524 
1525       aiff->state = AIFF_PARSE_DATA;
1526       GST_INFO_OBJECT (aiff, "AIFF_PARSE_DATA");
1527       /* fall-through */
1528 
1529     case AIFF_PARSE_DATA:
1530       if ((ret = gst_aiff_parse_stream_data (aiff)) != GST_FLOW_OK)
1531         goto pause;
1532       break;
1533     default:
1534       g_assert_not_reached ();
1535   }
1536   return;
1537 
1538   /* ERRORS */
1539 pause:
1540   {
1541     const gchar *reason = gst_flow_get_name (ret);
1542 
1543     GST_DEBUG_OBJECT (aiff, "pausing task, reason %s", reason);
1544     aiff->segment_running = FALSE;
1545     gst_pad_pause_task (pad);
1546 
1547     if (ret == GST_FLOW_EOS) {
1548       /* perform EOS logic */
1549       if (aiff->segment.flags & GST_SEEK_FLAG_SEGMENT) {
1550         GstClockTime stop;
1551 
1552         if ((stop = aiff->segment.stop) == -1)
1553           stop = aiff->segment.duration;
1554 
1555         gst_element_post_message (GST_ELEMENT_CAST (aiff),
1556             gst_message_new_segment_done (GST_OBJECT_CAST (aiff),
1557                 aiff->segment.format, stop));
1558         gst_pad_push_event (aiff->srcpad,
1559             gst_event_new_segment_done (aiff->segment.format, stop));
1560       } else {
1561         gst_pad_push_event (aiff->srcpad, gst_event_new_eos ());
1562       }
1563     } else if (ret < GST_FLOW_EOS || ret == GST_FLOW_NOT_LINKED) {
1564       /* for fatal errors we post an error message, post the error
1565        * first so the app knows about the error first. */
1566       GST_ELEMENT_FLOW_ERROR (aiff, ret);
1567       gst_pad_push_event (aiff->srcpad, gst_event_new_eos ());
1568     }
1569     return;
1570   }
1571 }
1572 
1573 static GstFlowReturn
1574 gst_aiff_parse_chain (GstPad * pad, GstObject * parent, GstBuffer * buf)
1575 {
1576   GstFlowReturn ret;
1577   GstAiffParse *aiff = GST_AIFF_PARSE (parent);
1578 
1579   GST_LOG_OBJECT (aiff, "adapter_push %" G_GSIZE_FORMAT " bytes",
1580       gst_buffer_get_size (buf));
1581 
1582   gst_adapter_push (aiff->adapter, buf);
1583 
1584   switch (aiff->state) {
1585     case AIFF_PARSE_START:
1586       GST_INFO_OBJECT (aiff, "AIFF_PARSE_START");
1587       if ((ret = gst_aiff_parse_parse_stream_init (aiff)) != GST_FLOW_OK)
1588         goto done;
1589 
1590       if (aiff->state != AIFF_PARSE_HEADER)
1591         break;
1592 
1593       /* otherwise fall-through */
1594     case AIFF_PARSE_HEADER:
1595       GST_INFO_OBJECT (aiff, "AIFF_PARSE_HEADER");
1596       if ((ret = gst_aiff_parse_stream_headers (aiff)) != GST_FLOW_OK)
1597         goto done;
1598 
1599       if (!aiff->got_comm || aiff->datastart == 0)
1600         break;
1601 
1602       aiff->state = AIFF_PARSE_DATA;
1603       GST_INFO_OBJECT (aiff, "AIFF_PARSE_DATA");
1604 
1605       /* fall-through */
1606     case AIFF_PARSE_DATA:
1607       if ((ret = gst_aiff_parse_stream_data (aiff)) != GST_FLOW_OK)
1608         goto done;
1609       break;
1610     default:
1611       g_return_val_if_reached (GST_FLOW_ERROR);
1612   }
1613 done:
1614   return ret;
1615 }
1616 
1617 static gboolean
1618 gst_aiff_parse_pad_convert (GstPad * pad,
1619     GstFormat src_format, gint64 src_value,
1620     GstFormat * dest_format, gint64 * dest_value)
1621 {
1622   GstAiffParse *aiffparse;
1623   gboolean res = TRUE;
1624 
1625   aiffparse = GST_AIFF_PARSE (GST_PAD_PARENT (pad));
1626 
1627   if (*dest_format == src_format) {
1628     *dest_value = src_value;
1629     return TRUE;
1630   }
1631 
1632   if (aiffparse->bytes_per_sample <= 0)
1633     return FALSE;
1634 
1635   GST_INFO_OBJECT (aiffparse, "converting value from %s to %s",
1636       gst_format_get_name (src_format), gst_format_get_name (*dest_format));
1637 
1638   switch (src_format) {
1639     case GST_FORMAT_BYTES:
1640       switch (*dest_format) {
1641         case GST_FORMAT_DEFAULT:
1642           *dest_value = src_value / aiffparse->bytes_per_sample;
1643           break;
1644         case GST_FORMAT_TIME:
1645           if (aiffparse->bps > 0) {
1646             *dest_value = gst_util_uint64_scale_ceil (src_value, GST_SECOND,
1647                 (guint64) aiffparse->bps);
1648             break;
1649           }
1650           /* Else fallthrough */
1651         default:
1652           res = FALSE;
1653           goto done;
1654       }
1655       break;
1656 
1657     case GST_FORMAT_DEFAULT:
1658       switch (*dest_format) {
1659         case GST_FORMAT_BYTES:
1660           *dest_value = src_value * aiffparse->bytes_per_sample;
1661           break;
1662         case GST_FORMAT_TIME:
1663           *dest_value = gst_util_uint64_scale (src_value, GST_SECOND,
1664               (guint64) aiffparse->rate);
1665           break;
1666         default:
1667           res = FALSE;
1668           goto done;
1669       }
1670       break;
1671 
1672     case GST_FORMAT_TIME:
1673       switch (*dest_format) {
1674         case GST_FORMAT_BYTES:
1675           if (aiffparse->bps > 0) {
1676             *dest_value = gst_util_uint64_scale (src_value,
1677                 (guint64) aiffparse->bps, GST_SECOND);
1678             break;
1679           }
1680           /* Else fallthrough */
1681           break;
1682         case GST_FORMAT_DEFAULT:
1683           *dest_value = gst_util_uint64_scale (src_value,
1684               (guint64) aiffparse->rate, GST_SECOND);
1685           break;
1686         default:
1687           res = FALSE;
1688           goto done;
1689       }
1690       break;
1691 
1692     default:
1693       res = FALSE;
1694       goto done;
1695   }
1696 
1697 done:
1698   return res;
1699 
1700 }
1701 
1702 /* handle queries for location and length in requested format */
1703 static gboolean
1704 gst_aiff_parse_pad_query (GstPad * pad, GstObject * parent, GstQuery * query)
1705 {
1706   gboolean res = FALSE;
1707   GstAiffParse *aiff = GST_AIFF_PARSE (parent);
1708 
1709   switch (GST_QUERY_TYPE (query)) {
1710     case GST_QUERY_DURATION:
1711     {
1712       gint64 duration = 0;
1713       GstFormat format;
1714 
1715       /* only if we know */
1716       if (aiff->state != AIFF_PARSE_DATA)
1717         break;
1718 
1719       gst_query_parse_duration (query, &format, NULL);
1720 
1721       switch (format) {
1722         case GST_FORMAT_TIME:{
1723           if ((res = gst_aiff_parse_calculate_duration (aiff))) {
1724             duration = aiff->duration;
1725           }
1726           break;
1727         }
1728         default:
1729           format = GST_FORMAT_BYTES;
1730           duration = aiff->datasize;
1731           break;
1732       }
1733       gst_query_set_duration (query, format, duration);
1734       break;
1735     }
1736     case GST_QUERY_CONVERT:
1737     {
1738       gint64 srcvalue, dstvalue;
1739       GstFormat srcformat, dstformat;
1740 
1741       /* only if we know */
1742       if (aiff->state != AIFF_PARSE_DATA)
1743         break;
1744 
1745       gst_query_parse_convert (query, &srcformat, &srcvalue,
1746           &dstformat, &dstvalue);
1747       res = gst_aiff_parse_pad_convert (pad, srcformat, srcvalue,
1748           &dstformat, &dstvalue);
1749       if (res)
1750         gst_query_set_convert (query, srcformat, srcvalue, dstformat, dstvalue);
1751       break;
1752     }
1753     case GST_QUERY_SEEKING:{
1754       GstFormat fmt;
1755 
1756       /* only if we know */
1757       if (aiff->state != AIFF_PARSE_DATA)
1758         break;
1759 
1760       gst_query_parse_seeking (query, &fmt, NULL, NULL, NULL);
1761       if (fmt == GST_FORMAT_TIME) {
1762         gboolean seekable = TRUE;
1763 
1764         if (!gst_aiff_parse_calculate_duration (aiff)) {
1765           seekable = FALSE;
1766         }
1767         gst_query_set_seeking (query, GST_FORMAT_TIME, seekable,
1768             0, aiff->duration);
1769         res = TRUE;
1770       }
1771       break;
1772     }
1773     default:
1774       res = gst_pad_query_default (pad, parent, query);
1775       break;
1776   }
1777   return res;
1778 }
1779 
1780 static gboolean
1781 gst_aiff_parse_srcpad_event (GstPad * pad, GstObject * parent, GstEvent * event)
1782 {
1783   GstAiffParse *aiffparse = GST_AIFF_PARSE (parent);
1784   gboolean res = FALSE;
1785 
1786   GST_DEBUG_OBJECT (aiffparse, "%s event", GST_EVENT_TYPE_NAME (event));
1787 
1788   switch (GST_EVENT_TYPE (event)) {
1789     case GST_EVENT_SEEK:
1790       /* can only handle events when we are in the data state */
1791       if (aiffparse->state == AIFF_PARSE_DATA) {
1792         res = gst_aiff_parse_perform_seek (aiffparse, event, FALSE);
1793       }
1794       gst_event_unref (event);
1795       break;
1796     default:
1797       res = gst_pad_push_event (aiffparse->sinkpad, event);
1798       break;
1799   }
1800   return res;
1801 }
1802 
1803 static gboolean
1804 gst_aiff_parse_sink_activate (GstPad * sinkpad, GstObject * parent)
1805 {
1806   GstQuery *query;
1807   gboolean pull_mode;
1808 
1809   query = gst_query_new_scheduling ();
1810 
1811   if (!gst_pad_peer_query (sinkpad, query)) {
1812     gst_query_unref (query);
1813     goto activate_push;
1814   }
1815 
1816   pull_mode = gst_query_has_scheduling_mode_with_flags (query,
1817       GST_PAD_MODE_PULL, GST_SCHEDULING_FLAG_SEEKABLE);
1818   gst_query_unref (query);
1819 
1820   if (!pull_mode)
1821     goto activate_push;
1822 
1823   GST_DEBUG_OBJECT (sinkpad, "going to pull mode");
1824   return gst_pad_activate_mode (sinkpad, GST_PAD_MODE_PULL, TRUE);
1825 
1826 activate_push:
1827   {
1828     GST_DEBUG_OBJECT (sinkpad, "going to push (streaming) mode");
1829     return gst_pad_activate_mode (sinkpad, GST_PAD_MODE_PUSH, TRUE);
1830   }
1831 }
1832 
1833 
1834 static gboolean
1835 gst_aiff_parse_sink_activate_mode (GstPad * sinkpad, GstObject * parent,
1836     GstPadMode mode, gboolean active)
1837 {
1838   gboolean res;
1839   GstAiffParse *aiff = GST_AIFF_PARSE (parent);
1840 
1841   if (aiff->adapter) {
1842     g_object_unref (aiff->adapter);
1843     aiff->adapter = NULL;
1844   }
1845 
1846   switch (mode) {
1847     case GST_PAD_MODE_PUSH:
1848       if (active) {
1849         aiff->streaming = TRUE;
1850         aiff->adapter = gst_adapter_new ();
1851       }
1852       res = TRUE;
1853       break;
1854     case GST_PAD_MODE_PULL:
1855       if (active) {
1856         aiff->streaming = FALSE;
1857         aiff->adapter = NULL;
1858         aiff->segment_running = TRUE;
1859         res =
1860             gst_pad_start_task (sinkpad, (GstTaskFunction) gst_aiff_parse_loop,
1861             sinkpad, NULL);
1862       } else {
1863         aiff->segment_running = FALSE;
1864         res = gst_pad_stop_task (sinkpad);
1865       }
1866       break;
1867     default:
1868       res = FALSE;
1869       break;
1870   }
1871   return res;
1872 };
1873 
1874 static GstFlowReturn
1875 gst_aiff_parse_flush_data (GstAiffParse * aiff)
1876 {
1877   GstFlowReturn ret = GST_FLOW_OK;
1878   guint av;
1879 
1880   if ((av = gst_adapter_available (aiff->adapter)) > 0) {
1881     aiff->dataleft = av;
1882     aiff->end_offset = aiff->offset + av;
1883     ret = gst_aiff_parse_stream_data (aiff);
1884   }
1885 
1886   return ret;
1887 }
1888 
1889 
1890 static gboolean
1891 gst_aiff_parse_sink_event (GstPad * pad, GstObject * parent, GstEvent * event)
1892 {
1893   GstAiffParse *aiff = GST_AIFF_PARSE (parent);
1894   gboolean ret = TRUE;
1895 
1896   GST_DEBUG_OBJECT (aiff, "handling %s event", GST_EVENT_TYPE_NAME (event));
1897 
1898   switch (GST_EVENT_TYPE (event)) {
1899     case GST_EVENT_CAPS:
1900     {
1901       /* discard, we'll come up with proper src caps */
1902       gst_event_unref (event);
1903       break;
1904     }
1905     case GST_EVENT_SEGMENT:
1906     {
1907       gint64 start, stop, offset = 0, end_offset = -1;
1908       GstSegment segment;
1909 
1910       /* some debug output */
1911       gst_event_copy_segment (event, &segment);
1912       GST_DEBUG_OBJECT (aiff, "received segment %" GST_SEGMENT_FORMAT,
1913           &segment);
1914 
1915       /* now we are either committed to TIME or BYTE format,
1916        * and we only expect a BYTE segment, e.g. following a seek */
1917       if (segment.format == GST_FORMAT_BYTES) {
1918         /* handle (un)signed issues */
1919         start = segment.start;
1920         stop = segment.stop;
1921         if (start > 0) {
1922           offset = start;
1923           start -= aiff->datastart;
1924           start = MAX (start, 0);
1925         }
1926         if (stop > 0) {
1927           end_offset = stop;
1928           stop -= aiff->datastart;
1929           stop = MAX (stop, 0);
1930         }
1931         if (aiff->state == AIFF_PARSE_DATA &&
1932             aiff->segment.format == GST_FORMAT_TIME) {
1933           /* operating in format TIME, so we can convert */
1934           if (aiff->bps) {
1935             if (start >= 0)
1936               start =
1937                   gst_util_uint64_scale_ceil (start, GST_SECOND,
1938                   (guint64) aiff->bps);
1939             if (stop >= 0)
1940               stop =
1941                   gst_util_uint64_scale_ceil (stop, GST_SECOND,
1942                   (guint64) aiff->bps);
1943           } else {
1944             GST_DEBUG_OBJECT (aiff, "unable to compute segment start/stop");
1945             goto exit;
1946           }
1947         }
1948       } else {
1949         GST_DEBUG_OBJECT (aiff, "unsupported segment format, ignoring");
1950         goto exit;
1951       }
1952 
1953       segment.start = start;
1954       segment.stop = stop;
1955 
1956       /* accept upstream's notion of segment and distribute along */
1957       if (aiff->state == AIFF_PARSE_DATA) {
1958         segment.format = aiff->segment.format;
1959         segment.time = segment.position = segment.start;
1960         segment.duration = aiff->segment.duration;
1961       }
1962 
1963       gst_segment_copy_into (&segment, &aiff->segment);
1964 
1965       if (aiff->start_segment)
1966         gst_event_unref (aiff->start_segment);
1967 
1968       aiff->start_segment = gst_event_new_segment (&segment);
1969 
1970       /* If the seek is within the same SSND chunk and there is no new
1971        * end_offset defined keep the previous end_offset. This will avoid noise
1972        * at the end of playback if e.g. a metadata chunk is located at the end
1973        * of the file. */
1974       if (aiff->end_offset > 0 && offset < aiff->end_offset &&
1975           offset >= aiff->datastart && end_offset == -1) {
1976         end_offset = aiff->end_offset;
1977       }
1978 
1979       /* stream leftover data in current segment */
1980       if (aiff->state == AIFF_PARSE_DATA)
1981         gst_aiff_parse_flush_data (aiff);
1982       /* and set up streaming thread for next one */
1983       aiff->offset = offset;
1984       aiff->end_offset = end_offset;
1985       if (aiff->end_offset > 0) {
1986         aiff->dataleft = aiff->end_offset - aiff->offset;
1987       } else {
1988         /* infinity; upstream will EOS when done */
1989         aiff->dataleft = G_MAXUINT64;
1990       }
1991     exit:
1992       gst_event_unref (event);
1993       break;
1994     }
1995     case GST_EVENT_FLUSH_START:
1996       ret = gst_pad_push_event (aiff->srcpad, event);
1997       break;
1998     case GST_EVENT_FLUSH_STOP:
1999       ret = gst_pad_push_event (aiff->srcpad, event);
2000       gst_adapter_clear (aiff->adapter);
2001       break;
2002     default:
2003       ret = gst_pad_event_default (aiff->sinkpad, parent, event);
2004       break;
2005   }
2006 
2007   return ret;
2008 }
2009 
2010 static GstStateChangeReturn
2011 gst_aiff_parse_change_state (GstElement * element, GstStateChange transition)
2012 {
2013   GstStateChangeReturn ret;
2014   GstAiffParse *aiff = GST_AIFF_PARSE (element);
2015 
2016   switch (transition) {
2017     case GST_STATE_CHANGE_NULL_TO_READY:
2018       break;
2019     case GST_STATE_CHANGE_READY_TO_PAUSED:
2020       gst_aiff_parse_reset (aiff);
2021       break;
2022     case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
2023       break;
2024     default:
2025       break;
2026   }
2027 
2028   ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
2029 
2030   switch (transition) {
2031     case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
2032       break;
2033     case GST_STATE_CHANGE_PAUSED_TO_READY:
2034       gst_aiff_parse_reset (aiff);
2035       break;
2036     case GST_STATE_CHANGE_READY_TO_NULL:
2037       break;
2038     default:
2039       break;
2040   }
2041   return ret;
2042 }