[Swfdec] 6 commits - libswfdec/Makefile.am libswfdec/swfdec_audio_flv.c libswfdec/swfdec_audio_flv.h libswfdec/swfdec_audio_stream.c libswfdec/swfdec_audio_stream.h libswfdec/swfdec_buffer.c libswfdec/swfdec_codec_adpcm.c libswfdec/swfdec_codec_audio.c libswfdec/swfdec_codec_audio.h libswfdec/swfdec_codec.c libswfdec/swfdec_codec_ffmpeg.c libswfdec/swfdec_codec.h libswfdec/swfdec_codec_mad.c libswfdec/swfdec_flv_decoder.c libswfdec/swfdec_flv_decoder.h libswfdec/swfdec_js.c libswfdec/swfdec_script.c libswfdec/swfdec_sound.c libswfdec/swfdec_sound.h libswfdec/swfdec_sprite_movie.c

Benjamin Otte company at kemper.freedesktop.org
Sun Apr 8 02:17:15 PDT 2007


 libswfdec/Makefile.am           |   10 -
 libswfdec/swfdec_audio_flv.c    |   55 ++++-----
 libswfdec/swfdec_audio_flv.h    |    8 -
 libswfdec/swfdec_audio_stream.c |   64 +++++-----
 libswfdec/swfdec_audio_stream.h |   10 -
 libswfdec/swfdec_buffer.c       |   10 +
 libswfdec/swfdec_codec.c        |  142 -----------------------
 libswfdec/swfdec_codec.h        |   58 ---------
 libswfdec/swfdec_codec_adpcm.c  |  154 ++++++-------------------
 libswfdec/swfdec_codec_audio.c  |  244 ++++++++++++++++++++++++++++++++++++++++
 libswfdec/swfdec_codec_audio.h  |   60 +++++++++
 libswfdec/swfdec_codec_ffmpeg.c |  124 ++++++++++----------
 libswfdec/swfdec_codec_mad.c    |  123 ++++++++++----------
 libswfdec/swfdec_flv_decoder.c  |    1 
 libswfdec/swfdec_flv_decoder.h  |    2 
 libswfdec/swfdec_js.c           |   14 +-
 libswfdec/swfdec_script.c       |   19 ++-
 libswfdec/swfdec_sound.c        |   42 ++----
 libswfdec/swfdec_sound.h        |    2 
 libswfdec/swfdec_sprite_movie.c |    8 -
 20 files changed, 602 insertions(+), 548 deletions(-)

New commits:
diff-tree 01bf0e400ee99da0e96707f606d41bb23d5a8b48 (from d137c59170a750a5155ee4a86a8d6a5922807770)
Author: Benjamin Otte <otte at gnome.org>
Date:   Sun Apr 8 11:07:02 2007 +0200

    eval "/:foo" too

