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 static void
 647 gst_aiff_parse_ignore_chunk (GstAiffParse * aiff, guint32 tag, guint32 size)
 648 {
 649 #ifdef GSTREAMER_LITE
 650     guint64 flush;
 651 #else
 652     guint flush;
 653 #endif
 654 
 655   if (aiff->streaming) {
 656     if (!gst_aiff_parse_peek_chunk (aiff, &tag, &size))
 657       return;
 658   }
 659   GST_WARNING_OBJECT (aiff, "Ignoring tag %" GST_FOURCC_FORMAT,
 660       GST_FOURCC_ARGS (tag));
 661 #ifdef GSTREAMER_LITE
 662   flush = 8 + (((guint64)size + 1) & ~1);
 663 #else
 664   flush = 8 + ((size + 1) & ~1);
 665 #endif
 666   aiff->offset += flush;
 667   if (aiff->streaming) {
 668     gst_adapter_flush (aiff->adapter, flush);
 669   }
 670 }
 671 
 672 static double
 673 gst_aiff_parse_read_IEEE80 (guint8 * buf)
 674 {
 675   int s = buf[0] & 0xff;
 676   int e = ((buf[0] & 0x7f) << 8) | (buf[1] & 0xff);
 677   double f = ((unsigned long) (buf[2] & 0xff) << 24) |
 678       ((buf[3] & 0xff) << 16) | ((buf[4] & 0xff) << 8) | (buf[5] & 0xff);
 679 
 680   if (e == 32767) {
 681     if (buf[2] & 0x80)
 682       return HUGE_VAL;          /* Really NaN, but this won't happen in reality */
 683     else {
 684       if (s)
 685         return -HUGE_VAL;
 686       else
 687         return HUGE_VAL;
 688     }
 689   }
 690 
 691   f = ldexp (f, 32);
 692   f += ((buf[6] & 0xff) << 24) |
 693       ((buf[7] & 0xff) << 16) | ((buf[8] & 0xff) << 8) | (buf[9] & 0xff);
 694 
 695   return ldexp (f, e - 16446);
 696 }
 697 
 698 static gboolean
 699 gst_aiff_parse_parse_comm (GstAiffParse * aiff, GstBuffer * buf)
 700 {
 701   int size;
 702   GstMapInfo info;
 703   guint32 fourcc;
 704 
 705   if (!gst_buffer_map (buf, &info, GST_MAP_READ)) {
 706     GST_WARNING_OBJECT (aiff, "Can't map buffer");
 707     gst_buffer_unref (buf);
 708     return FALSE;
 709   }
 710 
 711   if (aiff->is_aifc)
 712     size = 22;
 713   else
 714     size = 18;
 715 
 716   if (info.size < size)
 717     goto too_small;
 718 
 719   aiff->channels = GST_READ_UINT16_BE (info.data);
 720   aiff->total_frames = GST_READ_UINT32_BE (info.data + 2);
 721   aiff->depth = GST_READ_UINT16_BE (info.data + 6);
 722   aiff->width = GST_ROUND_UP_8 (aiff->depth);
 723   aiff->rate = (int) gst_aiff_parse_read_IEEE80 (info.data + 8);
 724 
 725   aiff->floating_point = FALSE;
 726 
 727   if (aiff->is_aifc) {
 728     fourcc = GST_READ_UINT32_LE (info.data + 18);
 729 
 730     /* We only support the 'trivial' uncompressed AIFC, but it can be
 731      * either big or little endian */
 732     switch (fourcc) {
 733       case GST_MAKE_FOURCC ('N', 'O', 'N', 'E'):
 734         aiff->endianness = G_BIG_ENDIAN;
 735         break;
 736       case GST_MAKE_FOURCC ('s', 'o', 'w', 't'):
 737         aiff->endianness = G_LITTLE_ENDIAN;
 738         break;
 739       case GST_MAKE_FOURCC ('F', 'L', '3', '2'):
 740       case GST_MAKE_FOURCC ('f', 'l', '3', '2'):
 741         aiff->floating_point = TRUE;
 742         aiff->width = aiff->depth = 32;
 743         aiff->endianness = G_BIG_ENDIAN;
 744         break;
 745       case GST_MAKE_FOURCC ('f', 'l', '6', '4'):
 746         aiff->floating_point = TRUE;
 747         aiff->width = aiff->depth = 64;
 748         aiff->endianness = G_BIG_ENDIAN;
 749         break;
 750       default:
 751         goto unknown_compression;
 752     }
 753   } else
 754     aiff->endianness = G_BIG_ENDIAN;
 755 
 756   gst_buffer_unmap (buf, &info);
 757   gst_buffer_unref (buf);
 758 
 759   return TRUE;
 760 
 761   /* ERRORS */
 762 too_small:
 763   {
 764     GST_WARNING_OBJECT (aiff, "COMM chunk too short, cannot parse header");
 765     gst_buffer_unmap (buf, &info);
 766     gst_buffer_unref (buf);
 767     return FALSE;
 768   }
 769 unknown_compression:
 770   {
 771     GST_WARNING_OBJECT (aiff, "Unsupported compression in AIFC "
 772         "file: %" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (fourcc));
 773     gst_buffer_unmap (buf, &info);
 774     gst_buffer_unref (buf);
 775     return FALSE;
 776   }
 777 }
 778 
 779 static GstFlowReturn
 780 gst_aiff_parse_read_chunk (GstAiffParse * aiff, guint64 * offset, guint32 * tag,
 781     GstBuffer ** data)
 782 {
 783   guint size;
 784   GstFlowReturn res;
 785   GstBuffer *buf = NULL;
 786   GstMapInfo info;
 787 
 788   if ((res =
 789           gst_pad_pull_range (aiff->sinkpad, *offset, 8, &buf)) != GST_FLOW_OK)
 790     return res;
 791 
 792   gst_buffer_map (buf, &info, GST_MAP_READ);
 793   *tag = GST_READ_UINT32_LE (info.data);
 794   size = GST_READ_UINT32_BE (info.data + 4);
 795   gst_buffer_unmap (buf, &info);
 796   gst_buffer_unref (buf);
 797   buf = NULL;
 798 
 799   if ((res =
 800           gst_pad_pull_range (aiff->sinkpad, (*offset) + 8, size,
 801               &buf)) != GST_FLOW_OK)
 802     return res;
 803   else if (gst_buffer_get_size (buf) < size)
 804     goto too_small;
 805 
 806   *data = buf;
 807   *offset += 8 + GST_ROUND_UP_2 (size);
 808 
 809   return GST_FLOW_OK;
 810 
 811   /* ERRORS */
 812 too_small:
 813   {
 814     /* short read, we return EOS to mark the EOS case */
 815     GST_DEBUG_OBJECT (aiff,
 816         "not enough data (available=%" G_GSIZE_FORMAT ", needed=%u)",
 817         gst_buffer_get_size (buf), size);
 818     gst_buffer_unref (buf);
 819     return GST_FLOW_EOS;
 820   }
 821 
 822 }
 823 
 824 #define _P(pos) (G_GUINT64_CONSTANT (1) << GST_AUDIO_CHANNEL_POSITION_ ##pos)
 825 
 826 static GstCaps *
 827 gst_aiff_parse_create_caps (GstAiffParse * aiff)
 828 {
 829   GstCaps *caps = NULL;
 830   const gchar *format = NULL;
 831   guint64 channel_mask;
 832 
 833   if (aiff->floating_point) {
 834     if (aiff->endianness == G_BIG_ENDIAN) {
 835       if (aiff->width == 32)
 836         format = "F32BE";
 837       else if (aiff->width == 64)
 838         format = "F64BE";
 839     }
 840   } else {
 841     if (aiff->endianness == G_BIG_ENDIAN) {
 842       if (aiff->width == 8)
 843         format = "S8";
 844       else if (aiff->width == 16)
 845         format = "S16BE";
 846       else if (aiff->width == 24)
 847         format = "S24BE";
 848       else if (aiff->width == 32)
 849         format = "S32BE";
 850     } else {
 851       if (aiff->width == 8)
 852         format = "S8";
 853       else if (aiff->width == 16)
 854         format = "S16LE";
 855       else if (aiff->width == 24)
 856         format = "S24LE";
 857       else if (aiff->width == 32)
 858         format = "S32LE";
 859     }
 860   }
 861   if (format) {
 862     caps = gst_caps_new_simple ("audio/x-raw",
 863         "format", G_TYPE_STRING, format,
 864         "channels", G_TYPE_INT, aiff->channels,
 865         "layout", G_TYPE_STRING, "interleaved",
 866         "rate", G_TYPE_INT, aiff->rate, NULL);
 867   }
 868 
 869   if (aiff->channels > 2) {
 870     GST_FIXME_OBJECT (aiff, "using fallback channel layout for %d channels",
 871         aiff->channels);
 872 
 873     /* based on AIFF-1.3.pdf */
 874     switch (aiff->channels) {
 875       case 1:
 876         channel_mask = 0;
 877         break;
 878       case 2:
 879         channel_mask = _P (FRONT_LEFT) | _P (FRONT_RIGHT);
 880         break;
 881       case 3:
 882         channel_mask = _P (FRONT_LEFT) | _P (FRONT_RIGHT) | _P (FRONT_CENTER);
 883         break;
 884       case 4:
 885         /* lists both this and 'quad' but doesn't say how to distinguish the two */
 886         channel_mask =
 887             _P (FRONT_LEFT) | _P (FRONT_RIGHT) | _P (REAR_LEFT) |
 888             _P (REAR_RIGHT);
 889         break;
 890       case 6:
 891         channel_mask =
 892             _P (FRONT_LEFT) | _P (FRONT_LEFT_OF_CENTER) | _P (FRONT_CENTER) |
 893             _P (FRONT_RIGHT) | _P (FRONT_RIGHT_OF_CENTER) | _P (LFE1);
 894         break;
 895       default:
 896         channel_mask = gst_audio_channel_get_fallback_mask (aiff->channels);
 897         break;
 898     }
 899 
 900 
 901     if (channel_mask != 0) {
 902       gst_caps_set_simple (caps, "channel-mask", GST_TYPE_BITMASK, channel_mask,
 903           NULL);
 904     }
 905   }
 906 
 907   GST_DEBUG_OBJECT (aiff, "Created caps: %" GST_PTR_FORMAT, caps);
 908 
 909   return caps;
 910 }
 911 
 912 static GstFlowReturn
 913 gst_aiff_parse_stream_headers (GstAiffParse * aiff)
 914 {
 915   GstFlowReturn res;
 916   GstBuffer *buf = NULL;
 917   guint32 tag, size;
 918   gboolean gotdata = FALSE;
 919   gboolean done = FALSE;
 920   GstEvent **event_p;
 921   gint64 upstream_size = 0;
 922 
 923   gst_pad_peer_query_duration (aiff->sinkpad, GST_FORMAT_BYTES, &upstream_size);
 924   GST_DEBUG_OBJECT (aiff, "upstream size %" G_GUINT64_FORMAT, upstream_size);
 925 
 926   /* loop headers until we get data */
 927   while (!done) {
 928     if (aiff->streaming) {
 929       if (!gst_aiff_parse_peek_chunk_info (aiff, &tag, &size))
 930         return GST_FLOW_OK;
 931     } else {
 932       GstMapInfo info;
 933 
 934       if ((res =
 935               gst_pad_pull_range (aiff->sinkpad, aiff->offset, 8,
 936                   &buf)) != GST_FLOW_OK)
 937         goto header_read_error;
 938 
 939       gst_buffer_map (buf, &info, GST_MAP_READ);
 940       tag = GST_READ_UINT32_LE (info.data);
 941       size = GST_READ_UINT32_BE (info.data + 4);
 942       gst_buffer_unmap (buf, &info);
 943       gst_buffer_unref (buf);
 944       buf = NULL;
 945     }
 946 
 947     GST_INFO_OBJECT (aiff,
 948         "Got TAG: %" GST_FOURCC_FORMAT ", offset %" G_GUINT64_FORMAT,
 949         GST_FOURCC_ARGS (tag), aiff->offset);
 950 
 951     /* We just keep reading chunks until we find the one we're interested in.
 952      */
 953     switch (tag) {
 954       case GST_MAKE_FOURCC ('C', 'O', 'M', 'M'):{
 955         GstCaps *caps;
 956         GstEvent *event;
 957         gchar *stream_id;
 958 
 959         if (aiff->streaming) {
 960           if (!gst_aiff_parse_peek_chunk (aiff, &tag, &size))
 961             return GST_FLOW_OK;
 962 
 963           gst_adapter_flush (aiff->adapter, 8);
 964           aiff->offset += 8;
 965 
 966           buf = gst_adapter_take_buffer (aiff->adapter, size);
 967           aiff->offset += size;
 968         } else {
 969           if ((res = gst_aiff_parse_read_chunk (aiff,
 970                       &aiff->offset, &tag, &buf)) != GST_FLOW_OK)
 971             return res;
 972         }
 973 
 974         if (!gst_aiff_parse_parse_comm (aiff, buf))
 975           goto parse_header_error;
 976 
 977         /* do sanity checks of header fields */
 978         if (aiff->channels == 0)
 979           goto no_channels;
 980         if (aiff->rate == 0)
 981           goto no_rate;
 982 
 983         stream_id =
 984             gst_pad_create_stream_id (aiff->srcpad, GST_ELEMENT_CAST (aiff),
 985             NULL);
 986         event = gst_event_new_stream_start (stream_id);
 987         gst_event_set_group_id (event, gst_util_group_id_next ());
 988         gst_pad_push_event (aiff->srcpad, event);
 989         g_free (stream_id);
 990 
 991         GST_DEBUG_OBJECT (aiff, "creating the caps");
 992 
 993         caps = gst_aiff_parse_create_caps (aiff);
 994         if (caps == NULL)
 995           goto unknown_format;
 996 
 997         gst_pad_push_event (aiff->srcpad, gst_event_new_caps (caps));
 998         gst_caps_unref (caps);
 999 
1000         aiff->bytes_per_sample = aiff->channels * aiff->width / 8;
1001         aiff->bps = aiff->bytes_per_sample * aiff->rate;
1002 
1003         if (!aiff->tags)
1004           aiff->tags = gst_tag_list_new_empty ();
1005 
1006         {
1007           GstCaps *templ_caps = gst_pad_get_pad_template_caps (aiff->sinkpad);
1008           gst_pb_utils_add_codec_description_to_tag_list (aiff->tags,
1009               GST_TAG_CONTAINER_FORMAT, templ_caps);
1010           gst_caps_unref (templ_caps);
1011         }
1012 
1013         if (aiff->bps) {
1014           guint bitrate = aiff->bps * 8;
1015 
1016           GST_DEBUG_OBJECT (aiff, "adding bitrate of %u bps to tag list",
1017               bitrate);
1018 
1019           /* At the moment, aiffparse only supports uncompressed PCM data.
1020            * Therefore, nominal, actual, minimum, maximum bitrate are the same.
1021            * XXX: If AIFF-C support is extended to include compression,
1022            * make sure that aiff->bps is set properly. */
1023           gst_tag_list_add (aiff->tags, GST_TAG_MERGE_REPLACE,
1024               GST_TAG_BITRATE, bitrate, GST_TAG_NOMINAL_BITRATE, bitrate,
1025               GST_TAG_MINIMUM_BITRATE, bitrate, GST_TAG_MAXIMUM_BITRATE,
1026               bitrate, NULL);
1027         }
1028 
1029         if (aiff->bytes_per_sample <= 0)
1030           goto no_bytes_per_sample;
1031 
1032         aiff->got_comm = TRUE;
1033         break;
1034       }
1035       case GST_MAKE_FOURCC ('S', 'S', 'N', 'D'):{
1036         guint32 datasize;
1037 
1038         GST_DEBUG_OBJECT (aiff, "Got 'SSND' TAG, size : %d", size);
1039 
1040         /* Now, read the 8-byte header in the SSND chunk */
1041         if (aiff->streaming) {
1042           const guint8 *ssnddata = NULL;
1043 
1044           if (!gst_aiff_parse_peek_data (aiff, 16, &ssnddata))
1045             return GST_FLOW_OK;
1046 
1047           aiff->ssnd_offset = GST_READ_UINT32_BE (ssnddata + 8);
1048           aiff->ssnd_blocksize = GST_READ_UINT32_BE (ssnddata + 12);
1049           gst_adapter_unmap (aiff->adapter);
1050           gst_adapter_flush (aiff->adapter, 16);
1051         } else {
1052           GstBuffer *ssndbuf = NULL;
1053           GstMapInfo info;
1054 
1055           if ((res =
1056                   gst_pad_pull_range (aiff->sinkpad, aiff->offset, 16,
1057                       &ssndbuf)) != GST_FLOW_OK)
1058             goto header_read_error;
1059 
1060           gst_buffer_map (ssndbuf, &info, GST_MAP_READ);
1061           aiff->ssnd_offset = GST_READ_UINT32_BE (info.data + 8);
1062           aiff->ssnd_blocksize = GST_READ_UINT32_BE (info.data + 12);
1063           gst_buffer_unmap (ssndbuf, &info);
1064           gst_buffer_unref (ssndbuf);
1065         }
1066 
1067         gotdata = TRUE;
1068 
1069         /* 8 byte chunk header, 8 byte SSND header */
1070         aiff->offset += 16;
1071         datasize = size - 8;
1072 
1073         aiff->datastart = aiff->offset + aiff->ssnd_offset;
1074         /* file might be truncated */
1075         if (upstream_size) {
1076           size = MIN (datasize, (upstream_size - aiff->datastart));
1077         }
1078         aiff->datasize = (guint64) datasize;
1079         aiff->dataleft = (guint64) datasize;
1080         aiff->end_offset = datasize + aiff->datastart;
1081         if (!aiff->streaming) {
1082           /* We will continue looking at chunks until the end - to read tags,
1083            * etc. */
1084           aiff->offset += datasize;
1085         }
1086         GST_DEBUG_OBJECT (aiff, "datasize = %d", datasize);
1087         if (aiff->streaming) {
1088           done = TRUE;
1089         }
1090         break;
1091       }
1092       case GST_MAKE_FOURCC ('I', 'D', '3', ' '):{
1093         GstTagList *tags;
1094 
1095         if (aiff->streaming) {
1096           if (!gst_aiff_parse_peek_chunk (aiff, &tag, &size))
1097             return GST_FLOW_OK;
1098 
1099           gst_adapter_flush (aiff->adapter, 8);
1100           aiff->offset += 8;
1101 
1102           buf = gst_adapter_take_buffer (aiff->adapter, size);
1103         } else {
1104           if ((res = gst_aiff_parse_read_chunk (aiff,
1105                       &aiff->offset, &tag, &buf)) != GST_FLOW_OK)
1106             return res;
1107         }
1108 
1109         GST_LOG_OBJECT (aiff, "ID3 chunk of size %" G_GSIZE_FORMAT,
1110             gst_buffer_get_size (buf));
1111 
1112         tags = gst_tag_list_from_id3v2_tag (buf);
1113         gst_buffer_unref (buf);
1114 
1115         GST_INFO_OBJECT (aiff, "ID3 tags: %" GST_PTR_FORMAT, tags);
1116 
1117         if (aiff->tags == NULL) {
1118           aiff->tags = tags;
1119         } else {
1120           gst_tag_list_insert (aiff->tags, tags, GST_TAG_MERGE_APPEND);
1121           gst_tag_list_unref (tags);
1122         }
1123         break;
1124       }
1125       case GST_MAKE_FOURCC ('C', 'H', 'A', 'N'):{
1126         GST_FIXME_OBJECT (aiff, "Handle CHAN chunk with channel layouts");
1127         gst_aiff_parse_ignore_chunk (aiff, tag, size);
1128         break;
1129       }
1130       default:
1131         gst_aiff_parse_ignore_chunk (aiff, tag, size);
1132     }
1133 
1134     buf = NULL;
1135 
1136     if (upstream_size && (aiff->offset >= upstream_size)) {
1137       /* Now we have gone through the whole file */
1138       done = TRUE;
1139     }
1140   }
1141 
1142   /* We read all the chunks (in pull mode) or reached the SSND chunk
1143    * (in push mode). We must have both COMM and SSND now; error out
1144    * otherwise.
1145    */
1146   if (!aiff->got_comm) {
1147     GST_WARNING_OBJECT (aiff, "Failed to find COMM chunk");
1148     goto no_header;
1149   }
1150   if (!gotdata) {
1151     GST_WARNING_OBJECT (aiff, "Failed to find SSND chunk");
1152     goto no_data;
1153   }
1154 
1155   GST_DEBUG_OBJECT (aiff, "Finished parsing headers");
1156 
1157   if (gst_aiff_parse_calculate_duration (aiff)) {
1158     gst_segment_init (&aiff->segment, GST_FORMAT_TIME);
1159     aiff->segment.duration = aiff->duration;
1160   } else {
1161     /* no bitrate, let downstream peer do the math, we'll feed it bytes. */
1162     gst_segment_init (&aiff->segment, GST_FORMAT_BYTES);
1163     aiff->segment.duration = aiff->datasize;
1164   }
1165 
1166   /* now we have all the info to perform a pending seek if any, if no
1167    * event, this will still do the right thing and it will also send
1168    * the right segment event downstream. */
1169   gst_aiff_parse_perform_seek (aiff, aiff->seek_event, TRUE);
1170   /* remove pending event */
1171   event_p = &aiff->seek_event;
1172   gst_event_replace (event_p, NULL);
1173 
1174   /* we just started, we are discont */
1175   aiff->discont = TRUE;
1176 
1177   aiff->state = AIFF_PARSE_DATA;
1178 
1179   /* determine reasonable max buffer size,
1180    * that is, buffers not too small either size or time wise
1181    * so we do not end up with too many of them */
1182   /* var abuse */
1183   upstream_size = 0;
1184   gst_aiff_parse_time_to_bytepos (aiff, 40 * GST_MSECOND, &upstream_size);
1185   aiff->max_buf_size = upstream_size;
1186   aiff->max_buf_size = MAX (aiff->max_buf_size, MAX_BUFFER_SIZE);
1187   if (aiff->bytes_per_sample > 0)
1188     aiff->max_buf_size -= (aiff->max_buf_size % aiff->bytes_per_sample);
1189 
1190   GST_DEBUG_OBJECT (aiff, "max buffer size %u", aiff->max_buf_size);
1191 
1192   return GST_FLOW_OK;
1193 
1194   /* ERROR */
1195 no_header:
1196   {
1197     GST_ELEMENT_ERROR (aiff, STREAM, TYPE_NOT_FOUND, (NULL),
1198         ("Invalid AIFF header (no COMM found)"));
1199     return GST_FLOW_ERROR;
1200   }
1201 no_data:
1202   {
1203     GST_ELEMENT_ERROR (aiff, STREAM, TYPE_NOT_FOUND, (NULL),
1204         ("Invalid AIFF: no SSND found"));
1205     return GST_FLOW_ERROR;
1206   }
1207 parse_header_error:
1208   {
1209     GST_ELEMENT_ERROR (aiff, STREAM, DEMUX, (NULL),
1210         ("Couldn't parse audio header"));
1211     return GST_FLOW_ERROR;
1212   }
1213 no_channels:
1214   {
1215     GST_ELEMENT_ERROR (aiff, STREAM, FAILED, (NULL),
1216         ("Stream claims to contain no channels - invalid data"));
1217     return GST_FLOW_ERROR;
1218   }
1219 no_rate:
1220   {
1221     GST_ELEMENT_ERROR (aiff, STREAM, FAILED, (NULL),
1222         ("Stream with sample_rate == 0 - invalid data"));
1223     return GST_FLOW_ERROR;
1224   }
1225 no_bytes_per_sample:
1226   {
1227     GST_ELEMENT_ERROR (aiff, STREAM, FAILED, (NULL),
1228         ("Could not calculate bytes per sample - invalid data"));
1229     return GST_FLOW_ERROR;
1230   }
1231 unknown_format:
1232   {
1233     GST_ELEMENT_ERROR (aiff, STREAM, TYPE_NOT_FOUND, (NULL),
1234         ("No caps found for format 0x%x, %d channels, %d Hz",
1235             aiff->format, aiff->channels, aiff->rate));
1236     return GST_FLOW_ERROR;
1237   }
1238 header_read_error:
1239   {
1240     GST_ELEMENT_ERROR (aiff, STREAM, DEMUX, (NULL),
1241         ("Couldn't read in header"));
1242     return GST_FLOW_ERROR;
1243   }
1244 }
1245 
1246 /*
1247  * Read AIFF file tag when streaming
1248  */
1249 static GstFlowReturn
1250 gst_aiff_parse_parse_stream_init (GstAiffParse * aiff)
1251 {
1252   if (gst_adapter_available (aiff->adapter) >= 12) {
1253     GstBuffer *tmp;
1254 
1255     /* _take flushes the data */
1256     tmp = gst_adapter_take_buffer (aiff->adapter, 12);
1257 
1258     GST_DEBUG_OBJECT (aiff, "Parsing aiff header");
1259     if (!gst_aiff_parse_parse_file_header (aiff, tmp))
1260       return GST_FLOW_ERROR;
1261 
1262     aiff->offset += 12;
1263     /* Go to next state */
1264     aiff->state = AIFF_PARSE_HEADER;
1265   }
1266   return GST_FLOW_OK;
1267 }
1268 
1269 /* handle an event sent directly to the element.
1270  *
1271  * This event can be sent either in the READY state or the
1272  * >READY state. The only event of interest really is the seek
1273  * event.
1274  *
1275  * In the READY state we can only store the event and try to
1276  * respect it when going to PAUSED. We assume we are in the
1277  * READY state when our parsing state != AIFF_PARSE_DATA.
1278  *
1279  * When we are steaming, we can simply perform the seek right
1280  * away.
1281  */
1282 static gboolean
1283 gst_aiff_parse_send_event (GstElement * element, GstEvent * event)
1284 {
1285   GstAiffParse *aiff = GST_AIFF_PARSE (element);
1286   gboolean res = FALSE;
1287   GstEvent **event_p;
1288 
1289   GST_DEBUG_OBJECT (aiff, "received event %s", GST_EVENT_TYPE_NAME (event));
1290 
1291   switch (GST_EVENT_TYPE (event)) {
1292     case GST_EVENT_SEEK:
1293       if (aiff->state == AIFF_PARSE_DATA) {
1294         /* we can handle the seek directly when streaming data */
1295         res = gst_aiff_parse_perform_seek (aiff, event, FALSE);
1296       } else {
1297         GST_DEBUG_OBJECT (aiff, "queuing seek for later");
1298 
1299         event_p = &aiff->seek_event;
1300         gst_event_replace (event_p, event);
1301 
1302         /* we always return true */
1303         res = TRUE;
1304       }
1305       break;
1306     default:
1307       break;
1308   }
1309   gst_event_unref (event);
1310   return res;
1311 }
1312 
1313 static GstFlowReturn
1314 gst_aiff_parse_stream_data (GstAiffParse * aiff)
1315 {
1316   GstBuffer *buf = NULL;
1317   GstFlowReturn res = GST_FLOW_OK;
1318   guint64 desired, obtained;
1319   GstClockTime timestamp, next_timestamp, duration;
1320   guint64 pos, nextpos;
1321 
1322   if (aiff->bytes_per_sample <= 0) {
1323     GST_ELEMENT_ERROR (aiff, STREAM, WRONG_TYPE, (NULL),
1324         ("File is not a valid AIFF file (invalid bytes per sample)"));
1325     return GST_FLOW_ERROR;
1326   }
1327 
1328 iterate_adapter:
1329   GST_LOG_OBJECT (aiff,
1330       "offset: %" G_GINT64_FORMAT " , end: %" G_GINT64_FORMAT " , dataleft: %"
1331       G_GINT64_FORMAT, aiff->offset, aiff->end_offset, aiff->dataleft);
1332 
1333   /* Get the next n bytes and output them */
1334   if (aiff->dataleft == 0 || aiff->dataleft < aiff->bytes_per_sample)
1335     goto found_eos;
1336 
1337   /* scale the amount of data by the segment rate so we get equal
1338    * amounts of data regardless of the playback rate */
1339   desired =
1340       MIN (gst_guint64_to_gdouble (aiff->dataleft),
1341       aiff->max_buf_size * ABS (aiff->segment.rate));
1342 
1343   if (desired >= aiff->bytes_per_sample)
1344     desired -= (desired % aiff->bytes_per_sample);
1345 
1346 #ifdef GSTREAMER_LITE
1347   if (desired == 0) {
1348     GST_ELEMENT_ERROR (aiff, STREAM, DEMUX, (NULL),
1349               ("Invalid stream"));
1350     return GST_FLOW_ERROR;
1351   }
1352 #endif // GSTREAMER_LITE
1353 
1354   GST_LOG_OBJECT (aiff, "Fetching %" G_GINT64_FORMAT " bytes of data "
1355       "from the sinkpad", desired);
1356 
1357   if (aiff->streaming) {
1358     guint avail = gst_adapter_available (aiff->adapter);
1359 
1360     if (avail < desired) {
1361       GST_LOG_OBJECT (aiff, "Got only %d bytes of data from the sinkpad",
1362           avail);
1363       return GST_FLOW_OK;
1364     }
1365 
1366     buf = gst_adapter_take_buffer (aiff->adapter, desired);
1367   } else {
1368     if ((res = gst_pad_pull_range (aiff->sinkpad, aiff->offset,
1369                 desired, &buf)) != GST_FLOW_OK)
1370       goto pull_error;
1371   }
1372 
1373   /* If we have a pending close/start segment, send it now. */
1374   if (G_UNLIKELY (aiff->close_segment != NULL)) {
1375     gst_pad_push_event (aiff->srcpad, aiff->close_segment);
1376     aiff->close_segment = NULL;
1377   }
1378   if (G_UNLIKELY (aiff->start_segment != NULL)) {
1379     gst_pad_push_event (aiff->srcpad, aiff->start_segment);
1380     aiff->start_segment = NULL;
1381   }
1382   if (G_UNLIKELY (aiff->tags != NULL)) {
1383     gst_pad_push_event (aiff->srcpad, gst_event_new_tag (aiff->tags));
1384     aiff->tags = NULL;
1385   }
1386 
1387   obtained = gst_buffer_get_size (buf);
1388 
1389   /* our positions in bytes */
1390   pos = aiff->offset - aiff->datastart;
1391   nextpos = pos + obtained;
1392 
1393   /* update offsets, does not overflow. */
1394   GST_BUFFER_OFFSET (buf) = pos / aiff->bytes_per_sample;
1395   GST_BUFFER_OFFSET_END (buf) = nextpos / aiff->bytes_per_sample;
1396 
1397   if (aiff->bps > 0) {
1398     /* and timestamps if we have a bitrate, be careful for overflows */
1399     timestamp =
1400         gst_util_uint64_scale_ceil (pos, GST_SECOND, (guint64) aiff->bps);
1401     next_timestamp =
1402         gst_util_uint64_scale_ceil (nextpos, GST_SECOND, (guint64) aiff->bps);
1403     duration = next_timestamp - timestamp;
1404 
1405     /* update current running segment position */
1406     aiff->segment.position = next_timestamp;
1407   } else {
1408     /* no bitrate, all we know is that the first sample has timestamp 0, all
1409      * other positions and durations have unknown timestamp. */
1410     if (pos == 0)
1411       timestamp = 0;
1412     else
1413       timestamp = GST_CLOCK_TIME_NONE;
1414     duration = GST_CLOCK_TIME_NONE;
1415     /* update current running segment position with byte offset */
1416     aiff->segment.position = nextpos;
1417   }
1418   if (aiff->discont) {
1419     GST_DEBUG_OBJECT (aiff, "marking DISCONT");
1420     GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_DISCONT);
1421     aiff->discont = FALSE;
1422   }
1423 
1424   GST_BUFFER_TIMESTAMP (buf) = timestamp;
1425   GST_BUFFER_DURATION (buf) = duration;
1426 
1427   GST_LOG_OBJECT (aiff,
1428       "Got buffer. timestamp:%" GST_TIME_FORMAT " , duration:%" GST_TIME_FORMAT
1429       ", size:%" G_GUINT64_FORMAT, GST_TIME_ARGS (timestamp),
1430       GST_TIME_ARGS (duration), obtained);
1431 
1432   if ((res = gst_pad_push (aiff->srcpad, buf)) != GST_FLOW_OK)
1433     goto push_error;
1434 
1435   if (obtained < aiff->dataleft) {
1436     aiff->offset += obtained;
1437     aiff->dataleft -= obtained;
1438   } else {
1439     aiff->offset += aiff->dataleft;
1440     aiff->dataleft = 0;
1441   }
1442 
1443   /* Iterate until need more data, so adapter size won't grow */
1444   if (aiff->streaming) {
1445     GST_LOG_OBJECT (aiff,
1446         "offset: %" G_GINT64_FORMAT " , end: %" G_GINT64_FORMAT, aiff->offset,
1447         aiff->end_offset);
1448     goto iterate_adapter;
1449   }
1450   return res;
1451 
1452   /* ERROR */
1453 found_eos:
1454   {
1455     GST_DEBUG_OBJECT (aiff, "found EOS");
1456     return GST_FLOW_EOS;
1457   }
1458 pull_error:
1459   {
1460     /* check if we got EOS */
1461     if (res == GST_FLOW_EOS)
1462       goto found_eos;
1463 
1464     GST_WARNING_OBJECT (aiff,
1465         "Error getting %" G_GINT64_FORMAT " bytes from the "
1466         "sinkpad (dataleft = %" G_GINT64_FORMAT ")", desired, aiff->dataleft);
1467     return res;
1468   }
1469 push_error:
1470   {
1471     GST_INFO_OBJECT (aiff,
1472         "Error pushing on srcpad %s:%s, reason %s, is linked? = %d",
1473         GST_DEBUG_PAD_NAME (aiff->srcpad), gst_flow_get_name (res),
1474         gst_pad_is_linked (aiff->srcpad));
1475     return res;
1476   }
1477 }
1478 
1479 static void
1480 gst_aiff_parse_loop (GstPad * pad)
1481 {
1482   GstFlowReturn ret;
1483   GstAiffParse *aiff = GST_AIFF_PARSE (GST_PAD_PARENT (pad));
1484 
1485   GST_LOG_OBJECT (aiff, "process data");
1486 
1487   switch (aiff->state) {
1488     case AIFF_PARSE_START:
1489       GST_INFO_OBJECT (aiff, "AIFF_PARSE_START");
1490       if ((ret = gst_aiff_parse_stream_init (aiff)) != GST_FLOW_OK)
1491         goto pause;
1492 
1493       aiff->state = AIFF_PARSE_HEADER;
1494       /* fall-through */
1495 
1496     case AIFF_PARSE_HEADER:
1497       GST_INFO_OBJECT (aiff, "AIFF_PARSE_HEADER");
1498       if ((ret = gst_aiff_parse_stream_headers (aiff)) != GST_FLOW_OK)
1499         goto pause;
1500 
1501       aiff->state = AIFF_PARSE_DATA;
1502       GST_INFO_OBJECT (aiff, "AIFF_PARSE_DATA");
1503       /* fall-through */
1504 
1505     case AIFF_PARSE_DATA:
1506       if ((ret = gst_aiff_parse_stream_data (aiff)) != GST_FLOW_OK)
1507         goto pause;
1508       break;
1509     default:
1510       g_assert_not_reached ();
1511   }
1512   return;
1513 
1514   /* ERRORS */
1515 pause:
1516   {
1517     const gchar *reason = gst_flow_get_name (ret);
1518 
1519     GST_DEBUG_OBJECT (aiff, "pausing task, reason %s", reason);
1520     aiff->segment_running = FALSE;
1521     gst_pad_pause_task (pad);
1522 
1523     if (ret == GST_FLOW_EOS) {
1524       /* perform EOS logic */
1525       if (aiff->segment.flags & GST_SEEK_FLAG_SEGMENT) {
1526         GstClockTime stop;
1527 
1528         if ((stop = aiff->segment.stop) == -1)
1529           stop = aiff->segment.duration;
1530 
1531         gst_element_post_message (GST_ELEMENT_CAST (aiff),
1532             gst_message_new_segment_done (GST_OBJECT_CAST (aiff),
1533                 aiff->segment.format, stop));
1534         gst_pad_push_event (aiff->srcpad,
1535             gst_event_new_segment_done (aiff->segment.format, stop));
1536       } else {
1537         gst_pad_push_event (aiff->srcpad, gst_event_new_eos ());
1538       }
1539     } else if (ret < GST_FLOW_EOS || ret == GST_FLOW_NOT_LINKED) {
1540       /* for fatal errors we post an error message, post the error
1541        * first so the app knows about the error first. */
1542       GST_ELEMENT_FLOW_ERROR (aiff, ret);
1543       gst_pad_push_event (aiff->srcpad, gst_event_new_eos ());
1544     }
1545     return;
1546   }
1547 }
1548 
1549 static GstFlowReturn
1550 gst_aiff_parse_chain (GstPad * pad, GstObject * parent, GstBuffer * buf)
1551 {
1552   GstFlowReturn ret;
1553   GstAiffParse *aiff = GST_AIFF_PARSE (parent);
1554 
1555   GST_LOG_OBJECT (aiff, "adapter_push %" G_GSIZE_FORMAT " bytes",
1556       gst_buffer_get_size (buf));
1557 
1558   gst_adapter_push (aiff->adapter, buf);
1559 
1560   switch (aiff->state) {
1561     case AIFF_PARSE_START:
1562       GST_INFO_OBJECT (aiff, "AIFF_PARSE_START");
1563       if ((ret = gst_aiff_parse_parse_stream_init (aiff)) != GST_FLOW_OK)
1564         goto done;
1565 
1566       if (aiff->state != AIFF_PARSE_HEADER)
1567         break;
1568 
1569       /* otherwise fall-through */
1570     case AIFF_PARSE_HEADER:
1571       GST_INFO_OBJECT (aiff, "AIFF_PARSE_HEADER");
1572       if ((ret = gst_aiff_parse_stream_headers (aiff)) != GST_FLOW_OK)
1573         goto done;
1574 
1575       if (!aiff->got_comm || aiff->datastart == 0)
1576         break;
1577 
1578       aiff->state = AIFF_PARSE_DATA;
1579       GST_INFO_OBJECT (aiff, "AIFF_PARSE_DATA");
1580 
1581       /* fall-through */
1582     case AIFF_PARSE_DATA:
1583       if ((ret = gst_aiff_parse_stream_data (aiff)) != GST_FLOW_OK)
1584         goto done;
1585       break;
1586     default:
1587       g_return_val_if_reached (GST_FLOW_ERROR);
1588   }
1589 done:
1590   return ret;
1591 }
1592 
1593 static gboolean
1594 gst_aiff_parse_pad_convert (GstPad * pad,
1595     GstFormat src_format, gint64 src_value,
1596     GstFormat * dest_format, gint64 * dest_value)
1597 {
1598   GstAiffParse *aiffparse;
1599   gboolean res = TRUE;
1600 
1601   aiffparse = GST_AIFF_PARSE (GST_PAD_PARENT (pad));
1602 
1603   if (*dest_format == src_format) {
1604     *dest_value = src_value;
1605     return TRUE;
1606   }
1607 
1608   if (aiffparse->bytes_per_sample <= 0)
1609     return FALSE;
1610 
1611   GST_INFO_OBJECT (aiffparse, "converting value from %s to %s",
1612       gst_format_get_name (src_format), gst_format_get_name (*dest_format));
1613 
1614   switch (src_format) {
1615     case GST_FORMAT_BYTES:
1616       switch (*dest_format) {
1617         case GST_FORMAT_DEFAULT:
1618           *dest_value = src_value / aiffparse->bytes_per_sample;
1619           break;
1620         case GST_FORMAT_TIME:
1621           if (aiffparse->bps > 0) {
1622             *dest_value = gst_util_uint64_scale_ceil (src_value, GST_SECOND,
1623                 (guint64) aiffparse->bps);
1624             break;
1625           }
1626           /* Else fallthrough */
1627         default:
1628           res = FALSE;
1629           goto done;
1630       }
1631       break;
1632 
1633     case GST_FORMAT_DEFAULT:
1634       switch (*dest_format) {
1635         case GST_FORMAT_BYTES:
1636           *dest_value = src_value * aiffparse->bytes_per_sample;
1637           break;
1638         case GST_FORMAT_TIME:
1639           *dest_value = gst_util_uint64_scale (src_value, GST_SECOND,
1640               (guint64) aiffparse->rate);
1641           break;
1642         default:
1643           res = FALSE;
1644           goto done;
1645       }
1646       break;
1647 
1648     case GST_FORMAT_TIME:
1649       switch (*dest_format) {
1650         case GST_FORMAT_BYTES:
1651           if (aiffparse->bps > 0) {
1652             *dest_value = gst_util_uint64_scale (src_value,
1653                 (guint64) aiffparse->bps, GST_SECOND);
1654             break;
1655           }
1656           /* Else fallthrough */
1657           break;
1658         case GST_FORMAT_DEFAULT:
1659           *dest_value = gst_util_uint64_scale (src_value,
1660               (guint64) aiffparse->rate, GST_SECOND);
1661           break;
1662         default:
1663           res = FALSE;
1664           goto done;
1665       }
1666       break;
1667 
1668     default:
1669       res = FALSE;
1670       goto done;
1671   }
1672 
1673 done:
1674   return res;
1675 
1676 }
1677 
1678 /* handle queries for location and length in requested format */
1679 static gboolean
1680 gst_aiff_parse_pad_query (GstPad * pad, GstObject * parent, GstQuery * query)
1681 {
1682   gboolean res = FALSE;
1683   GstAiffParse *aiff = GST_AIFF_PARSE (parent);
1684 
1685   switch (GST_QUERY_TYPE (query)) {
1686     case GST_QUERY_DURATION:
1687     {
1688       gint64 duration = 0;
1689       GstFormat format;
1690 
1691       /* only if we know */
1692       if (aiff->state != AIFF_PARSE_DATA)
1693         break;
1694 
1695       gst_query_parse_duration (query, &format, NULL);
1696 
1697       switch (format) {
1698         case GST_FORMAT_TIME:{
1699           if ((res = gst_aiff_parse_calculate_duration (aiff))) {
1700             duration = aiff->duration;
1701           }
1702           break;
1703         }
1704         default:
1705           format = GST_FORMAT_BYTES;
1706           duration = aiff->datasize;
1707           break;
1708       }
1709       gst_query_set_duration (query, format, duration);
1710       break;
1711     }
1712     case GST_QUERY_CONVERT:
1713     {
1714       gint64 srcvalue, dstvalue;
1715       GstFormat srcformat, dstformat;
1716 
1717       /* only if we know */
1718       if (aiff->state != AIFF_PARSE_DATA)
1719         break;
1720 
1721       gst_query_parse_convert (query, &srcformat, &srcvalue,
1722           &dstformat, &dstvalue);
1723       res = gst_aiff_parse_pad_convert (pad, srcformat, srcvalue,
1724           &dstformat, &dstvalue);
1725       if (res)
1726         gst_query_set_convert (query, srcformat, srcvalue, dstformat, dstvalue);
1727       break;
1728     }
1729     case GST_QUERY_SEEKING:{
1730       GstFormat fmt;
1731 
1732       /* only if we know */
1733       if (aiff->state != AIFF_PARSE_DATA)
1734         break;
1735 
1736       gst_query_parse_seeking (query, &fmt, NULL, NULL, NULL);
1737       if (fmt == GST_FORMAT_TIME) {
1738         gboolean seekable = TRUE;
1739 
1740         if (!gst_aiff_parse_calculate_duration (aiff)) {
1741           seekable = FALSE;
1742         }
1743         gst_query_set_seeking (query, GST_FORMAT_TIME, seekable,
1744             0, aiff->duration);
1745         res = TRUE;
1746       }
1747       break;
1748     }
1749     default:
1750       res = gst_pad_query_default (pad, parent, query);
1751       break;
1752   }
1753   return res;
1754 }
1755 
1756 static gboolean
1757 gst_aiff_parse_srcpad_event (GstPad * pad, GstObject * parent, GstEvent * event)
1758 {
1759   GstAiffParse *aiffparse = GST_AIFF_PARSE (parent);
1760   gboolean res = FALSE;
1761 
1762   GST_DEBUG_OBJECT (aiffparse, "%s event", GST_EVENT_TYPE_NAME (event));
1763 
1764   switch (GST_EVENT_TYPE (event)) {
1765     case GST_EVENT_SEEK:
1766       /* can only handle events when we are in the data state */
1767       if (aiffparse->state == AIFF_PARSE_DATA) {
1768         res = gst_aiff_parse_perform_seek (aiffparse, event, FALSE);
1769       }
1770       gst_event_unref (event);
1771       break;
1772     default:
1773       res = gst_pad_push_event (aiffparse->sinkpad, event);
1774       break;
1775   }
1776   return res;
1777 }
1778 
1779 static gboolean
1780 gst_aiff_parse_sink_activate (GstPad * sinkpad, GstObject * parent)
1781 {
1782   GstQuery *query;
1783   gboolean pull_mode;
1784 
1785   query = gst_query_new_scheduling ();
1786 
1787   if (!gst_pad_peer_query (sinkpad, query)) {
1788     gst_query_unref (query);
1789     goto activate_push;
1790   }
1791 
1792   pull_mode = gst_query_has_scheduling_mode_with_flags (query,
1793       GST_PAD_MODE_PULL, GST_SCHEDULING_FLAG_SEEKABLE);
1794   gst_query_unref (query);
1795 
1796   if (!pull_mode)
1797     goto activate_push;
1798 
1799   GST_DEBUG_OBJECT (sinkpad, "going to pull mode");
1800   return gst_pad_activate_mode (sinkpad, GST_PAD_MODE_PULL, TRUE);
1801 
1802 activate_push:
1803   {
1804     GST_DEBUG_OBJECT (sinkpad, "going to push (streaming) mode");
1805     return gst_pad_activate_mode (sinkpad, GST_PAD_MODE_PUSH, TRUE);
1806   }
1807 }
1808 
1809 
1810 static gboolean
1811 gst_aiff_parse_sink_activate_mode (GstPad * sinkpad, GstObject * parent,
1812     GstPadMode mode, gboolean active)
1813 {
1814   gboolean res;
1815   GstAiffParse *aiff = GST_AIFF_PARSE (parent);
1816 
1817   if (aiff->adapter) {
1818     g_object_unref (aiff->adapter);
1819     aiff->adapter = NULL;
1820   }
1821 
1822   switch (mode) {
1823     case GST_PAD_MODE_PUSH:
1824       if (active) {
1825         aiff->streaming = TRUE;
1826         aiff->adapter = gst_adapter_new ();
1827       }
1828       res = TRUE;
1829       break;
1830     case GST_PAD_MODE_PULL:
1831       if (active) {
1832         aiff->streaming = FALSE;
1833         aiff->adapter = NULL;
1834         aiff->segment_running = TRUE;
1835         res =
1836             gst_pad_start_task (sinkpad, (GstTaskFunction) gst_aiff_parse_loop,
1837             sinkpad, NULL);
1838       } else {
1839         aiff->segment_running = FALSE;
1840         res = gst_pad_stop_task (sinkpad);
1841       }
1842       break;
1843     default:
1844       res = FALSE;
1845       break;
1846   }
1847   return res;
1848 };
1849 
1850 static GstFlowReturn
1851 gst_aiff_parse_flush_data (GstAiffParse * aiff)
1852 {
1853   GstFlowReturn ret = GST_FLOW_OK;
1854   guint av;
1855 
1856   if ((av = gst_adapter_available (aiff->adapter)) > 0) {
1857     aiff->dataleft = av;
1858     aiff->end_offset = aiff->offset + av;
1859     ret = gst_aiff_parse_stream_data (aiff);
1860   }
1861 
1862   return ret;
1863 }
1864 
1865 
1866 static gboolean
1867 gst_aiff_parse_sink_event (GstPad * pad, GstObject * parent, GstEvent * event)
1868 {
1869   GstAiffParse *aiff = GST_AIFF_PARSE (parent);
1870   gboolean ret = TRUE;
1871 
1872   GST_DEBUG_OBJECT (aiff, "handling %s event", GST_EVENT_TYPE_NAME (event));
1873 
1874   switch (GST_EVENT_TYPE (event)) {
1875     case GST_EVENT_CAPS:
1876     {
1877       /* discard, we'll come up with proper src caps */
1878       gst_event_unref (event);
1879       break;
1880     }
1881     case GST_EVENT_SEGMENT:
1882     {
1883       gint64 start, stop, offset = 0, end_offset = -1;
1884       GstSegment segment;
1885 
1886       /* some debug output */
1887       gst_event_copy_segment (event, &segment);
1888       GST_DEBUG_OBJECT (aiff, "received segment %" GST_SEGMENT_FORMAT,
1889           &segment);
1890 
1891       /* now we are either committed to TIME or BYTE format,
1892        * and we only expect a BYTE segment, e.g. following a seek */
1893       if (segment.format == GST_FORMAT_BYTES) {
1894         /* handle (un)signed issues */
1895         start = segment.start;
1896         stop = segment.stop;
1897         if (start > 0) {
1898           offset = start;
1899           start -= aiff->datastart;
1900           start = MAX (start, 0);
1901         }
1902         if (stop > 0) {
1903           end_offset = stop;
1904           stop -= aiff->datastart;
1905           stop = MAX (stop, 0);
1906         }
1907         if (aiff->state == AIFF_PARSE_DATA &&
1908             aiff->segment.format == GST_FORMAT_TIME) {
1909           /* operating in format TIME, so we can convert */
1910           if (aiff->bps) {
1911             if (start >= 0)
1912               start =
1913                   gst_util_uint64_scale_ceil (start, GST_SECOND,
1914                   (guint64) aiff->bps);
1915             if (stop >= 0)
1916               stop =
1917                   gst_util_uint64_scale_ceil (stop, GST_SECOND,
1918                   (guint64) aiff->bps);
1919           } else {
1920             GST_DEBUG_OBJECT (aiff, "unable to compute segment start/stop");
1921             goto exit;
1922           }
1923         }
1924       } else {
1925         GST_DEBUG_OBJECT (aiff, "unsupported segment format, ignoring");
1926         goto exit;
1927       }
1928 
1929       segment.start = start;
1930       segment.stop = stop;
1931 
1932       /* accept upstream's notion of segment and distribute along */
1933       if (aiff->state == AIFF_PARSE_DATA) {
1934         segment.format = aiff->segment.format;
1935         segment.time = segment.position = segment.start;
1936         segment.duration = aiff->segment.duration;
1937       }
1938 
1939       gst_segment_copy_into (&segment, &aiff->segment);
1940 
1941       if (aiff->start_segment)
1942         gst_event_unref (aiff->start_segment);
1943 
1944       aiff->start_segment = gst_event_new_segment (&segment);
1945 
1946       /* If the seek is within the same SSND chunk and there is no new
1947        * end_offset defined keep the previous end_offset. This will avoid noise
1948        * at the end of playback if e.g. a metadata chunk is located at the end
1949        * of the file. */
1950       if (aiff->end_offset > 0 && offset < aiff->end_offset &&
1951           offset >= aiff->datastart && end_offset == -1) {
1952         end_offset = aiff->end_offset;
1953       }
1954 
1955       /* stream leftover data in current segment */
1956       if (aiff->state == AIFF_PARSE_DATA)
1957         gst_aiff_parse_flush_data (aiff);
1958       /* and set up streaming thread for next one */
1959       aiff->offset = offset;
1960       aiff->end_offset = end_offset;
1961       if (aiff->end_offset > 0) {
1962         aiff->dataleft = aiff->end_offset - aiff->offset;
1963       } else {
1964         /* infinity; upstream will EOS when done */
1965         aiff->dataleft = G_MAXUINT64;
1966       }
1967     exit:
1968       gst_event_unref (event);
1969       break;
1970     }
1971     case GST_EVENT_FLUSH_START:
1972       ret = gst_pad_push_event (aiff->srcpad, event);
1973       break;
1974     case GST_EVENT_FLUSH_STOP:
1975       ret = gst_pad_push_event (aiff->srcpad, event);
1976       gst_adapter_clear (aiff->adapter);
1977       break;
1978     default:
1979       ret = gst_pad_event_default (aiff->sinkpad, parent, event);
1980       break;
1981   }
1982 
1983   return ret;
1984 }
1985 
1986 static GstStateChangeReturn
1987 gst_aiff_parse_change_state (GstElement * element, GstStateChange transition)
1988 {
1989   GstStateChangeReturn ret;
1990   GstAiffParse *aiff = GST_AIFF_PARSE (element);
1991 
1992   switch (transition) {
1993     case GST_STATE_CHANGE_NULL_TO_READY:
1994       break;
1995     case GST_STATE_CHANGE_READY_TO_PAUSED:
1996       gst_aiff_parse_reset (aiff);
1997       break;
1998     case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
1999       break;
2000     default:
2001       break;
2002   }
2003 
2004   ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
2005 
2006   switch (transition) {
2007     case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
2008       break;
2009     case GST_STATE_CHANGE_PAUSED_TO_READY:
2010       gst_aiff_parse_reset (aiff);
2011       break;
2012     case GST_STATE_CHANGE_READY_TO_NULL:
2013       break;
2014     default:
2015       break;
2016   }
2017   return ret;
2018 }