[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