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 }