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   GST_LOG_OBJECT (aiff, "Fetching %" G_GINT64_FORMAT " bytes of data "
1347       "from the sinkpad", desired);
1348 
1349   if (aiff->streaming) {
1350     guint avail = gst_adapter_available (aiff->adapter);
1351 
1352     if (avail < desired) {
1353       GST_LOG_OBJECT (aiff, "Got only %d bytes of data from the sinkpad",
1354           avail);
1355       return GST_FLOW_OK;
1356     }
1357 
1358     buf = gst_adapter_take_buffer (aiff->adapter, desired);
1359   } else {
1360     if ((res = gst_pad_pull_range (aiff->sinkpad, aiff->offset,
1361                 desired, &buf)) != GST_FLOW_OK)
1362       goto pull_error;
1363   }
1364 
1365   /* If we have a pending close/start segment, send it now. */
1366   if (G_UNLIKELY (aiff->close_segment != NULL)) {
1367     gst_pad_push_event (aiff->srcpad, aiff->close_segment);
1368     aiff->close_segment = NULL;
1369   }
1370   if (G_UNLIKELY (aiff->start_segment != NULL)) {
1371     gst_pad_push_event (aiff->srcpad, aiff->start_segment);
1372     aiff->start_segment = NULL;
1373   }
1374   if (G_UNLIKELY (aiff->tags != NULL)) {
1375     gst_pad_push_event (aiff->srcpad, gst_event_new_tag (aiff->tags));
1376     aiff->tags = NULL;
1377   }
1378 
1379   obtained = gst_buffer_get_size (buf);
1380 
1381   /* our positions in bytes */
1382   pos = aiff->offset - aiff->datastart;
1383   nextpos = pos + obtained;
1384 
1385   /* update offsets, does not overflow. */
1386   GST_BUFFER_OFFSET (buf) = pos / aiff->bytes_per_sample;
1387   GST_BUFFER_OFFSET_END (buf) = nextpos / aiff->bytes_per_sample;
1388 
1389   if (aiff->bps > 0) {
1390     /* and timestamps if we have a bitrate, be careful for overflows */
1391     timestamp =
1392         gst_util_uint64_scale_ceil (pos, GST_SECOND, (guint64) aiff->bps);
1393     next_timestamp =
1394         gst_util_uint64_scale_ceil (nextpos, GST_SECOND, (guint64) aiff->bps);
1395     duration = next_timestamp - timestamp;
1396 
1397     /* update current running segment position */
1398     aiff->segment.position = next_timestamp;
1399   } else {
1400     /* no bitrate, all we know is that the first sample has timestamp 0, all
1401      * other positions and durations have unknown timestamp. */
1402     if (pos == 0)
1403       timestamp = 0;
1404     else
1405       timestamp = GST_CLOCK_TIME_NONE;
1406     duration = GST_CLOCK_TIME_NONE;
1407     /* update current running segment position with byte offset */
1408     aiff->segment.position = nextpos;
1409   }
1410   if (aiff->discont) {
1411     GST_DEBUG_OBJECT (aiff, "marking DISCONT");
1412     GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_DISCONT);
1413     aiff->discont = FALSE;
1414   }
1415 
1416   GST_BUFFER_TIMESTAMP (buf) = timestamp;
1417   GST_BUFFER_DURATION (buf) = duration;
1418 
1419   GST_LOG_OBJECT (aiff,
1420       "Got buffer. timestamp:%" GST_TIME_FORMAT " , duration:%" GST_TIME_FORMAT
1421       ", size:%" G_GUINT64_FORMAT, GST_TIME_ARGS (timestamp),
1422       GST_TIME_ARGS (duration), obtained);
1423 
1424   if ((res = gst_pad_push (aiff->srcpad, buf)) != GST_FLOW_OK)
1425     goto push_error;
1426 
1427   if (obtained < aiff->dataleft) {
1428     aiff->offset += obtained;
1429     aiff->dataleft -= obtained;
1430   } else {
1431     aiff->offset += aiff->dataleft;
1432     aiff->dataleft = 0;
1433   }
1434 
1435   /* Iterate until need more data, so adapter size won't grow */
1436   if (aiff->streaming) {
1437     GST_LOG_OBJECT (aiff,
1438         "offset: %" G_GINT64_FORMAT " , end: %" G_GINT64_FORMAT, aiff->offset,
1439         aiff->end_offset);
1440     goto iterate_adapter;
1441   }
1442   return res;
1443 
1444   /* ERROR */
1445 found_eos:
1446   {
1447     GST_DEBUG_OBJECT (aiff, "found EOS");
1448     return GST_FLOW_EOS;
1449   }
1450 pull_error:
1451   {
1452     /* check if we got EOS */
1453     if (res == GST_FLOW_EOS)
1454       goto found_eos;
1455 
1456     GST_WARNING_OBJECT (aiff,
1457         "Error getting %" G_GINT64_FORMAT " bytes from the "
1458         "sinkpad (dataleft = %" G_GINT64_FORMAT ")", desired, aiff->dataleft);
1459     return res;
1460   }
1461 push_error:
1462   {
1463     GST_INFO_OBJECT (aiff,
1464         "Error pushing on srcpad %s:%s, reason %s, is linked? = %d",
1465         GST_DEBUG_PAD_NAME (aiff->srcpad), gst_flow_get_name (res),
1466         gst_pad_is_linked (aiff->srcpad));
1467     return res;
1468   }
1469 }
1470 
1471 static void
1472 gst_aiff_parse_loop (GstPad * pad)
1473 {
1474   GstFlowReturn ret;
1475   GstAiffParse *aiff = GST_AIFF_PARSE (GST_PAD_PARENT (pad));
1476 
1477   GST_LOG_OBJECT (aiff, "process data");
1478 
1479   switch (aiff->state) {
1480     case AIFF_PARSE_START:
1481       GST_INFO_OBJECT (aiff, "AIFF_PARSE_START");
1482       if ((ret = gst_aiff_parse_stream_init (aiff)) != GST_FLOW_OK)
1483         goto pause;
1484 
1485       aiff->state = AIFF_PARSE_HEADER;
1486       /* fall-through */
1487 
1488     case AIFF_PARSE_HEADER:
1489       GST_INFO_OBJECT (aiff, "AIFF_PARSE_HEADER");
1490       if ((ret = gst_aiff_parse_stream_headers (aiff)) != GST_FLOW_OK)
1491         goto pause;
1492 
1493       aiff->state = AIFF_PARSE_DATA;
1494       GST_INFO_OBJECT (aiff, "AIFF_PARSE_DATA");
1495       /* fall-through */
1496 
1497     case AIFF_PARSE_DATA:
1498       if ((ret = gst_aiff_parse_stream_data (aiff)) != GST_FLOW_OK)
1499         goto pause;
1500       break;
1501     default:
1502       g_assert_not_reached ();
1503   }
1504   return;
1505 
1506   /* ERRORS */
1507 pause:
1508   {
1509     const gchar *reason = gst_flow_get_name (ret);
1510 
1511     GST_DEBUG_OBJECT (aiff, "pausing task, reason %s", reason);
1512     aiff->segment_running = FALSE;
1513     gst_pad_pause_task (pad);
1514 
1515     if (ret == GST_FLOW_EOS) {
1516       /* perform EOS logic */
1517       if (aiff->segment.flags & GST_SEEK_FLAG_SEGMENT) {
1518         GstClockTime stop;
1519 
1520         if ((stop = aiff->segment.stop) == -1)
1521           stop = aiff->segment.duration;
1522 
1523         gst_element_post_message (GST_ELEMENT_CAST (aiff),
1524             gst_message_new_segment_done (GST_OBJECT_CAST (aiff),
1525                 aiff->segment.format, stop));
1526         gst_pad_push_event (aiff->srcpad,
1527             gst_event_new_segment_done (aiff->segment.format, stop));
1528       } else {
1529         gst_pad_push_event (aiff->srcpad, gst_event_new_eos ());
1530       }
1531     } else if (ret < GST_FLOW_EOS || ret == GST_FLOW_NOT_LINKED) {
1532       /* for fatal errors we post an error message, post the error
1533        * first so the app knows about the error first. */
1534       GST_ELEMENT_FLOW_ERROR (aiff, ret);
1535       gst_pad_push_event (aiff->srcpad, gst_event_new_eos ());
1536     }
1537     return;
1538   }
1539 }
1540 
1541 static GstFlowReturn
1542 gst_aiff_parse_chain (GstPad * pad, GstObject * parent, GstBuffer * buf)
1543 {
1544   GstFlowReturn ret;
1545   GstAiffParse *aiff = GST_AIFF_PARSE (parent);
1546 
1547   GST_LOG_OBJECT (aiff, "adapter_push %" G_GSIZE_FORMAT " bytes",
1548       gst_buffer_get_size (buf));
1549 
1550   gst_adapter_push (aiff->adapter, buf);
1551 
1552   switch (aiff->state) {
1553     case AIFF_PARSE_START:
1554       GST_INFO_OBJECT (aiff, "AIFF_PARSE_START");
1555       if ((ret = gst_aiff_parse_parse_stream_init (aiff)) != GST_FLOW_OK)
1556         goto done;
1557 
1558       if (aiff->state != AIFF_PARSE_HEADER)
1559         break;
1560 
1561       /* otherwise fall-through */
1562     case AIFF_PARSE_HEADER:
1563       GST_INFO_OBJECT (aiff, "AIFF_PARSE_HEADER");
1564       if ((ret = gst_aiff_parse_stream_headers (aiff)) != GST_FLOW_OK)
1565         goto done;
1566 
1567       if (!aiff->got_comm || aiff->datastart == 0)
1568         break;
1569 
1570       aiff->state = AIFF_PARSE_DATA;
1571       GST_INFO_OBJECT (aiff, "AIFF_PARSE_DATA");
1572 
1573       /* fall-through */
1574     case AIFF_PARSE_DATA:
1575       if ((ret = gst_aiff_parse_stream_data (aiff)) != GST_FLOW_OK)
1576         goto done;
1577       break;
1578     default:
1579       g_return_val_if_reached (GST_FLOW_ERROR);
1580   }
1581 done:
1582   return ret;
1583 }
1584 
1585 static gboolean
1586 gst_aiff_parse_pad_convert (GstPad * pad,
1587     GstFormat src_format, gint64 src_value,
1588     GstFormat * dest_format, gint64 * dest_value)
1589 {
1590   GstAiffParse *aiffparse;
1591   gboolean res = TRUE;
1592 
1593   aiffparse = GST_AIFF_PARSE (GST_PAD_PARENT (pad));
1594 
1595   if (*dest_format == src_format) {
1596     *dest_value = src_value;
1597     return TRUE;
1598   }
1599 
1600   if (aiffparse->bytes_per_sample <= 0)
1601     return FALSE;
1602 
1603   GST_INFO_OBJECT (aiffparse, "converting value from %s to %s",
1604       gst_format_get_name (src_format), gst_format_get_name (*dest_format));
1605 
1606   switch (src_format) {
1607     case GST_FORMAT_BYTES:
1608       switch (*dest_format) {
1609         case GST_FORMAT_DEFAULT:
1610           *dest_value = src_value / aiffparse->bytes_per_sample;
1611           break;
1612         case GST_FORMAT_TIME:
1613           if (aiffparse->bps > 0) {
1614             *dest_value = gst_util_uint64_scale_ceil (src_value, GST_SECOND,
1615                 (guint64) aiffparse->bps);
1616             break;
1617           }
1618           /* Else fallthrough */
1619         default:
1620           res = FALSE;
1621           goto done;
1622       }
1623       break;
1624 
1625     case GST_FORMAT_DEFAULT:
1626       switch (*dest_format) {
1627         case GST_FORMAT_BYTES:
1628           *dest_value = src_value * aiffparse->bytes_per_sample;
1629           break;
1630         case GST_FORMAT_TIME:
1631           *dest_value = gst_util_uint64_scale (src_value, GST_SECOND,
1632               (guint64) aiffparse->rate);
1633           break;
1634         default:
1635           res = FALSE;
1636           goto done;
1637       }
1638       break;
1639 
1640     case GST_FORMAT_TIME:
1641       switch (*dest_format) {
1642         case GST_FORMAT_BYTES:
1643           if (aiffparse->bps > 0) {
1644             *dest_value = gst_util_uint64_scale (src_value,
1645                 (guint64) aiffparse->bps, GST_SECOND);
1646             break;
1647           }
1648           /* Else fallthrough */
1649           break;
1650         case GST_FORMAT_DEFAULT:
1651           *dest_value = gst_util_uint64_scale (src_value,
1652               (guint64) aiffparse->rate, GST_SECOND);
1653           break;
1654         default:
1655           res = FALSE;
1656           goto done;
1657       }
1658       break;
1659 
1660     default:
1661       res = FALSE;
1662       goto done;
1663   }
1664 
1665 done:
1666   return res;
1667 
1668 }
1669 
1670 /* handle queries for location and length in requested format */
1671 static gboolean
1672 gst_aiff_parse_pad_query (GstPad * pad, GstObject * parent, GstQuery * query)
1673 {
1674   gboolean res = FALSE;
1675   GstAiffParse *aiff = GST_AIFF_PARSE (parent);
1676 
1677   switch (GST_QUERY_TYPE (query)) {
1678     case GST_QUERY_DURATION:
1679     {
1680       gint64 duration = 0;
1681       GstFormat format;
1682 
1683       /* only if we know */
1684       if (aiff->state != AIFF_PARSE_DATA)
1685         break;
1686 
1687       gst_query_parse_duration (query, &format, NULL);
1688 
1689       switch (format) {
1690         case GST_FORMAT_TIME:{
1691           if ((res = gst_aiff_parse_calculate_duration (aiff))) {
1692             duration = aiff->duration;
1693           }
1694           break;
1695         }
1696         default:
1697           format = GST_FORMAT_BYTES;
1698           duration = aiff->datasize;
1699           break;
1700       }
1701       gst_query_set_duration (query, format, duration);
1702       break;
1703     }
1704     case GST_QUERY_CONVERT:
1705     {
1706       gint64 srcvalue, dstvalue;
1707       GstFormat srcformat, dstformat;
1708 
1709       /* only if we know */
1710       if (aiff->state != AIFF_PARSE_DATA)
1711         break;
1712 
1713       gst_query_parse_convert (query, &srcformat, &srcvalue,
1714           &dstformat, &dstvalue);
1715       res = gst_aiff_parse_pad_convert (pad, srcformat, srcvalue,
1716           &dstformat, &dstvalue);
1717       if (res)
1718         gst_query_set_convert (query, srcformat, srcvalue, dstformat, dstvalue);
1719       break;
1720     }
1721     case GST_QUERY_SEEKING:{
1722       GstFormat fmt;
1723 
1724       /* only if we know */
1725       if (aiff->state != AIFF_PARSE_DATA)
1726         break;
1727 
1728       gst_query_parse_seeking (query, &fmt, NULL, NULL, NULL);
1729       if (fmt == GST_FORMAT_TIME) {
1730         gboolean seekable = TRUE;
1731 
1732         if (!gst_aiff_parse_calculate_duration (aiff)) {
1733           seekable = FALSE;
1734         }
1735         gst_query_set_seeking (query, GST_FORMAT_TIME, seekable,
1736             0, aiff->duration);
1737         res = TRUE;
1738       }
1739       break;
1740     }
1741     default:
1742       res = gst_pad_query_default (pad, parent, query);
1743       break;
1744   }
1745   return res;
1746 }
1747 
1748 static gboolean
1749 gst_aiff_parse_srcpad_event (GstPad * pad, GstObject * parent, GstEvent * event)
1750 {
1751   GstAiffParse *aiffparse = GST_AIFF_PARSE (parent);
1752   gboolean res = FALSE;
1753 
1754   GST_DEBUG_OBJECT (aiffparse, "%s event", GST_EVENT_TYPE_NAME (event));
1755 
1756   switch (GST_EVENT_TYPE (event)) {
1757     case GST_EVENT_SEEK:
1758       /* can only handle events when we are in the data state */
1759       if (aiffparse->state == AIFF_PARSE_DATA) {
1760         res = gst_aiff_parse_perform_seek (aiffparse, event, FALSE);
1761       }
1762       gst_event_unref (event);
1763       break;
1764     default:
1765       res = gst_pad_push_event (aiffparse->sinkpad, event);
1766       break;
1767   }
1768   return res;
1769 }
1770 
1771 static gboolean
1772 gst_aiff_parse_sink_activate (GstPad * sinkpad, GstObject * parent)
1773 {
1774   GstQuery *query;
1775   gboolean pull_mode;
1776 
1777   query = gst_query_new_scheduling ();
1778 
1779   if (!gst_pad_peer_query (sinkpad, query)) {
1780     gst_query_unref (query);
1781     goto activate_push;
1782   }
1783 
1784   pull_mode = gst_query_has_scheduling_mode_with_flags (query,
1785       GST_PAD_MODE_PULL, GST_SCHEDULING_FLAG_SEEKABLE);
1786   gst_query_unref (query);
1787 
1788   if (!pull_mode)
1789     goto activate_push;
1790 
1791   GST_DEBUG_OBJECT (sinkpad, "going to pull mode");
1792   return gst_pad_activate_mode (sinkpad, GST_PAD_MODE_PULL, TRUE);
1793 
1794 activate_push:
1795   {
1796     GST_DEBUG_OBJECT (sinkpad, "going to push (streaming) mode");
1797     return gst_pad_activate_mode (sinkpad, GST_PAD_MODE_PUSH, TRUE);
1798   }
1799 }
1800 
1801 
1802 static gboolean
1803 gst_aiff_parse_sink_activate_mode (GstPad * sinkpad, GstObject * parent,
1804     GstPadMode mode, gboolean active)
1805 {
1806   gboolean res;
1807   GstAiffParse *aiff = GST_AIFF_PARSE (parent);
1808 
1809   if (aiff->adapter) {
1810     g_object_unref (aiff->adapter);
1811     aiff->adapter = NULL;
1812   }
1813 
1814   switch (mode) {
1815     case GST_PAD_MODE_PUSH:
1816       if (active) {
1817         aiff->streaming = TRUE;
1818         aiff->adapter = gst_adapter_new ();
1819       }
1820       res = TRUE;
1821       break;
1822     case GST_PAD_MODE_PULL:
1823       if (active) {
1824         aiff->streaming = FALSE;
1825         aiff->adapter = NULL;
1826         aiff->segment_running = TRUE;
1827         res =
1828             gst_pad_start_task (sinkpad, (GstTaskFunction) gst_aiff_parse_loop,
1829             sinkpad, NULL);
1830       } else {
1831         aiff->segment_running = FALSE;
1832         res = gst_pad_stop_task (sinkpad);
1833       }
1834       break;
1835     default:
1836       res = FALSE;
1837       break;
1838   }
1839   return res;
1840 };
1841 
1842 static GstFlowReturn
1843 gst_aiff_parse_flush_data (GstAiffParse * aiff)
1844 {
1845   GstFlowReturn ret = GST_FLOW_OK;
1846   guint av;
1847 
1848   if ((av = gst_adapter_available (aiff->adapter)) > 0) {
1849     aiff->dataleft = av;
1850     aiff->end_offset = aiff->offset + av;
1851     ret = gst_aiff_parse_stream_data (aiff);
1852   }
1853 
1854   return ret;
1855 }
1856 
1857 
1858 static gboolean
1859 gst_aiff_parse_sink_event (GstPad * pad, GstObject * parent, GstEvent * event)
1860 {
1861   GstAiffParse *aiff = GST_AIFF_PARSE (parent);
1862   gboolean ret = TRUE;
1863 
1864   GST_DEBUG_OBJECT (aiff, "handling %s event", GST_EVENT_TYPE_NAME (event));
1865 
1866   switch (GST_EVENT_TYPE (event)) {
1867     case GST_EVENT_CAPS:
1868     {
1869       /* discard, we'll come up with proper src caps */
1870       gst_event_unref (event);
1871       break;
1872     }
1873     case GST_EVENT_SEGMENT:
1874     {
1875       gint64 start, stop, offset = 0, end_offset = -1;
1876       GstSegment segment;
1877 
1878       /* some debug output */
1879       gst_event_copy_segment (event, &segment);
1880       GST_DEBUG_OBJECT (aiff, "received segment %" GST_SEGMENT_FORMAT,
1881           &segment);
1882 
1883       /* now we are either committed to TIME or BYTE format,
1884        * and we only expect a BYTE segment, e.g. following a seek */
1885       if (segment.format == GST_FORMAT_BYTES) {
1886         /* handle (un)signed issues */
1887         start = segment.start;
1888         stop = segment.stop;
1889         if (start > 0) {
1890           offset = start;
1891           start -= aiff->datastart;
1892           start = MAX (start, 0);
1893         }
1894         if (stop > 0) {
1895           end_offset = stop;
1896           stop -= aiff->datastart;
1897           stop = MAX (stop, 0);
1898         }
1899         if (aiff->state == AIFF_PARSE_DATA &&
1900             aiff->segment.format == GST_FORMAT_TIME) {
1901           /* operating in format TIME, so we can convert */
1902           if (aiff->bps) {
1903             if (start >= 0)
1904               start =
1905                   gst_util_uint64_scale_ceil (start, GST_SECOND,
1906                   (guint64) aiff->bps);
1907             if (stop >= 0)
1908               stop =
1909                   gst_util_uint64_scale_ceil (stop, GST_SECOND,
1910                   (guint64) aiff->bps);
1911           } else {
1912             GST_DEBUG_OBJECT (aiff, "unable to compute segment start/stop");
1913             goto exit;
1914           }
1915         }
1916       } else {
1917         GST_DEBUG_OBJECT (aiff, "unsupported segment format, ignoring");
1918         goto exit;
1919       }
1920 
1921       segment.start = start;
1922       segment.stop = stop;
1923 
1924       /* accept upstream's notion of segment and distribute along */
1925       if (aiff->state == AIFF_PARSE_DATA) {
1926         segment.format = aiff->segment.format;
1927         segment.time = segment.position = segment.start;
1928         segment.duration = aiff->segment.duration;
1929       }
1930 
1931       gst_segment_copy_into (&segment, &aiff->segment);
1932 
1933       if (aiff->start_segment)
1934         gst_event_unref (aiff->start_segment);
1935 
1936       aiff->start_segment = gst_event_new_segment (&segment);
1937 
1938       /* If the seek is within the same SSND chunk and there is no new
1939        * end_offset defined keep the previous end_offset. This will avoid noise
1940        * at the end of playback if e.g. a metadata chunk is located at the end
1941        * of the file. */
1942       if (aiff->end_offset > 0 && offset < aiff->end_offset &&
1943           offset >= aiff->datastart && end_offset == -1) {
1944         end_offset = aiff->end_offset;
1945       }
1946 
1947       /* stream leftover data in current segment */
1948       if (aiff->state == AIFF_PARSE_DATA)
1949         gst_aiff_parse_flush_data (aiff);
1950       /* and set up streaming thread for next one */
1951       aiff->offset = offset;
1952       aiff->end_offset = end_offset;
1953       if (aiff->end_offset > 0) {
1954         aiff->dataleft = aiff->end_offset - aiff->offset;
1955       } else {
1956         /* infinity; upstream will EOS when done */
1957         aiff->dataleft = G_MAXUINT64;
1958       }
1959     exit:
1960       gst_event_unref (event);
1961       break;
1962     }
1963     case GST_EVENT_FLUSH_START:
1964       ret = gst_pad_push_event (aiff->srcpad, event);
1965       break;
1966     case GST_EVENT_FLUSH_STOP:
1967       ret = gst_pad_push_event (aiff->srcpad, event);
1968       gst_adapter_clear (aiff->adapter);
1969       break;
1970     default:
1971       ret = gst_pad_event_default (aiff->sinkpad, parent, event);
1972       break;
1973   }
1974 
1975   return ret;
1976 }
1977 
1978 static GstStateChangeReturn
1979 gst_aiff_parse_change_state (GstElement * element, GstStateChange transition)
1980 {
1981   GstStateChangeReturn ret;
1982   GstAiffParse *aiff = GST_AIFF_PARSE (element);
1983 
1984   switch (transition) {
1985     case GST_STATE_CHANGE_NULL_TO_READY:
1986       break;
1987     case GST_STATE_CHANGE_READY_TO_PAUSED:
1988       gst_aiff_parse_reset (aiff);
1989       break;
1990     case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
1991       break;
1992     default:
1993       break;
1994   }
1995 
1996   ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
1997 
1998   switch (transition) {
1999     case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
2000       break;
2001     case GST_STATE_CHANGE_PAUSED_TO_READY:
2002       gst_aiff_parse_reset (aiff);
2003       break;
2004     case GST_STATE_CHANGE_READY_TO_NULL:
2005       break;
2006     default:
2007       break;
2008   }
2009   return ret;
2010 }