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>
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.
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.
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.
25 * SECTION:element-aiffparse
29 * Parse a .aiff file into raw or compressed audio.
32 * The aiffparse element supports both push and pull mode operations, making it
33 * possible to stream from a network source.
35 * <title>Example launch line</title>
38 * gst-launch filesrc location=sine.aiff ! aiffparse ! audioconvert ! alsasink
40 * Read a aiff file and output to the soundcard using the ALSA element. The
41 * aiff file is assumed to contain raw uncompressed samples.
45 * gst-launch souphhtpsrc location=http://www.example.org/sine.aiff ! queue ! aiffparse ! audioconvert ! alsasink
47 * Stream data from a network url.
59 #include "aiffparse.h"
60 #include <gst/audio/audio.h>
61 #include <gst/tag/tag.h>
62 #include <gst/gst-i18n-plugin.h>
64 GST_DEBUG_CATEGORY (aiffparse_debug);
65 #define GST_CAT_DEFAULT (aiffparse_debug)
67 static void gst_aiff_parse_dispose (GObject * object);
69 static gboolean gst_aiff_parse_sink_activate (GstPad * sinkpad,
71 static gboolean gst_aiff_parse_sink_activate_mode (GstPad * sinkpad,
72 GstObject * parent, GstPadMode mode, gboolean active);
73 static gboolean gst_aiff_parse_sink_event (GstPad * pad, GstObject * parent,
75 static gboolean gst_aiff_parse_send_event (GstElement * element,
77 static GstStateChangeReturn gst_aiff_parse_change_state (GstElement * element,
78 GstStateChange transition);
80 static gboolean gst_aiff_parse_pad_query (GstPad * pad, GstObject * parent,
82 static gboolean gst_aiff_parse_pad_convert (GstPad * pad,
84 gint64 src_value, GstFormat * dest_format, gint64 * dest_value);
86 static GstFlowReturn gst_aiff_parse_chain (GstPad * pad, GstObject * parent,
88 static void gst_aiff_parse_loop (GstPad * pad);
89 static gboolean gst_aiff_parse_srcpad_event (GstPad * pad, GstObject * parent,
92 static GstStaticPadTemplate sink_template_factory =
93 GST_STATIC_PAD_TEMPLATE ("sink",
96 GST_STATIC_CAPS ("audio/x-aiff")
99 static GstStaticPadTemplate src_template_factory =
100 GST_STATIC_PAD_TEMPLATE ("src",
103 GST_STATIC_CAPS (GST_AUDIO_CAPS_MAKE ("{ S8, S16BE, S16LE, S24BE, S24LE, "
104 "S32LE, S32BE, F32BE, F64BE }"))
107 #define MAX_BUFFER_SIZE 4096
109 #define gst_aiff_parse_parent_class parent_class
110 G_DEFINE_TYPE (GstAiffParse, gst_aiff_parse, GST_TYPE_ELEMENT);
113 gst_aiff_parse_class_init (GstAiffParseClass * klass)
115 GstElementClass *gstelement_class;
116 GObjectClass *object_class;
118 gstelement_class = (GstElementClass *) klass;
119 object_class = (GObjectClass *) klass;
121 object_class->dispose = gst_aiff_parse_dispose;
123 gst_element_class_add_pad_template (gstelement_class,
124 gst_static_pad_template_get (&sink_template_factory));
125 gst_element_class_add_pad_template (gstelement_class,
126 gst_static_pad_template_get (&src_template_factory));
128 gst_element_class_set_static_metadata (gstelement_class,
129 "AIFF audio demuxer", "Codec/Demuxer/Audio",
130 "Parse a .aiff file into raw audio",
131 "Pioneers of the Inevitable <songbird@songbirdnest.com>");
133 gstelement_class->change_state =
134 GST_DEBUG_FUNCPTR (gst_aiff_parse_change_state);
135 gstelement_class->send_event = GST_DEBUG_FUNCPTR (gst_aiff_parse_send_event);
139 gst_aiff_parse_reset (GstAiffParse * aiff)
141 aiff->state = AIFF_PARSE_START;
143 /* These will all be set correctly in the fmt chunk */
150 aiff->end_offset = 0;
155 aiff->got_comm = FALSE;
157 if (aiff->seek_event)
158 gst_event_unref (aiff->seek_event);
159 aiff->seek_event = NULL;
161 gst_adapter_clear (aiff->adapter);
162 aiff->adapter = NULL;
165 if (aiff->tags != NULL) {
166 gst_tag_list_unref (aiff->tags);
172 gst_aiff_parse_dispose (GObject * object)
174 GstAiffParse *aiff = GST_AIFF_PARSE (object);
176 GST_DEBUG_OBJECT (aiff, "AIFF: Dispose");
177 gst_aiff_parse_reset (aiff);
179 G_OBJECT_CLASS (parent_class)->dispose (object);
183 gst_aiff_parse_init (GstAiffParse * aiffparse)
185 gst_aiff_parse_reset (aiffparse);
189 gst_pad_new_from_static_template (&sink_template_factory, "sink");
190 gst_pad_set_activate_function (aiffparse->sinkpad,
191 GST_DEBUG_FUNCPTR (gst_aiff_parse_sink_activate));
192 gst_pad_set_activatemode_function (aiffparse->sinkpad,
193 GST_DEBUG_FUNCPTR (gst_aiff_parse_sink_activate_mode));
194 gst_pad_set_event_function (aiffparse->sinkpad,
195 GST_DEBUG_FUNCPTR (gst_aiff_parse_sink_event));
196 gst_pad_set_chain_function (aiffparse->sinkpad,
197 GST_DEBUG_FUNCPTR (gst_aiff_parse_chain));
198 gst_element_add_pad (GST_ELEMENT_CAST (aiffparse), aiffparse->sinkpad);
202 gst_pad_new_from_static_template (&src_template_factory, "src");
203 gst_pad_use_fixed_caps (aiffparse->srcpad);
204 gst_pad_set_query_function (aiffparse->srcpad,
205 GST_DEBUG_FUNCPTR (gst_aiff_parse_pad_query));
206 gst_pad_set_event_function (aiffparse->srcpad,
207 GST_DEBUG_FUNCPTR (gst_aiff_parse_srcpad_event));
208 gst_element_add_pad (GST_ELEMENT_CAST (aiffparse), aiffparse->srcpad);
212 gst_aiff_parse_parse_file_header (GstAiffParse * aiff, GstBuffer * buf)
214 guint32 header, type = 0;
217 if (!gst_buffer_map (buf, &info, GST_MAP_READ)) {
218 GST_WARNING_OBJECT (aiff, "Could not map buffer");
222 if (info.size < 12) {
223 GST_WARNING_OBJECT (aiff, "Buffer too short");
224 gst_buffer_unmap (buf, &info);
228 header = GST_READ_UINT32_LE (info.data);
229 type = GST_READ_UINT32_LE (info.data + 8);
230 gst_buffer_unmap (buf, &info);
232 if (header != GST_MAKE_FOURCC ('F', 'O', 'R', 'M'))
235 if (type == GST_MAKE_FOURCC ('A', 'I', 'F', 'F'))
236 aiff->is_aifc = FALSE;
237 else if (type == GST_MAKE_FOURCC ('A', 'I', 'F', 'C'))
238 aiff->is_aifc = TRUE;
242 gst_buffer_unref (buf);
248 GST_ELEMENT_ERROR (aiff, STREAM, WRONG_TYPE, (NULL),
249 ("File is not an AIFF file: 0x%" G_GINT32_MODIFIER "x", type));
250 gst_buffer_unref (buf);
256 gst_aiff_parse_stream_init (GstAiffParse * aiff)
259 GstBuffer *buf = NULL;
261 if ((res = gst_pad_pull_range (aiff->sinkpad,
262 aiff->offset, 12, &buf)) != GST_FLOW_OK)
264 else if (!gst_aiff_parse_parse_file_header (aiff, buf))
265 return GST_FLOW_ERROR;
273 gst_aiff_parse_time_to_bytepos (GstAiffParse * aiff, gint64 ts,
276 /* -1 always maps to -1 */
282 /* 0 always maps to 0 */
289 *bytepos = gst_util_uint64_scale_ceil (ts, (guint64) aiff->bps, GST_SECOND);
293 GST_WARNING_OBJECT (aiff, "No valid bps to convert position");
298 /* This function is used to perform seeks on the element in
301 * It also works when event is NULL, in which case it will just
302 * start from the last configured segment. This technique is
303 * used when activating the element and to perform the seek in
307 gst_aiff_parse_perform_seek (GstAiffParse * aiff, GstEvent * event,
314 GstSeekType start_type = GST_SEEK_TYPE_NONE, stop_type;
315 gint64 start, stop, upstream_size;
318 GstSegment seeksegment = { 0, };
322 GST_DEBUG_OBJECT (aiff, "doing seek with event");
324 gst_event_parse_seek (event, &rate, &format, &flags,
325 &start_type, &start, &stop_type, &stop);
327 /* no negative rates yet */
331 if (format != aiff->segment.format) {
332 GST_INFO_OBJECT (aiff, "converting seek-event from %s to %s",
333 gst_format_get_name (format),
334 gst_format_get_name (aiff->segment.format));
336 if (start_type != GST_SEEK_TYPE_NONE)
338 gst_pad_query_convert (aiff->srcpad, format, start,
339 aiff->segment.format, &start);
340 if (res && stop_type != GST_SEEK_TYPE_NONE)
342 gst_pad_query_convert (aiff->srcpad, format, stop,
343 aiff->segment.format, &stop);
347 format = aiff->segment.format;
350 GST_DEBUG_OBJECT (aiff, "doing seek without event");
354 start_type = GST_SEEK_TYPE_SET;
356 stop_type = GST_SEEK_TYPE_SET;
360 flush = flags & GST_SEEK_FLAG_FLUSH;
362 if (aiff->streaming && !starting) {
366 if ((start_type != GST_SEEK_TYPE_NONE)) {
367 /* bring offset to bytes, if the bps is 0, we have the segment in BYTES and
368 * we can just copy the position. If not, we use the bps to convert TIME to
372 gst_util_uint64_scale_ceil (start, (guint64) aiff->bps, GST_SECOND);
373 start -= (start % aiff->bytes_per_sample);
374 start += aiff->datastart;
377 if (stop_type != GST_SEEK_TYPE_NONE) {
380 gst_util_uint64_scale_ceil (stop, (guint64) aiff->bps, GST_SECOND);
381 stop -= (stop % aiff->bytes_per_sample);
382 stop += aiff->datastart;
385 /* make sure filesize is not exceeded due to rounding errors or so,
386 * same precaution as in _stream_headers */
387 if (gst_pad_peer_query_duration (aiff->sinkpad, GST_FORMAT_BYTES,
389 stop = MIN (stop, upstream_size);
391 if (stop >= 0 && stop <= start)
394 new_event = gst_event_new_seek (rate, GST_FORMAT_BYTES, flags,
395 start_type, start, stop_type, stop);
397 res = gst_pad_push_event (aiff->sinkpad, new_event);
399 /* now we need to make sure the streaming thread is stopped. We do this by
400 * either sending a FLUSH_START event downstream which will cause the
401 * streaming thread to stop with a FLUSHING.
402 * For a non-flushing seek we simply pause the task, which will happen as soon
403 * as it completes one iteration (and thus might block when the sink is
404 * blocking in preroll). */
406 GST_DEBUG_OBJECT (aiff, "sending flush start");
407 gst_pad_push_event (aiff->srcpad, gst_event_new_flush_start ());
409 gst_pad_pause_task (aiff->sinkpad);
412 /* we should now be able to grab the streaming thread because we stopped it
413 * with the above flush/pause code */
414 GST_PAD_STREAM_LOCK (aiff->sinkpad);
416 /* save current position */
417 position = aiff->segment.position;
419 GST_DEBUG_OBJECT (aiff, "stopped streaming at %" G_GINT64_FORMAT, position);
421 /* copy segment, we need this because we still need the old
422 * segment when we close the current segment. */
423 memcpy (&seeksegment, &aiff->segment, sizeof (GstSegment));
425 /* configure the seek parameters in the seeksegment. We will then have the
426 * right values in the segment to perform the seek */
428 GST_DEBUG_OBJECT (aiff, "configuring seek");
429 gst_segment_do_seek (&seeksegment, rate, format, flags,
430 start_type, start, stop_type, stop, &update);
433 /* figure out the last position we need to play. If it's configured (stop !=
434 * -1), use that, else we play until the total duration of the file */
435 if ((stop = seeksegment.stop) == -1)
436 stop = seeksegment.duration;
438 GST_DEBUG_OBJECT (aiff, "start_type =%d", start_type);
439 if ((start_type != GST_SEEK_TYPE_NONE)) {
440 /* bring offset to bytes, if the bps is 0, we have the segment in BYTES and
441 * we can just copy the position. If not, we use the bps to convert TIME to
445 gst_util_uint64_scale_ceil (seeksegment.position,
446 (guint64) aiff->bps, GST_SECOND);
448 aiff->offset = seeksegment.position;
449 GST_LOG_OBJECT (aiff, "offset=%" G_GUINT64_FORMAT, aiff->offset);
450 aiff->offset -= (aiff->offset % aiff->bytes_per_sample);
451 GST_LOG_OBJECT (aiff, "offset=%" G_GUINT64_FORMAT, aiff->offset);
452 aiff->offset += aiff->datastart;
453 GST_LOG_OBJECT (aiff, "offset=%" G_GUINT64_FORMAT, aiff->offset);
455 GST_LOG_OBJECT (aiff, "continue from offset=%" G_GUINT64_FORMAT,
459 if (stop_type != GST_SEEK_TYPE_NONE) {
462 gst_util_uint64_scale_ceil (stop, (guint64) aiff->bps, GST_SECOND);
464 aiff->end_offset = stop;
465 GST_LOG_OBJECT (aiff, "end_offset=%" G_GUINT64_FORMAT, aiff->end_offset);
466 aiff->end_offset -= (aiff->end_offset % aiff->bytes_per_sample);
467 GST_LOG_OBJECT (aiff, "end_offset=%" G_GUINT64_FORMAT, aiff->end_offset);
468 aiff->end_offset += aiff->datastart;
469 GST_LOG_OBJECT (aiff, "end_offset=%" G_GUINT64_FORMAT, aiff->end_offset);
471 GST_LOG_OBJECT (aiff, "continue to end_offset=%" G_GUINT64_FORMAT,
475 /* make sure filesize is not exceeded due to rounding errors or so,
476 * same precaution as in _stream_headers */
477 if (gst_pad_peer_query_duration (aiff->sinkpad, GST_FORMAT_BYTES,
479 aiff->end_offset = MIN (aiff->end_offset, upstream_size);
481 /* this is the range of bytes we will use for playback */
482 aiff->offset = MIN (aiff->offset, aiff->end_offset);
483 aiff->dataleft = aiff->end_offset - aiff->offset;
485 GST_DEBUG_OBJECT (aiff,
486 "seek: rate %lf, offset %" G_GUINT64_FORMAT ", end %" G_GUINT64_FORMAT
487 ", segment %" GST_TIME_FORMAT " -- %" GST_TIME_FORMAT, rate,
488 aiff->offset, aiff->end_offset, GST_TIME_ARGS (seeksegment.start),
489 GST_TIME_ARGS (stop));
491 /* prepare for streaming again */
493 /* if we sent a FLUSH_START, we now send a FLUSH_STOP */
494 GST_DEBUG_OBJECT (aiff, "sending flush stop");
495 gst_pad_push_event (aiff->srcpad, gst_event_new_flush_stop (TRUE));
498 /* now we did the seek and can activate the new segment values */
499 memcpy (&aiff->segment, &seeksegment, sizeof (GstSegment));
501 /* if we're doing a segment seek, post a SEGMENT_START message */
502 if (aiff->segment.flags & GST_SEEK_FLAG_SEGMENT) {
503 gst_element_post_message (GST_ELEMENT_CAST (aiff),
504 gst_message_new_segment_start (GST_OBJECT_CAST (aiff),
505 aiff->segment.format, aiff->segment.position));
508 /* now create the segment */
509 GST_DEBUG_OBJECT (aiff, "Creating segment from %" G_GINT64_FORMAT
510 " to %" G_GINT64_FORMAT, aiff->segment.position, stop);
512 /* store the segment event so it can be sent from the streaming thread. */
513 if (aiff->start_segment)
514 gst_event_unref (aiff->start_segment);
515 aiff->start_segment = gst_event_new_segment (&aiff->segment);
517 /* mark discont if we are going to stream from another position. */
518 if (position != aiff->segment.position) {
519 GST_DEBUG_OBJECT (aiff,
520 "mark DISCONT, we did a seek to another position");
521 aiff->discont = TRUE;
524 /* and start the streaming task again */
525 aiff->segment_running = TRUE;
526 if (!aiff->streaming) {
527 gst_pad_start_task (aiff->sinkpad, (GstTaskFunction) gst_aiff_parse_loop,
528 aiff->sinkpad, NULL);
531 GST_PAD_STREAM_UNLOCK (aiff->sinkpad);
541 GST_DEBUG_OBJECT (aiff, "negative playback rates are not supported yet.");
546 GST_DEBUG_OBJECT (aiff, "unsupported format given, seek aborted.");
552 * gst_aiff_parse_peek_chunk_info:
553 * @aiff AIFFparse object
554 * @tag holder for tag
555 * @size holder for tag size
557 * Peek next chunk info (tag and size)
559 * Returns: %TRUE when the chunk info (header) is available
562 gst_aiff_parse_peek_chunk_info (GstAiffParse * aiff, guint32 * tag,
565 const guint8 *data = NULL;
567 if (gst_adapter_available (aiff->adapter) < 8)
570 data = gst_adapter_map (aiff->adapter, 8);
571 *tag = GST_READ_UINT32_LE (data);
572 *size = GST_READ_UINT32_BE (data + 4);
573 gst_adapter_unmap (aiff->adapter);
575 GST_DEBUG_OBJECT (aiff,
576 "Next chunk size is %d bytes, type %" GST_FOURCC_FORMAT, *size,
577 GST_FOURCC_ARGS (*tag));
583 * gst_aiff_parse_peek_chunk:
584 * @aiff AIFFparse object
585 * @tag holder for tag
586 * @size holder for tag size
588 * Peek enough data for one full chunk
590 * Returns: %TRUE when the full chunk is available
593 gst_aiff_parse_peek_chunk (GstAiffParse * aiff, guint32 * tag, guint32 * size)
595 guint32 peek_size = 0;
598 if (!gst_aiff_parse_peek_chunk_info (aiff, tag, size))
601 GST_DEBUG_OBJECT (aiff, "Need to peek chunk of %d bytes", *size);
602 peek_size = (*size + 1) & ~1;
604 available = gst_adapter_available (aiff->adapter);
605 if (available >= (8 + peek_size)) {
608 GST_LOG_OBJECT (aiff, "but only %u bytes available now", available);
614 gst_aiff_parse_peek_data (GstAiffParse * aiff, guint32 size,
615 const guint8 ** data)
617 if (gst_adapter_available (aiff->adapter) < size)
620 *data = gst_adapter_map (aiff->adapter, size);
625 * gst_aiff_parse_calculate_duration:
626 * @aiff: aiffparse object
628 * Calculate duration on demand and store in @aiff.
630 * Returns: %TRUE if duration is available.
633 gst_aiff_parse_calculate_duration (GstAiffParse * aiff)
635 if (aiff->duration > 0)
638 if (aiff->datasize > 0 && aiff->bps > 0) {
640 gst_util_uint64_scale_ceil (aiff->datasize, GST_SECOND,
641 (guint64) aiff->bps);
642 GST_INFO_OBJECT (aiff, "Got duration %" GST_TIME_FORMAT,
643 GST_TIME_ARGS (aiff->duration));
650 gst_aiff_parse_ignore_chunk (GstAiffParse * aiff, guint32 tag, guint32 size)
654 if (aiff->streaming) {
655 if (!gst_aiff_parse_peek_chunk (aiff, &tag, &size))
658 GST_WARNING_OBJECT (aiff, "Ignoring tag %" GST_FOURCC_FORMAT,
659 GST_FOURCC_ARGS (tag));
660 flush = 8 + ((size + 1) & ~1);
661 aiff->offset += flush;
662 if (aiff->streaming) {
663 gst_adapter_flush (aiff->adapter, flush);
668 gst_aiff_parse_read_IEEE80 (guint8 * buf)
670 int s = buf[0] & 0xff;
671 int e = ((buf[0] & 0x7f) << 8) | (buf[1] & 0xff);
672 double f = ((unsigned long) (buf[2] & 0xff) << 24) |
673 ((buf[3] & 0xff) << 16) | ((buf[4] & 0xff) << 8) | (buf[5] & 0xff);
677 return HUGE_VAL; /* Really NaN, but this won't happen in reality */
687 f += ((buf[6] & 0xff) << 24) |
688 ((buf[7] & 0xff) << 16) | ((buf[8] & 0xff) << 8) | (buf[9] & 0xff);
690 return ldexp (f, e - 16446);
694 gst_aiff_parse_parse_comm (GstAiffParse * aiff, GstBuffer * buf)
700 if (!gst_buffer_map (buf, &info, GST_MAP_READ)) {
701 GST_WARNING_OBJECT (aiff, "Can't map buffer");
702 gst_buffer_unref (buf);
711 if (info.size < size)
714 aiff->channels = GST_READ_UINT16_BE (info.data);
715 aiff->total_frames = GST_READ_UINT32_BE (info.data + 2);
716 aiff->depth = GST_READ_UINT16_BE (info.data + 6);
717 aiff->width = GST_ROUND_UP_8 (aiff->depth);
718 aiff->rate = (int) gst_aiff_parse_read_IEEE80 (info.data + 8);
720 aiff->floating_point = FALSE;
723 fourcc = GST_READ_UINT32_LE (info.data + 18);
725 /* We only support the 'trivial' uncompressed AIFC, but it can be
726 * either big or little endian */
728 case GST_MAKE_FOURCC ('N', 'O', 'N', 'E'):
729 aiff->endianness = G_BIG_ENDIAN;
731 case GST_MAKE_FOURCC ('s', 'o', 'w', 't'):
732 aiff->endianness = G_LITTLE_ENDIAN;
734 case GST_MAKE_FOURCC ('F', 'L', '3', '2'):
735 case GST_MAKE_FOURCC ('f', 'l', '3', '2'):
736 aiff->floating_point = TRUE;
737 aiff->width = aiff->depth = 32;
738 aiff->endianness = G_BIG_ENDIAN;
740 case GST_MAKE_FOURCC ('f', 'l', '6', '4'):
741 aiff->floating_point = TRUE;
742 aiff->width = aiff->depth = 64;
743 aiff->endianness = G_BIG_ENDIAN;
746 goto unknown_compression;
749 aiff->endianness = G_BIG_ENDIAN;
751 gst_buffer_unmap (buf, &info);
752 gst_buffer_unref (buf);
759 GST_WARNING_OBJECT (aiff, "COMM chunk too short, cannot parse header");
760 gst_buffer_unmap (buf, &info);
761 gst_buffer_unref (buf);
766 GST_WARNING_OBJECT (aiff, "Unsupported compression in AIFC "
767 "file: %" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (fourcc));
768 gst_buffer_unmap (buf, &info);
769 gst_buffer_unref (buf);
775 gst_aiff_parse_read_chunk (GstAiffParse * aiff, guint64 * offset, guint32 * tag,
780 GstBuffer *buf = NULL;
784 gst_pad_pull_range (aiff->sinkpad, *offset, 8, &buf)) != GST_FLOW_OK)
787 gst_buffer_map (buf, &info, GST_MAP_READ);
788 *tag = GST_READ_UINT32_LE (info.data);
789 size = GST_READ_UINT32_BE (info.data + 4);
790 gst_buffer_unmap (buf, &info);
791 gst_buffer_unref (buf);
795 gst_pad_pull_range (aiff->sinkpad, (*offset) + 8, size,
796 &buf)) != GST_FLOW_OK)
798 else if (gst_buffer_get_size (buf) < size)
802 *offset += 8 + GST_ROUND_UP_2 (size);
809 /* short read, we return EOS to mark the EOS case */
810 GST_DEBUG_OBJECT (aiff,
811 "not enough data (available=%" G_GSIZE_FORMAT ", needed=%u)",
812 gst_buffer_get_size (buf), size);
813 gst_buffer_unref (buf);
820 gst_aiff_parse_create_caps (GstAiffParse * aiff)
822 GstCaps *caps = NULL;
823 const gchar *format = NULL;
825 if (aiff->floating_point) {
826 if (aiff->endianness == G_BIG_ENDIAN) {
827 if (aiff->width == 32)
829 else if (aiff->width == 64)
833 if (aiff->endianness == G_BIG_ENDIAN) {
834 if (aiff->width == 8)
836 else if (aiff->width == 16)
838 else if (aiff->width == 24)
840 else if (aiff->width == 32)
843 if (aiff->width == 8)
845 else if (aiff->width == 16)
847 else if (aiff->width == 24)
849 else if (aiff->width == 32)
854 caps = gst_caps_new_simple ("audio/x-raw",
855 "format", G_TYPE_STRING, format,
856 "channels", G_TYPE_INT, aiff->channels,
857 "layout", G_TYPE_STRING, "interleaved",
858 "rate", G_TYPE_INT, aiff->rate, NULL);
861 GST_DEBUG_OBJECT (aiff, "Created caps: %" GST_PTR_FORMAT, caps);
867 gst_aiff_parse_stream_headers (GstAiffParse * aiff)
870 GstBuffer *buf = NULL;
872 gboolean gotdata = FALSE;
873 gboolean done = FALSE;
875 gint64 upstream_size = 0;
877 gst_pad_peer_query_duration (aiff->sinkpad, GST_FORMAT_BYTES, &upstream_size);
878 GST_DEBUG_OBJECT (aiff, "upstream size %" G_GUINT64_FORMAT, upstream_size);
880 /* loop headers until we get data */
882 if (aiff->streaming) {
883 if (!gst_aiff_parse_peek_chunk_info (aiff, &tag, &size))
889 gst_pad_pull_range (aiff->sinkpad, aiff->offset, 8,
890 &buf)) != GST_FLOW_OK)
891 goto header_read_error;
893 gst_buffer_map (buf, &info, GST_MAP_READ);
894 tag = GST_READ_UINT32_LE (info.data);
895 size = GST_READ_UINT32_BE (info.data + 4);
896 gst_buffer_unmap (buf, &info);
897 gst_buffer_unref (buf);
901 GST_INFO_OBJECT (aiff,
902 "Got TAG: %" GST_FOURCC_FORMAT ", offset %" G_GUINT64_FORMAT,
903 GST_FOURCC_ARGS (tag), aiff->offset);
905 /* We just keep reading chunks until we find the one we're interested in.
908 case GST_MAKE_FOURCC ('C', 'O', 'M', 'M'):{
913 if (aiff->streaming) {
914 if (!gst_aiff_parse_peek_chunk (aiff, &tag, &size))
917 gst_adapter_flush (aiff->adapter, 8);
920 buf = gst_adapter_take_buffer (aiff->adapter, size);
921 aiff->offset += size;
923 if ((res = gst_aiff_parse_read_chunk (aiff,
924 &aiff->offset, &tag, &buf)) != GST_FLOW_OK)
928 if (!gst_aiff_parse_parse_comm (aiff, buf))
929 goto parse_header_error;
931 /* do sanity checks of header fields */
932 if (aiff->channels == 0)
938 gst_pad_create_stream_id (aiff->srcpad, GST_ELEMENT_CAST (aiff),
940 event = gst_event_new_stream_start (stream_id);
941 gst_event_set_group_id (event, gst_util_group_id_next ());
942 gst_pad_push_event (aiff->srcpad, event);
945 GST_DEBUG_OBJECT (aiff, "creating the caps");
947 caps = gst_aiff_parse_create_caps (aiff);
951 gst_pad_push_event (aiff->srcpad, gst_event_new_caps (caps));
952 gst_caps_unref (caps);
954 aiff->bytes_per_sample = aiff->channels * aiff->width / 8;
955 aiff->bps = aiff->bytes_per_sample * aiff->rate;
957 if (aiff->bytes_per_sample <= 0)
958 goto no_bytes_per_sample;
960 aiff->got_comm = TRUE;
963 case GST_MAKE_FOURCC ('S', 'S', 'N', 'D'):{
966 GST_DEBUG_OBJECT (aiff, "Got 'SSND' TAG, size : %d", size);
968 /* Now, read the 8-byte header in the SSND chunk */
969 if (aiff->streaming) {
970 const guint8 *ssnddata = NULL;
972 if (!gst_aiff_parse_peek_data (aiff, 16, &ssnddata))
975 aiff->ssnd_offset = GST_READ_UINT32_BE (ssnddata + 8);
976 aiff->ssnd_blocksize = GST_READ_UINT32_BE (ssnddata + 12);
977 gst_adapter_unmap (aiff->adapter);
978 gst_adapter_flush (aiff->adapter, 16);
980 GstBuffer *ssndbuf = NULL;
984 gst_pad_pull_range (aiff->sinkpad, aiff->offset, 16,
985 &ssndbuf)) != GST_FLOW_OK)
986 goto header_read_error;
988 gst_buffer_map (ssndbuf, &info, GST_MAP_READ);
989 aiff->ssnd_offset = GST_READ_UINT32_BE (info.data + 8);
990 aiff->ssnd_blocksize = GST_READ_UINT32_BE (info.data + 12);
991 gst_buffer_unmap (ssndbuf, &info);
992 gst_buffer_unref (ssndbuf);
997 /* 8 byte chunk header, 8 byte SSND header */
1001 aiff->datastart = aiff->offset + aiff->ssnd_offset;
1002 /* file might be truncated */
1003 if (upstream_size) {
1004 size = MIN (datasize, (upstream_size - aiff->datastart));
1006 aiff->datasize = (guint64) datasize;
1007 aiff->dataleft = (guint64) datasize;
1008 aiff->end_offset = datasize + aiff->datastart;
1009 if (!aiff->streaming) {
1010 /* We will continue looking at chunks until the end - to read tags,
1012 aiff->offset += datasize;
1014 GST_DEBUG_OBJECT (aiff, "datasize = %d", datasize);
1015 if (aiff->streaming) {
1020 case GST_MAKE_FOURCC ('I', 'D', '3', ' '):{
1023 if (aiff->streaming) {
1024 if (!gst_aiff_parse_peek_chunk (aiff, &tag, &size))
1027 gst_adapter_flush (aiff->adapter, 8);
1030 buf = gst_adapter_take_buffer (aiff->adapter, size);
1032 if ((res = gst_aiff_parse_read_chunk (aiff,
1033 &aiff->offset, &tag, &buf)) != GST_FLOW_OK)
1037 GST_LOG_OBJECT (aiff, "ID3 chunk of size %" G_GSIZE_FORMAT,
1038 gst_buffer_get_size (buf));
1040 tags = gst_tag_list_from_id3v2_tag (buf);
1041 gst_buffer_unref (buf);
1043 GST_INFO_OBJECT (aiff, "ID3 tags: %" GST_PTR_FORMAT, tags);
1045 if (aiff->tags == NULL) {
1048 gst_tag_list_insert (aiff->tags, tags, GST_TAG_MERGE_APPEND);
1049 gst_tag_list_unref (tags);
1054 gst_aiff_parse_ignore_chunk (aiff, tag, size);
1059 if (upstream_size && (aiff->offset >= upstream_size)) {
1060 /* Now we have gone through the whole file */
1065 /* We read all the chunks (in pull mode) or reached the SSND chunk
1066 * (in push mode). We must have both COMM and SSND now; error out
1069 if (!aiff->got_comm) {
1070 GST_WARNING_OBJECT (aiff, "Failed to find COMM chunk");
1074 GST_WARNING_OBJECT (aiff, "Failed to find SSND chunk");
1078 GST_DEBUG_OBJECT (aiff, "Finished parsing headers");
1080 if (gst_aiff_parse_calculate_duration (aiff)) {
1081 gst_segment_init (&aiff->segment, GST_FORMAT_TIME);
1082 aiff->segment.duration = aiff->duration;
1084 /* no bitrate, let downstream peer do the math, we'll feed it bytes. */
1085 gst_segment_init (&aiff->segment, GST_FORMAT_BYTES);
1086 aiff->segment.duration = aiff->datasize;
1089 /* now we have all the info to perform a pending seek if any, if no
1090 * event, this will still do the right thing and it will also send
1091 * the right segment event downstream. */
1092 gst_aiff_parse_perform_seek (aiff, aiff->seek_event, TRUE);
1093 /* remove pending event */
1094 event_p = &aiff->seek_event;
1095 gst_event_replace (event_p, NULL);
1097 /* we just started, we are discont */
1098 aiff->discont = TRUE;
1100 aiff->state = AIFF_PARSE_DATA;
1102 /* determine reasonable max buffer size,
1103 * that is, buffers not too small either size or time wise
1104 * so we do not end up with too many of them */
1107 gst_aiff_parse_time_to_bytepos (aiff, 40 * GST_MSECOND, &upstream_size);
1108 aiff->max_buf_size = upstream_size;
1109 aiff->max_buf_size = MAX (aiff->max_buf_size, MAX_BUFFER_SIZE);
1110 if (aiff->bytes_per_sample > 0)
1111 aiff->max_buf_size -= (aiff->max_buf_size % aiff->bytes_per_sample);
1113 GST_DEBUG_OBJECT (aiff, "max buffer size %u", aiff->max_buf_size);
1120 GST_ELEMENT_ERROR (aiff, STREAM, TYPE_NOT_FOUND, (NULL),
1121 ("Invalid AIFF header (no COMM found)"));
1122 return GST_FLOW_ERROR;
1126 GST_ELEMENT_ERROR (aiff, STREAM, TYPE_NOT_FOUND, (NULL),
1127 ("Invalid AIFF: no SSND found"));
1128 return GST_FLOW_ERROR;
1132 GST_ELEMENT_ERROR (aiff, STREAM, DEMUX, (NULL),
1133 ("Couldn't parse audio header"));
1134 return GST_FLOW_ERROR;
1138 GST_ELEMENT_ERROR (aiff, STREAM, FAILED, (NULL),
1139 ("Stream claims to contain no channels - invalid data"));
1140 return GST_FLOW_ERROR;
1144 GST_ELEMENT_ERROR (aiff, STREAM, FAILED, (NULL),
1145 ("Stream with sample_rate == 0 - invalid data"));
1146 return GST_FLOW_ERROR;
1148 no_bytes_per_sample:
1150 GST_ELEMENT_ERROR (aiff, STREAM, FAILED, (NULL),
1151 ("Could not calculate bytes per sample - invalid data"));
1152 return GST_FLOW_ERROR;
1156 GST_ELEMENT_ERROR (aiff, STREAM, TYPE_NOT_FOUND, (NULL),
1157 ("No caps found for format 0x%x, %d channels, %d Hz",
1158 aiff->format, aiff->channels, aiff->rate));
1159 return GST_FLOW_ERROR;
1163 GST_ELEMENT_ERROR (aiff, STREAM, DEMUX, (NULL),
1164 ("Couldn't read in header"));
1165 return GST_FLOW_ERROR;
1170 * Read AIFF file tag when streaming
1172 static GstFlowReturn
1173 gst_aiff_parse_parse_stream_init (GstAiffParse * aiff)
1175 if (gst_adapter_available (aiff->adapter) >= 12) {
1178 /* _take flushes the data */
1179 tmp = gst_adapter_take_buffer (aiff->adapter, 12);
1181 GST_DEBUG_OBJECT (aiff, "Parsing aiff header");
1182 if (!gst_aiff_parse_parse_file_header (aiff, tmp))
1183 return GST_FLOW_ERROR;
1186 /* Go to next state */
1187 aiff->state = AIFF_PARSE_HEADER;
1192 /* handle an event sent directly to the element.
1194 * This event can be sent either in the READY state or the
1195 * >READY state. The only event of interest really is the seek
1198 * In the READY state we can only store the event and try to
1199 * respect it when going to PAUSED. We assume we are in the
1200 * READY state when our parsing state != AIFF_PARSE_DATA.
1202 * When we are steaming, we can simply perform the seek right
1206 gst_aiff_parse_send_event (GstElement * element, GstEvent * event)
1208 GstAiffParse *aiff = GST_AIFF_PARSE (element);
1209 gboolean res = FALSE;
1212 GST_DEBUG_OBJECT (aiff, "received event %s", GST_EVENT_TYPE_NAME (event));
1214 switch (GST_EVENT_TYPE (event)) {
1215 case GST_EVENT_SEEK:
1216 if (aiff->state == AIFF_PARSE_DATA) {
1217 /* we can handle the seek directly when streaming data */
1218 res = gst_aiff_parse_perform_seek (aiff, event, FALSE);
1220 GST_DEBUG_OBJECT (aiff, "queuing seek for later");
1222 event_p = &aiff->seek_event;
1223 gst_event_replace (event_p, event);
1225 /* we always return true */
1232 gst_event_unref (event);
1236 static GstFlowReturn
1237 gst_aiff_parse_stream_data (GstAiffParse * aiff)
1239 GstBuffer *buf = NULL;
1240 GstFlowReturn res = GST_FLOW_OK;
1241 guint64 desired, obtained;
1242 GstClockTime timestamp, next_timestamp, duration;
1243 guint64 pos, nextpos;
1245 if (aiff->bytes_per_sample <= 0) {
1246 GST_ELEMENT_ERROR (aiff, STREAM, WRONG_TYPE, (NULL),
1247 ("File is not a valid AIFF file (invalid bytes per sample)"));
1248 return GST_FLOW_ERROR;
1252 GST_LOG_OBJECT (aiff,
1253 "offset: %" G_GINT64_FORMAT " , end: %" G_GINT64_FORMAT " , dataleft: %"
1254 G_GINT64_FORMAT, aiff->offset, aiff->end_offset, aiff->dataleft);
1256 /* Get the next n bytes and output them */
1257 if (aiff->dataleft == 0 || aiff->dataleft < aiff->bytes_per_sample)
1260 /* scale the amount of data by the segment rate so we get equal
1261 * amounts of data regardless of the playback rate */
1263 MIN (gst_guint64_to_gdouble (aiff->dataleft),
1264 aiff->max_buf_size * ABS (aiff->segment.rate));
1266 if (desired >= aiff->bytes_per_sample)
1267 desired -= (desired % aiff->bytes_per_sample);
1269 GST_LOG_OBJECT (aiff, "Fetching %" G_GINT64_FORMAT " bytes of data "
1270 "from the sinkpad", desired);
1272 if (aiff->streaming) {
1273 guint avail = gst_adapter_available (aiff->adapter);
1275 if (avail < desired) {
1276 GST_LOG_OBJECT (aiff, "Got only %d bytes of data from the sinkpad",
1281 buf = gst_adapter_take_buffer (aiff->adapter, desired);
1283 if ((res = gst_pad_pull_range (aiff->sinkpad, aiff->offset,
1284 desired, &buf)) != GST_FLOW_OK)
1288 /* If we have a pending close/start segment, send it now. */
1289 if (G_UNLIKELY (aiff->close_segment != NULL)) {
1290 gst_pad_push_event (aiff->srcpad, aiff->close_segment);
1291 aiff->close_segment = NULL;
1293 if (G_UNLIKELY (aiff->start_segment != NULL)) {
1294 gst_pad_push_event (aiff->srcpad, aiff->start_segment);
1295 aiff->start_segment = NULL;
1297 if (G_UNLIKELY (aiff->tags != NULL)) {
1298 gst_pad_push_event (aiff->srcpad, gst_event_new_tag (aiff->tags));
1302 obtained = gst_buffer_get_size (buf);
1304 /* our positions in bytes */
1305 pos = aiff->offset - aiff->datastart;
1306 nextpos = pos + obtained;
1308 /* update offsets, does not overflow. */
1309 GST_BUFFER_OFFSET (buf) = pos / aiff->bytes_per_sample;
1310 GST_BUFFER_OFFSET_END (buf) = nextpos / aiff->bytes_per_sample;
1312 if (aiff->bps > 0) {
1313 /* and timestamps if we have a bitrate, be careful for overflows */
1315 gst_util_uint64_scale_ceil (pos, GST_SECOND, (guint64) aiff->bps);
1317 gst_util_uint64_scale_ceil (nextpos, GST_SECOND, (guint64) aiff->bps);
1318 duration = next_timestamp - timestamp;
1320 /* update current running segment position */
1321 aiff->segment.position = next_timestamp;
1323 /* no bitrate, all we know is that the first sample has timestamp 0, all
1324 * other positions and durations have unknown timestamp. */
1328 timestamp = GST_CLOCK_TIME_NONE;
1329 duration = GST_CLOCK_TIME_NONE;
1330 /* update current running segment position with byte offset */
1331 aiff->segment.position = nextpos;
1333 if (aiff->discont) {
1334 GST_DEBUG_OBJECT (aiff, "marking DISCONT");
1335 GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_DISCONT);
1336 aiff->discont = FALSE;
1339 GST_BUFFER_TIMESTAMP (buf) = timestamp;
1340 GST_BUFFER_DURATION (buf) = duration;
1342 GST_LOG_OBJECT (aiff,
1343 "Got buffer. timestamp:%" GST_TIME_FORMAT " , duration:%" GST_TIME_FORMAT
1344 ", size:%" G_GUINT64_FORMAT, GST_TIME_ARGS (timestamp),
1345 GST_TIME_ARGS (duration), obtained);
1347 if ((res = gst_pad_push (aiff->srcpad, buf)) != GST_FLOW_OK)
1350 if (obtained < aiff->dataleft) {
1351 aiff->offset += obtained;
1352 aiff->dataleft -= obtained;
1354 aiff->offset += aiff->dataleft;
1358 /* Iterate until need more data, so adapter size won't grow */
1359 if (aiff->streaming) {
1360 GST_LOG_OBJECT (aiff,
1361 "offset: %" G_GINT64_FORMAT " , end: %" G_GINT64_FORMAT, aiff->offset,
1363 goto iterate_adapter;
1370 GST_DEBUG_OBJECT (aiff, "found EOS");
1371 return GST_FLOW_EOS;
1375 /* check if we got EOS */
1376 if (res == GST_FLOW_EOS)
1379 GST_WARNING_OBJECT (aiff,
1380 "Error getting %" G_GINT64_FORMAT " bytes from the "
1381 "sinkpad (dataleft = %" G_GINT64_FORMAT ")", desired, aiff->dataleft);
1386 GST_INFO_OBJECT (aiff,
1387 "Error pushing on srcpad %s:%s, reason %s, is linked? = %d",
1388 GST_DEBUG_PAD_NAME (aiff->srcpad), gst_flow_get_name (res),
1389 gst_pad_is_linked (aiff->srcpad));
1395 gst_aiff_parse_loop (GstPad * pad)
1398 GstAiffParse *aiff = GST_AIFF_PARSE (GST_PAD_PARENT (pad));
1400 GST_LOG_OBJECT (aiff, "process data");
1402 switch (aiff->state) {
1403 case AIFF_PARSE_START:
1404 GST_INFO_OBJECT (aiff, "AIFF_PARSE_START");
1405 if ((ret = gst_aiff_parse_stream_init (aiff)) != GST_FLOW_OK)
1408 aiff->state = AIFF_PARSE_HEADER;
1411 case AIFF_PARSE_HEADER:
1412 GST_INFO_OBJECT (aiff, "AIFF_PARSE_HEADER");
1413 if ((ret = gst_aiff_parse_stream_headers (aiff)) != GST_FLOW_OK)
1416 aiff->state = AIFF_PARSE_DATA;
1417 GST_INFO_OBJECT (aiff, "AIFF_PARSE_DATA");
1420 case AIFF_PARSE_DATA:
1421 if ((ret = gst_aiff_parse_stream_data (aiff)) != GST_FLOW_OK)
1425 g_assert_not_reached ();
1432 const gchar *reason = gst_flow_get_name (ret);
1434 GST_DEBUG_OBJECT (aiff, "pausing task, reason %s", reason);
1435 aiff->segment_running = FALSE;
1436 gst_pad_pause_task (pad);
1438 if (ret == GST_FLOW_EOS) {
1439 /* perform EOS logic */
1440 if (aiff->segment.flags & GST_SEEK_FLAG_SEGMENT) {
1443 if ((stop = aiff->segment.stop) == -1)
1444 stop = aiff->segment.duration;
1446 gst_element_post_message (GST_ELEMENT_CAST (aiff),
1447 gst_message_new_segment_done (GST_OBJECT_CAST (aiff),
1448 aiff->segment.format, stop));
1449 gst_pad_push_event (aiff->srcpad,
1450 gst_event_new_segment_done (aiff->segment.format, stop));
1452 gst_pad_push_event (aiff->srcpad, gst_event_new_eos ());
1454 } else if (ret < GST_FLOW_EOS || ret == GST_FLOW_NOT_LINKED) {
1455 /* for fatal errors we post an error message, post the error
1456 * first so the app knows about the error first. */
1457 GST_ELEMENT_ERROR (aiff, STREAM, FAILED,
1458 (_("Internal data flow error.")),
1459 ("streaming task paused, reason %s (%d)", reason, ret));
1460 gst_pad_push_event (aiff->srcpad, gst_event_new_eos ());
1466 static GstFlowReturn
1467 gst_aiff_parse_chain (GstPad * pad, GstObject * parent, GstBuffer * buf)
1470 GstAiffParse *aiff = GST_AIFF_PARSE (parent);
1472 GST_LOG_OBJECT (aiff, "adapter_push %" G_GSIZE_FORMAT " bytes",
1473 gst_buffer_get_size (buf));
1475 gst_adapter_push (aiff->adapter, buf);
1477 switch (aiff->state) {
1478 case AIFF_PARSE_START:
1479 GST_INFO_OBJECT (aiff, "AIFF_PARSE_START");
1480 if ((ret = gst_aiff_parse_parse_stream_init (aiff)) != GST_FLOW_OK)
1483 if (aiff->state != AIFF_PARSE_HEADER)
1486 /* otherwise fall-through */
1487 case AIFF_PARSE_HEADER:
1488 GST_INFO_OBJECT (aiff, "AIFF_PARSE_HEADER");
1489 if ((ret = gst_aiff_parse_stream_headers (aiff)) != GST_FLOW_OK)
1492 if (!aiff->got_comm || aiff->datastart == 0)
1495 aiff->state = AIFF_PARSE_DATA;
1496 GST_INFO_OBJECT (aiff, "AIFF_PARSE_DATA");
1499 case AIFF_PARSE_DATA:
1500 if ((ret = gst_aiff_parse_stream_data (aiff)) != GST_FLOW_OK)
1504 g_return_val_if_reached (GST_FLOW_ERROR);
1511 gst_aiff_parse_pad_convert (GstPad * pad,
1512 GstFormat src_format, gint64 src_value,
1513 GstFormat * dest_format, gint64 * dest_value)
1515 GstAiffParse *aiffparse;
1516 gboolean res = TRUE;
1518 aiffparse = GST_AIFF_PARSE (GST_PAD_PARENT (pad));
1520 if (*dest_format == src_format) {
1521 *dest_value = src_value;
1525 if (aiffparse->bytes_per_sample <= 0)
1528 GST_INFO_OBJECT (aiffparse, "converting value from %s to %s",
1529 gst_format_get_name (src_format), gst_format_get_name (*dest_format));
1531 switch (src_format) {
1532 case GST_FORMAT_BYTES:
1533 switch (*dest_format) {
1534 case GST_FORMAT_DEFAULT:
1535 *dest_value = src_value / aiffparse->bytes_per_sample;
1537 case GST_FORMAT_TIME:
1538 if (aiffparse->bps > 0) {
1539 *dest_value = gst_util_uint64_scale_ceil (src_value, GST_SECOND,
1540 (guint64) aiffparse->bps);
1543 /* Else fallthrough */
1550 case GST_FORMAT_DEFAULT:
1551 switch (*dest_format) {
1552 case GST_FORMAT_BYTES:
1553 *dest_value = src_value * aiffparse->bytes_per_sample;
1555 case GST_FORMAT_TIME:
1556 *dest_value = gst_util_uint64_scale (src_value, GST_SECOND,
1557 (guint64) aiffparse->rate);
1565 case GST_FORMAT_TIME:
1566 switch (*dest_format) {
1567 case GST_FORMAT_BYTES:
1568 if (aiffparse->bps > 0) {
1569 *dest_value = gst_util_uint64_scale (src_value,
1570 (guint64) aiffparse->bps, GST_SECOND);
1573 /* Else fallthrough */
1575 case GST_FORMAT_DEFAULT:
1576 *dest_value = gst_util_uint64_scale (src_value,
1577 (guint64) aiffparse->rate, GST_SECOND);
1595 /* handle queries for location and length in requested format */
1597 gst_aiff_parse_pad_query (GstPad * pad, GstObject * parent, GstQuery * query)
1599 gboolean res = FALSE;
1600 GstAiffParse *aiff = GST_AIFF_PARSE (parent);
1602 switch (GST_QUERY_TYPE (query)) {
1603 case GST_QUERY_DURATION:
1605 gint64 duration = 0;
1608 /* only if we know */
1609 if (aiff->state != AIFF_PARSE_DATA)
1612 gst_query_parse_duration (query, &format, NULL);
1615 case GST_FORMAT_TIME:{
1616 if ((res = gst_aiff_parse_calculate_duration (aiff))) {
1617 duration = aiff->duration;
1622 format = GST_FORMAT_BYTES;
1623 duration = aiff->datasize;
1626 gst_query_set_duration (query, format, duration);
1629 case GST_QUERY_CONVERT:
1631 gint64 srcvalue, dstvalue;
1632 GstFormat srcformat, dstformat;
1634 /* only if we know */
1635 if (aiff->state != AIFF_PARSE_DATA)
1638 gst_query_parse_convert (query, &srcformat, &srcvalue,
1639 &dstformat, &dstvalue);
1640 res = gst_aiff_parse_pad_convert (pad, srcformat, srcvalue,
1641 &dstformat, &dstvalue);
1643 gst_query_set_convert (query, srcformat, srcvalue, dstformat, dstvalue);
1646 case GST_QUERY_SEEKING:{
1649 /* only if we know */
1650 if (aiff->state != AIFF_PARSE_DATA)
1653 gst_query_parse_seeking (query, &fmt, NULL, NULL, NULL);
1654 if (fmt == GST_FORMAT_TIME) {
1655 gboolean seekable = TRUE;
1657 if (!gst_aiff_parse_calculate_duration (aiff)) {
1660 gst_query_set_seeking (query, GST_FORMAT_TIME, seekable,
1667 res = gst_pad_query_default (pad, parent, query);
1674 gst_aiff_parse_srcpad_event (GstPad * pad, GstObject * parent, GstEvent * event)
1676 GstAiffParse *aiffparse = GST_AIFF_PARSE (parent);
1677 gboolean res = FALSE;
1679 GST_DEBUG_OBJECT (aiffparse, "%s event", GST_EVENT_TYPE_NAME (event));
1681 switch (GST_EVENT_TYPE (event)) {
1682 case GST_EVENT_SEEK:
1683 /* can only handle events when we are in the data state */
1684 if (aiffparse->state == AIFF_PARSE_DATA) {
1685 res = gst_aiff_parse_perform_seek (aiffparse, event, FALSE);
1687 gst_event_unref (event);
1690 res = gst_pad_push_event (aiffparse->sinkpad, event);
1697 gst_aiff_parse_sink_activate (GstPad * sinkpad, GstObject * parent)
1702 query = gst_query_new_scheduling ();
1704 if (!gst_pad_peer_query (sinkpad, query)) {
1705 gst_query_unref (query);
1709 pull_mode = gst_query_has_scheduling_mode_with_flags (query,
1710 GST_PAD_MODE_PULL, GST_SCHEDULING_FLAG_SEEKABLE);
1711 gst_query_unref (query);
1716 GST_DEBUG_OBJECT (sinkpad, "going to pull mode");
1717 return gst_pad_activate_mode (sinkpad, GST_PAD_MODE_PULL, TRUE);
1721 GST_DEBUG_OBJECT (sinkpad, "going to push (streaming) mode");
1722 return gst_pad_activate_mode (sinkpad, GST_PAD_MODE_PUSH, TRUE);
1728 gst_aiff_parse_sink_activate_mode (GstPad * sinkpad, GstObject * parent,
1729 GstPadMode mode, gboolean active)
1732 GstAiffParse *aiff = GST_AIFF_PARSE (parent);
1734 if (aiff->adapter) {
1735 g_object_unref (aiff->adapter);
1736 aiff->adapter = NULL;
1740 case GST_PAD_MODE_PUSH:
1742 aiff->streaming = TRUE;
1743 aiff->adapter = gst_adapter_new ();
1747 case GST_PAD_MODE_PULL:
1749 aiff->streaming = FALSE;
1750 aiff->adapter = NULL;
1751 aiff->segment_running = TRUE;
1753 gst_pad_start_task (sinkpad, (GstTaskFunction) gst_aiff_parse_loop,
1756 aiff->segment_running = FALSE;
1757 res = gst_pad_stop_task (sinkpad);
1767 static GstFlowReturn
1768 gst_aiff_parse_flush_data (GstAiffParse * aiff)
1770 GstFlowReturn ret = GST_FLOW_OK;
1773 if ((av = gst_adapter_available (aiff->adapter)) > 0) {
1774 aiff->dataleft = av;
1775 aiff->end_offset = aiff->offset + av;
1776 ret = gst_aiff_parse_stream_data (aiff);
1784 gst_aiff_parse_sink_event (GstPad * pad, GstObject * parent, GstEvent * event)
1786 GstAiffParse *aiff = GST_AIFF_PARSE (parent);
1787 gboolean ret = TRUE;
1789 GST_DEBUG_OBJECT (aiff, "handling %s event", GST_EVENT_TYPE_NAME (event));
1791 switch (GST_EVENT_TYPE (event)) {
1792 case GST_EVENT_CAPS:
1794 /* discard, we'll come up with proper src caps */
1795 gst_event_unref (event);
1798 case GST_EVENT_SEGMENT:
1800 gint64 start, stop, offset = 0, end_offset = -1;
1803 /* some debug output */
1804 gst_event_copy_segment (event, &segment);
1805 GST_DEBUG_OBJECT (aiff, "received segment %" GST_SEGMENT_FORMAT,
1808 /* now we are either committed to TIME or BYTE format,
1809 * and we only expect a BYTE segment, e.g. following a seek */
1810 if (segment.format == GST_FORMAT_BYTES) {
1811 /* handle (un)signed issues */
1812 start = segment.start;
1813 stop = segment.stop;
1816 start -= aiff->datastart;
1817 start = MAX (start, 0);
1821 segment.stop -= aiff->datastart;
1822 segment.stop = MAX (stop, 0);
1824 if (aiff->state == AIFF_PARSE_DATA &&
1825 aiff->segment.format == GST_FORMAT_TIME) {
1826 guint64 bps = aiff->bps;
1828 /* operating in format TIME, so we can convert */
1832 gst_util_uint64_scale_ceil (start, GST_SECOND,
1833 (guint64) aiff->bps);
1836 gst_util_uint64_scale_ceil (stop, GST_SECOND,
1837 (guint64) aiff->bps);
1839 GST_DEBUG_OBJECT (aiff, "unable to compute segment start/stop");
1844 GST_DEBUG_OBJECT (aiff, "unsupported segment format, ignoring");
1848 segment.start = start;
1849 segment.stop = stop;
1851 /* accept upstream's notion of segment and distribute along */
1852 if (aiff->state == AIFF_PARSE_DATA) {
1853 segment.format = aiff->segment.format;
1854 segment.time = segment.position = segment.start;
1855 segment.duration = aiff->segment.duration;
1858 gst_segment_copy_into (&segment, &aiff->segment);
1860 if (aiff->start_segment)
1861 gst_event_unref (aiff->start_segment);
1863 aiff->start_segment = gst_event_new_segment (&segment);
1865 /* stream leftover data in current segment */
1866 if (aiff->state == AIFF_PARSE_DATA)
1867 gst_aiff_parse_flush_data (aiff);
1868 /* and set up streaming thread for next one */
1869 aiff->offset = offset;
1870 aiff->end_offset = end_offset;
1871 if (aiff->end_offset > 0) {
1872 aiff->dataleft = aiff->end_offset - aiff->offset;
1874 /* infinity; upstream will EOS when done */
1875 aiff->dataleft = G_MAXUINT64;
1878 gst_event_unref (event);
1881 case GST_EVENT_FLUSH_START:
1882 ret = gst_pad_push_event (aiff->srcpad, event);
1884 case GST_EVENT_FLUSH_STOP:
1885 ret = gst_pad_push_event (aiff->srcpad, event);
1886 gst_adapter_clear (aiff->adapter);
1889 ret = gst_pad_event_default (aiff->sinkpad, parent, event);
1896 static GstStateChangeReturn
1897 gst_aiff_parse_change_state (GstElement * element, GstStateChange transition)
1899 GstStateChangeReturn ret;
1900 GstAiffParse *aiff = GST_AIFF_PARSE (element);
1902 switch (transition) {
1903 case GST_STATE_CHANGE_NULL_TO_READY:
1905 case GST_STATE_CHANGE_READY_TO_PAUSED:
1906 gst_aiff_parse_reset (aiff);
1908 case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
1914 ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
1916 switch (transition) {
1917 case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
1919 case GST_STATE_CHANGE_PAUSED_TO_READY:
1920 gst_aiff_parse_reset (aiff);
1922 case GST_STATE_CHANGE_READY_TO_NULL: