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