gst: remove unnecessary GLIB_DISABLE_DEPRECATION_WARNINGS
[platform/upstream/gstreamer.git] / gst / aiff / aiffparse.c
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  *
27  * <refsect2>
28  * <para>
29  * Parse a .aiff file into raw or compressed audio.
30  * </para>
31  * <para>
32  * The aiffparse element supports both push and pull mode operations, making it
33  * possible to stream from a network source.
34  * </para>
35  * <title>Example launch line</title>
36  * <para>
37  * <programlisting>
38  * gst-launch filesrc location=sine.aiff ! aiffparse ! audioconvert ! alsasink
39  * </programlisting>
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.
42  * </para>
43  * <para>
44  * <programlisting>
45  * gst-launch souphhtpsrc location=http://www.example.org/sine.aiff ! queue ! aiffparse ! audioconvert ! alsasink
46  * </programlisting>
47  * Stream data from a network url.
48  * </para>
49  * </refsect2>
50  */
51
52 #ifdef HAVE_CONFIG_H
53 #include "config.h"
54 #endif
55
56 #include <string.h>
57 #include <math.h>
58
59 #include "aiffparse.h"
60 #include <gst/audio/audio.h>
61 #include <gst/tag/tag.h>
62 #include <gst/gst-i18n-plugin.h>
63
64 GST_DEBUG_CATEGORY (aiffparse_debug);
65 #define GST_CAT_DEFAULT (aiffparse_debug)
66
67 static void gst_aiff_parse_dispose (GObject * object);
68
69 static gboolean gst_aiff_parse_sink_activate (GstPad * sinkpad,
70     GstObject * parent);
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,
74     GstEvent * buf);
75 static gboolean gst_aiff_parse_send_event (GstElement * element,
76     GstEvent * event);
77 static GstStateChangeReturn gst_aiff_parse_change_state (GstElement * element,
78     GstStateChange transition);
79
80 static gboolean gst_aiff_parse_pad_query (GstPad * pad, GstObject * parent,
81     GstQuery * query);
82 static gboolean gst_aiff_parse_pad_convert (GstPad * pad,
83     GstFormat src_format,
84     gint64 src_value, GstFormat * dest_format, gint64 * dest_value);
85
86 static GstFlowReturn gst_aiff_parse_chain (GstPad * pad, GstObject * parent,
87     GstBuffer * buf);
88 static void gst_aiff_parse_loop (GstPad * pad);
89 static gboolean gst_aiff_parse_srcpad_event (GstPad * pad, GstObject * parent,
90     GstEvent * event);
91
92 static GstStaticPadTemplate sink_template_factory =
93 GST_STATIC_PAD_TEMPLATE ("sink",
94     GST_PAD_SINK,
95     GST_PAD_ALWAYS,
96     GST_STATIC_CAPS ("audio/x-aiff")
97     );
98
99 static GstStaticPadTemplate src_template_factory =
100 GST_STATIC_PAD_TEMPLATE ("src",
101     GST_PAD_SRC,
102     GST_PAD_ALWAYS,
103     GST_STATIC_CAPS (GST_AUDIO_CAPS_MAKE ("{ S8, S16BE, S16LE, S24BE, S24LE, "
104             "S32LE, S32BE, F32BE, F64BE }"))
105     );
106
107 #define MAX_BUFFER_SIZE 4096
108
109 #define gst_aiff_parse_parent_class parent_class
110 G_DEFINE_TYPE (GstAiffParse, gst_aiff_parse, GST_TYPE_ELEMENT);
111
112 static void
113 gst_aiff_parse_class_init (GstAiffParseClass * klass)
114 {
115   GstElementClass *gstelement_class;
116   GObjectClass *object_class;
117
118   gstelement_class = (GstElementClass *) klass;
119   object_class = (GObjectClass *) klass;
120
121   object_class->dispose = gst_aiff_parse_dispose;
122
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));
127
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>");
132
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);
136 }
137
138 static void
139 gst_aiff_parse_reset (GstAiffParse * aiff)
140 {
141   aiff->state = AIFF_PARSE_START;
142
143   /* These will all be set correctly in the fmt chunk */
144   aiff->rate = 0;
145   aiff->width = 0;
146   aiff->depth = 0;
147   aiff->channels = 0;
148   aiff->bps = 0;
149   aiff->offset = 0;
150   aiff->end_offset = 0;
151   aiff->dataleft = 0;
152   aiff->datasize = 0;
153   aiff->datastart = 0;
154   aiff->duration = 0;
155   aiff->got_comm = FALSE;
156
157   if (aiff->seek_event)
158     gst_event_unref (aiff->seek_event);
159   aiff->seek_event = NULL;
160   if (aiff->adapter) {
161     gst_adapter_clear (aiff->adapter);
162     aiff->adapter = NULL;
163   }
164
165   if (aiff->tags != NULL) {
166     gst_tag_list_unref (aiff->tags);
167     aiff->tags = NULL;
168   }
169 }
170
171 static void
172 gst_aiff_parse_dispose (GObject * object)
173 {
174   GstAiffParse *aiff = GST_AIFF_PARSE (object);
175
176   GST_DEBUG_OBJECT (aiff, "AIFF: Dispose");
177   gst_aiff_parse_reset (aiff);
178
179   G_OBJECT_CLASS (parent_class)->dispose (object);
180 }
181
182 static void
183 gst_aiff_parse_init (GstAiffParse * aiffparse)
184 {
185   gst_aiff_parse_reset (aiffparse);
186
187   /* sink */
188   aiffparse->sinkpad =
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);
199
200   /* source */
201   aiffparse->srcpad =
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);
209 }
210
211 static gboolean
212 gst_aiff_parse_parse_file_header (GstAiffParse * aiff, GstBuffer * buf)
213 {
214   guint32 header, type = 0;
215   GstMapInfo info;
216
217   if (!gst_buffer_map (buf, &info, GST_MAP_READ)) {
218     GST_WARNING_OBJECT (aiff, "Could not map buffer");
219     goto not_aiff;
220   }
221
222   if (info.size < 12) {
223     GST_WARNING_OBJECT (aiff, "Buffer too short");
224     gst_buffer_unmap (buf, &info);
225     goto not_aiff;
226   }
227
228   header = GST_READ_UINT32_LE (info.data);
229   type = GST_READ_UINT32_LE (info.data + 8);
230   gst_buffer_unmap (buf, &info);
231
232   if (header != GST_MAKE_FOURCC ('F', 'O', 'R', 'M'))
233     goto not_aiff;
234
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;
239   else
240     goto not_aiff;
241
242   gst_buffer_unref (buf);
243   return TRUE;
244
245   /* ERRORS */
246 not_aiff:
247   {
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);
251     return FALSE;
252   }
253 }
254
255 static GstFlowReturn
256 gst_aiff_parse_stream_init (GstAiffParse * aiff)
257 {
258   GstFlowReturn res;
259   GstBuffer *buf = NULL;
260
261   if ((res = gst_pad_pull_range (aiff->sinkpad,
262               aiff->offset, 12, &buf)) != GST_FLOW_OK)
263     return res;
264   else if (!gst_aiff_parse_parse_file_header (aiff, buf))
265     return GST_FLOW_ERROR;
266
267   aiff->offset += 12;
268
269   return GST_FLOW_OK;
270 }
271
272 static gboolean
273 gst_aiff_parse_time_to_bytepos (GstAiffParse * aiff, gint64 ts,
274     gint64 * bytepos)
275 {
276   /* -1 always maps to -1 */
277   if (ts == -1) {
278     *bytepos = -1;
279     return TRUE;
280   }
281
282   /* 0 always maps to 0 */
283   if (ts == 0) {
284     *bytepos = 0;
285     return TRUE;
286   }
287
288   if (aiff->bps > 0) {
289     *bytepos = gst_util_uint64_scale_ceil (ts, (guint64) aiff->bps, GST_SECOND);
290     return TRUE;
291   }
292
293   GST_WARNING_OBJECT (aiff, "No valid bps to convert position");
294
295   return FALSE;
296 }
297
298 /* This function is used to perform seeks on the element in
299  * pull mode.
300  *
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
304  * READY.
305  */
306 static gboolean
307 gst_aiff_parse_perform_seek (GstAiffParse * aiff, GstEvent * event,
308     gboolean starting)
309 {
310   gboolean res;
311   gdouble rate;
312   GstFormat format;
313   GstSeekFlags flags;
314   GstSeekType start_type = GST_SEEK_TYPE_NONE, stop_type;
315   gint64 start, stop, upstream_size;
316   gboolean flush;
317   gboolean update;
318   GstSegment seeksegment = { 0, };
319   gint64 position;
320
321   if (event) {
322     GST_DEBUG_OBJECT (aiff, "doing seek with event");
323
324     gst_event_parse_seek (event, &rate, &format, &flags,
325         &start_type, &start, &stop_type, &stop);
326
327     /* no negative rates yet */
328     if (rate < 0.0)
329       goto negative_rate;
330
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));
335       res = TRUE;
336       if (start_type != GST_SEEK_TYPE_NONE)
337         res =
338             gst_pad_query_convert (aiff->srcpad, format, start,
339             aiff->segment.format, &start);
340       if (res && stop_type != GST_SEEK_TYPE_NONE)
341         res =
342             gst_pad_query_convert (aiff->srcpad, format, stop,
343             aiff->segment.format, &stop);
344       if (!res)
345         goto no_format;
346
347       format = aiff->segment.format;
348     }
349   } else {
350     GST_DEBUG_OBJECT (aiff, "doing seek without event");
351     flags = 0;
352     rate = 1.0;
353     start = 0;
354     start_type = GST_SEEK_TYPE_SET;
355     stop = -1;
356     stop_type = GST_SEEK_TYPE_SET;
357   }
358
359   /* get flush flag */
360   flush = flags & GST_SEEK_FLAG_FLUSH;
361
362   if (aiff->streaming && !starting) {
363     GstEvent *new_event;
364
365     /* streaming seek */
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
369        * bytes. */
370       if (aiff->bps > 0)
371         start =
372             gst_util_uint64_scale_ceil (start, (guint64) aiff->bps, GST_SECOND);
373       start -= (start % aiff->bytes_per_sample);
374       start += aiff->datastart;
375     }
376
377     if (stop_type != GST_SEEK_TYPE_NONE) {
378       if (aiff->bps > 0)
379         stop =
380             gst_util_uint64_scale_ceil (stop, (guint64) aiff->bps, GST_SECOND);
381       stop -= (stop % aiff->bytes_per_sample);
382       stop += aiff->datastart;
383     }
384
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,
388             &upstream_size))
389       stop = MIN (stop, upstream_size);
390
391     if (stop >= 0 && stop <= start)
392       stop = start;
393
394     new_event = gst_event_new_seek (rate, GST_FORMAT_BYTES, flags,
395         start_type, start, stop_type, stop);
396
397     res = gst_pad_push_event (aiff->sinkpad, new_event);
398   } else {
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). */
405     if (flush) {
406       GST_DEBUG_OBJECT (aiff, "sending flush start");
407       gst_pad_push_event (aiff->srcpad, gst_event_new_flush_start ());
408     } else {
409       gst_pad_pause_task (aiff->sinkpad);
410     }
411
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);
415
416     /* save current position */
417     position = aiff->segment.position;
418
419     GST_DEBUG_OBJECT (aiff, "stopped streaming at %" G_GINT64_FORMAT, position);
420
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));
424
425     /* configure the seek parameters in the seeksegment. We will then have the
426      * right values in the segment to perform the seek */
427     if (event) {
428       GST_DEBUG_OBJECT (aiff, "configuring seek");
429       gst_segment_do_seek (&seeksegment, rate, format, flags,
430           start_type, start, stop_type, stop, &update);
431     }
432
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;
437
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
442        * bytes. */
443       if (aiff->bps > 0)
444         aiff->offset =
445             gst_util_uint64_scale_ceil (seeksegment.position,
446             (guint64) aiff->bps, GST_SECOND);
447       else
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);
454     } else {
455       GST_LOG_OBJECT (aiff, "continue from offset=%" G_GUINT64_FORMAT,
456           aiff->offset);
457     }
458
459     if (stop_type != GST_SEEK_TYPE_NONE) {
460       if (aiff->bps > 0)
461         aiff->end_offset =
462             gst_util_uint64_scale_ceil (stop, (guint64) aiff->bps, GST_SECOND);
463       else
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);
470     } else {
471       GST_LOG_OBJECT (aiff, "continue to end_offset=%" G_GUINT64_FORMAT,
472           aiff->end_offset);
473     }
474
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,
478             &upstream_size))
479       aiff->end_offset = MIN (aiff->end_offset, upstream_size);
480
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;
484
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));
490
491     /* prepare for streaming again */
492     if (flush) {
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));
496     }
497
498     /* now we did the seek and can activate the new segment values */
499     memcpy (&aiff->segment, &seeksegment, sizeof (GstSegment));
500
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));
506     }
507
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);
511
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);
516
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;
522     }
523
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);
529     }
530
531     GST_PAD_STREAM_UNLOCK (aiff->sinkpad);
532
533     res = TRUE;
534   }
535
536   return res;
537
538   /* ERRORS */
539 negative_rate:
540   {
541     GST_DEBUG_OBJECT (aiff, "negative playback rates are not supported yet.");
542     return FALSE;
543   }
544 no_format:
545   {
546     GST_DEBUG_OBJECT (aiff, "unsupported format given, seek aborted.");
547     return FALSE;
548   }
549 }
550
551 /*
552  * gst_aiff_parse_peek_chunk_info:
553  * @aiff AIFFparse object
554  * @tag holder for tag
555  * @size holder for tag size
556  *
557  * Peek next chunk info (tag and size)
558  *
559  * Returns: %TRUE when the chunk info (header) is available
560  */
561 static gboolean
562 gst_aiff_parse_peek_chunk_info (GstAiffParse * aiff, guint32 * tag,
563     guint32 * size)
564 {
565   const guint8 *data = NULL;
566
567   if (gst_adapter_available (aiff->adapter) < 8)
568     return FALSE;
569
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);
574
575   GST_DEBUG_OBJECT (aiff,
576       "Next chunk size is %d bytes, type %" GST_FOURCC_FORMAT, *size,
577       GST_FOURCC_ARGS (*tag));
578
579   return TRUE;
580 }
581
582 /*
583  * gst_aiff_parse_peek_chunk:
584  * @aiff AIFFparse object
585  * @tag holder for tag
586  * @size holder for tag size
587  *
588  * Peek enough data for one full chunk
589  *
590  * Returns: %TRUE when the full chunk is available
591  */
592 static gboolean
593 gst_aiff_parse_peek_chunk (GstAiffParse * aiff, guint32 * tag, guint32 * size)
594 {
595   guint32 peek_size = 0;
596   guint available;
597
598   if (!gst_aiff_parse_peek_chunk_info (aiff, tag, size))
599     return FALSE;
600
601   GST_DEBUG_OBJECT (aiff, "Need to peek chunk of %d bytes", *size);
602   peek_size = (*size + 1) & ~1;
603
604   available = gst_adapter_available (aiff->adapter);
605   if (available >= (8 + peek_size)) {
606     return TRUE;
607   } else {
608     GST_LOG_OBJECT (aiff, "but only %u bytes available now", available);
609     return FALSE;
610   }
611 }
612
613 static gboolean
614 gst_aiff_parse_peek_data (GstAiffParse * aiff, guint32 size,
615     const guint8 ** data)
616 {
617   if (gst_adapter_available (aiff->adapter) < size)
618     return FALSE;
619
620   *data = gst_adapter_map (aiff->adapter, size);
621   return TRUE;
622 }
623
624 /*
625  * gst_aiff_parse_calculate_duration:
626  * @aiff: aiffparse object
627  *
628  * Calculate duration on demand and store in @aiff.
629  *
630  * Returns: %TRUE if duration is available.
631  */
632 static gboolean
633 gst_aiff_parse_calculate_duration (GstAiffParse * aiff)
634 {
635   if (aiff->duration > 0)
636     return TRUE;
637
638   if (aiff->datasize > 0 && aiff->bps > 0) {
639     aiff->duration =
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));
644     return TRUE;
645   }
646   return FALSE;
647 }
648
649 static void
650 gst_aiff_parse_ignore_chunk (GstAiffParse * aiff, guint32 tag, guint32 size)
651 {
652   guint flush;
653
654   if (aiff->streaming) {
655     if (!gst_aiff_parse_peek_chunk (aiff, &tag, &size))
656       return;
657   }
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);
664   }
665 }
666
667 static double
668 gst_aiff_parse_read_IEEE80 (guint8 * buf)
669 {
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);
674
675   if (e == 32767) {
676     if (buf[2] & 0x80)
677       return HUGE_VAL;          /* Really NaN, but this won't happen in reality */
678     else {
679       if (s)
680         return -HUGE_VAL;
681       else
682         return HUGE_VAL;
683     }
684   }
685
686   f = ldexp (f, 32);
687   f += ((buf[6] & 0xff) << 24) |
688       ((buf[7] & 0xff) << 16) | ((buf[8] & 0xff) << 8) | (buf[9] & 0xff);
689
690   return ldexp (f, e - 16446);
691 }
692
693 static gboolean
694 gst_aiff_parse_parse_comm (GstAiffParse * aiff, GstBuffer * buf)
695 {
696   int size;
697   GstMapInfo info;
698   guint32 fourcc;
699
700   if (!gst_buffer_map (buf, &info, GST_MAP_READ)) {
701     GST_WARNING_OBJECT (aiff, "Can't map buffer");
702     gst_buffer_unref (buf);
703     return FALSE;
704   }
705
706   if (aiff->is_aifc)
707     size = 22;
708   else
709     size = 18;
710
711   if (info.size < size)
712     goto too_small;
713
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);
719
720   aiff->floating_point = FALSE;
721
722   if (aiff->is_aifc) {
723     fourcc = GST_READ_UINT32_LE (info.data + 18);
724
725     /* We only support the 'trivial' uncompressed AIFC, but it can be
726      * either big or little endian */
727     switch (fourcc) {
728       case GST_MAKE_FOURCC ('N', 'O', 'N', 'E'):
729         aiff->endianness = G_BIG_ENDIAN;
730         break;
731       case GST_MAKE_FOURCC ('s', 'o', 'w', 't'):
732         aiff->endianness = G_LITTLE_ENDIAN;
733         break;
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;
739         break;
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;
744         break;
745       default:
746         goto unknown_compression;
747     }
748   } else
749     aiff->endianness = G_BIG_ENDIAN;
750
751   gst_buffer_unmap (buf, &info);
752   gst_buffer_unref (buf);
753
754   return TRUE;
755
756   /* ERRORS */
757 too_small:
758   {
759     GST_WARNING_OBJECT (aiff, "COMM chunk too short, cannot parse header");
760     gst_buffer_unmap (buf, &info);
761     gst_buffer_unref (buf);
762     return FALSE;
763   }
764 unknown_compression:
765   {
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);
770     return FALSE;
771   }
772 }
773
774 static GstFlowReturn
775 gst_aiff_parse_read_chunk (GstAiffParse * aiff, guint64 * offset, guint32 * tag,
776     GstBuffer ** data)
777 {
778   guint size;
779   GstFlowReturn res;
780   GstBuffer *buf = NULL;
781   GstMapInfo info;
782
783   if ((res =
784           gst_pad_pull_range (aiff->sinkpad, *offset, 8, &buf)) != GST_FLOW_OK)
785     return res;
786
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);
792   buf = NULL;
793
794   if ((res =
795           gst_pad_pull_range (aiff->sinkpad, (*offset) + 8, size,
796               &buf)) != GST_FLOW_OK)
797     return res;
798   else if (gst_buffer_get_size (buf) < size)
799     goto too_small;
800
801   *data = buf;
802   *offset += 8 + GST_ROUND_UP_2 (size);
803
804   return GST_FLOW_OK;
805
806   /* ERRORS */
807 too_small:
808   {
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);
814     return GST_FLOW_EOS;
815   }
816
817 }
818
819 static GstCaps *
820 gst_aiff_parse_create_caps (GstAiffParse * aiff)
821 {
822   GstCaps *caps = NULL;
823   const gchar *format = NULL;
824
825   if (aiff->floating_point) {
826     if (aiff->endianness == G_BIG_ENDIAN) {
827       if (aiff->width == 32)
828         format = "F32BE";
829       else if (aiff->width == 64)
830         format = "F64BE";
831     }
832   } else {
833     if (aiff->endianness == G_BIG_ENDIAN) {
834       if (aiff->width == 8)
835         format = "S8";
836       else if (aiff->width == 16)
837         format = "S16BE";
838       else if (aiff->width == 24)
839         format = "S24BE";
840       else if (aiff->width == 32)
841         format = "S32BE";
842     } else {
843       if (aiff->width == 8)
844         format = "S8";
845       else if (aiff->width == 16)
846         format = "S16LE";
847       else if (aiff->width == 24)
848         format = "S24LE";
849       else if (aiff->width == 32)
850         format = "S32LE";
851     }
852   }
853   if (format) {
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);
859   }
860
861   GST_DEBUG_OBJECT (aiff, "Created caps: %" GST_PTR_FORMAT, caps);
862
863   return caps;
864 }
865
866 static GstFlowReturn
867 gst_aiff_parse_stream_headers (GstAiffParse * aiff)
868 {
869   GstFlowReturn res;
870   GstBuffer *buf = NULL;
871   guint32 tag, size;
872   gboolean gotdata = FALSE;
873   gboolean done = FALSE;
874   GstEvent **event_p;
875   gint64 upstream_size = 0;
876
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);
879
880   /* loop headers until we get data */
881   while (!done) {
882     if (aiff->streaming) {
883       if (!gst_aiff_parse_peek_chunk_info (aiff, &tag, &size))
884         return GST_FLOW_OK;
885     } else {
886       GstMapInfo info;
887
888       if ((res =
889               gst_pad_pull_range (aiff->sinkpad, aiff->offset, 8,
890                   &buf)) != GST_FLOW_OK)
891         goto header_read_error;
892
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);
898       buf = NULL;
899     }
900
901     GST_INFO_OBJECT (aiff,
902         "Got TAG: %" GST_FOURCC_FORMAT ", offset %" G_GUINT64_FORMAT,
903         GST_FOURCC_ARGS (tag), aiff->offset);
904
905     /* We just keep reading chunks until we find the one we're interested in.
906      */
907     switch (tag) {
908       case GST_MAKE_FOURCC ('C', 'O', 'M', 'M'):{
909         GstCaps *caps;
910         GstEvent *event;
911         gchar *stream_id;
912
913         if (aiff->streaming) {
914           if (!gst_aiff_parse_peek_chunk (aiff, &tag, &size))
915             return GST_FLOW_OK;
916
917           gst_adapter_flush (aiff->adapter, 8);
918           aiff->offset += 8;
919
920           buf = gst_adapter_take_buffer (aiff->adapter, size);
921           aiff->offset += size;
922         } else {
923           if ((res = gst_aiff_parse_read_chunk (aiff,
924                       &aiff->offset, &tag, &buf)) != GST_FLOW_OK)
925             return res;
926         }
927
928         if (!gst_aiff_parse_parse_comm (aiff, buf))
929           goto parse_header_error;
930
931         /* do sanity checks of header fields */
932         if (aiff->channels == 0)
933           goto no_channels;
934         if (aiff->rate == 0)
935           goto no_rate;
936
937         stream_id =
938             gst_pad_create_stream_id (aiff->srcpad, GST_ELEMENT_CAST (aiff),
939             NULL);
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);
943         g_free (stream_id);
944
945         GST_DEBUG_OBJECT (aiff, "creating the caps");
946
947         caps = gst_aiff_parse_create_caps (aiff);
948         if (caps == NULL)
949           goto unknown_format;
950
951         gst_pad_push_event (aiff->srcpad, gst_event_new_caps (caps));
952         gst_caps_unref (caps);
953
954         aiff->bytes_per_sample = aiff->channels * aiff->width / 8;
955         aiff->bps = aiff->bytes_per_sample * aiff->rate;
956
957         if (aiff->bytes_per_sample <= 0)
958           goto no_bytes_per_sample;
959
960         aiff->got_comm = TRUE;
961         break;
962       }
963       case GST_MAKE_FOURCC ('S', 'S', 'N', 'D'):{
964         guint32 datasize;
965
966         GST_DEBUG_OBJECT (aiff, "Got 'SSND' TAG, size : %d", size);
967
968         /* Now, read the 8-byte header in the SSND chunk */
969         if (aiff->streaming) {
970           const guint8 *ssnddata = NULL;
971
972           if (!gst_aiff_parse_peek_data (aiff, 16, &ssnddata))
973             return GST_FLOW_OK;
974
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);
979         } else {
980           GstBuffer *ssndbuf = NULL;
981           GstMapInfo info;
982
983           if ((res =
984                   gst_pad_pull_range (aiff->sinkpad, aiff->offset, 16,
985                       &ssndbuf)) != GST_FLOW_OK)
986             goto header_read_error;
987
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);
993         }
994
995         gotdata = TRUE;
996
997         /* 8 byte chunk header, 8 byte SSND header */
998         aiff->offset += 16;
999         datasize = size - 8;
1000
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));
1005         }
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,
1011            * etc. */
1012           aiff->offset += datasize;
1013         }
1014         GST_DEBUG_OBJECT (aiff, "datasize = %d", datasize);
1015         if (aiff->streaming) {
1016           done = TRUE;
1017         }
1018         break;
1019       }
1020       case GST_MAKE_FOURCC ('I', 'D', '3', ' '):{
1021         GstTagList *tags;
1022
1023         if (aiff->streaming) {
1024           if (!gst_aiff_parse_peek_chunk (aiff, &tag, &size))
1025             return GST_FLOW_OK;
1026
1027           gst_adapter_flush (aiff->adapter, 8);
1028           aiff->offset += 8;
1029
1030           buf = gst_adapter_take_buffer (aiff->adapter, size);
1031         } else {
1032           if ((res = gst_aiff_parse_read_chunk (aiff,
1033                       &aiff->offset, &tag, &buf)) != GST_FLOW_OK)
1034             return res;
1035         }
1036
1037         GST_LOG_OBJECT (aiff, "ID3 chunk of size %" G_GSIZE_FORMAT,
1038             gst_buffer_get_size (buf));
1039
1040         tags = gst_tag_list_from_id3v2_tag (buf);
1041         gst_buffer_unref (buf);
1042
1043         GST_INFO_OBJECT (aiff, "ID3 tags: %" GST_PTR_FORMAT, tags);
1044
1045         if (aiff->tags == NULL) {
1046           aiff->tags = tags;
1047         } else {
1048           gst_tag_list_insert (aiff->tags, tags, GST_TAG_MERGE_APPEND);
1049           gst_tag_list_unref (tags);
1050         }
1051         break;
1052       }
1053       default:
1054         gst_aiff_parse_ignore_chunk (aiff, tag, size);
1055     }
1056
1057     buf = NULL;
1058
1059     if (upstream_size && (aiff->offset >= upstream_size)) {
1060       /* Now we have gone through the whole file */
1061       done = TRUE;
1062     }
1063   }
1064
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 
1067    * otherwise.
1068    */
1069   if (!aiff->got_comm) {
1070     GST_WARNING_OBJECT (aiff, "Failed to find COMM chunk");
1071     goto no_header;
1072   }
1073   if (!gotdata) {
1074     GST_WARNING_OBJECT (aiff, "Failed to find SSND chunk");
1075     goto no_data;
1076   }
1077
1078   GST_DEBUG_OBJECT (aiff, "Finished parsing headers");
1079
1080   if (gst_aiff_parse_calculate_duration (aiff)) {
1081     gst_segment_init (&aiff->segment, GST_FORMAT_TIME);
1082     aiff->segment.duration = aiff->duration;
1083   } else {
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;
1087   }
1088
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);
1096
1097   /* we just started, we are discont */
1098   aiff->discont = TRUE;
1099
1100   aiff->state = AIFF_PARSE_DATA;
1101
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 */
1105   /* var abuse */
1106   upstream_size = 0;
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);
1112
1113   GST_DEBUG_OBJECT (aiff, "max buffer size %u", aiff->max_buf_size);
1114
1115   return GST_FLOW_OK;
1116
1117   /* ERROR */
1118 no_header:
1119   {
1120     GST_ELEMENT_ERROR (aiff, STREAM, TYPE_NOT_FOUND, (NULL),
1121         ("Invalid AIFF header (no COMM found)"));
1122     return GST_FLOW_ERROR;
1123   }
1124 no_data:
1125   {
1126     GST_ELEMENT_ERROR (aiff, STREAM, TYPE_NOT_FOUND, (NULL),
1127         ("Invalid AIFF: no SSND found"));
1128     return GST_FLOW_ERROR;
1129   }
1130 parse_header_error:
1131   {
1132     GST_ELEMENT_ERROR (aiff, STREAM, DEMUX, (NULL),
1133         ("Couldn't parse audio header"));
1134     return GST_FLOW_ERROR;
1135   }
1136 no_channels:
1137   {
1138     GST_ELEMENT_ERROR (aiff, STREAM, FAILED, (NULL),
1139         ("Stream claims to contain no channels - invalid data"));
1140     return GST_FLOW_ERROR;
1141   }
1142 no_rate:
1143   {
1144     GST_ELEMENT_ERROR (aiff, STREAM, FAILED, (NULL),
1145         ("Stream with sample_rate == 0 - invalid data"));
1146     return GST_FLOW_ERROR;
1147   }
1148 no_bytes_per_sample:
1149   {
1150     GST_ELEMENT_ERROR (aiff, STREAM, FAILED, (NULL),
1151         ("Could not calculate bytes per sample - invalid data"));
1152     return GST_FLOW_ERROR;
1153   }
1154 unknown_format:
1155   {
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;
1160   }
1161 header_read_error:
1162   {
1163     GST_ELEMENT_ERROR (aiff, STREAM, DEMUX, (NULL),
1164         ("Couldn't read in header"));
1165     return GST_FLOW_ERROR;
1166   }
1167 }
1168
1169 /*
1170  * Read AIFF file tag when streaming
1171  */
1172 static GstFlowReturn
1173 gst_aiff_parse_parse_stream_init (GstAiffParse * aiff)
1174 {
1175   if (gst_adapter_available (aiff->adapter) >= 12) {
1176     GstBuffer *tmp;
1177
1178     /* _take flushes the data */
1179     tmp = gst_adapter_take_buffer (aiff->adapter, 12);
1180
1181     GST_DEBUG_OBJECT (aiff, "Parsing aiff header");
1182     if (!gst_aiff_parse_parse_file_header (aiff, tmp))
1183       return GST_FLOW_ERROR;
1184
1185     aiff->offset += 12;
1186     /* Go to next state */
1187     aiff->state = AIFF_PARSE_HEADER;
1188   }
1189   return GST_FLOW_OK;
1190 }
1191
1192 /* handle an event sent directly to the element.
1193  *
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
1196  * event.
1197  *
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.
1201  *
1202  * When we are steaming, we can simply perform the seek right
1203  * away.
1204  */
1205 static gboolean
1206 gst_aiff_parse_send_event (GstElement * element, GstEvent * event)
1207 {
1208   GstAiffParse *aiff = GST_AIFF_PARSE (element);
1209   gboolean res = FALSE;
1210   GstEvent **event_p;
1211
1212   GST_DEBUG_OBJECT (aiff, "received event %s", GST_EVENT_TYPE_NAME (event));
1213
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);
1219       } else {
1220         GST_DEBUG_OBJECT (aiff, "queuing seek for later");
1221
1222         event_p = &aiff->seek_event;
1223         gst_event_replace (event_p, event);
1224
1225         /* we always return true */
1226         res = TRUE;
1227       }
1228       break;
1229     default:
1230       break;
1231   }
1232   gst_event_unref (event);
1233   return res;
1234 }
1235
1236 static GstFlowReturn
1237 gst_aiff_parse_stream_data (GstAiffParse * aiff)
1238 {
1239   GstBuffer *buf = NULL;
1240   GstFlowReturn res = GST_FLOW_OK;
1241   guint64 desired, obtained;
1242   GstClockTime timestamp, next_timestamp, duration;
1243   guint64 pos, nextpos;
1244
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;
1249   }
1250
1251 iterate_adapter:
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);
1255
1256   /* Get the next n bytes and output them */
1257   if (aiff->dataleft == 0 || aiff->dataleft < aiff->bytes_per_sample)
1258     goto found_eos;
1259
1260   /* scale the amount of data by the segment rate so we get equal
1261    * amounts of data regardless of the playback rate */
1262   desired =
1263       MIN (gst_guint64_to_gdouble (aiff->dataleft),
1264       aiff->max_buf_size * ABS (aiff->segment.rate));
1265
1266   if (desired >= aiff->bytes_per_sample)
1267     desired -= (desired % aiff->bytes_per_sample);
1268
1269   GST_LOG_OBJECT (aiff, "Fetching %" G_GINT64_FORMAT " bytes of data "
1270       "from the sinkpad", desired);
1271
1272   if (aiff->streaming) {
1273     guint avail = gst_adapter_available (aiff->adapter);
1274
1275     if (avail < desired) {
1276       GST_LOG_OBJECT (aiff, "Got only %d bytes of data from the sinkpad",
1277           avail);
1278       return GST_FLOW_OK;
1279     }
1280
1281     buf = gst_adapter_take_buffer (aiff->adapter, desired);
1282   } else {
1283     if ((res = gst_pad_pull_range (aiff->sinkpad, aiff->offset,
1284                 desired, &buf)) != GST_FLOW_OK)
1285       goto pull_error;
1286   }
1287
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;
1292   }
1293   if (G_UNLIKELY (aiff->start_segment != NULL)) {
1294     gst_pad_push_event (aiff->srcpad, aiff->start_segment);
1295     aiff->start_segment = NULL;
1296   }
1297   if (G_UNLIKELY (aiff->tags != NULL)) {
1298     gst_pad_push_event (aiff->srcpad, gst_event_new_tag (aiff->tags));
1299     aiff->tags = NULL;
1300   }
1301
1302   obtained = gst_buffer_get_size (buf);
1303
1304   /* our positions in bytes */
1305   pos = aiff->offset - aiff->datastart;
1306   nextpos = pos + obtained;
1307
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;
1311
1312   if (aiff->bps > 0) {
1313     /* and timestamps if we have a bitrate, be careful for overflows */
1314     timestamp =
1315         gst_util_uint64_scale_ceil (pos, GST_SECOND, (guint64) aiff->bps);
1316     next_timestamp =
1317         gst_util_uint64_scale_ceil (nextpos, GST_SECOND, (guint64) aiff->bps);
1318     duration = next_timestamp - timestamp;
1319
1320     /* update current running segment position */
1321     aiff->segment.position = next_timestamp;
1322   } else {
1323     /* no bitrate, all we know is that the first sample has timestamp 0, all
1324      * other positions and durations have unknown timestamp. */
1325     if (pos == 0)
1326       timestamp = 0;
1327     else
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;
1332   }
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;
1337   }
1338
1339   GST_BUFFER_TIMESTAMP (buf) = timestamp;
1340   GST_BUFFER_DURATION (buf) = duration;
1341
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);
1346
1347   if ((res = gst_pad_push (aiff->srcpad, buf)) != GST_FLOW_OK)
1348     goto push_error;
1349
1350   if (obtained < aiff->dataleft) {
1351     aiff->offset += obtained;
1352     aiff->dataleft -= obtained;
1353   } else {
1354     aiff->offset += aiff->dataleft;
1355     aiff->dataleft = 0;
1356   }
1357
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,
1362         aiff->end_offset);
1363     goto iterate_adapter;
1364   }
1365   return res;
1366
1367   /* ERROR */
1368 found_eos:
1369   {
1370     GST_DEBUG_OBJECT (aiff, "found EOS");
1371     return GST_FLOW_EOS;
1372   }
1373 pull_error:
1374   {
1375     /* check if we got EOS */
1376     if (res == GST_FLOW_EOS)
1377       goto found_eos;
1378
1379     GST_WARNING_OBJECT (aiff,
1380         "Error getting %" G_GINT64_FORMAT " bytes from the "
1381         "sinkpad (dataleft = %" G_GINT64_FORMAT ")", desired, aiff->dataleft);
1382     return res;
1383   }
1384 push_error:
1385   {
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));
1390     return res;
1391   }
1392 }
1393
1394 static void
1395 gst_aiff_parse_loop (GstPad * pad)
1396 {
1397   GstFlowReturn ret;
1398   GstAiffParse *aiff = GST_AIFF_PARSE (GST_PAD_PARENT (pad));
1399
1400   GST_LOG_OBJECT (aiff, "process data");
1401
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)
1406         goto pause;
1407
1408       aiff->state = AIFF_PARSE_HEADER;
1409       /* fall-through */
1410
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)
1414         goto pause;
1415
1416       aiff->state = AIFF_PARSE_DATA;
1417       GST_INFO_OBJECT (aiff, "AIFF_PARSE_DATA");
1418       /* fall-through */
1419
1420     case AIFF_PARSE_DATA:
1421       if ((ret = gst_aiff_parse_stream_data (aiff)) != GST_FLOW_OK)
1422         goto pause;
1423       break;
1424     default:
1425       g_assert_not_reached ();
1426   }
1427   return;
1428
1429   /* ERRORS */
1430 pause:
1431   {
1432     const gchar *reason = gst_flow_get_name (ret);
1433
1434     GST_DEBUG_OBJECT (aiff, "pausing task, reason %s", reason);
1435     aiff->segment_running = FALSE;
1436     gst_pad_pause_task (pad);
1437
1438     if (ret == GST_FLOW_EOS) {
1439       /* perform EOS logic */
1440       if (aiff->segment.flags & GST_SEEK_FLAG_SEGMENT) {
1441         GstClockTime stop;
1442
1443         if ((stop = aiff->segment.stop) == -1)
1444           stop = aiff->segment.duration;
1445
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));
1451       } else {
1452         gst_pad_push_event (aiff->srcpad, gst_event_new_eos ());
1453       }
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 ());
1461     }
1462     return;
1463   }
1464 }
1465
1466 static GstFlowReturn
1467 gst_aiff_parse_chain (GstPad * pad, GstObject * parent, GstBuffer * buf)
1468 {
1469   GstFlowReturn ret;
1470   GstAiffParse *aiff = GST_AIFF_PARSE (parent);
1471
1472   GST_LOG_OBJECT (aiff, "adapter_push %" G_GSIZE_FORMAT " bytes",
1473       gst_buffer_get_size (buf));
1474
1475   gst_adapter_push (aiff->adapter, buf);
1476
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)
1481         goto done;
1482
1483       if (aiff->state != AIFF_PARSE_HEADER)
1484         break;
1485
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)
1490         goto done;
1491
1492       if (!aiff->got_comm || aiff->datastart == 0)
1493         break;
1494
1495       aiff->state = AIFF_PARSE_DATA;
1496       GST_INFO_OBJECT (aiff, "AIFF_PARSE_DATA");
1497
1498       /* fall-through */
1499     case AIFF_PARSE_DATA:
1500       if ((ret = gst_aiff_parse_stream_data (aiff)) != GST_FLOW_OK)
1501         goto done;
1502       break;
1503     default:
1504       g_return_val_if_reached (GST_FLOW_ERROR);
1505   }
1506 done:
1507   return ret;
1508 }
1509
1510 static gboolean
1511 gst_aiff_parse_pad_convert (GstPad * pad,
1512     GstFormat src_format, gint64 src_value,
1513     GstFormat * dest_format, gint64 * dest_value)
1514 {
1515   GstAiffParse *aiffparse;
1516   gboolean res = TRUE;
1517
1518   aiffparse = GST_AIFF_PARSE (GST_PAD_PARENT (pad));
1519
1520   if (*dest_format == src_format) {
1521     *dest_value = src_value;
1522     return TRUE;
1523   }
1524
1525   if (aiffparse->bytes_per_sample <= 0)
1526     return FALSE;
1527
1528   GST_INFO_OBJECT (aiffparse, "converting value from %s to %s",
1529       gst_format_get_name (src_format), gst_format_get_name (*dest_format));
1530
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;
1536           break;
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);
1541             break;
1542           }
1543           /* Else fallthrough */
1544         default:
1545           res = FALSE;
1546           goto done;
1547       }
1548       break;
1549
1550     case GST_FORMAT_DEFAULT:
1551       switch (*dest_format) {
1552         case GST_FORMAT_BYTES:
1553           *dest_value = src_value * aiffparse->bytes_per_sample;
1554           break;
1555         case GST_FORMAT_TIME:
1556           *dest_value = gst_util_uint64_scale (src_value, GST_SECOND,
1557               (guint64) aiffparse->rate);
1558           break;
1559         default:
1560           res = FALSE;
1561           goto done;
1562       }
1563       break;
1564
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);
1571             break;
1572           }
1573           /* Else fallthrough */
1574           break;
1575         case GST_FORMAT_DEFAULT:
1576           *dest_value = gst_util_uint64_scale (src_value,
1577               (guint64) aiffparse->rate, GST_SECOND);
1578           break;
1579         default:
1580           res = FALSE;
1581           goto done;
1582       }
1583       break;
1584
1585     default:
1586       res = FALSE;
1587       goto done;
1588   }
1589
1590 done:
1591   return res;
1592
1593 }
1594
1595 /* handle queries for location and length in requested format */
1596 static gboolean
1597 gst_aiff_parse_pad_query (GstPad * pad, GstObject * parent, GstQuery * query)
1598 {
1599   gboolean res = FALSE;
1600   GstAiffParse *aiff = GST_AIFF_PARSE (parent);
1601
1602   switch (GST_QUERY_TYPE (query)) {
1603     case GST_QUERY_DURATION:
1604     {
1605       gint64 duration = 0;
1606       GstFormat format;
1607
1608       /* only if we know */
1609       if (aiff->state != AIFF_PARSE_DATA)
1610         break;
1611
1612       gst_query_parse_duration (query, &format, NULL);
1613
1614       switch (format) {
1615         case GST_FORMAT_TIME:{
1616           if ((res = gst_aiff_parse_calculate_duration (aiff))) {
1617             duration = aiff->duration;
1618           }
1619           break;
1620         }
1621         default:
1622           format = GST_FORMAT_BYTES;
1623           duration = aiff->datasize;
1624           break;
1625       }
1626       gst_query_set_duration (query, format, duration);
1627       break;
1628     }
1629     case GST_QUERY_CONVERT:
1630     {
1631       gint64 srcvalue, dstvalue;
1632       GstFormat srcformat, dstformat;
1633
1634       /* only if we know */
1635       if (aiff->state != AIFF_PARSE_DATA)
1636         break;
1637
1638       gst_query_parse_convert (query, &srcformat, &srcvalue,
1639           &dstformat, &dstvalue);
1640       res = gst_aiff_parse_pad_convert (pad, srcformat, srcvalue,
1641           &dstformat, &dstvalue);
1642       if (res)
1643         gst_query_set_convert (query, srcformat, srcvalue, dstformat, dstvalue);
1644       break;
1645     }
1646     case GST_QUERY_SEEKING:{
1647       GstFormat fmt;
1648
1649       /* only if we know */
1650       if (aiff->state != AIFF_PARSE_DATA)
1651         break;
1652
1653       gst_query_parse_seeking (query, &fmt, NULL, NULL, NULL);
1654       if (fmt == GST_FORMAT_TIME) {
1655         gboolean seekable = TRUE;
1656
1657         if (!gst_aiff_parse_calculate_duration (aiff)) {
1658           seekable = FALSE;
1659         }
1660         gst_query_set_seeking (query, GST_FORMAT_TIME, seekable,
1661             0, aiff->duration);
1662         res = TRUE;
1663       }
1664       break;
1665     }
1666     default:
1667       res = gst_pad_query_default (pad, parent, query);
1668       break;
1669   }
1670   return res;
1671 }
1672
1673 static gboolean
1674 gst_aiff_parse_srcpad_event (GstPad * pad, GstObject * parent, GstEvent * event)
1675 {
1676   GstAiffParse *aiffparse = GST_AIFF_PARSE (parent);
1677   gboolean res = FALSE;
1678
1679   GST_DEBUG_OBJECT (aiffparse, "%s event", GST_EVENT_TYPE_NAME (event));
1680
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);
1686       }
1687       gst_event_unref (event);
1688       break;
1689     default:
1690       res = gst_pad_push_event (aiffparse->sinkpad, event);
1691       break;
1692   }
1693   return res;
1694 }
1695
1696 static gboolean
1697 gst_aiff_parse_sink_activate (GstPad * sinkpad, GstObject * parent)
1698 {
1699   GstQuery *query;
1700   gboolean pull_mode;
1701
1702   query = gst_query_new_scheduling ();
1703
1704   if (!gst_pad_peer_query (sinkpad, query)) {
1705     gst_query_unref (query);
1706     goto activate_push;
1707   }
1708
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);
1712
1713   if (!pull_mode)
1714     goto activate_push;
1715
1716   GST_DEBUG_OBJECT (sinkpad, "going to pull mode");
1717   return gst_pad_activate_mode (sinkpad, GST_PAD_MODE_PULL, TRUE);
1718
1719 activate_push:
1720   {
1721     GST_DEBUG_OBJECT (sinkpad, "going to push (streaming) mode");
1722     return gst_pad_activate_mode (sinkpad, GST_PAD_MODE_PUSH, TRUE);
1723   }
1724 }
1725
1726
1727 static gboolean
1728 gst_aiff_parse_sink_activate_mode (GstPad * sinkpad, GstObject * parent,
1729     GstPadMode mode, gboolean active)
1730 {
1731   gboolean res;
1732   GstAiffParse *aiff = GST_AIFF_PARSE (parent);
1733
1734   if (aiff->adapter) {
1735     g_object_unref (aiff->adapter);
1736     aiff->adapter = NULL;
1737   }
1738
1739   switch (mode) {
1740     case GST_PAD_MODE_PUSH:
1741       if (active) {
1742         aiff->streaming = TRUE;
1743         aiff->adapter = gst_adapter_new ();
1744       }
1745       res = TRUE;
1746       break;
1747     case GST_PAD_MODE_PULL:
1748       if (active) {
1749         aiff->streaming = FALSE;
1750         aiff->adapter = NULL;
1751         aiff->segment_running = TRUE;
1752         res =
1753             gst_pad_start_task (sinkpad, (GstTaskFunction) gst_aiff_parse_loop,
1754             sinkpad, NULL);
1755       } else {
1756         aiff->segment_running = FALSE;
1757         res = gst_pad_stop_task (sinkpad);
1758       }
1759       break;
1760     default:
1761       res = FALSE;
1762       break;
1763   }
1764   return res;
1765 };
1766
1767 static GstFlowReturn
1768 gst_aiff_parse_flush_data (GstAiffParse * aiff)
1769 {
1770   GstFlowReturn ret = GST_FLOW_OK;
1771   guint av;
1772
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);
1777   }
1778
1779   return ret;
1780 }
1781
1782
1783 static gboolean
1784 gst_aiff_parse_sink_event (GstPad * pad, GstObject * parent, GstEvent * event)
1785 {
1786   GstAiffParse *aiff = GST_AIFF_PARSE (parent);
1787   gboolean ret = TRUE;
1788
1789   GST_DEBUG_OBJECT (aiff, "handling %s event", GST_EVENT_TYPE_NAME (event));
1790
1791   switch (GST_EVENT_TYPE (event)) {
1792     case GST_EVENT_CAPS:
1793     {
1794       /* discard, we'll come up with proper src caps */
1795       gst_event_unref (event);
1796       break;
1797     }
1798     case GST_EVENT_SEGMENT:
1799     {
1800       gint64 start, stop, offset = 0, end_offset = -1;
1801       GstSegment segment;
1802
1803       /* some debug output */
1804       gst_event_copy_segment (event, &segment);
1805       GST_DEBUG_OBJECT (aiff, "received segment %" GST_SEGMENT_FORMAT,
1806           &segment);
1807
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;
1814         if (start > 0) {
1815           offset = start;
1816           start -= aiff->datastart;
1817           start = MAX (start, 0);
1818         }
1819         if (stop > 0) {
1820           end_offset = stop;
1821           segment.stop -= aiff->datastart;
1822           segment.stop = MAX (stop, 0);
1823         }
1824         if (aiff->state == AIFF_PARSE_DATA &&
1825             aiff->segment.format == GST_FORMAT_TIME) {
1826           guint64 bps = aiff->bps;
1827
1828           /* operating in format TIME, so we can convert */
1829           if (bps) {
1830             if (start >= 0)
1831               start =
1832                   gst_util_uint64_scale_ceil (start, GST_SECOND,
1833                   (guint64) aiff->bps);
1834             if (stop >= 0)
1835               stop =
1836                   gst_util_uint64_scale_ceil (stop, GST_SECOND,
1837                   (guint64) aiff->bps);
1838           } else {
1839             GST_DEBUG_OBJECT (aiff, "unable to compute segment start/stop");
1840             goto exit;
1841           }
1842         }
1843       } else {
1844         GST_DEBUG_OBJECT (aiff, "unsupported segment format, ignoring");
1845         goto exit;
1846       }
1847
1848       segment.start = start;
1849       segment.stop = stop;
1850
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;
1856       }
1857
1858       gst_segment_copy_into (&segment, &aiff->segment);
1859
1860       if (aiff->start_segment)
1861         gst_event_unref (aiff->start_segment);
1862
1863       aiff->start_segment = gst_event_new_segment (&segment);
1864
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;
1873       } else {
1874         /* infinity; upstream will EOS when done */
1875         aiff->dataleft = G_MAXUINT64;
1876       }
1877     exit:
1878       gst_event_unref (event);
1879       break;
1880     }
1881     case GST_EVENT_FLUSH_START:
1882       ret = gst_pad_push_event (aiff->srcpad, event);
1883       break;
1884     case GST_EVENT_FLUSH_STOP:
1885       ret = gst_pad_push_event (aiff->srcpad, event);
1886       gst_adapter_clear (aiff->adapter);
1887       break;
1888     default:
1889       ret = gst_pad_event_default (aiff->sinkpad, parent, event);
1890       break;
1891   }
1892
1893   return ret;
1894 }
1895
1896 static GstStateChangeReturn
1897 gst_aiff_parse_change_state (GstElement * element, GstStateChange transition)
1898 {
1899   GstStateChangeReturn ret;
1900   GstAiffParse *aiff = GST_AIFF_PARSE (element);
1901
1902   switch (transition) {
1903     case GST_STATE_CHANGE_NULL_TO_READY:
1904       break;
1905     case GST_STATE_CHANGE_READY_TO_PAUSED:
1906       gst_aiff_parse_reset (aiff);
1907       break;
1908     case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
1909       break;
1910     default:
1911       break;
1912   }
1913
1914   ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
1915
1916   switch (transition) {
1917     case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
1918       break;
1919     case GST_STATE_CHANGE_PAUSED_TO_READY:
1920       gst_aiff_parse_reset (aiff);
1921       break;
1922     case GST_STATE_CHANGE_READY_TO_NULL:
1923       break;
1924     default:
1925       break;
1926   }
1927   return ret;
1928 }