aiffparse: don't unref NULL buffer
[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  * AIFFparse supports both push and pull mode operations, making it possible to
33  * 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 gnomevfssrc 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 /* FIXME 0.11: suppress warnings for deprecated API such as GStaticRecMutex
57  * with newer GLib versions (>= 2.31.0) */
58 #define GLIB_DISABLE_DEPRECATION_WARNINGS
59
60 #include <string.h>
61 #include <math.h>
62
63 #include "aiffparse.h"
64 #include <gst/audio/audio.h>
65 #include <gst/tag/tag.h>
66 #include <gst/gst-i18n-plugin.h>
67
68 GST_DEBUG_CATEGORY (aiffparse_debug);
69 #define GST_CAT_DEFAULT (aiffparse_debug)
70
71 static void gst_aiff_parse_dispose (GObject * object);
72
73 static gboolean gst_aiff_parse_sink_activate (GstPad * sinkpad,
74     GstObject * parent);
75 static gboolean gst_aiff_parse_sink_activate_mode (GstPad * sinkpad,
76     GstObject * parent, GstPadMode mode, gboolean active);
77 static gboolean gst_aiff_parse_send_event (GstElement * element,
78     GstEvent * event);
79 static GstStateChangeReturn gst_aiff_parse_change_state (GstElement * element,
80     GstStateChange transition);
81
82 static gboolean gst_aiff_parse_pad_query (GstPad * pad, GstObject * parent,
83     GstQuery * query);
84 static gboolean gst_aiff_parse_pad_convert (GstPad * pad,
85     GstFormat src_format,
86     gint64 src_value, GstFormat * dest_format, gint64 * dest_value);
87
88 static GstFlowReturn gst_aiff_parse_chain (GstPad * pad, GstObject * parent,
89     GstBuffer * buf);
90 static void gst_aiff_parse_loop (GstPad * pad);
91 static gboolean gst_aiff_parse_srcpad_event (GstPad * pad, GstObject * parent,
92     GstEvent * event);
93
94 static GstStaticPadTemplate sink_template_factory =
95 GST_STATIC_PAD_TEMPLATE ("sink",
96     GST_PAD_SINK,
97     GST_PAD_ALWAYS,
98     GST_STATIC_CAPS ("audio/x-aiff")
99     );
100
101 static GstStaticPadTemplate src_template_factory =
102 GST_STATIC_PAD_TEMPLATE ("src",
103     GST_PAD_SRC,
104     GST_PAD_ALWAYS,
105     GST_STATIC_CAPS (GST_AUDIO_CAPS_MAKE ("{ S8, S16BE, S16LE, S24BE, S24LE, "
106             "S32LE, S32BE, F32BE, F64BE }"))
107     );
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_chain_function (aiffparse->sinkpad,
195       GST_DEBUG_FUNCPTR (gst_aiff_parse_chain));
196   gst_element_add_pad (GST_ELEMENT_CAST (aiffparse), aiffparse->sinkpad);
197
198   /* source */
199   aiffparse->srcpad =
200       gst_pad_new_from_static_template (&src_template_factory, "src");
201   gst_pad_use_fixed_caps (aiffparse->srcpad);
202   gst_pad_set_query_function (aiffparse->srcpad,
203       GST_DEBUG_FUNCPTR (gst_aiff_parse_pad_query));
204   gst_pad_set_event_function (aiffparse->srcpad,
205       GST_DEBUG_FUNCPTR (gst_aiff_parse_srcpad_event));
206   gst_element_add_pad (GST_ELEMENT_CAST (aiffparse), aiffparse->srcpad);
207 }
208
209 static gboolean
210 gst_aiff_parse_parse_file_header (GstAiffParse * aiff, GstBuffer * buf)
211 {
212   guint32 header, type = 0;
213   GstMapInfo info;
214
215   if (!gst_buffer_map (buf, &info, GST_MAP_READ)) {
216     GST_WARNING_OBJECT (aiff, "Could not map buffer");
217     goto not_aiff;
218   }
219
220   if (info.size < 12) {
221     GST_WARNING_OBJECT (aiff, "Buffer too short");
222     gst_buffer_unmap (buf, &info);
223     goto not_aiff;
224   }
225
226   header = GST_READ_UINT32_LE (info.data);
227   type = GST_READ_UINT32_LE (info.data + 8);
228   gst_buffer_unmap (buf, &info);
229
230   if (header != GST_MAKE_FOURCC ('F', 'O', 'R', 'M'))
231     goto not_aiff;
232
233   if (type == GST_MAKE_FOURCC ('A', 'I', 'F', 'F'))
234     aiff->is_aifc = FALSE;
235   else if (type == GST_MAKE_FOURCC ('A', 'I', 'F', 'C'))
236     aiff->is_aifc = TRUE;
237   else
238     goto not_aiff;
239
240   gst_buffer_unref (buf);
241   return TRUE;
242
243   /* ERRORS */
244 not_aiff:
245   {
246     GST_ELEMENT_ERROR (aiff, STREAM, WRONG_TYPE, (NULL),
247         ("File is not an AIFF file: %" GST_FOURCC_FORMAT,
248             GST_FOURCC_ARGS (type)));
249     gst_buffer_unref (buf);
250     return FALSE;
251   }
252 }
253
254 static GstFlowReturn
255 gst_aiff_parse_stream_init (GstAiffParse * aiff)
256 {
257   GstFlowReturn res;
258   GstBuffer *buf = NULL;
259
260   if ((res = gst_pad_pull_range (aiff->sinkpad,
261               aiff->offset, 12, &buf)) != GST_FLOW_OK)
262     return res;
263   else if (!gst_aiff_parse_parse_file_header (aiff, buf))
264     return GST_FLOW_ERROR;
265
266   aiff->offset += 12;
267
268   return GST_FLOW_OK;
269 }
270
271 /* This function is used to perform seeks on the element in
272  * pull mode.
273  *
274  * It also works when event is NULL, in which case it will just
275  * start from the last configured segment. This technique is
276  * used when activating the element and to perform the seek in
277  * READY.
278  */
279 static gboolean
280 gst_aiff_parse_perform_seek (GstAiffParse * aiff, GstEvent * event)
281 {
282   gboolean res;
283   gdouble rate;
284   GstFormat format;
285   GstSeekFlags flags;
286   GstSeekType cur_type = GST_SEEK_TYPE_NONE, stop_type;
287   gint64 cur, stop, upstream_size;
288   gboolean flush;
289   gboolean update;
290   GstSegment seeksegment = { 0, };
291   gint64 position;
292
293   if (event) {
294     GST_DEBUG_OBJECT (aiff, "doing seek with event");
295
296     gst_event_parse_seek (event, &rate, &format, &flags,
297         &cur_type, &cur, &stop_type, &stop);
298
299     /* no negative rates yet */
300     if (rate < 0.0)
301       goto negative_rate;
302
303     if (format != aiff->segment.format) {
304       GST_INFO_OBJECT (aiff, "converting seek-event from %s to %s",
305           gst_format_get_name (format),
306           gst_format_get_name (aiff->segment.format));
307       res = TRUE;
308       if (cur_type != GST_SEEK_TYPE_NONE)
309         res =
310             gst_pad_query_convert (aiff->srcpad, format, cur,
311             aiff->segment.format, &cur);
312       if (res && stop_type != GST_SEEK_TYPE_NONE)
313         res =
314             gst_pad_query_convert (aiff->srcpad, format, stop,
315             aiff->segment.format, &stop);
316       if (!res)
317         goto no_format;
318
319       format = aiff->segment.format;
320     }
321   } else {
322     GST_DEBUG_OBJECT (aiff, "doing seek without event");
323     flags = 0;
324     rate = 1.0;
325     cur_type = GST_SEEK_TYPE_SET;
326     stop_type = GST_SEEK_TYPE_SET;
327   }
328
329   /* get flush flag */
330   flush = flags & GST_SEEK_FLAG_FLUSH;
331
332   /* now we need to make sure the streaming thread is stopped. We do this by
333    * either sending a FLUSH_START event downstream which will cause the
334    * streaming thread to stop with a FLUSHING.
335    * For a non-flushing seek we simply pause the task, which will happen as soon
336    * as it completes one iteration (and thus might block when the sink is
337    * blocking in preroll). */
338   if (flush) {
339     GST_DEBUG_OBJECT (aiff, "sending flush start");
340     gst_pad_push_event (aiff->srcpad, gst_event_new_flush_start ());
341   } else {
342     gst_pad_pause_task (aiff->sinkpad);
343   }
344
345   /* we should now be able to grab the streaming thread because we stopped it
346    * with the above flush/pause code */
347   GST_PAD_STREAM_LOCK (aiff->sinkpad);
348
349   /* save current position */
350   position = aiff->segment.position;
351
352   GST_DEBUG_OBJECT (aiff, "stopped streaming at %" G_GINT64_FORMAT, position);
353
354   /* copy segment, we need this because we still need the old
355    * segment when we close the current segment. */
356   memcpy (&seeksegment, &aiff->segment, sizeof (GstSegment));
357
358   /* configure the seek parameters in the seeksegment. We will then have the
359    * right values in the segment to perform the seek */
360   if (event) {
361     GST_DEBUG_OBJECT (aiff, "configuring seek");
362     gst_segment_do_seek (&seeksegment, rate, format, flags,
363         cur_type, cur, stop_type, stop, &update);
364   }
365
366   /* figure out the last position we need to play. If it's configured (stop !=
367    * -1), use that, else we play until the total duration of the file */
368   if ((stop = seeksegment.stop) == -1)
369     stop = seeksegment.duration;
370
371   GST_DEBUG_OBJECT (aiff, "cur_type =%d", cur_type);
372   if ((cur_type != GST_SEEK_TYPE_NONE)) {
373     /* bring offset to bytes, if the bps is 0, we have the segment in BYTES and
374      * we can just copy the position. If not, we use the bps to convert TIME to
375      * bytes. */
376     if (aiff->bps > 0)
377       aiff->offset =
378           gst_util_uint64_scale_ceil (seeksegment.position,
379           (guint64) aiff->bps, GST_SECOND);
380     else
381       aiff->offset = seeksegment.position;
382     GST_LOG_OBJECT (aiff, "offset=%" G_GUINT64_FORMAT, aiff->offset);
383     aiff->offset -= (aiff->offset % aiff->bytes_per_sample);
384     GST_LOG_OBJECT (aiff, "offset=%" G_GUINT64_FORMAT, aiff->offset);
385     aiff->offset += aiff->datastart;
386     GST_LOG_OBJECT (aiff, "offset=%" G_GUINT64_FORMAT, aiff->offset);
387   } else {
388     GST_LOG_OBJECT (aiff, "continue from offset=%" G_GUINT64_FORMAT,
389         aiff->offset);
390   }
391
392   if (stop_type != GST_SEEK_TYPE_NONE) {
393     if (aiff->bps > 0)
394       aiff->end_offset =
395           gst_util_uint64_scale_ceil (stop, (guint64) aiff->bps, GST_SECOND);
396     else
397       aiff->end_offset = stop;
398     GST_LOG_OBJECT (aiff, "end_offset=%" G_GUINT64_FORMAT, aiff->end_offset);
399     aiff->end_offset -= (aiff->end_offset % aiff->bytes_per_sample);
400     GST_LOG_OBJECT (aiff, "end_offset=%" G_GUINT64_FORMAT, aiff->end_offset);
401     aiff->end_offset += aiff->datastart;
402     GST_LOG_OBJECT (aiff, "end_offset=%" G_GUINT64_FORMAT, aiff->end_offset);
403   } else {
404     GST_LOG_OBJECT (aiff, "continue to end_offset=%" G_GUINT64_FORMAT,
405         aiff->end_offset);
406   }
407
408   /* make sure filesize is not exceeded due to rounding errors or so,
409    * same precaution as in _stream_headers */
410   if (gst_pad_peer_query_duration (aiff->sinkpad, GST_FORMAT_BYTES,
411           &upstream_size))
412     aiff->end_offset = MIN (aiff->end_offset, upstream_size);
413
414   /* this is the range of bytes we will use for playback */
415   aiff->offset = MIN (aiff->offset, aiff->end_offset);
416   aiff->dataleft = aiff->end_offset - aiff->offset;
417
418   GST_DEBUG_OBJECT (aiff,
419       "seek: rate %lf, offset %" G_GUINT64_FORMAT ", end %" G_GUINT64_FORMAT
420       ", segment %" GST_TIME_FORMAT " -- %" GST_TIME_FORMAT, rate, aiff->offset,
421       aiff->end_offset, GST_TIME_ARGS (seeksegment.start),
422       GST_TIME_ARGS (stop));
423
424   /* prepare for streaming again */
425   if (flush) {
426     /* if we sent a FLUSH_START, we now send a FLUSH_STOP */
427     GST_DEBUG_OBJECT (aiff, "sending flush stop");
428     gst_pad_push_event (aiff->srcpad, gst_event_new_flush_stop (TRUE));
429   }
430
431   /* now we did the seek and can activate the new segment values */
432   memcpy (&aiff->segment, &seeksegment, sizeof (GstSegment));
433
434   /* if we're doing a segment seek, post a SEGMENT_START message */
435   if (aiff->segment.flags & GST_SEEK_FLAG_SEGMENT) {
436     gst_element_post_message (GST_ELEMENT_CAST (aiff),
437         gst_message_new_segment_start (GST_OBJECT_CAST (aiff),
438             aiff->segment.format, aiff->segment.position));
439   }
440
441   /* now create the newsegment */
442   GST_DEBUG_OBJECT (aiff, "Creating newsegment from %" G_GINT64_FORMAT
443       " to %" G_GINT64_FORMAT, aiff->segment.position, stop);
444
445   /* store the newsegment event so it can be sent from the streaming thread. */
446   if (aiff->start_segment)
447     gst_event_unref (aiff->start_segment);
448   aiff->start_segment = gst_event_new_segment (&aiff->segment);
449
450   /* mark discont if we are going to stream from another position. */
451   if (position != aiff->segment.position) {
452     GST_DEBUG_OBJECT (aiff, "mark DISCONT, we did a seek to another position");
453     aiff->discont = TRUE;
454   }
455
456   /* and start the streaming task again */
457   aiff->segment_running = TRUE;
458   if (!aiff->streaming) {
459     gst_pad_start_task (aiff->sinkpad, (GstTaskFunction) gst_aiff_parse_loop,
460         aiff->sinkpad, NULL);
461   }
462
463   GST_PAD_STREAM_UNLOCK (aiff->sinkpad);
464
465   return TRUE;
466
467   /* ERRORS */
468 negative_rate:
469   {
470     GST_DEBUG_OBJECT (aiff, "negative playback rates are not supported yet.");
471     return FALSE;
472   }
473 no_format:
474   {
475     GST_DEBUG_OBJECT (aiff, "unsupported format given, seek aborted.");
476     return FALSE;
477   }
478 }
479
480 /*
481  * gst_aiff_parse_peek_chunk_info:
482  * @aiff AIFFparse object
483  * @tag holder for tag
484  * @size holder for tag size
485  *
486  * Peek next chunk info (tag and size)
487  *
488  * Returns: %TRUE when the chunk info (header) is available
489  */
490 static gboolean
491 gst_aiff_parse_peek_chunk_info (GstAiffParse * aiff, guint32 * tag,
492     guint32 * size)
493 {
494   const guint8 *data = NULL;
495
496   if (gst_adapter_available (aiff->adapter) < 8)
497     return FALSE;
498
499   data = gst_adapter_map (aiff->adapter, 8);
500   *tag = GST_READ_UINT32_LE (data);
501   *size = GST_READ_UINT32_BE (data + 4);
502   gst_adapter_unmap (aiff->adapter);
503
504   GST_DEBUG ("Next chunk size is %d bytes, type %" GST_FOURCC_FORMAT, *size,
505       GST_FOURCC_ARGS (*tag));
506
507   return TRUE;
508 }
509
510 /*
511  * gst_aiff_parse_peek_chunk:
512  * @aiff AIFFparse object
513  * @tag holder for tag
514  * @size holder for tag size
515  *
516  * Peek enough data for one full chunk
517  *
518  * Returns: %TRUE when the full chunk is available
519  */
520 static gboolean
521 gst_aiff_parse_peek_chunk (GstAiffParse * aiff, guint32 * tag, guint32 * size)
522 {
523   guint32 peek_size = 0;
524   guint available;
525
526   if (!gst_aiff_parse_peek_chunk_info (aiff, tag, size))
527     return FALSE;
528
529   GST_DEBUG ("Need to peek chunk of %d bytes", *size);
530   peek_size = (*size + 1) & ~1;
531
532   available = gst_adapter_available (aiff->adapter);
533   if (available >= (8 + peek_size)) {
534     return TRUE;
535   } else {
536     GST_LOG ("but only %u bytes available now", available);
537     return FALSE;
538   }
539 }
540
541 static gboolean
542 gst_aiff_parse_peek_data (GstAiffParse * aiff, guint32 size,
543     const guint8 ** data)
544 {
545   if (gst_adapter_available (aiff->adapter) < size)
546     return FALSE;
547
548   *data = gst_adapter_map (aiff->adapter, size);
549   return TRUE;
550 }
551
552 /*
553  * gst_aiff_parse_calculate_duration:
554  * @aiff: aiffparse object
555  *
556  * Calculate duration on demand and store in @aiff.
557  *
558  * Returns: %TRUE if duration is available.
559  */
560 static gboolean
561 gst_aiff_parse_calculate_duration (GstAiffParse * aiff)
562 {
563   if (aiff->duration > 0)
564     return TRUE;
565
566   if (aiff->datasize > 0 && aiff->bps > 0) {
567     aiff->duration =
568         gst_util_uint64_scale_ceil (aiff->datasize, GST_SECOND,
569         (guint64) aiff->bps);
570     GST_INFO_OBJECT (aiff, "Got duration %" GST_TIME_FORMAT,
571         GST_TIME_ARGS (aiff->duration));
572     return TRUE;
573   }
574   return FALSE;
575 }
576
577 static void
578 gst_aiff_parse_ignore_chunk (GstAiffParse * aiff, guint32 tag, guint32 size)
579 {
580   guint flush;
581
582   if (aiff->streaming) {
583     if (!gst_aiff_parse_peek_chunk (aiff, &tag, &size))
584       return;
585   }
586   GST_DEBUG_OBJECT (aiff, "Ignoring tag %" GST_FOURCC_FORMAT,
587       GST_FOURCC_ARGS (tag));
588   flush = 8 + ((size + 1) & ~1);
589   aiff->offset += flush;
590   if (aiff->streaming) {
591     gst_adapter_flush (aiff->adapter, flush);
592   }
593 }
594
595 static double
596 gst_aiff_parse_read_IEEE80 (guint8 * buf)
597 {
598   int s = buf[0] & 0xff;
599   int e = ((buf[0] & 0x7f) << 8) | (buf[1] & 0xff);
600   double f = ((unsigned long) (buf[2] & 0xff) << 24) |
601       ((buf[3] & 0xff) << 16) | ((buf[4] & 0xff) << 8) | (buf[5] & 0xff);
602
603   if (e == 32767) {
604     if (buf[2] & 0x80)
605       return HUGE_VAL;          /* Really NaN, but this won't happen in reality */
606     else {
607       if (s)
608         return -HUGE_VAL;
609       else
610         return HUGE_VAL;
611     }
612   }
613
614   f = ldexp (f, 32);
615   f += ((buf[6] & 0xff) << 24) |
616       ((buf[7] & 0xff) << 16) | ((buf[8] & 0xff) << 8) | (buf[9] & 0xff);
617
618   return ldexp (f, e - 16446);
619 }
620
621 static gboolean
622 gst_aiff_parse_parse_comm (GstAiffParse * aiff, GstBuffer * buf)
623 {
624   int size;
625   GstMapInfo info;
626   guint32 fourcc;
627
628   if (!gst_buffer_map (buf, &info, GST_MAP_READ)) {
629     GST_WARNING_OBJECT (aiff, "Can't map buffer");
630     gst_buffer_unref (buf);
631     return FALSE;
632   }
633
634   if (aiff->is_aifc)
635     size = 22;
636   else
637     size = 18;
638
639   if (info.size < size)
640     goto too_small;
641
642   aiff->channels = GST_READ_UINT16_BE (info.data);
643   aiff->total_frames = GST_READ_UINT32_BE (info.data + 2);
644   aiff->depth = GST_READ_UINT16_BE (info.data + 6);
645   aiff->width = GST_ROUND_UP_8 (aiff->depth);
646   aiff->rate = (int) gst_aiff_parse_read_IEEE80 (info.data + 8);
647
648   aiff->floating_point = FALSE;
649
650   if (aiff->is_aifc) {
651     fourcc = GST_READ_UINT32_LE (info.data + 18);
652
653     /* We only support the 'trivial' uncompressed AIFC, but it can be
654      * either big or little endian */
655     switch (fourcc) {
656       case GST_MAKE_FOURCC ('N', 'O', 'N', 'E'):
657         aiff->endianness = G_BIG_ENDIAN;
658         break;
659       case GST_MAKE_FOURCC ('s', 'o', 'w', 't'):
660         aiff->endianness = G_LITTLE_ENDIAN;
661         break;
662       case GST_MAKE_FOURCC ('F', 'L', '3', '2'):
663       case GST_MAKE_FOURCC ('f', 'l', '3', '2'):
664         aiff->floating_point = TRUE;
665         aiff->width = aiff->depth = 32;
666         aiff->endianness = G_BIG_ENDIAN;
667         break;
668       case GST_MAKE_FOURCC ('f', 'l', '6', '4'):
669         aiff->floating_point = TRUE;
670         aiff->width = aiff->depth = 64;
671         aiff->endianness = G_BIG_ENDIAN;
672         break;
673       default:
674         goto unknown_compression;
675     }
676   } else
677     aiff->endianness = G_BIG_ENDIAN;
678
679   gst_buffer_unmap (buf, &info);
680   gst_buffer_unref (buf);
681
682   return TRUE;
683
684   /* ERRORS */
685 too_small:
686   {
687     GST_WARNING_OBJECT (aiff, "COMM chunk too short, cannot parse header");
688     gst_buffer_unmap (buf, &info);
689     gst_buffer_unref (buf);
690     return FALSE;
691   }
692 unknown_compression:
693   {
694     GST_WARNING_OBJECT (aiff, "Unsupported compression in AIFC "
695         "file: %" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (fourcc));
696     gst_buffer_unmap (buf, &info);
697     gst_buffer_unref (buf);
698     return FALSE;
699   }
700 }
701
702 static GstFlowReturn
703 gst_aiff_parse_read_chunk (GstAiffParse * aiff, guint64 * offset, guint32 * tag,
704     GstBuffer ** data)
705 {
706   guint size;
707   GstFlowReturn res;
708   GstBuffer *buf = NULL;
709   GstMapInfo info;
710
711   if ((res =
712           gst_pad_pull_range (aiff->sinkpad, *offset, 8, &buf)) != GST_FLOW_OK)
713     return res;
714
715   gst_buffer_map (buf, &info, GST_MAP_READ);
716   *tag = GST_READ_UINT32_LE (info.data);
717   size = GST_READ_UINT32_BE (info.data + 4);
718   gst_buffer_unmap (buf, &info);
719   gst_buffer_unref (buf);
720   buf = NULL;
721
722   if ((res =
723           gst_pad_pull_range (aiff->sinkpad, (*offset) + 8, size,
724               &buf)) != GST_FLOW_OK)
725     return res;
726   else if (gst_buffer_get_size (buf) < size)
727     goto too_small;
728
729   *data = buf;
730   *offset += 8 + GST_ROUND_UP_2 (size);
731
732   return GST_FLOW_OK;
733
734   /* ERRORS */
735 too_small:
736   {
737     /* short read, we return EOS to mark the EOS case */
738     GST_DEBUG_OBJECT (aiff,
739         "not enough data (available=%" G_GSIZE_FORMAT ", needed=%u)",
740         gst_buffer_get_size (buf), size);
741     gst_buffer_unref (buf);
742     return GST_FLOW_EOS;
743   }
744
745 }
746
747 static GstCaps *
748 gst_aiff_parse_create_caps (GstAiffParse * aiff)
749 {
750   GstCaps *caps = NULL;
751   const gchar *format = NULL;
752
753   if (aiff->floating_point) {
754     if (aiff->endianness == G_BIG_ENDIAN) {
755       if (aiff->width == 32)
756         format = "F32BE";
757       else if (aiff->width == 32)
758         format = "F64BE";
759     }
760   } else {
761     if (aiff->endianness == G_BIG_ENDIAN) {
762       if (aiff->width == 8)
763         format = "S8";
764       else if (aiff->width == 16)
765         format = "S16BE";
766       else if (aiff->width == 24)
767         format = "S24BE";
768       else if (aiff->width == 32)
769         format = "S32BE";
770     } else {
771       if (aiff->width == 8)
772         format = "S8";
773       else if (aiff->width == 16)
774         format = "S16LE";
775       else if (aiff->width == 24)
776         format = "S24LE";
777       else if (aiff->width == 32)
778         format = "S32LE";
779     }
780   }
781   if (format) {
782     caps = gst_caps_new_simple ("audio/x-raw",
783         "format", G_TYPE_STRING, format,
784         "channels", G_TYPE_INT, aiff->channels,
785         "layout", G_TYPE_STRING, "interleaved",
786         "rate", G_TYPE_INT, aiff->rate, NULL);
787   }
788
789   GST_DEBUG_OBJECT (aiff, "Created caps: %" GST_PTR_FORMAT, caps);
790
791   return caps;
792 }
793
794 static GstFlowReturn
795 gst_aiff_parse_stream_headers (GstAiffParse * aiff)
796 {
797   GstFlowReturn res;
798   GstBuffer *buf = NULL;
799   guint32 tag, size;
800   gboolean gotdata = FALSE;
801   gboolean done = FALSE;
802   GstEvent **event_p;
803   gint64 upstream_size = 0;
804
805   gst_pad_peer_query_duration (aiff->sinkpad, GST_FORMAT_BYTES, &upstream_size);
806   GST_DEBUG_OBJECT (aiff, "upstream size %" G_GUINT64_FORMAT, upstream_size);
807
808   /* loop headers until we get data */
809   while (!done) {
810     if (aiff->streaming) {
811       if (!gst_aiff_parse_peek_chunk_info (aiff, &tag, &size))
812         return GST_FLOW_OK;
813     } else {
814       GstMapInfo info;
815
816       if ((res =
817               gst_pad_pull_range (aiff->sinkpad, aiff->offset, 8,
818                   &buf)) != GST_FLOW_OK)
819         goto header_read_error;
820
821       gst_buffer_map (buf, &info, GST_MAP_READ);
822       tag = GST_READ_UINT32_LE (info.data);
823       size = GST_READ_UINT32_BE (info.data + 4);
824       gst_buffer_unmap (buf, &info);
825       gst_buffer_unref (buf);
826       buf = NULL;
827     }
828
829     GST_INFO_OBJECT (aiff,
830         "Got TAG: %" GST_FOURCC_FORMAT ", offset %" G_GUINT64_FORMAT,
831         GST_FOURCC_ARGS (tag), aiff->offset);
832
833     /* We just keep reading chunks until we find the one we're interested in.
834      */
835     switch (tag) {
836       case GST_MAKE_FOURCC ('C', 'O', 'M', 'M'):{
837         GstCaps *caps;
838         GstEvent *event;
839         gchar *stream_id;
840
841         if (aiff->streaming) {
842           if (!gst_aiff_parse_peek_chunk (aiff, &tag, &size))
843             return GST_FLOW_OK;
844
845           gst_adapter_flush (aiff->adapter, 8);
846           aiff->offset += 8;
847
848           buf = gst_adapter_take_buffer (aiff->adapter, size);
849         } else {
850           if ((res = gst_aiff_parse_read_chunk (aiff,
851                       &aiff->offset, &tag, &buf)) != GST_FLOW_OK)
852             return res;
853         }
854
855         if (!gst_aiff_parse_parse_comm (aiff, buf))
856           goto parse_header_error;
857
858         /* do sanity checks of header fields */
859         if (aiff->channels == 0)
860           goto no_channels;
861         if (aiff->rate == 0)
862           goto no_rate;
863
864         stream_id =
865             gst_pad_create_stream_id (aiff->srcpad, GST_ELEMENT_CAST (aiff),
866             NULL);
867         event = gst_event_new_stream_start (stream_id);
868         gst_event_set_group_id (event, gst_util_group_id_next ());
869         gst_pad_push_event (aiff->srcpad, event);
870         g_free (stream_id);
871
872         GST_DEBUG_OBJECT (aiff, "creating the caps");
873
874         caps = gst_aiff_parse_create_caps (aiff);
875         if (caps == NULL)
876           goto unknown_format;
877
878         gst_pad_push_event (aiff->srcpad, gst_event_new_caps (caps));
879         gst_caps_unref (caps);
880
881         aiff->bytes_per_sample = aiff->channels * aiff->width / 8;
882         aiff->bps = aiff->bytes_per_sample * aiff->rate;
883
884         if (aiff->bytes_per_sample <= 0)
885           goto no_bytes_per_sample;
886
887         aiff->got_comm = TRUE;
888         break;
889       }
890       case GST_MAKE_FOURCC ('S', 'S', 'N', 'D'):{
891         guint32 datasize;
892
893         GST_DEBUG_OBJECT (aiff, "Got 'SSND' TAG, size : %d", size);
894
895         /* Now, read the 8-byte header in the SSND chunk */
896         if (aiff->streaming) {
897           const guint8 *ssnddata = NULL;
898
899           if (!gst_aiff_parse_peek_data (aiff, 16, &ssnddata))
900             return GST_FLOW_OK;
901
902           aiff->ssnd_offset = GST_READ_UINT32_BE (ssnddata + 8);
903           aiff->ssnd_blocksize = GST_READ_UINT32_BE (ssnddata + 12);
904           gst_adapter_unmap (aiff->adapter);
905           gst_adapter_flush (aiff->adapter, 16);
906         } else {
907           GstBuffer *ssndbuf = NULL;
908           GstMapInfo info;
909
910           if ((res =
911                   gst_pad_pull_range (aiff->sinkpad, aiff->offset, 16,
912                       &ssndbuf)) != GST_FLOW_OK)
913             goto header_read_error;
914
915           gst_buffer_map (ssndbuf, &info, GST_MAP_READ);
916           aiff->ssnd_offset = GST_READ_UINT32_BE (info.data + 8);
917           aiff->ssnd_blocksize = GST_READ_UINT32_BE (info.data + 12);
918           gst_buffer_unmap (ssndbuf, &info);
919           gst_buffer_unref (ssndbuf);
920         }
921
922         gotdata = TRUE;
923
924         /* 8 byte chunk header, 8 byte SSND header */
925         aiff->offset += 16;
926         datasize = size - 16;
927
928         aiff->datastart = aiff->offset + aiff->ssnd_offset;
929         /* file might be truncated */
930         if (upstream_size) {
931           size = MIN (datasize, (upstream_size - aiff->datastart));
932         }
933         aiff->datasize = (guint64) datasize;
934         aiff->dataleft = (guint64) datasize;
935         aiff->end_offset = datasize + aiff->datastart;
936         if (!aiff->streaming) {
937           /* We will continue looking at chunks until the end - to read tags,
938            * etc. */
939           aiff->offset += datasize;
940         }
941         GST_DEBUG_OBJECT (aiff, "datasize = %d", datasize);
942         if (aiff->streaming) {
943           done = TRUE;
944         }
945         break;
946       }
947       case GST_MAKE_FOURCC ('I', 'D', '3', ' '):{
948         GstTagList *tags;
949
950         if (aiff->streaming) {
951           if (!gst_aiff_parse_peek_chunk (aiff, &tag, &size))
952             return GST_FLOW_OK;
953
954           gst_adapter_flush (aiff->adapter, 8);
955           aiff->offset += 8;
956
957           buf = gst_adapter_take_buffer (aiff->adapter, size);
958         } else {
959           if ((res = gst_aiff_parse_read_chunk (aiff,
960                       &aiff->offset, &tag, &buf)) != GST_FLOW_OK)
961             return res;
962         }
963
964         GST_LOG_OBJECT (aiff, "ID3 chunk of size %" G_GSIZE_FORMAT,
965             gst_buffer_get_size (buf));
966
967         tags = gst_tag_list_from_id3v2_tag (buf);
968         gst_buffer_unref (buf);
969
970         GST_INFO_OBJECT (aiff, "ID3 tags: %" GST_PTR_FORMAT, tags);
971
972         if (aiff->tags == NULL) {
973           aiff->tags = tags;
974         } else {
975           gst_tag_list_insert (aiff->tags, tags, GST_TAG_MERGE_APPEND);
976           gst_tag_list_unref (tags);
977         }
978         break;
979       }
980       default:
981         gst_aiff_parse_ignore_chunk (aiff, tag, size);
982     }
983
984     buf = NULL;
985
986     if (upstream_size && (aiff->offset >= upstream_size)) {
987       /* Now we have gone through the whole file */
988       done = TRUE;
989     }
990   }
991
992   /* We read all the chunks (in pull mode) or reached the SSND chunk
993    * (in push mode). We must have both COMM and SSND now; error out 
994    * otherwise.
995    */
996   if (!aiff->got_comm) {
997     GST_WARNING_OBJECT (aiff, "Failed to find COMM chunk");
998     goto no_header;
999   }
1000   if (!gotdata) {
1001     GST_WARNING_OBJECT (aiff, "Failed to find SSND chunk");
1002     goto no_data;
1003   }
1004
1005   GST_DEBUG_OBJECT (aiff, "Finished parsing headers");
1006
1007   if (gst_aiff_parse_calculate_duration (aiff)) {
1008     gst_segment_init (&aiff->segment, GST_FORMAT_TIME);
1009     aiff->segment.duration = aiff->duration;
1010   } else {
1011     /* no bitrate, let downstream peer do the math, we'll feed it bytes. */
1012     gst_segment_init (&aiff->segment, GST_FORMAT_BYTES);
1013     aiff->segment.duration = aiff->datasize;
1014   }
1015
1016   /* now we have all the info to perform a pending seek if any, if no
1017    * event, this will still do the right thing and it will also send
1018    * the right newsegment event downstream. */
1019   gst_aiff_parse_perform_seek (aiff, aiff->seek_event);
1020   /* remove pending event */
1021   event_p = &aiff->seek_event;
1022   gst_event_replace (event_p, NULL);
1023
1024   /* we just started, we are discont */
1025   aiff->discont = TRUE;
1026
1027   aiff->state = AIFF_PARSE_DATA;
1028
1029   return GST_FLOW_OK;
1030
1031   /* ERROR */
1032 no_header:
1033   {
1034     GST_ELEMENT_ERROR (aiff, STREAM, TYPE_NOT_FOUND, (NULL),
1035         ("Invalid AIFF header (no COMM found)"));
1036     return GST_FLOW_ERROR;
1037   }
1038 no_data:
1039   {
1040     GST_ELEMENT_ERROR (aiff, STREAM, TYPE_NOT_FOUND, (NULL),
1041         ("Invalid AIFF: no SSND found"));
1042     return GST_FLOW_ERROR;
1043   }
1044 parse_header_error:
1045   {
1046     GST_ELEMENT_ERROR (aiff, STREAM, DEMUX, (NULL),
1047         ("Couldn't parse audio header"));
1048     return GST_FLOW_ERROR;
1049   }
1050 no_channels:
1051   {
1052     GST_ELEMENT_ERROR (aiff, STREAM, FAILED, (NULL),
1053         ("Stream claims to contain no channels - invalid data"));
1054     return GST_FLOW_ERROR;
1055   }
1056 no_rate:
1057   {
1058     GST_ELEMENT_ERROR (aiff, STREAM, FAILED, (NULL),
1059         ("Stream with sample_rate == 0 - invalid data"));
1060     return GST_FLOW_ERROR;
1061   }
1062 no_bytes_per_sample:
1063   {
1064     GST_ELEMENT_ERROR (aiff, STREAM, FAILED, (NULL),
1065         ("Could not caluclate bytes per sample - invalid data"));
1066     return GST_FLOW_ERROR;
1067   }
1068 unknown_format:
1069   {
1070     GST_ELEMENT_ERROR (aiff, STREAM, TYPE_NOT_FOUND, (NULL),
1071         ("No caps found for format 0x%x, %d channels, %d Hz",
1072             aiff->format, aiff->channels, aiff->rate));
1073     return GST_FLOW_ERROR;
1074   }
1075 header_read_error:
1076   {
1077     GST_ELEMENT_ERROR (aiff, STREAM, DEMUX, (NULL),
1078         ("Couldn't read in header"));
1079     return GST_FLOW_ERROR;
1080   }
1081 }
1082
1083 /*
1084  * Read AIFF file tag when streaming
1085  */
1086 static GstFlowReturn
1087 gst_aiff_parse_parse_stream_init (GstAiffParse * aiff)
1088 {
1089   if (gst_adapter_available (aiff->adapter) >= 12) {
1090     GstBuffer *tmp;
1091
1092     /* _take flushes the data */
1093     tmp = gst_adapter_take_buffer (aiff->adapter, 12);
1094
1095     GST_DEBUG ("Parsing aiff header");
1096     if (!gst_aiff_parse_parse_file_header (aiff, tmp))
1097       return GST_FLOW_ERROR;
1098
1099     aiff->offset += 12;
1100     /* Go to next state */
1101     aiff->state = AIFF_PARSE_HEADER;
1102   }
1103   return GST_FLOW_OK;
1104 }
1105
1106 /* handle an event sent directly to the element.
1107  *
1108  * This event can be sent either in the READY state or the
1109  * >READY state. The only event of interest really is the seek
1110  * event.
1111  *
1112  * In the READY state we can only store the event and try to
1113  * respect it when going to PAUSED. We assume we are in the
1114  * READY state when our parsing state != AIFF_PARSE_DATA.
1115  *
1116  * When we are steaming, we can simply perform the seek right
1117  * away.
1118  */
1119 static gboolean
1120 gst_aiff_parse_send_event (GstElement * element, GstEvent * event)
1121 {
1122   GstAiffParse *aiff = GST_AIFF_PARSE (element);
1123   gboolean res = FALSE;
1124   GstEvent **event_p;
1125
1126   GST_DEBUG_OBJECT (aiff, "received event %s", GST_EVENT_TYPE_NAME (event));
1127
1128   switch (GST_EVENT_TYPE (event)) {
1129     case GST_EVENT_SEEK:
1130       if (aiff->state == AIFF_PARSE_DATA) {
1131         /* we can handle the seek directly when streaming data */
1132         res = gst_aiff_parse_perform_seek (aiff, event);
1133       } else {
1134         GST_DEBUG_OBJECT (aiff, "queuing seek for later");
1135
1136         event_p = &aiff->seek_event;
1137         gst_event_replace (event_p, event);
1138
1139         /* we always return true */
1140         res = TRUE;
1141       }
1142       break;
1143     default:
1144       break;
1145   }
1146   gst_event_unref (event);
1147   return res;
1148 }
1149
1150 #define MAX_BUFFER_SIZE 4096
1151
1152 static GstFlowReturn
1153 gst_aiff_parse_stream_data (GstAiffParse * aiff)
1154 {
1155   GstBuffer *buf = NULL;
1156   GstFlowReturn res = GST_FLOW_OK;
1157   guint64 desired, obtained;
1158   GstClockTime timestamp, next_timestamp, duration;
1159   guint64 pos, nextpos;
1160
1161 iterate_adapter:
1162   GST_LOG_OBJECT (aiff,
1163       "offset: %" G_GINT64_FORMAT " , end: %" G_GINT64_FORMAT " , dataleft: %"
1164       G_GINT64_FORMAT, aiff->offset, aiff->end_offset, aiff->dataleft);
1165
1166   /* Get the next n bytes and output them */
1167   if (aiff->dataleft == 0 || aiff->dataleft < aiff->bytes_per_sample)
1168     goto found_eos;
1169
1170   /* scale the amount of data by the segment rate so we get equal
1171    * amounts of data regardless of the playback rate */
1172   desired =
1173       MIN (gst_guint64_to_gdouble (aiff->dataleft),
1174       MAX_BUFFER_SIZE * ABS (aiff->segment.rate));
1175
1176   if (desired >= aiff->bytes_per_sample && aiff->bytes_per_sample > 0)
1177     desired -= (desired % aiff->bytes_per_sample);
1178
1179   GST_LOG_OBJECT (aiff, "Fetching %" G_GINT64_FORMAT " bytes of data "
1180       "from the sinkpad", desired);
1181
1182   if (aiff->streaming) {
1183     guint avail = gst_adapter_available (aiff->adapter);
1184
1185     if (avail < desired) {
1186       GST_LOG_OBJECT (aiff, "Got only %d bytes of data from the sinkpad",
1187           avail);
1188       return GST_FLOW_OK;
1189     }
1190
1191     buf = gst_adapter_take_buffer (aiff->adapter, desired);
1192   } else {
1193     if ((res = gst_pad_pull_range (aiff->sinkpad, aiff->offset,
1194                 desired, &buf)) != GST_FLOW_OK)
1195       goto pull_error;
1196   }
1197
1198   /* If we have a pending close/start segment, send it now. */
1199   if (G_UNLIKELY (aiff->close_segment != NULL)) {
1200     gst_pad_push_event (aiff->srcpad, aiff->close_segment);
1201     aiff->close_segment = NULL;
1202   }
1203   if (G_UNLIKELY (aiff->start_segment != NULL)) {
1204     gst_pad_push_event (aiff->srcpad, aiff->start_segment);
1205     aiff->start_segment = NULL;
1206   }
1207   if (G_UNLIKELY (aiff->tags != NULL)) {
1208     gst_pad_push_event (aiff->srcpad, gst_event_new_tag (aiff->tags));
1209     aiff->tags = NULL;
1210   }
1211
1212   obtained = gst_buffer_get_size (buf);
1213
1214   /* our positions in bytes */
1215   pos = aiff->offset - aiff->datastart;
1216   nextpos = pos + obtained;
1217
1218   /* update offsets, does not overflow. */
1219   GST_BUFFER_OFFSET (buf) = pos / aiff->bytes_per_sample;
1220   GST_BUFFER_OFFSET_END (buf) = nextpos / aiff->bytes_per_sample;
1221
1222   if (aiff->bps > 0) {
1223     /* and timestamps if we have a bitrate, be careful for overflows */
1224     timestamp =
1225         gst_util_uint64_scale_ceil (pos, GST_SECOND, (guint64) aiff->bps);
1226     next_timestamp =
1227         gst_util_uint64_scale_ceil (nextpos, GST_SECOND, (guint64) aiff->bps);
1228     duration = next_timestamp - timestamp;
1229
1230     /* update current running segment position */
1231     aiff->segment.position = next_timestamp;
1232   } else {
1233     /* no bitrate, all we know is that the first sample has timestamp 0, all
1234      * other positions and durations have unknown timestamp. */
1235     if (pos == 0)
1236       timestamp = 0;
1237     else
1238       timestamp = GST_CLOCK_TIME_NONE;
1239     duration = GST_CLOCK_TIME_NONE;
1240     /* update current running segment position with byte offset */
1241     aiff->segment.position = nextpos;
1242   }
1243   if (aiff->discont) {
1244     GST_DEBUG_OBJECT (aiff, "marking DISCONT");
1245     GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_DISCONT);
1246     aiff->discont = FALSE;
1247   }
1248
1249   GST_BUFFER_TIMESTAMP (buf) = timestamp;
1250   GST_BUFFER_DURATION (buf) = duration;
1251
1252   GST_LOG_OBJECT (aiff,
1253       "Got buffer. timestamp:%" GST_TIME_FORMAT " , duration:%" GST_TIME_FORMAT
1254       ", size:%" G_GUINT64_FORMAT, GST_TIME_ARGS (timestamp),
1255       GST_TIME_ARGS (duration), obtained);
1256
1257   if ((res = gst_pad_push (aiff->srcpad, buf)) != GST_FLOW_OK)
1258     goto push_error;
1259
1260   if (obtained < aiff->dataleft) {
1261     aiff->offset += obtained;
1262     aiff->dataleft -= obtained;
1263   } else {
1264     aiff->offset += aiff->dataleft;
1265     aiff->dataleft = 0;
1266   }
1267
1268   /* Iterate until need more data, so adapter size won't grow */
1269   if (aiff->streaming) {
1270     GST_LOG_OBJECT (aiff,
1271         "offset: %" G_GINT64_FORMAT " , end: %" G_GINT64_FORMAT, aiff->offset,
1272         aiff->end_offset);
1273     goto iterate_adapter;
1274   }
1275   return res;
1276
1277   /* ERROR */
1278 found_eos:
1279   {
1280     GST_DEBUG_OBJECT (aiff, "found EOS");
1281     return GST_FLOW_EOS;
1282   }
1283 pull_error:
1284   {
1285     /* check if we got EOS */
1286     if (res == GST_FLOW_EOS)
1287       goto found_eos;
1288
1289     GST_WARNING_OBJECT (aiff,
1290         "Error getting %" G_GINT64_FORMAT " bytes from the "
1291         "sinkpad (dataleft = %" G_GINT64_FORMAT ")", desired, aiff->dataleft);
1292     return res;
1293   }
1294 push_error:
1295   {
1296     GST_INFO_OBJECT (aiff,
1297         "Error pushing on srcpad %s:%s, reason %s, is linked? = %d",
1298         GST_DEBUG_PAD_NAME (aiff->srcpad), gst_flow_get_name (res),
1299         gst_pad_is_linked (aiff->srcpad));
1300     return res;
1301   }
1302 }
1303
1304 static void
1305 gst_aiff_parse_loop (GstPad * pad)
1306 {
1307   GstFlowReturn ret;
1308   GstAiffParse *aiff = GST_AIFF_PARSE (GST_PAD_PARENT (pad));
1309
1310   GST_LOG_OBJECT (aiff, "process data");
1311
1312   switch (aiff->state) {
1313     case AIFF_PARSE_START:
1314       GST_INFO_OBJECT (aiff, "AIFF_PARSE_START");
1315       if ((ret = gst_aiff_parse_stream_init (aiff)) != GST_FLOW_OK)
1316         goto pause;
1317
1318       aiff->state = AIFF_PARSE_HEADER;
1319       /* fall-through */
1320
1321     case AIFF_PARSE_HEADER:
1322       GST_INFO_OBJECT (aiff, "AIFF_PARSE_HEADER");
1323       if ((ret = gst_aiff_parse_stream_headers (aiff)) != GST_FLOW_OK)
1324         goto pause;
1325
1326       aiff->state = AIFF_PARSE_DATA;
1327       GST_INFO_OBJECT (aiff, "AIFF_PARSE_DATA");
1328       /* fall-through */
1329
1330     case AIFF_PARSE_DATA:
1331       if ((ret = gst_aiff_parse_stream_data (aiff)) != GST_FLOW_OK)
1332         goto pause;
1333       break;
1334     default:
1335       g_assert_not_reached ();
1336   }
1337   return;
1338
1339   /* ERRORS */
1340 pause:
1341   {
1342     const gchar *reason = gst_flow_get_name (ret);
1343
1344     GST_DEBUG_OBJECT (aiff, "pausing task, reason %s", reason);
1345     aiff->segment_running = FALSE;
1346     gst_pad_pause_task (pad);
1347
1348     if (ret == GST_FLOW_EOS) {
1349       /* perform EOS logic */
1350       if (aiff->segment.flags & GST_SEEK_FLAG_SEGMENT) {
1351         GstClockTime stop;
1352
1353         if ((stop = aiff->segment.stop) == -1)
1354           stop = aiff->segment.duration;
1355
1356         gst_element_post_message (GST_ELEMENT_CAST (aiff),
1357             gst_message_new_segment_done (GST_OBJECT_CAST (aiff),
1358                 aiff->segment.format, stop));
1359         gst_pad_push_event (aiff->srcpad,
1360             gst_event_new_segment_done (aiff->segment.format, stop));
1361       } else {
1362         gst_pad_push_event (aiff->srcpad, gst_event_new_eos ());
1363       }
1364     } else if (ret < GST_FLOW_EOS || ret == GST_FLOW_NOT_LINKED) {
1365       /* for fatal errors we post an error message, post the error
1366        * first so the app knows about the error first. */
1367       GST_ELEMENT_ERROR (aiff, STREAM, FAILED,
1368           (_("Internal data flow error.")),
1369           ("streaming task paused, reason %s (%d)", reason, ret));
1370       gst_pad_push_event (aiff->srcpad, gst_event_new_eos ());
1371     }
1372     return;
1373   }
1374 }
1375
1376 static GstFlowReturn
1377 gst_aiff_parse_chain (GstPad * pad, GstObject * parent, GstBuffer * buf)
1378 {
1379   GstFlowReturn ret;
1380   GstAiffParse *aiff = GST_AIFF_PARSE (parent);
1381
1382   GST_LOG_OBJECT (aiff, "adapter_push %" G_GSIZE_FORMAT " bytes",
1383       gst_buffer_get_size (buf));
1384
1385   gst_adapter_push (aiff->adapter, buf);
1386
1387   switch (aiff->state) {
1388     case AIFF_PARSE_START:
1389       GST_INFO_OBJECT (aiff, "AIFF_PARSE_START");
1390       if ((ret = gst_aiff_parse_parse_stream_init (aiff)) != GST_FLOW_OK)
1391         goto done;
1392
1393       if (aiff->state != AIFF_PARSE_HEADER)
1394         break;
1395
1396       /* otherwise fall-through */
1397     case AIFF_PARSE_HEADER:
1398       GST_INFO_OBJECT (aiff, "AIFF_PARSE_HEADER");
1399       if ((ret = gst_aiff_parse_stream_headers (aiff)) != GST_FLOW_OK)
1400         goto done;
1401
1402       if (!aiff->got_comm || aiff->datastart == 0)
1403         break;
1404
1405       aiff->state = AIFF_PARSE_DATA;
1406       GST_INFO_OBJECT (aiff, "AIFF_PARSE_DATA");
1407
1408       /* fall-through */
1409     case AIFF_PARSE_DATA:
1410       if ((ret = gst_aiff_parse_stream_data (aiff)) != GST_FLOW_OK)
1411         goto done;
1412       break;
1413     default:
1414       g_return_val_if_reached (GST_FLOW_ERROR);
1415   }
1416 done:
1417   return ret;
1418 }
1419
1420 static gboolean
1421 gst_aiff_parse_pad_convert (GstPad * pad,
1422     GstFormat src_format, gint64 src_value,
1423     GstFormat * dest_format, gint64 * dest_value)
1424 {
1425   GstAiffParse *aiffparse;
1426   gboolean res = TRUE;
1427
1428   aiffparse = GST_AIFF_PARSE (GST_PAD_PARENT (pad));
1429
1430   if (*dest_format == src_format) {
1431     *dest_value = src_value;
1432     return TRUE;
1433   }
1434
1435   if (aiffparse->bytes_per_sample <= 0)
1436     return FALSE;
1437
1438   GST_INFO_OBJECT (aiffparse, "converting value from %s to %s",
1439       gst_format_get_name (src_format), gst_format_get_name (*dest_format));
1440
1441   switch (src_format) {
1442     case GST_FORMAT_BYTES:
1443       switch (*dest_format) {
1444         case GST_FORMAT_DEFAULT:
1445           *dest_value = src_value / aiffparse->bytes_per_sample;
1446           break;
1447         case GST_FORMAT_TIME:
1448           if (aiffparse->bps > 0) {
1449             *dest_value = gst_util_uint64_scale_ceil (src_value, GST_SECOND,
1450                 (guint64) aiffparse->bps);
1451             break;
1452           }
1453           /* Else fallthrough */
1454         default:
1455           res = FALSE;
1456           goto done;
1457       }
1458       break;
1459
1460     case GST_FORMAT_DEFAULT:
1461       switch (*dest_format) {
1462         case GST_FORMAT_BYTES:
1463           *dest_value = src_value * aiffparse->bytes_per_sample;
1464           break;
1465         case GST_FORMAT_TIME:
1466           *dest_value = gst_util_uint64_scale (src_value, GST_SECOND,
1467               (guint64) aiffparse->rate);
1468           break;
1469         default:
1470           res = FALSE;
1471           goto done;
1472       }
1473       break;
1474
1475     case GST_FORMAT_TIME:
1476       switch (*dest_format) {
1477         case GST_FORMAT_BYTES:
1478           if (aiffparse->bps > 0) {
1479             *dest_value = gst_util_uint64_scale (src_value,
1480                 (guint64) aiffparse->bps, GST_SECOND);
1481             break;
1482           }
1483           /* Else fallthrough */
1484           break;
1485         case GST_FORMAT_DEFAULT:
1486           *dest_value = gst_util_uint64_scale (src_value,
1487               (guint64) aiffparse->rate, GST_SECOND);
1488           break;
1489         default:
1490           res = FALSE;
1491           goto done;
1492       }
1493       break;
1494
1495     default:
1496       res = FALSE;
1497       goto done;
1498   }
1499
1500 done:
1501   return res;
1502
1503 }
1504
1505 /* handle queries for location and length in requested format */
1506 static gboolean
1507 gst_aiff_parse_pad_query (GstPad * pad, GstObject * parent, GstQuery * query)
1508 {
1509   gboolean res = TRUE;
1510   GstAiffParse *aiff = GST_AIFF_PARSE (parent);
1511
1512   /* only if we know */
1513   if (aiff->state != AIFF_PARSE_DATA) {
1514     return FALSE;
1515   }
1516
1517   switch (GST_QUERY_TYPE (query)) {
1518     case GST_QUERY_DURATION:
1519     {
1520       gint64 duration = 0;
1521       GstFormat format;
1522
1523       gst_query_parse_duration (query, &format, NULL);
1524
1525       switch (format) {
1526         case GST_FORMAT_TIME:{
1527           if ((res = gst_aiff_parse_calculate_duration (aiff))) {
1528             duration = aiff->duration;
1529           }
1530           break;
1531         }
1532         default:
1533           format = GST_FORMAT_BYTES;
1534           duration = aiff->datasize;
1535           break;
1536       }
1537       gst_query_set_duration (query, format, duration);
1538       break;
1539     }
1540     case GST_QUERY_CONVERT:
1541     {
1542       gint64 srcvalue, dstvalue;
1543       GstFormat srcformat, dstformat;
1544
1545       gst_query_parse_convert (query, &srcformat, &srcvalue,
1546           &dstformat, &dstvalue);
1547       res = gst_aiff_parse_pad_convert (pad, srcformat, srcvalue,
1548           &dstformat, &dstvalue);
1549       if (res)
1550         gst_query_set_convert (query, srcformat, srcvalue, dstformat, dstvalue);
1551       break;
1552     }
1553     case GST_QUERY_SEEKING:{
1554       GstFormat fmt;
1555
1556       gst_query_parse_seeking (query, &fmt, NULL, NULL, NULL);
1557       if (fmt == GST_FORMAT_TIME) {
1558         gboolean seekable = TRUE;
1559
1560         if (!gst_aiff_parse_calculate_duration (aiff)) {
1561           seekable = FALSE;
1562         }
1563         gst_query_set_seeking (query, GST_FORMAT_TIME, seekable,
1564             0, aiff->duration);
1565         res = TRUE;
1566       }
1567       break;
1568     }
1569     default:
1570       res = gst_pad_query_default (pad, parent, query);
1571       break;
1572   }
1573   return res;
1574 }
1575
1576 static gboolean
1577 gst_aiff_parse_srcpad_event (GstPad * pad, GstObject * parent, GstEvent * event)
1578 {
1579   GstAiffParse *aiffparse = GST_AIFF_PARSE (parent);
1580   gboolean res = FALSE;
1581
1582   GST_DEBUG_OBJECT (aiffparse, "%s event", GST_EVENT_TYPE_NAME (event));
1583
1584   switch (GST_EVENT_TYPE (event)) {
1585     case GST_EVENT_SEEK:
1586       /* can only handle events when we are in the data state */
1587       if (aiffparse->state == AIFF_PARSE_DATA) {
1588         res = gst_aiff_parse_perform_seek (aiffparse, event);
1589       }
1590       gst_event_unref (event);
1591       break;
1592     default:
1593       res = gst_pad_push_event (aiffparse->sinkpad, event);
1594       break;
1595   }
1596   return res;
1597 }
1598
1599 static gboolean
1600 gst_aiff_parse_sink_activate (GstPad * sinkpad, GstObject * parent)
1601 {
1602   GstQuery *query;
1603   gboolean pull_mode;
1604
1605   query = gst_query_new_scheduling ();
1606
1607   if (!gst_pad_peer_query (sinkpad, query)) {
1608     gst_query_unref (query);
1609     goto activate_push;
1610   }
1611
1612   pull_mode = gst_query_has_scheduling_mode_with_flags (query,
1613       GST_PAD_MODE_PULL, GST_SCHEDULING_FLAG_SEEKABLE);
1614   gst_query_unref (query);
1615
1616   if (!pull_mode)
1617     goto activate_push;
1618
1619   GST_DEBUG_OBJECT (sinkpad, "going to pull mode");
1620   return gst_pad_activate_mode (sinkpad, GST_PAD_MODE_PULL, TRUE);
1621
1622 activate_push:
1623   {
1624     GST_DEBUG_OBJECT (sinkpad, "going to push (streaming) mode");
1625     return gst_pad_activate_mode (sinkpad, GST_PAD_MODE_PUSH, TRUE);
1626   }
1627 }
1628
1629
1630 static gboolean
1631 gst_aiff_parse_sink_activate_mode (GstPad * sinkpad, GstObject * parent,
1632     GstPadMode mode, gboolean active)
1633 {
1634   gboolean res;
1635   GstAiffParse *aiff = GST_AIFF_PARSE (parent);
1636
1637   if (aiff->adapter)
1638     g_object_unref (aiff->adapter);
1639
1640   switch (mode) {
1641     case GST_PAD_MODE_PUSH:
1642       aiff->streaming = TRUE;
1643       aiff->adapter = gst_adapter_new ();
1644       res = TRUE;
1645       break;
1646     case GST_PAD_MODE_PULL:
1647       if (active) {
1648         aiff->streaming = FALSE;
1649         aiff->adapter = NULL;
1650         aiff->segment_running = TRUE;
1651         res =
1652             gst_pad_start_task (sinkpad, (GstTaskFunction) gst_aiff_parse_loop,
1653             sinkpad, NULL);
1654       } else {
1655         aiff->segment_running = FALSE;
1656         res = gst_pad_stop_task (sinkpad);
1657       }
1658       break;
1659     default:
1660       res = FALSE;
1661       break;
1662   }
1663   return res;
1664 };
1665
1666 static GstStateChangeReturn
1667 gst_aiff_parse_change_state (GstElement * element, GstStateChange transition)
1668 {
1669   GstStateChangeReturn ret;
1670   GstAiffParse *aiff = GST_AIFF_PARSE (element);
1671
1672   switch (transition) {
1673     case GST_STATE_CHANGE_NULL_TO_READY:
1674       break;
1675     case GST_STATE_CHANGE_READY_TO_PAUSED:
1676       gst_aiff_parse_reset (aiff);
1677       break;
1678     case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
1679       break;
1680     default:
1681       break;
1682   }
1683
1684   ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
1685
1686   switch (transition) {
1687     case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
1688       break;
1689     case GST_STATE_CHANGE_PAUSED_TO_READY:
1690       gst_aiff_parse_reset (aiff);
1691       break;
1692     case GST_STATE_CHANGE_READY_TO_NULL:
1693       break;
1694     default:
1695       break;
1696   }
1697   return ret;
1698 }