diff --git a/libswfdec/swfdec_js.c b/libswfdec/swfdec_js.c
index 350d891..9e5b594 100644
--- a/libswfdec/swfdec_js.c
+++ b/libswfdec/swfdec_js.c
@@ -240,6 +240,8 @@ swfdec_js_slash_to_dot (const char *slas
 
   if (*cur == '/') {
     g_string_append (str, "_root");
+    if (cur[1] == ':')
+      cur++;
   } else {
     goto start;
   }
diff-tree d137c59170a750a5155ee4a86a8d6a5922807770 (from db9f11b9b1f4ba2aa1122c94d0dc8ac459a074d1)
Author: Benjamin Otte <otte at gnome.org>
Date:   Sun Apr 8 11:06:26 2007 +0200

    implement StringEquals action

diff --git a/libswfdec/swfdec_script.c b/libswfdec/swfdec_script.c
index d8ce1ad..5163ce7 100644
--- a/libswfdec/swfdec_script.c
+++ b/libswfdec/swfdec_script.c
@@ -360,7 +360,8 @@ swfdec_action_goto_frame (JSContext *cx,
   }
   frame = GUINT16_FROM_LE (*((guint16 *) data));
   if (movie) {
-    swfdec_movie_goto (movie, frame);
+    if (frame < movie->n_frames)
+      swfdec_movie_goto (movie, frame);
     movie->stopped = TRUE;
   } else {
     SWFDEC_ERROR ("no movie to goto on");
@@ -1185,6 +1186,20 @@ swfdec_action_not_5 (JSContext *cx, guin
 }
 
 static JSBool
+swfdec_action_string_equals (JSContext *cx, guint action, const guint8 *data, guint len)
+{
+  JSString *lval, *rval;
+
+  if (!(rval = JS_ValueToString (cx, cx->fp->sp[-1])) ||
+      !(lval = JS_ValueToString (cx, cx->fp->sp[-2])))
+    return JS_FALSE;
+
+  cx->fp->sp--;
+  cx->fp->sp[-1] = BOOLEAN_TO_JSVAL (js_CompareStrings (rval, lval) == 0);
+  return JS_TRUE;
+}
+
+static JSBool
 swfdec_action_jump (JSContext *cx, guint action, const guint8 *data, guint len)
 {
   if (len != 2) {
@@ -2507,7 +2522,7 @@ static const SwfdecActionSpec actions[25
   [0x10] = { "And", NULL, 2, 1, { NULL, /* FIXME */NULL, swfdec_action_logical_5, swfdec_action_logical_5, swfdec_action_logical_7 } },
   [0x11] = { "Or", NULL, 2, 1, { NULL, /* FIXME */NULL, swfdec_action_logical_5, swfdec_action_logical_5, swfdec_action_logical_7 } },
   [0x12] = { "Not", NULL, 1, 1, { NULL, swfdec_action_not_4, swfdec_action_not_5, swfdec_action_not_5, swfdec_action_not_5 } },
-  [0x13] = { "StringEquals", NULL },
+  [0x13] = { "StringEquals", NULL, 2, 1, { NULL, swfdec_action_string_equals, swfdec_action_string_equals, swfdec_action_string_equals, swfdec_action_string_equals } },
   [0x14] = { "StringLength", NULL },
   [0x15] = { "StringExtract", NULL },
   [0x17] = { "Pop", NULL, 1, 0, { NULL, swfdec_action_pop, swfdec_action_pop, swfdec_action_pop, swfdec_action_pop } },
diff-tree db9f11b9b1f4ba2aa1122c94d0dc8ac459a074d1 (from e869d0ff88487c7f8998b190b849d7cb174fcaa4)
Author: Benjamin Otte <otte at gnome.org>
Date:   Sun Apr 8 10:53:30 2007 +0200

    only spawn a new audio stream if there really is something to decode

diff --git a/libswfdec/swfdec_sprite_movie.c b/libswfdec/swfdec_sprite_movie.c
index a114315..81ad295 100644
--- a/libswfdec/swfdec_sprite_movie.c
+++ b/libswfdec/swfdec_sprite_movie.c
@@ -293,9 +293,11 @@ new_decoder:
     g_object_unref (movie->sound_stream);
   }
 
-  movie->sound_stream = swfdec_audio_stream_new (player, 
-      movie->sprite, movie->current_frame);
-  movie->sound_frame = movie->current_frame;
+  if (current->sound_block) {
+    movie->sound_stream = swfdec_audio_stream_new (player, 
+	movie->sprite, movie->current_frame);
+    movie->sound_frame = movie->current_frame;
+  }
   return TRUE;
 }
 
diff-tree e869d0ff88487c7f8998b190b849d7cb174fcaa4 (from f62be51acb786924ee781a1114c51852dc6816ac)
Author: Benjamin Otte <otte at gnome.org>
Date:   Sun Apr 8 10:52:53 2007 +0200

    add initial support to eval Flash 4 properties with ':'

diff --git a/libswfdec/swfdec_js.c b/libswfdec/swfdec_js.c
index 5ec2303..350d891 100644
--- a/libswfdec/swfdec_js.c
+++ b/libswfdec/swfdec_js.c
@@ -243,7 +243,7 @@ swfdec_js_slash_to_dot (const char *slas
   } else {
     goto start;
   }
-  while (cur && *cur == '/') {
+  while (cur && (*cur == '/' || *cur == ':')) {
     cur++;
 start:
     if (str->len > 0)
@@ -257,8 +257,14 @@ start:
 	g_string_append_len (str, cur, slash - cur);
 	cur = slash;
       } else {
-	g_string_append (str, cur);
-	cur = NULL;
+	slash = strchr (cur, ':');
+	if (slash) {
+	  g_string_append_len (str, cur, slash - cur);
+	  cur = slash;
+	} else {
+	  g_string_append (str, cur);
+	  cur = NULL;
+	}
       }
     }
     /* cur should now point to the slash */
diff-tree f62be51acb786924ee781a1114c51852dc6816ac (from 98188d1d5062c367332e9cc2ba49a01020e074e1)
Author: Benjamin Otte <otte at gnome.org>
Date:   Sun Apr 8 10:52:06 2007 +0200

    document swfdec_buffer_queue_pull_buffer

diff --git a/libswfdec/swfdec_buffer.c b/libswfdec/swfdec_buffer.c
index babf3ac..86c00a6 100644
--- a/libswfdec/swfdec_buffer.c
+++ b/libswfdec/swfdec_buffer.c
@@ -353,6 +353,16 @@ swfdec_buffer_queue_push (SwfdecBufferQu
   queue->depth += buffer->length;
 }
 
+/**
+ * swfdec_buffer_queue_pull_buffer:
+ * @queue: a #SwfdecBufferQueue
+ *
+ * Pulls the first buffer out of @queue and returns it. This function is 
+ * equivalent to calling swfdec_buffer_queue_pull() with the size of the
+ * first buffer in it.
+ *
+ * Returns: The first buffer in @queue or %NULL if @queue is empty.
+ **/
 SwfdecBuffer *
 swfdec_buffer_queue_pull_buffer (SwfdecBufferQueue * queue)
 {
diff-tree 98188d1d5062c367332e9cc2ba49a01020e074e1 (from f9ed2528c36837320c94bb1fec2313445c85c886)
Author: Benjamin Otte <otte at gnome.org>
Date:   Sun Apr 8 10:51:46 2007 +0200

    update the audio codec subsystem
    
    Much cleaner API now and should be suitable for hooking in GStreamer

diff --git a/libswfdec/Makefile.am b/libswfdec/Makefile.am
index fa1abb6..352d46b 100644
--- a/libswfdec/Makefile.am
+++ b/libswfdec/Makefile.am
@@ -4,15 +4,15 @@ DIST_SUBDIRS = jpeg js 
 
 CODECS =
 
-if HAVE_MAD
-CODECS += swfdec_codec_mad.c
-endif
 if HAVE_FFMPEG
 CODECS += swfdec_codec_ffmpeg.c
 endif
 if HAVE_GST
 CODECS += swfdec_codec_gst.c
 endif
+if HAVE_MAD
+CODECS += swfdec_codec_mad.c
+endif
 
 lib_LTLIBRARIES = libswfdec- at SWFDEC_MAJORMINOR@.la
 
@@ -31,8 +31,8 @@ libswfdec_ at SWFDEC_MAJORMINOR@_la_SOURCES
 	swfdec_cache.c \
 	swfdec_cached.c \
 	swfdec_character.c \
-	swfdec_codec.c \
 	swfdec_codec_adpcm.c \
+	swfdec_codec_audio.c \
 	$(CODECS) \
 	swfdec_codec_screen.c \
 	swfdec_codec_video.c \
@@ -122,7 +122,7 @@ noinst_HEADERS = \
 	swfdec_cache.h \
 	swfdec_cached.h \
 	swfdec_character.h \
-	swfdec_codec.h \
+	swfdec_codec_audio.h \
 	swfdec_codec_video.h \
 	swfdec_color.h \
 	swfdec_connection.h \
diff --git a/libswfdec/swfdec_audio_flv.c b/libswfdec/swfdec_audio_flv.c
index feb6b57..bdca2c2 100644
--- a/libswfdec/swfdec_audio_flv.c
+++ b/libswfdec/swfdec_audio_flv.c
@@ -35,10 +35,8 @@ swfdec_audio_flv_dispose (GObject *objec
   SwfdecAudioFlv *flv = SWFDEC_AUDIO_FLV (object);
 
   if (flv->decoder != NULL) {
-    SwfdecBuffer *buffer = swfdec_audio_codec_finish (flv->codec, flv->decoder);
+    swfdec_audio_decoder_free (flv->decoder);
     flv->decoder = NULL;
-    if (buffer)
-      swfdec_buffer_unref (buffer);
   }
   g_queue_foreach (flv->playback_queue, (GFunc) swfdec_buffer_unref, NULL);
   g_queue_free (flv->playback_queue);
@@ -69,15 +67,13 @@ swfdec_audio_flv_decode_one (SwfdecAudio
 	(guint) SWFDEC_TICKS_TO_MSECS (flv->timestamp), 
 	flv->next_timestamp, flv->playback_skip);
   }
-next:
-  if (flv->out && flv->next_timestamp == 0) {
-    if (flv->decoder == NULL)
+  if (flv->decoder)
+    buffer = swfdec_audio_decoder_pull (flv->decoder);
+  else
+    buffer = NULL;
+  while (buffer == NULL) {
+    if (flv->decoder && flv->next_timestamp == 0)
       return NULL;
-    buffer = swfdec_audio_codec_finish (flv->codec, flv->decoder);
-    flv->decoder = NULL;
-    if (buffer == NULL)
-      return NULL;
-  } else {
     buffer = swfdec_flv_decoder_get_audio (flv->flvdecoder, flv->next_timestamp,
       &format, &width, &in, &now, &soon);
 
@@ -92,31 +88,27 @@ next:
     if (flv->in == 0) {
       /* init */
       if (flv->decoder) {
-	swfdec_audio_codec_finish (flv->codec, flv->decoder);
+	swfdec_audio_decoder_free (flv->decoder);
 	flv->decoder = NULL;
       }
       flv->format = format;
       flv->width = width;
       flv->in = in;
-      flv->codec = swfdec_codec_get_audio (flv->format);
-      if (flv->codec) {
-	flv->decoder = swfdec_audio_codec_init (flv->codec, flv->format, flv->width, flv->in);
-	flv->out = swfdec_audio_codec_get_format (flv->codec, flv->decoder);
-      }
+      flv->decoder = swfdec_audio_decoder_new (flv->format, flv->width, flv->in);
+      if (flv->decoder == NULL)
+	return NULL;
     } else if (format != flv->format ||
 	width != flv->width ||
 	in != flv->in) {
       SWFDEC_ERROR ("FIXME: format change not implemented");
       return NULL;
     }
-    if (flv->decoder == NULL)
-      return NULL;
-    buffer = swfdec_audio_codec_decode (flv->codec, flv->decoder, buffer);
-    if (buffer == NULL)
-      goto next;
+    swfdec_audio_decoder_push (flv->decoder, buffer);
+    if (flv->next_timestamp == 0)
+      swfdec_audio_decoder_push (flv->decoder, NULL);
+    buffer = swfdec_audio_decoder_pull (flv->decoder);
   }
 
-  g_assert (buffer);
   g_queue_push_tail (flv->playback_queue, buffer);
   return buffer;
 }
@@ -144,7 +136,8 @@ swfdec_audio_flv_render (SwfdecAudio *au
       if (!buffer)
 	break;
     }
-    samples = swfdec_sound_buffer_get_n_samples (buffer, flv->out);
+    samples = swfdec_sound_buffer_get_n_samples (buffer, 
+	swfdec_audio_decoder_get_format (flv->decoder));
     if (start) {
       if (samples <= start) {
 	start -= samples;
@@ -157,7 +150,9 @@ swfdec_audio_flv_render (SwfdecAudio *au
       SWFDEC_LOG ("rendering %u samples", samples);
     }
     samples = MIN (samples, n_samples);
-    swfdec_sound_buffer_render (dest, buffer, flv->out, previous, start, samples);
+    swfdec_sound_buffer_render (dest, buffer, 
+	swfdec_audio_decoder_get_format (flv->decoder), previous, start, 
+	samples);
     start = 0;
     n_samples -= samples;
     dest += 2 * samples;
@@ -175,12 +170,14 @@ swfdec_audio_flv_iterate (SwfdecAudio *a
   flv->playback_skip += remove;
   buffer = g_queue_peek_head (flv->playback_queue);
   while (buffer && flv->playback_skip >= 
-	 swfdec_sound_buffer_get_n_samples (buffer, flv->out) 
-	 + SWFDEC_AUDIO_OUT_GRANULARITY (flv->out)) {
+	 swfdec_sound_buffer_get_n_samples (buffer, swfdec_audio_decoder_get_format (flv->decoder)) 
+	 + SWFDEC_AUDIO_OUT_GRANULARITY (swfdec_audio_decoder_get_format (flv->decoder))) {
     buffer = g_queue_pop_head (flv->playback_queue);
     SWFDEC_LOG ("removing buffer with %u samples", 
-	swfdec_sound_buffer_get_n_samples (buffer, flv->out));
-    flv->playback_skip -= swfdec_sound_buffer_get_n_samples (buffer, flv->out);
+	swfdec_sound_buffer_get_n_samples (buffer, 
+	  swfdec_audio_decoder_get_format (flv->decoder)));
+    flv->playback_skip -= swfdec_sound_buffer_get_n_samples (buffer, 
+	swfdec_audio_decoder_get_format (flv->decoder));
     swfdec_buffer_unref (buffer);
     buffer = g_queue_peek_head (flv->playback_queue);
   }
diff --git a/libswfdec/swfdec_audio_flv.h b/libswfdec/swfdec_audio_flv.h
index 5a41edc..8e4c5a5 100644
--- a/libswfdec/swfdec_audio_flv.h
+++ b/libswfdec/swfdec_audio_flv.h
@@ -41,15 +41,13 @@ struct _SwfdecAudioFlv
 
   SwfdecFlvDecoder *	flvdecoder;	/* decoder we play back */
   SwfdecAudioFormat	format;		/* codec format of audio */
-  const SwfdecAudioCodec *codec;      	/* codec in use */
   gboolean		width;		/* width of audio */
   SwfdecAudioOut	in;		/* input format of data */
-  SwfdecAudioOut	out;		/* output format of codec */
-  gpointer		decoder;	/* decoder used for playback */
+  SwfdecAudioDecoder *	decoder;	/* decoder used for playback */
 
   SwfdecTick		timestamp;	/* current playback timestamp */
-  guint		next_timestamp;	/* next timestamp in FLV file we request from */
-  guint		playback_skip;	/* number of samples to skip at start of queue */
+  guint			next_timestamp;	/* next timestamp in FLV file we request from */
+  guint			playback_skip;	/* number of samples to skip at start of queue */
   GQueue *		playback_queue;	/* all the samples we've decoded so far */
 };
 
diff --git a/libswfdec/swfdec_audio_stream.c b/libswfdec/swfdec_audio_stream.c
index b2c7fd3..b03ef14 100644
--- a/libswfdec/swfdec_audio_stream.c
+++ b/libswfdec/swfdec_audio_stream.c
@@ -38,10 +38,8 @@ swfdec_audio_stream_dispose (GObject *ob
   SwfdecAudioStream *stream = SWFDEC_AUDIO_STREAM (object);
 
   if (stream->decoder != NULL) {
-    SwfdecBuffer *buffer = swfdec_audio_codec_finish (stream->codec, stream->decoder);
+    swfdec_audio_decoder_free (stream->decoder);
     stream->decoder = NULL;
-    if (buffer)
-      swfdec_buffer_unref (buffer);
   }
   g_queue_foreach (stream->playback_queue, (GFunc) swfdec_buffer_unref, NULL);
   g_queue_free (stream->playback_queue);
@@ -56,34 +54,31 @@ swfdec_audio_stream_decode_one (SwfdecAu
   SwfdecBuffer *buffer;
 
   g_assert (!stream->done);
-  while (!stream->done) {
+  while (!(buffer = swfdec_audio_decoder_pull (stream->decoder)) &&
+         !stream->done) {
     if (stream->current_frame >= stream->sprite->n_frames)
-      break;
+      goto end;
     frame = &stream->sprite->frames[stream->current_frame];
     stream->current_frame++;
     if (frame->sound_head != stream->sound) 
-      break;
+      goto end;
     if (frame->sound_samples == 0)
       continue;
-    /* FIXME: with this method and mad not giving out full samples, we end up 
+    /* FIXME: with this method and mad/gst not giving out full samples, we end up 
      * putting silence too early */
     if (frame->sound_block) {
-      buffer = swfdec_audio_codec_decode (stream->codec, stream->decoder, frame->sound_block);
-      if (buffer == NULL)
-	continue;
+      swfdec_audio_decoder_push (stream->decoder, frame->sound_block);
+      continue;
     } else {
-      /* wanna speed this up by not allocating buffers? */
-      buffer = swfdec_buffer_new_and_alloc (frame->sound_samples * 4);
-      memset (buffer->data, 0, buffer->length);
+      SWFDEC_DEBUG ("frame %u has no sound block, inserting %u samples of silence", 
+	  stream->current_frame - 1, frame->sound_samples);
+      buffer = swfdec_buffer_new_and_alloc0 (4 * frame->sound_samples);
+      break;
     }
-    g_queue_push_tail (stream->playback_queue, buffer);
-    return buffer;
+end:
+    swfdec_audio_decoder_push (stream->decoder, NULL);
+    stream->done = TRUE;
   }
-  buffer = swfdec_audio_codec_finish (stream->codec, stream->decoder);
-  stream->decoder = NULL;
-  stream->done = TRUE;
-  if (buffer)
-    g_queue_push_tail (stream->playback_queue, buffer);
   return buffer;
 }
 
@@ -111,8 +106,10 @@ swfdec_audio_stream_render (SwfdecAudio 
       buffer = swfdec_audio_stream_decode_one (stream);
       if (!buffer)
 	break;
+      g_queue_push_tail (stream->playback_queue, buffer);
     }
-    samples = swfdec_sound_buffer_get_n_samples (buffer, stream->format);
+    samples = swfdec_sound_buffer_get_n_samples (buffer, 
+	swfdec_audio_decoder_get_format (stream->decoder));
     if (start) {
       if (samples <= start) {
 	start -= samples;
@@ -125,7 +122,9 @@ swfdec_audio_stream_render (SwfdecAudio 
       SWFDEC_LOG ("rendering %u samples", samples);
     }
     samples = MIN (samples, n_samples);
-    swfdec_sound_buffer_render (dest, buffer, stream->format, previous, start, samples);
+    swfdec_sound_buffer_render (dest, buffer, 
+	swfdec_audio_decoder_get_format (stream->decoder), 
+	previous, start, samples);
     start = 0;
     n_samples -= samples;
     dest += 2 * samples;
@@ -142,12 +141,14 @@ swfdec_audio_stream_iterate (SwfdecAudio
   stream->playback_skip += remove;
   buffer = g_queue_peek_head (stream->playback_queue);
   while (buffer && stream->playback_skip >= 
-	 swfdec_sound_buffer_get_n_samples (buffer, stream->format) 
-	 + SWFDEC_AUDIO_OUT_GRANULARITY (stream->format)) {
+	 swfdec_sound_buffer_get_n_samples (buffer, swfdec_audio_decoder_get_format (stream->decoder)) 
+	 + SWFDEC_AUDIO_OUT_GRANULARITY (swfdec_audio_decoder_get_format (stream->decoder))) {
     buffer = g_queue_pop_head (stream->playback_queue);
     SWFDEC_LOG ("removing buffer with %u samples", 
-	swfdec_sound_buffer_get_n_samples (buffer, stream->format));
-    stream->playback_skip -= swfdec_sound_buffer_get_n_samples (buffer, stream->format);
+	swfdec_sound_buffer_get_n_samples (buffer, 
+	  swfdec_audio_decoder_get_format (stream->decoder)));
+    stream->playback_skip -= swfdec_sound_buffer_get_n_samples (buffer, 
+	swfdec_audio_decoder_get_format (stream->decoder));
     swfdec_buffer_unref (buffer);
     buffer = g_queue_peek_head (stream->playback_queue);
   }
@@ -157,9 +158,10 @@ swfdec_audio_stream_iterate (SwfdecAudio
   } else {
     GList *walk;
     guint ret = 0;
+    SwfdecAudioOut format = swfdec_audio_decoder_get_format (stream->decoder);
     
     for (walk = g_queue_peek_head_link (stream->playback_queue); walk; walk = walk->next) {
-      ret += swfdec_sound_buffer_get_n_samples (walk->data, stream->format);
+      ret += swfdec_sound_buffer_get_n_samples (walk->data, format);
     }
     return ret - stream->playback_skip;
   }
@@ -199,12 +201,8 @@ swfdec_audio_stream_new (SwfdecPlayer *p
   stream->sound = frame->sound_head;
   stream->playback_skip = frame->sound_skip;
   stream->current_frame = start_frame;
-  stream->codec = swfdec_codec_get_audio (stream->sound->format);
-  if (stream->codec)
-    stream->decoder = swfdec_audio_codec_init (stream->codec, 
-	stream->sound->format, stream->sound->width, stream->sound->original_format);
-  if (stream->decoder)
-    stream->format = swfdec_audio_codec_get_format (stream->codec, stream->decoder);
+  stream->decoder = swfdec_audio_decoder_new (stream->sound->format, 
+      stream->sound->width, stream->sound->original_format);
   swfdec_audio_add (SWFDEC_AUDIO (stream), player);
 
   return SWFDEC_AUDIO (stream);
diff --git a/libswfdec/swfdec_audio_stream.h b/libswfdec/swfdec_audio_stream.h
index 9d31b3c..306c9c8 100644
--- a/libswfdec/swfdec_audio_stream.h
+++ b/libswfdec/swfdec_audio_stream.h
@@ -23,7 +23,7 @@
 #define _SWFDEC_AUDIO_STREAM_H_
 
 #include <libswfdec/swfdec_audio_internal.h>
-#include <libswfdec/swfdec_codec.h>
+#include <libswfdec/swfdec_codec_audio.h>
 
 G_BEGIN_DECLS
 
@@ -43,12 +43,10 @@ struct _SwfdecAudioStream
 
   SwfdecSprite *	sprite;		/* sprite we're playing back */
   SwfdecSound *		sound;	      	/* sound we're playing */
-  const SwfdecAudioCodec *codec;	/* codec used by this stream */
-  gpointer		decoder;	/* decoder used for this frame */
-  SwfdecAudioOut	format;		/* format used by decoder */
-  guint		playback_skip;	/* number of samples to skip at the beginning of queue */
+  SwfdecAudioDecoder *	decoder;	/* decoder used for this frame */
+  guint			playback_skip;	/* number of samples to skip at the beginning of queue */
   GQueue *		playback_queue;	/* all the samples we've decoded so far */
-  guint		current_frame;	/* last decoded frame */
+  guint			current_frame;	/* last decoded frame */
   gboolean		done;		/* TRUE when no new data will be made available */
 };
 
diff --git a/libswfdec/swfdec_codec.c b/libswfdec/swfdec_codec.c
deleted file mode 100644
index 32ad9cc..0000000
--- a/libswfdec/swfdec_codec.c
+++ /dev/null
@@ -1,142 +0,0 @@
-/* Swfdec
- * Copyright (C) 2006 Benjamin Otte <otte at gnome.org>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- * 
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- * 
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, 
- * Boston, MA  02110-1301  USA
- */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "swfdec_codec.h"
-#include "swfdec_debug.h"
-
-/*** DECODER LIST ***/
-
-extern const SwfdecAudioCodec swfdec_codec_adpcm;
-
-#ifdef HAVE_MAD
-extern const SwfdecAudioCodec swfdec_codec_mad;
-#endif
-
-#ifdef HAVE_FFMPEG
-extern const SwfdecAudioCodec swfdec_codec_ffmpeg_audio;
-#endif
-
-/*** UNCOMPRESSED SOUND ***/
-
-#define U8_FLAG (0x10000)
-static gpointer
-swfdec_codec_uncompressed_init (SwfdecAudioFormat type, gboolean width, SwfdecAudioOut format)
-{
-  guint ret = format;
-  if (!width)
-    ret |= U8_FLAG;
-  return GUINT_TO_POINTER (ret);
-}
-
-static SwfdecBuffer *
-swfdec_codec_uncompressed_decode_8bit (SwfdecBuffer *buffer)
-{
-  SwfdecBuffer *ret = swfdec_buffer_new_and_alloc (buffer->length * 2);
-  gint16 *out = (gint16 *) ret->data;
-  guint8 *in = buffer->data;
-  guint count = buffer->length;
-  guint i;
-
-  for (i = 0; i < count; i++) {
-    *out = ((gint16) *in << 8) ^ (-1);
-    out++;
-    in++;
-  }
-  return ret;
-}
-
-static SwfdecBuffer *
-swfdec_codec_uncompressed_decode_16bit (SwfdecBuffer *buffer)
-{
-  swfdec_buffer_ref (buffer);
-  return buffer;
-}
-
-static SwfdecAudioOut
-swfdec_codec_uncompressed_get_format (gpointer codec_data)
-{
-  guint format = GPOINTER_TO_UINT (codec_data);
-  return format & ~U8_FLAG;
-}
-
-static SwfdecBuffer *
-swfdec_codec_uncompressed_decode (gpointer codec_data, SwfdecBuffer *buffer)
-{
-  guint data = GPOINTER_TO_UINT (codec_data);
-  if (data & U8_FLAG) {
-    return swfdec_codec_uncompressed_decode_8bit (buffer);
-  } else {
-    return swfdec_codec_uncompressed_decode_16bit (buffer);
-  }
-}
-
-static SwfdecBuffer *
-swfdec_codec_uncompressed_finish (gpointer codec_data)
-{
-  return NULL;
-}
-
-static const SwfdecAudioCodec swfdec_codec_uncompressed = {
-  swfdec_codec_uncompressed_init,
-  swfdec_codec_uncompressed_get_format,
-  swfdec_codec_uncompressed_decode,
-  swfdec_codec_uncompressed_finish,
-};
-
-/*** PUBLIC API ***/
-
-const SwfdecAudioCodec *
-swfdec_codec_get_audio (SwfdecAudioFormat format)
-{
-  switch (format) {
-    case SWFDEC_AUDIO_FORMAT_UNDEFINED:
-    case SWFDEC_AUDIO_FORMAT_UNCOMPRESSED:
-      return &swfdec_codec_uncompressed;
-    case SWFDEC_AUDIO_FORMAT_ADPCM:
-      return &swfdec_codec_adpcm;
-#ifdef HAVE_FFMPEG
-      return &swfdec_codec_ffmpeg_audio;
-#else
-      SWFDEC_ERROR ("adpcm sound requires ffmpeg");
-      return NULL;
-#endif
-    case SWFDEC_AUDIO_FORMAT_MP3:
-#ifdef HAVE_MAD
-      return &swfdec_codec_mad;
-#else
-#ifdef HAVE_FFMPEG
-      return &swfdec_codec_ffmpeg_audio;
-#else
-      SWFDEC_ERROR ("mp3 sound requires ffmpeg or mad");
-      return NULL;
-#endif
-#endif
-    case SWFDEC_AUDIO_FORMAT_NELLYMOSER:
-      SWFDEC_ERROR ("Nellymoser sound is not implemented yet");
-      return NULL;
-    default:
-      SWFDEC_ERROR ("undefined sound format %u", format);
-      return NULL;
-  }
-}
-
diff --git a/libswfdec/swfdec_codec.h b/libswfdec/swfdec_codec.h
deleted file mode 100644
index 1920e03..0000000
--- a/libswfdec/swfdec_codec.h
+++ /dev/null
@@ -1,58 +0,0 @@
-/* Swfdec
- * Copyright (C) 2006 Benjamin Otte <otte at gnome.org>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- * 
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- * 
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, 
- * Boston, MA  02110-1301  USA
- */
-
-#ifndef _SWFDEC_CODEC_H_
-#define _SWFDEC_CODEC_H_
-
-#include <glib.h>
-#include <libswfdec/swfdec_audio_internal.h>
-#include <libswfdec/swfdec_buffer.h>
-
-typedef struct _SwfdecAudioCodec SwfdecAudioCodec;
-
-typedef enum {
-  SWFDEC_AUDIO_FORMAT_UNDEFINED = 0,
-  SWFDEC_AUDIO_FORMAT_ADPCM = 1,
-  SWFDEC_AUDIO_FORMAT_MP3 = 2,
-  SWFDEC_AUDIO_FORMAT_UNCOMPRESSED = 3,
-  SWFDEC_AUDIO_FORMAT_NELLYMOSER_8KHZ = 5,
-  SWFDEC_AUDIO_FORMAT_NELLYMOSER = 6
-} SwfdecAudioFormat;
-
-struct _SwfdecAudioCodec {
-  gpointer		(* init)	(SwfdecAudioFormat	type,
-					 gboolean		width,
-					 SwfdecAudioOut		format);
-  SwfdecAudioOut	(* get_format)	(gpointer	        codec_data);
-  /* FIXME: add SwfdecRect *invalid for invalidated region - might make sense for screen? */
-  SwfdecBuffer *	(* decode)	(gpointer		codec_data,
-					 SwfdecBuffer *		buffer);
-  SwfdecBuffer *	(* finish)	(gpointer		codec_data);
-};
-
-const SwfdecAudioCodec *   	swfdec_codec_get_audio		(SwfdecAudioFormat	format);
-
-#define swfdec_audio_codec_init(codec,type,width,format) (codec)->init (type, width, format)
-#define swfdec_audio_codec_get_format(codec, codec_data) (codec)->get_format (codec_data)
-#define swfdec_audio_codec_decode(codec, codec_data, buffer) (codec)->decode (codec_data, buffer)
-#define swfdec_audio_codec_finish(codec, codec_data) (codec)->finish (codec_data)
-
-
-G_END_DECLS
-#endif
diff --git a/libswfdec/swfdec_codec_adpcm.c b/libswfdec/swfdec_codec_adpcm.c
index 20cfc1e..d094968 100644
--- a/libswfdec/swfdec_codec_adpcm.c
+++ b/libswfdec/swfdec_codec_adpcm.c
@@ -21,10 +21,15 @@
 #include "config.h"
 #endif
 
-#include "swfdec_codec.h"
+#include "swfdec_codec_audio.h"
 #include "swfdec_bits.h"
 #include "swfdec_debug.h"
 
+typedef struct {
+  SwfdecAudioDecoder	decoder;
+  SwfdecBufferQueue *	queue;
+} SwfdecAudioDecoderAdpcm;
+
 static const int indexTable[4][16] = {
   { -1, 2 },
   { -1, -1, 2, 4 },
@@ -43,21 +48,9 @@ static const int stepSizeTable[89] = {
     5894, 6484, 7132, 7845, 8630, 9493, 10442, 11487, 12635, 13899,
     15289, 16818, 18500, 20350, 22385, 24623, 27086, 29794, 32767
 };
-    
-static gpointer
-swfdec_codec_adpcm_init (SwfdecAudioFormat type, gboolean width, SwfdecAudioOut format)
-{
-  return GUINT_TO_POINTER ((guint) format);
-}
-
-static SwfdecAudioOut
-swfdec_codec_adpcm_get_format (gpointer data)
-{
-  return GPOINTER_TO_UINT (data);
-}
 
 static SwfdecBuffer *
-swfdec_codec_adpcm_decode_chunk (SwfdecBits *bits, guint n_bits, guint channels)
+swfdec_audio_decoder_adpcm_decode_chunk (SwfdecBits *bits, guint n_bits, guint channels)
 {
   SwfdecBuffer *ret;
   guint len;
@@ -133,124 +126,59 @@ swfdec_codec_adpcm_decode_chunk (SwfdecB
   return ret;
 }
 
-static SwfdecBuffer *
-swfdec_codec_adpcm_decode (gpointer data, SwfdecBuffer *buffer)
+static void
+swfdec_audio_decoder_adpcm_push (SwfdecAudioDecoder *dec, SwfdecBuffer *buffer)
 {
-  SwfdecAudioOut format = GPOINTER_TO_UINT (data);
+  SwfdecAudioDecoderAdpcm *adpcm = (SwfdecAudioDecoderAdpcm *) dec;
   guint channels, n_bits;
   SwfdecBits bits;
-  SwfdecBufferQueue *queue = swfdec_buffer_queue_new ();
 
-  channels = SWFDEC_AUDIO_OUT_N_CHANNELS (format);
+  if (buffer == NULL)
+    return;
+
+  channels = SWFDEC_AUDIO_OUT_N_CHANNELS (dec->out_format);
   swfdec_bits_init (&bits, buffer);
   n_bits = swfdec_bits_getbits (&bits, 2) + 2;
   SWFDEC_DEBUG ("starting decoding: %u channels, %u bits", channels, n_bits);
   /* 22 is minimum required header size */
   while (swfdec_bits_left (&bits) >= 22) {
-    buffer = swfdec_codec_adpcm_decode_chunk (&bits, n_bits, channels);
+    buffer = swfdec_audio_decoder_adpcm_decode_chunk (&bits, n_bits, channels);
     if (buffer)
-      swfdec_buffer_queue_push (queue, buffer);
-  }
-  if (swfdec_buffer_queue_get_depth (queue)) {
-    buffer = swfdec_buffer_queue_pull (queue,
-	swfdec_buffer_queue_get_depth (queue));
-  } else {
-    buffer = NULL;
+      swfdec_buffer_queue_push (adpcm->queue, buffer);
   }
-  swfdec_buffer_queue_unref (queue);
-  return buffer;
 }
 
 static SwfdecBuffer *
-swfdec_codec_adpcm_finish (gpointer data)
+swfdec_audio_decoder_adpcm_pull (SwfdecAudioDecoder *dec)
 {
-  return NULL;
-}
+  SwfdecAudioDecoderAdpcm *adpcm = (SwfdecAudioDecoderAdpcm *) dec;
 
-const SwfdecAudioCodec swfdec_codec_adpcm = {
-  swfdec_codec_adpcm_init,
-  swfdec_codec_adpcm_get_format,
-  swfdec_codec_adpcm_decode,
-  swfdec_codec_adpcm_finish
-};
+  return swfdec_buffer_queue_pull_buffer (adpcm->queue);
+}
 
-#if 0
-void
-adpcm_decoder(indata, outdata, len, state)
-    char indata[];
-    short outdata[];
-    int len;
-    struct adpcm_state *state;
+static void
+swfdec_audio_decoder_adpcm_free (SwfdecAudioDecoder *dec)
 {
-    signed char *inp;		/* Input buffer pointer */
-    short *outp;		/* output buffer pointer */
-    int sign;			/* Current adpcm sign bit */
-    int delta;			/* Current adpcm output value */
-    int step;			/* Stepsize */
-    int valpred;		/* Predicted value */
-    int vpdiff;			/* Current change to valpred */
-    int index;			/* Current step change index */
-    int inputbuffer;		/* place to keep next 4-bit value */
-    int bufferstep;		/* toggle between inputbuffer/input */
-
-    outp = outdata;
-    inp = (signed char *)indata;
-
-    valpred = state->valprev;
-    index = state->index;
-    step = stepSizeTable[index];
-
-    bufferstep = 0;
-    
-    for ( ; len > 0 ; len-- ) {
-	
-	/* Step 1 - get the delta value */
-	if ( bufferstep ) {
-	    delta = inputbuffer & 0xf;
-	} else {
-	    inputbuffer = *inp++;
-	    delta = (inputbuffer >> 4) & 0xf;
-	}
-	bufferstep = !bufferstep;
-
-	/* Step 2 - Find new index value (for later) */
-	index += indexTable[delta];
-	if ( index < 0 ) index = 0;
-	if ( index > 88 ) index = 88;
-
-	/* Step 3 - Separate sign and magnitude */
-	sign = delta & 8;
-	delta = delta & 7;
-
-	/* Step 4 - Compute difference and new predicted value */
-	/*
-	** Computes 'vpdiff = (delta+0.5)*step/4', but see comment
-	** in adpcm_coder.
-	*/
-	vpdiff = step >> 3;
-	if ( delta & 4 ) vpdiff += step;
-	if ( delta & 2 ) vpdiff += step>>1;
-	if ( delta & 1 ) vpdiff += step>>2;
-
-	if ( sign )
-	  valpred -= vpdiff;
-	else
-	  valpred += vpdiff;
-
-	/* Step 5 - clamp output value */
-	if ( valpred > 32767 )
-	  valpred = 32767;
-	else if ( valpred < -32768 )
-	  valpred = -32768;
+  SwfdecAudioDecoderAdpcm *adpcm = (SwfdecAudioDecoderAdpcm *) dec;
 
-	/* Step 6 - Update step value */
-	step = stepSizeTable[index];
+  swfdec_buffer_queue_unref (adpcm->queue);
+  g_slice_free (SwfdecAudioDecoderAdpcm, adpcm);
+}
 
-	/* Step 7 - Output value */
-	*outp++ = valpred;
-    }
+SwfdecAudioDecoder *
+swfdec_audio_decoder_adpcm_new (SwfdecAudioFormat type, gboolean width, SwfdecAudioOut format)
+{
+  SwfdecAudioDecoderAdpcm *adpcm;
+
+  if (type != SWFDEC_AUDIO_FORMAT_ADPCM)
+    return NULL;
+  adpcm->decoder.out_format = format;
+  adpcm->decoder.push = swfdec_audio_decoder_adpcm_push;
+  adpcm->decoder.pull = swfdec_audio_decoder_adpcm_pull;
+  adpcm->decoder.free = swfdec_audio_decoder_adpcm_free;
+  adpcm->queue = swfdec_buffer_queue_new ();
 
-    state->valprev = valpred;
-    state->index = index;
+  adpcm = g_slice_new (SwfdecAudioDecoderAdpcm);
+  return &adpcm->decoder;
 }
-#endif
+
diff --git a/libswfdec/swfdec_codec_audio.c b/libswfdec/swfdec_codec_audio.c
new file mode 100644
index 0000000..b5d00fb
--- /dev/null
+++ b/libswfdec/swfdec_codec_audio.c
@@ -0,0 +1,244 @@
+/* Swfdec
+ * Copyright (C) 2006-2007 Benjamin Otte <otte at gnome.org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, 
+ * Boston, MA  02110-1301  USA
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "swfdec_codec_audio.h"
+#include "swfdec_debug.h"
+
+/*** UNCOMPRESSED SOUND ***/
+
+typedef struct {
+  SwfdecAudioDecoder	decoder;
+  SwfdecBufferQueue *	queue;		/* queue collecting output buffers */
+} SwfdecAudioDecoderUncompressed;
+
+static void
+swfdec_audio_decoder_uncompressed_decode_8bit (SwfdecAudioDecoder *decoder, 
+    SwfdecBuffer *buffer)
+{
+  SwfdecBuffer *ret;
+  gint16 *out;
+  guint8 *in;
+  guint i;
+
+  if (buffer == NULL)
+    return;
+
+  ret = swfdec_buffer_new_and_alloc (buffer->length * 2);
+  out = (gint16 *) ret->data;
+  in = buffer->data;
+  for (i = 0; i < buffer->length; i++) {
+    *out = ((gint16) *in << 8) ^ (-1);
+    out++;
+    in++;
+  }
+  swfdec_buffer_queue_push (((SwfdecAudioDecoderUncompressed *) decoder)->queue, ret);
+}
+
+static void
+swfdec_audio_decoder_uncompressed_decode_16bit (SwfdecAudioDecoder *decoder, 
+    SwfdecBuffer *buffer)
+{
+  if (buffer == NULL)
+    return;
+
+  swfdec_buffer_ref (buffer);
+  swfdec_buffer_queue_push (((SwfdecAudioDecoderUncompressed *) decoder)->queue, buffer);
+}
+
+static SwfdecBuffer *
+swfdec_audio_decoder_uncompressed_pull (SwfdecAudioDecoder *decoder)
+{
+  SwfdecAudioDecoderUncompressed *dec = (SwfdecAudioDecoderUncompressed *) decoder;
+  
+  return swfdec_buffer_queue_pull_buffer (dec->queue);
+}
+
+static void
+swfdec_audio_decoder_uncompressed_free (SwfdecAudioDecoder *decoder)
+{
+  SwfdecAudioDecoderUncompressed *dec = (SwfdecAudioDecoderUncompressed *) decoder;
+
+  swfdec_buffer_queue_unref (dec->queue);
+  g_free (dec);
+}
+
+static SwfdecAudioDecoder *
+swfdec_audio_decoder_uncompressed_new (SwfdecAudioFormat type, gboolean width, SwfdecAudioOut format)
+{
+  SwfdecAudioDecoderUncompressed *dec;
+
+  if (format != SWFDEC_AUDIO_FORMAT_UNDEFINED &&
+      format != SWFDEC_AUDIO_FORMAT_UNCOMPRESSED)
+    return NULL;
+  if (format == SWFDEC_AUDIO_FORMAT_UNDEFINED) {
+    SWFDEC_WARNING ("endianness of audio unknown, assuming little endian");
+  }
+  dec = g_new (SwfdecAudioDecoderUncompressed, 1);
+  dec->decoder.out_format = format;
+  if (width)
+    dec->decoder.push = swfdec_audio_decoder_uncompressed_decode_16bit;
+  else
+    dec->decoder.push = swfdec_audio_decoder_uncompressed_decode_8bit;
+  dec->decoder.pull = swfdec_audio_decoder_uncompressed_pull;
+  dec->decoder.free = swfdec_audio_decoder_uncompressed_free;
+  dec->queue = swfdec_buffer_queue_new ();
+
+  return &dec->decoder;
+}
+
+/*** DECODER LIST ***/
+
+extern SwfdecAudioDecoderNewFunc swfdec_audio_decoder_adpcm_new;
+
+#ifdef HAVE_MAD
+extern SwfdecAudioDecoderNewFunc swfdec_audio_decoder_mad_new;
+#endif
+
+#ifdef HAVE_FFMPEG
+extern SwfdecAudioDecoderNewFunc swfdec_audio_decoder_ffmpeg_new;
+#endif
+
+/*** PUBLIC API ***/
+
+/**
+ * swfdec_audio_decoder_new:
+ * @format: #SwfdecAudioFormat to decode
+ *
+ * Creates a decoder suitable for decoding @format. If no decoder is available
+ * for the given for mat, %NULL is returned.
+ *
+ * Returns: a new decoder or %NULL
+ **/
+SwfdecAudioDecoder *
+swfdec_audio_decoder_new (SwfdecAudioFormat format, gboolean width, SwfdecAudioOut data_format)
+{
+  SwfdecAudioDecoder *ret;
+
+  ret = swfdec_audio_decoder_uncompressed_new (format, width, data_format);
+  if (ret == NULL)
+    ret = swfdec_audio_decoder_adpcm_new (format, width, data_format);
+#ifdef HAVE_MAD
+  if (ret == NULL)
+    ret = swfdec_audio_decoder_mad_new (format, width, data_format);
+#endif
+#ifdef HAVE_FFMPEG
+  if (ret == NULL)
+    ret = swfdec_audio_decoder_ffmpeg_new (format, width, data_format);
+#endif
+#if 0
+#ifdef HAVE_GST
+  if (ret == NULL)
+    ret = swfdec_audio_decoder_gst_new (format, width, data_format);
+#endif
+#endif
+  if (ret) {
+    ret->format = format;
+    g_return_val_if_fail (ret->out_format != 0, NULL);
+    g_return_val_if_fail (ret->push, NULL);
+    g_return_val_if_fail (ret->pull, NULL);
+    g_return_val_if_fail (ret->free, NULL);
+  } else {
+    SWFDEC_ERROR ("no suitable decoder for audio format %u", format);
+    return NULL;
+  }
+  return ret;
+}
+
+/**
+ * swfdec_audio_decoder_free:
+ * @decoder: a #SwfdecAudioDecoder
+ *
+ * Frees the given decoder. When finishing decoding, be sure to pass a %NULL
+ * buffer to swfdec_audio_decoder_push() first to flush the decoder. See that
+ * function for details.
+ **/
+void
+swfdec_audio_decoder_free (SwfdecAudioDecoder *decoder)
+{
+  g_return_if_fail (decoder != NULL);
+
+  decoder->free (decoder);
+}
+
+/**
+ * swfdec_audio_decoder_get_format:
+ * @decoder: a #SwfdecAudioDecoder
+ *
+ * Queries the format that is used by the decoder for its produced output.
+ *
+ * Returns: the format of the decoded data
+ **/
+SwfdecAudioOut
+swfdec_audio_decoder_get_format	(SwfdecAudioDecoder *decoder)
+{
+  g_return_val_if_fail (decoder != NULL, 0);
+
+  return decoder->out_format;
+}
+
+/**
+ * swfdec_audio_decoder_push:
+ * @decoder: a #SwfdecAudioDecoder
+ * @buffer: a #SwfdecBuffer to process or %NULL to flush
+ *
+ * Pushes a new buffer into the decoding pipeline. After this the results can
+ * be queried using swfdec_audio_decoder_pull(). Some decoders may not decode
+ * all available data immediately. So when you are done decoding, you may want
+ * to flush the decoder. Flushing can be achieved by passing %NULL as the 
+ * @buffer argument. Do this when you are finished decoding.
+ **/
+void
+swfdec_audio_decoder_push (SwfdecAudioDecoder *decoder, SwfdecBuffer *buffer)
+{
+  g_return_if_fail (decoder != NULL);
+
+  decoder->push (decoder, buffer);
+}
+
+/**
+ * swfdec_audio_decoder_pull:
+ * @decoder: a #SwfdecAudioDecoder
+ *
+ * Gets the next buffer of decoded audio data. Since some decoders do not
+ * produce one output buffer per input buffer, any number of buffers may be
+ * available after calling swfdec_audio_decoder_push(), even none. When no more
+ * buffers are available, this function returns %NULL. You need to provide more
+ * input in then. A simple decoding pipeline would look like this:
+ * <informalexample><programlisting>do {
+ *   input = next_input_buffer ();
+ *   swfdec_audio_decoder_push (decoder, input);
+ *   while ((output = swfdec_audio_decoder_pull (decoder))) {
+ *     ... process output ...
+ *   }
+ * } while (input != NULL); </programlisting></informalexample>
+ *
+ * Returns: the next buffer or %NULL if no more buffers are available.
+ **/
+SwfdecBuffer *
+swfdec_audio_decoder_pull (SwfdecAudioDecoder *decoder)
+{
+  g_return_val_if_fail (decoder != NULL, NULL);
+
+  return decoder->pull (decoder);
+}
+
diff --git a/libswfdec/swfdec_codec_audio.h b/libswfdec/swfdec_codec_audio.h
new file mode 100644
index 0000000..a7c46f4
--- /dev/null
+++ b/libswfdec/swfdec_codec_audio.h
@@ -0,0 +1,60 @@
+/* Swfdec
+ * Copyright (C) 2006-2007 Benjamin Otte <otte at gnome.org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, 
+ * Boston, MA  02110-1301  USA
+ */
+
+#ifndef _SWFDEC_CODEC_H_
+#define _SWFDEC_CODEC_H_
+
+#include <glib.h>
+#include <libswfdec/swfdec_audio_internal.h>
+#include <libswfdec/swfdec_buffer.h>
+
+typedef struct _SwfdecAudioDecoder SwfdecAudioDecoder;
+
+typedef enum {
+  SWFDEC_AUDIO_FORMAT_UNDEFINED = 0,
+  SWFDEC_AUDIO_FORMAT_ADPCM = 1,
+  SWFDEC_AUDIO_FORMAT_MP3 = 2,
+  SWFDEC_AUDIO_FORMAT_UNCOMPRESSED = 3,
+  SWFDEC_AUDIO_FORMAT_NELLYMOSER_8KHZ = 5,
+  SWFDEC_AUDIO_FORMAT_NELLYMOSER = 6
+} SwfdecAudioFormat;
+
+typedef SwfdecAudioDecoder * (SwfdecAudioDecoderNewFunc) (SwfdecAudioFormat type, gboolean width,
+    SwfdecAudioOut format);
+struct _SwfdecAudioDecoder {
+  SwfdecAudioFormat	format;
+  SwfdecAudioOut	out_format;
+  void			(* push)	(SwfdecAudioDecoder *	decoder,
+					 SwfdecBuffer *		buffer);
+  SwfdecBuffer *	(* pull)	(SwfdecAudioDecoder *	decoder);
+  void		  	(* free)	(SwfdecAudioDecoder *	decoder);
+};
+
+SwfdecAudioDecoder *   	swfdec_audio_decoder_new      	(SwfdecAudioFormat	format,
+							 gboolean		width,
+							 SwfdecAudioOut		data_format);
+void			swfdec_audio_decoder_free      	(SwfdecAudioDecoder *	decoder);
+SwfdecAudioOut		swfdec_audio_decoder_get_format	(SwfdecAudioDecoder *	decoder);
+void			swfdec_audio_decoder_push	(SwfdecAudioDecoder *	decoder,
+							 SwfdecBuffer *		buffer);
+SwfdecBuffer *		swfdec_audio_decoder_pull	(SwfdecAudioDecoder *	decoder);
+
+
+G_END_DECLS
+#endif
diff --git a/libswfdec/swfdec_codec_ffmpeg.c b/libswfdec/swfdec_codec_ffmpeg.c
index 08b9c34..8f333e8 100644
--- a/libswfdec/swfdec_codec_ffmpeg.c
+++ b/libswfdec/swfdec_codec_ffmpeg.c
@@ -23,13 +23,13 @@
 #include <string.h>
 #include <avcodec.h>
 
-#include "swfdec_codec.h"
+#include "swfdec_codec_audio.h"
 #include "swfdec_codec_video.h"
 #include "swfdec_debug.h"
 
 /*** GENERAL ***/
 
-static gpointer
+static AVCodecContext *
 swfdec_codec_ffmpeg_init (enum CodecID id)
 {
   AVCodec *codec;
@@ -60,37 +60,11 @@ fail:
 
 /*** AUDIO ***/
 
-static gpointer
-swfdec_codec_ffmpeg_audio_init (SwfdecAudioFormat type, gboolean width, SwfdecAudioOut format)
-{
-  AVCodecContext *ctx;
-  enum CodecID id;
-
-  switch (type) {
-    case SWFDEC_AUDIO_FORMAT_ADPCM:
-      id = CODEC_ID_ADPCM_SWF;
-      break;
-    case SWFDEC_AUDIO_FORMAT_MP3:
-      id = CODEC_ID_MP3;
-      break;
-    default:
-      g_assert_not_reached ();
-      id = 0;
-      break;
-  }
-  ctx = swfdec_codec_ffmpeg_init (id);
-  ctx->sample_rate = SWFDEC_AUDIO_OUT_RATE (format);
-  ctx->channels = SWFDEC_AUDIO_OUT_N_CHANNELS (format);
-
-  return ctx;
-}
-
-static SwfdecAudioOut
-swfdec_codec_ffmpeg_get_format (gpointer data)
-{
-  /* FIXME: improve this */
-  return SWFDEC_AUDIO_OUT_STEREO_44100;
-}
+typedef struct {
+  SwfdecAudioDecoder	decoder;
+  AVCodecContext *	ctx;
+  SwfdecBufferQueue *	queue;
+} SwfdecAudioDecoderFFMpeg;
 
 static SwfdecBuffer *
 swfdec_codec_ffmpeg_convert (AVCodecContext *ctx, SwfdecBuffer *buffer)
@@ -136,68 +110,94 @@ swfdec_codec_ffmpeg_convert (AVCodecCont
   return ret;
 }
 
-static SwfdecBuffer *
-swfdec_codec_ffmpeg_decode (gpointer ctx, SwfdecBuffer *buffer)
+static void
+swfdec_audio_decoder_ffmpeg_push (SwfdecAudioDecoder *dec, SwfdecBuffer *buffer)
 {
+  SwfdecAudioDecoderFFMpeg *ffmpeg = (SwfdecAudioDecoderFFMpeg *) dec;
   int out_size;
   int len;
   guint amount;
   SwfdecBuffer *outbuf = NULL;
-  SwfdecBufferQueue *queue = swfdec_buffer_queue_new ();
 
+  if (buffer == NULL)
+    return;
   outbuf = swfdec_buffer_new_and_alloc (AVCODEC_MAX_AUDIO_FRAME_SIZE);
   for (amount = 0; amount < buffer->length; amount += len) {
     
-    len = avcodec_decode_audio (ctx, (short *) outbuf->data, &out_size, buffer->data + amount, buffer->length - amount);
+    len = avcodec_decode_audio (ffmpeg->ctx, (short *) outbuf->data, &out_size, buffer->data + amount, buffer->length - amount);
 
     if (len < 0) {
       SWFDEC_ERROR ("Error %d while decoding", len);
-      swfdec_buffer_queue_unref (queue);
       swfdec_buffer_unref (outbuf);
-      return NULL;
+      return;
     }
     if (out_size > 0) {
       SwfdecBuffer *convert;
       outbuf->length = out_size;
-      convert = swfdec_codec_ffmpeg_convert (ctx, outbuf);
+      convert = swfdec_codec_ffmpeg_convert (ffmpeg->ctx, outbuf);
       if (convert == NULL) {
-	swfdec_buffer_queue_unref (queue);
 	swfdec_buffer_unref (outbuf);
-	return NULL;
+	return;
       }
-      swfdec_buffer_queue_push (queue, convert);
+      swfdec_buffer_queue_push (ffmpeg->queue, convert);
       outbuf->length = AVCODEC_MAX_AUDIO_FRAME_SIZE;
     }
   }
   swfdec_buffer_unref (outbuf);
+}
 
-  amount = swfdec_buffer_queue_get_depth (queue);
-  //g_print ("got %u bytes\n", amount);
-  if (amount > 0)
-    outbuf = swfdec_buffer_queue_pull (queue, amount);
-  else
-    outbuf = NULL;
-  swfdec_buffer_queue_unref (queue);
+static SwfdecBuffer *
+swfdec_audio_decoder_ffmpeg_pull (SwfdecAudioDecoder *dec)
+{
+  SwfdecAudioDecoderFFMpeg *ffmpeg = (SwfdecAudioDecoderFFMpeg *) dec;
 
-  return outbuf;
+  return swfdec_buffer_queue_pull_buffer (ffmpeg->queue);
 }
 
-static SwfdecBuffer *
-swfdec_codec_ffmpeg_audio_finish (gpointer ctx)
+static void
+swfdec_audio_decoder_ffmpeg_free (SwfdecAudioDecoder *dec)
 {
-  avcodec_close (ctx);
-  av_free (ctx);
+  SwfdecAudioDecoderFFMpeg *ffmpeg = (SwfdecAudioDecoderFFMpeg *) dec;
 
-  return NULL;
+  avcodec_close (ffmpeg->ctx);
+  av_free (ffmpeg->ctx);
+  swfdec_buffer_queue_unref (ffmpeg->queue);
+
+  g_slice_free (SwfdecAudioDecoderFFMpeg, ffmpeg);
 }
 
+SwfdecAudioDecoder *
+swfdec_audio_decoder_ffmpeg_new (SwfdecAudioFormat type, gboolean width, SwfdecAudioOut format)
+{
+  SwfdecAudioDecoderFFMpeg *ffmpeg;
+  AVCodecContext *ctx;
+  enum CodecID id;
+
+  switch (type) {
+    case SWFDEC_AUDIO_FORMAT_ADPCM:
+      id = CODEC_ID_ADPCM_SWF;
+      break;
+    case SWFDEC_AUDIO_FORMAT_MP3:
+      id = CODEC_ID_MP3;
+      break;
+    default:
+      return NULL;
+  }
+  ctx = swfdec_codec_ffmpeg_init (id);
+  if (ctx == NULL)
+    return NULL;
+  ffmpeg = g_slice_new (SwfdecAudioDecoderFFMpeg);
+  ffmpeg->ctx = ctx;
+  ffmpeg->queue = swfdec_buffer_queue_new ();
+  ffmpeg->decoder.out_format = SWFDEC_AUDIO_OUT_STEREO_44100;
+  ffmpeg->decoder.pull = swfdec_audio_decoder_ffmpeg_pull;
+  ffmpeg->decoder.push = swfdec_audio_decoder_ffmpeg_push;
+  ffmpeg->decoder.free = swfdec_audio_decoder_ffmpeg_free;
+  ctx->sample_rate = SWFDEC_AUDIO_OUT_RATE (format);
+  ctx->channels = SWFDEC_AUDIO_OUT_N_CHANNELS (format);
 
-const SwfdecAudioCodec swfdec_codec_ffmpeg_audio = {
-  swfdec_codec_ffmpeg_audio_init,
-  swfdec_codec_ffmpeg_get_format,
-  swfdec_codec_ffmpeg_decode,
-  swfdec_codec_ffmpeg_audio_finish
-};
+  return &ffmpeg->decoder;
+}
 
 /*** VIDEO ***/
 
diff --git a/libswfdec/swfdec_codec_mad.c b/libswfdec/swfdec_codec_mad.c
index 8a83928..66f0753 100644
--- a/libswfdec/swfdec_codec_mad.c
+++ b/libswfdec/swfdec_codec_mad.c
@@ -1,3 +1,22 @@
+/* Swfdec
+ * Copyright (C) 2006-2007 Benjamin Otte <otte at gnome.org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, 
+ * Boston, MA  02110-1301  USA
+ */
+
 #ifdef HAVE_CONFIG_H
 #include "config.h"
 #endif
@@ -6,37 +25,20 @@
 #include <liboil/liboil.h>
 #include <mad.h>
 
-#include "swfdec_codec.h"
+#include "swfdec_codec_audio.h"
 #include "swfdec_debug.h"
 
 typedef struct {
+  SwfdecAudioDecoder	decoder;
+
   struct mad_stream	stream;
   struct mad_frame	frame;
   struct mad_synth	synth;
   guint8		data[MAD_BUFFER_MDLEN * 3];
   guint			data_len;
+  SwfdecBufferQueue *	queue;
 } MadData;
 
-static gpointer
-swfdec_codec_mad_init (SwfdecAudioFormat type, gboolean width, SwfdecAudioOut format)
-{
-  MadData *data = g_new (MadData, 1);
-
-  mad_stream_init (&data->stream);
-  mad_frame_init (&data->frame);
-  mad_synth_init (&data->synth);
-  data->data_len = 0;
-
-  return data;
-}
-
-static SwfdecAudioOut
-swfdec_codec_mad_get_format (gpointer data)
-{
-  /* FIXME: improve this */
-  return SWFDEC_AUDIO_OUT_STEREO_44100;
-}
-
 static SwfdecBuffer *
 convert_synth_to_buffer (MadData *mdata)
 {
@@ -138,15 +140,18 @@ convert_synth_to_buffer (MadData *mdata)
   return buffer;
 }
 
-static SwfdecBuffer *
-swfdec_codec_mad_decode (gpointer datap, SwfdecBuffer *buffer)
+static void
+swfdec_audio_decoder_mad_push (SwfdecAudioDecoder *dec, SwfdecBuffer *buffer)
 {
-  MadData *data = datap;
-  SwfdecBuffer *out;
-  SwfdecBufferQueue *queue;
+  MadData *data = (MadData *) dec;
+  SwfdecBuffer *out, *empty = NULL;
   guint amount = 0, size;
 
-  queue = swfdec_buffer_queue_new ();
+  if (buffer == NULL) {
+    buffer = empty = swfdec_buffer_new ();
+    empty->data = g_malloc0 (MAD_BUFFER_GUARD * 3);
+    empty->length = MAD_BUFFER_GUARD * 3;
+  }
 
   //write (1, buffer->data, buffer->length);
   //g_print ("buffer %p gave us %u bytes\n", buffer, buffer->length);
@@ -171,9 +176,8 @@ swfdec_codec_mad_decode (gpointer datap,
 
       mad_synth_frame (&data->synth, &data->frame);
       out = convert_synth_to_buffer (data);
-      if (out) {
-	swfdec_buffer_queue_push (queue, out);
-      }
+      if (out)
+	swfdec_buffer_queue_push (data->queue, out);
     }
     if (data->stream.next_frame == NULL) {
       data->data_len = 0;
@@ -184,40 +188,47 @@ swfdec_codec_mad_decode (gpointer datap,
   }
   //g_print ("%u bytes left\n", data->data_len);
 
-  size = swfdec_buffer_queue_get_depth (queue);
-  if (size > 0)
-    out = swfdec_buffer_queue_pull (queue, size);
-  else
-    out = NULL;
-  swfdec_buffer_queue_unref (queue);
-
-  return out;
+  if (empty)
+    swfdec_buffer_unref (empty);
 }
 
-static SwfdecBuffer *
-swfdec_codec_mad_finish (gpointer datap)
+static void
+swfdec_audio_decoder_mad_free (SwfdecAudioDecoder *dec)
 {
-  MadData *data = datap;
-  SwfdecBuffer *empty, *result;
-
-  empty = swfdec_buffer_new ();
-  empty->data = g_malloc0 (MAD_BUFFER_GUARD * 3);
-  empty->length = MAD_BUFFER_GUARD * 3;
-  result = swfdec_codec_mad_decode (data, empty);
-  swfdec_buffer_unref (empty);
+  MadData *data = (MadData *) dec;
 
   mad_synth_finish (&data->synth);
   mad_frame_finish (&data->frame);
   mad_stream_finish (&data->stream);
-  g_free (data);
+  swfdec_buffer_queue_unref (data->queue);
+  g_slice_free (MadData, data);
+}
 
-  return result;
+static SwfdecBuffer *
+swfdec_audio_decoder_mad_pull (SwfdecAudioDecoder *dec)
+{
+  return swfdec_buffer_queue_pull_buffer (((MadData *) dec)->queue);
 }
 
-const SwfdecAudioCodec swfdec_codec_mad = {
-  swfdec_codec_mad_init,
-  swfdec_codec_mad_get_format,
-  swfdec_codec_mad_decode,
-  swfdec_codec_mad_finish
-};
+SwfdecAudioDecoder *
+swfdec_audio_decoder_mad_new (SwfdecAudioFormat type, gboolean width, SwfdecAudioOut format)
+{
+  MadData *data;
+  
+  if (type != SWFDEC_AUDIO_FORMAT_MP3)
+    return NULL;
+
+  data = g_slice_new (MadData);
+  data->decoder.out_format = SWFDEC_AUDIO_OUT_STEREO_44100;
+  data->decoder.push = swfdec_audio_decoder_mad_push;
+  data->decoder.pull = swfdec_audio_decoder_mad_pull;
+  data->decoder.free = swfdec_audio_decoder_mad_free;
+  mad_stream_init (&data->stream);
+  mad_frame_init (&data->frame);
+  mad_synth_init (&data->synth);
+  data->data_len = 0;
+  data->queue = swfdec_buffer_queue_new ();
+
+  return &data->decoder;
+}
 
diff --git a/libswfdec/swfdec_flv_decoder.c b/libswfdec/swfdec_flv_decoder.c
index b6dfff0..d91f416 100644
--- a/libswfdec/swfdec_flv_decoder.c
+++ b/libswfdec/swfdec_flv_decoder.c
@@ -24,7 +24,6 @@
 #include "swfdec_flv_decoder.h"
 #include "swfdec_audio_internal.h"
 #include "swfdec_bits.h"
-#include "swfdec_codec.h"
 #include "swfdec_debug.h"
 
 enum {
diff --git a/libswfdec/swfdec_flv_decoder.h b/libswfdec/swfdec_flv_decoder.h
index c26b169..622dca0 100644
--- a/libswfdec/swfdec_flv_decoder.h
+++ b/libswfdec/swfdec_flv_decoder.h
@@ -20,7 +20,7 @@
 #ifndef __SWFDEC_FLV_DECODER_H__
 #define __SWFDEC_FLV_DECODER_H__
 
-#include <libswfdec/swfdec_codec.h>
+#include <libswfdec/swfdec_codec_audio.h>
 #include <libswfdec/swfdec_codec_video.h>
 #include <libswfdec/swfdec_decoder.h>
 
diff --git a/libswfdec/swfdec_sound.c b/libswfdec/swfdec_sound.c
index 2ffa3bc..1087f5f 100644
--- a/libswfdec/swfdec_sound.c
+++ b/libswfdec/swfdec_sound.c
@@ -179,9 +179,9 @@ tag_func_define_sound (SwfdecSwfDecoder 
 SwfdecBuffer *
 swfdec_sound_get_decoded (SwfdecSound *sound, SwfdecAudioOut *format)
 {
-  const SwfdecAudioCodec *codec;
   gpointer decoder;
-  SwfdecBuffer *tmp, *tmp2;
+  SwfdecBuffer *tmp;
+  SwfdecBufferQueue *queue;
   guint sample_bytes;
 
   g_return_val_if_fail (SWFDEC_IS_SOUND (sound), NULL);
@@ -194,38 +194,24 @@ swfdec_sound_get_decoded (SwfdecSound *s
   }
   if (sound->encoded == NULL)
     return NULL;
-  codec = swfdec_codec_get_audio (sound->format);
-  if (codec == NULL)
-    return NULL;
 
-  decoder = swfdec_audio_codec_init (codec, sound->format, sound->width, sound->original_format);
+  decoder = swfdec_audio_decoder_new (sound->format, sound->width, sound->original_format);
   if (decoder == NULL)
     return NULL;
-  sound->decoded_format = swfdec_audio_codec_get_format (codec, decoder);
+  sound->decoded_format = swfdec_audio_decoder_get_format (decoder);
   sample_bytes = 2 * SWFDEC_AUDIO_OUT_N_CHANNELS (sound->decoded_format);
   /* FIXME: The size is only a guess */
   swfdec_cached_load (SWFDEC_CACHED (sound), sound->n_samples * sample_bytes);
-  tmp = swfdec_audio_codec_decode (codec, decoder, sound->encoded);
-  tmp2 = swfdec_audio_codec_finish (codec, decoder);
-  if (tmp == NULL) {
-    if (tmp2) {
-      tmp = tmp2;
-    } else {
-      SWFDEC_ERROR ("got no data when decoding sound %u", 
-	  SWFDEC_CHARACTER (sound)->id);
-      swfdec_cached_unload (SWFDEC_CACHED (sound));
-      return NULL;
-    }
-  } else {
-    if (tmp2) {
-      /* and all this code just because mad sucks... */
-      SwfdecBufferQueue *queue = swfdec_buffer_queue_new ();
-      swfdec_buffer_queue_push (queue, tmp);
-      swfdec_buffer_queue_push (queue, tmp2);
-      tmp = swfdec_buffer_queue_pull (queue, swfdec_buffer_queue_get_depth (queue));
-      swfdec_buffer_queue_unref (queue);
-    }
-  }
+
+  swfdec_audio_decoder_push (decoder, sound->encoded);
+  swfdec_audio_decoder_push (decoder, NULL);
+  queue = swfdec_buffer_queue_new ();
+  while ((tmp = swfdec_audio_decoder_pull (decoder)))
+    swfdec_buffer_queue_push (queue, tmp);
+  swfdec_audio_decoder_free (decoder);
+  tmp = swfdec_buffer_queue_pull (queue, swfdec_buffer_queue_get_depth (queue));
+  swfdec_buffer_queue_unref (queue);
+
   SWFDEC_LOG ("after decoding, got %u samples, should get %u and skip %u", 
       tmp->length / sample_bytes, sound->n_samples, sound->skip);
   if (sound->skip) {
diff --git a/libswfdec/swfdec_sound.h b/libswfdec/swfdec_sound.h
index ea3e9af..118d37f 100644
--- a/libswfdec/swfdec_sound.h
+++ b/libswfdec/swfdec_sound.h
@@ -23,7 +23,7 @@
 #define _SWFDEC_SOUND_H_
 
 #include <libswfdec/swfdec_cached.h>
-#include <libswfdec/swfdec_codec.h>
+#include <libswfdec/swfdec_codec_audio.h>
 #include <libswfdec/swfdec_swf_decoder.h>
 #include <libswfdec/swfdec_types.h>
 


More information about the Swfdec mailing list